Как повторно инициализировать оптимизацию в Python Gekko из предыдущего решения - PullRequest
1 голос
/ 06 июня 2019

Я решаю задачу нелинейной оптимизации с помощью Gekko в цикле и хочу использовать предыдущее решение для инициализации следующего решения. Я создал упрощенную проблему с кодом ниже, чтобы показать проблему.

from gekko import GEKKO
m = GEKKO() # Initialize gekko
# Initialize variables
x1 = m.Var(value=1,lb=1,ub=5)
x2 = m.Var(value=5,lb=1,ub=5)
# Equations
m.Equation(x1==x2*2)
m.Equation(x1**2+x2**2==10)
m.Obj(x1*x2) # Objective
m.options.solver=1

m.solve(disp=False) # Solve
print('Iterations: ' + str(m.options.iterations))
print(x1.value[0], x2.value[0])
print('Objective: ' + str(m.options.objfcnval))

m.solve(disp=False) # Solve again
print('Iterations: ' + str(m.options.iterations))
print(x1.value[0], x2.value[0])
print('Objective: ' + str(m.options.objfcnval))

Консоль печатает:

  Iterations: 5
  2.8284271334 1.4142135667
  Objective: 4.0000000245
  Iterations: 5
  2.8284271334 1.4142135667
  Objective: 4.0000000245

Значения x1 и x2 возвращаются к начальным догадкам 1 и 5 до попытки «Решить снова». Я пытался x1.value = x1.value, но это возвращает RecursionError: maximum recursion depth exceeded. Как правильно инициализировать значения из предыдущего решения в Gekko?

1 Ответ

1 голос
/ 06 июня 2019

Для решений в устойчивом состоянии (IMODE = 1 или 3) Gekko использует предыдущие x1.value и x2.value до тех пор, пока они не будут изменены. .value имеет два свойства: .value и .change. Есть несколько способов сообщить, что они изменились, в том числе:

  1. Установите значения из предыдущего решения с помощью:
x1.value = x1.value.value  # = 2.8284271334
x2.value = x2.value.value  # = 1.4142135667
  1. Сигнал о том, что начальное значение догадки должно измениться на новое значение с помощью:
x1.value.change = True
x2.value.change = True

Это легко с двумя переменными, но сложнее со многими переменными. Если вы хотите автоматизировать это для всех ваших переменных, вы можете использовать встроенный список переменных в цикле с vi in m._variables:

from gekko import GEKKO
m = GEKKO() # Initialize gekko
# Initialize variables
x1 = m.Var(value=1,lb=1,ub=5)
x2 = m.Var(value=5,lb=1,ub=5)
# Equations
m.Equation(x1==x2*2)
m.Equation(x1**2+x2**2==10)
m.Obj(x1*x2) # Objective
m.options.solver=1

m.solve(disp=False) # Solve
print('Iterations: ' + str(m.options.iterations))
print(x1.value[0], x2.value[0])
print('Objective: ' + str(m.options.objfcnval))

for vi in m._variables:
    vi.value.change = True

m.solve(disp=False) # Solve again
print('Iterations: ' + str(m.options.iterations))
print(x1.value[0], x2.value[0])
print('Objective: ' + str(m.options.objfcnval))

Во второй раз, когда он решает проблему, решатель завершает 1 итерацию вместо 5 итераций. В качестве отправной точки используется предыдущее решение.

  Iterations: 5
  2.8284271334 1.4142135667
  Objective: 4.0000000245
  Iterations: 1
  2.8284271247 1.4142135624
  Objective: 4.0
...