Это немного сложная проблема, поскольку она требует решения системы символьных уравнений неравенства со знаменателями.Символическое решение с неравенствами со знаменателями сложно, потому что умножение на знаменатель может перевернуть знак неравенства, в зависимости от значения еще неизвестной переменной.Решить один из них в одиночку сложно ... но если добавить, что решение невыполнимо, это еще хуже.Итак, имейте в виду, что следующее немного шатко ... но это, вероятно, самое лучшее, что вы можете сделать, чтобы непосредственно подойти к этой проблеме.
>>> 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
может использоватьнекоторые улучшения, чтобы лучше обрабатывать подобные случаи.
EDIT: В приведенном выше решении я забыл использовать ключевое слово join
.Значение по умолчанию join=None
, которое применяет каждое уравнение последовательно.Хотя это быстрее, это не то, что вы хотите, если есть противоречивые уравнения.Наверное, мне следовало бы использовать:
>>> from mystic.constraints import and_
>>> cf = generate_constraint(generate_solvers(eqn), join=and_)
, что должно лучше обеспечить соблюдение всех ограничений.