Fit several functions with lmfit with shared parameters, no datasets- in Python - python

I would like to find the parameters E_u, tau_max, and G from these 3 functions.
The functions are the following:
Function 1:
0=0.009000900090009*E_u*(0.000103939092728486*exp(1500000.0/tau_max) + 0.000157703794137242*exp(2999000.0/tau_max) + 0.00017784012*exp(4500000.0/tau_max) + 0.00025534696*exp(6000000.0/tau_max) + 0.00027086158*exp(7500000.0/tau_max) + 0.000280826592271819*exp(9000000.0/tau_max) + 0.0004132622*exp(10501000.0/tau_max))*exp(-10501000.0/tau_max) + 1000000.0*G*(0.000467438377626028*exp(2999000.0/tau_max) + 0.00117770839577636*exp(4500000.0/tau_max) + 0.00197826966391473*exp(6000000.0/tau_max) + 0.00312798328672298*exp(7500000.0/tau_max) + 0.00434787369844519*exp(9000000.0/tau_max) + 0.00561383708066149*exp(10501000.0/tau_max))*exp(-10501000.0/tau_max)/tau_max
Function 2:
1.13624775718=0.09000900090009*E_u*(0.000103939092728486*exp(15000.0/tau_max) + 0.000157703794137242*exp(29990.0/tau_max) + 0.00017784012*exp(45000.0/tau_max) + 0.00025534696*exp(60000.0/tau_max) + 0.00027086158*exp(75000.0/tau_max) + 0.000280826592271819*exp(90000.0/tau_max) + 0.0004132622*exp(105010.0/tau_max))*exp(-105010.0/tau_max) + 10000.0*G*(0.000467438377626028*exp(29990.0/tau_max) + 0.00117770839577636*exp(45000.0/tau_max) + 0.00197826966391473*exp(60000.0/tau_max) + 0.00312798328672298*exp(75000.0/tau_max) + 0.00434787369844519*exp(90000.0/tau_max) + 0.00561383708066149*exp(105010.0/tau_max))*exp(-105010.0/tau_max)/tau_max
Function 3:
1.13106678093=0.9000900090009*E_u*(0.000103939092728486*exp(150.0/tau_max) + 0.000157703794137242*exp(299.9/tau_max) + 0.00017784012*exp(450.0/tau_max) + 0.00025534696*exp(600.0/tau_max) + 0.00027086158*exp(750.0/tau_max) + 0.000280826592271819*exp(900.0/tau_max) + 0.0004132622*exp(1050.1/tau_max))*exp(-1050.1/tau_max) + 100.0*G*(0.000467438377626028*exp(299.9/tau_max) + 0.00117770839577636*exp(450.0/tau_max) + 0.00197826966391473*exp(600.0/tau_max) + 0.00312798328672298*exp(750.0/tau_max) + 0.00434787369844519*exp(900.0/tau_max) + 0.00561383708066149*exp(1050.1/tau_max))*exp(-1050.1/tau_max)/tau_max

You have 3 non-linear equations and 3 unknowns in a set of transcendental equations. There will not be a closed-form solution, but you can get numerical values for the parameters. I know this is in the python section, but you should look into Mathematica for this. There is a good example here: https://mathematica.stackexchange.com/questions/9875/numerically-solving-two-dependent-transcendental-equations

Related

Is there a statsmodel formula equivalent of the R glm library for y ~ .?

I have a dataframe containing the following columns:
y as the dependent variable
A, B, C, D, E, F as the independent variables.
I want to make a regression using the statsmodels module and I don't want to express the formula argument as follows:
formula = 'y ~ A + B + C + D + E + F'
R glm library does have a simplification by expressing formula = y ~ .
I was wondering if statsmodel shortcut as there is one for the glm library in R.
P.S.: the actual dataframe that I'm working has 27 variables
There is no shortcut like "." in patsy formula handling which is used by statsmodels.
However, python string manipulation is simple.
An example that I'm currently using,
DATA is my dataframe, docvis is the outcome variable, and I have a constant column that is not needed in the formula.
formula = "docvis ~ " + " + ".join([i for i in DATA if i not in ["docvis", "const"]])
formula
'docvis ~ offer + ssiratio + age + educyr + physician + nonphysician + medicaid + private + female + phylim + actlim + income + totchr + insured + age2 + linc + bh + ldocvis + ldocvisa + docbin + aget + aget2 + incomet'
More explicit would be to use column names directly DATA.columns.
In modern Python we don't need to build the list in the list comprehension, and we can use
formula = "docvis ~ " + " + ".join(i for i in DATA.columns if i not in ["docvis", "const"])

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.

Factor/collect expression in Sympy

I have an equation like:
R₂⋅V₁ + R₃⋅V₁ - R₃⋅V₂
i₁ = ─────────────────────
R₁⋅R₂ + R₁⋅R₃ + R₂⋅R₃
defined and I'd like to split it into factors that include only single variable - in this case V1 and V2.
So as a result I'd expect
-R₃ (R₂ + R₃)
i₁ = V₂⋅───────────────────── + V₁⋅─────────────────────
R₁⋅R₂ + R₁⋅R₃ + R₂⋅R₃ R₁⋅R₂ + R₁⋅R₃ + R₂⋅R₃
But the best I could get so far is
-R₃⋅V₂ + V₁⋅(R₂ + R₃)
i₁ = ─────────────────────
R₁⋅R₂ + R₁⋅R₃ + R₂⋅R₃
using equation.factor(V1,V2). Is there some other option to factor or another method to separate the variables even further?
If it was possible to exclude something from the factor algorithm (the denominator in this case) it would have been easy. I don't know a way to do this, so here is a manual solution:
In [1]: a
Out[1]:
r₁⋅v₁ + r₂⋅v₂ + r₃⋅v₂
─────────────────────
r₁⋅r₂ + r₁⋅r₃ + r₂⋅r₃
In [2]: b,c = factor(a,v2).as_numer_denom()
In [3]: b.args[0]/c + b.args[1]/c
Out[3]:
r₁⋅v₁ v₂⋅(r₂ + r₃)
───────────────────── + ─────────────────────
r₁⋅r₂ + r₁⋅r₃ + r₂⋅r₃ r₁⋅r₂ + r₁⋅r₃ + r₂⋅r₃
You may also look at the evaluate=False options in Add and Mul, to build those expressions manually. I don't know of a nice general solution.
In[3] can be a list comprehension if you have many terms.
You may also check if it is possible to treat this as multivariate polynomial in v1 and v2. It may give a better solution.
Here I have sympy 0.7.2 installed and the sympy.collect() works for this purpose:
import sympy
i1 = (r2*v1 + r3*v1 - r3*v2)/(r1*r2 + r1*r3 + r2*r3)
sympy.pretty_print(sympy.collect(i1, (v1, v2)))
# -r3*v2 + v1*(r2 + r3)
# ---------------------
# r1*r2 + r1*r3 + r2*r3

Categories