问题描述
我是python的新手,由于进行了优化而选择了它,我想学习一些新知识。我已经使用PyQt5和PuLP制作了一个lp解算器程序。这个概念很简单:用户在QTextEdit小部件中输入Lp问题,然后单击“解决”按钮,然后在QTextBrowser中得到结果。
我正在使用并尝试复制的示例练习:
prob = LpProblem("LP problem",LpMaximize)
x1 = LpVariable("x1",lowBound=0,cat='Integer') # Integer variable x1 >= 0
x2 = LpVariable("x2",cat='Integer') # Integer variable x2 >= 0
prob += x2<=4
prob += 4*x1 + 2*x2 <= 20
prob += 1*x1 + 4*x2 <= 12
prob += 4*x1 + 4*x2
prob.solve()
这种方式就像一种魅力。该按钮的功能:
def textToVar(self):
prob = LpProblem("LP problem",LpMaximize)
x1 = LpVariable("x1",cat='Integer') # Integer variable x1 >= 0
x2 = LpVariable("x2",cat='Integer') # Integer variable x2 >= 0
mytext = self.lpInput.toPlainText()
split = mytext.splitlines()
for ele in range(0,len(split)):
prob += split[ele]
prob.solve()
for v in prob.variables():
self.lpOutput.append(str(v.name) + ' = ' + str(v.varValue))
vmax = (value(prob.objective))
self.lpOutput.append('max = ' + str(vmax))
它不起作用,我认为这是因为split = mytext.splitlines()
生成了['x2<=4','4*x1+2*x2<=20','1*x1+4*x2<=12','4*x1+4*x2']
而不是[x2<=4,4*x1+2*x2<=20,1*x1+4*x2<=12,4*x1+4*x2]
。如何将列表从第一个列表转换为第二个列表?也许我可以使用另一种方法将输入存储在列表或变量中,而不是splitlines()
?
提前谢谢!
解决方法
您可以使用exec()
,就像@AirSquid在其评论中指出的那样,但这确实引起了安全问题。另一种方法是解析字符串,因为您知道它们将包含什么。然后,如果出现意外情况,则可以轻松引发错误。
import re
import pulp as pl
x1 = pl.LpVariable("x1",lowBound=0,cat='Integer') # Integer variable x1 >= 0
x2 = pl.LpVariable("x2",cat='Integer') # Integer variable x2 >= 0
def parse_equation(string):
string_parts = re.split("(<=|=|>=)",string)
if len(string_parts) == 1:
# Objective function
return parse_equation_part(string_parts[0])
if len(string_parts) != 3:
raise Exception(f"Unexpected number of parts in {string_parts}")
lhs,comparator,rhs = (
parse_equation_part(string_parts[0]),string_parts[1],parse_equation_part(string_parts[2])
)
if comparator == "<=":
return lhs <= rhs
if comparator == ">=":
return lhs >= rhs
return lhs == rhs
def parse_equation_part(string):
addition_parts = re.split("(\+|-)",string)
result = parse_addition_part(addition_parts.pop(0))
while addition_parts:
symbol,addition_part,addition_parts =\
addition_parts[0],addition_parts[1],addition_parts[2:]
part_result = parse_addition_part(addition_part)
if symbol not in ('+','-'):
raise Exception(f"Unexpected value {symbol}")
if symbol == '-':
result -= part_result
else:
result += part_result
return result
def parse_addition_part(string):
parts = string.split("*")
result = 1
for part in parts:
if part == 'x1':
result *= x1
elif part == 'x2':
result *= x2
elif part.isnumeric():
result *= float(part)
else:
raise Exception(f"Unexpected part {part},expected number or x1/x2")
return result
for s in ['x2>=4','4*x1+2*x2=20','1*x1-4*x2<=12','4*x1+4*x2']:
print(s.ljust(20,' '),'->',parse_equation(s))
收益
x2>=4 -> x2 >= 4.0
4*x1+2*x2=20 -> 4.0*x1 + 2.0*x2 = 20.0
1*x1-4*x2<=12 -> x1 - 4.0*x2 <= 12.0
4*x1+4*x2 -> 4.0*x1 + 4.0*x2