Я полностью делаю это не по назначению ... но вот как я это сделаю с mystic
.
>>> equations = """
... 3.*x0 + 5.*x1 + 7.*x2 + 9.*x3 = 1.*x0 + 2.*x1 + 3.*x3
... """
>>> bounds = [(0,None)]*4
>>>
>>> def objective(x):
... return x[0]**2 + 2*x[1] - 2*x[2] - x[3]**2
...
>>> from mystic.symbolic import generate_penalty, generate_conditions
>>> pf = generate_penalty(generate_conditions(equations))
>>> from mystic.constraints import integers
>>>
>>> @integers()
... def round(x):
... return x
...
>>> from mystic.solvers import diffev2
>>> result = diffev2(objective, x0=bounds, bounds=bounds, penalty=pf, constraints=round, npop=20, gtol=50, disp=True, full_output=True)
Optimization terminated successfully.
Current function value: 0.000000
Iterations: 121
Function evaluations: 2440
>>> result[0]
array([0., 0., 0., 0.])
Теперь немного изменим уравнения ...
>>> equations = """
... 3.*x0 + 5.*x1 + 7.*x2 + 9.*x3 = 5 + 1.*x0 + 2.*x1 + 3.*x3
... """
>>> pf = generate_penalty(generate_conditions(equations))
>>> result = diffev2(objective, x0=bounds, bounds=bounds, penalty=pf, constraints=round, npop=20, gtol=50, disp=True, full_output=True)
Optimization terminated successfully.
Current function value: 3.000000
Iterations: 102
Function evaluations: 2060
>>> result[0]
array([1., 1., 0., 0.])
Если вы хотите, чтобы двоичные переменные вместо целых чисел, вы можете либо использовать bounds = [(0,1)]*4
, либо заменить @integers()
на @discrete([0.0, 1.0])
.
Хотя приведенное выше не слишком интересно для результатаЕсть несколько более продуманных примеров глобальной оптимизации с целочисленным программированием и обобщенными ограничениями на GitHub от Mystic: https://github.com/uqfoundation/mystic/blob/master/examples2/integer_programming.py https://github.com/uqfoundation/mystic/blob/master/examples2/olympic.py