Я не знаком с оптимизацией и хочу достичь следующей цели:
Предположим, у меня есть 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])
Однако я не совсем уверен, что делать в этом случае. Любая подсказка приветствуется.






Свойство .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