I am making a program that compares the elements A[i,j] with A[j,i], if it is true once that A[i,j] = A[j,i]= 1, the matrix will not be antisymmetric. In the comparison, the elements A[i,j] where i=j (diagonal of the matrix) should not be evaluated.
import numpy as np
A = np.array([[1,0,0],[0,0,0],[0,0,1]])
for i in range (0,2):
for j in range (0,2):
if A[i,j] ==1 and A[i,j] == A[j,i]:
print('A is not antisymmetric')
antisymmetric = False
break
I have tried to add the condition i != j to not evaluate the diagonal, but it has not worked
It looks like your original example had a typo, as you were checking for values of the matrix to be literally 1, which is not relevant to the matrix being antisymmetric?
You were after:
import numpy as np
def is_antisymmetric(a):
r, c = a.shape
if r != c:
return False
for i in range(r):
for j in range(c):
if a[i, j] != -a[j, i] and j != i:
return False
return True
print(is_antisymmetric(np.array(
[[1,0,-1], [0,0,0], [1,0,1]]
)))
Or, briefer:
def is_antisymmetric(a):
return (
(s := a.shape[0]) == a.shape[1] and
(all(a[i, j] == -a[j, i] or j == i for i in range(s) for j in range(s)))
)
Related
I am trying to convert this piece of code into a list comprehension:
a = np.random.rand(10) #input vector
n = len(a) # element count of input vector
b = np.random.rand(3) #coefficient vector
nb = len(b) #element count of coefficients
d = nb #decimation factor (could be any integer < len(a))
c = []
for i in range(0, n, d):
psum = 0
for j in range(nb):
if i + j < n:
psum += a[i + j]*b[j]
c.append(psum)
I've tried following suggestions from:
List comprehension with an accumulator
nested for loops to list comprehension with differents "if" conditions
For example:
from itertools import accumulate
c = [accumulate([a[i + j] * b[j] for j in range(nb) if i + j < n] ) for i in range(0, n, d)]
Later, when trying to get values from c (e.g. c[:index]):
TypeError: 'NoneType' object is not subscriptable
Or:
from functools import partial
def get_val(a, b, i, j, n):
if i + j < n:
return(a[i + j] * b[j])
else:
return(0)
c = [
list(map(partial(get_val, i=i, j=j, n=n), a, b))
for i in range(0, n, d)
for j in range(nb)
]
in get_val, return(a[i + j] * b[j])
IndexError: invalid index to scalar variable.
Or:
psum_pieces = [[a[i + j] * b[j] if i + j < n else 0 for j in range(nb)] for i in range(0, n, d)]
c = [sum(psum) for psum in psum_pieces]
As well as many other iterations of these approaches. Any guidance would be much appreciated.
You really don't need to be using a list comprehension here. With numpy, you can create a fast pipelined solution that does not run any loops directly in the interpreter.
First convert a into a 2D array shaped (n // d, nb). The missing elements (i.e., where i + j >= n in the loop) can be zero since that will make the corresponding increment to psum zero:
# pre-compute i+j as a 2D array
indices = np.arange(nb) + np.arange(0, n, d)[:, None]
# we only want valid locations
mask = indices < n
t = np.zeros(indices.shape)
t[mask] = a[indices[mask]]
Now you can compute c directly as
(t * b).sum(axis=1)
I suspect that if you benchmark this solution against anything written in vanilla python not compiled with numba, it will be much faster.
If I've understood correctly what you want is something like
res = [sum(a[i+j]*b[j] for j in range(nb) if i+j < n) for i in range(0,n,d)]
For each i, this will add to the resulting list the sum of the products a[i+j]*b[j] for j that varies from 0 to nb-1 when i+j < n
I'm trying to solve a dynamic programming problem, and I came up with a simple loop-based algorithm which fills in a 2D array based on a series of if statements like this:
s = # some string of size n
opt = numpy.zeros(shape=(n, n))
for j in range(0, n):
for i in range(j, -1, -1):
if j - i == 0:
opt[i, j] = 1
elif j - i == 1:
opt[i, j] = 2 if s[i] == s[j] else 1
elif s[i] == s[j] and opt[i + 1, j - 1] == (j - 1) - (i + 1) + 1:
opt[i, j] = 2 + opt[i + 1, j - 1]
else:
opt[i, j] = max(opt[i + 1, j], opt[i, j - 1], opt[i + 1, j - 1])
Unfortunately, this code is extremely slow for large values of N. I found that it is much better to use built in functions such as numpy.where and numpy.fill to fill in the values of the array as opposed to for loops, but I'm struggling to find any examples which explain how these functions (or other optimized numpy methods) can be made to work with a series of if statements, as my algorithm does. What would be an appropriate way to rewrite the above code with built-in numpy libraries to make it better optimized for Python?
I don't think that np.where and np.fill can solve your problem. np.where is used to return elements of a numpy array that satisfy a certain condition, but in your case, the condition is NOT on VALUES of the numpy array, but on the values from variables i and j.
For your particular question, I would recommend using Cython to optimize your code specially for larger values of N. Cython is basically an interface between Python and C. The beauty of Cython is that it allows you to keep your python syntax, but optimize it using C structures. It allows you to define types of variables in a C-like manner to speed up your computations. For example, defining i and j as integers using Cython will speed thing up quite considerably because the types of i and j are checked at every loop iteration.
Also, Cython will allow you to define classic, fast, 2D arrays using C. You can then use pointers for fast element access to this 2D array instead of using numpy arrays. In your case, opt will be that 2D array.
Your if statements and the left-hand sides of your assignment statements contain references to the array that you're modifying in the loop. This means that there will be no general way to translate your loop into array operations. So you're stuck with some kind of for loop.
If you instead had the simpler loop:
for j in range(0, n):
for i in range(j, -1, -1):
if j - i == 0:
opt[i, j] = 1
elif j - i == 1:
opt[i, j] = 2
elif s[i] == s[j]:
opt[i, j] = 3
else:
opt[i, j] = 4
you could construct boolean arrays (using some broadcasting) that represent your three conditions:
import numpy as np
# get arrays i and j that represent the row and column indices
i,j = np.ogrid[:n, :n]
# construct an array with the characters from s
sarr = np.fromiter(s, dtype='U1').reshape(1, -1)
cond1 = i==j # result will be a bool arr with True wherever row index equals column index
cond2 = j==i+1 # result will be a bool arr with True wherever col index equals (row index + 1)
cond3 = sarr==sarr.T # result will be a bool arr with True wherever s[i]==s[j]
You could then use numpy.select to construct your desired opt:
opt = np.select([cond1, cond2, cond3], [1, 2, 3], default=4)
For n=5 and s='abbca', this would yield:
array([[1, 2, 4, 4, 3],
[4, 1, 2, 4, 4],
[4, 3, 1, 2, 4],
[4, 4, 4, 1, 2],
[3, 4, 4, 4, 1]])
Here is a vectorized solution.
It creates diagonal views into the output array which allow us to do accumulation in diagonal direction.
Step-by-step explanation:
evaluate s[i] == s[j] in the diagonal view.
only keep those which are connected to the main or first sub- diagonal by a series of Trues in top right to bottom left direction
replace all Trues with 2s except the main diagonal which gets 1s instead; take the cumulative sum in bottom left to top right direction
finally, take the cumulative maximum in bottom up and left right direction
As it is not totally obvious this does the same as the loopy code I've tested on quite a few examples (using function stresstest below) and it seems correct. And is roughly 7x faster for moderately large strings (1-100 characters).
import numpy as np
def loopy(s):
n = len(s)
opt = np.zeros(shape=(n, n), dtype=int)
for j in range(0, n):
for i in range(j, -1, -1):
if j - i == 0:
opt[i, j] = 1
elif j - i == 1:
opt[i, j] = 2 if s[i] == s[j] else 1
elif s[i] == s[j] and opt[i + 1, j - 1] == (j - 1) - (i + 1) + 1:
opt[i, j] = 2 + opt[i + 1, j - 1]
else:
opt[i, j] = max(opt[i + 1, j], opt[i, j - 1], opt[i + 1, j - 1])
return opt
def vect(s):
n = len(s)
h = (n+1) // 2
s = np.array([s, s]).view('U1').ravel()
opt = np.zeros((n+2*h-1, n+2*h-1), int)
y, x = opt.strides
hh = np.lib.stride_tricks.as_strided(opt[h-1:, h-1:], (2, h, n), (x, x-y, x+y))
p, o, c = np.ogrid[:2, :h, :n]
hh[...] = 2 * np.logical_and.accumulate(s[c+o+p] == s[c-o], axis=1)
np.einsum('ii->i', opt)[...] = 1
hh[...] = hh.cumsum(axis=1)
opt = np.maximum.accumulate(opt[-h-1:None if h == 1 else h-2:-1, h-1:-h], axis=0)[::-1]
return np.maximum.accumulate(opt, axis=1)
def stresstest(n=100):
from string import ascii_lowercase
import random
from timeit import timeit
Tv, Tl = 0, 0
for i in range(n):
s = ''.join(random.choices(ascii_lowercase[:random.randint(2, 26)], k=random.randint(1, 100)))
print(s, end=' ')
assert np.all(vect(s) == loopy(s))
Tv += timeit(lambda: vect(s), number=10)
Tl += timeit(lambda: loopy(s), number=10)
print()
print(f"total time loopy {Tl}, vect {Tv}")
Demo:
>>> stresstest(20)
caccbbdbcfbfdcacebbecffacabeddcfdededeeafaebeaeedaaedaabebfacbdd fckjhrmupcqmihlohjog dffffgalbdbhkjigladhgdjaaagelddehahbbhejkibdgjhlkbcihiejdgidljfalfhlaglcgcih eacdebdcfcdcccaacfccefbccbced agglljlhfj mvwlkedblhvwbsmvtbjpqhgbaolnceqpgkhfivtbkwgbvujskkoklgforocj jljiqlidcdolcpmbfdqbdpjjjhbklcqmnmkfckkch ohsxiviwanuafkjocpexjmdiwlcmtcbagksodasdriieikvxphksedajwrbpee mcwdxsoghnuvxglhxcxxrezcdkahpijgujqqrqaideyhepfmrgxndhyifg omhppjaenjprnd roubpjfjbiafulerejpdniniuljqpouimsfukudndgtjggtbcjbchhfcdhrgf krutrwnttvqdemuwqwidvntpvptjqmekjctvbbetrvehsgxqfsjhoivdvwonvjd adiccabdbifigeigdfaieecceciaghadiaigibehdaichfibeaggcgdciahfegefigghgebhddciaei llobdegpmebejvotsr rtnsevatjvuowmquaulfmgiwsophuvlablslbwrpnhtekmpphsenarhrptgbjvlseeqstewjgfhopqwgmcbcihljeguv gcjlfihmfjbkdmimjknamfbahiccbhnceiahbnhghnlleimmieglgbfjbnmemdgddndhinncegnmgmfmgahhhjkg nhbnfhp cyjcygpaaeotcpwfhnumcfveq snyefmeuyjhcglyluezrx hcjhejhdaejchedbce
total time loopy 0.2523909523151815, vect 0.03500175685621798
This program tests if a matrix is an identity matrix or not.
I have pasted my code beneath, and would like to know ways in which I can optimize the efficiency of this code. Also I am new to python programming, are there some built in functions that can solve the purpose too?
def is_identity_matrix(test):
if (test == []):
return False
i = 0
while (i < len(test)):
if (len(test[i]) == len(test)):
j = 0
while(j < len(test[i])):
if (j != i):
if(test[i][j] != 0):
return False
else:
if(test[i][j] != 1):
return False
if(j == (len(test[i]) - 1)):
break
j += 1
if(i == (len(test) - 1)):
break
i += 1
else:
return False
if(i == j and i == (len(test) - 1)):
return True
# Test Cases:
matrix1 = [[1,0,0,0],
[0,1,0,0],
[0,0,1,0],
[0,0,0,1]]
print is_identity_matrix(matrix1)
#>>>True
matrix2 = [[1,0,0],
[0,1,0],
[0,0,0]]
print is_identity_matrix(matrix2)
#>>>False
matrix3 = [[2,0,0],
[0,2,0],
[0,0,2]]
print is_identity_matrix(matrix3)
#>>>False
matrix4 = [[1,0,0,0],
[0,1,1,0],
[0,0,0,1]]
print is_identity_matrix(matrix4)
#>>>False
matrix5 = [[1,0,0,0,0,0,0,0,0]]
print is_identity_matrix(matrix5)
#>>>False
matrix6 = [[1,0,0,0],
[0,1,0,2],
[0,0,1,0],
[0,0,0,1]]
print is_identity_matrix(matrix6)
#>>>False
def is_identity_matrix(listoflist):
return all(val == (x == y)
for y, row in enumerate(listoflist)
for x, val in enumerate(row))
(though, this does not check if the matrix is square, and it returns True for an empty list)
Explanation: Inside all we have a generator expression with nested loops where val loops over each value in the matrix. x == y evaluates to True on the diagonal and False elsewhere. In Python, True == 1 and False == 0, so you can compare val == (x == y). The parentheses are important:
val == x == y would be a chained comparison equivalent to val == x and x == y
I'd use numpy:
(np.array(matrix1) == np.identity(len(matrix1))).all()
Of course, it'd be better if you were storing matrix1 as a numpy array in the first place to avoid the conversion.
Multiply by the all ones vector and check that the result is the same
Check the size of your matrix, make sure it is n x n, then create an actual identity matrix using np.identity(n), then compare your matrix with the new one you created.
def is_identity_matrix(test):
if not test : return False
le = len(test[0])
for i,x in enumerate(test):
if len(x) == le:
if any(y!=1 if j==i else y!=0 for j,y in enumerate(x)):
return False
else:
return False
return True if len(test) == le else False
If speed is important you should probably look at Numpy, but in a situation where you can't use it or perhaps it isn't worth it to have the matrix as a Numpy array you could also use the following:
def is_identity(mat):
for i, row in enumerate(mat):
if any(row[:i]) or row[i]!=1 or any(row[i+1:]):
return False
return True
About 12x faster than the code of the currently accepted answer! For a matrix of 2000x2000 at least...
The above does not check the matrix dimensions, but you can easily add something like:
n = len(matrix)
if not all(len(row) == n for row in matrix):
return False
I'm about to write some code that computes the determinant of a square matrix (nxn), using the Laplace algorithm (Meaning recursive algorithm) as written Wikipedia's Laplace Expansion.
I already have the class Matrix, which includes init, setitem, getitem, repr and all the things I need to compute the determinant (including minor(i,j)).
So I've tried the code below:
def determinant(self,i=0) # i can be any of the matrix's rows
assert isinstance(self,Matrix)
n,m = self.dim() # Q.dim() returns the size of the matrix Q
assert n == m
if (n,m) == (1,1):
return self[0,0]
det = 0
for j in range(n):
det += ((-1)**(i+j))*(self[i,j])*((self.minor(i,j)).determinant())
return det
As expected, in every recursive call, self turns into an appropriate minor. But when coming back from the recursive call, it doesn't change back to it's original matrix.
This causes trouble when in the for loop (when the function arrives at (n,m)==(1,1), this one value of the matrix is returned, but in the for loop, self is still a 1x1 matrix - why?)
Are you sure that your minor returns the a new object and not a reference to your original matrix object? I used your exact determinant method and implemented a minor method for your class, and it works fine for me.
Below is a quick/dirty implementation of your matrix class, since I don't have your implementation. For brevity I have chosen to implement it for square matrices only, which in this case shouldn't matter as we are dealing with determinants. Pay attention to det method, that is the same as yours, and minor method (the rest of the methods are there to facilitate the implementation and testing):
class matrix:
def __init__(self, n):
self.data = [0.0 for i in range(n*n)]
self.dim = n
#classmethod
def rand(self, n):
import random
a = matrix(n)
for i in range(n):
for j in range(n):
a[i,j] = random.random()
return a
#classmethod
def eye(self, n):
a = matrix(n)
for i in range(n):
a[i,i] = 1.0
return a
def __repr__(self):
n = self.dim
for i in range(n):
print str(self.data[i*n: i*n+n])
return ''
def __getitem__(self,(i,j)):
assert i < self.dim and j < self.dim
return self.data[self.dim*i + j]
def __setitem__(self, (i, j), val):
assert i < self.dim and j < self.dim
self.data[self.dim*i + j] = float(val)
#
def minor(self, i,j):
n = self.dim
assert i < n and j < n
a = matrix(self.dim-1)
for k in range(n):
for l in range(n):
if k == i or l == j: continue
if k < i:
K = k
else:
K = k-1
if l < j:
L = l
else:
L = l-1
a[K,L] = self[k,l]
return a
def det(self, i=0):
n = self.dim
if n == 1:
return self[0,0]
d = 0
for j in range(n):
d += ((-1)**(i+j))*(self[i,j])*((self.minor(i,j)).det())
return d
def __mul__(self, v):
n = self.dim
a = matrix(n)
for i in range(n):
for j in range(n):
a[i,j] = v * self[i,j]
return a
__rmul__ = __mul__
Now for testing
import numpy as np
a = matrix(3)
# same matrix from the Wikipedia page
a[0,0] = 1
a[0,1] = 2
a[0,2] = 3
a[1,0] = 4
a[1,1] = 5
a[1,2] = 6
a[2,0] = 7
a[2,1] = 8
a[2,2] = 9
a.det() # returns 0.0
# trying with numpy the same matrix
A = np.array(a.data).reshape([3,3])
print np.linalg.det(A) # returns -9.51619735393e-16
The residual in case of numpy is because it calculates the determinant through (Gaussian) elimination method rather than the Laplace expansion. You can also compare the results on random matrices to see that the difference between your determinant function and numpy's doesn't grow beyond float precision:
import numpy as np
a = 10*matrix.rand(4)
A = np.array( a.data ).reshape([4,4])
print (np.linalg.det(A) - a.det())/a.det() # varies between zero and 1e-14
use Sarrus' Rule (non recursive method)
example on below link is in Javascript, but easily can be written in python
https://github.com/apanasara/Faster_nxn_Determinant
import numpy as np
def smaller_matrix(original_matrix,row, column):
for ii in range(len(original_matrix)):
new_matrix=np.delete(original_matrix,ii,0)
new_matrix=np.delete(new_matrix,column,1)
return new_matrix
def determinant(matrix):
"""Returns a determinant of a matrix by recursive method."""
(r,c) = matrix.shape
if r != c:
print("Error!Not a square matrix!")
return None
elif r==2:
simple_determinant = matrix[0][0]*matrix[1][1]-matrix[0][1]*matrix[1][0]
return simple_determinant
else:
answer=0
for j in range(r):
cofactor = (-1)**(0+j) * matrix[0][j] * determinant(smaller_matrix(matrix, 0, j))
answer+= cofactor
return answer
#test the function
#Only works for numpy.array input
np.random.seed(1)
matrix=np.random.rand(5,5)
determinant(matrix)
Here's the function in python 3.
Note: I used a one-dimensional list to house the matrix and the size array is the amount of rows or columns in the square array. It uses a recursive algorithm to find the determinant.
def solve(matrix,size):
c = []
d = 0
print_matrix(matrix,size)
if size == 0:
for i in range(len(matrix)):
d = d + matrix[i]
return d
elif len(matrix) == 4:
c = (matrix[0] * matrix[3]) - (matrix[1] * matrix[2])
print(c)
return c
else:
for j in range(size):
new_matrix = []
for i in range(size*size):
if i % size != j and i > = size:
new_matrix.append(matrix[i])
c.append(solve(new_matrix,size-1) * matrix[j] * ((-1)**(j+2)))
d = solve(c,0)
return d
i posted this code because i couldn't fine it on the internet, how to solve n*n determinant using only standard library.
the purpose is to share it with those who will find it useful.
i started by calculating the submatrix Ai related to a(0,i).
and i used recursive determinant to make it short.
def submatrix(M, c):
B = [[1] * len(M) for i in range(len(M))]
for l in range(len(M)):
for k in range(len(M)):
B[l][k] = M[l][k]
B.pop(0)
for i in range(len(B)):
B[i].pop(c)
return B
def det(M):
X = 0
if len(M) != len(M[0]):
print('matrice non carrée')
else:
if len(M) <= 2:
return M[0][0] * M[1][1] - M[0][1] * M[1][0]
else:
for i in range(len(M)):
X = X + ((-1) ** (i)) * M[0][i] * det(submatrix(M, i))
return X
sorry for not commenting before guys :)
if you need any further explanation don't hesitate to ask .
Hello (excuse my English), I have a big doubt in python with matrix multiplication, I create a list of lists and multiplied by a scaling matrix, this is what I've done and I can not alparecer perform a multiplication operation problem with indexes, I check with paper and pencil and it works, I'm doing something bad to accommodate indexes or am I wrong accommodating matrices from the beginning?
def main():
if len(sys.argv) > 1:
v = int(sys.argv[1])
else:
print "error python exe:"
print "\tpython <programa.py> <num_vertices>"
A = []
for i in range(v):
A.append([0]*2)
for i in range(v):
for j in range(2):
A[i][j] = input("v: ")
print A
Escala(A)
def Escala(A):
print "Escala"
sx = input("Sx: ")
sy = input("Sy: ")
S = [(sx,0),(0,sy)]
print S
M = mult(S,A)
print M
def mult(m1,m2):
M = zero(len(m1),len(m2[0]))
for i in range(len(m2)):
for j in range(len(m2[0])):
for k in range(len(m1)):
M[i][j] += m1[k][j]*m2[k][j]
print M
return M
def zero(m,n):
# Create zero matrix
new_matrix = [[0 for row in range(n)] for col in range(m)]
return new_matrix
This seems wrong to me:
M[i][j] += m1[k][j]*m2[k][j]
shouldn't it be:
M[i][j] += m1[i][k]*m2[k][j]