Same equation gives different values in Matlab and Numpy? - python

I'm trying to convert a function from Matlab to Python. The Matlab function is:
function [f,df_dr1,df_dr2,g,dg_dr1,dg_dr2] = f_eval_2eq(r1,r2,r3,z1,z2,z3,n1,n2,n3)
f = (r1)./sqrt(r1.^2 + z1.^2)...
- (n2/n1)*(r2-r1)./sqrt((r2-r1).^2 + z2.^2);
df_dr1 = 1./sqrt(r1.^2 + z1.^2)...
- r1.^2./(r1.^2 + z1.^2).^(3/2)...
+ (n2/n1)./sqrt(z2.^2 + (r1-r2).^2)...
- (n2/n1).*(r1-r2).*(2*r1-2*r2)./(2*((r1-r2).^2 + z2.^2).^(3/2));
df_dr2 = (n2/n1).*(r1-r2).*(2*r1-2*r2)./(2*((r1-r2).^2 + z2.^2).^(3/2))...
- (n2/n1)./sqrt(z2.^2 + (r1-r2).^2);
g = (r2-r1)./sqrt((r2-r1).^2 + z2.^2)...
- (n3/n2)*(r3-r2)./sqrt((r3-r2).^2 + z3.^2);
dg_dr1 = (r1-r2).*(2*r1-2*r2)./(2*((r1-r2).^2 + z2.^2).^(3/2))...
- 1./sqrt(z2.^2 + (r1-r2).^2);
dg_dr2 = 1./sqrt((r1-r2).^2 + z2.^2)...
+ (n3/n2)./sqrt(z3.^2 + (r2-r3).^2)...
- (r1-r2).*(2*r1-2*r2)./(2*((r1-r2).^2 + z2.^2).^(3/2))...
- (n3/n2).*(r2-r3).*(2*r2-2*r3)./(2*((r2-r3).^2 + z3.^2).^(3/2));
end
%test code
K>> a=[1,2,3];b=a+1;c=b+1;d=a;e=b;f=c;g=1;h=2;i=3;
K>> [f,df_dr1,df_dr2,g,dg_dr1,dg_dr2] = f_eval_2eq(a,b,c,d,e,f,g,h,i)
The Python function I wrote is:
def f_eval_2eq(r1,r2,r3,z1,z2,z3,n1,n2,n3):
#evaluate gradients
#n_ are scalars
f = (r1)/np.sqrt(r1**2 + z1**2) \
- (n2/n1)*(r2-r1)/np.sqrt((r2-r1)**2 + z2**2);
df_dr1 = 1/np.sqrt(r1**2 + z1**2) \
- r1**2/((r1**2 + z1**2)**(3/2)) \
+ (n2/n1)/np.sqrt(z2**2 + (r1-r2)**2) \
- (n2/n1)*(r1-r2)*(2*r1-2*r2)/(2*((r1-r2)**2 + z2**2)**(3/2));
df_dr2 = (n2/n1)*(r1-r2)*(2*r1-2*r2)/(2*((r1-r2)**2 + z2**2)**(3/2)) \
- (n2/n1)/np.sqrt(z2**2 + (r1-r2)**2);
g = (r2-r1)/np.sqrt((r2-r1)**2 + z2**2) \
- (n3/n2)*(r3-r2)/np.sqrt((r3-r2)**2 + z3**2);
dg_dr1 = (r1-r2)*(2*r1-2*r2)/(2*((r1-r2)**2 + z2**2)**(3/2)) \
- 1/np.sqrt(z2**2 + (r1-r2)**2);
dg_dr2 = 1/np.sqrt((r1-r2)**2 + z2**2) \
+ (n3/n2)/np.sqrt(z3**2 + (r2-r3)**2) \
- (r1-r2)*(2*r1-2*r2)/(2*((r1-r2)**2 + z2**2)**(3/2)) \
- (n3/n2)*(r2-r3)*(2*r2-2*r3)/(2*((r2-r3)**2 + z3**2)**(3/2));
return (f,df_dr1,df_dr2,g,dg_dr1,dg_dr2)
#test code
A=np.array([1,2,3])
B=A+1
C=B+1
D=A
E=B
F=C
G=1
H=2
I=3
[f,df_dr1,df_dr2,g,dg_dr1,dg_dr2] =f_eval_2eq(A,B,C,D,E,F,G,H,I)
print ('f= '+str(f) +'\n'+'df_dr1= '+str(df_dr1) +'\n' +'df_dr2='+str(df_dr2) +'\n'+'g= '+str(g) +'\n'+'dg_dr1= '+str(dg_dr1) +'\n'+'dg_dr2= '+str(dg_dr2) +'\n')
The output for f is the same in both, but all the other values are different and I cant figure out why???
Any help is appreciated.

