converting a Matlab array to python - python

I have the following Matlab code:
A=[length(x) sum(x) sum(y) sum(x.*y);
sum(x) sum(x.^2) sum(x.*y) sum(y.*x.^2);
sum(y) sum(x.*y) sum(y.^2) sum(x.*y.^2);
sum(x.*y) sum((x.^2).*y) sum(x.*y.^2) sum((x.^2).*(y.^2))];
v=[sum(z); sum(z.*x); sum(z.*y); sum(x.*y.*z)];
solution=inv(A)*v;
a=solution(1);
b=solution(2);
c=solution(3);
d=solution(4);
which I want to convert into Python. I have no knowledge of Matlab, and with some research came up with the following Python code:
A = [
[len(x), x.sum(), y.sum(), (x * y).sum()],
[x.sum(), (x**2).sum(), (x * y).sum(), ((y * x) ** 2).sum()],
[y.sum(), (x * y).sum(), (y**2).sum(), ((x * y) ** 2).sum()],
[(x * y).sum(), ((x**2) * y).sum(), ((x * y)**2).sum(), ((x**2) * (y**2)).sum()]
]
v = [z.sum(), (z * x).sum(), (z * y).sum(), (x * y * z).sum()]
solution = np.linalg.inv(A) * v
I excpected a list with 4 values, which should be the coefficients which I want to use for a function. However, the result is another matrix. What am I doing wrong?

In the last step, you should use matrix multiplication instead of corresponding position multiplication.
Matrix multiplication uses operator#:
solution = np.linalg.inv(A) # v
Or function numpy.matmul:
solution = np.matmul(np.linalg.inv(A), v)

Related

How to make fsolve function work inside a for loop?

I am writing a function to calculate three nonlinear equations. I have the function to calculate them, but the thing is I give initial guess to them - which works fine. But now I have a constraint for x between (1/4 and 1/3). For that, I am making 2 for lops. One is for ptinting 13 different values, the other one for the constraint.
However the code does not give me the result at all:
import numpy as np
import math
from scipy.optimize import fsolve
def equations(vars):
x, y, z = vars
eq1 = ((x / (1 - x)) - (((2.5*np.cos(z)) / (8 * np.pi * np.sin(z) ** 2)) * (1 + (design_ratio * np.tan(z)))))
eq2 = ((y / (1 + y)) - (2.5 / (8 * np.pi * np.cos(z))) * (1 -design_ratio *( (1 / np.tan(z)))))
eq3 = np.tan(z) - ((1-x) /( 1.40 * (1+y)))
return [eq1, eq2, eq3]
n=13
for i in range(0, n):
for j in range(25555, 33333):
x = 0.00001 *x
x, y, z = fsolve(equations, (0.328, 0.048, 28))
print(x, y, z)
Frankly, using a loop is a terrible approach to handle the box constraint 1/4 <= x <= 1/3. Since fsolve doesn't support (box) constraints, you can rewrite the problem
Solve F(x,y,z) = 0 with 1/4 <= x <= 1/3
as an equivalent minimization problem
min np.sum(F(x,y,z)**2) s.t. 1/4 <= x <= 1/3
and solve it by means of scipy.optimize.minimize like this:
import numpy as np
from scipy.optimize import minimize
def F(vars):
x, y, z = vars
eq1 = ((x / (1 - x)) - (((2.5*np.cos(z)) / (8 * np.pi * np.sin(z) ** 2)) * (1 + (design_ratio * np.tan(z)))))
eq2 = ((y / (1 + y)) - (2.5 / (8 * np.pi * np.cos(z))) * (1 -design_ratio *( (1 / np.tan(z)))))
eq3 = np.tan(z) - ((1-x) /( 1.40 * (1+y)))
return np.array([eq1, eq2, eq3])
bounds = [(1./4, 1./3), (None, None), (None, None)]
res = minimize(lambda vars: np.sum(F(vars)**2), x0=(0.328, 0.048, 28), bounds=bounds)

