Finding Pyomo provided math functions - python

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.

Related

Using Sympy on methods from the math module

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?

How to avoid RRuntimeError when calling R stats.optim function within python using rpy2?

I am trying to call stats.optim R function within python using rpy2. However, I encountered the following error:
RRuntimeError: Error in (function (par, fn, gr = NULL, ..., method = c("Nelder-Mead", : objective function in optim evaluates to length 0 not 1
I have mostly followed the optim function example from here :
http://rpy.sourceforge.net/rpy2/doc-2.2/html/rinterface.html). See section "Calling Python functions from R"
Here is my code:
from rpy2.robjects import r
import rpy2.robjects as robjects
import rpy2.rinterface as ri
# Function to be optimized, v1 is a 1-dimensional numpy array and m1 is n
# by 3 numpy matrix
def f(beta):
return np.sum(np.square((np.divide(v1,np.matmul(m1,beta))-1)))
# convert python function to R function
r_f = ri.rternalize(f)
Beta = robjects.FloatVector((0,1,0))
res = r.optim(Beta, r_f)
I made sure the function f being defined was correct and could be converted to an r function object. When I call r_f(Beta) for example, it returns a correct result. I am wondering if there is a way to avoid such a problem. I just learnt about rpy2 and any advice is appreciated! Thank you in advance
This is likely because your objective function failing as np, v1, and m1 are not defined.
There is also likely a buglet in rpy2 as the error should normally make their way as warnings of some sort.

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

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