Pinv not inverting my complex matrix entirely correct - python

I have quite an extensive code so I'm not sure how I can share it and it be easy for you to read but my main question concerns the pinv function in numpy.linalg.
I am inverting a non-square complex matrix. Upon inverting I find myself with absolute values that are correct but the real or the complex (always one is incorrect but never both) values are negative when they need to be postive and vice-versa.
To resolve this I thought multiplying by -1 would have resolved the problem but as mentioned it's never both signs that are wrong. Does anyone have any idea why the pinv function would do this?

I wrote a code about it without using np.linalg.pinv. it worked fine.
it is my code:
X and Y are my matrix
Xt = np.transpose(X)
X1 = np.matmul(Xt,X)
X2 = np.matmul(X,Xt)
try:
Xinv = np.linalg.inv(X1)
W = np.matmul(Xinv,Xt)
print("1")
except:
Xinv = np.linalg.inv(X2)
W = np.matmul(Xt,Xinv)
print("2")
#W = np.linalg.pinv(X,rcond=1e-5)
W = np.matmul(W,Y)

Related

Getting the non-trivial solution to a set of linear equations

I'm trying to write a program that will allow me to solve a system of equations using numpy, however, I want the solution to be non-trivial (not all zeros). Obviously the program is just going to set everything to 0, and boom, problem solved. I attempted to use a while loop (like below), but quickly found out it's going to continue to spit 0 back at me. I don't care if I end up using numpy, I'm open to other solutions if it's more elegant.
I actually haven't solved this particular set by hand, maybe the trivial solution is the only solution. If so, the principle still applies. Numpy seems to always spit 0 back.
Any help would be appreciated! Thanks.
x1 = .5
x2 = .3
x3 = .2
x4 = .05
a = np.array([[x1,x2],[x3,x4]])
b = np.array([0,0])
ans = np.linalg.solve(a,b)
while ans[0] == 0 and ans[1] == 0:
print ("got here")
ans = np.linalg.solve(a,b)
print(ans)
In your case, the matrix a is invertible. Therefore your system of linear equations has only one solution and the solution is [0, 0]. Are you wondering why you only get that unique solution?
Check out Sympy and it's use of solve and matrix calculations. Here are the pages for both.
http://docs.sympy.org/latest/tutorial/matrices.html
http://docs.sympy.org/latest/tutorial/solvers.html

sympy solveset returns FiniteSet in one case but a Complement in another case

So I am starting with an equality of an equation and a fraction that I use to solve for both x and y:
mrs = y/x
ratio = 2/5
x = sympy.solveset(sympy.Eq(mrs, ratio), x)
y = sympy.solveset(sympy.Eq(mrs, ratio), y)
In the end, solving for y returns:
{2*x/5}
Which is a FiniteSet
But solving for x returns:
{5*y/2} \ {0}
Which is a Complement
I don't get why solving for one variable gives me a FiniteSet when solving for the other doesn't do the same? Also, would there be a way to solve for the other variable so as to get a FiniteSet instead of a Complement?
What do you expect as a result? Could you solve this problem by hand and write the expected solution? And why would you want a FiniteSet as solution?
I myself can not come up with a better notation than sympy, since x=0 needs to be excluded.
When you continue working with the solutions sympy can easily work with both, FiniteSet and Complement. Mathematically those are not completely different structures. The difference is that sympy somehow needs to represent these solutions internally and can not use the same construction for everything, but rather uses small building blocks to create the solution. The result you get with type(x) is symply the last building block used.
EDIT: Some math here: x=0 does not solve the equation y/x=2/5 for any y. So this must be excluded from the solutionset.
If you solve for y, then x=0 is already excluded since y/0 is not well defined.
If you solve for y, then y=0 is a priori possible, since 0/x=0 for x!=0. Thus sympy needs to exclude x=0 manually, which it does by removing 0 from the set of solutions.
Now, since we know that x=0 can never be a solution of the equation we can exclude it before even trying to solve the equation. Therefore we do
x = sympy.symbols('x', real=True, nonzero=True)
right at the beginning of the example (before the definition of mrs). The rest can remain unchanged.

Returning incorrect values with complex numbers in Python