Formatting of Complex number in Sympy expression

I am trying to solve expression in SymPy.
x,c,m=symbols('x,c,m')
y = x**4 + sym.Rational(11/4)*(c/m)*(x**2)+(sym.Rational(3/2)*(c/m)**2)
solve(y,x)
Is there a way in Sympy where sqrt(-1) will automatically get formatted as i in the output expression instead of containing as -1 in the square root?
The equation results in [-sqrt(2)*sqrt(-c/m), sqrt(2)*sqrt(-c/m), -sqrt(3)*sqrt(-c/m)/2, sqrt(3)*sqrt(-c/m)/2]. Without any hints, all variable can be complex, and c/m could be a positive real. There isn't a reason to bring I out of the square root. (Note that sympy represents I with a capital.)
If, however, c and m are declared as real and positive, the output changes:
import sympy as sym
c, m = sym.symbols('c,m', real=True, positive=True)
x = sym.symbols('x')
y = x ** 4 + sym.Rational(11 / 4) * (c / m) * (x ** 2) + (sym.Rational(3 / 2) * (c / m) ** 2)
sym.solve(y, x)
Result:
[-sqrt(2)*I*sqrt(c)/sqrt(m),
sqrt(2)*I*sqrt(c)/sqrt(m),
-sqrt(3)*I*sqrt(c)/(2*sqrt(m)),
sqrt(3)*I*sqrt(c)/(2*sqrt(m))]

Fitting piecewise function: running into NaN problems due to boolean array indexing

So I've been trying to fit to an exponentially modified gaussian function (if interested, https://en.wikipedia.org/wiki/Exponentially_modified_Gaussian_distribution)
import numpy as np
import scipy.optimize as sio
import scipy.special as sps
def exp_gaussian(x, h, u, c, t):
z = 1.0/sqrt(2.0) * (c/t - (x-u)/c) #not important
k1 = k2 = h * c / t * sqrt(pi / 2) #not important
n1 = 1/2 * (c / t)**2 - (x-u)/t #not important
n2 = -1 / 2 * ((x - u) / c)**2 #not important
y = np.zeros(len(x))
y += (k1 * np.exp(n1) * sps.erfc(z)) * (z < 0)
y += (k2 * np.exp(n2) * sps.erfcx(z)) * (z >= 0)
return y
In order to prevent overflow problems, one of two equivilent functions must be used depending on whether z is positive or negative (see Alternative forms for computation from previous wikipedia page).
The problem I am having is this: The line y += (k2 * np.exp(n2) * sps.erfcx(z)) * (z >= 0)is only supposed to add to y when z is positive. But if z is, say, -30, sps.erfcx(-30) is inf, and inf * False is NaN. Therefore, instead of leaving y untouched, the resulting y is clustered with NaN. Example:
x = np.linspace(400, 1000, 1001)
y = exp_gaussian(x, 100, 400, 10, 5)
y
array([ 84.27384586, 86.04516723, 87.57518493, ..., nan,
nan, nan])
I tried the replacing the line in question with the following:
y += numpy.nan_to_num((k2 * np.exp(n2) * sps.erfcx(z)) * (z >= 0))
But doing this ran into serious runtime issues. Is there a way to only evaluate (k2 * np.exp(n2) * sps.erfcx(z)) on the condition that (z >= 0) ? Is there some other way to solve this without sacrificing runtime?
Thanks!
EDIT: After Rishi's advice, the following code seems to work much better:
def exp_gaussian(x, h, u, c, t):
z = 1.0/sqrt(2.0) * (c/t - (x-u)/c)
k1 = k2 = h * c / t * sqrt(pi / 2)
n1 = 1/2 * (c / t)**2 - (x-u)/t
n2 = -1 / 2 * ((x - u) / c)**2
return = np.where(z >= 0, k2 * np.exp(n2) * sps.erfcx(z), k1 * np.exp(n1) * sps.erfc(z))
How about using numpy.where with something like: np.where(z >= 0, sps.erfcx(z), sps.erfc(z)). I'm no numpy expert, so don't know if it's efficient. Looks elegant at least!
One thing you could do is create a mask and reuse it so it wouldn't need to be evaluated twice. Another idea is to use the nan_to_num only once at the end
mask = (z<0)
y += (k1 * np.exp(n1) * sps.erfc(z)) * (mask)
y += (k2 * np.exp(n2) * sps.erfcx(z)) * (~mask)
y = numpy.nan_yo_num(y)
Try and see if this helps...

