Python新手。
我有一个库函数,它期待一个公式对象;solver.Add(x + y < 5)
然而,我的公式是动态的,由另一个系统作为字符串"x + y < 5"
提供库函数不接受字符串,我的问题是有一种方法来创建一个函数,可以评估我的字符串,并返回公式作为对象?如solver.Add(evaluateFormula("x + y < 5"))
或solver.Add(evaluateFormula("x + y") < 5)
使用内置的eval()
不适合这种类型的公式,因为它试图执行公式,这不是我想做的。
下面是一些完整的示例代码;
from ortools.linear_solver import pywraplp
def main():
# Create the MIP solver BOP/SAT/CBC
solver = pywraplp.Solver.CreateSolver('BOP')
# Sample Input Data
req_json = {
"Variables": [
{
"Name": "x",
"Max": 10
},
{
"Name": "y",
"Max": 5
}
],
"Constraints": [
{
"Name": "c",
"Formula": "x + y < 5"
}
]
}
# Create the variables
v = {}
for i in range(len(req_json['Variables'])):
v[i] = solver.IntVar(0, req_json['Variables'][i]['Max'], req_json['Variables'][i]['Name'])
# Create the constraints
solver.Add(v[0] + v[1] < 5)
# solver.Add(evaluateFormula(req_json['Constraints'][0]['Formula']))
# Maximize
solver.Maximize(v[0] + v[1])
# Solve
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
print('Solution:')
print('Objective value =', solver.Objective().Value())
print('x =', v[0].solution_value())
print('y =', v[1].solution_value())
这个想法是x
和y
是变量,例如,
x = solver.IntVar(0, xmax, 'x')
y = solver.IntVar(0, ymax, 'y')
以便在调用solver.Add(x + y < 5)
时,python将查找名称x
和y
,并将它们替换为它们所对应的对象。即IntVar + IntVar < 5
,它将是一个约束对象。
当你执行eval('x + y < 5')
时,就好像你在执行x + y < 5
,所以你只需要确保名称x
和y
存在于当前作用域中。有两种方法可以实现,即
var = req_json['Variables'][0]
exec('{0} = IntVar(0, {1}, "{0}")'.format(var['Name'], var['Max'])) # first
locals()[var['Name']] = IntVar(0, var['Max'], var['Name']) # second
第一个创建字符串'x = IntVar(0, 10, "x")'
,并将其作为字面python语句执行。而第二个则以编程方式创建IntVar
,然后将其存储在名称x
中。locals()['x'] = 1
相当于x = 1
。
总而言之,解决方案可能是
# You don't need to manually store the variables, as they're added in `solver.variables()`
for var in req_json['Variables']:
name = var['Name']
locals()[name] = solver.IntVar(0, var['Max'], name)
for constraint in req_json['Constraints']:
solver.Add(eval(constraint['Formula']), constraint['Name'])
# However you decide what the expression is to maximise. Whether it's another key
# in your `req_json` dict, or the LHS of the constraint formula. I'll just hardcode this.
solver.Maximize(x + y)
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
print('Solution:')
print('Objective value =', solver.Objective().Value())
for v in solver.variables():
print('{} = {}'.format(v.name(), v.solution_value()))
这假设eval(constraint['Formula'])
永远不会做任何恶意的事情,你说是你的案子。如果你不能保证这一点,你的另一个选择是手动解析字符串的变量名、操作和关系,并建立一个安全的字符串,然后可以求值。
最后,如果你按原样运行,你会得到一个错误,说
ValueError: Operators "<" and ">" not supported with the linear solver
但是如果你将约束公式更改为'x + y <= 5'
,它将正常工作。