How to sum two matrix in a class - python

I'm trying to define some methods to a class Matrix that receives the number of rows and the number of columns, a list or a code as arguments.
I have to do:
import numpy as np
class Matrix:
def __init__(self, rows = 0, columns =0, data=None, code =''):
if data is None:
data = []
self.code = ''
self.rows = rows
self.columns = columns
self.data = data
self.code = code
self.matrix = [[]]
assert self.columns != 0 and self.rows != 0
if code == 'z':
self.matrix = np.zeros([self.rows, self.columns], int)
elif code == 'u':
self.matrix = np.ones([self.rows, self.columns], int)
elif code == 'i':
self.matrix = np.identity(self.rows, int)
else:
if code == '' and len(self.data) != 0:
self.matrix = np.reshape(self.data, (-1, self.columns))
def __str__(self):
return f'Matrix: {self.matrix}'
def get_matrix(self):
return self.matrix
def sumM(self,m1):
k = self.get_matrix()
m1.get_matrix()
print(k)
print(m1.get_matrix())
assert (self.rows == m1.rows)
m3 = np.zeros([self.rows, self.rows])
print(m3.shape)
for i in range(m3.shape[0]):
for j in range(m3.shape[1]):
output = m1[i, j] + k[i, j]
print(output)
return m3
Although, when I'm call the sumM method, python retrieves the error:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:/Users/sandr/PycharmProjects/Trabalho 2/teste2.py", line 41, in sumM
output = m1[i, j] + k[i, j]
TypeError: 'Matrix' object is not subscriptable
What I'm doing wrong?

This should do it:
def sumM(self,m1):
k = self.get_matrix()
k1 = m1.get_matrix()
assert (self.rows == m1.rows)
m3 = np.zeros([self.rows, self.rows])
for i in range(m3.shape[0]):
for j in range(m3.shape[1]):
m3[i][j] = k1[i][j] + k[i][j]
return m3

Related

AttributeError: 'list' object has no attribute 'row'

