Как уже сказал новичок, используйте linprog, если ваша целевая функция и ваши ограничения линейны.В случае, если ваши ограничения являются линейными, а целевая функция - нет, вы должны использовать метод минимизации, подобный следующему:
minimize(obj_fun, x0=xinit, bounds=bnds, constraints=cons)
, где obj_fun
- ваша целевая функция, xinit
начальная точка,bnds
список кортежей для границ ваших переменных и cons
список диктов.
Вот пример.Предполагая, что вы хотите
Поскольку все ограничения являются линейными, мы можем записать его как A * x> = b, где A - матрица 3x2 иb вектор правой стороны 3x1:
import numpy as np
from scipy.optimize import minimize
obj_fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2
A = np.array([[1, -2], [-1, -2], [-1, 2]])
b = np.array([-2, -6, -2])
bnds = [(0, None) for i in range(A.shape[1])] # x_1 >= 0, x_2 >= 0
xinit = [0, 0]
Теперь осталось только определить ограничения, каждое из которых должно быть в форме
{"type": "ineq", "fun": constr_fun}
, где constr_fun
является вызываемой функцией, такой, что constr_fun> = 0. Для первого ограничения это будет
{"type": "ineq", "fun": lambda x: x[0] - 2* x[1] + 2}
Поскольку оно работает так же для других, вы можете определить
cons = [{'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + 2},
{'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6},
{'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2}]
и все будет готовоВ качестве альтернативы вы можете передать все ограничения непосредственно с помощью векторной функции (настоятельно рекомендуется в случае множества ограничений):
cons = [{"type": "ineq", "fun": lambda x: A @ x - b}]
Обратите внимание, что @
является оператором матричного умножения (доступно только с Python3.5)и я предположил, что все ограничения являются ограничениями неравенства.
Вызов
res = minimize(obj_fun, x0=xinit, bounds=bnds, constraints=cons)
print(res)
output
fun: 0.799999999999998
jac: array([ 0.79999999, -1.59999999])
message: 'Optimization terminated successfully.'
nfev: 16
nit: 4
njev: 4
status: 0
success: True
x: array([1.39999999, 1.69999999])
Редактировать: Чтобы ответить на ваш новый вопрос:
# b1 <= A * x <==> -b1 >= -A*x <==> A*x - b1 >= 0
# A * x <= b2 <==> A*x - b2 <= 0 <==> -Ax + b2 >= 0
cons = [{"type": "ineq", "fun": lambda x: A @ x - b1}, {"type": "ineq", "fun": lambda x: -A @ x + b2}]
sol=minimize(obj,x0,constraints=cons)
print(sol)