In Python 2.x, if you divide two integers (such as 2 and 3) the result is cast as an integer as well:
x = 3/2
# 1
type(x)
# <type 'int'>
You need to explicitly specify either the numerator or denominator to be a float rather than an integer using a decimal point and this will allow the output to be a float as well.
y = 3./2
# 1.5
type(y)
# <type 'float'>
Alternately, as suggested by #rayryeng, you can place the following at the top of your code to get the behavior you expect.
from __future__ import division

You can also add
from __future__ import division
to the top of your file, if you're using Python 2, in order to get the Python 3 behavior, i.e. always using float division.

Related

Sympy: solving non linear equation

I want to solve this non linear equation:
f100 = omega_nf_eq
where:
f100 : numerical costant, defined as a variable for now.
omega_nf_eq: equation.
Firstly I've tried to solve it sybolically and my code was:
import sympy as sym
K_u, K_m = sym.symbols('K_u, K_m', real = True)
J_p1, J_p2, J_g1, J_g2, J_r, J_u, J_m, J_p12, J_g12, J_gb, J_2, J_1, J_p = sym.symbols('J_p1, J_p2, J_g1, J_g2, J_r, J_u, J_m, J_p12, J_g12, J_gb, J_2, J_1, J_p', real = True)
tau_1, tau_2 = sym.symbols('tau_1, tau_2', real = True)
omega_nf, f100 = sym.symbols('omega_nf, f100', real = True)
omega_nf_eq = sym.Eq(omega_nf, sym.sqrt(2)*sym.sqrt(K_m/(J_g2*tau_2**2 + J_p1 + J_p2) + K_u/(J_g2*tau_2**2 + J_p1 + J_p2) + K_u/(tau_2**2*(J_g1 + J_u)) + K_m/J_m - sym.sqrt(J_m**2*K_m**2*tau_2**4*(J_g1 + J_u)**2 + 2*J_m**2*K_m*K_u*tau_2**4*(J_g1 + J_u)**2 - 2*J_m**2*K_m*K_u*tau_2**2*(J_g1 + J_u)*(J_g2*tau_2**2 + J_p1 + J_p2) + J_m**2*K_u**2*tau_2**4*(J_g1 + J_u)**2 + 2*J_m**2*K_u**2*tau_2**2*(J_g1 + J_u)*(J_g2*tau_2**2 + J_p1 + J_p2) + J_m**2*K_u**2*(J_g2*tau_2**2 + J_p1 + J_p2)**2 + 2*J_m*K_m**2*tau_2**4*(J_g1 + J_u)**2*(J_g2*tau_2**2 + J_p1 + J_p2) - 2*J_m*K_m*K_u*tau_2**4*(J_g1 + J_u)**2*(J_g2*tau_2**2 + J_p1 + J_p2) - 2*J_m*K_m*K_u*tau_2**2*(J_g1 + J_u)*(J_g2*tau_2**2 + J_p1 + J_p2)**2 + K_m**2*tau_2**4*(J_g1 + J_u)**2*(J_g2*tau_2**2 + J_p1 + J_p2)**2)/(J_m*tau_2**2*(J_g1 + J_u)*(J_g2*tau_2**2 + J_p1 + J_p2)))/2)
solution = sym.solve(f100 - omega_nf_eq.args[1], J_u, dict = True)
But this gave me just this result: [ ].
I've also tried to substitute all variable value except for J_u, which is the one i want. So now the omega_nf equation is:
omega_nf_eq = sym.Eq(omega_nf, sym.sqrt(2)*sym.sqrt(76019006.3529542 - 84187769.0684942*sym.sqrt(0.813040126459949*J_u**2 - 4.69199504596906e-5*J_u + 1.03236146920168e-9)/J_u + 2704.98520837442/J_u)/2)
So to solve now i've tried:
solution = sym.solve( 942.5 - omega_nf_eq.args[1], J_u,, dict = True, force=True, manual=True, set=True)
It works now, but it requires a couple of minutes.
So I've tried to solve it numerically, to speed up the process, with sympy.nsolve(); this is the code:
omega_nf_eq = sym.Eq(omega_nf, sym.sqrt(2)*sym.sqrt(76019006.3529542 - 84187769.0684942*sym.sqrt(0.813040126459949*J_u**2 - 4.69199504596906e-5*J_u + 1.03236146920168e-9)/J_u + 2704.98520837442/J_u)/2)
eq_solution = sym.nsolve(942.5 - omega_nf_eq, J_u, 0.0071, verify=False)
But i do not obtain the right result, which is: J_u = 0.00717865789803973.
What I'm doing wrong?
There's a smarter way to use sympy?
There is not J_u in your first symbolic equation so that's why you got [] for the solution. When you attempted a numerical solution you used omega_nf_eq (which is an Equality); I think you meant 'nsolve(942.5 - omega_nf_eq.rhs, J_u, .0071)'. But even still, that won't find a solution for you since the equation, as written, is ill-behaved with J_u in the denominator. If you use sympy.solvers.solvers.unrad to give you to radical-free expression whose roots will contain, as a subset, those you are interested in you will find that you need only solve a quadratic in J_u...and that will be fast.
>>> unrad(942.5 - omega_nf_eq.rhs)
(1.0022170762796e+15*J_u**2 - 2936792314038.5*J_u + 2.04890966415405e-7, [])
>>> solve(_[0])
[6.97669240810738e-20, 0.00293029562511584]
I would recommend that you revist your first symbolic expression and unrad that -- or even just try solve that -- after identifying which variable corresponds to J_u.
I have solved using :
sympy.solveset(942.5 - omega_nf_eq.rhs, J_u)
I link the sympy.solveset() docs :
Now is pretty fast.

