Derivative on index symbols in sympy - python

I am trying to do symbolical calculations (derivatives mostly) on time-indexed variables using sympy.
Using indexed symbols like r[t] below produces an error:
from sympy import *
t = Idx('t',10)
r = IndexedBase('r')
diff(r[t],r[t])
diff(r,r)
ValueError:
Can't differentiate wrt the variable: r[t], 1
Could the reason be that something went wrong here:
In [15]: r[t].indices
Out[15]: (t,)
The comma after the index t looks suspicious to me, but I have no idea what went wrong.
Does anyone know how to do this in sympy?

You can differentiate wrt symbols, functions and derivatives. Will this work:
>>> t = Idx('t',10)
>>> r=Function('r')
>>> r(t).diff(r(t))
1
>>> var('t')
t
>>> r(t).diff(t)
Derivative(r(t), t)

Related

How to solve implementation problem in sympy

I need to solve an equation, but spider returns me this error:
import sympy as sym
import sympy as sympy
Re=100
Epsilon=0.00000075
D=0.01
f=symbols('f')
eq=(((1/(-2* sympy.log((Epsilon/D/ 3.7)+( 2.51 / (Re*(f**0.5))), 10)))**2 -f),0)
sym.solve((eq), (f))
print(f)
NotImplementedError: could not solve -4*f*log(202702702702703/10000000000000000000 + 251/(10000*sqrt(f)))**2 + log(10)**2
The solve function is for finding analytic solutions but that isn't possible for your equation (not all equations have analytic solutions):
In [11]: eq[0]
Out[11]:
2
log (10)
-f + ──────────────────────────────────────────
2⎛ -0.5 ⎞
4⋅log ⎝0.0251⋅f + 2.02702702702703e-5⎠
You can find a numeric solution with nsolve:
In [12]: sym.nsolve(eq[0], f, 0.1)
Out[12]: 0.169438052045717
https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.solvers.nsolve
This can be represented in terms of the LambertW function, but it needs some help. SymPy doesn't recognize the inverted sqrt(f) in the log. If you replace that with 1/y and solve for y and transform the solutions for y back to f you can get a symbolic solution.
It's easier in this case to let SymPy work with symbols instead of Floats and substitute the values later. Your equation looks like this:
>>> from sympy import a,b,c
>>> seq = a**2/log(b/sqrt(f) + c)**2 - f
>>> reps = {a:log(10)/2, c:Epsilon/D/3.7, b:2.51/Re}
Replace that sqrt(f) with 1/y
>>> ysol = solve(seq.xreplace(sqrt(f), 1/y), y)
Calculate the corresponding solutions for f:
>>> fsol = [((1/i)**2) for i in ysol]
Substitute in your values -- or any values that you are interested in:
>>> [i.xreplace(reps).n(3) for i in fsol]
[0.00771 - 0.107*I, 0.169]
Testing in the original shows that the second solution is valid
>>> [eq.subs(f,i).n() for i in _]
[0.148289010493944 + 0.206688429851791*I, 6.05179945288758e-6]
So your symbolic solution is
>>> fsol[1]
(-c/b + LambertW(a*exp(a*c/b)/b)/a)**(-2)
The nice thing about this form is that you can substitute any values of a,b,c and get the corresponding value of f. Whether this is faster than using nsolve, you will have to see.

Sympy 'solve' returns 'list index out of range' error

I am using JuypterLab trying to solve a simple algebra problem:
3 * r**0.25 * s**0.75 = 14.086
I need to solve for s for values of r between 3 and 17.
import numpy as np
import pandas
import sympy as sym
from sympy import symbols, solve
s = Symbol('s')
expr = 3 * 18**0.25 * s**0.75 = 14.086
sol = solve(expr)
num = sol[10]
num
When I run the code I get the list out of range error
I also tried
s = Symbol('s')
expr = 3 * 18**0.25 * s**0.75
sol = solve(expr)
u = 14.086
num = sol[u]
num
When I run this code I get list indices must be integers or slices, not float
I would like to find the value of s for values of r
between 3 and 17.
Equations in sympy are written using Eq(). You can call solve with such an equation (or a list of multiple equations). You can tell solve that you look for an expression for s given r, by providing s as a second parameter.
The result of solve can take a few different forms, depending on the equations. Usually it is a list, and in this case there is only one expression that solves for s, so a list with one element. (E.g. a quadratic equation could have multiple solutions.)
The result of solve often isn't a single number, but a symbolic expression. In this case, it is an expression involving the variable r. To get a value for s for a specific r (e.g. r=10), expr.subs(r, 10) can be used. Sometimes the solution is numeric, but still in its symbolic form (e.g. sqrt(2)). Calling .evalf() will give a fully numeric solution.
from sympy import Symbol, solve, Eq, plot
r = Symbol('r')
s = Symbol('s')
equation = Eq(3 * r**0.25 * s**0.75, 14)
sol = solve(equation, s) # [7.79846345438935/r**(1/3)]
s_of_r = sol[0]
for ri in range(3, 18):
si = s_of_r.subs(r, ri).evalf()
print(f"for r={ri} the corresponding value for s={si:.6f}")
Sympy can also do some basic plotting:
plot(s_of_r, (r, 3, 17))
Regarding the first error "When I run the code I get the list out of range error":
this is because sol is a one element list, and you are trying to access the tenth element that doesn't exist.
Regarding the second error "When I run this code I get list indices must be integers or slices, not float"
this is because to access a position of a list you are trying with a decimal, which besides not working it doesn't make sense
As for the output of sol it is [0.0].
Isn't the code bellow what you are looking for? Cause It seems to me you wanto to find out the output of the expression when s is 14.086, right?
import numpy as np
import pandas
import sympy as sym
from sympy import Symbol, solve
s = Symbol('s')
expr = 3 * 18**0.25 * s**0.75
y = expr.replace(s, 14.086)
print(y)
Instead, if you want to find the value of sol given a expression value you can use this approach
# equation example 3 + s, given an output of 5
y = solveset(Eq(3 + s, 5), s)
print(y)

