How to reduce run time in my python code? - python

I am currently working on a project that requires me to run a complete python code base. For research purpose, I need to run the code as fast as possible. Yet I am fairly new to programming and have no idea how to reduce run time. So I hope someone can help me on that. Any advice would be appreciated. Here's part of my code base, which used a lot of nested for loops, so it might significantly increase run time.
def a_j(r, a, A): # the Claussius-Mossotti factor, determined by a symmetric (3 × 3) matrix such that (A_i)^T = A_i
alph = np.array([[0,0,0],[0,0,0],[0,0,0]],complex)
for i in range(3):
for j in range(3):
alph[i,j] = (r * a * A[i,j])
return alph
def W_ext(x, k, rho, alpha, A): # particle–particle interaction term
n = x.shape[0] # the number of x vextors
result = np.zeros([3*n,3*n],complex)
u = np.zeros((n, 3)) # u = x - x'
for i in range(n):
for j in range(n):
if i != j:
u[i] = x[i] - x[j]
block_result = a_j(rho[i], alpha, A) * G((u[i]), k) * a_j(rho[j], alpha, A)
for m in range(3):
for l in range(3):
result[3*i + m, 3*j + l] = block_result[m,l]
return result.imag
def A_ext(rho, a, A): # single-particle term
n = rho.shape[0]
result = np.zeros([3*n,3*n],complex)
for i in range(n):
for j in range(n):
if i == j:
block_result = a_j(rho[i], a, A).imag
for m in range(3):
for l in range(3):
result[3*i + m, 3*j + l] = block_result[m,l]
return result # (3 x 3) matrix
def P_ext(e, A, W, omega):
eT = np.matrix.getH(e)
mm1 = np.matmul(A, e)
mm2 = np.matmul(W, e)
extinction = (np.dot(eT, mm1) + np.dot(eT, mm2)) * (omega/2.0)
return extinction
#ABSORPTION
def W_abs(x, k, rho, alpha, A, chi): # particle–particle interaction term
n = x.shape[0]
result = np.zeros([3*n,3*n],complex)
u = np.zeros((n, 3))
for i in range(n):
for j in range(n):
if i != j:
u[i] = x[i] - x[j]
block_result = np.matrix.getH(a_j(rho[i], alpha, A)) * (1.0 / np.conjugate(chi)).imag * a_j(rho[i], alpha, A) * G((u[i]), k) * a_j(rho[j], alpha, A)
for m in range(3):
for l in range(3):
result[3*i + m, 3*j + l] = block_result[m,l]
return 2.0 * result.real # (3 x 3) matrix
def A_abs(rho, a, A, chi): # single-particle term
n = rho.shape[0]
result = np.zeros([3*n,3*n],complex)
for i in range(n):
for j in range(n):
if i == j:
block_result = np.matrix.getH(a_j(rho[i], a, A)) * (1.0 / np.conjugate(chi)).imag * a_j(rho[i], a, A)
for m in range(3):
for l in range(3):
result[3*i + m, 3*j + l] = block_result[m,l]
return result # (3 x 3) matrix

Related

Implementation of an algorithm for simultaneous diagonalization