Following Code From the book deep learning and the game of go
Not Sure Why I am getting this error
full error:
Traceback (most recent call last): File "bot_v_bot.py", line 25, in
main() File "bot_v_bot.py", line 20, in main
bot_move = bots[game.next_player].select_move(game) File "C:\Users\Max\Desktop\books\pdf\code\Go ML\dlgo\agent\naive.py", line
14, in select_move
if game_state.is_valid_move(Move.play(canidate)) and not is_point_an_eye(game_state.board, canidate, game_state.next_player):
File "C:\Users\Max\Desktop\books\pdf\code\Go
ML\dlgo\agent\helpers.py", line 20, in is_point_an_eye
if board.is_on_grid(corners): File "C:\Users\Max\Desktop\books\pdf\code\Go ML\dlgo\goboard_slow.py", line
71, in is_on_grid
return 1 <= point.row <= self.num_rows and 1 <= point.col <=
self.num_cols AttributeError: 'list' object has no attribute 'row'
My Directory looks like
GO ML
-bot_v_bot.py
-dlgo
---__pychache__
---agent
----__init__.py
----base.py
----helpers.py
----naive.py
---__init__.py
---goboard_slow.py
---gotypes.py
---utils.py
Bot_V_Bot code
from dlgo.agent import naive
from dlgo import goboard_slow
from dlgo import gotypes
from dlgo.utils import print_board, print_move
import time
def main():
board_size = 9
game = goboard_slow.GameState.new_game(board_size)
bots = {
gotypes.Player.black: naive.RandomBot(),
gotypes.Player.white: naive.RandomBot(),
}
while not game.is_over():
time.sleep(0.3)
print(chr(27) + "[2j")
print_board(game.board)
bot_move = bots[game.next_player].select_move(game)
print_move(game.next_player, bot_move)
game = game.apply_move(bot_move)
if __name__ == '__main__':
main()
goboard_slow code
import copy
from dlgo.gotypes import Player
from dlgo.gotypes import Point
class GoString():
def __init__(self, color, stones, liberties):
self.color = color
self.stones = set(stones)
self.liberties = set(liberties)
def remove_liberty(self, point):
self.liberties.remove(point)
def add_liberty(self, point):
self.liberties.add(point)
def merged_with(self, go_string):
assert go_string.color == self.color
combined_stones = self.stones | go_string.stones
return GoString(
self.color,
combined_stones,
(self.liberties | go_string.liberties) - combined_stones)
#property
def num_liberties(self):
return len(self.liberties)
def __eq__(self, other):
return isinstance(other, GoString) and \
self.color == other.color and \
self.stones == other.stones and \
self.liberties == other.liberties
class Board():
def __init__(self, num_rows, num_cols):
self.num_rows = num_rows
self.num_cols = num_cols
self._grid = {}
def place_stone(self, player, point):
assert self.is_on_grid(point)
assert self._grid.get(point) is None
adjacent_same_color = []
adjacent_opposite_color = []
liberties = []
for neighbor in point.neighbors():
if not self.is_on_grid(neighbor):
continue
neighbor_string = self._grid.get(neighbor)
if neighbor_string is None:
liberties.append(neighbor)
elif neighbor_string.color == player:
if neighbor_string not in adjacent_same_color:
adjacent_same_color.append(neighbor_string)
else:
if neighbor_string not in adjacent_opposite_color:
adjacent_opposite_color.append(neighbor_string)
new_string = GoString(player, [point], liberties)
for same_color_string in adjacent_same_color:
new_string = new_string.merged_with(same_color_string)
for new_string_point in new_string.stones:
self._grid[new_string_point] = new_string
for other_color_string in adjacent_opposite_color:
other_color_string.remove_liberty(point)
for other_color_string in adjacent_same_color:
if other_color_string.num_liberties == 0:
self._remove_string(other_color_string)
def is_on_grid(self, point):
return 1 <= point.row <= self.num_rows and 1 <= point.col <= self.num_cols
def get(self, point):
string = self._grid.get(point)
if string is None:
return None
return string.color
def get_go_string(self, point):
string = self._grid.get(point)
if string is None:
return None
return string
def _remove_string(self, string):
for point in string.stones:
for neighbor in point.neighbors():
neighbor_string = self._grid.get(neighbor)
if neighbor_string is None:
continue
if neighbor_string is not string:
neighbor_string.add_liberty(point)
self._grid[point] = None
class Move():
def __init__(self, point=None, is_pass=False, is_resign=False):
assert (point is not None) ^ is_pass ^ is_resign
self.point = point
self.is_play = (self.point is not None)
self.is_pass = is_pass
self.is_resign = is_resign
#classmethod
def play(cls, point):
return Move(point=point)
#classmethod
def pass_turn(cls):
return Move(is_pass=True)
#classmethod
def resign(cls):
return Move(is_resign=True)
class GameState():
def __init__(self, board, next_player, previous, move):
self.board = board
self.next_player = next_player
self.previous_state = previous
self.last_move = move
def apply_move(self, move):
if move.is_play:
next_board = copy.deepcopy(self.board)
next_board.place_stone(self.next_player, move.point)
else:
next_board = self.board
return GameState(next_board, self.next_player.other, self, move)
#classmethod
def new_game(cls, board_size):
if isinstance(board_size, int):
board_size = (board_size, board_size)
board = Board(*board_size)
return GameState(board, Player.black, None, None)
def is_over(self):
if self.last_move is None:
return False
if self.last_move.is_resign:
return True
second_last_move = self.previous_state.last_move
if second_last_move is None:
return False
return self.last_move.is_pass and second_last_move.is_pass
def is_move_self_capture(self, Player, move):
if not move.is_play:
return False
next_board = copy.deepcopy(self.board)
next_board.place_stone(Player, move.point)
new_string = next_board.get_go_string(move.point)
return new_string.num_liberties == 0
#property
def situation(self):
return (self.next_player, self.board)
def does_move_validate_ko(self, player, move):
if not move.is_play:
return False
next_board = copy.deepcopy(self.board)
next_board.place_stone(player, move.point)
next_situation = (Player.other, next_board)
past_state = self.previous_state
while past_state is not None:
if past_state.situation == next_situation:
return True
past_state = past_state.previous_state
return False
def is_valid_move(self, move):
if self.is_over():
return False
if move.is_pass or move.is_resign:
return True
return (
self.board.get(move.point) is None and
not self.is_move_self_capture(self.next_player, move) and
not self.does_move_validate_ko(self.next_player, move))
gotypes code
import enum
from collections import namedtuple
class Player(enum.Enum):
black = 1
white = 2
#property
def other(self):
return Player.black if self == Player.white else Player.white
class Point(namedtuple('Point', 'row col')):
def neighbors(self):
return [
Point(self.row - 1, self.col),
Point(self.row + 1, self.col),
Point(self.row, self.col - 1),
Point(self.row, self.col + 1),
]
utils code
import random
from dlgo.agent.base import Agent
from dlgo.agent.helpers import is_point_an_eye
from dlgo.goboard_slow import Move
from dlgo.gotypes import Point
class RandomBot(Agent):
def select_move(self, game_state):
""""Choose a random valid move that preserves our own eyes."""
canidates = []
for r in range(1, game_state.board.num_rows + 1):
for c in range(1, game_state.board.num_cols +1):
canidate = Point(row=r, col=c)
if game_state.is_valid_move(Move.play(canidate)) and not is_point_an_eye(game_state.board, canidate, game_state.next_player):
canidates.append(canidate)
if not canidates:
return Move.pass_turn()
return Move.play(random.choice(canidates))
from dlgo import gotypes
COLS = 'ABCDEFGHIJKLMNOPQRST'
STONE_TO_CHAR = {
None: ' . ',
gotypes.Player.black: ' x ',
gotypes.Player.white: ' o ',
}
def print_move(player, move):
if move.is_pass:
move_str = 'passes'
elif move.is_resign:
move_str = 'resigns'
else:
move_str = '%s%d' % (COLS[move.point.col - 1], move.point.row)
print('%s %s' % (player, move_str))
def print_board(board):
for row in range(board.num_rows, 0, -1):
bump = " " if row <= 9 else ""
line = []
for col in range(1, board.num_cols + 1):
stone = board.get(gotypes.Point(row = row, col = col))
line.append(STONE_TO_CHAR[stone])
print('%s%d %s' % (bump, row, ''.join(line)))
print(' ' + ' '.join(COLS[:board.num_cols]))
Helpers Code
from dlgo.gotypes import Point
def is_point_an_eye(board, point, color):
if board.get(point) is not None:
return False
for neighbor in point.neighbors():
if board.is_on_grid(neighbor):
neighbor_color= board.get(neighbor)
if neighbor_color != color:
return False
friendly_corners = 0
off_board_corners = 0
corners = [
Point(point.row - 1, point.col - 1),
Point(point.row - 1, point.col + 1),
Point(point.row + 1, point.col - 1),
Point(point.row + 1, point.col + 1),
]
for corner in corners:
if board.is_on_grid(corners):
corner_color = board.get(corner)
if corner_color == olor:
friendly_corners += 1
else:
off_board_corners += 1
if off_board_corners > 0:
return off_board_corners + friendly_corners == 4
return friendly_corners >= 3
Base Code
class Agent:
def __init(self):
pass
def selec_move(self, game_state):
raise NotImplementedError()
Both Inits are empty
corners is the list of all corner points, corner is
the current element in the for loop.
Barmar
I think it's just a typo: board.is_on_grid(corners)
should be board.is_on_grid(corner)
Barmar
These worked and fixed it

