Pyomo是一个基于python的开源软件包,它支持多种优化功能,用于制定和分析优化模型。
sympy是一个符号计算的Python库,支持符号计算、高精度计算、模式匹配、绘图、解方程、微积分、组合数学、离散 数学、几何学、概率与统计、物理学等方面的功能。
当我们在pyomo中构建优化问题时,经常需要对某一特定函数进行求导、积分等操作,一般需要手写推导,而Python中恰好有sympy符号运算库来帮我们做这个事情。
sympy中构建一个表达式之后,可以利用subs成员函数将表达式中的特定符号替换为我们想要的东西,代码示例如下
import sympy as sy
x = sy.symbols('x')
y = x**2 + x
y = y.subs(x, 2)
print(y)
结果为6,即
subs函数也支持批量代入,代码示例如下
import sympy as sy
x, y = sy.symbols('x y')
z = x**2 + y**2
z = z.subs([(x, 2), (y, 3)])
print(z)
结果为13,即
但是,pyomo对象组件无法直接代入sympy表达式从而获得pyomo表达式,因为sympy拒绝执行这种未定义的行为。
幸运的是,pyomo中提供了执行上述操作的工具。
首先,我们需要导入下面几个包
from pyomo.environ import *
import sympy as sy
from pyomo.core.expr.sympy_tools import sympy2pyomo_expression, PyomoSympyBimap
pyomo在pyomo.core.expr.sympy_tools中的函数sympy2pyomo_expression就是将sympy表达式转换为pyomo表达式,由于该转换需要用户提供sympy符号与pyomo符号的对应关系,因此需要用户额外构造一个PyomoSympyBimap对象。
现在假设我们有一个sympy表达式
x, y = sy.symbols('x y')
sympy_expr = x**2 + y**2
以及两个pyomo对象
m = ConcreteModel()
m.a = Var()
m.b = Var()
我们现在希望将sympy表达式中的x替换为m.a,y替换为m.b,从而得到形如m.a**2 + m.b**2的pyomo的表达式。
首先,我们需要利用PyomoSympyBimap建立sympy符号与pyomo符号的对应关系
bimap = PyomoSympyBimap()
bimap.sympy2pyomo = {x: m.a, y: m.b}
有了bimap就可以直接完成转换
pyomo_expr = sympy2pyomo_expression(sympy_expr, bimap)
转换后的pyomo_expr就可以直接在pyomo里面用了。
完整代码:
from pyomo.environ import *
import sympy as sy
from pyomo.core.expr.sympy_tools import sympy2pyomo_expression, PyomoSympyBimap
if __name__ == '__main__':
x, y = sy.symbols('x y')
sympy_expr = x ** 2 + y ** 2
m = ConcreteModel()
m.a = Var()
m.b = Var()
bimap = PyomoSympyBimap()
bimap.sympy2pyomo = {x: m.a, y: m.b}
pyomo_expr = sympy2pyomo_expression(sympy_expr, bimap)