I am trying to write an implementation of an algorithm for the simultaneous diagonalization of two matrices (which are assumed to be simultaneously diagonalizable). However, the algorithm does not seem to converge. The algorithm is described in SIAM J. Matrix Anal. Appl. 14, 927 (1993).
Here is the first part of my code to set up a test case:
import numpy as np
import numpy.linalg as lin
from scipy.optimize import minimize
N = 3
# Unitary example matrix
X = np.array([
[-0.54717736-0.43779416j, 0.26046313+0.11082439j, 0.56151027-0.33692186j],
[-0.33452046-0.37890784j, -0.40907097-0.70730291j, -0.15344477+0.23100467j],
[-0.31253864-0.39468687j, 0.05342909+0.49940543j, -0.70062586+0.05835082j]
])
# Generate eigenvalues
LA = np.diag(np.arange(0, N))
LB = np.diag(np.arange(N, 2*N))
# Generate simultaneously diagonalizable matrices
A = X # LA # np.conj(X).T
B = X # LB # np.conj(X).T
This should generate two 3x3 matrices which are simultaneously diagonalizable, since they are constructed this way via X. The following code block then defines a few helper functions:
def off2(A, B):
"""Defines the distance from the matrices from
their diagonal form.
"""
C = np.abs(A) ** 2 + np.abs(B) ** 2
diag_idx = np.diag_indices(N)
C[diag_idx] = 0
return np.sum(C)
def Rijcs(i, j, c, s):
"""Function R(i, j, c, s) from the paper, see
Eq. (1) therein. Used for plane rotations in
the plane ij.
"""
res = np.eye(N, dtype=complex)
res[i, i] = c
res[i, j] = -np.conj(s)
res[j, i] = s
res[j, j] = np.conj(c)
return res
def cs(theta, phi):
"""Parametrization for c and s."""
c = np.cos(theta)
s = np.exp(1j * phi) * np.sin(theta)
return c, s
With these definitions, the algorithm can be implemented:
tol = 1e-10
Q = np.eye(N, dtype=complex)
while True:
off = off2(A, B)
# Print statement for debugging purposes
print(off)
# Terminate if the result is converged
if off <= tol * (lin.norm(A, "fro") + lin.norm(B, "fro")):
break
for i in range(N):
for j in range(i + 1, N):
def fij(c, s):
aij = A[i, j]
aji = A[j, i]
aii = A[i, i]
ajj = A[j, j]
bij = B[i, j]
bji = B[j, i]
bii = B[i, i]
bjj = B[j, j]
x = np.array(
[
[np.conj(aij), np.conj(aii - ajj), -np.conj(aji)],
[aji, (aii - ajj), -aij ],
[np.conj(bij), np.conj(bii - bjj), -np.conj(bji)],
[bji, (bii - bjj), -bij ]
]
)
y = np.array(
[
[c ** 2],
[c * s],
[s ** 2]
]
)
return lin.norm(x # y, 2)
# 5
result = minimize(
lambda x: fij(*cs(x[0], x[1])),
x0=(0, 0),
bounds=(
(-0.25 * np.pi, 0.25 * np.pi),
(-np.pi, np.pi)
),
)
theta, phi = result['x']
c, s = cs(theta, phi)
# 6
R = Rijcs(i, j, c, s)
# 7
Q = Q # R
A = np.conj(R).T # A # R
B = np.conj(R).T # B # R
As you can observe from the print statement, the "distance" of A and B from diagonal form does not really converge. Instead, the values printed range from 0.5 up to 3 and oscillate up and down. Is there a bug in this code and if so, where exactly is it?

Vectorizing theano/aesara variable operations

I am trying to compute the function below with theano/aesara in an preferably vectorized manner:
![image|620x182](upload://9Px5wAGjZdkBXVBg4fqmuSPorPr.png)
The solution i have is not vectorized and therefore way too slow:
def apply_adstock_with_lag(x, L, P, D):
"""
params:
x: original array
L: length
P: peak, delay in effect
D: decay, retain
"""
x = np.append(np.zeros(L - 1), x)
weights = [0 for _ in range(L)]
for l in range(L):
weight = D ** ((l - P) ** 2)
weights[L - 1 - l] = weight
weights = np.array(weights)
adstocked_x = []
for i in range(L - 1, len(x)):
x_array = x[i - L + 1:i + 1]
xi = sum(x_array * weights) / sum(weights)
adstocked_x.append(xi)
adstocked_x = tt.as_tensor_variable(adstocked_x)
return adstocked_x
An similar function although simplier and its vectorized solution can be found below, note that this is much much quicker probably due to the vectorized operations:
![image|252x39](upload://ucZeqCmCXcBRAHLdA7lJ0crs1Oz.png)
def adstock_geometric_theano_pymc3(x, theta):
x = tt.as_tensor_variable(x)
def adstock_geometric_recurrence_theano(index, input_x, decay_x, theta):
return tt.set_subtensor(decay_x[index], tt.sum(input_x + theta * decay_x[index - 1]))
len_observed = x.shape[0]
x_decayed = tt.zeros_like(x)
x_decayed = tt.set_subtensor(x_decayed[0], x[0])
output, _ = theano.scan(
fn=adstock_geometric_recurrence_theano,
sequences=[tt.arange(1, len_observed), x[1:len_observed]],
outputs_info=x_decayed,
non_sequences=theta,
n_steps=len_observed - 1
)
return output[-1]
I cant come up with the vectorized solution to my adstock-function, can anyone give it a go?
Have you tried:
def apply_adstock_with_lag(x, L, P, D):
adstocked_x = np.convolve(x, D**((np.arange(0, L, 1) - P)**2))[:-(L-1)] / sum(D**((np.arange(0, L, 1) - P)**2))
adstocked_x = at.as_tensor_variable(adstocked_x)
return adstocked_x
This should work

Python: TypeError: 'int' object is not subscriptable Monte Carlo

I know this is a fairly common question but looking at other answers for this has not helped me as I do not understand the problem exactly. I get the actual error itself but this problem is only occurring in one of the editions of my code where this line is the same in both that is the issue.
Here is version one:
import numpy as np
import numpy.random as rnd
import matplotlib.pyplot as plt
#S[i, j] = 1 (spin up)
#S[i, j] = -1 (spin down)
def InitSpins(S, N):
for i in range(N):
for j in range(N):
S[i, j] = 2*rnd.randint(2)-1
return S
def GenerateMove(S, N):
i = rnd.randint(N)
j = rnd.randint(N)
return i, j, S[i][j], - S[i][j]
def ComputeEnergy(S, N):
E = 0.0
for i in range(N):
for j in range(N):
E += -J*S[i,j]*S[(i+1)%N,j] - J*S[i,j]*S[i,(j+1)%N] - H*S[i,j]
return E
def ComputeDiffEnergy(S, i, j, old, new, N):
Eold = ComputeEnergy(S, N)
S[i,j] = new
Enew = ComputeEnergy(S, N)
S[i,j] = old
return Enew - Eold
def MCStep(S, N, E, nacc, T):
i,j,old,new = GenerateMove(S, N)
DE = ComputeDiffEnergy(S, i, j, old, new, N)
if np.any(DE <= 0) or np.any(rnd.random() < np.exp(-DE/T)):
AcceptMove(S, i, j, old, new, N)
E += DE
nacc += 1
# elif
# AcceptMove(S, i, j, old, new, N)
# E += DE
# nacc += 1
else:
RejectMove(S, i, j, old, new, N)
return E, nacc
def AcceptMove(S, i, j, old, new, N):
S[i, j] = new
def RejectMove(S, i, j, old, new, N):
S[i, j] = old
def ComputeX(S, N):
X = 0.0
for i in range(N):
for j in range(N):
X += S[i,j]
X += 1/(N**2)*np.sum(X)
return X
N = 10 #dimension of lattice
NIter = 10000 #iterations for production run
NEquil = NIter//10 #iterations in actual calculation
NT = 100 #number of time steps
T = 2.4
H = 0.0 #set outside magnetisation
J = 1.0 #set internal magnetisation
S = np.empty([N, N]) #set initlal spin array
S = InitSpins(S, N)
print(S)
print('energy',ComputeEnergy(S, N))
# Equilibration:
nacc = 0
E = ComputeEnergy(S, N)
for i in range(NEquil):
E, nacc = MCStep(S, N, E, nacc, T)
# Production run
nacc = 0
sum_E = 0.0
sum_E2 = 0.0
E = ComputeEnergy(S, N)
for i in range(NIter):
E, nacc = MCStep(S, N, E, nacc, T)
sum_E += E
sum_E2 += E**2
X = ComputeX(S, N)
def SumX(X, N):
sum_X = 0.0
sum_X2 = 0.0
for i in range(NIter):
sum_X += X
sum_X2 += X**2
return sum_X, sum_X2
sum_X, sum_X2 = SumX(X, N)
# Calculate averages
av_E = sum_E/float(NIter)
av_E2 = sum_E2/float(NIter)
av_X = sum_X/float(NIter)
av_X2 = sum_X2/float(NIter)
CV = 1/(1*(T**2))*(av_E2-av_E**2)
chi = 1/1*(T**2)*(av_X2-av_X**2)
#M =
# print results
print("acceptance ratio",nacc/float(NIter))
print("average energy",av_E)
print("heat capacity",CV)
print("magnetic susceptibility", chi)
#print("magnetisation, )
This, though incomplete, gives me results.
Then I tried to make python run through a range of T (temperature) to give me a graph of the changing heat capacity. This breaks my GenerateMove function with the error given in the title for the return i,j, S[i][j], -S[i][j].
Updated code that doesn't work is:
import numpy as np
import numpy.random as rnd
import matplotlib.pyplot as plt
#S[i, j] = 1 (spin up)
#S[i, j] = -1 (spin down)
def InitSpins(S, N):
for i in range(N):
for j in range(N):
S[i, j] = 2*rnd.randint(2)-1
return S
def GenerateMove(S, N):
i = rnd.randint(N)
j = rnd.randint(N)
return i, j, S[i][j], - S[i][j]
def ComputeEnergy(S, N):
E = 0.0
for i in range(N):
for j in range(N):
E += -J*S[i,j]*S[(i+1)%N,j] - J*S[i,j]*S[i,(j+1)%N] - H*S[i,j]
return E
def ComputeDiffEnergy(S, i, j, old, new, N):
Eold = ComputeEnergy(S, N)
S[i,j] = new
Enew = ComputeEnergy(S, N)
S[i,j] = old
return Enew - Eold
def MCStep(S, N, E, nacc, T):
i,j,old,new = GenerateMove(S, N)
DE = ComputeDiffEnergy(S, i, j, old, new, N)
if np.any(DE <= 0) or np.any(rnd.random() < np.exp(-DE/T)):
AcceptMove(S, i, j, old, new, N)
E += DE
nacc += 1
# elif
# AcceptMove(S, i, j, old, new, N)
# E += DE
# nacc += 1
else:
RejectMove(S, i, j, old, new, N)
return E, nacc
def AcceptMove(S, i, j, old, new, N):
S[i, j] = new
def RejectMove(S, i, j, old, new, N):
S[i, j] = old
def ComputeX(S, N):
X = 0.0
for i in range(N):
for j in range(N):
X += S[i,j]
X += 1/(N**2)*np.sum(X)
return X
N = 10 #dimension of lattice
NIter = 10000 #iterations for production run
NEquil = NIter//10 #iterations in actual calculation
NT = 100 #number of time steps
T = np.linspace(0.1,5.0,NT) #set temperaure range
C = np.zeros(NT) #inital heat capacity
H = 0.0 #set outside magnetisation
J = 1.0 #set internal magnetisation
S = np.empty([N, N]) #set initlal spin array
S = InitSpins(S, N)
print(S)
print('energy',ComputeEnergy(S, N))
## Equilibration:
#nacc = 0
#E = ComputeEnergy(S, N)
#for i in range(NEquil):
# E, nacc = MCStep(S, N, E, nacc, T)
#
## Production run
#nacc = 0
#sum_E = 0.0
#sum_E2 = 0.0
#E = ComputeEnergy(S, N)
#for i in range(NIter):
# E, nacc = MCStep(S, N, E, nacc, T)
# sum_E += E
# sum_E2 += E**2
X = ComputeX(S, N)
def SumX(X, N):
sum_X = 0.0
sum_X2 = 0.0
for i in range(NIter):
sum_X += X
sum_X2 += X**2
return sum_X, sum_X2
sum_X, sum_X2 = SumX(X, N)
for t in range(NT):
nacc = 0
sum_E = 0.0
sum_E2 = 0.0
S = InitSpins(S, N)
E = ComputeEnergy(S, N)
for i in range(NIter):
S = MCStep(S, N, E, nacc, T[t])
for i in range(NEquil):
S = MCStep(S, N, E, nacc, T[t])
E, nacc = MCStep(S, N, E, nacc, T)
sum_E += E
sum_E2 += E**2
av_E = sum_E/float(NIter)
av_E2 = sum_E2/float(NIter)
C[t] = (sum_E/(float(NIter*N*N)) - sum_E*sum_E/(NIter*NIter*N*N))/T[t]**2
# Calculate averages
av_X = sum_X/float(NIter)
av_X2 = sum_X2/float(NIter)
CV = 1/(1*(T**2))*(av_E2-av_E**2)
chi = 1/1*(T**2)*(av_X2-av_X**2)
#M =
# print results
print("acceptance ratio",nacc/float(NIter))
print("average energy",av_E)
print("heat capacity",CV)
print("magnetic susceptibility", chi)
#print("magnetisation, )
#plotting resultts
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(T, C)
plt.show()
EDIT: here is the full traceback
Traceback (most recent call last):
File "<ipython-input-3-52258536ecbb>", line 1, in <module>
runfile('F:/adv. numerical project graph.py', wdir='F:')
File "C:\Users\User\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 704, in runfile
execfile(filename, namespace)
File "C:\Users\User\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "F:/adv. numerical project graph.py", line 121, in <module>
S = MCStep(S, N, E, nacc, T[t])
File "F:/adv. numerical project graph.py", line 42, in MCStep
i,j,old,new = GenerateMove(S, N)
File "F:/adv. numerical project graph.py", line 24, in GenerateMove
return i, j, S[i][j], - S[i][j]
IndexError: tuple index out of range
You have unnecessarily complicated your code. The extension of your first code for a fixed temperature to a range of temperatures is quite straightforward. All you had to do was to club your code performing the lattice initialization, MC equilibration and MC production runs in a for loop running over the given temperature range. I have created lists to store the heat capacity, chi, and average energy at each temperature.
Below is how it's done. I am choosing 30 temperature values instead of 100 so as to quickly give you a working solution. I am only showing the relevant code. Rest of the code with function definitions stay the same.
I am not comfortable with the behavior of your MC predicted heat capacity. It is supposed to increase with temperature. You need to cross check your implementation. You have everything now.
NT = 30 # number of temperature steps
T_list = np.linspace(0.1, 5.0, NT) # set temperaure range
av_E_list, CV_list, chi_list = [], [], []
for T in T_list: # <--- Loop over different temperatures
print ("Performing MC for T = %.2f" %T)
S = np.empty([N, N]) #set initlal spin array
S = InitSpins(S, N)
# Equilibration:
nacc = 0
E = ComputeEnergy(S, N)
for i in range(NEquil):
E, nacc = MCStep(S, N, E, nacc, T)
# Production run
nacc = 0
sum_E = 0.0
sum_E2 = 0.0
E = ComputeEnergy(S, N)
for i in range(NIter):
E, nacc = MCStep(S, N, E, nacc, T)
sum_E += E
sum_E2 += E**2
X = ComputeX(S, N)
sum_X, sum_X2 = SumX(X, N)
# Calculate averages
av_E = sum_E/float(NIter)
av_E2 = sum_E2/float(NIter)
av_X = sum_X/float(NIter)
av_X2 = sum_X2/float(NIter)
CV = 1/(1*(T**2))*(av_E2-av_E**2)
chi = 1/1*(T**2)*(av_X2-av_X**2)
CV_list.append(CV)
chi_list.append(chi)
av_E_list.append(av_E)
# Plotting
plt.plot(T_list, CV_list, '-b*')

Calculate special correlation distance matrix faster

I would like to build a distance matrix using Pearson correlation distance.
I first tried the scipy.spatial.distance.pdist(df,'correlation') which is very fast for my 5000 rows * 20 features dataset.
Since I want to build a recommender, I wanted to slightly change the distance, only considering features which are distinct for NaN for both users. Indeed, scipy.spatial.distance.pdist(df,'correlation') output NaN when it meets any feature whose value is float('nan').
Here is my code, df being my 5000*20 pandas DataFrame
dist_mat = []
d = df.shape[1]
for i,row_i in enumerate(df.itertuples()):
for j,row_j in enumerate(df.itertuples()):
if i<j:
print(i,j)
ind = [False if (math.isnan(row_i[t+1]) or math.isnan(row_j[t+1])) else True for t in range(d)]
dist_mat.append(scipy.spatial.distance.correlation([row_i[t] for t in ind],[row_j[t] for t in ind]))
This code works but it is ashtoningly slow compared to the scipy.spatial.distance.pdist(df,'correlation') one. My question is: how can I improve my code so it runs a lot faster? Or where can I find a library which calculates correlation between two vectors which only take in consideration features which appears in both of them?
Thank you for your answers.
I think you need to do this with Cython, here is an example:
#cython: boundscheck=False, wraparound=False, cdivision=True
import numpy as np
cdef extern from "math.h":
bint isnan(double x)
double sqrt(double x)
def pair_correlation(double[:, ::1] x):
cdef double[:, ::] res = np.empty((x.shape[0], x.shape[0]))
cdef double u, v
cdef int i, j, k, count
cdef double du, dv, d, n, r
cdef double sum_u, sum_v, sum_u2, sum_v2, sum_uv
for i in range(x.shape[0]):
for j in range(i, x.shape[0]):
sum_u = sum_v = sum_u2 = sum_v2 = sum_uv = 0.0
count = 0
for k in range(x.shape[1]):
u = x[i, k]
v = x[j, k]
if u == u and v == v:
sum_u += u
sum_v += v
sum_u2 += u*u
sum_v2 += v*v
sum_uv += u*v
count += 1
if count == 0:
res[i, j] = res[j, i] = -9999
continue
um = sum_u / count
vm = sum_v / count
n = sum_uv - sum_u * vm - sum_v * um + um * vm * count
du = sqrt(sum_u2 - 2 * sum_u * um + um * um * count)
dv = sqrt(sum_v2 - 2 * sum_v * vm + vm * vm * count)
r = 1 - n / (du * dv)
res[i, j] = res[j, i] = r
return res.base
To check the output without NAN:
import numpy as np
from scipy.spatial.distance import pdist, squareform, correlation
x = np.random.rand(2000, 20)
np.allclose(pair_correlation(x), squareform(pdist(x, "correlation")))
To check the output with NAN:
x = np.random.rand(2000, 20)
x[x < 0.3] = np.nan
r = pair_correlation(x)
i, j = 200, 60 # change this
mask = ~(np.isnan(x[i]) | np.isnan(x[j]))
u = x[i, mask]
v = x[j, mask]
assert abs(correlation(u, v) - r[i, j]) < 1e-12

Modular matrix inversion with large number

I am trying to find a way for modular matrix inversion. I found the code here:
def generalizedEuclidianAlgorithm(a, b):
if b > a:
#print a, b
return generalizedEuclidianAlgorithm(b,a);
elif b == 0:
return (1, 0);
else:
#print a,b
(x, y) = generalizedEuclidianAlgorithm(b, a % b);
return (y, x - (a / b) * y)
def inversemodp(a, p):
a = a % p
if (a == 0):
print "a is 0 mod p"
return 0
(x,y) = generalizedEuclidianAlgorithm(p, a % p);
return y % p
def identitymatrix(n):
return [[long(x == y) for x in range(0, n)] for y in range(0, n)]
def inversematrix(matrix, q):
n = len(matrix)
A = np.matrix([[ matrix[j, i] for i in range(0,n)] for j in range(0, n)], dtype = long)
Ainv = np.matrix(identitymatrix(n), dtype = long)
for i in range(0, n):
factor = inversemodp(A[i,i], q)
A[i] = A[i] * factor % q
Ainv[i] = Ainv[i] * factor % q
for j in range(0, n):
if (i != j):
factor = A[j, i]
A[j] = (A[j] - factor * A[i]) % q
Ainv[j] = (Ainv[j] - factor * Ainv[i]) % q
# print A, Ainv
# print i, j, factor
return Ainv
When I test with small prime q and matrix elements, the result is correct. However, when I test with large prime q and matrix consisting of large elements (e.g, 1024 bits), it printed out the error:
A = np.matrix([[ matrix[j, i] for i in range(0,n)] for j in range(0, n)], dtype = long)
File "C:\Python27\lib\site-packages\numpy\matrixlib\defmatrix.py", line 257, in __new__
arr = N.array(data, dtype=dtype, copy=copy)
Is it because of dtype of np.matrix? If so, why "long" datatype cannot support this case?
Could you please show me how to solve the error. Thanks in advance
I have just figured out that np.array causes many problems. One solution is just to treat the matrix as 2-dimensional list. The following is my code
def generalizedEuclidianAlgorithm(a, b):
if b > a:
return generalizedEuclidianAlgorithm(b,a);
elif b == 0:
return (1, 0);
else:
(x, y) = generalizedEuclidianAlgorithm(b, a % b);
return (y, x - (a / b) * y)
def inversemodp(a, p):
a = a % p
if (a == 0):
print "a is 0 mod p"
return 0
(x,y) = generalizedEuclidianAlgorithm(p, a % p);
return y % p
def identitymatrix(n):
return [[long(x == y) for x in range(0, n)] for y in range(0, n)
def multiply_vector_scalar (vector, scalar, q):
kq = []
for i in range (0, len(vector)):
kq.append (vector[i] * scalar %q)
return kq
def minus_vector_scalar1(vector1, scalar, vector2, q):
kq = []
for i in range (0, len(vector1)):
kq.append ((vector1[i] - scalar * vector2[i]) %q)
return kq
def inversematrix1(matrix, q):
n = len(matrix)
A =[]
for j in range (0, n):
temp = []
for i in range (0, n):
temp.append (matrix[j][i])
A.append(temp)
Ainv = identitymatrix(n)
for i in range(0, n):
factor = inversemodp(A[i][i], q)
A[i] = multiply_vector_scalar(A[i],factor,q)
Ainv[i] = multiply_vector_scalar(Ainv[i],factor,q)
for j in range(0, n):
if (i != j):
factor = A[j][i]
A[j] = minus_vector_scalar1(A[j],factor,A[i],q)
Ainv[j] = minus_vector_scalar1(Ainv[j],factor,Ainv[i],q)
return Ainv

Categories