решение системы неравенств, где решение невозможно - PullRequest
0 голосов
/ 28 декабря 2018

Я пытаюсь решить проблему нелинейной оптимизации.Я хотел бы попробовать Mystic, поскольку SciPy.optimize не работает должным образом (более подробная информация приведена ниже).

Optimization problem formulation

Поскольку c_1 = 3, проблема неосуществима.Это потому, что (p_1 - 3 - 0,22) / p_1 <0,05 означает, что значение p_1 должно быть больше 3,22, что будет конфликтовать с p_1 / 2,2 <= 0,65. </p>

Существует без ответа вопрос, касающийся фундаментальной проблемы SciPy, успешно завершающейся из-за невозможных проблем здесь .К сожалению, мне нужно, чтобы эта конкретная проблема была решена с помощью Python, поэтому я снова пытаюсь здесь испытать удачу.

Когда я использовал SciPy.optimize, программа также успешно завершилась, преодолев ограничения без возникновения проблемы (дажепри установке keep_feasible = True).Моя проблема больше, и другие ограничения также не могут быть выполнены.Соответственно, SciPy, похоже, не подходит для этой работы.

Мой первый вопрос: я что-то не так делаю?Если нет: есть ли альтернативы SciPy.optimize?Я также изучал мистику, но не смог заставить ее работать вообще.

Я знаю, что это довольно специфическая проблема, поэтому я благодарю всех, кто хочет скинуться. Наконец, мои извиненияесли я оскорблял математиков, возможно, неправильной формулировкой задачи.

1 Ответ

0 голосов
/ 02 января 2019

Это немного сложная проблема, поскольку она требует решения системы символьных уравнений неравенства со знаменателями.Символическое решение с неравенствами со знаменателями сложно, потому что умножение на знаменатель может перевернуть знак неравенства, в зависимости от значения еще неизвестной переменной.Решить один из них в одиночку сложно ... но если добавить, что решение невыполнимо, это еще хуже.Итак, имейте в виду, что следующее немного шатко ... но это, вероятно, самое лучшее, что вы можете сделать, чтобы непосредственно подойти к этой проблеме.

>>> 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_)

, что должно лучше обеспечить соблюдение всех ограничений.

...