Using sympy to solve an equation, python - python

I want to solve the below using Pythons sympy module instead of adapting what if have hand written. The result is x=26.8.
Any help appreciated.
Tks
EDIT:
my equation without sympy:
def cal_equ(total_vel=1.23, vel_vent_mg=17.74, vel_vent_tg=28.45, const=105):
a = (const / vel_vent_tg / const) + (1 / vel_vent_mg)
b = (total_vel - const / vel_vent_tg)
return b / a

from sympy import *
# create a symbol: it represents your unkown
x = symbols("x")
# create your constants
total_vel=1.23
vel_vent_mg=17.74
vel_vent_tg=28.45
const=105
# there are many ways to create an equation.
# here we create an equality, something that states that
# the left hand side is equal to the right hand side
eq = Eq((const - x) / vel_vent_tg - x / vel_vent_mg, total_vel)
# finally, we use the solve function to solve for the equation for x
sol = solve(eq, x)
sol[0].n()
# out: 26.8871034856029

Related

Differentiating absolute value functions using sympy in python won't return an answer

I'm trying to find the maximum points of curvature of a tanh(x) function, but the mathematical definition for curvature contains an absolute value function. I've specified that x must be real-valued which resolves sympy returning an imaginary function for the derivative of the curvature. However when trying to solve for k'(x)=0 using the sym.solve() method python will simply continue running and not return an answer at all.
x = sym.symbols('x', real=True)
# below are parameters I found from curve fitting raw data elsewhere that are just converted to sympy variables
a = sym.Float(a)
b = sym.Float(b)
c = sym.Float(c)
d = sym.Float(d)
# function in question
def f(x):
return a * sym.tanh(b * x + c) + d
def fprime(x):
return sym.diff(f(x),x,1)
def f2prime(x):
return sym.diff(f(x),x,2)
f1 = fprime(x)
f2 = f2prime(x)
# mathematical definition of curvature
def kappa(f1,f2):
return sym.Abs(f2) / ( 1 + f1**2 )**(3/2)
def kprime(f1,f2):
return sym.diff(kappa(f1,f2),x,1)
k1 = kprime(f1,f2)
print(k1)
One combination of the constants a,b,c,d=[-2.40402847 -3.20154993 0.51489147 -8.05771537] and k1 was
0.324273723818531*(1 - tanh(0.514891472285591 - 3.2015499273203*x)**2)*((1 - tanh(0.514891472285591 - 3.2015499273203*x)**2)**2 + 0.0168810800591381)**(-2.5)*(6.40309985464061*tanh(0.514891472285591 - 3.2015499273203*x)**2 - 6.40309985464061)*tanh(0.514891472285591 - 3.2015499273203*x)*Abs((tanh(3.2015499273203*x - 0.514891472285591)**2 - 1)*tanh(3.2015499273203*x - 0.514891472285591)) + 0.108091241272844*((3.2015499273203 - 3.2015499273203*tanh(3.2015499273203*x - 0.514891472285591)**2)*(tanh(3.2015499273203*x - 0.514891472285591)**2 - 1) + (6.40309985464061 - 6.40309985464061*tanh(3.2015499273203*x - 0.514891472285591)**2)*tanh(3.2015499273203*x - 0.514891472285591)**2)*((1 - tanh(0.514891472285591 - 3.2015499273203*x)**2)**2 + 0.0168810800591381)**(-1.5)*sign((tanh(3.2015499273203*x - 0.514891472285591)**2 - 1)*tanh(3.2015499273203*x - 0.514891472285591))
Then trying to solve this for x using print(sym.solve(k1),x) could never return an answer.
It's a pretty high-order nonlinear equation. Try nsolve:
>>> nsolve(k1, -.5)
-0.427127686132521

Sympy - got two solutions from trigonometric equation, I was expecting only one

