python : simulate an array with different length - python

See the code. I am trying to simulate an array called 'xx'. Following the code, I am simulating each component in the matrix one by one. This is super time-consuming when M and N are very large. The reason why I do this is because in the function 'func', for each column data, the 'samplesize 'is different. Is there any faster way to generate this numpy array please? Thank you.
import numpy as np
def func ( x , n):
samplesize = np.random.poisson(x)
return np.random.uniform(0, 2, samplesize)
def singlerow(x, n ,N):
rowdata = np.zeros(N)
rowdata[0] = 0
for i in range(1, N):
rowdata[i] = rowdata[i-1] + np.sum(func(x, n))
return rowdata
def simulatematrix( x,n ,M, N):
result = np.zeros((M,N))
for m in range(M):
result[m] = singlerow(x,n, N)
return result
M = 100
N = 10
xx = simulatematrix(40, 10, M, N)

Related

Array won't update with new values in while-loop

I am having a problem updating my x0x1 array with the new values in my while loop. When I print my array out to check each generation iteration, its printing out the same values each time (despite me getting different z vector values). Not sure why.
I am getting the z-values for each iteration in my for loop, but for some reason, my newly generated x0x1 arrays each generation of the while loop are not being updated.
import numpy as np
import numpy.random
def calculateFunctionValueMatrix(x0x1, N):
functionValueArray = np.zeros((N-1, 1))
for i in range(0, N-1):
functionValueArray[i] = calculateFunctionValue(x0x1[i])
return functionValueArray
def calculateFunctionValue(x):
function = (x[0]-1)**2 + 5*((x[1]-x[0]**2)**2)
return function
def x0x1Array(N):
x0x1 = np.random.uniform(-2, 2, size = (N-1,2))
generateCandidateVector(x0x1)
def generateCandidateVector(x0x1):
print(x0x1)
K = 10
F= 0.8
N = 10
generation = 1
while generation <= K:
for i in range(0, N-1):
x0_ind, x1_ind, x2_ind = np.random.choice(len(x0x1), 3)
x0 = x0x1[x0_ind]
x1 = x0x1[x1_ind]
x2 = x0x1[x2_ind]
vectorZ = x0 + F*(x1-x2)
print("this is vector", vectorZ)
if(calculateFunctionValue(vectorZ) < calculateFunctionValue(x0x1[i])):
vectorZ = x0x1[i]
elif(calculateFunctionValue(vectorZ) > calculateFunctionValue(x0x1[i])):
x0x1[i] = x0x1[i]
print(x0x1)
if(np.std(calculateFunctionValueMatrix(x0x1, N)) < 0.01):
print("Optimal Solution Found")
generation = generation + 1
def main():
N=50
x0x1Array(N)
main()

Gauss seidel Implementation in python