Computing determinant of matrix recursively

I'm trying to compute the determinant of matrix using recursive function.
I got a Matrix class that have getitem, setitem,... The .eliminated(i,j) method will return a new matrix that is removed row i, column j.
Here is the Matrix class, I also created Array, Array_2D class before and they are all fine:
class Matrix:
def __init__(self, numRows, numCols):
self.grid = Array_2D(numRows,numCols)
self.grid.clear(0)
def __getitem__(self, tuple):
return self.grid[tuple[0],tuple[1]]
def numRows(self):
return self.grid.numRows()
def numCols(self):
return self.grid.numCols()
def __add__(self, other):
assert other.numRows() == self.numRows() and\
other.numCols == self.numCols() , "Matrix sizes not compatible"
newMatrix = Matrix(self.numRows(),self.numCols())
for r in range(self.numRows()):
for c in range(self.numCols()):
newMatrix[r,c]=self[r,c]+other[r,c]
return newMatrix
def __setitem__(self, tuple, value):
self.grid[tuple[0],tuple[1]]=value
def scaleBy(self,scalar):
for r in range(self.numRows()):
for c in range(self.numCols()):
self[r,c]=self[r,c]*scalar
def tranpose(self):
newMatrix = Matrix(self.numCols(),self.numRows())
for r in range(newMatrix.numRows()):
for c in range(newMatrix.numCols()):
newMatrix[r,c]=self[c,r]
return newMatrix
def __sub__(self, other):
assert other.numRows() == self.numRows() and \
other.numCols == self.numCols(), "Matrix sizes not compatible"
newMatrix = Matrix(self.numRows(), self.numCols())
for r in range(self.numRows()):
for c in range(self.numCols()):
newMatrix[r, c] = self[r, c] - other[r, c]
return newMatrix
def __mul__(self, other):
assert other.numRows() == self.numCols(), "Matrix sizes not compatible"
newMatrix = Matrix(self.numRows(),other.numCols())
for r in range(newMatrix.numRows()):
for c in range(newMatrix.numCols()):
newMatrix[r,c] = 0
for i in range(self.numCols()):
newMatrix[r,c]+=self[r,i]*other[i,c]
return newMatrix
def determinant(self):
assert self.numCols()==self.numRows(), "Must be a square matrix"
assert self.numCols() > 0
if self.numCols() == 1:
return self[0,0]
if self.numCols() == 2:
return self[0,0]*self[1,1]-self[0,1]*self[1,0]
det = 0
if self.numCols() >=2:
for c in range(self.numCols()):
det+=((-1) ** c) * self[0, c] * self.eliminated(0, c).determinant()
return det
def eliminated(self,row,col):
assert row >=0 and row < self.numRows(), "Invalid row"
assert col >=0 and col < self.numCols(), "Invalid column"
assert self.numCols() >1 and self.numRows()>1
entry_list = []
for r in range(self.numRows()):
for c in range(self.numCols()):
self[r, col] = None
self[row,c]=None
if self[r,c] != None:
entry_list.append(self[r,c])
new_matrix = Matrix(self.numRows()-1, self.numCols()-1)
for r in range(new_matrix.numRows()):
for c in range(new_matrix.numCols()):
new_matrix[r,c] = entry_list[c + r*new_matrix.numCols()]
return new_matrix
I kept getting this error for 3x3 Matrix, 2x2 and 1x1 are fine:
Traceback (most recent call last):
File "E:/DataStructures/matrix.py", line 100, in <module>
print(ma4.determinant())
File "E:/DataStructures/matrix.py", line 67, in determinant
det+=((-1) ** c) * self[0, c] * self.eliminated(0, c).determinant()
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
I know that my recursive function keeps removing row and column until it gets to NoneType, but no idea how to fix it
Hello there check out this:
matrix=[]
def det(IC,i):
global matrix,row
determinent=0
m=1
for j in range(len(matrix)):
if j not in IC:
m+=1
if i == row-1:
determinent = matrix[i][j]
else:
determinent+=(-1)**(m)*matrix[i][j]*det(IC+[j],i+1)
return determinent
row=int(input("enter order:"))
for i in range(row):
rowEntry=[int(x) for x in input().split(' ')]
matrix.append(rowEntry)
print(matrix)
print(det([],0))
please give input carefully e.g:
enter order:3
2 3 4
1 2 3
3 4 5

