def hadamard(A, B): """Calculate the Hadamard product of two matrices.""" if not all(isinstance(M, IntegerMatrix) for M in (A, B)): raise TypeError("can only Hadamard two matrices") if type(A) is not type(B): raise TypeError("matrices must be the same type") if A.m != B.m or A.n != B.n: raise exc.ComformabilityError( "matrices must have the same dimensions") data = [[A[i, j] * B[i, j] for j in range(A.n)] for i in range(A.m)] return A.__class__(A.m, B.m, data)
def __mul__(self, obj): """Multiply this matrix by a valid object and return the result. Doesn't modify the current matrix. Valid objects include other matrices vectors, and numeric scalars. In the case where the other object is a matrix, multiplication occurs with the current matrix on the left-hand side. """ if isinstance(obj, Matrix): if self.n != obj.m: raise exc.ComformabilityError( "inner matrix dimensions must match") if type(self) is not type(obj): raise TypeError("matrices must be the same type") data = [[ sum([self[i, k] * obj[k, j] for k in range(self.n)]) for j in range(obj.n) ] for i in range(self.m)] return self.__class__(self.m, obj.n, data) elif isinstance(obj, vec.Vector): raise NotImplementedError("vector type system not implemented") if self.n != obj.m: raise exc.ComformabilityError( "number of matrix columns much match vector length") data = [ sum([self[i, k] * obj[k] for k in range(self.n)]) for i in range(self.m) ] return vec.Vector(self.m, data) elif Matrix.is_numeric(obj): self._validate_scalar(obj) data = [[self[i, j] * obj for j in range(self.n)] for i in range(self.m)] return self.__class__(self.m, self.n, data) else: raise TypeError("cannot add object of type " + type(obj).__name__ + " to matrix")
def elem_equal(self, obj): """Element-wise equality.""" if type(obj) == self.__class__: if self.m != obj.m or self.n != obj.n: raise exc.ComformabilityError( "matrices must have the same dimensions") if type(self) is not type(obj): raise TypeError("matrices must be the same type") data = [[self[i, j] == obj[i, j] for j in range(self.n)] for i in range(self.m)] elif type(obj) == self._type: data = [[self[i, j] == obj for j in range(self.n)] for i in range(self.m)] else: raise TypeError("cannot add object of type " + type(obj).__name__ + " to matrix") return BooleanMatrix(self.m, self.n, data)
def __neq__(self, obj): """Elementwise equality.""" if isinstance(obj, Matrix): if self.m != obj.m or self.n != obj.n: raise exc.ComformabilityError( "matrices must have the same dimensions") if type(self) is not type(obj): raise TypeError("matrices must be the same type") data = [[self[i, j] != obj[i, j] for j in range(self.n)] for i in range(self.m)] elif Matrix.is_numeric(obj): self._validate_scalar(obj) data = [[self[i, j] != obj for j in range(self.n)] for i in range(self.m)] else: raise TypeError("cannot add object of type " + type(obj).__name__ + " to matrix") return BooleanMatrix(self.m, self.n, data)
def _boolean_operation(self, obj, op): """Perform a generic Boolean operation.""" if isinstance(obj, Matrix): if self.m != obj.m or self.n != obj.n: raise exc.ComformabilityError( "matrices must have the same dimensions") if not isinstance(obj, BooleanMatrix): raise TypeError("operation only exists for Boolean matrices") data = [[op(self[i, j], obj[i, j]) for j in range(self.n)] for i in range(self.m)] elif isinstance(obj, bool): data = [[op(self[i, j], obj) for j in range(self.n)] for i in range(self.m)] else: raise TypeError( "operation can't be performed with object of type " + type(obj).__name__) return self.__class__(self.m, self.n, data)
def __sub__(self, obj): """Subtract a valid object from this matrix and return the result. Doesn't modify the current matrix. Valid objects include other matrices and numeric scalars """ if isinstance(obj, Matrix): if self.m != obj.m or self.n != obj.n: raise exc.ComformabilityError( "matrices must have the same dimensions") if type(self) is not type(obj): raise TypeError("matrices must be the same type") data = [[self[i, j] - obj[i, j] for j in range(self.n)] for i in range(self.m)] elif Matrix.is_numeric(obj): self._validate_scalar(obj) data = [[self[i, j] - obj for j in range(self.n)] for i in range(self.m)] else: raise TypeError("cannot subtract object of type " + type(obj).__name__ + " to matrix") return self.__class__(self.m, self.n, data)