SymPy is a symbolic mathematics library while SciPy is a numeric mathematics library. SciPy does not understand anything to do with SymPy's symbols and it will only work with numeric values such as floats.
You must try and make every single variable have its own name in order to avoid confusion. That means clearly separating your numeric values of x
with its symbolic values. For example, in func
, you do nothing with your input values x2
and u2
possibly due to this confusion. fm
is a symbolic expression that SciPy does not understand. To get a float from fm
, you need to evaluate it at a point using subs()
.
The second mistake is that SciPy uses functions that take a single tuple input instead of a function with multiple float inputs. You need to separate the inputs yourself within the function.
The third mistake is swapping x2
and u2
between func
, constraint1
and constraint2
. This would cause the conditions' inputs to be swapped which would create a completely different constraint to what you were expecting.
Here is your code with these 3 fixes:
from scipy.optimize import minimize
import sympy as sp
x2_symbol = sp.Symbol('x2')
u2_symbol = sp.Symbol('u2')
fm = 25 * u2_symbol - 20.0 * (sp.sin(x2_symbol)) + 38.7296387 * (sp.cos(x2_symbol)) - 38.7296387
def func(x):
x2_float, u2_float = x
return -fm.subs([(x2_symbol, x2_float), (u2_symbol, u2_float)])
def constraint1(x):
x2_float, u2_float = x
return -u2_float + 40 * sp.sin(x2_float) + 0.2
def constraint2(x):
x2_float, u2_float = x
return -u2_float - 40 * sp.sin(x2_float) + 0.2
b = [-1, 1]
bounds = [b, b]
con1 = {'type': 'ineq', 'fun': constraint1}
con2 = {'type': 'ineq', 'fun': constraint2}
constraints = (con1, con2)
x0 = [0, 0]
solution = minimize(func, x0, method='SLSQP', bounds=bounds, constraints=constraints)
print(solution)
I assume fm
was achieved from a previous solution to another problem and so must contain symbols. If not, this problem could be solved purely numerically with very little change to the code above.
You could also solve this problem purely symbolically using Karush–Kuhn–Tucker conditions. I may post a solution for that if I feel up to it.
lambdify
is the best tool for converting a sympy expression into anumpy
function.func
needs to be validnumpy
, without any sympy symbols or objects. Scipy is built onnumpy
, and "knows" nothing about sympy. - hpaulj