python sympy does not factor well polynomials of booleans

I am trying to factor a polynomial of booleans to get the minimal form of a logic net. My variables are a1, a2, a3 ... and the negative counterparts na1, na2, na3 ...
If would expect a function
f = a1*a2*b2*nb1 + a1*b1*na2*nb2 + a1*b1*na2 + a2*b2*na1*nb1
to be factored like this (at least) :
f = a1*b1*(b2*nb1 + na2*(nb2 + 1)) + a2*b2*na1*nb1
I run this script:
import sympy
a1,a2,b1,b2,b3,na1,na2,na3,nb1,nb2,nb3 = \
sympy.symbols("a1:3, b1:4, na1:4, nb1:4", bool=True)
f = "a1*na2*b1 + a1*a2*nb1*b2 + a1*na2*b1*nb2 + na1*a2*nb1*b2"
sympy.init_printing(use_unicode=True)
sympy.factor(f)
and this returns me the same function, not factored.
a1*a2*b2*nb1 + a1*b1*na2*nb2 + a1*b1*na2 + a2*b2*na1*nb1
What am I doing wrong ?
Your expected output
f = a1*b1*(b2*nb1 + na2*(nb2 + 1)) + a2*b2*na1*nb1
is not a factorization of f, so factor is not going to produce it. To factor something means to write it as a product, not "a product plus some other stuff".
If you give a polynomial that can actually be factored, say f = a1*na2*b1 + a1*a2*nb1*b2 + a1*na2*b1*nb2, then factor(f) has an effect.
What you are looking for is closer to collecting the terms with the same variable, which is done with collect.
f = a1*na2*b1 + a1*a2*nb1*b2 + a1*na2*b1*nb2 + na1*a2*nb1*b2
collect(f, a1)
outputs
a1*(a2*b2*nb1 + b1*na2*nb2 + b1*na2) + a2*b2*na1*nb1
The method coeff also works in that direction, e.g., f.coeff(a1) returns the contents of the parentheses in the previous formula.