I'm trying to solve a trigonometric equation with sympy. I'm having issues understanding what sympy is doing: I was expecting only one solution, instead I got two. Here is the code:
import sympy as sp
sp.var("a, b, c, d, z")
myeq = sp.Eq(c * sp.sin(a * (b / 2 - z)) + d * sp.cos(a * (b / 2 - z)), 0)
sol = sp.solve(myeq, z)
print(sol)
Output: [(a*b - 4*atan((c - sqrt(c**2 + d**2))/d))/(2*a), (a*b - 4*atan((c + sqrt(c**2 + d**2))/d))/(2*a)]
The solution I was expecting is: [b / 2 + atan(c / d) / a]
What am I missing? For this specific case, is it possible to obtain a single solution?
If you rearrange your equation to combine the sin and cos into tan you will get what you are looking for:
>>> solve(c/d*tan(a*(b/2-z))-1,z)
[b/2 - atan(d/c)/a]
If you don't, SymPy will rewrite and solve in terms of exp...and in that case, as you can verify, it will be quadratic in exp(l*a*z).
An attempt at rewriting a two-arg sum as a ratio could be done like this:
>>> def ratio(eq):
... if isinstance(eq, Eq):
... eq=eq.rewrite(Add)
... A, B = eq.as_two_terms()
... if not A.is_Add and not B.is_Add:
... return Eq(A/B, 1)
>>> trigsimp(ratio(eq))
Eq(c*tan(a*b/2 - a*z)/d, 1)
(The function returns None if there aren't two terms to work with.) As you can see, in this case you get a new equation which will solve as you desired.

Smart rewriting of expressions in sympy

I found this to be tricky to explain, but I'll do my best through an example.
Consider the expression assigned to the variable grad below
from sympy import *
a, x, b = symbols("a x b")
y_pred = a * x
loss = log(1 + exp(- b * y_pred))
grad = diff(loss, x, 1)
grad has the following expression:
-a*b*exp(-a*b*x)/(1 + exp(-a*b*x))
Now I want to manipulate grad in two ways.
1) I want sympy to try rewrite the expression grad such that none of its terms look like
exp(-a*b*x)/(1 + exp(-a*b*x)).
2) I also want it to try to rewrite the expression such that it has at least one term that look like this 1./(1 + exp(a*b*x)).
So at the end, grad becomes:
-a*b/(1 + exp(a*b*x)
Note that 1./(1 + exp(a*b*x)) is equivalent to exp(-a*b*x)/(1 + exp(-a*b*x)) but I don't want to mention that to sympy explicitly :).
I'm not sure if this is feasible at all, but it would be interesting to know whether it's possible to do this to some extent.
cancel does this
In [16]: cancel(grad)
Out[16]:
-a⋅b
──────────
a⋅b⋅x
ℯ + 1
This works because it sees the expression as -a*b*(1/A)/(1 + 1/A), where A = exp(a*b*x), and cancel rewrites rational functions as canceled p/q (see the section on cancel in the SymPy tutorial for more information).
Note that this only works because it uses A = exp(a*b*x) instead of A = exp(-a*b*x). So for instance, cancel won't do the similar simplification here
In [17]: cancel(-a*b*exp(a*b*x)/(1 + exp(a*b*x)))
Out[17]:
a⋅b⋅x
-a⋅b⋅ℯ
────────────
a⋅b⋅x
ℯ + 1
Are you just looking for simplify?
>>> grad
-a*b*exp(-a*b*x)/(1 + exp(-a*b*x))
>>> simplify(grad)
-a*b/(exp(a*b*x) + 1)

Differentiation in python using Sympy

How do i implement this kind of equation in python dC/dt = r + kI - dC where the left hand side are constants and the right hand side are varibles?
i am relatively new to python and as such can't really do much.
from sympy.solvers import ode
r=float(input("enter r:"))
k=float(input("enter k:"))
I=float(input("enter I:"))
d=float(input("enter d:"))
C=float(input("enter C:"))
dC/dt=x
x=r + kI-dC
print(x)
what it just does equate the values of x and not any differential, would like help getting this to work.
if possible i would like to get answer specifying the using of sympy,
but all answers are truly appreciated.
You asigned values to all the variables that are on the rhs of x so when you show x you see the value that it took on with the variables that you defined. Rather than input values, why not try solve the ode symbolically if possible?
>>> from sympy import *
>>> var('r k I d C t')
(r, k, I, d, C, t)
>>> eq = Eq(C(t).diff(t), r + k*I + d*C(t)) # note d*C(t) not d*C
>>> ans = dsolve(eq); ans
C(t) == (-I*k - r + exp(d*(C1 + t)))/d
Now you can substitute in values for the variables to see the result:
>>> ans.subs({k: 0})
C(t) == (-r + exp(d*(C1 + t)))/d

Non-linear equation solving Sympy Python for hydraulics - Need resolve TypeError("can't convert expression to float")

I am trying to write a piece of python script to automate a quite time consuming task in some hydraulics problems, that occur in civil engineering.
The equation is from Colebrook-White, and is the following:
I have written the following code:
from math import *
from sympy import *
e = 0.2
d = 0.2
v = 0.00000131
q = 10
s = ( pi * d ** 2 ) / 4
u = q / s
re = u * d / v
lamb = symbols( 'lamb' )
solve( 1 / sqrt( lamb ) \
+ 2 * log10( e / ( 3.7 * d ) \
+ 2.51 / ( re * sqrt( lamb ) ) \
), \
lamb \
)
But it gives the error:
File "hg.py", line 12, in <module>
solve(1/sqrt(lamb) + 2*log10(k/(3.7*d) + 2.51/(re*sqrt(lamb))),lamb)
File "/home/luis/Documents/sympy/sympy/core/expr.py", line 211, in __float__
raise TypeError("can't convert expression to float")
TypeError: can't convert expression to float
I couldn't post a picture of how the equation looks, as im new.
Since sqrt(lambda) is in both sides of the equation, I think it has to be solved by an iterative method, but I don't know how to do it... On my calculator (TI-Voyage 200) I usually use nSolve() and it does the job.
Thanks in advance!
Don't do from math import *. This is munging up your namespace with functions from the math module, which don't work with SymPy expressions (they only work with floats). In this case, log10 comes from math. Just do from sympy import *, or better, if you are writing a script, import everything you use explicitly. The SymPy equivalent of log10(x) is log(x, 10).
You are still using log10 instead of log( expr, 10 ). Correcting that and using bisection with nsolve works:
>>> eq = 1/sqrt(lamb) + 2*log(e/(3.7*d) + 2.51/(re*sqrt(lamb)), 10)
>>> nsolve(eq,lamb, (.1, 1.1), method='bisect')
mpf('0.77434599870454337')
See help( mpmath.findroot ) for other solver options besides bisect.
Thanks for all the help!
With your help, together with other threads here on stackoverflow, I have been able to solve the problem.
This is my final, solved, code:
def f(x):
return (-2*numpy.log10((2.51/(Re*numpy.sqrt(x))) + (k/(3.7*d))) - 1.0/numpy.sqrt(x))
lamb = float(fsolve(f, 0.02))
print "Lambda = %f " % lamb

Categories