How to execute the cross multiplication in unittest - python

I have the following class
from math import sqrt
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __eq__(self, other): # v == w
return self.x == other.x and self.y == other.y and self.z == other.z
def __ne__(self, other): # v != w
return not self == other
def __repr__(self):
return "Vector(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ")"
def __add__(self, other):
return Vector(self.x + other.x,self.y + other.y,self.z + other.z)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y, self.z - other.z)
def __mul__(self, other):
return self.x * other.x + self.y * other.y + self.z * other.z
def cross(self, other):
return Vector(self.y * other.z - self.z * other.y,self.z * other.x - self.x * other.z,self.x * other.y - self.y * other.x)
def length(self):
return sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2)
def __hash__(self):
return hash((self.x, self.y, self.z))
on which I am trying to use the unittest function as follows:
class TestVector(unittest.TestCase):
# test function to test equality of two value
def test_vector_equality(self):
A = [1, 2, 3]
B = [1, 2, 3]
# error message in case if test case got failed
#message = "First value and second value are not equal!"
self.assertTrue(A == B)
def test_vector_inequality(self):
A = [1, 2, 3]
B = [1,-2,-3]
self.assertFalse(A == B)
def test_vector_addition(self):
A = [1, 2, 3]
B = [1, 2, 3]
result = [2, 4, 6]
self.assertEqual([x + y for x, y in zip(A, B)], result)
def test_vector_mulitplication(self):
A = [1, 2, 3]
B = [1, 2, 3]
result = [1, 4, 9]
self.assertEqual([x*y for x, y in zip(A, B)], result)
def test_vector_subtraction(self):
A = [1, 2, 3]
B = [1, 5, 8]
result = [0, -3, -5]
self.assertEqual([x - y for x, y in zip(A, B)], result)
def test_vector_cross_multiplication(self):
A = [1, 2, 3]
B = [1, 5, 8]
result = [1 ,5, 3]
self.assertEqual([(x[0]*y[1], x[1]*y[0]) for x, y in zip(A, B)], result)
def test_length(self):
A = [1, 2, 3]
B = [1, 4, 9]
self.assertEqual(B, [i ** 2 for i in A])
if __name__ == "__main__":
unittest.main(argv=['first-arg-is-ignored'], exit= False)
It works great for all the tests before the cross multiplication one. I would like to get some suggestions about how to set it. Also, I do not know how to set the hash test. Just let me know if you possibly might suggest some way to fix this.
Thank you so much

Unrelated to the question, but imporant: this is not how you unittest. Tests are expected to use class methods, comparing results with expected ones.
Now the issues with test_vector_cross_multiplication:
the result should be [1, -5, 3] instead of [1, 5, 3]
the comprehension [(x[0]*y[1], x[1]*y[0]) for x, y in zip(A, B)] uses indexes on numbers and produces tuples
The correct way to calculate the cross product:
[(A[i]*B[i+1] - B[i]*A[i+1]) for i in range(1-len(A), 1)]

Related

error message with exception in cross product

I'm trying to define a class Vector, in a way the cross-product of two vectors v1 and v2 results in a perpendicular unit vector v3, while such a product is zero, then it should turn back an exception message. I've set the code as follows:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __repr__(self):
return "Vector(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ")"
def cross(self, V):
return Vector(self.y * V.z - self.z * V.y,self.z * V.x - self.x * V.z,self.x * V.y - self.y * V.x)
def find_axis(v,w):
x = v.cross(w)
print(type(x))
if x==Vector(0,0,0):
return "error"
#raise Exception(" (ValueError)")return x
But when trying to run the product between vectors, which cross product would be supposed to be different from zero, like the following example:
v = Vector(1, 2, 3)
w = Vector(1, 2, 3)
And I get excalty:
v.cross(w)
Vector(0, 0, 0)
I cannot figure out which the error is, since in this case the code is supposed to return an error message. Can anyone please know what is up?
A second way I tried was
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __repr__(self):
return "Vector(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ")"
def cross(self, V):
return Vector(self.y * V.z - self.z * V.y,self.z * V.x - self.x * V.z,self.x * V.y - self.y * V.x)
def __eq__(self, V):
if self.x == V.x and self.y == V.y and self.z == V.z:
raise ValueError("negative x")
but I got the same problem
The solution to this just required to invert in the exact order the if statement unde cross definition:
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __repr__(self):
return "Vector(" + str(self.x) + ", " + str(self.y) + ", " + str(self.z) + ")"
def cross(self, V):
if self.x == V.x and self.y == V.y and self.z == V.z:
raise ValueError("The vector is parallel and not perpendicular")
else:
return Vector(self.y * V.z - self.z * V.y, self.z * V.x - self.x * V.z,self.x * V.y - self.y * V.x)
#1st case
v = Vector(1, 2, 3)
w = Vector(9, 2, 3)
print(v.cross(w))
#2nd Case
v = Vector(1, 2, 3)
w = Vector(1, 2, 3)
print(v.cross(w))