Can we replace the 'Derivative' terms in sympy coming from the differentiation of sympy.Function variables?

When the following code is run Derivative(Ksi(uix, uiy), uix)) and Derivative(Ksi(uix, uiy), uiy)) terms appear:
In [4]: dgN
Out[4]:
Matrix([
[-(x1x - x2x)*(-x1y + x2y)*((x1x - x2x)**2 + (-x1y + x2y)**2)**(-0.5)*Derivative(Ksi(uix, uiy), uix) + (-x1y + x2y)*(-(-x1x + x2x)*Derivative(Ksi(uix, uiy), uix) + 1)*((x1x - x2x)**2 + (-x1y + x2y)**2)**(-0.5)],
[-(-x1x + x2x)*(-x1y + x2y)*((x1x - x2x)**2 + (-x1y + x2y)**2)**(-0.5)*Derivative(Ksi(uix, uiy), uiy) + (x1x - x2x)*(-(-x1y + x2y)*Derivative(Ksi(uix, uiy), uiy) + 1)*((x1x - x2x)**2 + (-x1y + x2y)**2)**(-0.5)]])
I would like to replace this Derivative terms by, let's say, the symbolic expression of the derivative of a function that I know for example, I would like to set Derivative(Ksi(uix,uiy), uix) = 2 * uix.
Is there a neat way to do this substitution and to get a symbolic expression for dgN with Derivative(Ksi(uix,uiy), uix) set to 2 * uix? Here is my code:
import sympy as sp
sp.var("kPenN, Xix, Xiy, uix, uiy, Alpha, x1x, x1y, x2x, x2y, x3x, x3y ", real = True)
Ksi = sp.Function('Ksi')(uix,uiy)
Xi = sp.Matrix([Xix, Xiy])
ui = sp.Matrix([uix, uiy])
xix = Xix + uix
xiy = Xiy + uiy
xi = sp.Matrix([xix, xiy])
x1 = sp.Matrix([x1x, x1y])
x2 = sp.Matrix([x2x, x2y])
N = sp.Matrix([x2 - x1, sp.zeros(1)]).cross(sp.Matrix([sp.zeros(2,1) , sp.ones(1)]))
N = sp.Matrix(2,1, sp.flatten(N[0:2]))
N = N / (N.dot(N))**(0.5)
xp = x1 + (x2 - x1)*Ksi
# make it scalar (in agreement with 9.231)
gN = (xi - xp).dot(N)
dgN = sp.Matrix([gN.diff(uix), gN.diff(uiy)])
The substitution you want can be achieved with
dgN_subbed = dgN.subs(sp.Derivative(Ksi, uix), 2*uix)
Here Ksi is without arguments (uix,uiy) since those were already declared when Ksi was created.
The syntax would be a little more intuitive if you defined Ksi as Ksi = sp.Function('Ksi'), leaving the arguments -- whatever they may be -- to be supplied later. Then sp.Derivative(Ksi(uix, uiy), uix) would be the way to reference the derivative.

The QRsolve method of sympy never returns or throws "Could not normalize the vector" error

