Python Scipy Error - python

import scipy.sparse.linalg as scial
import scipy.sparse as scisp
import numpy
def buildB(A,x,col_size_A):
d = numpy.zeros(col_size_A)
for index in xrange(col_size_A):
d[index] = 2*x[index]-1
tmp = scisp.spdiags(d,0,col_size_A,col_size_A)
return scisp.bmat([[A],[tmp]])
def buildQ(l,row_size_A):
q = numpy.zeros(row_size_A)
for index in xrange(row_size_A):
q[index] = 2*l[index]
return scisp.spdiags(q,0,row_size_A,row_size_A)
def buildh(A,x,b,col_size_A):
p = A.dot(x)
p = numpy.subtract(p, b)
quad = numpy.zeros(col_size_A)
for index in xrange(col_size_A):
quad[index] = x[index]*x[index]-x[index]
return numpy.concatenate((p, quad))
def ini():
A = numpy.array([[1,1],[1,-1]])
b = [1, 0]
c = [1, 1]
col_size_A = 2
row_size_A = 2
main(A,b,c,col_size_A,row_size_A)
def main(A,b,c, col_size_A, row_size_A):
x = numpy.zeros(col_size_A)
l = numpy.zeros(row_size_A*2)
eps = 10e-6
k = 0
while True:
B = buildB(A,x,col_size_A)
Q = buildQ(l[row_size_A/2:row_size_A+1], col_size_A)
Bt = B.transpose()
h = buildh(A,x,b,col_size_A)
g = numpy.add(c,Bt.dot(l))
F = numpy.concatenate((g, h))
print "Iteration " + str(k),
tol = numpy.amax(F)
print "- Tol "+ str(tol)
if tol < eps:
print "Done"
break
tF = -numpy.concatenate((c, h))
FGrad2 = scisp.csc_matrix(scisp.bmat([[Q,Bt],[B, None]]))
print FGrad2
print FGrad2.todense()
print " "
print tF
xdelta = scial.spsolve(FGrad2,tF)
print xdelta
x = x + xdelta[0:col_size_A]
l = x[col_size_A:]
k = k + 1
if __name__ == "__main__":
ini()
The output is:
(2, 0) 1.0
(3, 0) 1.0
(4, 0) -1.0
(2, 1) 1.0
(3, 1) -1.0
(5, 1) -1.0
(0, 2) 1.0
(1, 2) 1.0
(0, 3) 1.0
(1, 3) -1.0
(0, 4) -1.0
(1, 5) -1.0
[[ 0. 0. 1. 1. -1. 0.]
[ 0. 0. 1. -1. 0. -1.]
[ 1. 1. 0. 0. 0. 0.]
[ 1. -1. 0. 0. 0. 0.]
[-1. 0. 0. 0. 0. 0.]
[ 0. -1. 0. 0. 0. 0.]]
lda must be >= MAX(N,1): lda=2 N=3BLAS error: Parameter number 7 passed to cblas_dtrsv had an invalid value
[-1. -1. 1. -0. -0. -0.]
So FGrad2 seems to be a valid csc matrix and tF a valid numpy.array.
What is wrong with this code? I don't even know why the error is before the print of tF even so the error is behind at spsolve
Edit
Ok i fixed that, it is because the first guess for the parameters was wrong leading to a singular matrix, but suppling a valid guess for l, leads to wrong calculation of spsolve
as mentioned i labeled all output as you can see spsolve returns the wrong calculation.
$FGrad2 * xdelta != tF$
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import scipy.sparse.linalg as scial
import scipy.sparse as scisp
import numpy
def buildB(A,x,col_size_A):
d = numpy.zeros(col_size_A)
for index in xrange(col_size_A):
d[index] = 2*x[index]-1
tmp = scisp.spdiags(d,0,col_size_A,col_size_A)
return scisp.bmat([[A],[tmp]])
def buildQ(l,row_size_A):
q = numpy.zeros(row_size_A)
for index in xrange(row_size_A):
q[index] = 2*l[index]
return scisp.spdiags(q,0,row_size_A,row_size_A)
def buildh(A,x,b,col_size_A):
p = A.dot(x)
p = numpy.subtract(p, b)
quad = numpy.zeros(col_size_A)
for index in xrange(col_size_A):
quad[index] = x[index]*x[index]-x[index]
return numpy.concatenate((p, quad))
def ini():
A = numpy.array([[1,1],[1,0]])
b = [1, 0]
c = [1, 1]
col_size_A = 2
row_size_A = 2
main(A,b,c,col_size_A,row_size_A)
def main(A,b,c, col_size_A, row_size_A):
x = numpy.zeros(col_size_A)
x[0] = 0
x[1] = 1
l = numpy.ones(row_size_A*2)
eps = 10e-6
k = 0
while True:
B = buildB(A,x,col_size_A)
Q = buildQ(l[row_size_A:], col_size_A)
Bt = B.transpose()
h = buildh(A,x,b,col_size_A)
g = numpy.add(c,Bt.dot(l))
F = numpy.concatenate((g, h))
print "Iteration " + str(k),
tol = numpy.amax(numpy.absolute(F))
print "- Tol "+ str(tol)
if tol < eps:
print "Done"
print x
break
tF = -numpy.concatenate((c, h))
FGrad2 = scisp.csc_matrix(scisp.bmat([[Q,Bt],[B, None]]))
print "FGrad2"
print FGrad2.todense()
print "tF"
print tF
xdelta = scial.spsolve(FGrad2,tF)
print "spsolution"
print xdelta
print ""
x = x + xdelta[0:col_size_A]
l = xdelta[col_size_A:]
k = k + 1
if __name__ == "__main__":
ini()
Output:
Iteration 0 - Tol 3.0
FGrad2
[[ 2. 0. 1. 1. -1. 0.]
[ 0. 2. 1. 0. 0. 1.]
[ 1. 1. 0. 0. 0. 0.]
[ 1. 0. 0. 0. 0. 0.]
[-1. 0. 0. 0. 0. 0.]
[ 0. 1. 0. 0. 0. 0.]]
tF
[-1. -1. -0. -0. -0. -0.]
spsolution
[-1. -1. -0. -0. -0. -0.]

