Я должен получить min и max y для линейного выражения, ограниченного некоторыми линейными неравенствами в python.

Здесь вы можете увидеть уравнения и неравенства, которые я ввел в Desmos:

3x+12y = 1000
x > 30
x < 160
y < 60
y > 10
x + y > 180

Desmos equation + inequalities

Я могу решить их вручную, нарисовав и вычеркнув неравенства. Но я не могу сделать это в Python. В Python я до сих пор пытался получить y = 83,33 при x = 0; х = 333,33 при у = 0; После получения min и max x, y я затем применяю неравенства 1 на 1. Но к каждому неравенству я должен добавить предыдущие, а также проверить, прошел ли x или y определенный диапазон и так далеко, и это почти уверен, что я пропущу проверку.

Я посмотрел на numpy и sympy, но не мог понять, как решить это, используя их. Можете ли вы предложить, что / как я могу использовать, чтобы получить диапазон, который белая стрелка показывает на картинке?

3
random12231 24 Фев 2018 в 22:49

3 ответа

Лучший ответ

Ваша проблема в линейном программировании, где ваши равенства и неравенства являются ограничениями, и вы хотите минимизировать (а затем и максимизировать) выражение y. Равенство, неравенства и выражения являются линейными, что делает его линейным программированием. Пакет scipy, использующий функцию scipy.optimize.linprog, может выполнять такое линейное программирование.

Вот закомментированный код, чтобы делать то, что вы хотите. Обратите внимание, что все неравенства были немного изменены, чтобы включить равенство, которое необходимо, чтобы максимальное или минимальное значение y. Чтобы найти максимальное значение y, код вместо этого находит минимальное значение -y, а затем печатает аддитивную обратную величину, поскольку linprog минимизирует целевую функцию. Наконец, ограничения неравенства должны быть «меньше или равны» в linprog, поэтому я умножил обе части вашего неравенства x + y > 180 на -1, чтобы получить единицу, а именно -x + -y <= -180 , Спросите, если у вас есть какие-либо вопросы.

from scipy.optimize import linprog

# Set up values relating to both minimum and maximum values of y
coefficients_inequalities = [[-1, -1]]  # require -1*x + -1*y <= -180
constants_inequalities = [-180]
coefficients_equalities = [[3, 12]]  # require 3*x + 12*y = 1000
constants_equalities = [1000]
bounds_x = (30, 160)  # require 30 <= x <= 160
bounds_y = (10, 60)  # require 10 <= y <= 60

# Find and print the minimal value of y
coefficients_min_y = [0, 1]  # minimize 0*x + 1*y
res = linprog(coefficients_min_y,
              A_ub=coefficients_inequalities,
              b_ub=constants_inequalities,
              A_eq=coefficients_equalities,
              b_eq=constants_equalities,
              bounds=(bounds_x, bounds_y))
print('Minimum value of y =', res.fun)

# Find and print the maximal value of y = minimal value of -y
coefficients_max_y = [0, -1]  # minimize 0*x + -1*y
res = linprog(coefficients_max_y,
              A_ub=coefficients_inequalities,
              b_ub=constants_inequalities,
              A_eq=coefficients_equalities,
              b_eq=constants_equalities,
              bounds=(bounds_x, bounds_y))
print('Maximum value of y =', -res.fun)  # opposite of value of -y

Распечатка из этого кода

Minimum value of y = 43.3333333333
Maximum value of y = 51.1111111111

Что правильно с точностью до плавающей запятой. Если вам нужны соответствующие значения x, посмотрите значение res.x, которое представляет собой массив, который дает значения как x, так и y в нужной точке - { {X4}} равен res.x[0], а y равен res.x[1].

3
Rory Daulton 25 Фев 2018 в 21:56

Вы можете попробовать cvxpy. Это решение для выпуклых задач, поэтому оно может быть излишним для ваших нужд. Мне нравится, как легко закодировать вашу проблему с ним. Большинство других библиотек требуют, чтобы вы закодировали свою проблему в несколько матриц.

0
Jacques Kvam 25 Фев 2018 в 03:06

Следуя подсказке, приведенной в комментарии, вы можете решить свою проблему, используя scipy.optimize.linprog следующим образом ...

In [1]: import numpy as np

In [2]: from scipy import optimize

In [3]: c = np.zeros(2)

In [4]: A_ub = np.array([[-1, -1]])

In [5]: b_ub = np.array([-180])

In [6]: A_eq = np.array([[3, 12]])

In [7]: b_eq = np.array([1000])

In [8]: bounds = [(30, 160), (10, 60)]

In [9]: optimize.linprog(c, A_ub, b_ub, A_eq, b_eq, bounds, method="simplex")
Out[11]: 
     fun: -0.0
 message: 'Optimization terminated successfully.'
     nit: 5
   slack: array([ 31.11111111,  98.88888889,   0.        ,  41.11111111,   8.88888889])
  status: 0
 success: True
       x: array([ 128.88888889,   51.11111111])

Хитрость заключается в том, чтобы отметить, что решение системы уравнений может быть выражено как задача оптимизации с постоянной нулевой целевой функцией. Вот почему я установил c=np.zeros(2) выше.

0
davidrpugh 25 Фев 2018 в 02:40