I've tried QRsolve and cholesky_solve on the matrices shown below (printed str repr). I get results from numpy with these. The functions never return with sympy, I guess this has something to do with sympy trying to solve these using a symbolic method? The reason I'm trying sympy is that as my system becomes more complex the matrices become ill-conditioned and I am attempting to increase the precision using sympy and mpmath.
from sympy.matrices import Matrix as sy_matrix
A = sy_matrix([[-1.73598602689344 - 0.555723094599341j, -1.73598602689344 - 0.555723094599341j, 0.232989179693563 - 0.308565151130628j, 0.232989179693563 - 0.308565151130628j, 0.785911137306334 + 0.373372141423308j, 0.785911137306334 + 0.373372141423308j, 0.436377021604638 + 0.329496457808818j, 0.436377021604638 + 0.329496457808818j],
[-2.47182252542744 - 3.12228363243637j, -8.23364083219883 - 10.4003267796456j, 0.752244101320904 + 0.206999511678148j, 2.50572510149994 + 0.689515373399912j, 8.05887958417013 + 10.8152044077855j, 26.8441278948708 + 36.0254458823337j, -0.534283343532919 + 1.94160599872119j, -1.77969781730816 + 6.46748958174029j],
[-2.44359008697499 - 4.49072303037516j, -13.8356070724522 - 25.4264737979839j, 1.0065385313486 + 0.721365705527217j, 5.69902116449569 + 4.08437262469506j, 15.1118001221454 + 29.8836019724734j, 85.5630122915864 + 169.200954368143j, -2.42747866727978 + 3.38711806497384j, -13.744384214138 + 19.1778624838817j],
[-3.12331363856586 - 6.06170033660146j, -24.9646459130564 - 48.4511707904544j, 1.44382306453606 + 1.1598998787916j, 11.5404777548365 + 9.27107973118107j, 24.2361910493061 + 51.4282308184496j, 193.719875057099 + 411.065848931859j, -4.63756924615993 + 5.77276501482576j, -37.0680909845555 + 46.1417107635014j],
[0.232989179693563 - 0.308565151130628j, 0.232989179693563 - 0.308565151130628j, -1.73598602689344 - 0.555723094599341j, -1.73598602689344 - 0.555723094599341j, 0.436377021604638 + 0.329496457808818j, 0.436377021604638 + 0.329496457808818j, 0.785911137306335 + 0.373372141423309j, 0.785911137306335 + 0.373372141423309j],
[0.752244101320904 + 0.206999511678148j, 2.50572510149994 + 0.689515373399912j, -2.47182252542744 - 3.12228363243637j, -8.23364083219883 - 10.4003267796456j, -0.534283343532919 + 1.94160599872119j, -1.77969781730816 + 6.46748958174029j, 8.05887958417013 + 10.8152044077855j, 26.8441278948708 + 36.0254458823337j],
[1.0065385313486 + 0.721365705527217j, 5.69902116449569 + 4.08437262469506j, -2.44359008697499 - 4.49072303037516j, -13.8356070724522 - 25.4264737979839j, -2.42747866727978 + 3.38711806497384j, -13.744384214138 + 19.1778624838817j, 15.1118001221454 + 29.8836019724734j, 85.5630122915864 + 169.200954368143j],
[1.44382306453606 + 1.1598998787916j, 11.5404777548365 + 9.27107973118107j, -3.12331363856586 - 6.06170033660146j, -24.9646459130564 - 48.4511707904544j, -4.63756924615993 + 5.77276501482576j, -37.0680909845555 + 46.1417107635014j, 24.2361910493061 + 51.4282308184496j, 193.7198750571 + 411.065848931859j]])
b = sy_matrix([[1.73598602689344 + 0.555723094599341j], [0.742066203971011 + 0.937341228590923j], [0.431577196569235 + 0.793133703704558j], [0.39075611642261 + 0.758376121181231j], [-0.232989179693563 + 0.308565151130628j], [-0.225831312314891 - 0.06214335385114j], [-0.177770846229001 - 0.127404751947585j], [-0.180635939514086 - 0.145114460001454j]])
x = A.QRsolve(b)
I pasted the code as suggested in the comment, constructing a simple repo script. The difference here is that I create the matrices on initialisation, rather than value-by-value. Now I don't get a block but the following error:
Traceback (most recent call last):
File "sympyTest.py", line 14, in
x = A.QRsolve(b)
File "C:\Python27\lib\site-packages\sympy\matrices\matrices.py", line 1633, in QRsolve
Q, R = self.as_mutable().QRdecomposition()
File "C:\Python27\lib\site-packages\sympy\matrices\matrices.py", line 1599, in QRdecomposition
"Could not normalize the vector %d." % j)
NotImplementedError: Could not normalize the vector 1.
As QRsolve documentation says,
This is mainly for educational purposes and symbolic matrices, for real (or complex) matrices use sympy.mpmath.qr_solve.
I suggest following this advice, or just use mpmath on its own.
Here is a much simpler repro of the issue qith QRsolve:
A = sy_matrix([[2+3j, 1], [1, 1]])
b = sy_matrix([[1], [1]])
A.QRsolve(b)
This throws "NotImplementedError: Could not normalize the vector 0." because the QRdecomposition method, on which QRsolve relies, does not even try to handle floating point errors. This is what it does:
R[j, j] = tmp.norm()
Q[:, j] = tmp / R[j, j]
if Q[:, j].norm() != 1:
raise NotImplementedError("Could not normalize the vector %d." % j)
Obviously, the vector obtained by dividing a column of floating-point numbers by its norm need not have norm exactly 1. In my example,
>>> (A[:,0]/A[:,0].norm()).norm() == 1
False