TypeError: 'list' object is not callable , problem with passing generated array to second iteration

I am trying to run 500 iterations in optimization problem. I am doing some changes on pop array and than I am trying to pass it again to the next iteration, however run into error, tho the first iteration is working all fine, I get pop array and then pass it to created_moved_pop and create_star_pop and get some problems. Will be very thankful if someone could explain my why this happens
error trace
C:\Users\yuliy\PycharmProjects\method_deform_stars\venv\Scripts\python.exe C:/Users/yuliy/PycharmProjects/method_deform_stars/DS.py
[0.8575697060274371, 0.8802225709314421, 0.6098937002728221, 0.5482650148523068, 0.5395302259903021, 0.6330576538506912, 0.734280095260012, 0.6826885236666879, 0.5797401283594749, 0.8381278588403586, 0.4983449567579089, 0.37081148554598065, 0.19916270916904044, 0.7590390380364216, 0.8272752130297748, 0.8837021413140848, 0.9750382019031415, 0.5436068899712437, 0.6490739970397773, 0.3014768191053475]
Traceback (most recent call last):
File "C:/Users/yuliy/PycharmProjects/method_deform_stars/DS.py", line 70, in
star_pop = create_star_pop(pop)
[(0.11503376215798591, 6.794025806650792), (0.5133530350808552, 1.0230252795290697), (0.37081148554598065, 0.8887201815324006), (0.4201038734097051, 0.8215339609930865), (0.6098937002728221, 0.7952234761836543), (0.19916270916904044, 0.7689552603259296), (0.250319764137194, 0.7111682294644993), (0.3014768191053475, 0.7008819653567403), (0.6582300480283956, 0.6632231712798371), (0.6666685334677784, 0.658688271415733), (0.7646482839856097, 0.6322183223530311), (0.8120560994714594, 0.6155315414048562), (0.7590390380364216, 0.59962403681057), (0.8609150000772217, 0.569512653796447), (0.8083043720319294, 0.5354111445749077), (0.620024614496207, 0.4887918787850577), (0.5035114962372264, 0.4844464118877576), (0.8670977366853939, 0.48321853250106644), (0.5541193285153655, 0.4821747663938167), (0.8575697060274371, 0.47491541406252397)]
File "C:/Users/yuliy/PycharmProjects/method_deform_stars/DS.py", line 60, in create_star_pop
new_element = star_pop(population)
TypeError: 'list' object is not callable
[0.11503376215798591, 0.5133530350808552, 0.37081148554598065, 0.4201038734097051, 0.6098937002728221, 0.19916270916904044, 0.250319764137194, 0.3014768191053475, 0.6582300480283956, 0.6666685334677784, 0.7646482839856097, 0.8120560994714594, 0.7590390380364216, 0.8609150000772217, 0.8083043720319294, 0.620024614496207, 0.5035114962372264, 0.8670977366853939, 0.5541193285153655, 0.8575697060274371]
Process finished with exit code 1
import numpy as np
import math
import random
import operator
# Global variables
a = 0.1
b = 1
def function(x):
return (math.sin(40*math.pi*x)+math.pow(x-1, 4))/(2*x)
def initial_pop():
pop = np.random.uniform(a, b, 20)
pop = pop.tolist()
return pop
def moving_pop(population):
# e c
rand_item = population[random.randrange(len(population))]
# print(rand_item)
direction_arr = [-1, 1]
direction = direction_arr[random.randrange(len(direction_arr))]
# print(direction)
new_element = rand_item + direction * np.random.normal(0, 0.2)
if new_element > b:
extra = new_element - b
new_element = a + extra
if new_element < a:
extra = abs(new_element - a)
new_element = b - extra
# print(new_element)
return new_element
def create_moved_pop(population):
new_population = []
for x in range(0, 20):
new_element = moving_pop(population)
new_population.append(new_element)
# print(new_population)
return new_population
def star_pop(population):
random_item1 = population[random.randrange(len(population))]
random_item2 = population[random.randrange(len(population))]
while random_item2 == random_item1:
random_item2 = population[random.randrange(len(population))]
e_star = (random_item1 + random_item2)/2
return e_star
def create_star_pop(population):
star_population = []
for x in range(0, 20):
new_element = star_pop(population)
star_population.append(new_element)
# print(new_population)
return star_population
pop = initial_pop()
print(pop)
for i in range(0, 500):
moved_pop = create_moved_pop(pop)
star_pop = create_star_pop(pop)
pop_combined = sorted(sorted(pop) + sorted(moved_pop) +
sorted(star_pop))
y_array = []
for x in range(0, len(pop_combined)):
y_array.append(function(pop_combined[x]))
x_y_array = dict(zip(pop_combined, y_array))
sorted_x_y_array = sorted(x_y_array.items(), key=operator.itemgetter(1), reverse=True)
sorted_x_y_array = sorted_x_y_array[0:20]
print(sorted_x_y_array)
pop.clear()
for x in sorted_x_y_array:
pop.append(x[0])
print(pop)
you are re-defining star_pop as list
star_pop = create_star_pop(pop)
find the below fixed code
import numpy as np
import math
import random
import operator
# Global variables
a = 0.1
b = 1
def function(x):
return (math.sin(40*math.pi*x)+math.pow(x-1, 4))/(2*x)
def initial_pop():
pop = np.random.uniform(a, b, 20)
pop = pop.tolist()
return pop
def moving_pop(population):
# e c
rand_item = population[random.randrange(len(population))]
# print(rand_item)
direction_arr = [-1, 1]
direction = direction_arr[random.randrange(len(direction_arr))]
# print(direction)
new_element = rand_item + direction * np.random.normal(0, 0.2)
if new_element > b:
extra = new_element - b
new_element = a + extra
if new_element < a:
extra = abs(new_element - a)
new_element = b - extra
# print(new_element)
return new_element
def create_moved_pop(population):
new_population = []
for x in range(0, 20):
new_element = moving_pop(population)
new_population.append(new_element)
# print(new_population)
return new_population
def star_pop(population):
random_item1 = population[random.randrange(len(population))]
random_item2 = population[random.randrange(len(population))]
while random_item2 == random_item1:
random_item2 = population[random.randrange(len(population))]
e_star = (random_item1 + random_item2)/2
return e_star
def create_star_pop(population):
star_population = []
for x in range(0, 20):
new_element = star_pop(population)
star_population.append(new_element)
# print(new_population)
return star_population
pop = initial_pop()
print(pop)
for i in range(0, 500):
moved_pop = create_moved_pop(pop)
star_pop_ = create_star_pop(pop)
pop_combined = sorted(sorted(pop) + sorted(moved_pop) +
sorted(star_pop_))
y_array = []
for x in range(0, len(pop_combined)):
y_array.append(function(pop_combined[x]))
x_y_array = dict(zip(pop_combined, y_array))
sorted_x_y_array = sorted(x_y_array.items(), key=operator.itemgetter(1), reverse=True)
sorted_x_y_array = sorted_x_y_array[0:20]
print(sorted_x_y_array)
pop.clear()
for x in sorted_x_y_array:
pop.append(x[0])
print(pop)
You got a method called star_pop and an object called star_pop, in the 2nd iteration of the for loop you are trying
new_element = star_pop(population)
after doing
star_pop = create_star_pop(pop)
which returns a list
I think you mixed up your names. You can fix it by renaming either the function or the star_pop list.
Unrelated to that, you dont need to include the 0 in range(0, 500). Ranges always start at 0 by default.