Vector addition and multiplication, adding error

I'm supposed to create a program that is used to multiply or and/or add vectors. I'm supposed to do this using classes and overloading the built in functions like "+" and "str". I've done most of it but my problem is when I run the cases
v1 = Vector([2, 3, 4])
v2 = Vector([1, 2, 2])
v2[3] = 3
print(str(v2) == 'Vector: [1, 2, 3]')
print(str(v1 + v2) == 'Vector: [3, 5, 7]')
print(str(v2 * 2) == 'Vector: [2, 4, 6]')
print(str(2 * (v1 + v2)) == 'Vector: [6, 10, 14]')
For the last case I receive false, I did some poking around and found that my function is storing the data from the previous cases and is using them to compute the last case.
using print(str(v1 + v2) == 'Vector: [3, 5, 7]')
print(str(v2 * 2) == 'Vector: [2, 4, 6]')
as the 2 vectors instead and getting Vector: [10, 18, 26] as an output
my code is below:
class Vector:
def __init__(self,l):
if (isinstance(l,list) == False):
raise TypeError
elif(isinstance(l,list)):
for i in l:
if (isinstance(i, int) == False and isinstance(i,int) == False):
raise TypeError
else:
self.l = l
def dim(self):
return len(self.l)
def __getitem__ (self,i):
if i > len(self.l) or i < 1:
raise IndexError
return (self.l[i-1])
def __setitem__(self, i, x):
if i > len(self.l) or i < 1:
raise IndexError
self.l[i-1] = x
def __str__(self):
print ("Vector: "+ str(self.l))
return ("Vector: "+ str(self.l))
def __add__(self, other):
if (not isinstance(other, Vector)):
raise ValueError
elif(other.dim() != self.dim()):
raise ValueError
for i in range(0,len(self.l)):
self.l[i] = self.l[i] + other[i+1]
return Vector(self.l)
def __mul__(self, other):
if (isinstance(other,float)) or (isinstance(other,int)):
for j in range (0, len(self.l)):
self.l[j] = self.l[j] * other
return Vector(self.l)
elif (isinstance(other, Vector)):
for i in range(0,len(self.l)):
self.l[b] = self.l[b] * other[i+1]
return sum(self.l)
else:
raise AssertionError
def __rmul__(self,other):
if (isinstance(other,float)) or (isinstance(other,int)):
for k in range (0, len(self.l)):
self.l[k] = self.l[k] * other
return Vector(self.l)
elif (isinstance(other, Vector)):
for i in range(0,len(self.l)):
self.l[b] = self.l[b] * other[i+1]
return sum(self.l)
else:
raise AssertionError
How can I fix this unwanted overwriting?

Optimization 8-puzzle

