Оптимизация Python и Gekko

Я не знаком с оптимизацией и хочу достичь следующей цели:

Предположим, у меня есть 3 списка констант:

list_1 = [1, 2, 3, 4]
list_2 = [5, 8, 10, 11]
list_3 = [20, 27, 89, 100]

Я хочу найти 3 индекса i1, i2, i3, соответствующих 3 спискам выше, так что сумма будет минимизирована: min(list_1[i1] + list_2[i2] + list_3[i3])

с некоторыми ограничениями:

i1 >= 0
i2 >= 0
i3 >= 0
i1 + i2 + i3 == 4
64 * i1 + 72 * i2 + 74 * i3 >= 240

Я попытался написать это как:

from gekko import GEKKO

m = GEKKO()

x_1_storage = m.Array(m.Const, 4)
x_1_values = [1, 2, 3, 4]
i = 0
for xi in x_1_storage:
    xi.value = x_1_values[i]
    i += 1

x_2_storage = m.Array(m.Const, 4)
x_2_values = [5, 8, 10, 11]
i = 0
for xi in x_2_storage:
    xi.value = x_2_values[i]
    i += 1

x_3_storage = m.Array(m.Const, 4)
x_3_values = [20, 27, 89, 100]
i = 0
for xi in x_3_storage:
    xi.value = x_3_values[i]
    i += 1


x,y,z = m.Array(m.Var,3,integer=True,lb=0) 
m.Minimize(x_1_storage[x.value.value] + x_2_storage[y.value.value] + x_3_storage[z.value.value])
m.Equations([x>=0,
             y>=0,
             z>=0,
             x+y+z==4,
             64*x + 72*y + 74*z >= 240])
m.options.SOLVER = 1
m.solve()
print('Objective: ', m.options.OBJFCNVAL)
print('x: ', x.value[0])
print('y: ', y.value[0])
print('z: ', z.value[0])

Однако напечатанное целевое значение равно 26, тогда как правильное целевое значение должно быть равно 4, поскольку x_1_storage[4] = 4. Каким-то образом первый элемент в каждом списке добавляется как целевое значение. У меня сложилось впечатление, что что-то не так с тем, как выражается цель:

m.Minimize(x_1_storage[x.value.value] + x_2_storage[y.value.value] + x_3_storage[z.value.value])

Однако я не совсем уверен, что делать в этом случае. Любая подсказка приветствуется.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Свойство .value предназначено только для хранения начального значения предположения до m.solve() и для сообщения решения после решения. Это будут постоянные значения в задаче оптимизации, если они используются в выражениях.

Решение i1=4 неверно, потому что индекс идет от 0 к 3. Ниже приведена альтернативная форма, которая решает проблему. Объект кубического сплайна cspline используется для связывания переменной решения индекса со значением списка x_store для целевой функции.

from gekko import GEKKO

m = GEKKO(remote=True)

# index decision variable
x = m.Array(m.Var,3,value=4,lb=0,ub=3,integer=True)
i1,i2,i3 = x

# cublic spline
ix = [0,1,2,3]
list_1 = [1, 2, 3, 4]
list_2 = [5, 8, 10, 11]
list_3 = [20, 27, 89, 100]
y = m.Array(m.Var,3)
y1,y2,y3 = y
for i,iy in enumerate([list_1,list_2,list_3]):
    m.cspline(x[i],y[i],ix,iy,bound_x=True)

# constraints
m.Equations([i1+i2+i3==4,
             64 * i1 + 72 * i2 + 74 * i3 >= 240])
             
# objective
m.Minimize(y1+y2+y3)

# solve
m.options.SOLVER = 1
m.solve()

# print solution
print(f'x: {x}')
print(f'y: {y}')
print(f'objective: {m.options.OBJFCNVAL}')

Решение:

x: [[3.0] [1.0] [0.0]]
y: [[4.0] [8.0] [20.0]]
objective: 32.0

Если индекс может находиться в диапазоне от 1 до 4, решение i1=4 неверно, поскольку ограничение i1+i2+i3=4 невозможно, если существуют нижние границы i1>=1, i2>=1 и i3>=1. Если это индекс, основанный на 1, то i2=0 и i3=0 не допускаются.

from gekko import GEKKO

m = GEKKO(remote=False)

# index decision variable
x = m.Array(m.Var,3,lb=1,ub=4,integer=True)
i1,i2,i3 = x

# cublic spline
ix = [1,2,3,4]
list_1 = [1, 2, 3, 4]
list_2 = [5, 8, 10, 11]
list_3 = [20, 27, 89, 100]
y = m.Array(m.Var,3)
y1,y2,y3 = y
for i,iy in enumerate([list_1,list_2,list_3]):
    m.cspline(x[i],y[i],ix,iy,bound_x=True)

# constraints
m.Equations([i1+i2+i3==4,
             64 * i1 + 72 * i2 + 74 * i3 >= 240])
             
# objective
m.Minimize(y1+y2+y3)

# solve
m.options.SOLVER = 1
m.solve()

# print solution
print(f'x: {x}')
print(f'y: {y}')
print(f'objective: {m.options.OBJFCNVAL}')

Решение:

x: [[2.0] [1.0] [1.0]]
y: [[2.0] [5.0] [20.0]]
objective: 27.0

Другие вопросы по теме