I'm working a physics problem with complex numbers and think I'm setting everything up correctly but am obviously not doing something right along the way. It could be that I'm either not using the right equations or that I'm unfamiliar with how Python's handling the math, and I'm pretty sure I'm using the right stuff. I've already worked a problem using the same kind of procedure and got the correct value, so substituting my new values should
Given f = 1000, SWR = -5.9, L = 0.081, I apparently should be getting z = 1.4 - 0.23j.
Here's what I'm doing:
import numpy as np
import cmath
f = 1000 #frequency
SWR = -5.9
L = 0.081
w = 2*f*np.pi #angular frequency
c = 343 #speed of sound in air
k = w/c #wavenumber
BA = (SWR-1)/(SWR+1) #given
theta = 2*k*L-np.pi #given
z = (1+BA*np.e**(1j*theta))/(1-BA*np.e**(1j*theta)) #given
print(z)
This gives me z = (-4.699946746470462-2.3316919882323677j), obviously not what I'm being told is the correct value.
I've gone over this multiple times now and can't find anything wrong. I just again worked through the problem I already got correct and made the minor substitutions to fit these given values, and I'm still getting the returned value of z. I don't want to tell my professor his "check that your code is giving the correct results" result is wrong, but...
Am I missing something?
E: Apologies for the rough display, but I'm not sure I can type in LaTeX here. The following are what I'm working with. Furthermore, the final image shows that I worked basically the same problem correctly and that I should be able to just make some substitutions to work this one. Also note that in my code, z is actually z divided by the rhocS quantity. I'm after that, don't need to know their values.
Equation for z, BA, theta, and the worked similar problem

How to handle number overflow?

I am calculating a trend line slope using numpy:
xs = []
ys = []
my_x = 0
for i in range(2000):
my_x += 1
ys.append(5*my_x+random.rand())
xs.append(my_x)
A = matrix(xs).T;
b = matrix(ys).T;
N = A.T*A
U = A.T*b
print N,U
a = (N.I*U)[0,0]
print a
The result I get is a=-8.2053307679 instead of the expected 5. Probably it happends beacuse the number in variable N is too big.
How to overcome this problem ? any help will be appreciated.
When I run the code, the answer is as you would expect:
[[2668667000]] [[ 1.33443472e+10]]
5.00037927592
It's probably due to the fact that you're on a 32-bit system, and I'm on a 64-bit system. Instead, you can use
A = matrix(xs, dtype='float64').T;
b = matrix(ys, dtype='float64').T;
Just FYI, when using numpy you'll be much more efficient if you work on vectorizing your algorithms. For example, you could replace the first several lines with this:
xs = np.arange(2000)
ys = 5 * xs + np.random.rand(2000)
Edit – one more thing: numerically, it is a bad idea to explicitly invert matrices when doing computations like these. It would be better to use something like a = np.linalg.solve(N, U)[0, 0] in your algorithm. It won't make a big difference here, but if you move to more complicated problems it definitely will! For some discussion this, take a look at this article.
:) The problem solved by using:
A = matrix(xs,float64).T;
b = matrix(ys,float64).T;

Using other data with a function of the form f(x,y) = f(x,y,z).sum(axis=-1)

So, in my previous question wflynny gave me a really neat solution (Surface where height is a function of two functions, and a sum over the third). I've got that part working for my simple version, but now I'm trying to improve on this.
Consider the following lambda function:
x = np.arange(0,100, 0.1)
y = np.sin(y);
f = lambda xx: (xx-y[x=xx])**2
values = f(x)
Now, in this scenario it works. In fact, the [x=xx] is trivial in the example. However, the example can be extended:
x = np.arange(0,100, 0.1)
z = np.sin(y);
f = lambda xx, yy: ( (xx-z[x=xx])**2 + yy**2)**0.5
y = np.arange(0,100,0.1)
[xgrid, ygrid] = np.meshgrid(x,y);
values = f(xgrid,ygrid)
In this case, the error ValueError: boolean index array should have 1 dimension is generated. This is because z.shape is different from xgrid.shape, I think.
Note that here, y=np.sin(y) is a simplification. It's not a function but an array of arbitrary values. We really need to go to that array to retrieve them.
I do not know what the proper way to implement this is. I am going to try some things, but I hope that somebody here will give me hints or provide me with the proper way to do this in Python.
EDIT: I originally thought I had solved it by using the following:
retrieve = lambda pp: map(lambda pp: dataArray[pp==phiArray][0], phi)
However, this merely returns the dataArray. Suppose dataArray contains a number of 'maximum' values for the polar radius. Then, you would normally incorporate this by saying something like g = lambda xx, yy: f(xx,yy) * Heaviside( dataArray - radius(xx,yy)). Then g would properly be zero if the radius is too large.
However, this doesn't work. I'm not fully sure but the behaviour seems to be something like taking a single value of dataArray instead of the entire array.
Thanks!
EDIT: Sadly, this stuff has to work and I can't spend more time on making it nice. Therefore, I've opted for the dirty implementation. The actual thing I was interested in would be of the sort as the g = lambda xx, yy written above, so I can implement that directly (dirty) instead of nicely (without nested for loops).
def envelope(xx, yy):
value = xx * 0.
for i in range(0,N): #N is defined somewhere, and xx.shape = (N,N)
for j in range(0,N):
if ( dataArray[x=xx[i,j]][0] > radius(xx[i,j],yy[i,j])):
value[i,j] = 1.
else:
value[i,j] = 0.
return value
A last resort, but it works. And, sometimes results matter over writing good code, especially when there's a deadline coming up (and you are the only one that cares about good code).
I would still be very much interested in learning how to do this properly, if there is a proper way, and thus increase my fluency in clean Python.

Categories