Referencing a variable outside the Python class in the same script gives an error

I define arr = [] before anything else. Why do I get an error when my class references it?
arr = []
class BST:
key = 0
left = None
right = None
height = 0
index = 0
def __init__(self):
height = 0
def __str__(self):
return str(self.key)
def populate(self):
print("populating")
print(self.key)
if (self.left != None):
arr = arr + [self.left.populate()]
if (self.right != None):
arr = arr + [self.right.populate()]
return self.key
m1 = BST()
m1.key = 3
m2 = BST()
m2.key = 5
m1.left = m2
print(m1.left != None)
m3 = BST()
m3.key = 6
m2.left = m3
res = m1.populate()
print(res)
~/py/python bst.py
True
populating
3
Traceback (most recent call last):
File "bst.py", line 41, in <module>
res = m1.populate()
File "bst.py", line 22, in populate
arr = arr + [self.left.populate()]
UnboundLocalError: local variable 'arr' referenced before assignment
~/py/
Use global in the scope of function
arr = []
class BST:
key = 0
left = None
right = None
height = 0
index = 0
def __init__(self):
height = 0
def __str__(self):
return str(self.key)
def populate(self):
global arr
print("populating")
print(self.key)
if (self.left != None):
arr = arr + [self.left.populate()]
if (self.right != None):
arr = arr + [self.right.populate()]
return self.key
m1 = BST()
m1.key = 3
m2 = BST()
m2.key = 5
m1.left = m2
print(m1.left != None)
m3 = BST()
m3.key = 6
m2.left = m3
res = m1.populate()
print(res)
True
populating
3
populating
5
populating
6
3
You can import the main module, or make it global inside
arr = []
class BST:
key = 0
left = None
right = None
height = 0
index = 0
def __init__(self):
height = 0
def __str__(self):
return str(self.key)
def populate(self):
import __main__
print("populating")
print(self.key)
if (self.left != None):
__main__.arr = arr + [self.left.populate()]
if (self.right != None):
__main__.arr = arr + [self.right.populate()]
return self.key
m1 = BST()
m1.key = 3
m2 = BST()
m2.key = 5
m1.left = m2
print(m1.left != None)
m3 = BST()
m3.key = 6
m2.left = m3
res = m1.populate()
print(res)
True
populating
3
populating
5
populating
6
3
The reason is in these lines:
if (self.left != None):
arr = arr + [self.left.populate()]
if (self.right != None):
arr = arr + [self.right.populate()]
You think that the assignment to a global variable arr should be made. But the fact is, when Python compiles the body of the function def populate(), it decides that arr is a local
variable because it is assigned within the function. The generated bytecode reflects this
decision and will try to fetch arr from the local environment. Later, when the call m1.populate() is made, the body of populate() trying to fetch the value of local variable arr and discovers that arr is unbound.
Your code will work if you will try not to override arr but to extend it:
if (self.left != None):
arr.append(self.left.populate())
if (self.right != None):
arr.append(self.right.populate())