Algorithm to invert strings of algebraic expressions in Python

Is there an easy way to make a function to inverse an algorithm for example like this:
>>> value = inverse("y = 2*x+3")
>>> print(value)
"x = (y-3)/2"
If you can't make actual code for the function, please recommend me tools that would make this task easier. The function would be only used to inverse algorithms with +, -, * and /
You should try SymPy for doing that:
from sympy import solve
from sympy.abc import x, y
e = 2*x+3-y
solve(e,x)
#[y/2 - 3/2]
solve(e,y)
#[2*x + 3]
Based on this, you can build your inverse() like (works for two variables):
def inverse(string, left_string=None):
from sympy import solve, Symbol, sympify
string = '-' + string
e = sympify(string.replace('=','+'))
if left_string:
ans = left_string + ' = ' + str(solve(e, sympify(left_string))[0])
else:
left = sympify(string.split('=')[0].strip().replace('-',''))
symbols = e.free_symbols
symbols.remove( left )
right = list(symbols)[0]
ans = str(right) + ' = ' + str(solve(e, right)[0])
return ans
Examples:
inverse(' x = 4*y/2')
#'y = x/2'
inverse(' y = 100/x + x**2')
#'x = -y/(3*(sqrt(-y**3/27 + 2500) + 50)**(1/3)) - (sqrt(-y**3/27 + 2500) + 50)**(1/3)'
inverse("screeny = (isox+isoy)*29/2.0344827586206895", "isoy")
#'isoy = -isox + 0.0701545778834721*screeny'
This is a little long for a comment, but here's the sort of thing I had in mind:
import sympy
def inverse(s):
terms = [sympy.sympify(term) for term in s.split("=")]
eqn = sympy.Eq(*terms)
var_to_solve_for = min(terms[1].free_symbols)
solns = sympy.solve(eqn, var_to_solve_for)
output_eqs = [sympy.Eq(var_to_solve_for, soln) for soln in solns]
return output_eqs
After which we have
>>> inverse("y = 2*x+3")
[x == y/2 - 3/2]
>>> inverse("x = 100/z + z**2")
[z == -x/(3*(sqrt(-x**3/27 + 2500) + 50)**(1/3)) - (sqrt(-x**3/27 + 2500) + 50)**(1/3), z == -x/(3*(-1/2 - sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3)) - (-1/2 - sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3),
z == -x/(3*(-1/2 + sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3)) - (-1/2 + sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3)]
etc.

Categories