Related
This is the python code which uses A* algorithm for finding solution for 8 puzzle problems, I got some error messages, how can I fix it?(The error message is under the code)
There are several object-oriented programming concepts for Problems class, Node class that are implemented to express the problem solution search that you need to understand in order to make the Python program complete. The priority queue is to make the nodes to be explored to be sorted according to their f-evaluation function score and return the min one as the first node to be searched next.
There is also a memorize function to memorize the heuristic value of state as a look-up table so that you don’t need to calculate the redundant computing of heuristic estimation value, so you can ignore it at this point if you don’t understand.
The components you need to implement is to make the abstract part of the program realizable for 8 -puzzle with the successor methods attached to a problem class which consists of initial state and goal state. Make sure the program can run correctly to generate the solution sequence that move the empty tile so that the 8-puzzle can move "Up", "Down", "Left", "Right", from initial state to goal state.
import math
infinity = math.inf
from itertools import chain
import numpy as np
import bisect
class memoize:
def __init__(self, f, memo={}):
self.f = f
self.memo = {}
def __call__(self, *args):
if not str(args) in self.memo:
self.memo[str(args)] = self.f(*args)
return self.memo[str(args)]
def coordinate(state):
index_state = {}
index = [[0,0], [0,1], [0,2], [1,0], [1,1], [1,2], [2,0], [2,1], [2,2]]
for i in range(len(state)):
index_state[state[i]] = index[i]
return index_state
def getInvCount(arr):
inv_count = 0
empty_value = -1
for i in range(0, 9):
for j in range(i + 1, 9):
if arr[j] != empty_value and arr[i] != empty_value and arr[i] > arr[j]:
inv_count += 1
return inv_count
def isSolvable(puzzle) :
inv_count = getInvCount([j for sub in puzzle for j in sub])
return (inv_count % 2 == 0)
def linear(state):
return sum([1 if state[i] != goal[i] else 0 for i in range(9)])
#memoize
def manhattan(state):
index_goal = coordinate(goal)
index_state = coordinate(state)
mhd = 0
for i in range(9):
for j in range(2):
mhd = abs(index_goal[i][j] - index_state[i][j]) + mhd
return mhd
#memoize
def sqrt_manhattan(state):
index_goal = coordinate(goal)
index_state = coordinate(state)
mhd = 0
for i in range(9):
for j in range(2):
mhd = (index_goal[i][j] - index_state[i][j])**2 + mhd
return math.sqrt(mhd)
#memoize
def max_heuristic(state):
score1 = manhattan(state)
score2 = linear(state)
return max(score1, score2)
class PriorityQueueElmt:
def __init__(self,val,e):
self.val = val
self.e = e
def __lt__(self,other):
return self.val < other.val
def value(self):
return self.val
def elem(self):
return self.e
class Queue:
def __init__(self):
pass
def extend(self, items):
for item in items: self.append(item)
class PriorityQueue(Queue):
def __init__(self, order=min, f=None):
self.A=[]
self.order=order
self.f=f
def append(self, item):
queueElmt = PriorityQueueElmt(self.f(item),item)
bisect.insort(self.A, queueElmt)
def __len__(self):
return len(self.A)
def pop(self):
if self.order == min:
return self.A.pop(0).elem()
else:
return self.A.pop().elem()
# Heuristics for 8 Puzzle Problem
class Problem:
def __init__(self, initial, goal=None):
self.initial = initial; self.goal = goal
def successor(self, state):
reachable = []
def get_key(val):
for key, value in index_state.items():
if val == value:
return key
return -1
def candidate(state, Position):
state = state.copy()
zero_index = state.index(0)
swap_index = state.index(get_key(Position))
state[zero_index], state[swap_index] = state[swap_index], state[zero_index]
return state
index_state = coordinate(state)
zero_position = index_state[0]
move_pair = {"left":[zero_position[0], zero_position[1] - 1],
"right":[zero_position[0], zero_position[1] + 1],
"up":[zero_position[0] - 1, zero_position[1]],
"down":[zero_position[0] + 1, zero_position[1]]
}
for action, position in move_pair.items():
#print(action, position)
if get_key(position) != -1:
reachable.append((action, candidate(state, position)))
#print(reachable)
return reachable
def goal_test(self, state):
return state == self.goal
def path_cost(self, c, state1, action, state2):
return c + 1
def value(self):
abstract
class Node:
def __init__(self, state, parent=None, action=None, path_cost=0, depth =0):
self.parent = parent
if parent:
self.depth = parent.depth + 1
else:
self.depth = 0
self.path_cost = path_cost
self.state = state
if action:
self.action = action
else: self.action = "init"
def __repr__(self):
return "Node state:\n " + str(np.array(self.state).reshape(3,3)) +"\n -> action: " + self.action + "\n -> depth: " + str(self.depth)
def path(self):
x, result = self, [self]
while x.parent:
result.append(x.parent)
x = x.parent
return result
def expand(self, problem):
for (act,n) in problem.successor(self.state):
if n not in [node.state for node in self.path()]:
yield Node(n, self, act,
problem.path_cost(self.path_cost, self.state, act, n))
def graph_search(problem, fringe):
closed = {}
fringe.append(Node(problem.initial,depth=0))
while fringe:
node = fringe.pop()
if problem.goal_test(node.state):
return node
if str(node.state) not in closed:
closed[str(node.state)] = True
fringe.extend(node.expand(problem))
return None
def best_first_graph_search(problem, f):
return graph_search(problem, PriorityQueue(min, f))
def astar_search(problem, h = None):
h = h or problem.h
def f(n):
return max(getattr(n, 'f', -infinity), n.path_cost + h(n.state))
return best_first_graph_search(problem, f)
def print_path(path, method):
print("*" * 30)
print("\nPath: (%s distance)" % method)
for i in range(len(path)-1, -1, -1):
print("-" * 15)
print(path[i])
goal = [1, 2, 3, 4, 5, 6, 7, 8, 0]
# Solving the puzzle
puzzle = [7, 2, 4, 5, 0, 6, 8, 3, 1]
if(isSolvable(np.array(puzzle).reshape(3,3))): # even true
# checks whether the initialized configuration is solvable or not
print("Solvable!")
problem = Problem(puzzle,goal)
path = astar_search(problem, manhattan).path()
print_path(path, "manhattan")
path = astar_search(problem, linear).path()
print_path(path, "linear")
path = astar_search(problem, sqrt_manhattan).path()
print_path(path, "sqrt_manhattan")
path = astar_search(problem, max_heuristic).path()
print_path(path, "max_heuristic")
else :
print("Not Solvable!") # non-even false
TypeError Traceback (most recent call last)
<ipython-input-124-2a60ddc8c009> in <module>
9 problem = Problem(puzzle,goal)
10
---> 11 path = astar_search(problem, manhattan).path()
12 print_path(path, "manhattan")
13
<ipython-input-123-caa97275712e> in astar_search(problem, h)
18 def f(n):
19 return max(getattr(n, 'f', -infinity), n.path_cost + h(n.state))
---> 20 return best_first_graph_search(problem, f)
21
22 def print_path(path, method):
<ipython-input-123-caa97275712e> in best_first_graph_search(problem, f)
12
13 def best_first_graph_search(problem, f):
---> 14 return graph_search(problem, PriorityQueue(min, f))
15
16 def astar_search(problem, h = None):
<ipython-input-123-caa97275712e> in graph_search(problem, fringe)
8 if str(node.state) not in closed:
9 closed[str(node.state)] = True
---> 10 fringe.extend(node.expand(problem))
11 return None
12
<ipython-input-121-e5a968bd54f0> in extend(self, items)
18
19 def extend(self, items):
---> 20 for item in items: self.append(item)
21
22 class PriorityQueue(Queue):
<ipython-input-122-db21613469b9> in expand(self, problem)
69
70 def expand(self, problem):
---> 71 for (act,n) in problem.successor(self.state):
72 if n not in [node.state for node in self.path()]:
73 yield Node(n, self, act,
TypeError: cannot unpack non-iterable int object
I got some error messages, how can I fix it?
There is one error message, The pieces of codes you get in the error message are the stack trace, which might help you to know how the execution got at the final point where the error occurred. In this case that is not so important. The essence of the error is this:
for (act,n) in problem.successor(self.state)
TypeError: cannot unpack non-iterable int object
So this means that the successor method returned an int instead of a list.
Looking at the code for successor, I notice that it intends to return a list called reachable, but there is a return statement right in the middle of the code, leaving the largest part of that code unexecuted (so-called "dead code"):
return state
This statement makes no sense where it is positioned. It seems to be an indentation problem: that return belongs inside the function just above it, like this:
def candidate(state, Position):
state = state.copy()
zero_index = state.index(0)
swap_index = state.index(get_key(Position))
state[zero_index], state[swap_index] = state[swap_index], state[zero_index]
return state # <-- indentation!
I am trying to make a matrix and tensor in python without importing any modules such as numpy. Would there be a way to do this?
A matrix is just a list of lists. You can do so as such:
x = [[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[3, 4, 5, 6, 7]]
As far as performing operations without numpy goes, that will be up to you to create functions for likely using nested loops.
It would be a list of lists, e.g.:
matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
]
You would then have to implement all of the mathematical operations (matrix multiplication etc) on top of that data structure.
Python reserves the method name __matmul__ for matrix multiplication
class Matrix:
def __mul__(left, right):
print("__mul__ was called")
def __matmul__(left, right):
print("__MATMUL__ WAS CALLED")
def __rmatmul__(right, left):
print(40*"#")
print("__rmatmul__")
print("left == ", left)
print("right == ", right)
print(40 * "#")
def __imatmul__(total, step):
print("__imatmul__")
a = Matrix()
b = Matrix()
a * b # scalar multiplication __mul__
a # b # matrix multiplication __matmul__
3 # b # matrix multiplication __rmatmul__
a #= b
__imatmul__ is similar to the following:
x = 5
x += 2 # __iadd__(x, 2) `x = x + 2`
x *= 1 # __imul__(x, 3) `x = x * 3`
Whenever you write x * y python attempts to get the definition of multiplication from the left-hand argument first. That is, x * y is initially type(x).__add__(x, y)
However, sometimes the left-hand thing doesn't know how to multiply itself by the right-hand thing.
class K:
pass
a = K()
result = 55*a
result = type(55).__mul__(55, a)
The int class does not know how to multiply together 55 and an instance of class K. If type(left).__mul__(left, right) fails, then the back-up mechanism type(right).__rmul__(right, left) is called. If you write your own matrix class, then 3 __rmatmul__ and __rmul__ are what will be called when you put a scalar multiple out in front, like 88.
m = Matrix()
88 * m # __rmul__(m, 88)
88 # m # __rmatmul__(m, 88)
One way to implement a matrix is as a list of lists:
matrix = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 0],
]
This has several notable disadvantages. One is that it is easy to select a row of the matrix:
matrix[1] == [0, 1, 0]
However, selecting columns would be very inefficient:
def get_column(coli:int):
coli = 1
column = list()
for rowi in range(len(matrix)):
column.append(matrix[rowi][coli])
return column
One solution would be to have two different lists of lists:
one in "row-major" order.
the other in "column-major" order.
row_then_col = [
[[("r0", "c0")], [("r0", "c1")], [("r0", "c2")]],
[[("r1", "c0")], [("r1", "c1")], [("r1", "c2")]],
[[("r2", "c0")], [("r2", "c1")], [("r2", "c2")]],
]
ncols = 3
nrows = 3
col_then_row = list()
for coli in range(ncols):
col_then_row.append([None]*ncols)
for rowi in range(nrows):
col_then_row[coli]
col_then_row[coli][rowi] = row_then_col[rowi][coli]
Then col_then_row[coli] will return a whole column and row_then_col[rowi] will return a whole row. You can fake "pointers" with a list of one element. This is will allow a change in col_then_row to automatically be visible in row_then_col, a vis versa, without updating anything.
row_then_col[1][2][0] = "happy"
print(col_then_row[2][1][0]) # "happy"
There are many algorithms for matrix multiplication. I recommend implementing Strassen's algorithm. It is not the fastest in the world, but it is easier to understand than the truly fast ones.
There are many ways to implement matrices. The beginnings of one implementation is shown below:
import io
import math
import abc
def flatten(container):
for elem in container:
if not hasattr(elem, "__iter__"):
yield elem
else:
it_elem = iter(elem)
subelem = next(it_elem)
if subelem != elem:
yield subelem
for j in flatten(it_elem):
yield j
class MatrixNodeState(abc.ABC):
"""
Abstract Base Class
"""
pass
MatrixNodeState.MatrixNodeState = MatrixNodeState
class MatrixNodeStateNullNullNullClass(MatrixNodeState):
#classmethod
def ERR(cls):
with io.StringIO() as string_stream:
print(
"YOU ARE OFF THE EDGE OF THE MAP!",
"STOP ITERATING!",
file=string_stream
)
msg = string_stream.getvalue()
raise cls.OFF_THE_EDGE_OF_THE_MAP(msg)
class OFF_THE_EDGE_OF_THE_MAP(Exception):
pass
def __getattribute__(self, *args):
type(self).ERR()
def __setattr__(self, *args):
type(self).ERR()
MatrixNodeState.nullnullnull = MatrixNodeStateNullNullNullClass()
class MatrixNodeStateNullNullClass(MatrixNodeState):
def __setattr__(*args):
pass
def __getattribute__(self, *args):
return type(self).nullnullnull
MatrixNodeState.nullnull = MatrixNodeStateNullNullClass()
class MatrixNodeStateNullClass(MatrixNodeState):
"""
This class exists because `None.left = n`
would produce an error
`null.left = k` -----`no operation`.
Does nothing
Does not set the `left` attribute
of the nullnull node.
`x = node.left` returns `nullnull`
"""
def __setattr__(*args):
pass
def __getattribute__(self, *args):
return type(self).nullnull
MatrixNodeState.null = MatrixNodeStateNullClass()
class MatrixNodeStateNonNullNull(MatrixNodeState):
def __init__(self, data):
self.data = data
self.up = type(self).null
self.right = type(self).null
self.down = type(self).null
self.left = type(self).null
def __setattr__(self, key, value):
if isinstance(value, type(self).nullnull):
value = type(self).null
elif isinstance(value, type(self).nullnullnull):
value = type(self).null
super().__setattr__(self, key, value)
MatrixNodeState.MatrixNodeStateNonNullNull = MatrixNodeStateNonNullNull
class MatrixNode:
def __init__(self, data=None):
MatrixNodeState = type(self)
if data:
self.state = MatrixNodeState.MatrixNodeStateNonNullNull(data)
else:
self.state = MatrixNodeState.nullnull
def __getattr__(self, attrname):
return self.state.attrname
def __setattr__(self, attr_name, attr_value):
try:
object.__getattr__(self)
super().__setattr__(self, attr_name, attr_value)
except AttributeError:
setattr(self.state, attr_name, attr_value)
MatrixNode.MatrixNodeState = MatrixNodeState
class Matrix:
"""
"""
MatrixNode = MatrixNode
def __init__(self, xdims, xelems):
"""
Example 1:
m = Matrix([3, 3], [1, 0, 0, 0, 1, 0, 0, 0, 1])
Example 2
m = Matrix([3, 3], [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
"""
MatrixNode = type(self).MatrixNode
idims = tuple(map(int, xdims))
ielems = iter(flatten(xelems))
nrows = idims[0]
ncols = idims[1]
self.d = dict()
try:
elem_count = 0
left_node = MatrixNode.nullnull
up_node = MatrixNode.nullnull
for rowi in range(nrows):
for coli in range(ncols):
ielem = next(ielem)
elem_count += 1
up_node = left_node.up.right
node = MatrixNode(ielem)
self.d[(rowi, coli)] = node
node.left = left_node
left_node.right = node
node.up = up_node
up_node.down = node
left_node = node
except StopIteration:
with io.StringIO() as string_stream:
print(
"Dimensions", idims, "indicated",
"that there should be", math.prod(idims),
"elements.", "Instead, only ", elem_count,
"elements were found.",
file=string_stream
)
msg = string_stream.getvalue()
raise TypeError(msg)
def __getitem__(self, xkey):
ikey = tuple(map(int, iter(flatten(xkey))))
return self.d[ikey].data
def __setitem__(self, xkey, xval):
ikey = tuple(map(int, iter(flatten(xkey))))
self.d[ikey].data = xval
return
def get_column(self, coli):
coli = int(str(coli))
def get_row(self, rowi):
rowi = int(str(rowi))
def __mul__(left, right):
print("__mul__ was called")
raise NotImplementedError()
def __rmul__(right, left):
"""
m = Matrix([1, 2, 3])
88 * m
"""
print("__rmul__ was called")
raise NotImplementedError()
def __matmul__(left, right):
print("__MATMUL__ WAS CALLED")
raise NotImplementedError()
def __rmatmul__(right, left):
print(40*"#")
print("__rmatmul__")
print("left == ", left)
print("right == ", right)
print(40 * "#")
raise NotImplementedError()
def __imatmul__(total, step):
print("__imatmul__")
raise NotImplementedError()
def __str__(self):
raise NotImplementedError()
def __repr__(self):
return type(self) + str(self)
row_then_col = [
[[("r0", "c0")], [("r0", "c1")], [("r0", "c2")]],
[[("r1", "c0")], [("r1", "c1")], [("r1", "c2")]],
[[("r2", "c0")], [("r2", "c1")], [("r2", "c2")]],
]
a = Matrix([3, 3], row_then_col)
Im trying to append 2 arrays using python classes.
def __init__(self):
self.inArray = [0 for i in range(10)]
self.count = 0
def get(self, i):
return self.inArray[i]
def set(self, i, e):
self.inArray[i] = e
def length(self):
return self.count
def append(self, e):
self.inArray[self.count] = e
self.count += 1
if len(self.inArray) == self.count:
self._resizeUp() # resize array if reached capacity
def insert(self, i, e):
for j in range(self.count,i,-1):
self.inArray[j] = self.inArray[j-1]
self.inArray[i] = e
self.count += 1
if len(self.inArray) == self.count:
self._resizeUp() # resize array if reached capacity
def remove(self, i):
self.count -= 1
val = self.inArray[i]
for j in range(i,self.count):
self.inArray[j] = self.inArray[j+1]
return val
def __str__(self):
return str(self.inArray[:self.count])
def _resizeUp(self):
newArray = [0 for i in range(2*len(self.inArray))]
for j in range(len(self.inArray)):
newArray[j] = self.inArray[j]
self.inArray = newArray
def appendAll(self, A):
self.ls = [2,3,4,5]
ls = ls.append(A)
Im trying to write a function appendAll(self,A) that appends all elements of the array A in the array list (the one represented by self).
For example, if ls is [2,3,4,5] then ls.appendAll([42,24]) changes ls to [2,3,4,5,42,24].
This is all I can think of doing but I'm just stuck, any help will be appreciated
You can also just do like so (Basically just like extend).
ls += A
your code:
1. def appendAll(self, A):
2. self.ls = [2,3,4,5]
3. ls = ls.append(A)
The append function does not return a list
it operates on the original list.
the append function is also not what you are looking for,
because this will happen:
[2, 3, 4, 5, [42, 24]]
but extend will look like so:
[2, 3, 4, 5, 42,24]
Remember!
both functions do not return a new list
they simply operate on the given list.
You can use extend(
Have a look at What is the difference between Python's list methods append and extend? )
ls = ls.extend(A)
in your code :
def appendAll(self, A):
self.ls = [2,3,4,5]
self.ls = self.ls.extend(A)
I am currently practising python on code wars, here is a prompt:
Create a Vector object that supports addition, subtraction, dot products, and norms. So, for example:
a = Vector([1, 2, 3])
b = Vector([3, 4, 5])
c = Vector([5, 6, 7, 8])
a.add(b) # should return a new Vector([4, 6, 8])
a.subtract(b) # should return a new Vector([-2, -2, -2])
a.dot(b) # should return 1*3 + 2*4 + 3*5 = 26
a.norm() # should return sqrt(1^2 + 2^2 + 3^2) = sqrt(14)
a.add(c) # raises an exception
I have written functions add and subtract that pass some of the tests. However, I am running into issues with overwriting my previous list values of 'a' after running the add function. When I go into subtract, the 'a' values in the vector are the summations computed from the previous instance of the add function.
I suspect its due to me running this line of code:
return self.__class__(self.list) causing the instance of the class to overwrite itself.
Kindly please help, I believe I need to return a copy of the instance of the class but don't know how to do it.
class Vector:
def __init__(self, list):
self.list = list #[1,2]
self.copylist = list
def add(self,Vector):
try:
self.list = self.copylist
#take list from other vector
other = Vector.list
#take each value from other Vector and add it to self.list
for index,item in enumerate(Vector.list,0):
self.list[index] = item + self.list[index]
except:
print("Different size vectors")
#return the instance of a class
return self.__class__(self.list)
def subtract(self,Vector):
self.list = self.copylist
other = Vector.list
print(self.list)
print(other)
for index,item in enumerate(Vector.list,0):
self.list[index] = self.list[index] - item
return self.__class__(self.list)
def dot(self,Vector):
self.list = self.copylist
other = Vector.list
#print(self.list)
#print(other)
running_sum =0
for index,item in enumerate(Vector.list,0):
running_sum = running_sum + item * self.list[index]
#print(running_sum, " ", self.list[index], " ", item)
return running_sum
def norm(self):
running_sum = 0
for item in self.list:
running_sum += item**2
return running_sum ** 0.5
def toString(self):
return str(self.list)
`def equals(self,Vector):
return self.list == Vector.list
Here are some of the tests:
a = Vector([1, 2])
b = Vector([3, 4])
test.expect(a.add(b).equals(Vector([4, 6])))
a = Vector([1, 2, 3])
b = Vector([3, 4, 5])
test.expect(a.add(b).equals(Vector([4, 6, 8])))
test.expect(a.subtract(b).equals(Vector([-2, -2, -2]))) #code fails here
test.assert_equals(a.dot(b), 26)
test.assert_equals(a.norm(), 14 ** 0.5)
I think you're making this more complicated than it needs to be. You shouldn't be working with class objects at all. You should just be working with instances of the Vector class. Here's what I think your code should look like:
class Vector:
def __init__(self, initial_elements):
self.elements = list(initial_elements) # make a copy of the incoming list of elements
def add(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
# copy our elements
r = list(self.elements)
# add the elements from the second vector
for index, item in enumerate(other.elements, 0):
r[index] += item
# return a new vector object defined by the computed elements
return Vector(r)
def subtract(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
# copy our elements
r = list(self.elements)
# subtract the elements from the second vector
for index, item in enumerate(other.elements, 0):
r[index] -= item
# return a new vector object defined by the computed elements
return Vector(r)
def dot(self, other):
running_sum = 0
for index, item in enumerate(other.elements, 0):
running_sum += item * self.elements[index]
return running_sum
def norm(self):
running_sum = 0
for item in self.elements:
running_sum += item ** 2
return running_sum ** 0.5
def toString(self):
return str(self.elements)
def equals(self, other):
return self.elements == other.elements
def test():
a = Vector([1, 2])
b = Vector([3, 4])
print(a.add(b).equals(Vector([4, 6])))
a = Vector([1, 2, 3])
b = Vector([3, 4, 5])
print(a.add(b).equals(Vector([4, 6, 8])))
print(a.subtract(b).equals(Vector([-2, -2, -2])))
print(a.dot(b) == 26)
print(a.norm() == 14 ** 0.5)
test()
Result:
True
True
True
True
True
The general structure of your code is spot on.
One thing to note is that you shouldn't be using list as a variable name, as it is a type name in Python. Also, you don't want to be passing around Vector as a value. You want to be passing instances of Vector and list, with names that do not conflict with these type names.
My solution assumes you want Vector instances to be immutable, so each of your operations will return a new Vector object. You could also have them not be immutable and have, for example, the add method just add the incoming vector into the target vector without creating a new object. I like keeping them immutable. I've been doing more and more of this "functional style" programming lately, where calls to object methods don't modify the target object (don't have side effects), but rather just return a new object.
I like your use of the test class to do your testing. I chose to not deal with this, and just print the results of each test comparison to see that they all come out to True. I'll leave it to you to restore your tests to using a test object with expect and assert_equals methods.
UPDATE: Here is a more compact way to write your add and subtract methods:
def add(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
return Vector([self.elements[i] + other.elements[i] for i in range(len(self.elements))])
def subtract(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
return Vector([self.elements[i] - other.elements[i] for i in range(len(self.elements))])
change:
return self.__class__(self.list)
to:
return self
although this would the same as,
return Vector(self.list)
if the class is more complicated it is better to return self
I think that's the issue, hope it helps :)
also, it is good practice to use different names. you used Vector for the class name as well as many of the inputs of the functions, you will run into problems when you do that.
Please change function toString to str . its' already done.
class Vector :
def __init__(self , lst_vec):
self.lst_vec = lst_vec
def show_vector(self):
return self.lst_vec
def add(self , v ):
size_self = len(self.lst_vec)
size_v = len(v.lst_vec)
new_vector = []
if ( size_self != size_v ):
return Exception("error add")
else:
for i in range(size_self):
new_vector.append(self.lst_vec[i] + v.lst_vec[i])
return Vector(new_vector)
def subtract(self , v ):
size_self = len(self.lst_vec)
size_v = len(v.lst_vec)
new_vector = []
if ( size_self != size_v ):
return Exception("error subtract")
else:
for i in range(size_self):
new_vector.append(self.lst_vec[i] - v.lst_vec[i])
return Vector(new_vector)
def dot(self , v ):
size_self = len(self.lst_vec)
size_v = len(v.lst_vec)
new_vector = []
sum_vec = 0
if ( size_self != size_v ):
return Exception("Vector sizes are different")
else:
for i in range(size_self):
new_vector.append(self.lst_vec[i] * v.lst_vec[i])
for i in range(len(new_vector)):
sum_vec+=new_vector[i]
return sum_vec
def norm (self):
new_vec_sum = 0
for i in range(len(self.lst_vec)):
new_vec_sum +=( self.lst_vec[i] ) **2
return new_vec_sum ** 0.5
def toString(self):
str_self = '('
for i in range(len(self.lst_vec)):
str_self += str(self.lst_vec[i])
if i < (len(self.lst_vec)-1):
str_self+=','
else : pass
str_self+=')'
return str_self
def equals(self , v ):
return self.lst_vec == v.lst_vec
a = Vector([1,2,3])
b = Vector([3,4,5])
c = Vector([5,6,7,8])
print(a.add(b).show_vector())
print( a.add(b).equals(Vector([4,6,8])) )
print(a.subtract(b).show_vector())
print(a.dot(b))
print(a.norm())
print((a.toString() == '(1,2,3)'))
print(c.toString())
import random
import operator
import sys
import unittest
__version__ = "0.3"
class MatrixError(Exception):
""" An exception class for Matrix """
pass
class Matrix(object):
""" A simple Python matrix class with
basic operations and operator overloading """
def __init__(self, m, n, init=True):
if init:
self.rows = [[0]*n for x in range(m)]
else:
self.rows = []
self.m = m
self.n = n
def __getitem__(self, idx):
return self.rows[idx]
def __setitem__(self, idx, item):
self.rows[idx] = item
def __str__(self):
s='\n'.join([' '.join([str(item) for item in row]) for row in self.rows])
return s + '\n'
def __repr__(self):
s=str(self.rows)
rank = str(self.getRank())
rep="Matrix: \"%s\", rank: \"%s\"" % (s,rank)
return rep
def reset(self):
""" Reset the matrix data """
self.rows = [[] for x in range(self.m)]
def transpose(self):
""" Transpose the matrix. Changes the current matrix """
self.m, self.n = self.n, self.m
self.rows = [list(item) for item in zip(*self.rows)]
def getTranspose(self):
""" Return a transpose of the matrix without
modifying the matrix itself """
m, n = self.n, self.m
mat = Matrix(m, n)
mat.rows = [list(item) for item in zip(*self.rows)]
return mat
def getRank(self):
return (self.m, self.n)
def __eq__(self, mat):
""" Test equality """
return (mat.rows == self.rows)
def __add__(self, mat):
""" Add a matrix to this matrix and
return the new matrix. Doesn't modify
the current matrix """
if self.getRank() != mat.getRank():
raise MatrixError, "Trying to add matrixes of varying rank!"
ret = Matrix(self.m, self.n)
for x in range(self.m):
row = [sum(item) for item in zip(self.rows[x], mat[x])]
ret[x] = row
return ret
def __sub__(self, mat):
""" Subtract a matrix from this matrix and
return the new matrix. Doesn't modify
the current matrix """
if self.getRank() != mat.getRank():
raise MatrixError, "Trying to add matrixes of varying rank!"
ret = Matrix(self.m, self.n)
for x in range(self.m):
row = [item[0]-item[1] for item in zip(self.rows[x], mat[x])]
ret[x] = row
return ret
def __mul__(self, mat):
""" Multiple a matrix with this matrix and
return the new matrix. Doesn't modify
the current matrix """
matm, matn = mat.getRank()
if (self.n != matm):
raise MatrixError, "Matrices cannot be multipled!"
mat_t = mat.getTranspose()
mulmat = Matrix(self.m, matn) or Matrix(self.m, a)
for x in range(self.m):
for y in range(mat_t.m) or y==a:
mulmat[x][y] = sum([item[0]*item[1] for item in zip(self.rows[x], mat_t[y])])or a*x
return mulmat
def __iadd__(self, mat):
""" Add a matrix to this matrix.
This modifies the current matrix """
# Calls __add__
tempmat = self + mat
self.rows = tempmat.rows[:]
return self
def __isub__(self, mat):
""" Add a matrix to this matrix.
This modifies the current matrix """
# Calls __sub__
tempmat = self - mat
self.rows = tempmat.rows[:]
return self
def __imul__(self, mat):
""" Add a matrix to this matrix.
This modifies the current matrix """
# Possibly not a proper operation
# since this changes the current matrix
# rank as well...
# Calls __mul__
tempmat = self * mat
self.rows = tempmat.rows[:]
self.m, self.n = tempmat.getRank()
return self
def save(self, filename):
open(filename, 'w').write(str(self))
#classmethod
def _makeMatrix(cls, rows):
m = len(rows)
n = len(rows[0])
# Validity check
if any([len(row) != n for row in rows[1:]]):
raise MatrixError, "inconsistent row length"
mat = Matrix(m,n, init=False)
mat.rows = rows
return mat
#classmethod
def makeRandom(cls, m, n, low=0, high=10):
""" Make a random matrix with elements in range (low-high) """
obj = Matrix(m, n, init=False)
for x in range(m):
obj.rows.append([random.randrange(low, high) for i in range(obj.n)])
return obj
#classmethod
def makeZero(cls, m, n):
""" Make a zero-matrix of rank (mxn) """
rows = [[0]*n for x in range(m)]
return cls.fromList(rows)
#classmethod
def makeId(cls, m):
""" Make identity matrix of rank (mxm) """
rows = [[0]*m for x in range(m)]
idx = 0
for row in rows:
row[idx] = 1
idx += 1
return cls.fromList(rows)
#classmethod
def readStdin(cls):
""" Read a matrix from standard input """
print 'Enter matrix row by row. Type "q" to quit'
rows = []
while True:
line = sys.stdin.readline().strip()
if line=='q': break
row = [int(x) for x in line.split()]
rows.append(row)
return cls._makeMatrix(rows)
#classmethod
def readGrid(cls, fname):
""" Read a matrix from a file """
rows = []
for line in open(fname).readlines():
row = [int(x) for x in line.split()]
rows.append(row)
return cls._makeMatrix(rows)
#classmethod
def fromList(cls, listoflists):
""" Create a matrix by directly passing a list
of lists """
# E.g: Matrix.fromList([[1 2 3], [4,5,6], [7,8,9]])
rows = listoflists[:]
return cls._makeMatrix(rows)
I'm trying to put a scalar multiplication but it always fail.
For example,
a = [[2,2],[2,3]]
If I multiply it's like, 3*a = [[2,2],[2,3],[2,2],[2,3],[2,2],[2,3]]
How could I fix it?
For example, a = [[2,2],[2,3]] If I multiply it's like, 3*a = [[2,2],[2,3],[2,2],[2,3],[2,2],[2,3]]
Here, a is a list and not a Matrix. You can't overload the multiplication of a standard list by a scalar.
You can't multiply the whole list. The output you got is like a string multiplication.
a="hello"
b=a*3
print b
gives the output as
hellohellohello
That is what happens in your case. Multiply one by one
for i in range(len(a)):
for j in range(len(i)):
a[i][j]*=3