import numpy as np
from scipy.linalg import solve_triangular as triSolve
#O(n) per iteration, so overall O(nN), good for large SPD/SDD matrices
def GS_iter(A, b, N):
m = len(A)
L = np.tril(A)
P = L-A
print(P)
x = np.zeros(m)
print(x)
for k in range(N):
x = triSolve(L,b+P#x, True)
return x
#examples
A = np.array([[10,2,3,1],[1,10,0,1],[0.2,1,10,2],[0.1,3,3,10]])
b = np.array([1,2,1,0])
x = GS_iter(A,b,50000)
ans = A#x-b
print(ans)
print(np.linalg.norm(ans))
Above is my Gauss-Seidel method in Python. For some reason it is not converging even after 50000 iterations to the solution even when the matrix A is strict diagonal dominant. Below is the same implementation in MATLAB which works:
function x = gSeidel(A,B,N)
[n,~] = size(A);
L = tril(A);
P = L-A; %P = -U
x = zeros(n,1); %x_0
for k = 1:N
x = L\(B+P*x);
end
end
What mistakes did I make? I think it is in TriSolve method since if I replaced it with regular LU solver such as (np.linalg.solve) it works. Why doesn't triangular solve behave as intended here?
the lower argument is the fourth
replace your line by x = triSolve(L,b+P#x, lower=True)
Signature:
triSolve(
a,
b,
trans=0,
lower=False,
unit_diagonal=False,
overwrite_b=False,
debug=None,
check_finite=True,
)

Compute commutation matrix in numpy/scipy efficiently

I am trying to compute the commutation matrix in python for a large dataset. I wrote the following code but found it performs terribly (and runs into memory errors for examples of around 500 by 500). In my code a and b are equivilent to the m and n notation in the linked wikipedia page. Can anyone provide a quicker and more memory efficient alternative to my current attempt?
def vec(matrix):
#Return vectorised matrix
return(matrix.transpose().reshape(matrix.shape[0]*matrix.shape[1],1))
def commutation(a, b):
# Example matrix with unique elements
m = np.arange(a*b).reshape(a,b)
# Vec(m)
vecm = vec(m)
vecm = vecm.reshape(vecm.shape[0])
# Get row inds
rowInds = np.arange(a*b)
# Get column inds
colInds = np.argsort(vecm)
colInds = colInds.reshape(colInds.shape[0])
# Work out mapping between them.
K = scipy.sparse.csr_matrix((np.ones(a*b),(rowInds,colInds)))
return(K)
Below is an improved version of your code:
import numpy as np
from scipy.sparse import csr_matrix
def vec(A):
m, n = A.shape[0], A.shape[1]
return A.reshape(m*n, order='F')
def commutation_matrix_sp(A):
m, n = A.shape[0], A.shape[1]
row = np.arange(m*n)
col = row.reshape((m, n), order='F').ravel()
data = np.ones(m*n, dtype=np.int8)
K = csr_matrix((data, (row, col)), shape=(m*n, m*n))
return K
Test:
A = np.random.rand(500, 500)
K = commutation_matrix_sp(A)
print(f'{K.data.nbytes/2**20:.2f} MB')
# 0.24 MB
print(np.all(K # vec(A) == vec(A.T)))
# True

Setting numpy array values to be more precise

I have an array which has values, if calcualted precisely: [3.056565 3.924560] however in python it prints rounded numbers and the array is [3.06, 3.93]. The array is the used to calculate something else and the result is different than expected. How can I make that array to stop rounding itself?
Here is the code where you can see that array is not precisely calcualted:
import datetime
import math
import numpy as np
def numGradient(f, x, h):
n = len(x)
g = [0]*n
g = np.array(g)
for i in range(n):
e = [0]*n
e[i] = 1
e=np.array(e)
g[i] = (f(x+e*h)-f(x-e*h))//(2*h)
return(g)
def myFun(x) :
return ( 0.6 + ((math.sin(x[0]**2-x[1]**2))**2-0.5)/((1+0.001*(x[0]**2+x[1]**2))**2) )
x_old=(3,4)
xthis = x_old - 0.01*numGradient(myFun, x_old, 10**(-6))
print(xthis)
There are several issues with your code. It probably does not compute what you expect it to compute.
First, this is the wrong way to initialize a NumPy array
g = [0]*n
g = np.array(g)
Replace it with
g = np.zeros(n)
Second, do the same with e.
for i in range(n):
e = np.zeros(n)
e[i] = 1
And most importantly replace
g[i] = (f(x+e*h)-f(x-e*h))//(2*h)
with
g[i] = (f(x+e*h)-f(x-e*h))/(2*h)
This is floating point division after all. And // is the so-called integer division in Python 3.
After the changes you will get
[ 3.056565 3.92456 ]
Which is probably what you should be getting.
Here is the complete code after the changes:
import datetime
import math
import numpy as np
def numGradient(f, x, h):
n = len(x)
g = np.zeros(n)
for i in range(n):
e = np.zeros(n)
e[i] = 1
g[i] = (f(x+e*h)-f(x-e*h))/(2*h)
return(g)
def myFun(x) :
return ( 0.6 +
((math.sin(x[0]**2-x[1]**2))**2-0.5)/((1+0.001*(x[0]**2+x[1]**2))**2) )
x_old=(3,4)
np.set_printoptions(precision=6)
xthis = x_old - 0.01*numGradient(myFun, x_old, 10**(-6))
print(xthis)

How do I vectorized these two numpy operations without using for loop?

there is an operation in numpy I've found hard to implement without looping
That operation is that I have two inputs: beta,x
beta.shape = (M,N,K) and x.shape = (I,K)
The operation I'm interested in can be done using for loop as follows
result = np.zeros((M,N,I,K)) # buffer to save my operation results
for m in range(M):
for n in range(N):
beta_ = beta[m][n] # has shape (K,)
result[m][n] = x * beta_
Let tricks here that I can do without loops so that the whole operation can be computational efficient ?
You're interested in multiplying the elements across the common K dimension, and keeping the results along the remaining dimensions.
This means you can use np.einsum using the dimensions of beta, x, and the shape result you're interested in like 'mnk,ik->mnik':
import numpy as np
M = 4
N = 3
I = 7
K = 6
beta = np.arange(M*N*K).reshape(M,N,K)
x = np.arange(I*K).reshape(I,K)
result1 = np.zeros((M,N,I,K)) # buffer to save my operation results
for m in range(M):
for n in range(N):
beta_ = beta[m][n] # has shape (K,)
result1[m][n] = x * beta_
result2 = np.einsum('mnk,ik->mnik', beta, x)
print (np.array_equal(result1,result2))
True
Not part of the question but while talking about np.einsum... If you want to sum across any of these dimensions, you can omit it from the end dimensions:
import numpy as np
M = 4
N = 3
I = 7
K = 6
beta = np.arange(M*N*K).reshape(M,N,K)
x = np.arange(I*K).reshape(I,K)
result1 = np.zeros((M,N,I,K)) # buffer to save my operation results
for m in range(M):
for n in range(N):
beta_ = beta[m][n] # has shape (K,)
result1[m][n] = x * beta_
result1 = result1.sum(axis=1)
result2 = np.einsum('mnk,ik->mik', beta, x)
print (np.array_equal(result1,result2))
True

Categories