1
votes

I'm solving a non-linear optimization problem with Gekko in a loop and want to use the prior solution to initialize the next solution. I've created a simplified the problem with the code below to show the issue.

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))

The console prints:

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

The values of x1 and x2 return to the initial guesses of 1 and 5 before the "Solve again" attempt. I tried x1.value = x1.value but this returns RecursionError: maximum recursion depth exceeded. What is the right way to initialize values from a prior solution in Gekko?

1

1 Answers

2
votes

For steady state solutions (IMODE=1 or 3), Gekko uses the prior x1.value and x2.value until they are changed. The .value has two properties: .value and .change. There are multiple ways to signal that they have changed including:

  1. Set the values from the prior solution with:
x1.value = x1.value.value  # = 2.8284271334
x2.value = x2.value.value  # = 1.4142135667
  1. Signal that the initial guess value should change to the new value with:
x1.value.change = True
x2.value.change = True

This is easy with two variables but it is more challenging with many variables. If you want to automate this for all of your variables, you could use the built-in list of variables in a loop with 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))

The second time it solves the problem, the solver finishes in 1 iteration instead of 5 iterations. It is using the prior solution as the starting point.

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