I'm trying to build a code which finds the eigenvectors of a matrix given its eigenvalues. I need to write the code myself so inbuilt functions are not an option here.
I already made a simple code to calculate the eigenvalues of a given matrix from which I use these values to calculate the eigenvectors. The problem is that when I solve the homogenous system (A−λI)v=0 where λ is an eigenvalue of A and I is the identity matrix, the code returns an empty set, whereas the analytical solution is x=t where t is some free parameter and y=0. The code I have is this:
import numpy as np
import sympy as sym
from sympy.solvers.solveset import linsolve
A_1 = sym.Matrix([[0,1],[0,1]])
system = A, b = A_1[:,0], A_1[:,-1]
linsolve(system, x, y)
This returns an empty set as I said before. When I print b however I get the vector (1,1) which I'm not sure why python is returning this. I need to emphasize that I'm only looking for non-trivial solutions here as I don't want an eigenvector of zeros.
I don't think this statement does what you think it does:
system = A, b = A_1[:,0], A_1[:,-1]
That will be parsed like this:
A, b = A_1[:,0], A_1[:,-1]
System = A, b
That first statement is a tuple assignment. A will be assigned A_1[:,0], which is [0,0], and b will be assigned the value of A_1[:,-1], which is [1,1]. system is then assigned a tuple with both values.
Related
Let's say I have inputs 'A' and 'B' for my function, which outputs 'C'. For each value of A, I would like to find what value of B results in the maximum value of C; I would then like to record values B and C. Is there a function that can perform this action? Perhaps something which depends on convergence mechanisms?
*in case you found this through one of the non-python related tags I applied, please make note that I am using python 3.x
Let's define function to take parameters (A,B) and return a value C. We can optimize this with Python by doing
from scipy import optimize
f = lambda a,b: ... # your_code_which_returns_C
optimal_vals = np.zeros((2, len(list_of_all_A_values)))
for i, a in enumerate(list_of_all_A_values) # assuming some list is defined above
b_opt, c_opt, *rest = optimize.fmin(lambda b: -f(a,b), 0)
optimal_vals[:,i] = np.array([b_opt, c_opt])
This takes advantage of scipy's fmin function, which relies on the convergence of the downhill simplex algorithm. For this reason, it's crucial to not forget the minus sign on .
I am having trouble creating a function with two variables and three parameters. I want to perform a definite (numerical) integral over one of the variables (say t), and have it spit out an array F1(x;a,b,c), i.e. an array with a value associated with each entry in x, with scalar parameters a, b, and c. Ultimately I will need to fit the parameters (a,b,c) to data using leastsq, which I have done before using simpler functions.
Code looks like this:
def H1(t,x,a,b,c): #integrand
return (a function of the above, with parameters a,b,c, dummy variable to be integrated from 0 to inf t, and x)
def F1(x,a,b,c): #integrates H1: 0<t<inf
f_int1 = integrate.quad(H1,0.,np.inf,args=(x,a,b,c)) #integrating t from 0 to inf, x is going to be an element of the array in x_data.
return f_int1
Now, for example if I try to use F1 as a function:
F1(x_data,70.,.05,.1) #where x_data is an array of real numbers, between 0 and 500
I get the message:
quadpack.error: Supplied function does not return a valid float
I am hoping it will spit out an array: F1 for all the entries in x_data. If I just use a single scalar value for the first input into F1, e.g.:
F1(x_data[4],70.,.05,.1)
It spits out two numbers, which are the value of F1 at that point and the error tolerance. This looks like part of what I want, but I think I need it to work when passing an array through. So: it works for passing a single scalar value, but I need it to accept an array (and therefore make an array).
I am guessing the problem lies when I am trying to pass an array through the function as an argument. Though I am not sure what is a better way to do this? I think I have to figure out a way to do it as a function, since I will be using leastsq in the next few lines of code. (I know how to use leastsq, I think!)
Anyone have any ideas on how to get around this?
scipy.integrate.quad does not accept array-valued functions. Your best bet is to have a loop over the components (possibly with syntactic sugar of numpy.vectorize).
I am trying to implement the Double-and-Add Algorithm for Elliptic curves, which is done below. However, I am not producing the same answers as the textbook. Instead I am getting a repeat answer. Is there anything wrong with the code?
The code should do the following:
Input: Point, P, and an integer n greater than or equal to 1.
Set Q=P and R=(0,0).
Loop while n>0.
If n=1 mod 2, set R=R+Q.
Set Q=2Q and n=floor(n/2)
If n>0, continue with loop at Step 3.
Return the point R, which equals nP.
def doubleandadd(n, A, B, p, (x,y)):
P=(x,y)
Q,R=P,(0,0)
while n>0:
if (n%2)==1:
R=R+Q
Q,n=2*Q,math.floor(n/2)
print R
You're using tuples for your points, but the + operator concatenates tuples, rather than adding their values together. Similarly, multiplying a tuple by an integer repeats the tuple's values, rather than multiplying each of them.
I suggest using a numerical type like numpy's arrays instead (or just adding the components of the tuples yourself, if you don't want to use numpy).
I have two arrays A,B and want to take the outer product on their last dimension,
e.g.
result[:,i,j]=A[:,i]*B[:,j]
when A,B are 2-dimensional.
How can I do this if I don't know whether they will be 2 or 3 dimensional?
In my specific problem A,B are slices out of a bigger 3-dimensional array Z,
Sometimes this may be called with integer indices A=Z[:,1,:], B=Z[:,2,:] and other times
with slices A=Z[:,1:3,:],B=Z[:,4:6,:].
Since scipy "squeezes" singleton dimensions, I won't know what dimensions my inputs
will be.
The array-outer-product I'm trying to define should satisfy
array_outer_product( Y[a,b,:], Z[i,j,:] ) == scipy.outer( Y[a,b,:], Z[i,j,:] )
array_outer_product( Y[a:a+N,b,:], Z[i:i+N,j,:])[n,:,:] == scipy.outer( Y[a+n,b,:], Z[i+n,j,:] )
array_outer_product( Y[a:a+N,b:b+M,:], Z[i:i+N, j:j+M,:] )[n,m,:,:]==scipy.outer( Y[a+n,b+m,:] , Z[i+n,j+m,:] )
for any rank-3 arrays Y,Z and integers a,b,...i,j,k...n,N,...
The kind of problem I'm dealing with involves a 2-D spatial grid, with a vector-valued function at each grid point. I want to be able to calculate the covariance matrix (outer product) of these vectors, over regions defined by slices in the first two axes.
You may have some luck with einsum :
http://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html
After discovering the use of ellipsis in numpy/scipy arrays
I ended up implementing it as a recursive function:
def array_outer_product(A, B, result=None):
''' Compute the outer-product in the final two dimensions of the given arrays.
If the result array is provided, the results are written into it.
'''
assert(A.shape[:-1] == B.shape[:-1])
if result is None:
result=scipy.zeros(A.shape+B.shape[-1:], dtype=A.dtype)
if A.ndim==1:
result[:,:]=scipy.outer(A, B)
else:
for idx in xrange(A.shape[0]):
array_outer_product(A[idx,...], B[idx,...], result[idx,...])
return result
Assuming I've understood you correctly, I encountered a similar issue in my research a couple weeks ago. I realized that the Kronecker product is simply an outer product which preserves dimensionality. Thus, you could do something like this:
import numpy as np
# Generate some data
a = np.random.random((3,2,4))
b = np.random.random((2,5))
# Now compute the Kronecker delta function
c = np.kron(a,b)
# Check the shape
np.prod(c.shape) == np.prod(a.shape)*np.prod(b.shape)
I'm not sure what shape you want at the end, but you could use array slicing in combination with np.rollaxis, np.reshape, np.ravel (etc.) to shuffle things around as you wish. I guess the downside of this is that it does some extra calculations. This may or may not matter, depending on your limitations.
I'm a CS major in university working on a programming project for my Calc III course involving singular-value decomposition. The idea is basically to convert an image of m x n dimensions into an m x n matrix wherein each element is a tuple representing the color channels (r, g, b) of the pixel at point (m, n). I'm using Python because it's the only language I've really been (well-)taught so far.
From what I can tell, Python generally doesn't like tuples as elements of an array. I did a little research of my own and found a workaround, namely, pre-allocating the array as follows:
def image_to_array(): #converts an image to an array
aPic = loadPicture("zorak_color.gif")
ph = getHeight(aPic)
pw = getWidth(aPic)
anArray = zeros((ph,pw), dtype='O')
for h in range(ph):
for w in range(pw):
p = getPixel(aPic, w, h)
anArray[h][w] = (getRGB(p))
return anArray
This worked correctly for the first part of the assignment, which was simply to convert an image to a matrix (no linear algebra involved).
The part with SVD, though, is where it gets trickier. When I call the built-in numPy svd function, using the array I built from my image (where each element is a tuple), I get the following error:
Traceback (most recent call last):
File "<pyshell#5>", line 1, in -toplevel-
svd(x)
File "C:\Python24\Lib\site-packages\numpy\linalg\linalg.py", line 724, in svd
a = _fastCopyAndTranspose(t, a)
File "C:\Python24\Lib\site-packages\numpy\linalg\linalg.py", line 107, in _fastCopyAndTranspose
cast_arrays = cast_arrays + (_fastCT(a.astype(type)),)
ValueError: setting an array element with a sequence.
This is the same error I was getting initially, before I did some research and found that I could pre-allocate my arrays to allow tuples as elements.
The issue now is that I am only in my first semester of (college-level) programming, and these numPy functions written by and for professional programmers are a little too black-box for me (though I'm sure they're much clearer to those with experience). So editing these functions to allow for tuples is a bit more complicated than when I did it on my own function. Where do I need to go from here? I assume I should copy the relevant numPy functions into my own program, and modify them accordingly?
Thanks in advance.
Instead of setting the array element type to 'O' (object) you should set it to a tuple. See the SciPy manual for some examples.
In your case, easiest is to use something like
a = zeros((ph,pw), dtype=(float,3))
Assuming your RGB values are tuples of 3 floating point numbers.
This is similar to creating a 3d array (as Steve suggested) and, in fact, the tuple elements are accessed as a[n,m][k] or z[n,m,k] where k is the element in the tuple.
Of course, the SVD is defined for 2d matrices and not 3d arrays so you cannot use linalg.svd(a). You have to decide SVD of what matrix (of the three possible ones: R G and B) you need.
If, for example, you want the SVD of the "R" matrix (assuming that is the first element of the tuple) use something like:
linalg.svd(a[:,:,1])
I think you want a ph by pw by 3 numpy array.
anArray = zeros((ph,pw,3))
for h in range(ph):
for w in range(pw):
p = getPixel(aPic, w, h)
anArray[h][w] = getRGB(p)
You just need to make sure getRGB returns a 3-element list instead of a tuple.