I'm a beginner with Python (v 3.7) and I am trying to evaluate numerically a derivative of a symbolic function that contains parameters but I can't feed the values in a successful way.
I've tried different combinations getting inspiration from reading this question and something also from here.
Here is a minimal example that replicates my problem:
import sympy as sym
from sympy import*
x, y, a = sym.var('x, y, a')
def f(x,y):
return a*x**2 + x*y**2
fprime = sym.diff(f(x,y),x)
print(f(1,1))
print(fprime.evalf(subs={x: 1, y: 1}))
As expected the output of the first print is a+1 but the issue arrives with the second print because the output I get is 2.0*a*x + y**2 while I wish to obtain 2*a+1.
How shall I amend my code? I've also tried defining fprime separately and run the following:
def fprime(x,y):
return sym.diff(f(x,y),x)
print(fprime(x,1))
but still I can't make any progress. Thanks!
Just use substitution. Use evalf when you are trying to get a number from an expression that is a number. Your, containing unevaluated a is not yet a number so evaluation rejects it.
>>> fprime.subs({x: 1, y: 1})
2*a + 1
Related
I want to evaluate Re(df(t)/dt) where t is real and f(t) is real. However, this does not work using sympy.
Here is a example:
from sympy import re, im, symbols, Function
t = symbols('t',real=True)
f = Function('f',real=True)(t)
print(re(f))
print(re(t))
print(re(f.diff(t)))
This will print
f(t)
t
re(Derivative(f(t), t))
The two first prints are as expected, but I expected the last one to be
Derivative(f(t), t)
I checked the issue "simplify does not simplify complex numbers composed into real and imaginary part #18271" which led me to try (f.diff(t)).expand(complex=True,deep=True) and (f.diff(t)).as_real_imag(), but it still does not recognize that df(t)/dt is real.
I also looked at what re and im do (source code is here https://henrikfinsberg.com/docs.gotran/_modules/sympy/functions/elementary/complexes.html) but I don't understand it well enough to find a way out.
Would you know how to solve this issue or have a workaround? Thanks!
I would just do a replacement:
>>> re(f.diff(t)).replace(lambda x: isinstance(x, re) and
... x.args[0].is_Derivative
... and x.args[0].expr.is_real,
... lambda x: x.args[0])
Derivative(f(t), t)
I have searched online, and through this website, but the similar posts that create a function that evaluates the derivative of a function at x are not user input functions. For example, they will have f=2*x**2, and I want to create a function that works for pretty much any function that contains algebraic operators, trig and log expressions, etc. I created a function that evaluates a user input function at x using numpy/math imports and eval(), but I can't quite replicate this for the derivative of a user input function.
from sympy import sympify, Symbol
import numpy
import math
x = Symbol('x')
y=sympify(input('Type your function:'))
yprime = y.diff(x)
I found this from a post online, and it accurately calculates the derivative of a user input function but I couldn't figure out how to add a function that evaluates yprime at some x value. When I tried to add
def fprime(x):
return eval(yprime, {'x': x, 'np': numpy, 'math': math})
I got an error that yprime is not a string, which it isn't.
TypeError: eval() arg 1 must be a string, bytes or code object
I would appreciate any help I can get, and note that I am a beginner with python.
You could try something like this:
from sympy import sympify, Symbol
import numpy
import math
x = Symbol('x')
y=sympify(input('Type your function:'))
value=float(input('Type the value to evaluate: '))
yprime = y.diff(x)
print(y)
print(yprime)
def fprime(value):
return float(yprime.subs({x:value}))
print(fprime(value))
everyone
Is it possible to solve the following like:
x = np.matrix([[8.3,-20.6],[-20.6,65.8]])
y is a function of P:
y = lambda P: np.matrix([[0.02P,-0.02P], [-0.02P,0.04P]])
I want to find the P value given conditions that:
P>0, det(x-y)==0;
Is there any handy way for this?
Thank you very much!
Shawn
If you don't mind using an additional package, scipy.optimize has a number of methods that would be perfect. Otherwise, you could implement your own zero finding function.
If you want to go the scipy route:
1) Define your problem as a function that takes your unknown parameter (P) as its first argument, and returns the value you want to minimize:
def zerofn(P, x, y):
return np.linalg.det(x - y(P))
2) Optimize this function, using scipy. The example here uses a simple Newton-Raphson zero finder, but there are many other options which you might want to use to specify parameter bounds (e.g. P > 0).
import scipy.optimize as opt
opt.newton(zerofn, x0=1, args=(x, y))
>> 160.25865914054651
The result of this zero finder is your optimized value of P.
Hi I am writing Python code which returns the associated Legendre function.
Using numpy poly1d function on this part,
firstTerm = (np.poly1d([-1,0,1]))**(m/2.0) # HELP!
It yields an error since it can only be raised to integer.
Is there any other alternative where I can raise the desired function to power 1/2 and etc.?
The reason you can't raise your poly1d to half-integer power is that that would not be a polynomial, since it would contain square roots.
While in principle you could orthogonalize the functions yourself, or construct the functions from something like sympy.special.legendre, but your safest bet is symbolic math. And hey, we already have sympy.functions.special.polynomials.assoc_legendre! Since symbolic math is slow, you should probably use sympy.lambdify to turn each function into a numerical one:
import sympy as sym
x = sym.symbols('x')
n = 3
m = 1
legfun_sym = sym.functions.special.polynomials.assoc_legendre(n,m,x)
legfun_num = sym.lambdify(x,legfun_sym)
print(legfun_sym)
print(legfun_num)
x0 = 0.25
print(legfun_sym.evalf(subs={x:x0}) - legfun_num(x0))
This prints
-sqrt(-x**2 + 1)*(15*x**2/2 - 3/2)
<function <lambda> at 0x7f0a091976e0>
-1.11022302462516e-16
which seems to make sense (the first is the symbolic function at x, the second shows that lambdify indeed creates a lambda from the function, and the last one is the numerical difference of the two functions at the pseudorandom point x0 = 0.25, and is clearly zero within machine precision).
Let us say I have an equation
x + 2*cos(x) = 0
and I want to solve it. Then I can program the following:
def func1(x):
out = x + 2*cos(x)
return out
Solution = fsolve(func1, StartValue)
StartValue can have an arbitrary value in this example. So far so good! I am programming a simulation that creates a non linear system of equations which I want to solve with fsolve().
The challenge is now that (!) before run time the size of the non linear system of equations is not known (!). This means that I can have for example
x + 2*cos(x) = 0
in the same way as I can have
2*x + 4*y = 0
18*y -18 = 0
In order to solve the last mentioned system of equations (which will generally always be a non linear one in my program) I have found the following solution:
def func2(x):
out = [2*x[0] + 4*x[1]]
out.append(18*x[1]-18)
return out
Solution = fsolve(func2, [1, 1])
This works quite well, too. But there is a certain reason why I cannot use the solution shown for func2(x): It makes my program very slow!
The function fsolve() calls the function func2(x) iteratively several times until it has found the solution [-2 1]. But my program will handle a linear system of equations
of some hundred to thousend rows. This would mean that in every iteration step all those thousends rows are appended as it is shown in func2(x). Therefore I am looking for a solution that ONCE creates the system of equations as a function func3(x) and afterwards fsolve() only calls the ready built func3(x). Here is a PSEUDO CODE example:
func3 = lambda x: 2*x[0] + 4*x[1]
func3.append(lambda x: 18*x[1] - 18)
Solution = fsolve(func3, [1, 1])
Unfortunately, functions cannot be appended as I show it above in my PSEUDO CODE. Therefore my question: How can I dynamically build my function func3 and then pass the (
!) ONCE READY BUILT (!) function func3 to fsolve() ???
Thank you very much in advance
Solution: "outsource the command into a string concetanation"
One can build a string outside the function as follows:
StringCommand = "f = [2*x[0] + 4*x[1], 18*x[1] - 18]"
Afterwards this StringCommand is used as input parameter of the function to be called as follows:
def func(x,StringCommand):
exec StringCommand
return f
Thus, the StringCommand is executed via the command exec. Finally, one just needs to call the function within fsolve() as follows:
fsolve(func, [1, 1], StringCommand)
That's it. Doing it this way, the StringCommand is built once outside the function func() and therefore much time is saved when fsolve() does its iteration with function func(). Note that [1,1] are the start values for the iteration!