I think this is failing for you because your matrix is singular. E.g. convert to dense and use the regular numpy.linalg.solve:
>>> xdelta = numpy.linalg.solve(FGrad2.todense(), tF)
...
raise LinAlgError('Singular matrix')
numpy.linalg.linalg.LinAlgError: Singular matrix

The error I get is:
File "stack27538259.py", line 62, in main
xdelta = scial.spsolve(FGrad2,tF)
File "/usr/lib/python2.7/dist-packages/scipy/sparse/linalg/dsolve/linsolve.py", line 143, in spsolve
b, flag, options=options)
RuntimeError: superlu failure (singular matrix?) at line 100 in file scipy/sparse/linalg/dsolve/SuperLU/SRC/dsnode_bmod.c
As xnx wrote, FGrad2 is singular.
np.linalg.det(FGrad2.todense()) # 0.0
(scipy version 0.14.0)
after the change I get:
/usr/lib/python2.7/dist-packages/scipy/sparse/linalg/dsolve/linsolve.py:145: MatrixRankWarning: Matrix is exactly singular
and
spsolution
[ nan nan nan nan nan nan]
and an infinite loop unless I add k counter and break.

Documentation for cblas_dtrsv may be found (here)
Accordingly,
the routine solves a triangular system A*X = B (presumably)
lda is the leading dimension of matrix B
N is the order of the matrix A
the error message says lda = 2 and N = 3 but lda must be >= MAX(N,1)
Perhaps this helps track down the problem.

Related

Rank issue with spdiags in Python

