how can i add a matrix using the implemented methods?
my problem is that I don't know very much how I can get an operation to add the matrix correctly.
for example, such an operation:
A = 1 2 3 1 2 1
4 5 6 + 0 1 0
7 8 9 3 2 1
I would like to use the methods from the Matrix class:
class Matrix:
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 __add__(self, mat):
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
Updated to the below runs for me, even though there is room for improvement (checking matrix sizes,...)
def getitem(self, idx):
return self.rows[idx]
def setitem(self, idx, item):
self.rows[idx] = item
def add(self, mat):
ret = Matrix(self.m, self.n)
for x in range(self.m):
row = [sum(item) for item in zip(self.rows[x], mat.getitem(x))]
ret.setitem(x,row)
return ret
mat_a = Matrix(5,5)
mat_b = Matrix(5,5)
mat_b.setitem(slice(0,3),[[1,2,3,4,5],[4,5,6,7,8],[9,10,4,3,1]])
mat_c = mat_a.add(mat_b)
print(mat_c.getitem(slice(0,3)))
Related
I have a problem with matrix initialization, namely with the "bool" parameter, how can I e.g. initialize a matrix and add it?
class Matrix:
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 __add__(self, mat):
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
m1 = Matrix(3,5,**? bool type)**
You can either pass the third argument as such:
m1 = Matrix(3,5,False)
Or using named parameters:
m1 = Matrix(3,5,init = False)
Notice how in Python it's False with a capital F and not false like in some other languages.
maybe a bit trivial question but i'm having trouble calling the object.
How can I call an object from this class and possibly call the add method correctly?
sample code:
class MyMatrix:
height = 0
width = 0
data = tuple()
def __init__(self, data):
self.height = len(data)
self.width = len(data[0])
self.data = data
def add(mat1, mat2):
if mat1.height != mat2.height or mat1.width != mat2.width:
print("The matrices are not the same size!")
return
rows = []
for i in range(len(mat1.data)):
row = []
for j in range(len(mat1.data[0])):
row.append(mat1[i][j] + mat2[i][j])
rows.append(tuple(row))
return MyMatrix(tuple(rows))
Thank you in advance for every answer.
You can call the methods like follows; for your code to work, however, you need to implement getitem (so that you can do matrix[1][2] e.g.).
class MyMatrix:
height = 0
width = 0
data = tuple()
def __init__(self, data):
self.height = len(data)
self.width = len(data[0])
self.data = data
def __getitem__(self, item):
return self.data.__getitem__(item)
def add(mat1, mat2):
if mat1.height != mat2.height or mat1.width != mat2.width:
print("The matrices are not the same size!")
return
rows = []
for i in range(len(mat1.data)):
row = []
for j in range(len(mat1.data[0])):
row.append(mat1[i][j] + mat2[i][j])
rows.append(tuple(row))
return MyMatrix(tuple(rows))
m1 = MyMatrix([[1,2,3]])
m2 = MyMatrix([[3,2,1]])
m12 = m1.add(m2)
print(m12.data)
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
In Mathematica I can convert multivariable moments in cumulants and back using MomentConvert:
MomentConvert[Cumulant[{2, 2,1}], "Moment"] // TraditionalForm
as one can try in wolframcloud.
I would like to do exactly the same in python. Is there any library in python capable of this?
At least the one direction I now programmed by myself:
# from http://code.activestate.com/recipes/577211-generate-the-partitions-of-a-set-by-index/
from collections import defaultdict
class Partition:
def __init__(self, S):
self.data = list(S)
self.m = len(S)
self.table = self.rgf_table()
def __getitem__(self, i):
#generates set partitions by index
if i > len(self) - 1:
raise IndexError
L = self.unrank_rgf(i)
result = self.as_set_partition(L)
return result
def __len__(self):
return self.table[self.m,0]
def as_set_partition(self, L):
# Transform a restricted growth function into a partition
n = max(L[1:]+[1])
m = self.m
data = self.data
P = [[] for _ in range(n)]
for i in range(m):
P[L[i+1]-1].append(data[i])
return P
def rgf_table(self):
# Compute the table values
m = self.m
D = defaultdict(lambda:1)
for i in range(1,m+1):
for j in range(0,m-i+1):
D[i,j] = j * D[i-1,j] + D[i-1,j+1]
return D
def unrank_rgf(self, r):
# Unrank a restricted growth function
m = self.m
L = [1 for _ in range(m+1)]
j = 1
D = self.table
for i in range(2,m+1):
v = D[m-i,j]
cr = j*v
if cr <= r:
L[i] = j + 1
r -= cr
j += 1
else:
L[i] = r // v + 1
r %= v
return L
# S = set(range(4))
# P = Partition(S)
# for x in P:
# print (x)
# using https://en.wikipedia.org/wiki/Cumulant#Joint_cumulants
import math
def Cum2Mom(arr, state):
def E(op):
return qu.expect(op, state)
def Arr2str(arr,sep):
r = ''
for i,x in enumerate(arr):
r += str(x)
if i<len(arr)-1:
r += sep
return r
if isinstance( arr[0],str):
myprod = lambda x: Arr2str(x,'*')
mysum = lambda x: Arr2str(x,'+')
E=lambda x: 'E('+str(x)+')'
myfloat = str
else:
myfloat = lambda x: x
myprod = np.prod
mysum = sum
S = set(range(len(arr)))
P = Partition(S)
return mysum([
myprod([myfloat(math.factorial(len(pi)-1) * (-1)**(len(pi)-1))
,myprod([
E(myprod([
arr[i]
for i in B
]))
for B in pi])])
for pi in P])
print(Cum2Mom(['a','b','c','d'],1) )
import qutip as qu
print(Cum2Mom([qu.qeye(3) for i in range(3)],qu.qeye(3)) )
It's designed to work with qutip opjects and it also works with strings to verify the correct separation and prefactors.
Exponents of the variables can be represented by repeating the variable.
I have a graph that is very big about 1,000,000 nodes and many edges. This is what i wanted to know which is the best suited data structure when implementing an adjacency list. Here are the objects that i keep track of
Edge list
Node to node connection list
I am coding with python so I used a set(because according to this it has a o(1) average insertion time) for edge list and a dictionary to node to node connection list(by making it completely hashable according to How to make an object properly hashable?). Here is my code
class node:
def __init__(self, name = ""):
self.__name = name
def getName(self):
return self.__name
def __str__(self):
return self.__name
def __hash__(self):
return hash(self.__name)
def __lt__(self, other):
if(type(self) != type(other)):
return NotImplemented
return self.__name.__lt__(other.__name)
def __eq__(self, other):
if(type(self)) != type(other):
return NotImplemented
return self.__name == other.__name
class Edge:
def __init__(self, name = "", node1 = None, node2 = None, weight = 0):
self.__name = name
self.__firstNode = node1
self.__secondNode = node2
self.__weight = weight
def getName(self):
return self.__name
def getFirstNode(self):
return self.__firstNode
def getSecondNode(self):
return self.__secondNode
def getWeight(self):
return self.__weight
def __lt__(self, other):
if(type(self) != type(other)):
return NotImplemented
return self.__name.__lt__(other.__name) and self.__firstNode.__lt__(other.__firstNode) and self.__secondNode.__lt__(other.__secondNode) and self.__weight.__lt__(other.__weight)
def __eq__(self, other):
if(type(self) != type(other)):
return NotImplemented
return self.__name == other.__name and self.__firstNode == other.__firstNode and self.__secondNode == other.__secondNode and self.__weight == other.__weight
def __str__(self):
return self.__name + " " + str(self.__firstNode) + " " + str(self.__secondNode) + " " + str(self.__weight)
def __hash__(self):
return hash(hash(self.__name) + hash(self.__firstNode) + hash(self.__secondNode) + hash(self.__weight))
class graph:
def __init__(self):
self.__nodeToNode = {}
self.__edgeList = set()
def addEdge(self, edge):
if(type(edge) != type(Edge())):
return False
self.__edgeList.add(edge)
if(not edge.getFirstNode() in self.__nodeToNode):
self.__nodeToNode[edge.getFirstNode()] = set()
self.__nodeToNode[edge.getFirstNode()].add(edge.getSecondNode())
if(not edge.getSecondNode() in self.__nodeToNode):
self.__nodeToNode[edge.getSecondNode()] = set()
self.__nodeToNode[edge.getSecondNode()].add(edge.getSecondNode())
return True
def getNodes(self):
return dict(self.__nodeToNode)
def getEdges(self):
return set(self.__edgeList)
import string
import random
import time
grp = graph()
nodes = [None] * 20000
for i in range(20000):
st = ''.join(random.SystemRandom().choice(string.ascii_letters) for i in range(10))
node1 = node(st)
nodes[i] = node1
current = time.time()
for i in range(3000000):
rdm = random.randint(0, 199)
rdm2 = random.randint(0, 199)
st = ''.join(random.SystemRandom().choice(string.ascii_letters) for i in range(10))
eg = Edge(st, nodes[rdm], nodes[rdm2])
grp.addEdge(eg)
last = time.time()
print((last - current))
nodes = grp.getNodes()
edges = grp.getEdges()
but this code runs very slowly can i make it faster? If so by using what data structure?
Let me introduce you a way to create an adjacency list:
Suppose you have the input like this:
4 4
1 2
3 2
4 3
1 4
The first line contains 2 numbers V and E, the next E lines defines an edge between two vertices.
You can either create a .txt file and read the input or directly type in via sys.stdin.read():
input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(data[0:(2 * m):2], data[1:(2 * m):2]))
x, y = data[2 * m:]
adj = [[] for _ in range(n)]
x, y = x - 1, y - 1
for (a, b) in edges:
adj[a - 1].append(b - 1)
adj[b - 1].append(a - 1)
Let's output the adjacency list adj:
>>> print(adj)
[[1, 3], [0, 2], [1, 3], [2, 0]]
adj[0] have two adj nodes: 1 and 3. Meaning the node 1 have two adj nodes: 2 and 4.
And now, if you want a directed, weighted graph, you just need to modify the input like this:
4 4
1 2 3 # edge(1, 2) has the weight of 3
3 2 1
4 3 1
1 4 2
input = sys.stdin.read()
data = list(map(int, input.split()))
n, m = data[0:2]
data = data[2:]
edges = list(zip(zip(data[0:(3 * m):3], data[1:(3 * m):3]), data[2:(3 * m):3]))
data = data[3 * m:]
adj = [[] for _ in range(n)]
cost = [[] for _ in range(n)]
for ((a, b), w) in edges:
adj[a - 1].append(b - 1)
cost[a - 1].append(w)
You store the weight in cost, and for example, cost[0][1] = 3, cost[0][3] = 2.
Hope this helped!