AttributeError: 'tuple' object has no attribute 'times_scalar'

This is my Linear System code. The times_scalar function is defined in the Vector object. When executing the multiply_coefficient_and_row function, I get AttributeError: 'tuple' object has no attribute 'times_scalar'. I tried different things including converting the tuple into a list and back to a tuple but had no success.
from decimal import Decimal, getcontext
from copy import deepcopy
from Vector import Vector
from Plane import Plane
getcontext().prec = 30
class LinearSystem(object):
ALL_PLANES_MUST_BE_IN_SAME_DIM_MSG = 'All planes in the system should live in the same dimension'
NO_SOLUTIONS_MSG = 'No solutions'
INF_SOLUTIONS_MSG = 'Infinitely many solutions'
def __init__(self, planes):
try:
d = planes[0].dimension
for p in planes:
assert p.dimension == d
self.planes = planes
self.dimension = d
except AssertionError:
raise Exception(self.ALL_PLANES_MUST_BE_IN_SAME_DIM_MSG)
def swap_rows(self, row1, row2):
self[row1], self[row2] = self[row2], self[row1]
def multiply_coefficient_and_row(self, coefficient, row):
n = self[row].normal_vector.coordinates
k = self[row].constant_term
new_normal_vector = n.times_scalar(coefficient)
new_constant_term = k * coefficient
self[row] = Plane(normal_vector = new_normal_vector, constant_term = new_constant_term)
def add_multiple_times_row_to_row(self, coefficient, row_to_add, row_to_be_added_to):
n1 = self[row_to_add].normal_vector.coordinates
n2 = self[row_to_be_added_to].normal_vector.coordinates
k1 = self[row_to_add].constant_term
k2 = self[row_to_be_added_to].constant_term
new_normal_vector = n1.times_scalar(coefficient).plus(n2)
new_constant_term = (k1 * coefficient) + k2
self[row_to_be_added_to] = Plane(normal_vector = new_normal_vector, constant_term = new_constant_term)
def indices_of_first_nonzero_terms_in_each_row(self):
num_equations = len(self)
num_variables = self.dimension
indices = [-1] * num_equations
for i,p in enumerate(self.planes):
try:
indices[i] = p.first_nonzero_index(p.normal_vector.coordinates)
except Exception as e:
if str(e) == Plane.NO_NONZERO_ELTS_FOUND_MSG:
continue
else:
raise e
return indices
def __len__(self):
return len(self.planes)
def __getitem__(self, i):
return self.planes[i]
def __setitem__(self, i, x):
try:
assert x.dimension == self.dimension
self.planes[i] = x
except AssertionError:
raise Exception(self.ALL_PLANES_MUST_BE_IN_SAME_DIM_MSG)
def __str__(self):
ret = 'Linear System:\n'
temp = ['Equation {}: {}'.format(i+1,p) for i,p in enumerate(self.planes)]
ret += '\n'.join(temp)
return ret
class MyDecimal(Decimal):
def is_near_zero(self, eps=1e-10):
return abs(self) < eps
and from the Vector class this times_scalar function:
def times_scalar(self, c):
new_coordinates = [Decimal(c) * x for x in self.coordinates]
return Vector(new_coordinates)

Categories