I need to find all the user made functions (and things like derivatives on the user function) in a SymPy expression tree with the location to then replace with just standard user-defined symbols
from sympy import *
t=symbols('t')
Now create the user made SymPy function:
theta_t = Function(r'\theta')(t)
Also, I create the symbol that I want to replace theta_t with:
theta = Symbol(r'\theta')
The expression that I want to work with is:
y = sin(theta_t)
And this is its derivative with respect to t:
dydt = y.diff(t)
I want to find and replace d/dt(theta(t)) and theta_t with symbols omega, theta. For example after substituting I want dydt to be:
dydt_new = cos(theta)*omega
So now I can work with this last expression numerically, e.g., with lambdify.
You can just substitute derivatives like anything else. You only have to be careful about substituting the derivative before the actual function. The following works for me:
from sympy import *
t = symbols('t')
theta_t = Function('theta')(t)
theta = Symbol('theta')
omega = Symbol('omega')
y = sin(theta_t)
dydt = y.diff(t)
dydt_new = dydt.subs([
( diff(theta_t,t), omega ),
( theta_t, theta ),
])
assert dydt_new==cos(theta)*omega
Note how this fails if you swap the order of substitutions.
Related
Consider this simple MWE:
from sympy.solvers.diophantine import diophantine
from sympy import symbols
x, y, z = symbols("x, y, z", integer=True)
diophantine(x*(2*x + 3*y - z))
This outputs:
[(t_0, t_1, 2*t_0 + 3*t_1), (0, n1, n2)]
If I want to create instances of these solutions I would like, for
example, to able to substitute integer values into t_0 and t_1. How
can you do that?
I tried e.g.
diof = diophantine(x*(2*x + 3*y - z))
list(diof)[0][0].subs(t_0, 0)
but that gives
NameError: name 't_0' is not defined
t_0 is not defined as a Python variable. You can create the Python variable in a couple of different ways:
from sympy import symbols
t_0 = symbols("t_0")
Alternatively, you can capture the symbol generated from your SymPy calculation into a Python variable. Here's one way:
diofl = list(diof) # Assuming that diof is as you had defined it.
t_0 = diofl[1][0] # Presuming that this is the part of diofl
# that contains the correct symbol. Print
# diofl[1][0] to be sure!
After that, you can then use t_0 as an argument of the subs() method.
I have learned how to automatically find the partial derivative of a function with sympy. My problem is, I need to define a new function that returns the partial derivative of the other function.
from sympy import Symbol, Derivative
y= Symbol('y')
function = y ** 2
deriv = Derivative(function, y).doit()
def func(y):
return deriv
Something like that. Hope you all understood. Thanks!
So y is another function as in predefined like y = Symbol('x') ** 2? I believe your function need another input.
x = Symbol('x')
y = x ** 2
def func(function, symbol):
deriv = Derivative(function, symbol).doit()
return deriv
derivative = func(y, x)
You can't do it without specifying symbol - especially since this is partial derivative you need to tell which symbol it's trying to derive against.
I want to take the derivative of a multivariable function using SymPy and then for a) the symbolic result to be printed and then b) the result of the derivative at a point to be printed. I'm using the following code
import math as m
import numpy
import scipy
#define constants
lambdasq = 0.09
Ca = 3
qOsq = 2
def f1(a,b,NN,ktsq,x):
return NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq/lambdasq))/m.log(qOsq/lambdasq))))
from sympy import *
x = symbols('x')
def f2(NN,a,b,x,ktsq):
return -x*diff(m.log(f1),x)
This runs but I can't find a way to get the symbolic result to be printed and when I try to evaluate at a point, say e.g adding in print(f2(0.3,0.1,-0.2,0.1,3)) I get an error
TypeError: must be real number, not function
When I replace f1 with its symbolic representation, I get instead the error
ValueError:
Can't calculate 1st derivative wrt 0.100000000000000.
So I can summarise my question as follows
a) How to print out a symbolic derivative and its value at a point when I call diff(m.log(f1),x) (i.e without having to replace f1 by its actual representation)
b) If I have to use the symbolic representation in the differentiation (i.e use diff(m.log(NN*x**(-a)*ktsq**b*m.exp(m.sqrt(16*Ca/9*m.log(1/x)*m.log((m.log(ktsq\
/lambdasq))/m.log(qOsq/lambdasq))))),x) then how to print out the symbolic derivative and its value at a point?
New to Python so hopefully there is a relatively simple fix.
Thanks!
I'm posting this answer since this thread is #1 on my search engine when searching for 'simpy multivariate differentiation' and might help someone.
example 1
import sympy as sp
def f(u):
return (u[0]**2 + u[1]**10 + u[2] - 4)**2
u = sp.IndexedBase('u')
print(sp.diff(f(u), u[0]))
outputs
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
This is the derivative of f(u) wrt u[0]
example 2
if we want the whole jacobian, we can do:
for i in range(3):
print(sp.diff(f(u), u[i]))
which outputs
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0]
20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9
2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8
we can define a temp function and copy paste these lines
def temp(u):
return np.array([
4*(u[0]**2 + u[1]**10 + u[2] - 4)*u[0],
20*(u[0]**2 + u[1]**10 + u[2] - 4)*u[1]**9,
2*u[0]**2 + 2*u[1]**10 + 2*u[2] - 8,
])
temp([1., 1., 1.])
this outputs array([ -4., -20., -2.])
and to verify
from autograd import grad
gradient = grad(f)
gradient([1., 1., 1.])
this outputs: [array(-4.), array(-20.), array(-2.)]
Note:This is just a simple showcase how you can do multivariate derivatives in sympy. I hope I can help someone with this
First, math functions are numeric, they cannot work with SymPy's symbols. Use the corresponding functions from SymPy (exp, log, sqrt) which you already imported with from sympy import *:
def f1(a, b, NN, ktsq, x):
return NN*x**(-a)*ktsq**b*exp(sqrt(16*Ca/9*log(1/x)*log((log(ktsq/lambdasq))/log(qOsq/lambdasq))))
Second, within f2 you are trying to differentiate f1. But f1 is a callable Python function, not a SymPy expression. You need to pass in some arguments to get a SymPy expression, which can then be differentiated.
def f2(NN, a, b, x0, ktsq):
return (-x*diff(log(f1(a, b, NN, ktsq, x)), x)).subs(x, x0)
Here the numeric arguments, except the value x0, are passed to f1, resulting in a SymPy expression containing x. That is a thing to be differentiated. After that, the numeric value x0 is substituted for x.
print(f2(0.3,0.1,-0.2,0.1,3)) # 0.366748952743614
A take-away point is that SymPy differentiates expressions, not functions. There is no concept of f' in SymPy, only f'(x).
I have the following equation:
Eq(5*Abs(4*x+2)+6,56).
What I am trying to do is solve for x = -3 for the math question 5 |4x+2|+6=56, but I keep getting the
"Absolute values cannot be inverted in the complex domain"
error in sympy.
Is there a way around this?
You must specify that x is a real-valued variable. You can do that when you define the variable as follows.
import sympy as sp
x = sp.symbols('x', real = True)
eq = sp.Eq(5*sp.Abs(4*x+2)+6,56)
sol = sp.solve(eq, x)
print(sol)
[-3, 2]
EDIT: The sympy.solveset function can be used instead of sympy.solve. In that case, you need to explicitly state that you are solving over the domain of reals. By doing so, you do not have to define your variable as real.
import sympy as sp
x = sp.symbols('x') # implies that x is complex
eq = sp.Eq(5*sp.Abs(4*x+2)+6,56)
sol = sp.solveset(eq, x, domain=sp.S.Reals)
print(sol)
{-3, 2}
So pretty much, I am aiming to achieve a function f(x)
My problem is that my function has an integral in it, and I only know how to construct definite integrals, so my question is how does one create an indefinite integral in a function (or there may be some other method I am currently unaware of)
My function is defined as :
(G is gravitational constant, although you can leave G out of your answer for simplicity, I'll add it in my code)
Here is the starting point, but I don't know how to do the integral portion
import numpy as np
def f(x):
rho = 5*(1/(1+((x**2)/(3**2))))
function_result = rho * 4 * np.pi * x**2
return function_result
Please let me know if I need to elaborate on something.
EDIT-----------------------------------------------------
I made some major progress, but I still have one little error.
Pretty much, I did this:
from sympy import *
x = Symbol('x')
rho = p0()*(1/(1+((x**2)/(rc()**2))))* 4 * np.pi * x**2
fooply = integrate(rho,x)
def f(rx):
function_result = fooply.subs({x:rx})
return function_result
Which works fine when I plug in one number for f; however, when I plug in an array (as I need to later), I get the error:
raise SympifyError(a)
sympy.core.sympify.SympifyError: SympifyError: [3, 3, 3, 3, 3]
(Here, I did print(f([3,3,3,3,3]))). Usually, the function returns an array of values. So if I did f([3,2]) it should return [f(3),f(2)]. Yet, for some reason, it doesn't for my function....
Thanks in advance
how about:
from sympy import *
x, p0, rc = symbols('x p0 rc', real=True, positive=True)
rho = p0*(1/(1+((x**2)/(rc))))* 4 * pi * x**2
fooply = integrate(rho,x)/x
rho, fooply
(4*pi*p0*x**2/(1 + x**2/rc),
4*pi*p0*rc*(-sqrt(rc)*atan(x/sqrt(rc)) + x)/x)
fooply = fooply.subs({p0: 2.0, rc: 3.0})
np_fooply = lambdify(x, fooply, 'numpy')
print(np_fooply(np.array([3,3,3,3,3])))
[ 29.81247362 29.81247362 29.81247362 29.81247362 29.81247362]
To plug in an array to a SymPy expression, you need to use lambdify to convert it to a NumPy function (f = lambdify(x, fooply)). Just using def and subs as you have done will not work.
Also, in general, when using symbolic computations, it's better to use sympy.pi instead of np.pi, as the former is symbolic and can simplify. It will automatically be converted to the numeric pi by lambdify.