I'm junior programmer, I am trying to solve 8-puzzle problem with breadth first search, but it took too long time to solve it, i want to optimize my code.
Configuration: [[5, 4, 3], [0, 7, 2], [6, 1, 8]] is going to solve in 22.623718615 seconds,
configuration [[8, 0, 6], [5, 4, 7], [2, 3, 1]] took among 235.721346421 seconds.
I want to decrease solve time.
There is my code:
from copy import deepcopy
from collections import deque
from time import perf_counter
most_hard = [[8, 0, 6], [5, 4, 7], [2, 3, 1]] # 30 moves
class CheckPuzzle:
def __init__(self, puzzle: list):
self.puzzle = puzzle
self.len = len(puzzle)
if self.len == 3:
self.goal = [[1, 2, 3],
[4, 5, 6],
[7, 8, 0]]
elif self.len == 4:
self.goal = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
if not self.is_valid():
raise TypeError("Puzzle is not valid")
elif not self.is_solvable():
raise Exception("Unsolvable puzzle")
# создай ф-ию check
def sum_of_numbers(self) -> int:
return sum(self.convert_to_1d(self.goal))
def sum_of_squares(self) -> int:
return sum([i ** 2 for i in self.convert_to_1d(self.goal)])
def is_valid(self) -> bool:
sum_of_numbers = 0
sum_of_squares = 0
for row in range(self.len):
for column in range(self.len):
sum_of_numbers += self.puzzle[row][column]
sum_of_squares += (self.puzzle[row][column]) ** 2
return sum_of_numbers == self.sum_of_numbers() and sum_of_squares == self.sum_of_squares()
def convert_to_1d(self, board) -> list:
one_dimension_matrix = []
for row in range(self.len):
for column in range(self.len):
one_dimension_matrix.append(board[row][column])
return one_dimension_matrix
def inversion(self, board) -> int:
inversion = 0
one_dimension_matrix = self.convert_to_1d(board)
for index in range(len(one_dimension_matrix)):
temp = one_dimension_matrix[index]
if temp == 0 or temp == 1:
continue
for elem in one_dimension_matrix[index:]:
if elem == 0:
continue
if temp > elem:
inversion += 1
return inversion
def is_solvable(self) -> bool:
inv_of_matrix = self.inversion(self.puzzle)
inv_of_goal_matrix = self.inversion(self.goal)
return (inv_of_matrix % 2 == 0 and inv_of_goal_matrix % 2 == 0) or \
(inv_of_matrix % 2 == 1 and inv_of_goal_matrix % 2 == 1)
class Puzzle:
def __init__(self, board: list):
self.board = board
self.len = len(board)
if self.len == 3:
self.goal = [[1, 2, 3],
[4, 5, 6],
[7, 8, 0]]
elif self.len == 4:
self.goal = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
def print_matrix(self) -> str:
output = ''
for row in self.board:
for elem in row:
output += str(elem) + " "
output += '\n'
return output
def get_index(self, matrix, value) -> tuple:
for i in range(self.len):
for j in range(self.len):
if matrix[i][j] == value:
return i, j
def manhattan(self):
distance = 0
for i in range(self.len):
for j in range(self.len):
if self.board[i][j] != 0:
x, y = divmod(self.board[i][j] - 1, self.len)
distance += abs(x - i) + abs(y - j)
return distance
def list_of_possible_moves(self) -> list:
x, y = self.get_index(self.board, 0)
possible_moves = []
if x > 0:
possible_moves.append((x - 1, y))
if x < self.len - 1:
possible_moves.append((x + 1, y))
if y > 0:
possible_moves.append((x, y - 1))
if y < self.len - 1:
possible_moves.append((x, y + 1))
return possible_moves
def move(self, to: tuple) -> list:
moving_board = deepcopy(self.board)
x, y = self.get_index(self.board, 0)
i, j = to
moving_board[x][y], moving_board[i][j] = moving_board[i][j], moving_board[x][y]
return moving_board
def solved(self) -> bool:
return self.board == self.goal
def __str__(self) -> str:
return ''.join(map(str, self))
def __iter__(self):
for row in self.board:
yield from row
class Node:
def __init__(self, puzzle, parent=None):
self.puzzle = puzzle
self.parent = parent
if self.parent:
self.g = parent.g + 1
else:
self.g = 0
def state(self) -> str:
return str(self)
def path(self):
node, p = self, []
while node:
p.append(node)
node = node.parent
yield from reversed(p)
def solved(self) -> bool:
return self.puzzle.solved()
def pretty_print(self) -> str:
return self.puzzle.print_matrix()
def h(self) -> int:
return self.puzzle.manhattan()
def f(self) -> int:
return self.h() + self.g
def all_moves(self) -> list:
return self.puzzle.list_of_possible_moves()
def __str__(self) -> str:
return str(self.puzzle)
def make_a_move(self, to: tuple) -> list:
return self.puzzle.move(to)
class GameTree:
def __init__(self, root):
self.root = root
def solve(self):
queue = deque([Node(self.root)])
seen = set()
seen.add(queue[0].state())
while queue:
queue = deque(sorted(list(queue), key=lambda node: node.f()))
node = queue.popleft()
if node.solved():
return node.path()
for move in node.all_moves():
moved = node.make_a_move(move)
child = Node(Puzzle(moved), node)
if child.state() not in seen:
queue.append(child)
seen.add(child.state())
def main():
a = [[5, 4, 3], [0, 7, 2], [6, 1, 8]]
c = Puzzle(a)
d = GameTree(c)
tic = perf_counter()
p = d.solve()
toc = perf_counter()
step = 0
for i in p:
print(i.pretty_print())
step += 1
print(step)
print(toc-tic)
if __name__ == "__main__":
main()
Description:
The 15-puzzle (also called Gem Puzzle, Boss Puzzle, Game of Fifteen,
Mystic Square and many others) is a sliding puzzle that consists of a
frame of numbered square tiles in random order with one tile missing.
The puzzle also exists in other sizes, particularly the smaller
8-puzzle. If the size is 3×3 tiles, the puzzle is called the 8-puzzle
or 9-puzzle, and if 4×4 tiles, the puzzle is called the 15-puzzle or
16-puzzle named, respectively, for the number of tiles and the number
of spaces. The object of the puzzle is to place the tiles in order by
making sliding moves that use the empty space.
https://en.wikipedia.org/wiki/15_puzzle