Multiplying matrices that are stored in an array in Python

This may seem like a silly question, but I am a bloody newby in Python (and in programming). I am running a physics simulation that involves many (~10 000) 2x2 matrices that I store in an array. I call these matrices M and the array T in the code below. Then I simply want to compute the product of all of these matrices. This is what I came up with, but it looks ugly and it would be so much work for 10000+ 2x2 matrices. Is there a simpler way or an inbuilt function that I could use?
import numpy as np
#build matrix M (dont read it, just an example, doesnt matter here)
def M(k1 , k2 , x):
a = (k1 + k2) * np.exp(1j * (k2-k1) * x)
b = (k1 - k2) * np.exp(-1j * (k1 + k2) * x)
c = (k1 - k2) * np.exp(1j * (k2 + k1) * x)
d = (k1 + k2) * np.exp(-1j * (k2 - k1) * x)
M = np.array([[a , b] , [c , d]])
M *= 1. / (2. * k1)
return M
#array of test matrices T
T = np.array([M(1,2,3), M(3,3,3), M(54,3,9), M(33,11,42) ,M(12,9,5)])
#compute the matrix product of T[0] * T[1] *... * T[4]
#I originally had this line of code, which is wrong, as pointed out in the comments
#np.dot(T[0],np.dot(T[1], np.dot(T[2], np.dot(T[2],np.dot(T[3],T[4])))))
#it should be:
np.dot(T[0], np.dot(T[1], np.dot(T[2],np.dot(T[3],T[4]))))
Not very NumPythonic, but you could do:
reduce(lambda x,y: np.dot(x,y), T, np.eye(2))
Or more concisely, as suggested
reduce(np.dot, T, np.eye(2))

solving equations simultaneously

I have the following set of equations, and I want to solve them simultaneously for X and Y. I've been advised that I could use numpy to solve these as a system of linear equations. Is that the best option, or is there a better way?
a = (((f * X) + (f2 * X3 )) / (1 + (f * X) + (f2 * X3 ))) * i
b = ((f2 * X3 ) / (1 + (f * X) + (f2 * X3))) * i
c = ((f * X) / (1 + (j * X) + (k * Y))) * i
d = ((k * Y) / (1 + (j * X) + (k * Y))) * i
f = 0.0001
i = 0.001
j = 0.0001
k = 0.001
e = 0 = X + a + b + c
g = 0.0001 = Y + d
h = i - a
As noted by Joe, this is actually a system of nonlinear equations. You are going to need more firepower than numpy alone provides.
Solution of nonlinear equations is tricky, and the typical approach is to define an objective function
F(z) = sum( e[n]^2, n=1...13 )
where z is a vector containing a value for each of your 13 variables a,b,c,d,e,f,g,h,i,X,Y and e[n] is the amount by which each of your 13 equations is violated. For example
e[3] = (d - ((k * Y) / (1 + (j * X) + (k * Y))) * i )
Once you have that objective function, then you can apply a nonlinear solver to try to find a z for which F(z)=0. That of course corresponds to a solution to your equations.
Commonly used solvers include:
The Solver in Microsoft Excel
The python library scipy.optimize
Fitting routines in the Gnu Scientific Library
Matlab's optimization toolbox
Note that all of them will work far better if you first alter your set of equations to eliminate as many variables as practical before trying to run the solver (e.g. by substituting for k wherever it is found). The reduced dimensionality makes a big difference.

Categories