I am currently trying to create a sparse matrix that will look like this.
[[ 50. -25. 0. 0.]
[-25. 50. -25. 0.]
[ 0. -25. 50. -25.]
[ 0. 0. -25. 50.]]
But when I run it through I keep getting the value error
'data array must have rank 2' in my data array.
I am positive it is a problem with my B variable. I have tried several things but nothing is working. Any advice?
def sparse(a,b,N):
h = (b-a)/(N+1)
e = np.ones([N,1])/h**2
B = np.array([e, -2*e, e])
diags = np.array([-1,0,1])
A = spdiags(B,diags,N,N).toarray()
return A
print(sparse(0,1,4))
Just change to this:
import numpy as np
from scipy.sparse import spdiags
def sparse(a, b, N):
h = (b - a) / (N + 1)
e = np.ones(N) / h ** 2
diags = np.array([-1, 0, 1])
A = spdiags([-1 * e, 2 * e, -1 * e], diags, N, N).toarray()
return A
print(sparse(0, 1, 4))
Output
[[-50. 25. 0. 0.]
[ 25. -50. 25. 0.]
[ 0. 25. -50. 25.]
[ 0. 0. 25. -50.]]
The main change is this:
e = np.ones([N,1])/h**2
by
e = np.ones(N) / h ** 2
Note that toarray transforms the sparse matrix into a dense one, from the documentation:
Return a dense ndarray representation of this matrix.

python - how to get the data/ calculated matrix before saving to be an image?

I have the following code
from PIL import Image
from pylab import *
from numpy import NaN
import numpy as np
import matplotlib.pyplot as plt
def julia(C):
X = arange(-1.5, 1.5, 0.005)
Y = arange(-1.5, 1.5, 0.005)
M = zeros((len(Y), len(X)))
plt.axis('off')
for x_iter, x in enumerate(X):
for y_iter, y in enumerate(Y):
z = x + 1j * y
pixel = NaN
for n in range(1, 4096):
z = z**2 + C
if abs(z) > 2:
pixel = n
break
M[y_iter, x_iter] = pixel
# (Please help! right here I want to print the intensity matrix elements out to check the actual data values, but how to write out this piece of code?!)
plt.imshow(M, cmap = cm.cubehelix, extent = (X.min(), X.max(), Y.min(), Y.max()))
plt.savefig('julia.tiff')
I want to print the intensity matrix elements out to check the actual data values, but how to write out this piece of code?! Due to if I just print M by print("Calculated Matrix: ", M), I could get only all [[1. 1. 1. ... 1. 1. 1.] [1. 1. 1. ... 1. 1. 1.] [1. 1. 1. ... 1. 1. 1.] ... [1. 1. 1. ... 1. 1. 1.] [1. 1. 1. ... 1. 1. 1.] [1. 1. 1. ... 1. 1. 1.]]. However, the calculated matrix elements should be any number in the range [0, 65536], not just all equal to 1! Any comment will be awesome!!
you get only 1 because hereļ¼š
for n in range(1, 4096)
...
break
n is 1 and then break

How to randomly change some members of a 2D-matrix to zero in python?

I have a 2D-matrix of some numbers and I want to randomly change a fraction of the non-zero members (e.x. 0.2) to become zero and then again randomly choose equal to that fraction amount (0.2) between all zeroes and give them random numbers. Is there any straight forward way to do that?
for example:
The original matrix is : x = [[1,2,3],[4,0,7],[2,10,0]]
After first step (2 randomly selected numbers change to zero): x = [[1,0,0],[4,0,7],[2,10,0]]
After second step (2 randomly selected zeros change to random numbers): x = [[1,0,5],[4,7,7],[2,10,0]]
One method:
arr = np.ones((5, 5)) # Your matrix
print("Before Replacement")
print(arr)
# Number of elements to replace
num_replaced = 3
# Random (x, y) coordinates
indices_x = np.random.randint(0, arr.shape[0], num_replaced)
indices_y = np.random.randint(0, arr.shape[1], num_replaced)
arr[indices_x, indices_y] = 0
print("After replacement")
print(arr)
Sample Output:
Before Replacement
[[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 1. 1. 1. 1.]]
After replacement
[[0. 1. 1. 1. 1.]
[1. 0. 1. 1. 1.]
[1. 1. 1. 1. 1.]
[1. 0. 1. 1. 1.]
[1. 1. 1. 1. 1.]]
EDIT
You can use np.random.choice instead on np.random.randint as follows:
indices_x = np.random.choice(range(arr.shape[0]), num_replaced, replace=REPLACE)
indices_y = np.random.choice(range(arr.shape[1]), num_replaced, replace=REPLACE)
Here, you can easily switch between sampling with or without replacement.
I would try to create a simple function for this. So you can input the number desired.
import pandas as pd
import random
def random_converter(dataframe, k, isZero=True, input_data='random_value'):
# Copy df
dataframe_local = dataframe.copy()
if input_data=='random_value':
input_data = random.randint(0,10)
ki = 0
while ki < k:
row_selected = dataframe_local.sample(1).T
# VERIFY CONDITION
if isZero:
attributes = row_selected[row_selected.iloc[:, 0] == 0]
else:
attributes = row_selected[row_selected.iloc[:, 0] != 0]
# No zero in the row
if attributes.size == 0:
continue
column_index = attributes.index
row_index = attributes.columns
dataframe_local.iloc[row_index, column_index] = input_data
ki += 0
return dataframe_local

