I would like to get the value of the variables at each iteration of the optimization process when using Python GEKKO.
For example, the following code from the documentation (https://gekko.readthedocs.io/en/latest/quick_start.html#example) solves problem HS71:
from gekko import GEKKO import numpy as np m = GEKKO(remote=False) x = m.Array(m.Var, 4, value=1, lb=1, ub=5) x1, x2, x3, x4 = x # rename variables x2.value = 5; x3.value = 5 # change guess m.Equation(np.prod(x) >= 25) # prod>=25 m.Equation(m.sum([xi**2 for xi in x]) == 40) # sum=40 m.Minimize(x1*x4*(x1 + x2 + x3) + x3) # objective m.solve() print(x, m.options.OBJFCNVAL)
The output displayed in the console is the following:
---------------------------------------------------------------- APMonitor, Version 1.0.0 APMonitor Optimization Suite ---------------------------------------------------------------- --------- APM Model Size ------------ Each time step contains Objects : 1 Constants : 0 Variables : 10 Intermediates: 0 Connections : 5 Equations : 7 Residuals : 7 Number of state variables: 10 Number of total equations: - 7 Number of slack variables: - 1 --------------------------------------- Degrees of freedom : 2 ********************************************** Steady State Optimization with Interior Point Solver ********************************************** Info: Exact Hessian ****************************************************************************** This program contains Ipopt, a library for large-scale nonlinear optimization. Ipopt is released as open source code under the Eclipse Public License (EPL). For more information visit http://projects.coin-or.org/Ipopt ****************************************************************************** This is Ipopt version 3.10.2, running with linear solver mumps. Number of nonzeros in equality constraint Jacobian...: 19 Number of nonzeros in inequality constraint Jacobian.: 0 Number of nonzeros in Lagrangian Hessian.............: 10 Total number of variables............................: 10 variables with only lower bounds: 1 variables with lower and upper bounds: 4 variables with only upper bounds: 0 Total number of equality constraints.................: 7 Total number of inequality constraints...............: 0 inequality constraints with only lower bounds: 0 inequality constraints with lower and upper bounds: 0 inequality constraints with only upper bounds: 0 iter objective inf_pr inf_du lg(mu) ||d|| lg(rg) alpha_du alpha_pr ls 0 1.6109693e+001 4.00e+001 5.24e-001 0.0 0.00e+000 - 0.00e+000 0.00e+000 0 1 1.6896037e+001 7.28e-001 7.82e-001 -0.9 4.00e+001 - 1.00e+000 1.00e+000h 1 2 1.7121828e+001 1.66e-001 6.51e-001 -1.1 2.15e+000 - 8.23e-001 1.00e+000h 1 3 1.6954231e+001 1.60e-001 6.46e-002 -2.1 6.34e-001 - 1.00e+000 1.00e+000h 1 4 1.7008327e+001 1.68e-002 1.22e-002 -2.9 3.39e-001 - 9.94e-001 1.00e+000h 1 5 1.7013921e+001 3.15e-004 1.47e-004 -4.6 3.56e-002 - 1.00e+000 1.00e+000h 1 6 1.7014017e+001 2.51e-007 4.50e-007 -10.5 5.56e-004 - 9.99e-001 1.00e+000h 1 Number of Iterations....: 6 (scaled) (unscaled) Objective...............: 1.7014017181012623e+001 1.7014017181012623e+001 Dual infeasibility......: 4.5045555432827566e-007 4.5045555432827566e-007 Constraint violation....: 2.5086595754315365e-007 2.5086595754315365e-007 Complementarity.........: 4.8294565936715572e-008 4.8294565936715572e-008 Overall NLP error.......: 4.5045555432827566e-007 4.5045555432827566e-007 Number of objective function evaluations = 7 Number of objective gradient evaluations = 7 Number of equality constraint evaluations = 7 Number of inequality constraint evaluations = 0 Number of equality constraint Jacobian evaluations = 7 Number of inequality constraint Jacobian evaluations = 0 Number of Lagrangian Hessian evaluations = 6 Total CPU secs in IPOPT (w/o function evaluations) = 0.014 Total CPU secs in NLP function evaluations = 0.000 EXIT: Optimal Solution Found. The solution was found. The final value of the objective function is 17.014017181012623 --------------------------------------------------- Solver : IPOPT (v3.12) Solution time : 0.021100000000000008 sec Objective : 17.014017181012623 Successful solution --------------------------------------------------- [[1.0000000339] [4.7429996271] [3.8211500196] [1.3794082228]] 17.014017181
This includes the value of the objective function at each iteration, but I would also like to get the value of the variables (x
) at each iteration.
Advertisement
Answer
The solvers don’t have call-backs to Python. One way to get the values at each iteration is to call the solver multiple times with a max_iter
(maximum iteration) limit and report the values until the solver is successful. Use debug=0
to not raise an exception with an unsuccessful solution.
from gekko import GEKKO import numpy as np max_iter = 0 while True: m = GEKKO(remote=False) x = m.Array(m.Var, 4, value=1, lb=1, ub=5) x1, x2, x3, x4 = x # rename variables x2.value = 5; x3.value = 5 # change guess m.Equation(np.prod(x) >= 25) # prod>=25 m.Equation(m.sum([xi**2 for xi in x]) == 40) # sum=40 m.Minimize(x1*x4*(x1 + x2 + x3) + x3) # objective m.options.MAX_ITER = max_iter m.solve(disp=False,debug=0) print(max_iter,x, m.options.OBJFCNVAL) if m.options.APPSTATUS==1: # break loop with successful solution break else: # increment maximum iterations max_iter += 1
Here is the iteration summary with iteration number, variable values x
, and objective function value. The objective function may get worse (higher) because the equations are not yet satisfied, and the solution may be infeasible.
0 [[1.00999999] [4.960000049] [4.960000049] [1.00999999]] 16.109692918 1 [[1.1256700056] [4.4664784656] [4.2706611878] [1.1371887857]] 16.896036995 2 [[1.1003048073] [4.6596383632] [3.9630056459] [1.2300025937]] 17.121828401 3 [[1.0211678027] [4.7139849665] [3.8710712025] [1.3337143994]] 16.954231463 4 [[1.0027660895] [4.740529129] [3.8261434464] [1.3737295983]] 17.008327097 5 [[1.0000616664] [4.7429670916] [3.8212258627] [1.3792900699]] 17.013920783 6 [[1.0000000339] [4.7429996271] [3.8211500196] [1.3794082228]] 17.014017181
If you have a large model that you don’t want to redefine multiple times, then just put the m.solve()
function in a loop with m.options.COLDSTART=1
.
from gekko import GEKKO import numpy as np m = GEKKO(remote=False) x = m.Array(m.Var, 4, value=1, lb=1, ub=5) x1, x2, x3, x4 = x # rename variables x2.value = 5; x3.value = 5 # change guess m.Equation(np.prod(x) >= 25) # prod>=25 m.Equation(m.sum([xi**2 for xi in x]) == 40) # sum=40 m.Minimize(x1*x4*(x1 + x2 + x3) + x3) # objective max_iter = 0 while True: m.options.MAX_ITER = max_iter m.options.COLDSTART=1 m.solve(disp=False,debug=0) print(max_iter,x, m.options.OBJFCNVAL) if m.options.APPSTATUS==1: # break loop with successful solution break else: # increment maximum iterations max_iter += 1