Assigning variable = self creating a copy. Need it to be a reference (pointer)

I am working on creating a matrix class for an assignment I have and usually if I assign a variable as x = self, x is a reference to self and thus all operations are in place. I have a function that reduces the matrix, and as an optional parameter I've added inplace=False such that:
if inplace:
self = A
else:
A = self.copy()
Now normally when I do this, if I were to do an operation such as A += B, self would be modified. However, when I run A.reduce(inplace=True), A is not modified. I've included the full class below and am hoping that someone can tell my why the operations are not happening in place. Thanks in advance.
import numpy as np
class matrix:
def __init__(self, A):
self.value = np.array(A, dtype=np.float)
self.indices = np.arange(self.value.shape[0])
self.shape = self.value.shape
def swap_rows(self, r1, r2):
ind = np.arange(self.value.shape[0])
swap = (r1, r2)
ind[swap[0]] = swap[1]
ind[swap[1]] = swap[0]
temp_ind = self.indices[swap[0]]
self.indices[swap[0]] = self.indices[swap[1]]
self.indices[swap[1]] = temp_ind
self.value = self.value[ind]
def add_rows(self, operations):
# operations = [(c, row1, row2)]
# where operation will be:
# c * row1 + row2 -> row2
for c, row1, row2 in operations:
self.value[row2] += c * self.value[row1]
# ... #
def reduce(self, b_ = None, swap=True, normalize=True, return_steps=False, inplace=False, debug=False):
if inplace:
A = self
else:
A = self.copy()
if b_:
b = b_.copy()
if len(b.shape) == 1:
b.reshape((-1, 1), inplace=True)
if return_steps:
steps = []
# Normalize
if normalize:
A_max = A.row_max()
A /= A_max
if debug:
print("A after normalization:")
print(A)
print("")
if return_steps:
steps.append([('normalize', A_max)])
if b_:
b /= A_max
m, n = A.shape
for col in range(n-1):
# Swap
if swap:
# Check for max value
max_ind = np.argmax(np.abs(A[:, col]))
# Check if max is zero
if np.abs(A[max_ind, col]) < 1e-30:
print('Matrix is singular')
if b_:
return A, b
else:
return A
# Swap if necessary
if max_ind > col:
A.swap_rows(col, max_ind)
if return_steps:
steps.append([('swap', col, max_ind)])
if b_:
b.swap_rows(col, max_ind)
# Get constants
cs = -A[col+1:, col] / A[col, col]
operations = [(c, col, i+col+1) for i, c in enumerate(cs)]
if return_steps:
steps.append(operations)
A.add_rows(operations)
if b_:
b.add_rows(operations)
if debug:
print("A after row operations:")
print(A)
print("")
return_vals = np.array([A, None, None])
if b_:
return_vals[1] = b
if return_steps:
return_vals[2] = steps
if inplace:
return_vals = return_vals[1:]
if return_vals.any():
return tuple(return_vals[return_vals != None])
# ... #
def row_max(self):
return np.array([self[row, i] for row, i in enumerate(np.argmax(np.abs(self.value), axis=1))]).reshape(-1, 1)
# ... #
def copy(self):
return matrix(np.copy(self.value))
def T(self):
return matrix(self.value.T)
def inverse(self):
return matrix(np.linalg.inv(self.value))
def flip(self, axis=None, inplace=False):
if inplace:
self.value = np.flip(self.value, axis=axis)
else:
return matrix(np.flip(self.value, axis=axis))
def reshape(self, shape, inplace=False):
if inplace:
self.value = self.value.reshape(*shape)
else:
return matrix(self.value.reshape(*shape))
def __add__(self, x):
if isinstance(x, matrix):
return matrix(self.value + x.value)
else:
return matrix(self.value + x)
def __sub__(self, x):
if isinstance(x, matrix):
return matrix(self.value - x.value)
else:
return matrix(self.value - x)
def __mul__(self, x):
if isinstance(x, matrix):
return matrix(self.value * x.value)
else:
return matrix(self.value * x)
def __truediv__(self, x):
if isinstance(x, matrix):
return matrix(self.value / x.value)
else:
return matrix(self.value / x)
# ... #
def __matmul__(self, A):
if isinstance(A, matrix):
return matrix(self.value # A.value)
else:
return matrix(self.value # A)
def __repr__(self):
return str(self.value)
def __getitem__(self, item):
return self.value[item]
def __setitem__(self, i, v):
self.value[i] = v
A = matrix([ [ 5, 6, 7, 5, -1],
[ 8, -4, -1, 0, -3],
[ 2, 1, -1, 3, 6],
[-9, 10, 1, -4, 6],
[ 9, 5, -5, -8, 4] ])
print("Original A:")
print(A)
print("")
A.reduce(inplace=True, debug=True)
print("A after inplace reduce function:")
print(A)
print("")
EDIT
Here is what I am trying to recreate in a simplistic way:
class obj:
def __init__(self, value):
self.value = value
def copy(self):
return obj(self.value)
def op(self, y, inplace=False):
if inplace:
x = self
else:
x = self.copy()
x.value += y
x.value /= y
if not inplace:
return x
def __repr__(self):
return str(self.value)
x = obj(5)
x.op(3)
print("Copy:", x)
x.op(3, inplace=True)
print("Inplace:", x)
You say that operators like += modify objects in place, but that's not always true. It only happens if the type of the object on the left side of the operator has an __iadd__ method. If it only has an __add__ method, then the Python interpreter translates X += Y to X = X + Y which is generally not an in-place operation.
So the reason your code doesn't do what you expect is because you don't have an __itruediv__ operator, and when you call A /= A_max (if normalize is True), you make a copy, despite your intention to be operating in place.

about vector by using class

I need some helps with my code!
Here is some instruction:
v.mul(other) : If other is of type Vector , returns the dot > product of v and other , which is the sum of the products of the >
corresponding components; raises an assertion error if other is of >
different dimension. If other is of type int or float , returns a new
vector resulting from the scalar multiplication of v with other . If > the type of other is not Vector , int , or float , raises an
assertion > error.
v.rmul(other) : Defined exactly like v.mul(other)
========================================================================
Here is the code:
class Vector(object):
vec = []
def __init__(self, l):
self.vec = l
def dim():
return len(self.vec)
def __getitem__(self, i):
return self.vec[i - 1]
def __setitem__(self, i, x):
self.vec[i - 1] = x
def __str__(self):
s = 'Vector: ['
for i in range(0, len(self.vec)):
s = s + str(self.vec[i])
if i < len(self.vec) - 1:
s = s + ', '
s = s + ']'
return s
def __add__(self, other):
assert(type(other) == Vector)
v = self.vec
for i in range(0, len(v)):
v[i]=v[i] + other[i+1]
x = Vector(v)
return x
def __mul__(self, other):
if type(other) == type(self):
v = self.vec
for i in range(0, len(v)):
v[i]=v[i]*other[i+1]
x = Vector(v)
return sum(x)
elif type(other) == type(1) or type(other) == type(1.0):
v = self.vec
for i in range(0, len(v)):
v[i] = v[i] *other
x = Vector(v)
return x
def __rmul__(self, other):
return self.__mul__(other)
Here are some output from the code:
>>> v1 = Vector([2, 3, 4]); v2 = Vector([1, 2, 3])
>>> print(v2 * 2); print(2 * v2)
Vector: [2, 4, 6]
Vector: [4, 8, 12]
>>> print(v1 * v2); print(v2 * v1)
128
1376
But, the correct output is:
>>> v1 = Vector([2, 3, 4]); v2 = Vector([1, 2, 3])
>>> print(v2 * 2); print(2 * v2)
Vector: [2, 4, 6]
Vector: [2, 4, 6]
>>> print(v1 * v2); print(v2 * v1)
20
20
So, I want to know what the problem is and how to fix it.
Thanks!!
This method gives the desired output:
def __mul__(self, other):
if isinstance(other, self.__class__):
if len(self.vec) != len(other.vec):
raise AssertionError('Vectors have different lengths '
'of {} and {}'.format(len(self.vec), len(other.vec)))
return sum(x * y for x, y in zip(self.vec, other.vec))
elif isinstance(other, (int, float)):
return Vector([x * other for x in self.vec])
else:
raise AssertionError('Cannot use type ' + str(type(other)))

Categories