Python build numpy matrix

I am given this matrix and am trying to write a function to build this matrix for any size of n. I am told the height of the matrix is n, but not sure the width.
Below is my code and output, is this correct? I am slightly confused by the notation of the matrix itself.
def buildMatrix(n, a):
matrix = np.zeros([n, n], dtype=float)
x_diag, y_diag = np.diag_indices_from(matrix)
for (x,y) in zip(x_diag, y_diag):
if x > (n / 2):
matrix[x][y] = -2*a
elif x == (n / 2):
matrix[x][y] = -(1 + a)
else:
matrix[x][y] = -2
if x != n - 1:
matrix[x + 1][y] = a if x >= (n / 2) else 1
matrix[x][y + 1] = a if x >= (n / 2) else 1
return matrix
Output with buildMatrix(5, 2)
[[-2. 1. 0. 0. 0.]
[ 1. -2. 1. 0. 0.]
[ 0. 1. -3. 2. 0.]
[ 0. 0. 2. -4. 2.]
[ 0. 0. 0. 2. -4.]]
Can anyone help me out?
To answer your first question, the matrix has to have a width of n in order for the matrix-vector product to be compatible.
The picture of the matrix is ambiguous on where the switch from -2 to -(1-a) to -2a occurs. In your code, you check if x==n/2 to set the switch. This is fine in python2 but will cause problems in python3 since x/2 returns 2.5. Using safer x==n//2 since n//2 return an integer in python2 as well as python3.
For generality, I'm going to assume that the switch happens at row m. The matrix can be built easier using slicing and the np.diag command.
def buildmat(n, m, a):
diag = np.zeros(n)
offdiag = np.zeros(n-1)
offdiag[0:m] = 1
offdiag[m:n-1] = a
diag[0:m] = -2
diag[m] = -(1+a)
diag[m+1:n] = -2*a
matrix = np.diag(diag) + np.diag(offdiag, 1) + np.diag(offdiag, -1)
return matrix
Running
buildmat(5, 2, 3)
produces
[[-2. 1. 0. 0. 0.]
[ 1. -2. 1. 0. 0.]
[ 0. 1. -3. 2. 0.]
[ 0. 0. 2. -4. 2.]
[ 0. 0. 0. 2. -4.]]

How to access array?

right now I'm working on control.matlap.tf2ss and I would like to access my array in my state space.
Here is my code
Gs = tf([P.l], [P.Jzz, 0, 0])
Cs = tf([P.Kp, P.Kd], 1)
Gcl = feedback(series(Cs, Gs), 1)
po = pole(Gcl)
num, den = tfdata(Gs)
sys = tf2ss(Gs)
print sys
Result:
A = [[ 0. 0.]
[ 1. 0.]]
B = [[-10.58350385]
[ 0. ]]
C = [[ 0. -1.]]
D = [[ 0.]]
How can I access array A, B, C, D?
For arrays of state-space models with variable numbers of states, use the syntax:
[a,b,c,d] = ssdata(sys,'cell')

Categories