这是一个有点困难的问题,因为它需要求解一个带有分母的符号不等式方程组。带有分母的不等式的符号求解很棘手,因为乘以分母可以翻转不等式的符号,具体取决于未知变量的值。单独解决其中一个问题是很困难的……但再加上解决方案不可行,情况会变得更糟。所以,请记住,以下内容有点不稳定......但这可能是您可以直接解决此问题的最佳方法。
>>> def objective(x):
... x0,x1,x2 = x
... return (x0 - 3 - .23)/x0 + (x1 - 1.17 - .23)/x1 + (x2 - 0.71 - .23)/x2
...
>>> def cost(x): # maximize
... return -objective(x)
...
>>> bounds = [(None,.65*2.2),(None,.65*2.9),(None,.65*1.91)]
>>>
>>> equations = '''
... (x0 - 3.00 - .23)/(38000 * x0) >= .05
... (x1 - 1.17 - .23)/(33000 * x1) >= .05
... (x2 - 0.71 - .23)/(29000 * x2) >= .05
... (38000 * x0 + 33000 * x1 + 29000 * x2) / (38000 * (2.2 - x0) + 33000 * (2.9 - x1) + 29000 * (1.91 - x2)) <= -0.5
... (38000 * (2.2 - x0) + 33000 * (2.9 - x1) + 29000 * (1.91 - x2)) / (38000 * x0 + 33000 * x1 + 29000 * x2) >= 0.18
... '''
>>> from mystic.solvers import diffev2
>>> from mystic.symbolic import generate_constraint, generate_solvers, simplify
这应该是问题的根源......现在到了棘手的部分。简化方程,然后求解。
>>> eqn = simplify(equations)
>>> cf = generate_constraint(generate_solvers(eqn))
>>> result = diffev2(cost, x0=bounds, bounds=bounds, constraints=cf, npop=40, gtol=50, disp=True, full_output=True)
Warning: Maximum number of iterations has been exceeded
>>> print(result[1])
inf
我们看到我们得到inf
,这表明mystic
正在遇到一个不可行的解决方案。但是,我正在掩盖上面的一些东西,实际上有点幸运。让我们看一下简化的方程。
>>> print(eqn)
x0 > 0
x0 > -0.868421052631579*x1 - 0.763157894736842*x2 + 6.17605263157895
x2 >= -0.000648723257418910
x1 >= -0.000848999393571862
x0 >= -0.868421052631579*x1 - 0.763157894736842*x2 - 6.17605263157895
x2 < 0
x1 < 0
x0 < -33*x1/38 - 29*x2/38
x0 <= -0.00170089520800421
x0 >= -0.868421052631579*x1 - 0.763157894736842*x2 + 5.23394290811775
如上所述,由于分母和不等式,这只是几个简化方程中的一种可能……它恰好是正确的。我们可以得到所有候选简化方程,如下:
>>> all_eqn = simplify(equations, all=True)
>>> len(all_eqn)
32
请注意,我们有 32 种可能性——其中一些是“好”的,而另一些不是——取决于变量的值。您可以插入all_eqn
,cf = generate_constraint(generate_solvers(all_eqn))
然后mystic
将尽最大努力找到使所有可能的简化方程最小化的解决方案。这通常可以正常工作......而且我确信可能会失败。随着最大化,情况会变得更糟,更重要的是,您正在寻找的解决方案是不可行的。
我要说这是一个积极发展的领域,mystic
可以通过一些改进来更好地处理这样的案例。
编辑:在上面的解决方案中,我忘了使用关键字join
。默认值是join=None
按顺序应用每个方程。虽然这更快,但如果存在冲突的方程式,这不是您想要的。我可能应该使用:
>>> from mystic.constraints import and_
>>> cf = generate_constraint(generate_solvers(eqn), join=and_)
这应该更好地确保所有约束都得到尊重。