Using Sympy on methods from the math module - python

As part of a wider plotting program I have a script where there is a function f defined as a lambda expression, and I need to find its derivative. My code for testing the script is:
import math
import sympy as sym
f = lambda x : math.sin(x)
sx = sym.symbols('x')
sf = sym.diff(f(sx), sx)
print(sf)
While this works fine when f is defined without using any outside methods, the above throws TypeError: can't convert expression to float because the math module's methods don't support the symbolic representations used by Sympy. However, while this works when f instead uses sym.sin, because of how the aforementioned program is structured the definition of f cannot be changed. Is there a way to symbolically interpret the math module's methods?

Related

How do you make lambda a symbol when importing all Sympy functions?

If I import sympy with:
from sympy import *
Then how do set lambda to be a symbol and not a function?
E.g.
lambda = symbols('lambda')
In my case, likely because sympy has all its functions imported (I am working in a sympy only environment so it is convenient), I receive the error:
lambda = symbols('lambda')
^
SyntaxError: invalid syntax
Is there any way to avoid this if I am importing all the functions from sympy?
Thank you
This is because lambda is a keyword for creating lambda functions. You can't use it as your variable name. You'll have to find a new name. Even if you find a way to assign lambda to something, it won't work because it's not parsed as a potential variable name.
For example:
lambda_ = symbols('lambda')
will not have the same error.

Could I find a variable in the bessel function in python?

I am using Python to solve an equation. I added the 'Bessel function' in scipy.special, It was working. Now I want to find a variable using Bessel function. For example, I added the order(1) and value(0.44005058574) in Python, but it is not working. (in order to find the variable, I also used solver)
How I can solve the problem?
import numpy as np
import scipy.special as sc
import math
from sympy import Symbol
from sympy.solvers import solve
x=Symbol('x')
y=sc.jn(1,x)-0.44005058574
print(solve(x))
As the output is hinting, the function scipy.special.jn does not know how to handle the object x from simpy. Instead, you should use a numerical approach
>>> from scipy import optimize
>>> f = lambda x: sc.jn(1, x) - 0.44005058574
>>> root = optimize.newton(f, 1.0)
>>> print(root)
0.9999999999848267

Finding Pyomo provided math functions

In Pyomo I want to solve the following minimization problem, which matches the playback rate and timing of two audio files:
import pyomo
from pyomo.environ import *
from pyomo.opt import SolverFactory
import soundfile as sf
import math
import numpy
#Create Model:
model = ConcreteModel()
#Declare Variables:
model.P = Var(initialize = 1, within=PositiveReals, bounds = (0.5,2))
model.T = Var(initialize = 0, within=Reals, bounds = (-500,500))
#Objective function:
def shift(data,rate,t,point):
Y=numpy.zeros(len(data))
for i in range(len(data)):
for j in range(point):
if math.floor(i*rate+t-j+point/2)>=0 and math.floor(i*rate+t-j+point/2)<=len(data)-1:
Y[i]+=data[math.floor(i*rate+t-j+point/2)]*numpy.sinc((math.floor(i*rate+t)-i*rate-t)-(j-point/2))
return Y
def obj_fun(model):
#Read data from audiofile:
Audio1, samplerate = sf.read('C:/Audio1.wav')
Audio2, samplerate = sf.read('C:/Audio2.wav')
Audio1=Audio1[:,0]
Audio2=Audio2[:,0]
Audio2= numpy.pad(Audio2,(0,len(Audio1)-len(Audio2)),'constant', constant_values=(0, 0))
return -1*numpy.sum(shift(Audio2,model.P,model.T,4)*Audio1)
#Create obj function:
model.obj = Objective(rule=obj_fun, sense=1)
The problem is the following error:
TypeError: Implicit conversion of Pyomo NumericValue type `<class 'pyomo.core.base.expr_coopr3._SumExpression'>' to a float is
disabled. This error is often the result of using Pyomo components as
arguments to one of the Python built-in math module functions when
defining expressions. Avoid this error by using Pyomo-provided math
functions.
The solver can't function unless numpy's/math's sinc and floor functions are changed. However, in Pyomo's documentation there is no reference to Pyomo-provided functions. What do I change the standard sinc/floor functions with in order to get the model object created without errors?
Also I am wondering whether there is a smarter way to read the data into the model. As of now, it's unnecessarily read on every pass of the objective function.
Pyomo provided intrinsic functions (sin, log, etc.) are automatically imported with the line from pyomo.environ import *. The problem is that you are importing math after that line which overwrites Pyomo's intrinsic functions with the ones from the math library. The solution is to remove the math import statement entirely or to move the math import statement above the pyomo import statement.

How can I override the __str__ method of sympy.core.numbers.Float?

I am trying to overcome the flaws of sub-classing Python's float by using a different class hierarchy of numbers. However the following code:
from sympy import *
import sympy.core.numbers
f = 1.123456789
n = N(f, 8)
print n
print type(n)
sympy.core.numbers.Float.__str__ = lambda f: "{:.8f}".format(f)
print n
yields the error:
AttributeError: 'module' object has no attribute 'numbers'
How can I overcome this?
This does what you need:
Code:
from sympy.core.numbers import Float
Float.__str__ = lambda f: "{:.8f}".format(float(f))
Test Code:
from sympy import N
from sympy.core.numbers import Float
f = 1.123456789
n = N(f, 8)
Float.__str__ = lambda f: "{:.8f}".format(float(f))
print n
Results:
1.12345679
Monkeypatching __str__ is bad practice in this situation, as SymPy already has a built in way to modify how SymPy objects are printed, by subclassing the printers. Here I've taken and modified the original sympy.printing.str.StrPrinter._print_Float.
from sympy.printing.str import StrPrinter
class MyStrPrinter(StrPrinter)
def _print_Float(self, expr):
return '{:.8f}'.format(expr)
Then use MyStrPrinter().doprint instead of str. You can also make str itself use this by using
from sympy import init_printing
init_printing(pretty_print=False, str_printer=MyStrPrinter().doprint)
Due to some bad name choices, the sympy.core.core submodule gets imported over the "real" sympy.core subpackage, so attempting to access sympy.core gets you sympy.core.core, and attempting to access sympy.core.numbers gets you an AttributeError.
There are a number of ways you can work around this. SymPy provides access to the class you want as sympy.Float, for example:
import sympy
do_whatever_with(sympy.Float)

Converting a function from sympy to numpy (attribute error)

import numpy as np
import sympy as sym
from numpy import sin
from sympy import symbols, diff
func = lambda x: sin(x)
x = symbols('x')
print diff(func(x),x)
This works if I replace my function with a polynomial, or if I place the trig function directly into the diff operator. But in this format I get AttributeError: sin.
Basically I think python can't recognize func as just being a trig function which it knows how to symbolically integrate. I could just have sympy import sin and then things would work, but then I'm stuck with func referencing sin in the sympy namespace and there are future things I want to do with func which require that it be defined using sin in the numpy namespace.
You should build your expression up symbolically using SymPy functions, and then use lambdify to convert them into things that can be evaluated with NumPy.
This simply isn't how you use sympy. You can't use normal functions in conjunction with numpy--you need to build symbolic expressions using the stuff it provides.
To write code to get the derivative of sin(x), you would do
import sympy as sym
from sympy import sin, symbols, diff
x = symbols('x')
print diff(sin(x), x)
If you have some other particular case you're having trouble with, you'll have to show it. You can't mix sympy with non-sympy stuff in this way, so there isn't some general feedback that can be provided.

Categories