NOTE: The information on this page has been copied into the Ipopt documentation.
Optimal Sensitivity Based on IPOPT
This project provides a toolbox that uses NLP sensitivity theory to generate fast approximations to solutions when parameters in the problem change. This toolbox has been developed primarily by Hans Pirnay (RWTH-Aachen), Rodrigo López-Negrete (CMU), and Lorenz Biegler (CMU). If you have problems or questions please email them to the Ipopt mailing list.
Sensitivity of nonlinear programming problems is a key step in any optimization study. Sensitivity provides information on regularity and curvature conditions at KKT points, assesses which variables play dominant roles in the optimization, and provides first order estimates for parametric nonlinear programs. Moreover, for NLP algorithms that use exact second derivatives, sensitivity can be implemented very efficiently within NLP solvers and provide valuable information with very little added computation. This implementation provides IPOPT with the capabilities to calculate sensitivities, and approximate perturbed solutions with them.
The basic sensitivity strategy implemented here is based on the application of the Implicit Function Theorem (IFT) to the KKT conditions of the NLP. As shown by Fiacco (1983), sensitivities can be obtained from a solution with suitable regularity conditions merely by solving a linearization of the KKT conditions. More details can be found in the documentation or in the implementation paper:
- Pirnay, R. Lopez-Negrete, and L.T. Biegler, Optimal Sensitivity based on IPOPT, Math Prog Comp, 4(4):307--331, 2012.
If you are using sIpopt for your research please cite the paper above.
Also, a preprint can be found here.
sIPOPT was developed under the constraint that it must work with the regular IPOPT code. Due to this constraint, some compromises had to be made.
However, there is an ongoing effort to develop sIPOPT 2, which is a fork of the IPOPT code that allows for the explicit definition of parametric NLPs. This code can be found on github. If you have questions about sIPOPT 2, please contact Hans Pirnay.
The ﬁrst step to install the software is to install the trunk version of IPOPT, once this is done installing sIPOPT is very simple. IPOPT’s installation instructions can be found in the IPOPT documentation. Also note that in the following we refer to $IPOPT as the main folder, where the Ipopt/, ThirdParty/, BuildTools/, . . . , folders are located.
If you wish to use the AMPL interface, make sure that your IPOPT installation also includes it. To do this you need to download the ASL library, with the get.ASL script located in $IPOPT/ThirdParty/ASL.
Finally, we assume that you created a build folder to install IPOPT in $IPOPT/build/. In this case, to download the trunk version of IPOPT you would type:
$ svn co https://projects.coin-or.org/svn/Ipopt/trunk $IPOPT
Once IPOPT has been compiled and installed, we can proceed to build sIPOPT. To do this go to the $IPOPT/build/Ipopt/contrib/sIPOPT/ folder, and type make there.
$ cd $IPOPT/build/Ipopt/contrib/sIPOPT $ make
If no errors are shown after compilation you can proceed to install the libraries and to generate the AMPL executable. To do this type
$ make install
This should copy the generated libraries (libsipopt.*) to $IPOPT/build/lib, and the AMPL executable (ipopt_sens) to $IPOPT/build/bin/.
To illustrate the use of the toolbox we solve the following NLP
min x1^2 + x2^2 + x3^2 st 6x1 + 3x2 + 2x3 − p1 = 0 p2 x1 + x2 − x3 − 1 = 0 x1 , x2 , x3 ≥ 0,
and we perturb the parameters p1 and p2 from paT = [p1 p2] = [5 1] to pbT = [4.5 1]. For this case the AMPL code is shown below.
reset ; # Suffixes for sensitivity update suffix sens_state_0, IN; suffix sens_state_1, IN; suffix sens_state_value_1, IN; suffix sens_sol_state_1, OUT; suffix sens_init_constr, IN; suffix sens_sol_state_1_z_U, OUT ; suffix sens_sol_state_1_z_L, OUT ; # Original value of parameters param et1p ; param et2p ; # Original parameter values let et1p := 5 ; let et2p := 1 ; # Define variables, with bounds and initial guess var x1 >= 0, := 0.15 ; var x2 >= 0, := 0.15 ; var x3 >= 0, := 0.00 ; # Artificial variables so IPOPT sees the parameters var et1 ; var et2 ; # objective function minimize objf: x1^2 + x2^2 + x3^2 ; # constraints subject to r1: 6*x1 + 3*x2 + 2*x3 - et1 = 0 ; r2: et2*x1 + x2 - x3 - 1 = 0 ; # Artificial constraints to pass parameters to IPOPT r3: et1 = et1p ; r4: et2 = et2p ; # Define solver and Ampl options in this case we don't want Ampl's # presolve to accidentally remove artificial variables. options solver ipopt_sens ; option presolve 0; # compute sensitivity option ipopt_options "run_sens yes" ; # define an order to the parameters that will change. # In step 0, only et1 changes, and has position 1 let et1.sens_state_0 := 1 ; # in the first step/change et1 has position 1 let et1.sens_state_1 := 1 ; # Perturbed value of parameter et1 (in step 1) let et1.sens_state_value_1 := 4.5 ; # In step 0, et2 has position 1 let et2.sens_state_0 := 2 ; # in the first step/change et1 has position 2 let et2.sens_state_1 := 2 ; # Perturbed value of parameter et2 (in step 1) let et2.sens_state_value_1 := 1 ; # Artificial constraints let r3.sens_init_constr := 1 ; let r4.sens_init_constr := 1 ; # solve problem solve ; #********************************************** # Print nominal solution and bound multipliers #********************************************** display x1, x2, x3, et1, et2 ; display x1.ipopt_zU_out, x2.ipopt_zU_out, x3.ipopt_zU_out, et1.ipopt_zU_out, et2.ipopt_zU_out ; display x1.ipopt_zL_out, x2.ipopt_zL_out, x3.ipopt_zL_out, et1.ipopt_zL_out, et2.ipopt_zL_out ; # Constraint multipliers display r1, r2, r3, r4 ; #************************ # Print updated solution #************************ display x1.sens_sol_state_1, x2.sens_sol_state_1, x3.sens_sol_state_1, et1.sens_sol_state_1, et2.sens_sol_state_1 ; display x1.sens_sol_state_1_z_U, x2.sens_sol_state_1_z_U, x3.sens_sol_state_1_z_U, et1.sens_sol_state_1_z_U, et2.sens_sol_state_1_z_U ; display x1.sens_sol_state_1_z_L, x2.sens_sol_state_1_z_L, x3.sens_sol_state_1_z_L, et1.sens_sol_state_1_z_L, et2.sens_sol_state_1_z_L ; # and updated constraint multipliers display r1.sens_sol_state_1, r2.sens_sol_state_1, r3.sens_sol_state_1, r4.sens_sol_state_1 ;