Converting expression involving tranpose of vector to numerical function with lambdify

I have written a script in python that uses sympy to compute a couple of vector/matrix formulas. However, when I try to convert those to functions that I can evaluate with sympy.lambdify, I get a
SyntaxError : EOL while scanning string literal
Here's some code with the same error, so that you can see what I mean.
import sympy
x = sympy.MatrixSymbol('x',3,1)
f = sympy.lambdify(x, x.T*x)
So, the syntax error has to do with the expression "x'.dot(x)" and the conversion of ".T" to '.
How can I work around this to correctly define f from the above lambdify?
Found a work around, although not the cleanest looking solution... but it works.
Use the implemented_function() method from sympy to define your function. Read full documentation here: http://docs.sympy.org/latest/modules/utilities/lambdify.html
Here is the code:
import sympy
import numpy as np
from sympy.utilities.lambdify import implemented_function
x = sympy.MatrixSymbol('x',3,1)
f = implemented_function(sympy.Function('f'), lambda x: x.T*x)
lam_f= sympy.lambdify(x, f(x))
Hope this solves your problem :)
It has been solved in sympy version >= 1.1
Edit:
Example
when u define this
x = sympy.MatrixSymbol('x',3,1)
you are creating a matrix,
you can check its indexing and shape using
print(sympy.Matrix(x))
Now that you want to multiply Transpose of x to x, you will have to give x a matrix of same shape that you have defined before
here try this:
from sympy import MatrixSymbol, lambdify, Matrix
x = MatrixSymbol('x', 3, 1)
f = lambdify(x, x.T*x)
a = Matrix([[1], [2], [3]])
print(f(a))
you can check this link out to understand lambdify better:
http://docs.sympy.org/latest/modules/utilities/lambdify.html

Separating real and imaginary parts using Sympy

I am trying to segregate real and imaginary parts of the output for the following program.
import sympy as sp
a = sp.symbols('a', imaginary=True)
b=sp.symbols('b',real=True)
V=sp.symbols('V',imaginary=True)
a=4*sp.I
b=5
V=a+b
print V
Kindly help. Thanks in advance.
The lines
b=sp.symbols('b',real=True)
V=sp.symbols('V',imaginary=True)
have no effect, because you overwrite the variables b and V in the lines
b=5
V=a+b
It's important to understand the difference between Python variables and SymPy symbols when using SymPy. Whenever you use =, you are assigning a Python variable, which is just a pointer to the number or expression you assign it to. Assigning it again changes the pointer, not the expression. See http://docs.sympy.org/latest/tutorial/intro.html and http://nedbatchelder.com/text/names.html.
To do what you want, use the as_real_imag() method, like
In [1]: expr = 4*I + 5
In [2]: expr.as_real_imag()
Out[2]: (5, 4)
You can also use the re() and im() functions:
In [3]: re(expr)
Out[3]: 5
In [4]: im(expr)
Out[4]: 4

Equation roots: parameter doesn't get simplified

I am using Python with Sympy.
I need to solve the following equation, finding the 4 roots (omega is my unknown):
deter= 0.6*omega**4*cos(omega*t)**2 - 229.0*omega**2*cos(omega*t)**2 + 5880.0*cos(omega*t)**2
I tried to use solve:
eqcarr=solve(deter,omega,exclude=[t])
I get this output:
[-18.8143990830350, -5.26165884593044, 5.26165884593044, 18.8143990830350, 1.5707963267949/t, 4.71238898038469/t]
I only need the first 4 values, and not the values with the t coefficient. I expect the cos(omega*t)**2 to be simplified in solve, but this doesn't happen.
According to documentation solve will not solve for any of the free symbols passed in the exclude.
'exclude=[] (default)'
don't try to solve for any of the free symbols in exclude;
if expressions are given, the free symbols in them will
be extracted automatically.
It is not meant to filter solution.
You can solve your problem by doing this:
In [10]: from sympy import *
In [11]: from sympy.abc import omega, t
In [12]: deter= 0.6*omega**4*cos(omega*t)**2 - 229.0*omega**2*cos(omega*t)**2 + 5880.0*cos(omega*t)**2
In [13]: eqcarr=solve(deter,omega,exclude=[t])
In [14]: filtered = [i for i in eqcarr if not i.has(t)]
In [15]: filtered
Out[15]: [-18.8143990830350, -5.26165884593044, 5.26165884593044, 18.8143990830350]

Categories