1#![allow(clippy::too_many_lines, clippy::approx_constant)]
13
14use pounce_common::exception::SolverException;
15use pounce_common::reg_options::RegisteredOptions;
16
17pub fn register_all_upstream_options(r: &RegisteredOptions) -> Result<(), SolverException> {
18 r.set_registering_category("Output");
20 r.add_bounded_integer_option("print_level", "Output verbosity level.", 0, 12, 5, "Sets the default verbosity level for console output. The larger this value the more detailed is the output.")?;
21 r.add_string_option("output_file", "File name of desired output file (leave unset for no file output).", "", &[("*", "Any acceptable standard file name")], "NOTE: This option only works when read from the ipopt.opt options file! An output file with this name will be written (leave unset for no file output). The verbosity level is by default set to \"print_level\", but can be overridden with \"file_print_level\". The file name is changed to use only small letters.")?;
22 r.add_bounded_integer_option("file_print_level", "Verbosity level for output file.", 0, 12, 5, "NOTE: This option only works when read from the ipopt.opt options file! Determines the verbosity level for the file specified by \"output_file\". By default it is the same as \"print_level\".")?;
23 r.add_bool_option(
24 "file_append",
25 "Whether to append to output file, if set, instead of truncating.",
26 false,
27 "NOTE: This option only works when read from the ipopt.opt options file!",
28 )?;
29 r.add_bool_option("print_user_options", "Print all options set by the user.", false, "If selected, the algorithm will print the list of all options set by the user including their values and whether they have been used. In some cases this information might be incorrect, due to the internal program flow.")?;
30 r.add_bool_option("print_options_documentation", "Switch to print all algorithmic options with some documentation before solving the optimization problem.", false, "")?;
31 r.add_bounded_integer_option("debug_print_level", "Verbosity level for debug file.", 0, 12, 5, "This Ipopt library has been compiled in debug mode, and a file \"debug.out\" is produced for every run. This option determines the verbosity level for this file. By default it is the same as \"print_level\".")?;
32 r.add_bool_option("print_timing_statistics", "Switch to print timing statistics.", false, "If selected, the program will print the time spend for selected tasks. This implies timing_statistics=yes.")?;
33 r.set_registering_category("Miscellaneous");
34 r.add_string_option("option_file_name", "File name of options file.", "ipopt.opt", &[("*", "Any acceptable standard file name")], "By default, the name of the Ipopt options file is \"ipopt.opt\" - or something else if specified in the IpoptApplication::Initialize call. If this option is set by SetStringValue BEFORE the options file is read, it specifies the name of the options file. It does not make any sense to specify this option within the options file. Setting this option to an empty string disables reading of an options file.")?;
35 r.add_bool_option(
36 "replace_bounds",
37 "Whether all variable bounds should be replaced by inequality constraints",
38 false,
39 "This option must be set for the inexact algorithm.",
40 )?;
41 r.add_bool_option("skip_finalize_solution_call", "Whether a call to NLP::FinalizeSolution after optimization should be suppressed", false, "In some Ipopt applications, the user might want to call the FinalizeSolution method separately. Setting this option to \"yes\" will cause the IpoptApplication object to suppress the default call to that method.")?;
42 r.set_registering_category("Undocumented");
43 r.add_bool_option("suppress_all_output", "", false, "")?;
44 r.add_bool_option(
45 "inexact_algorithm",
46 "Whether to activate the version of Ipopt that allows iterative linear solvers.",
47 false,
48 "EXPERIMENTAL",
49 )?;
50 r.set_registering_category("");
51
52 r.set_registering_category("Output");
54 r.add_string_option(
55 "print_options_mode",
56 "format in which to print options documentation",
57 "text",
58 &[
59 ("text", "Ordinary text"),
60 ("latex", "LaTeX formatted"),
61 ("doxygen", "Doxygen (markdown) formatted"),
62 ],
63 "",
64 )?;
65 r.add_bool_option(
66 "print_advanced_options",
67 "whether to print also advanced options",
68 false,
69 "",
70 )?;
71
72 r.set_registering_category("NLP");
74 r.add_number_option(
75 "nlp_lower_bound_inf",
76 "any bound less or equal this value will be considered -inf (i.e. not lower bounded).",
77 -1e19,
78 "",
79 )?;
80 r.add_number_option(
81 "nlp_upper_bound_inf",
82 "any bound greater or this value will be considered +inf (i.e. not upper bounded).",
83 1e19,
84 "",
85 )?;
86 r.add_string_option("fixed_variable_treatment", "Determines how fixed variables should be handled.", "make_parameter", &[("make_parameter", "Remove fixed variable from optimization variables"), ("make_parameter_nodual", "Remove fixed variable from optimization variables and do not compute bound multipliers for fixed variables"), ("make_constraint", "Add equality constraints fixing variables"), ("relax_bounds", "Relax fixing bound constraints")], "The main difference between those options is that the starting point in the \"make_constraint\" case still has the fixed variables at their given values, whereas in the case \"make_parameter(_nodual)\" the functions are always evaluated with the fixed values for those variables. Also, for \"relax_bounds\", the fixing bound constraints are relaxed (according to\" bound_relax_factor\"). For all but \"make_parameter_nodual\", bound multipliers are computed for the fixed variables.")?;
87 r.add_bool_option("dependency_detection_with_rhs", "Indicates if the right hand sides of the constraints should be considered in addition to gradients during dependency detection", false, "")?;
89 r.add_lower_bounded_integer_option("num_linear_variables", "Number of linear variables", 0, 0, "When the Hessian is approximated, it is assumed that the first num_linear_variables variables are linear. The Hessian is then not approximated in this space. If the get_number_of_nonlinear_variables method in the TNLP is implemented, this option is ignored.")?;
90 r.add_string_option(
91 "jacobian_approximation",
92 "Specifies technique to compute constraint Jacobian",
93 "exact",
94 &[
95 ("exact", "user-provided derivatives"),
96 (
97 "finite-difference-values",
98 "user-provided structure, values by finite differences",
99 ),
100 ],
101 "",
102 )?;
103 r.add_string_option(
104 "gradient_approximation",
105 "Specifies technique to compute objective Gradient",
106 "exact",
107 &[
108 ("exact", "user-provided gradient"),
109 ("finite-difference-values", "values by finite differences"),
110 ],
111 "",
112 )?;
113 r.add_lower_bounded_number_option(
114 "findiff_perturbation",
115 "Size of the finite difference perturbation for derivative approximation.",
116 0.0,
117 true,
118 1e-7,
119 "This determines the relative perturbation of the variable entries.",
120 )?;
121 r.set_registering_category("Derivative Checker");
122 r.add_string_option("derivative_test", "Enable derivative checker", "none", &[("none", "do not perform derivative test"), ("first-order", "perform test of first derivatives at starting point"), ("second-order", "perform test of first and second derivatives at starting point"), ("only-second-order", "perform test of second derivatives at starting point")], "If this option is enabled, a (slow!) derivative test will be performed before the optimization. The test is performed at the user provided starting point and marks derivative values that seem suspicious")?;
123 r.add_lower_bounded_integer_option("derivative_test_first_index", "Index of first quantity to be checked by derivative checker", -2, -2, "If this is set to -2, then all derivatives are checked. Otherwise, for the first derivative test it specifies the first variable for which the test is done (counting starts at 0). For second derivatives, it specifies the first constraint for which the test is done; counting of constraint indices starts at 0, and -1 refers to the objective function Hessian.")?;
124 r.add_lower_bounded_number_option(
125 "derivative_test_perturbation",
126 "Size of the finite difference perturbation in derivative test.",
127 0.0,
128 true,
129 1e-8,
130 "This determines the relative perturbation of the variable entries.",
131 )?;
132 r.add_lower_bounded_number_option("derivative_test_tol", "Threshold for indicating wrong derivative.", 0.0, true, 1e-4, "If the relative deviation of the estimated derivative from the given one is larger than this value, the corresponding derivative is marked as wrong.")?;
133 r.add_bool_option(
134 "derivative_test_print_all",
135 "Indicates whether information for all estimated derivatives should be printed.",
136 false,
137 "Determines verbosity of derivative checker.",
138 )?;
139 r.add_lower_bounded_number_option("point_perturbation_radius", "Maximal perturbation of an evaluation point.", 0.0, false, 10.0, "If a random perturbation of a points is required, this number indicates the maximal perturbation. This is for example used when determining the center point at which the finite difference derivative test is executed.")?;
140 r.add_string_option("dependency_detector", "Indicates which linear solver should be used to detect linearly dependent equality constraints.", "none", &[("none", "don't check; no extra work at beginning"), ("mumps", "use MUMPS"), ("wsmp", "use WSMP"), ("ma28", "use MA28")], "This is experimental and does not work well.")?;
141
142 r.set_registering_category("Barrier Parameter Update");
144 r.add_lower_bounded_number_option("mu_max_fact", "Factor for initialization of maximum value for barrier parameter.", 0.0, true, 1e3, "This option determines the upper bound on the barrier parameter. This upper bound is computed as the average complementarity at the initial point times the value of this option. (Only used if option \"mu_strategy\" is chosen as \"adaptive\".)")?;
145 r.add_lower_bounded_number_option("mu_max", "Maximum value for barrier parameter.", 0.0, true, 1e5, "This option specifies an upper bound on the barrier parameter in the adaptive mu selection mode. If this option is set, it overwrites the effect of mu_max_fact. (Only used if option \"mu_strategy\" is chosen as \"adaptive\".)")?;
146 r.add_lower_bounded_number_option("mu_min", "Minimum value for barrier parameter.", 0.0, true, 1e-11, "This option specifies the lower bound on the barrier parameter in the adaptive mu selection mode. By default, it is set to the minimum of 1e-11 and min(\"tol\",\"compl_inf_tol\")/(\"barrier_tol_factor\"+1), which should be a reasonable value. (Only used if option \"mu_strategy\" is chosen as \"adaptive\".)")?;
147 r.set_registering_category("Undocumented");
148 r.add_lower_bounded_number_option("adaptive_mu_safeguard_factor", "", 0.0, false, 0.0, "")?;
149 r.set_registering_category("");
150 r.add_string_option("adaptive_mu_globalization", "Globalization strategy for the adaptive mu selection mode.", "obj-constr-filter", &[("kkt-error", "nonmonotone decrease of kkt-error"), ("obj-constr-filter", "2-dim filter for objective and constraint violation"), ("never-monotone-mode", "disables globalization")], "To achieve global convergence of the adaptive version, the algorithm has to switch to the monotone mode (Fiacco-McCormick approach) when convergence does not seem to appear. This option sets the criterion used to decide when to do this switch. (Only used if option \"mu_strategy\" is chosen as \"adaptive\".)")?;
151 r.add_lower_bounded_integer_option("adaptive_mu_kkterror_red_iters", "Maximum number of iterations requiring sufficient progress.", 0, 4, "For the \"kkt-error\" based globalization strategy, sufficient progress must be made for \"adaptive_mu_kkterror_red_iters\" iterations. If this number of iterations is exceeded, the globalization strategy switches to the monotone mode.")?;
152 r.add_bounded_number_option("adaptive_mu_kkterror_red_fact", "Sufficient decrease factor for \"kkt-error\" globalization strategy.", 0.0, true, 1.0, true, 0.9999, "For the \"kkt-error\" based globalization strategy, the error must decrease by this factor to be deemed sufficient decrease.")?;
153 r.add_bounded_number_option("filter_margin_fact", "Factor determining width of margin for obj-constr-filter adaptive globalization strategy.", 0.0, true, 1.0, true, 1e-5, "When using the adaptive globalization strategy, \"obj-constr-filter\", sufficient progress for a filter entry is defined as follows: (new obj) < (filter obj) - filter_margin_fact*(new constr-viol) OR (new constr-viol) < (filter constr-viol) - filter_margin_fact*(new constr-viol). For the description of the \"kkt-error-filter\" option see \"filter_max_margin\".")?;
154 r.add_lower_bounded_number_option(
155 "filter_max_margin",
156 "Maximum width of margin in obj-constr-filter adaptive globalization strategy.",
157 0.0,
158 true,
159 1.0,
160 "",
161 )?;
162 r.add_bool_option("adaptive_mu_restore_previous_iterate", "Indicates if the previous accepted iterate should be restored if the monotone mode is entered.", false, "When the globalization strategy for the adaptive barrier algorithm switches to the monotone mode, it can either start from the most recent iterate (no), or from the last iterate that was accepted (yes).")?;
163 r.add_lower_bounded_number_option("adaptive_mu_monotone_init_factor", "Determines the initial value of the barrier parameter when switching to the monotone mode.", 0.0, true, 0.8, "When the globalization strategy for the adaptive barrier algorithm switches to the monotone mode and fixed_mu_oracle is chosen as \"average_compl\", the barrier parameter is set to the current average complementarity times the value of \"adaptive_mu_monotone_init_factor\".")?;
164 r.add_string_option("adaptive_mu_kkt_norm_type", "Norm used for the KKT error in the adaptive mu globalization strategies.", "2-norm-squared", &[("1-norm", "use the 1-norm (abs sum)"), ("2-norm-squared", "use the 2-norm squared (sum of squares)"), ("max-norm", "use the infinity norm (max)"), ("2-norm", "use 2-norm")], "When computing the KKT error for the globalization strategies, the norm to be used is specified with this option. Note, this option is also used in the QualityFunctionMuOracle.")?;
165
166 r.set_registering_category("");
168 r.set_registering_category("Linear Solver");
169 r.add_string_option(
172 "hsllib",
173 "Name of library containing HSL routines for load at runtime",
174 "libhsl.so",
175 &[("*", "Any acceptable filename (may contain path, too)")],
176 "",
177 )?;
178 r.add_string_option("pardisolib", "Name of library containing Pardiso routines (from pardiso-project.org) for load at runtime", "libpardiso.so", &[("*", "Any acceptable filename (may contain path, too)")], "")?;
179 r.set_registering_category("NLP Scaling");
180 r.set_registering_category("Barrier Parameter Update");
182 r.add_string_option(
183 "mu_strategy",
184 "Update strategy for barrier parameter.",
185 "monotone",
186 &[
187 ("monotone", "use the monotone (Fiacco-McCormick) strategy"),
188 ("adaptive", "use the adaptive update strategy"),
189 ],
190 "Determines which barrier parameter update strategy is to be used.",
191 )?;
192 r.add_string_option("mu_oracle", "Oracle for a new barrier parameter in the adaptive strategy.", "quality-function", &[("probing", "Mehrotra's probing heuristic"), ("loqo", "LOQO's centrality rule"), ("quality-function", "minimize a quality function")], "Determines how a new barrier parameter is computed in each \"free-mode\" iteration of the adaptive barrier parameter strategy. (Only considered if \"adaptive\" is selected for option \"mu_strategy\").")?;
193 r.add_string_option("fixed_mu_oracle", "Oracle for the barrier parameter when switching to fixed mode.", "average_compl", &[("probing", "Mehrotra's probing heuristic"), ("loqo", "LOQO's centrality rule"), ("quality-function", "minimize a quality function"), ("average_compl", "base on current average complementarity")], "Determines how the first value of the barrier parameter should be computed when switching to the \"monotone mode\" in the adaptive strategy. (Only considered if \"adaptive\" is selected for option \"mu_strategy\".)")?;
194 r.set_registering_category("Hessian Approximation");
195 r.add_string_option(
196 "limited_memory_aug_solver",
197 "Strategy for solving the augmented system for low-rank Hessian.",
198 "sherman-morrison",
199 &[
200 ("sherman-morrison", "use Sherman-Morrison formula"),
201 ("extended", "use an extended augmented system"),
202 ],
203 "",
204 )?;
205 r.set_registering_category("Line Search");
206 r.add_string_option("line_search_method", "Globalization method used in backtracking line search", "filter", &[("filter", "Filter method"), ("cg-penalty", "Chen-Goldfarb penalty function"), ("penalty", "Standard penalty function")], "Only the \"filter\" choice is officially supported. But sometimes, good results might be obtained with the other choices.")?;
207 r.set_registering_category("Undocumented");
208 r.add_bool_option(
209 "wsmp_iterative",
210 "Switches to use iterative instead of direct solver in WSMP.",
211 false,
212 "EXPERIMENTAL!",
213 )?;
214 r.add_string_option("linear_solver", "Linear solver used for step computations.", "ma57", &[("ma27", "use the Harwell routine MA27"), ("ma57", "use the Harwell routine MA57"), ("ma77", "use the Harwell routine HSL_MA77"), ("ma86", "use the Harwell routine HSL_MA86"), ("ma97", "use the Harwell routine HSL_MA97"), ("pardiso", "use the Pardiso package from pardiso-project.org"), ("pardisomkl", "use the Pardiso package from Intel MKL"), ("spral", "use the SPRAL package"), ("wsmp", "use WSMP package"), ("mumps", "use MUMPS package"), ("custom", "use custom linear solver (expert use)"), ("feral", "use FERAL pure-Rust sparse symmetric solver (pounce extension)")], "Determines which linear algebra package is to be used for the solution of the augmented linear system (for obtaining the search directions).")?;
215 r.add_string_option("linear_system_scaling", "Method for scaling the linear system.", "none", &[("none", "no scaling will be performed"), ("mc19", "use the Harwell routine MC19"), ("slack-based", "use the slack values")], "Determines the method used to compute symmetric scaling factors for the augmented system (see also the \"linear_scaling_on_demand\" option). This scaling is independent of the NLP problem scaling.")?;
216 r.add_string_option("nlp_scaling_method", "Select the technique used for scaling the NLP.", "gradient-based", &[("none", "no problem scaling will be performed"), ("user-scaling", "scaling parameters will come from the user"), ("gradient-based", "scale the problem so the maximum gradient at the starting point is nlp_scaling_max_gradient"), ("equilibration-based", "scale the problem so that first derivatives are of order 1 at random points (uses Harwell routine MC19)")], "Selects the technique used for scaling the problem internally before it is solved. For user-scaling, the parameters come from the NLP.")?;
217
218 r.set_registering_category("Line Search");
220 r.add_bounded_number_option("alpha_red_factor", "Fractional reduction of the trial step size in the backtracking line search.", 0.0, true, 1.0, true, 0.5, "At every step of the backtracking line search, the trial step size is reduced by this factor.")?;
221 r.set_registering_category("Undocumented");
222 r.add_bool_option(
223 "magic_steps",
224 "Enables magic steps.",
225 false,
226 "DOESN'T REALLY WORK YET!",
227 )?;
228 r.set_registering_category("");
229 r.add_bool_option("accept_every_trial_step", "Always accept the first trial step.", false, "Setting this option to \"yes\" essentially disables the line search and makes the algorithm take aggressive steps, without global convergence guarantees.")?;
230 r.add_lower_bounded_integer_option("accept_after_max_steps", "Accept a trial point after maximal this number of steps even if it does not satisfy line search conditions.", -1, -1, "Setting this to -1 disables this option.")?;
231 r.add_string_option(
232 "alpha_for_y",
233 "Method to determine the step size for constraint multipliers (alpha_y) .",
234 "primal",
235 &[
236 ("primal", "use primal step size"),
237 (
238 "bound-mult",
239 "use step size for the bound multipliers (good for LPs)",
240 ),
241 ("min", "use the min of primal and bound multipliers"),
242 ("max", "use the max of primal and bound multipliers"),
243 ("full", "take a full step of size one"),
244 (
245 "min-dual-infeas",
246 "choose step size minimizing new dual infeasibility",
247 ),
248 (
249 "safer-min-dual-infeas",
250 "like \"min_dual_infeas\", but safeguarded by \"min\" and \"max\"",
251 ),
252 (
253 "primal-and-full",
254 "use the primal step size, and full step if delta_x <= alpha_for_y_tol",
255 ),
256 (
257 "dual-and-full",
258 "use the dual step size, and full step if delta_x <= alpha_for_y_tol",
259 ),
260 ("acceptor", "Call LSAcceptor to get step size for y"),
261 ],
262 "",
263 )?;
264 r.add_lower_bounded_number_option("alpha_for_y_tol", "Tolerance for switching to full equality multiplier steps.", 0.0, false, 10.0, "This is only relevant if \"alpha_for_y\" is chosen \"primal-and-full\" or \"dual-and-full\". The step size for the equality constraint multipliers is taken to be one if the max-norm of the primal step is less than this tolerance.")?;
265 r.add_lower_bounded_number_option("tiny_step_tol", "Tolerance for detecting numerically insignificant steps.", 0.0, false, 10.0 * f64::EPSILON, "If the search direction in the primal variables (x and s) is, in relative terms for each component, less than this value, the algorithm accepts the full step without line search. If this happens repeatedly, the algorithm will terminate with a corresponding exit message. The default value is 10 times machine precision.")?;
266 r.add_lower_bounded_number_option("tiny_step_y_tol", "Tolerance for quitting because of numerically insignificant steps.", 0.0, false, 1e-2, "If the search direction in the primal variables (x and s) is, in relative terms for each component, repeatedly less than tiny_step_tol, and the step in the y variables is smaller than this threshold, the algorithm will terminate.")?;
267 r.add_lower_bounded_integer_option("watchdog_shortened_iter_trigger", "Number of shortened iterations that trigger the watchdog.", 0, 10, "If the number of successive iterations in which the backtracking line search did not accept the first trial point exceeds this number, the watchdog procedure is activated. Choosing \"0\" here disables the watchdog procedure.")?;
268 r.add_lower_bounded_integer_option("watchdog_trial_iter_max", "Maximum number of watchdog iterations.", 1, 3, "This option determines the number of trial iterations allowed before the watchdog procedure is aborted and the algorithm returns to the stored point.")?;
269 r.set_registering_category("Restoration Phase");
270 r.add_bool_option("expect_infeasible_problem", "Enable heuristics to quickly detect an infeasible problem.", false, "This options is meant to activate heuristics that may speed up the infeasibility determination if you expect that there is a good chance for the problem to be infeasible. In the filter line search procedure, the restoration phase is called more quickly than usually, and more reduction in the constraint violation is enforced before the restoration phase is left. If the problem is square, this option is enabled automatically.")?;
271 r.add_lower_bounded_number_option("expect_infeasible_problem_ctol", "Threshold for disabling \"expect_infeasible_problem\" option.", 0.0, false, 1e-3, "If the constraint violation becomes smaller than this threshold, the \"expect_infeasible_problem\" heuristics in the filter line search are disabled. If the problem is square, this options is set to 0.")?;
272 r.add_lower_bounded_number_option("expect_infeasible_problem_ytol", "Multiplier threshold for activating \"expect_infeasible_problem\" option.", 0.0, true, 1e8, "If the max norm of the constraint multipliers becomes larger than this value and \"expect_infeasible_problem\" is chosen, then the restoration phase is entered.")?;
273 r.add_bool_option("start_with_resto", "Whether to switch to restoration phase in first iteration.", false, "Setting this option to \"yes\" forces the algorithm to switch to the feasibility restoration phase in the first iteration. If the initial point is feasible, the algorithm will abort with a failure.")?;
274 r.add_lower_bounded_number_option("soft_resto_pderror_reduction_factor", "Required reduction in primal-dual error in the soft restoration phase.", 0.0, false, 1.0 - 1e-4, "The soft restoration phase attempts to reduce the primal-dual error with regular steps. If the damped primal-dual step (damped only to satisfy the fraction-to-the-boundary rule) is not decreasing the primal-dual error by at least this factor, then the regular restoration phase is called. Choosing \"0\" here disables the soft restoration phase.")?;
275 r.add_lower_bounded_integer_option("max_soft_resto_iters", "Maximum number of iterations performed successively in soft restoration phase.", 0, 10, "If the soft restoration phase is performed for more than so many iterations in a row, the regular restoration phase is called.")?;
276
277 r.set_registering_category("Line Search");
279 r.add_lower_bounded_number_option("theta_max_fact", "Determines upper bound for constraint violation in the filter.", 0.0, true, 1e4, "The algorithmic parameter theta_max is determined as theta_max_fact times the maximum of 1 and the constraint violation at initial point. Any point with a constraint violation larger than theta_max is unacceptable to the filter (see Eqn. (21) in the implementation paper).")?;
280 r.add_lower_bounded_number_option("theta_min_fact", "Determines constraint violation threshold in the switching rule.", 0.0, true, 1e-4, "The algorithmic parameter theta_min is determined as theta_min_fact times the maximum of 1 and the constraint violation at initial point. The switching rule treats an iteration as an h-type iteration whenever the current constraint violation is larger than theta_min (see paragraph before Eqn. (19) in the implementation paper).")?;
281 r.add_bounded_number_option(
282 "eta_phi",
283 "Relaxation factor in the Armijo condition.",
284 0.0,
285 true,
286 0.5,
287 true,
288 1e-8,
289 "See Eqn. (20) in the implementation paper.",
290 )?;
291 r.add_lower_bounded_number_option(
292 "delta",
293 "Multiplier for constraint violation in the switching rule.",
294 0.0,
295 true,
296 1.0,
297 "See Eqn. (19) in the implementation paper.",
298 )?;
299 r.add_lower_bounded_number_option(
300 "s_phi",
301 "Exponent for linear barrier function model in the switching rule.",
302 1.0,
303 true,
304 2.3,
305 "See Eqn. (19) in the implementation paper.",
306 )?;
307 r.add_lower_bounded_number_option(
308 "s_theta",
309 "Exponent for current constraint violation in the switching rule.",
310 1.0,
311 true,
312 1.1,
313 "See Eqn. (19) in the implementation paper.",
314 )?;
315 r.add_bounded_number_option(
316 "gamma_phi",
317 "Relaxation factor in the filter margin for the barrier function.",
318 0.0,
319 true,
320 1.0,
321 true,
322 1e-8,
323 "See Eqn. (18a) in the implementation paper.",
324 )?;
325 r.add_bounded_number_option(
326 "gamma_theta",
327 "Relaxation factor in the filter margin for the constraint violation.",
328 0.0,
329 true,
330 1.0,
331 true,
332 1e-5,
333 "See Eqn. (18b) in the implementation paper.",
334 )?;
335 r.add_bounded_number_option(
336 "alpha_min_frac",
337 "Safety factor for the minimal step size (before switching to restoration phase).",
338 0.0,
339 true,
340 1.0,
341 true,
342 0.05,
343 "This is gamma_alpha in Eqn. (23) in the implementation paper.",
344 )?;
345 r.add_lower_bounded_integer_option("max_soc", "Maximum number of second order correction trial steps at each iteration.", 0, 4, "Choosing 0 disables the second order corrections. This is p^{max} of Step A-5.9 of Algorithm A in the implementation paper.")?;
346 r.add_lower_bounded_number_option("kappa_soc", "Factor in the sufficient reduction rule for second order correction.", 0.0, true, 0.99, "This option determines how much a second order correction step must reduce the constraint violation so that further correction steps are attempted. See Step A-5.9 of Algorithm A in the implementation paper.")?;
347 r.add_lower_bounded_number_option("obj_max_inc", "Determines the upper bound on the acceptable increase of barrier objective function.", 1.0, true, 5.0, "Trial points are rejected if they lead to an increase in the barrier objective function by more than obj_max_inc orders of magnitude.")?;
348 r.add_lower_bounded_integer_option("max_filter_resets", "Maximal allowed number of filter resets", 0, 5, "A positive number enables a heuristic that resets the filter, whenever in more than \"filter_reset_trigger\" successive iterations the last rejected trial steps size was rejected because of the filter. This option determine the maximal number of resets that are allowed to take place.")?;
349 r.add_lower_bounded_integer_option("filter_reset_trigger", "Number of iterations that trigger the filter reset.", 1, 5, "If the filter reset heuristic is active and the number of successive iterations in which the last rejected trial step size was rejected because of the filter, the filter is reset.")?;
350 r.add_string_option("corrector_type", "The type of corrector steps that should be taken.", "none", &[("none", "no corrector"), ("affine", "corrector step towards mu=0"), ("primal-dual", "corrector step towards current mu")], "If \"mu_strategy\" is \"adaptive\", this option determines what kind of corrector steps should be tried. Changing this option is experimental.")?;
351 r.add_bool_option("skip_corr_if_neg_curv", "Whether to skip the corrector step in negative curvature iteration.", true, "The corrector step is not tried if negative curvature has been encountered during the computation of the search direction in the current iteration. This option is only used if \"mu_strategy\" is \"adaptive\". Changing this option is experimental.")?;
352 r.add_bool_option("skip_corr_in_monotone_mode", "Whether to skip the corrector step during monotone barrier parameter mode.", true, "The corrector step is not tried if the algorithm is currently in the monotone mode (see also option \"barrier_strategy\"). This option is only used if \"mu_strategy\" is \"adaptive\". Changing this option is experimental.")?;
353 r.add_lower_bounded_number_option("corrector_compl_avrg_red_fact", "Complementarity tolerance factor for accepting corrector step.", 0.0, true, 1.0, "This option determines the factor by which complementarity is allowed to increase for a corrector step to be accepted. Changing this option is experimental.")?;
354 r.add_bounded_integer_option("soc_method", "Ways to apply second order correction", 0, 1, 0, "This option determines the way to apply second order correction, 0 is the method described in the implementation paper. 1 is the modified way which adds alpha on the rhs of x and s rows.")?;
355
356 r.set_registering_category("Line Search");
358 r.add_lower_bounded_number_option(
359 "nu_init",
360 "Initial value of the penalty parameter.",
361 0.0,
362 true,
363 1e-6,
364 "",
365 )?;
366 r.add_lower_bounded_number_option(
367 "nu_inc",
368 "Increment of the penalty parameter.",
369 0.0,
370 true,
371 1e-4,
372 "",
373 )?;
374 r.add_bounded_number_option(
375 "rho",
376 "Value in penalty parameter update formula.",
377 0.0,
378 true,
379 1.0,
380 true,
381 1e-1,
382 "",
383 )?;
384
385 r.set_registering_category("NLP Scaling");
387 r.add_number_option("obj_scaling_factor", "Scaling factor for the objective function.", 1.0, "This option sets a scaling factor for the objective function. The scaling is seen internally by Ipopt but the unscaled objective is reported in the console output. If additional scaling parameters are computed (e.g. user-scaling or gradient-based), both factors are multiplied. If this value is chosen to be negative, Ipopt will maximize the objective function instead of minimizing it.")?;
388
389 r.set_registering_category("NLP Scaling");
391 r.add_lower_bounded_number_option("nlp_scaling_max_gradient", "Maximum gradient after NLP scaling.", 0.0, true, 100.0, "This is the gradient scaling cut-off. If the maximum gradient is above this value, then gradient based scaling will be performed. Scaling parameters are calculated to scale the maximum gradient back to this value. (This is g_max in Section 3.8 of the implementation paper.) Note: This option is only used if \"nlp_scaling_method\" is chosen as \"gradient-based\".")?;
392 r.add_lower_bounded_number_option("nlp_scaling_obj_target_gradient", "Target value for objective function gradient size.", 0.0, false, 0.0, "If a positive number is chosen, the scaling factor for the objective function is computed so that the gradient has the max norm of the given size at the starting point. This overrides nlp_scaling_max_gradient for the objective function.")?;
393 r.add_lower_bounded_number_option("nlp_scaling_constr_target_gradient", "Target value for constraint function gradient size.", 0.0, false, 0.0, "If a positive number is chosen, the scaling factors for the constraint functions are computed so that the gradient has the max norm of the given size at the starting point. This overrides nlp_scaling_max_gradient for the constraint functions.")?;
394 r.add_lower_bounded_number_option("nlp_scaling_min_value", "Minimum value of gradient-based scaling values.", 0.0, false, 1e-8, "This is the lower bound for the scaling factors computed by gradient-based scaling method. If some derivatives of some functions are huge, the scaling factors will otherwise become very small, and the (unscaled) final constraint violation, for example, might then be significant. Note: This option is only used if \"nlp_scaling_method\" is chosen as \"gradient-based\".")?;
395
396 r.set_registering_category("");
398 r.set_registering_category("Line Search");
399 r.add_lower_bounded_number_option("kappa_sigma", "Factor limiting the deviation of dual variables from primal estimates.", 0.0, true, 1e10, "If the dual variables deviate from their primal estimates, a correction is performed. See Eqn. (16) in the implementation paper. Setting the value to less than 1 disables the correction.")?;
400 r.add_string_option("recalc_y", "Tells the algorithm to recalculate the equality and inequality multipliers as least square estimates.", "no", &[("no", "use the Newton step to update the multipliers"), ("yes", "use least-square multiplier estimates")], "This asks the algorithm to recompute the multipliers, whenever the current infeasibility is less than recalc_y_feas_tol. Choosing yes might be helpful in the quasi-Newton option. However, each recalculation requires an extra factorization of the linear system. If a limited memory quasi-Newton option is chosen, this is used by default.")?;
401 r.add_lower_bounded_number_option("recalc_y_feas_tol", "Feasibility threshold for recomputation of multipliers.", 0.0, true, 1e-6, "If recalc_y is chosen and the current infeasibility is less than this value, then the multipliers are recomputed.")?;
402 r.set_registering_category("Step Calculation");
403 r.add_bool_option("mehrotra_algorithm", "Indicates whether to do Mehrotra's predictor-corrector algorithm.", false, "If enabled, line search is disabled and the (unglobalized) adaptive mu strategy is chosen with the \"probing\" oracle, and \"corrector_type=affine\" is used without any safeguards; you should not set any of those options explicitly in addition. Also, unless otherwise specified, the values of \"bound_push\", \"bound_frac\", and \"bound_mult_init_val\" are set more aggressive, and sets \"alpha_for_y=bound_mult\". The Mehrotra's predictor-corrector algorithm works usually very well for LPs and convex QPs.")?;
404 r.set_registering_category("Undocumented");
405 r.add_bool_option(
406 "sb",
407 "whether to skip printing Ipopt copyright banner",
408 false,
409 "",
410 )?;
411 r.set_registering_category("Miscellaneous");
412 r.add_bool_option(
413 "timing_statistics",
414 "Indicates whether to measure time spend in components of Ipopt and NLP evaluation",
415 false,
416 "The overall algorithm time is unaffected by this option.",
417 )?;
418
419 r.set_registering_category("");
421 r.set_registering_category("Termination");
422 r.add_lower_bounded_number_option("tol", "Desired convergence tolerance (relative).", 0.0, true, 1e-8, "Determines the convergence tolerance for the algorithm. The algorithm terminates successfully, if the (scaled) NLP error becomes smaller than this value, and if the (absolute) criteria according to \"dual_inf_tol\", \"constr_viol_tol\", and \"compl_inf_tol\" are met. This is epsilon_tol in Eqn. (6) in implementation paper. See also \"acceptable_tol\" as a second termination criterion. Note, some other algorithmic features also use this quantity to determine thresholds etc.")?;
423
424 r.set_registering_category("");
426 r.set_registering_category("Termination");
427 r.add_lower_bounded_number_option(
428 "s_max",
429 "Scaling threshold for the NLP error.",
430 0.0,
431 true,
432 100.0,
433 "See paragraph after Eqn. (6) in the implementation paper.",
434 )?;
435 r.set_registering_category("NLP");
436 r.add_lower_bounded_number_option(
437 "kappa_d",
438 "Weight for linear damping term (to handle one-sided bounds).",
439 0.0,
440 false,
441 1e-5,
442 "See Section 3.7 in implementation paper.",
443 )?;
444 r.set_registering_category("Line Search");
445 r.add_lower_bounded_number_option("slack_move", "Correction size for very small slacks.", 0.0, false, (f64::EPSILON).powf(0.75), "Due to numerical issues or the lack of an interior, the slack variables might become very small. If a slack becomes very small compared to machine precision, the corresponding bound is moved slightly. This parameter determines how large the move should be. Its default value is mach_eps^{3/4}. See also end of Section 3.5 in implementation paper - but actual implementation might be somewhat different.")?;
446 r.add_string_option("constraint_violation_norm_type", "Norm to be used for the constraint violation in the line search.", "1-norm", &[("1-norm", "use the 1-norm"), ("2-norm", "use the 2-norm"), ("max-norm", "use the infinity norm")], "Determines which norm should be used when the algorithm computes the constraint violation in the line search.")?;
447
448 r.set_registering_category("Hessian Approximation");
450 r.add_lower_bounded_integer_option("limited_memory_max_history", "Maximum size of the history for the limited quasi-Newton Hessian approximation.", 0, 6, "This option determines the number of most recent iterations that are taken into account for the limited-memory quasi-Newton approximation.")?;
451 r.add_string_option(
452 "limited_memory_update_type",
453 "Quasi-Newton update formula for the limited memory quasi-Newton approximation.",
454 "bfgs",
455 &[
456 ("bfgs", "BFGS update (with skipping)"),
457 ("sr1", "SR1 (not working well)"),
458 ],
459 "",
460 )?;
461 r.add_string_option("limited_memory_initialization", "Initialization strategy for the limited memory quasi-Newton approximation.", "scalar1", &[("scalar1", "sigma = s^Ty/s^Ts"), ("scalar2", "sigma = y^Ty/s^Ty"), ("scalar3", "arithmetic average of scalar1 and scalar2"), ("scalar4", "geometric average of scalar1 and scalar2"), ("constant", "sigma = limited_memory_init_val")], "Determines how the diagonal Matrix B_0 as the first term in the limited memory approximation should be computed.")?;
462 r.add_lower_bounded_number_option("limited_memory_init_val", "Value for B0 in low-rank update.", 0.0, true, 1.0, "The starting matrix in the low rank update, B0, is chosen to be this multiple of the identity in the first iteration (when no updates have been performed yet), and is constantly chosen as this value, if \"limited_memory_initialization\" is \"constant\".")?;
463 r.add_lower_bounded_number_option("limited_memory_init_val_max", "Upper bound on value for B0 in low-rank update.", 0.0, true, 1e8, "The starting matrix in the low rank update, B0, is chosen to be this multiple of the identity in the first iteration (when no updates have been performed yet), and is constantly chosen as this value, if \"limited_memory_initialization\" is \"constant\".")?;
464 r.add_lower_bounded_number_option("limited_memory_init_val_min", "Lower bound on value for B0 in low-rank update.", 0.0, true, 1e-8, "The starting matrix in the low rank update, B0, is chosen to be this multiple of the identity in the first iteration (when no updates have been performed yet), and is constantly chosen as this value, if \"limited_memory_initialization\" is \"constant\".")?;
465 r.add_lower_bounded_integer_option("limited_memory_max_skipping", "Threshold for successive iterations where update is skipped.", 1, 2, "If the update is skipped more than this number of successive iterations, the quasi-Newton approximation is reset.")?;
466 r.add_bool_option("limited_memory_special_for_resto", "Determines if the quasi-Newton updates should be special during the restoration phase.", false, "Until Nov 2010, Ipopt used a special update during the restoration phase, but it turned out that this does not work well. The new default uses the regular update procedure and it improves results. If for some reason you want to get back to the original update, set this option to \"yes\".")?;
467
468 r.set_registering_category("Barrier Parameter Update");
470 r.add_lower_bounded_number_option("mu_init", "Initial value for the barrier parameter.", 0.0, true, 0.1, "This option determines the initial value for the barrier parameter (mu). It is only relevant in the monotone, Fiacco-McCormick version of the algorithm. (i.e., if \"mu_strategy\" is chosen as \"monotone\")")?;
471 r.add_lower_bounded_number_option("barrier_tol_factor", "Factor for mu in barrier stop test.", 0.0, true, 10.0, "The convergence tolerance for each barrier problem in the monotone mode is the value of the barrier parameter times \"barrier_tol_factor\". This option is also used in the adaptive mu strategy during the monotone mode. This is kappa_epsilon in implementation paper.")?;
472 r.add_bounded_number_option("mu_linear_decrease_factor", "Determines linear decrease rate of barrier parameter.", 0.0, true, 1.0, true, 0.2, "For the Fiacco-McCormick update procedure the new barrier parameter mu is obtained by taking the minimum of mu*\"mu_linear_decrease_factor\" and mu^\"superlinear_decrease_power\". This is kappa_mu in implementation paper. This option is also used in the adaptive mu strategy during the monotone mode.")?;
473 r.add_bounded_number_option("mu_superlinear_decrease_power", "Determines superlinear decrease rate of barrier parameter.", 1.0, true, 2.0, true, 1.5, "For the Fiacco-McCormick update procedure the new barrier parameter mu is obtained by taking the minimum of mu*\"mu_linear_decrease_factor\" and mu^\"superlinear_decrease_power\". This is theta_mu in implementation paper. This option is also used in the adaptive mu strategy during the monotone mode.")?;
474 r.add_string_option("mu_allow_fast_monotone_decrease", "Allow skipping of barrier problem if barrier test is already met.", "yes", &[("no", "Take at least one iteration per barrier problem even if the barrier test is already met for the updated barrier parameter"), ("yes", "Allow fast decrease of mu if barrier test it met")], "")?;
475 r.add_bounded_number_option("tau_min", "Lower bound on fraction-to-the-boundary parameter tau.", 0.0, true, 1.0, true, 0.99, "This is tau_min in the implementation paper. This option is also used in the adaptive mu strategy during the monotone mode.")?;
476
477 r.set_registering_category("Termination");
479 r.add_lower_bounded_integer_option(
480 "max_iter",
481 "Maximum number of iterations.",
482 0,
483 3000,
484 "The algorithm terminates with a message if the number of iterations exceeded this number.",
485 )?;
486 r.add_lower_bounded_number_option("max_wall_time", "Maximum number of walltime clock seconds.", 0.0, true, 1e20, "A limit on walltime clock seconds that Ipopt can use to solve one problem. If during the convergence check this limit is exceeded, Ipopt will terminate with a corresponding message.")?;
487 r.add_lower_bounded_number_option("max_cpu_time", "Maximum number of CPU seconds.", 0.0, true, 1e20, "A limit on CPU seconds that Ipopt can use to solve one problem. If during the convergence check this limit is exceeded, Ipopt will terminate with a corresponding message.")?;
488 r.add_lower_bounded_number_option("dual_inf_tol", "Desired threshold for the dual infeasibility.", 0.0, true, 1.0, "Absolute tolerance on the dual infeasibility. Successful termination requires that the max-norm of the (unscaled) dual infeasibility is less than this threshold.")?;
489 r.add_lower_bounded_number_option("constr_viol_tol", "Desired threshold for the constraint and variable bound violation.", 0.0, true, 1e-4, "Absolute tolerance on the constraint and variable bound violation. Successful termination requires that the max-norm of the (unscaled) constraint violation is less than this threshold. If option bound_relax_factor is not zero 0, then Ipopt relaxes given variable bounds. The value of constr_viol_tol is used to restrict the absolute amount of this bound relaxation. ")?;
490 r.add_lower_bounded_number_option("compl_inf_tol", "Desired threshold for the complementarity conditions.", 0.0, true, 1e-4, "Absolute tolerance on the complementarity. Successful termination requires that the max-norm of the (unscaled) complementarity is less than this threshold.")?;
491 r.add_lower_bounded_number_option("acceptable_tol", "\"Acceptable\" convergence tolerance (relative).", 0.0, true, 1e-6, "Determines which (scaled) overall optimality error is considered to be \"acceptable\". There are two levels of termination criteria. If the usual \"desired\" tolerances (see tol, dual_inf_tol etc) are satisfied at an iteration, the algorithm immediately terminates with a success message. On the other hand, if the algorithm encounters \"acceptable_iter\" many iterations in a row that are considered \"acceptable\", it will terminate before the desired convergence tolerance is met. This is useful in cases where the algorithm might not be able to achieve the \"desired\" level of accuracy.")?;
492 r.add_lower_bounded_integer_option("acceptable_iter", "Number of \"acceptable\" iterates before triggering termination.", 0, 15, "If the algorithm encounters this many successive \"acceptable\" iterates (see \"acceptable_tol\"), it terminates, assuming that the problem has been solved to best possible accuracy given round-off. If it is set to zero, this heuristic is disabled.")?;
493 r.add_lower_bounded_number_option("acceptable_dual_inf_tol", "\"Acceptance\" threshold for the dual infeasibility.", 0.0, true, 1e10, "Absolute tolerance on the dual infeasibility. \"Acceptable\" termination requires that the (max-norm of the unscaled) dual infeasibility is less than this threshold; see also acceptable_tol.")?;
494 r.add_lower_bounded_number_option("acceptable_constr_viol_tol", "\"Acceptance\" threshold for the constraint violation.", 0.0, true, 1e-2, "Absolute tolerance on the constraint violation. \"Acceptable\" termination requires that the max-norm of the (unscaled) constraint violation is less than this threshold; see also acceptable_tol.")?;
495 r.add_lower_bounded_number_option("acceptable_compl_inf_tol", "\"Acceptance\" threshold for the complementarity conditions.", 0.0, true, 1e-2, "Absolute tolerance on the complementarity. \"Acceptable\" termination requires that the max-norm of the (unscaled) complementarity is less than this threshold; see also acceptable_tol.")?;
496 r.add_lower_bounded_number_option("acceptable_obj_change_tol", "\"Acceptance\" stopping criterion based on objective function change.", 0.0, false, 1e20, "If the relative change of the objective function (scaled by Max(1,|f(x)|)) is less than this value, this part of the acceptable tolerance termination is satisfied; see also acceptable_tol. This is useful for the quasi-Newton option, which has trouble to bring down the dual infeasibility.")?;
497 r.add_lower_bounded_number_option("diverging_iterates_tol", "Threshold for maximal value of primal iterates.", 0.0, true, 1e20, "If any component of the primal iterates exceeded this value (in absolute terms), the optimization is aborted with the exit message that the iterates seem to be diverging.")?;
498 r.add_lower_bounded_number_option("mu_target", "Desired value of complementarity.", 0.0, false, 0.0, "Usually, the barrier parameter is driven to zero and the termination test for complementarity is measured with respect to zero complementarity. However, in some cases it might be desired to have Ipopt solve barrier problem for strictly positive value of the barrier parameter. In this case, the value of \"mu_target\" specifies the final value of the barrier parameter, and the termination tests are then defined with respect to the barrier problem for this value of the barrier parameter.")?;
499 r.add_lower_bounded_number_option("infeas_stationarity_tol", "Stationarity tolerance for rapid infeasibility detection.", 0.0, false, 1e-8, "The main loop terminates with local infeasibility when the scaled infeasibility stationarity norm(J^T c) / max(1, norm(c)) stays at or below this value, while the constraint violation stays bounded away from zero (see infeas_viol_kappa), for infeas_max_streak successive iterations. Setting this to 0 disables rapid infeasibility detection.")?;
502 r.add_lower_bounded_number_option("infeas_viol_kappa", "Constraint-violation margin for rapid infeasibility detection.", 0.0, false, 1e2, "An iterate only counts toward the infeasibility streak when its max-norm constraint violation exceeds this multiple of constr_viol_tol. Keeps rapid infeasibility detection from firing on nearly-feasible flat spots.")?;
503 r.add_lower_bounded_integer_option("infeas_max_streak", "Successive infeasible-stationary iterations before declaring local infeasibility.", 0, 5, "Number of consecutive iterations that must satisfy the rapid infeasibility detection test before the main loop terminates with local infeasibility. Setting this to 0 disables rapid infeasibility detection.")?;
504
505 r.set_registering_category("NLP");
507 r.add_lower_bounded_number_option("bound_relax_factor", "Factor for initial relaxation of the bounds.", 0.0, false, 1e-8, "Before start of the optimization, the bounds given by the user are relaxed. This option sets the factor for this relaxation. Additional, the constraint violation tolerance constr_viol_tol is used to bound the relaxation by an absolute value. If it is set to zero, then then bounds relaxation is disabled. See Eqn.(35) in implementation paper. Note that the constraint violation reported by Ipopt at the end of the solution process does not include violations of the original (non-relaxed) variable bounds. See also option honor_original_bounds.")?;
508 r.add_bool_option("honor_original_bounds", "Indicates whether final points should be projected into original bounds.", false, "Ipopt might relax the bounds during the optimization (see, e.g., option \"bound_relax_factor\"). This option determines whether the final point should be projected back into the user-provide original bounds after the optimization. Note that violations of constraints and complementarity reported by Ipopt at the end of the solution process are for the non-projected point.")?;
509 r.set_registering_category("Warm Start");
510 r.add_bool_option("warm_start_same_structure", "Indicates whether a problem with a structure identical to the previous one is to be solved.", false, "If enabled, then the algorithm assumes that an NLP is now to be solved whose structure is identical to one that already was considered (with the same NLP object).")?;
511 r.add_bool_option("warm_start_init_point", "Warm-start for initial point", false, "Indicates whether this optimization should use a warm start initialization, where values of primal and dual variables are given (e.g., from a previous optimization of a related problem.)")?;
520 r.set_registering_category("NLP");
521 r.add_bool_option("check_derivatives_for_naninf", "Indicates whether it is desired to check for Nan/Inf in derivative matrices", false, "Activating this option will cause an error if an invalid number is detected in the constraint Jacobians or the Lagrangian Hessian. If this is not activated, the test is skipped, and the algorithm might proceed with invalid numbers and fail. If test is activated and an invalid number is detected, the matrix is written to output with print_level corresponding to J_MOREDETAILED (7); so beware of large output!")?;
522 r.add_bool_option("grad_f_constant", "Indicates whether to assume that the objective function is linear", false, "Activating this option will cause Ipopt to ask for the Gradient of the objective function only once from the NLP and reuse this information later.")?;
523 r.add_bool_option("jac_c_constant", "Indicates whether to assume that all equality constraints are linear", false, "Activating this option will cause Ipopt to ask for the Jacobian of the equality constraints only once from the NLP and reuse this information later.")?;
524 r.add_bool_option("jac_d_constant", "Indicates whether to assume that all inequality constraints are linear", false, "Activating this option will cause Ipopt to ask for the Jacobian of the inequality constraints only once from the NLP and reuse this information later.")?;
525 r.add_bool_option("hessian_constant", "Indicates whether to assume the problem is a QP (quadratic objective, linear constraints)", false, "Activating this option will cause Ipopt to ask for the Hessian of the Lagrangian function only once from the NLP and reuse this information later.")?;
526 r.set_registering_category("Hessian Approximation");
527 r.add_string_option("hessian_approximation", "Indicates what Hessian information is to be used.", "exact", &[("exact", "Use second derivatives provided by the NLP."), ("limited-memory", "Perform a limited-memory quasi-Newton approximation")], "This determines which kind of information for the Hessian of the Lagrangian function is used by the algorithm.")?;
528 r.add_string_option(
529 "hessian_approximation_space",
530 "Indicates in which subspace the Hessian information is to be approximated.",
531 "nonlinear-variables",
532 &[
533 (
534 "nonlinear-variables",
535 "only in space of nonlinear variables.",
536 ),
537 (
538 "all-variables",
539 "in space of all variables (without slacks)",
540 ),
541 ],
542 "",
543 )?;
544
545 r.set_registering_category("Output");
547 r.set_registering_category("Output");
548 r.add_bool_option("print_info_string", "Enables printing of additional info string at end of iteration output.", false, "This string contains some insider information about the current iteration. For details, look for \"Diagnostic Tags\" in the Ipopt documentation.")?;
549 r.add_string_option("inf_pr_output", "Determines what value is printed in the \"inf_pr\" output column.", "original", &[("internal", "max-norm of violation of internal equality constraints"), ("original", "maximal constraint violation in original NLP")], "Ipopt works with a reformulation of the original problem, where slacks are introduced and the problem might have been scaled. The choice \"internal\" prints out the constraint violation of this formulation. With \"original\" the true constraint violation in the original NLP is printed.")?;
550 r.add_lower_bounded_integer_option("print_frequency_iter", "Determines at which iteration frequency the summarizing iteration output line should be printed.", 1, 1, "Summarizing iteration output is printed every print_frequency_iter iterations, if at least print_frequency_time seconds have passed since last output.")?;
551 r.add_lower_bounded_number_option("print_frequency_time", "Determines at which time frequency the summarizing iteration output line should be printed.", 0.0, false, 0.0, "Summarizing iteration output is printed if at least print_frequency_time seconds have passed since last output and the iteration number is a multiple of print_frequency_iter.")?;
552 r.set_registering_category("");
553
554 r.set_registering_category("Step Calculation");
556 r.set_registering_category("Step Calculation");
557 r.add_bool_option("fast_step_computation", "Indicates if the linear system should be solved quickly.", false, "If enabled, the algorithm assumes that the linear system that is solved to obtain the search direction is solved sufficiently well. In that case, no residuals are computed to verify the solution and the computation of the search direction is a little faster.")?;
558
559 r.set_registering_category("Step Calculation");
561 r.add_lower_bounded_integer_option("min_refinement_steps", "Minimum number of iterative refinement steps per linear system solve.", 0, 1, "Iterative refinement (on the full unsymmetric system) is performed for each right hand side. This option determines the minimum number of iterative refinements (i.e. at least \"min_refinement_steps\" iterative refinement steps are enforced per right hand side.)")?;
562 r.add_lower_bounded_integer_option("max_refinement_steps", "Maximum number of iterative refinement steps per linear system solve.", 0, 10, "Iterative refinement (on the full unsymmetric system) is performed for each right hand side. This option determines the maximum number of iterative refinement steps.")?;
563 r.add_lower_bounded_number_option("residual_ratio_max", "Iterative refinement tolerance", 0.0, true, 1e-10, "Iterative refinement is performed until the residual test ratio is less than this tolerance (or until \"max_refinement_steps\" refinement steps are performed).")?;
564 r.add_lower_bounded_number_option("residual_ratio_singular", "Threshold for declaring linear system singular after failed iterative refinement.", 0.0, true, 1e-5, "If the residual test ratio is larger than this value after failed iterative refinement, the algorithm pretends that the linear system is singular.")?;
565 r.add_lower_bounded_number_option("residual_improvement_factor", "Minimal required reduction of residual test ratio in iterative refinement.", 0.0, true, 0.999999999, "If the improvement of the residual test ratio made by one iterative refinement step is not better than this factor, iterative refinement is aborted.")?;
566 r.add_lower_bounded_number_option("neg_curv_test_tol", "Tolerance for heuristic to ignore wrong inertia.", 0.0, false, 0.0, "If nonzero, incorrect inertia in the augmented system is ignored, and Ipopt tests if the direction is a direction of positive curvature. This tolerance is alpha_n in the paper by Zavala and Chiang (2014) and it determines when the direction is considered to be sufficiently positive. A value in the range of [1e-12, 1e-11] is recommended.")?;
567 r.add_string_option("neg_curv_test_reg", "Whether to do the curvature test with the primal regularization (see Zavala and Chiang, 2014).", "yes", &[("yes", "use primal regularization with the inertia-free curvature test"), ("no", "use original IPOPT approach, in which the primal regularization is ignored")], "")?;
568
569 r.set_registering_category("Step Calculation");
571 r.add_lower_bounded_number_option("max_hessian_perturbation", "Maximum value of regularization parameter for handling negative curvature.", 0.0, true, 1e20, "In order to guarantee that the search directions are indeed proper descent directions, Ipopt requires that the inertia of the (augmented) linear system for the step computation has the correct number of negative and positive eigenvalues. The idea is that this guides the algorithm away from maximizers and makes Ipopt more likely converge to first order optimal points that are minimizers. If the inertia is not correct, a multiple of the identity matrix is added to the Hessian of the Lagrangian in the augmented system. This parameter gives the maximum value of the regularization parameter. If a regularization of that size is not enough, the algorithm skips this iteration and goes to the restoration phase. This is delta_w^max in the implementation paper.")?;
572 r.add_lower_bounded_number_option("min_hessian_perturbation", "Smallest perturbation of the Hessian block.", 0.0, false, 1e-20, "The size of the perturbation of the Hessian block is never selected smaller than this value, unless no perturbation is necessary. This is delta_w^min in implementation paper.")?;
573 r.add_lower_bounded_number_option("perturb_inc_fact_first", "Increase factor for x-s perturbation for very first perturbation.", 1.0, true, 100.0, "The factor by which the perturbation is increased when a trial value was not sufficient - this value is used for the computation of the very first perturbation and allows a different value for the first perturbation than that used for the remaining perturbations. This is bar_kappa_w^+ in the implementation paper.")?;
574 r.add_lower_bounded_number_option("perturb_inc_fact", "Increase factor for x-s perturbation.", 1.0, true, 8.0, "The factor by which the perturbation is increased when a trial value was not sufficient - this value is used for the computation of all perturbations except for the first. This is kappa_w^+ in the implementation paper.")?;
575 r.add_bounded_number_option("perturb_dec_fact", "Decrease factor for x-s perturbation.", 0.0, true, 1.0, true, 1.0 / 3.0, "The factor by which the perturbation is decreased when a trial value is deduced from the size of the most recent successful perturbation. This is kappa_w^- in the implementation paper.")?;
576 r.add_lower_bounded_number_option("first_hessian_perturbation", "Size of first x-s perturbation tried.", 0.0, true, 1e-4, "The first value tried for the x-s perturbation in the inertia correction scheme. This is delta_0 in the implementation paper.")?;
577 r.add_lower_bounded_number_option(
578 "jacobian_regularization_value",
579 "Size of the regularization for rank-deficient constraint Jacobians.",
580 0.0,
581 false,
582 1e-8,
583 "This is bar delta_c in the implementation paper.",
584 )?;
585 r.add_lower_bounded_number_option(
586 "jacobian_regularization_exponent",
587 "Exponent for mu in the regularization for rank-deficient constraint Jacobians.",
588 0.0,
589 false,
590 0.25,
591 "This is kappa_c in the implementation paper.",
592 )?;
593 r.add_bool_option("perturb_always_cd", "Active permanent perturbation of constraint linearization.", false, "Enabling this option leads to using the delta_c and delta_d perturbation for the computation of every search direction. Usually, it is only used when the iteration matrix is singular.")?;
594
595 r.set_registering_category("Barrier Parameter Update");
597 r.add_lower_bounded_number_option("sigma_max", "Maximum value of the centering parameter.", 0.0, true, 1e2, "This is the upper bound for the centering parameter chosen by the quality function based barrier parameter update. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
598 r.add_lower_bounded_number_option("sigma_min", "Minimum value of the centering parameter.", 0.0, false, 1e-6, "This is the lower bound for the centering parameter chosen by the quality function based barrier parameter update. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
599 r.add_string_option(
600 "quality_function_norm_type",
601 "Norm used for components of the quality function.",
602 "2-norm-squared",
603 &[
604 ("1-norm", "use the 1-norm (abs sum)"),
605 ("2-norm-squared", "use the 2-norm squared (sum of squares)"),
606 ("max-norm", "use the infinity norm (max)"),
607 ("2-norm", "use 2-norm"),
608 ],
609 "Only used if option \"mu_oracle\" is set to \"quality-function\".",
610 )?;
611 r.add_string_option("quality_function_centrality", "The penalty term for centrality that is included in quality function.", "none", &[("none", "no penalty term is added"), ("log", "complementarity * the log of the centrality measure"), ("reciprocal", "complementarity * the reciprocal of the centrality measure"), ("cubed-reciprocal", "complementarity * the reciprocal of the centrality measure cubed")], "This determines whether a term is added to the quality function to penalize deviation from centrality with respect to complementarity. The complementarity measure here is the xi in the Loqo update rule. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
612 r.add_string_option("quality_function_balancing_term", "The balancing term included in the quality function for centrality.", "none", &[("none", "no balancing term is added"), ("cubic", "Max(0,Max(dual_inf,primal_inf)-compl)^3")], "This determines whether a term is added to the quality function that penalizes situations where the complementarity is much smaller than dual and primal infeasibilities. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
613 r.add_lower_bounded_integer_option("quality_function_max_section_steps", "Maximum number of search steps during direct search procedure determining the optimal centering parameter.", 0, 8, "The golden section search is performed for the quality function based mu oracle. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
614 r.add_bounded_number_option("quality_function_section_sigma_tol", "Tolerance for the section search procedure determining the optimal centering parameter (in sigma space).", 0.0, false, 1.0, true, 1e-2, "The golden section search is performed for the quality function based mu oracle. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
615 r.add_bounded_number_option("quality_function_section_qf_tol", "Tolerance for the golden section search procedure determining the optimal centering parameter (in the function value space).", 0.0, false, 1.0, true, 0.0, "The golden section search is performed for the quality function based mu oracle. Only used if option \"mu_oracle\" is set to \"quality-function\".")?;
616
617 r.set_registering_category("Restoration Phase");
619 r.add_bounded_number_option("required_infeasibility_reduction", "Required reduction of infeasibility before leaving restoration phase.", 0.0, false, 1.0, true, 0.9, "The restoration phase algorithm is performed, until a point is found that is acceptable to the filter and the infeasibility has been reduced by at least the fraction given by this option.")?;
620 r.add_lower_bounded_integer_option("max_resto_iter", "Maximum number of successive iterations in restoration phase.", 0, 3000000, "The algorithm terminates with an error message if the number of iterations successively taken in the restoration phase exceeds this number.")?;
621
622 r.set_registering_category("Restoration Phase");
624 r.add_bool_option("evaluate_orig_obj_at_resto_trial", "Determines if the original objective function should be evaluated at restoration phase trial points.", true, "Enabling this option makes the restoration phase algorithm evaluate the objective function of the original problem at every trial point encountered during the restoration phase, even if this value is not required. In this way, it is guaranteed that the original objective function can be evaluated without error at all accepted iterates; otherwise the algorithm might fail at a point where the restoration phase accepts an iterate that is good for the restoration phase problem, but not the original problem. On the other hand, if the evaluation of the original objective is expensive, this might be costly.")?;
625 r.add_lower_bounded_number_option(
626 "resto_penalty_parameter",
627 "Penalty parameter in the restoration phase objective function.",
628 0.0,
629 true,
630 1e3,
631 "This is the parameter rho in equation (31a) in the Ipopt implementation paper.",
632 )?;
633 r.add_lower_bounded_number_option("resto_proximity_weight", "Weighting factor for the proximity term in restoration phase objective.", 0.0, false, 1.0, "This determines how the parameter zeta in equation (29a) in the implementation paper is computed. zeta here is resto_proximity_weight*sqrt(mu), where mu is the current barrier parameter.")?;
634
635 r.set_registering_category("Restoration Phase");
637 r.add_lower_bounded_number_option("bound_mult_reset_threshold", "Threshold for resetting bound multipliers after the restoration phase.", 0.0, false, 1e3, "After returning from the restoration phase, the bound multipliers are updated with a Newton step for complementarity. Here, the change in the primal variables during the entire restoration phase is taken to be the corresponding primal Newton step. However, if after the update the largest bound multiplier exceeds the threshold specified by this option, the multipliers are all reset to 1.")?;
638 r.add_lower_bounded_number_option("constr_mult_reset_threshold", "Threshold for resetting equality and inequality multipliers after restoration phase.", 0.0, false, 0.0, "After returning from the restoration phase, the constraint multipliers are recomputed by a least square estimate. This option triggers when those least-square estimates should be ignored.")?;
639 r.add_lower_bounded_number_option("resto_failure_feasibility_threshold", "Threshold for primal infeasibility to declare failure of restoration phase.", 0.0, false, 0.0, "If the restoration phase is terminated because of the \"acceptable\" termination criteria and the primal infeasibility is smaller than this value, the restoration phase is declared to have failed. The default value is actually 1e2*tol, where tol is the general termination tolerance.")?;
640
641 r.set_registering_category("Warm Start");
643 r.add_lower_bounded_number_option(
644 "warm_start_bound_push",
645 "same as bound_push for the regular initializer",
646 0.0,
647 true,
648 1e-3,
649 "",
650 )?;
651 r.add_bounded_number_option(
652 "warm_start_bound_frac",
653 "same as bound_frac for the regular initializer",
654 0.0,
655 true,
656 0.5,
657 false,
658 1e-3,
659 "",
660 )?;
661 r.add_lower_bounded_number_option(
662 "warm_start_slack_bound_push",
663 "same as slack_bound_push for the regular initializer",
664 0.0,
665 true,
666 1e-3,
667 "",
668 )?;
669 r.add_bounded_number_option(
670 "warm_start_slack_bound_frac",
671 "same as slack_bound_frac for the regular initializer",
672 0.0,
673 true,
674 0.5,
675 false,
676 1e-3,
677 "",
678 )?;
679 r.add_lower_bounded_number_option(
680 "warm_start_mult_bound_push",
681 "same as mult_bound_push for the regular initializer",
682 0.0,
683 true,
684 1e-3,
685 "",
686 )?;
687 r.add_number_option(
688 "warm_start_mult_init_max",
689 "Maximum initial value for the equality multipliers.",
690 1e6,
691 "",
692 )?;
693 r.add_string_option(
694 "warm_start_entire_iterate",
695 "Tells algorithm whether to use the GetWarmStartIterate method in the NLP.",
696 "no",
697 &[
698 ("no", "call GetStartingPoint in the NLP"),
699 ("yes", "call GetWarmStartIterate in the NLP"),
700 ],
701 "",
702 )?;
703 r.add_number_option("warm_start_target_mu", "", 0.0, "Experimental!")?;
704
705 r.set_registering_category("CG Penalty");
707 r.add_lower_bounded_number_option(
708 "penalty_init_max",
709 "Maximal value for the initial penalty parameter (for Chen-Goldfarb line search).",
710 0.0,
711 true,
712 1e5,
713 "",
714 )?;
715 r.add_lower_bounded_number_option("penalty_init_min", "Minimal value for the initial penalty parameter for line search (for Chen-Goldfarb line search).", 0.0, true, 1.0, "")?;
716 r.add_lower_bounded_number_option(
717 "penalty_max",
718 "Maximal value for the penalty parameter (for Chen-Goldfarb line search).",
719 0.0,
720 true,
721 1e30,
722 "",
723 )?;
724 r.add_lower_bounded_number_option(
725 "pen_des_fact",
726 "a parameter used in penalty parameter computation (for Chen-Goldfarb line search).",
727 0.0,
728 true,
729 2e-1,
730 "",
731 )?;
732 r.add_lower_bounded_number_option("kappa_x_dis", "a parameter used to check if the fast direction can be used as the line search direction (for Chen-Goldfarb line search).", 0.0, true, 1e2, "")?;
733 r.add_lower_bounded_number_option("kappa_y_dis", "a parameter used to check if the fast direction can be used as the line search direction (for Chen-Goldfarb line search).", 0.0, true, 1e4, "")?;
734 r.add_lower_bounded_number_option("vartheta", "a parameter used to check if the fast direction can be used as the line search direction (for Chen-Goldfarb line search).", 0.0, true, 0.5, "")?;
735 r.add_lower_bounded_number_option("delta_y_max", "a parameter used to check if the fast direction can be used as the line search direction (for Chen-Goldfarb line search).", 0.0, true, 1e12, "")?;
736 r.add_lower_bounded_number_option("fast_des_fact", "a parameter used to check if the fast direction can be used as the line search direction (for Chen-Goldfarb line search).", 0.0, true, 1e-1, "")?;
737 r.add_lower_bounded_number_option("pen_init_fac", "a parameter used to choose initial penalty parameters when the regularized Newton method is used.", 0.0, true, 5e1, "")?;
738 r.add_bool_option(
739 "never_use_fact_cgpen_direction",
740 "Toggle to switch off the fast Chen-Goldfarb direction",
741 false,
742 "",
743 )?;
744
745 r.set_registering_category("CG Penalty");
747 r.add_bool_option(
748 "never_use_piecewise_penalty_ls",
749 "Toggle to switch off the piecewise penalty method",
750 false,
751 "",
752 )?;
753 r.add_bounded_number_option(
754 "eta_penalty",
755 "Relaxation factor in the Armijo condition for the penalty function.",
756 0.0,
757 true,
758 0.5,
759 true,
760 1e-8,
761 "",
762 )?;
763 r.add_lower_bounded_number_option("penalty_update_infeasibility_tol", "Threshold for infeasibility in penalty parameter update test.", 0.0, true, 1e-9, "If the new constraint violation is smaller than this tolerance, the penalty parameter is not increased.")?;
764 r.add_lower_bounded_number_option("eta_min", "", 0.0, true, 1e1, "")?;
765 r.add_lower_bounded_number_option("pen_theta_max_fact", "Determines upper bound for constraint violation in the filter.", 0.0, true, 1e4, "The algorithmic parameter theta_max is determined as theta_max_fact times the maximum of 1 and the constraint violation at initial point. Any point with a constraint violation larger than theta_max is unacceptable to the filter (see Eqn. (21) in implementation paper).")?;
766 r.add_lower_bounded_number_option("penalty_update_compl_tol", "", 0.0, true, 1e1, "")?;
767 r.add_lower_bounded_number_option("chi_hat", "", 0.0, true, 2.0, "")?;
768 r.add_lower_bounded_number_option("chi_tilde", "", 0.0, true, 5.0, "")?;
769 r.add_lower_bounded_number_option("chi_cup", "", 0.0, true, 1.5, "")?;
770 r.add_lower_bounded_number_option("gamma_hat", "", 0.0, true, 0.04, "")?;
771 r.add_lower_bounded_number_option("gamma_tilde", "", 0.0, true, 4.0, "")?;
772 r.add_lower_bounded_number_option("epsilon_c", "", 0.0, true, 1e-2, "")?;
773 r.add_lower_bounded_number_option("piecewisepenalty_gamma_obj", "", 0.0, true, 1e-13, "")?;
774 r.add_lower_bounded_number_option("piecewisepenalty_gamma_infeasi", "", 0.0, true, 1e-13, "")?;
775 r.add_lower_bounded_number_option("min_alpha_primal", "", 0.0, true, 1e-13, "")?;
776 r.add_lower_bounded_number_option("theta_min", "", 0.0, true, 1e-6, "")?;
777 r.add_lower_bounded_number_option(
778 "mult_diverg_feasibility_tol",
779 "tolerance for deciding if the multipliers are diverging",
780 0.0,
781 true,
782 1e-7,
783 "",
784 )?;
785 r.add_lower_bounded_number_option(
786 "mult_diverg_y_tol",
787 "tolerance for deciding if the multipliers are diverging",
788 0.0,
789 true,
790 1e8,
791 "",
792 )?;
793
794 r.set_registering_category("Linear Solver");
796 r.add_bool_option("linear_scaling_on_demand", "Flag indicating that linear scaling is only done if it seems required.", true, "This option is only important if a linear scaling method (e.g., mc19) is used. If you choose \"no\", then the scaling factors are computed for every linear system from the start. This can be quite expensive. Choosing \"yes\" means that the algorithm will start the scaling method only when the solutions to the linear system seem not good, and then use it until the end.")?;
797
798 r.set_registering_category("MA27 Linear Solver");
800 r.add_bounded_integer_option("ma27_print_level", "Debug printing level for the linear solver MA27", 0, 4, 0, "0: no printing; 1: Error messages only; 2: Error and warning messages; 3: Error and warning messages and terse monitoring; 4: All information.")?;
801 r.add_bounded_number_option(
802 "ma27_pivtol",
803 "Pivot tolerance for the linear solver MA27.",
804 0.0,
805 true,
806 1.0,
807 true,
808 1e-8,
809 "A smaller number pivots for sparsity, a larger number pivots for stability.",
810 )?;
811 r.add_bounded_number_option("ma27_pivtolmax", "Maximum pivot tolerance for the linear solver MA27.", 0.0, true, 1.0, true, 1e-4, "Ipopt may increase pivtol as high as ma27_pivtolmax to get a more accurate solution to the linear system.")?;
812 r.add_lower_bounded_number_option("ma27_liw_init_factor", "Integer workspace memory for MA27.", 1.0, false, 5.0, "The initial integer workspace memory = liw_init_factor * memory required by unfactored system. Ipopt will increase the workspace size by ma27_meminc_factor if required.")?;
813 r.add_lower_bounded_number_option("ma27_la_init_factor", "Real workspace memory for MA27.", 1.0, false, 5.0, "The initial real workspace memory = la_init_factor * memory required by unfactored system. Ipopt will increase the workspace size by ma27_meminc_factor if required.")?;
814 r.add_lower_bounded_number_option("ma27_meminc_factor", "Increment factor for workspace size for MA27.", 1.0, false, 2.0, "If the integer or real workspace is not large enough, Ipopt will increase its size by this factor.")?;
815 r.add_bool_option("ma27_skip_inertia_check", "Whether to always pretend that inertia is correct.", false, "Setting this option to \"yes\" essentially disables inertia check. This option makes the algorithm non-robust and easily fail, but it might give some insight into the necessity of inertia control.")?;
816 r.add_bool_option("ma27_ignore_singularity", "Whether to use MA27's ability to solve a linear system even if the matrix is singular.", false, "Setting this option to \"yes\" means that Ipopt will call MA27 to compute solutions for right hand sides, even if MA27 has detected that the matrix is singular (but is still able to solve the linear system). In some cases this might be better than using Ipopt's heuristic of small perturbation of the lower diagonal of the KKT matrix.")?;
817
818 r.set_registering_category("MA57 Linear Solver");
820 r.add_lower_bounded_integer_option("ma57_print_level", "Debug printing level for the linear solver MA57", 0, 0, "0: no printing; 1: Error messages only; 2: Error and warning messages; 3: Error and warning messages and terse monitoring; >=4: All information.")?;
821 r.add_bounded_number_option(
822 "ma57_pivtol",
823 "Pivot tolerance for the linear solver MA57.",
824 0.0,
825 true,
826 1.0,
827 true,
828 1e-8,
829 "A smaller number pivots for sparsity, a larger number pivots for stability.",
830 )?;
831 r.add_bounded_number_option("ma57_pivtolmax", "Maximum pivot tolerance for the linear solver MA57.", 0.0, true, 1.0, true, 1e-4, "Ipopt may increase pivtol as high as ma57_pivtolmax to get a more accurate solution to the linear system.")?;
832 r.add_lower_bounded_number_option("ma57_pre_alloc", "Safety factor for work space memory allocation for the linear solver MA57.", 1.0, false, 1.05, "If 1 is chosen, the suggested amount of work space is used. However, choosing a larger number might avoid reallocation if the suggest values do not suffice.")?;
833 r.add_bounded_integer_option(
834 "ma57_pivot_order",
835 "Controls pivot order in MA57",
836 0,
837 5,
838 5,
839 "This is ICNTL(6) in MA57.",
840 )?;
841 r.add_bool_option("ma57_automatic_scaling", "Controls whether to enable automatic scaling in MA57", false, "For higher reliability of the MA57 solver, you may want to set this option to yes. This is ICNTL(15) in MA57.")?;
842 r.add_lower_bounded_integer_option(
843 "ma57_block_size",
844 "Controls block size used by Level 3 BLAS in MA57BD",
845 1,
846 16,
847 "This is ICNTL(11) in MA57.",
848 )?;
849 r.add_lower_bounded_integer_option(
850 "ma57_node_amalgamation",
851 "Node amalgamation parameter",
852 1,
853 16,
854 "This is ICNTL(12) in MA57.",
855 )?;
856 r.add_bounded_integer_option("ma57_small_pivot_flag", "Handling of small pivots", 0, 1, 0, "If set to 1, then when small entries defined by CNTL(2) are detected they are removed and the corresponding pivots placed at the end of the factorization. This can be particularly efficient if the matrix is highly rank deficient. This is ICNTL(16) in MA57.")?;
857
858 r.set_registering_category("FERAL Linear Solver");
869 r.add_bool_option("feral_cascade_break", "Whether to enable FERAL's cascade-break pivot heuristic.", false, "Cascade-break accelerates the dense trailing-update kernels in FERAL's supernodal LDL^T factor (e.g. ~30x per factor on the 64k x 64k pinene_3200 KKT), but introduces small per-pivot perturbations that can flip the negative-eigenvalue count on borderline iterates. Pounce reads that as WrongInertia and escalates delta_w, which corrupts the search direction on a few problem families (robot_1600, NARX_CFy). Default is off; flip to yes for IPM-style KKTs with dense supernodes where the per-factor speedup matters and the IPM trajectory is well-behaved. See crates/pounce-feral/src/lib.rs and pounce#31 / feral#17.")?;
870 r.add_bool_option("feral_fma", "Whether FERAL should dispatch dense kernels through fused multiply-add intrinsics.", false, "On aarch64 / x86_v3, FMA-dispatched panel and trailing-update kernels run at roughly 2x the throughput of the generic kernels. The downside is small per-pivot rounding drift that trips more WrongInertia checks and delayed pivots — the same failure mode that forced cascade-break off by default. Off by default; turn on for workloads where kernel throughput dominates and the IPM tolerates a slightly noisier inertia signal.")?;
871 r.add_bool_option("feral_refine", "Whether FERAL should run iterative refinement on every back-solve.", true, "Iterative refinement at solve time closes the residual floor produced by cascade-break's L-factor perturbation; without it, pinene_3200 and similar IPM tails stall as the per-pivot residual exceeds the duality gap. Enabled by default; set no only when timing the bare factor + back-solve in isolation.")?;
872 r.add_lower_bounded_number_option("feral_singular_pivot_floor", "Near-singularity trigger for the FERAL backend.", 0.0, false, 1e-20, "FERAL's default zero-pivot policy force-accepts a pivot at the working-precision floor and still reports a successful factorization, so a numerically rank-deficient KKT system that happens to land on the correct inertia produces a clean solve and the IPM never escalates delta_w. This option is pounce's analog of MA57's CNTL(2) small-pivot threshold: after a successful factor, the smallest accepted D-block pivot magnitude min|lambda(D)| (scaled space) is compared against this absolute floor, and if it falls below, the factor is reported Singular so PDPerturbationHandler::PerturbForSingularity bumps the Hessian perturbation. An absolute floor is used rather than the scale-free ratio min/max ~ 1/cond(D), because an interior-point KKT is designed to become ill-conditioned as mu->0 and the ratio collapses on healthy full-rank systems near the solution. Lower values are more permissive (fewer factors flagged singular); 0 disables the trigger. Default 1e-20 (MA57 CNTL(2)). See crates/pounce-feral/src/lib.rs and feral dev/research/near-singularity-signal.md.")?;
873
874 r.set_registering_category("MA77 Linear Solver");
876 r.add_integer_option("ma77_print_level", "Debug printing level for the linear solver MA77", -1, "<0: no printing; 0: Error and warning messages only; 1: Limited diagnostic printing; >1 Additional diagnostic printing.")?;
877 r.add_lower_bounded_integer_option(
878 "ma77_buffer_lpage",
879 "Number of scalars per MA77 in-core buffer page in the out-of-core solver MA77",
880 1,
881 4096,
882 "Must be at most ma77_file_size.",
883 )?;
884 r.add_lower_bounded_integer_option(
885 "ma77_buffer_npage",
886 "Number of pages that make up MA77 buffer",
887 1,
888 1600,
889 "Number of pages of size buffer_lpage that exist in-core for the out-of-core solver MA77.",
890 )?;
891 r.add_lower_bounded_integer_option("ma77_file_size", "Target size of each temporary file for MA77, scalars per type", 1, 2097152, "MA77 uses many temporary files, this option controls the size of each one. It is measured in the number of entries (int or double), NOT bytes.")?;
892 r.add_lower_bounded_integer_option("ma77_maxstore", "Maximum storage size for MA77 in-core mode", 0, 0, "If greater than zero, the maximum size of factors stored in core before out-of-core mode is invoked.")?;
893 r.add_lower_bounded_integer_option(
894 "ma77_nemin",
895 "Node Amalgamation parameter",
896 1,
897 8,
898 "Two nodes in elimination tree are merged if result has fewer than ma77_nemin variables.",
899 )?;
900 r.add_lower_bounded_number_option(
901 "ma77_small",
902 "Zero Pivot Threshold",
903 0.0,
904 false,
905 1e-20,
906 "Any pivot less than ma77_small is treated as zero.",
907 )?;
908 r.add_lower_bounded_number_option("ma77_static", "Static Pivoting Threshold", 0.0, false, 0.0, "See MA77 documentation. Either ma77_static=0.0 or ma77_static>ma77_small. ma77_static=0.0 disables static pivoting.")?;
909 r.add_bounded_number_option(
910 "ma77_u",
911 "Pivoting Threshold",
912 0.0,
913 false,
914 0.5,
915 false,
916 1e-8,
917 "See MA77 documentation.",
918 )?;
919 r.add_bounded_number_option(
920 "ma77_umax",
921 "Maximum Pivoting Threshold",
922 0.0,
923 false,
924 0.5,
925 false,
926 1e-4,
927 "Maximum value to which u will be increased to improve quality.",
928 )?;
929 r.add_string_option(
930 "ma77_order",
931 "Controls type of ordering used by MA77",
932 "metis",
933 &[
934 (
935 "amd",
936 "Use the HSL_MC68 approximate minimum degree algorithm",
937 ),
938 (
939 "metis",
940 "Use the MeTiS nested dissection algorithm (if available)",
941 ),
942 ],
943 "",
944 )?;
945
946 r.set_registering_category("MA86 Linear Solver");
948 r.add_integer_option("ma86_print_level", "Debug printing level", -1, "<0: no printing; 0: Error and warning messages only; 1: Limited diagnostic printing; >1 Additional diagnostic printing.")?;
949 r.add_lower_bounded_integer_option(
950 "ma86_nemin",
951 "Node Amalgamation parameter",
952 1,
953 32,
954 "Two nodes in elimination tree are merged if result has fewer than ma86_nemin variables.",
955 )?;
956 r.add_lower_bounded_number_option(
957 "ma86_small",
958 "Zero Pivot Threshold",
959 0.0,
960 false,
961 1e-20,
962 "Any pivot less than ma86_small is treated as zero.",
963 )?;
964 r.add_lower_bounded_number_option("ma86_static", "Static Pivoting Threshold", 0.0, false, 0.0, "See MA86 documentation. Either ma86_static=0.0 or ma86_static>ma86_small. ma86_static=0.0 disables static pivoting.")?;
965 r.add_bounded_number_option(
966 "ma86_u",
967 "Pivoting Threshold",
968 0.0,
969 false,
970 0.5,
971 false,
972 1e-8,
973 "See MA86 documentation.",
974 )?;
975 r.add_bounded_number_option(
976 "ma86_umax",
977 "Maximum Pivoting Threshold",
978 0.0,
979 false,
980 0.5,
981 false,
982 1e-4,
983 "Maximum value to which u will be increased to improve quality.",
984 )?;
985 r.add_string_option(
986 "ma86_scaling",
987 "Controls scaling of matrix",
988 "mc64",
989 &[
990 ("none", "Do not scale the linear system matrix"),
991 ("mc64", "Scale linear system matrix using MC64"),
992 ("mc77", "Scale linear system matrix using MC77 [1,3,0]"),
993 ],
994 "",
995 )?;
996 r.add_string_option(
997 "ma86_order",
998 "Controls type of ordering",
999 "auto",
1000 &[
1001 ("auto", "Try both AMD and MeTiS, pick best"),
1002 (
1003 "amd",
1004 "Use the HSL_MC68 approximate minimum degree algorithm",
1005 ),
1006 (
1007 "metis",
1008 "Use the MeTiS nested dissection algorithm (if available)",
1009 ),
1010 ],
1011 "",
1012 )?;
1013
1014 r.set_registering_category("MA97 Linear Solver");
1016 r.add_integer_option("ma97_print_level", "Debug printing level", -1, "<0: no printing; 0: Error and warning messages only; 1: Limited diagnostic printing; >1 Additional diagnostic printing.")?;
1017 r.add_lower_bounded_integer_option(
1018 "ma97_nemin",
1019 "Node Amalgamation parameter",
1020 1,
1021 8,
1022 "Two nodes in elimination tree are merged if result has fewer than ma97_nemin variables.",
1023 )?;
1024 r.add_lower_bounded_number_option(
1025 "ma97_small",
1026 "Zero Pivot Threshold",
1027 0.0,
1028 false,
1029 1e-20,
1030 "Any pivot less than ma97_small is treated as zero.",
1031 )?;
1032 r.add_bounded_number_option(
1033 "ma97_u",
1034 "Pivoting Threshold",
1035 0.0,
1036 false,
1037 0.5,
1038 false,
1039 1e-8,
1040 "See MA97 documentation.",
1041 )?;
1042 r.add_bounded_number_option(
1043 "ma97_umax",
1044 "Maximum Pivoting Threshold",
1045 0.0,
1046 false,
1047 0.5,
1048 false,
1049 1e-4,
1050 "See MA97 documentation.",
1051 )?;
1052 r.add_string_option("ma97_scaling", "Specifies strategy for scaling", "dynamic", &[("none", "Do not scale the linear system matrix"), ("mc30", "Scale all linear system matrices using MC30"), ("mc64", "Scale all linear system matrices using MC64"), ("mc77", "Scale all linear system matrices using MC77 [1,3,0]"), ("dynamic", "Dynamically select scaling according to rules specified by ma97_scalingX and ma97_switchX options.")], "")?;
1053 r.add_string_option("ma97_scaling1", "First scaling.", "mc64", &[("none", "No scaling"), ("mc30", "Scale linear system matrix using MC30"), ("mc64", "Scale linear system matrix using MC64"), ("mc77", "Scale linear system matrix using MC77 [1,3,0]")], "If ma97_scaling=dynamic, this scaling is used according to the trigger ma97_switch1. If ma97_switch2 is triggered it is disabled.")?;
1054 r.add_string_option("ma97_switch1", "First switch, determine when ma97_scaling1 is enabled.", "od_hd_reuse", &[("never", "Scaling is never enabled."), ("at_start", "Scaling to be used from the very start."), ("at_start_reuse", "Scaling to be used on first iteration, then reused thereafter."), ("on_demand", "Scaling to be used after Ipopt request improved solution (i.e. iterative refinement has failed)."), ("on_demand_reuse", "As on_demand, but reuse scaling from previous itr"), ("high_delay", "Scaling to be used after more than 0.05*n delays are present"), ("high_delay_reuse", "Scaling to be used only when previous itr created more that 0.05*n additional delays, otherwise reuse scaling from previous itr"), ("od_hd", "Combination of on_demand and high_delay"), ("od_hd_reuse", "Combination of on_demand_reuse and high_delay_reuse")], "If ma97_scaling=dynamic, ma97_scaling1 is enabled according to this condition. If ma97_switch2 occurs this option is henceforth ignored.")?;
1055 r.add_string_option("ma97_scaling2", "Second scaling.", "mc64", &[("none", "No scaling"), ("mc30", "Scale linear system matrix using MC30"), ("mc64", "Scale linear system matrix using MC64"), ("mc77", "Scale linear system matrix using MC77 [1,3,0]")], "If ma97_scaling=dynamic, this scaling is used according to the trigger ma97_switch2. If ma97_switch3 is triggered it is disabled.")?;
1056 r.add_string_option("ma97_switch2", "Second switch, determine when ma97_scaling2 is enabled.", "never", &[("never", "Scaling is never enabled."), ("at_start", "Scaling to be used from the very start."), ("at_start_reuse", "Scaling to be used on first iteration, then reused thereafter."), ("on_demand", "Scaling to be used after Ipopt request improved solution (i.e. iterative refinement has failed)."), ("on_demand_reuse", "As on_demand, but reuse scaling from previous itr"), ("high_delay", "Scaling to be used after more than 0.05*n delays are present"), ("high_delay_reuse", "Scaling to be used only when previous itr created more that 0.05*n additional delays, otherwise reuse scaling from previous itr"), ("od_hd", "Combination of on_demand and high_delay"), ("od_hd_reuse", "Combination of on_demand_reuse and high_delay_reuse")], "If ma97_scaling=dynamic, ma97_scaling2 is enabled according to this condition. If ma97_switch3 occurs this option is henceforth ignored.")?;
1057 r.add_string_option(
1058 "ma97_scaling3",
1059 "Third scaling.",
1060 "mc64",
1061 &[
1062 ("none", "No scaling"),
1063 ("mc30", "Scale linear system matrix using MC30"),
1064 ("mc64", "Scale linear system matrix using MC64"),
1065 ("mc77", "Scale linear system matrix using MC77 [1,3,0]"),
1066 ],
1067 "If ma97_scaling=dynamic, this scaling is used according to the trigger ma97_switch3.",
1068 )?;
1069 r.add_string_option("ma97_switch3", "Third switch, determine when ma97_scaling3 is enabled.", "never", &[("never", "Scaling is never enabled."), ("at_start", "Scaling to be used from the very start."), ("at_start_reuse", "Scaling to be used on first iteration, then reused thereafter."), ("on_demand", "Scaling to be used after Ipopt request improved solution (i.e. iterative refinement has failed)."), ("on_demand_reuse", "As on_demand, but reuse scaling from previous itr"), ("high_delay", "Scaling to be used after more than 0.05*n delays are present"), ("high_delay_reuse", "Scaling to be used only when previous itr created more that 0.05*n additional delays, otherwise reuse scaling from previous itr"), ("od_hd", "Combination of on_demand and high_delay"), ("od_hd_reuse", "Combination of on_demand_reuse and high_delay_reuse")], "If ma97_scaling=dynamic, ma97_scaling3 is enabled according to this condition.")?;
1070 r.add_string_option(
1071 "ma97_order",
1072 "Controls type of ordering",
1073 "auto",
1074 &[
1075 (
1076 "auto",
1077 "Use HSL_MA97 heuristic to guess best of AMD and METIS",
1078 ),
1079 ("best", "Try both AMD and MeTiS, pick best"),
1080 (
1081 "amd",
1082 "Use the HSL_MC68 approximate minimum degree algorithm",
1083 ),
1084 ("metis", "Use the MeTiS nested dissection algorithm"),
1085 (
1086 "matched-auto",
1087 "Use the HSL_MC80 matching with heuristic choice of AMD or METIS",
1088 ),
1089 (
1090 "matched-metis",
1091 "Use the HSL_MC80 matching based ordering with METIS",
1092 ),
1093 (
1094 "matched-amd",
1095 "Use the HSL_MC80 matching based ordering with AMD",
1096 ),
1097 ],
1098 "",
1099 )?;
1100 r.add_string_option(
1101 "ma97_dump_matrix",
1102 "Controls whether HSL_MA97 dumps each matrix to a file",
1103 "no",
1104 &[("no", "Do not dump matrix"), ("yes", "Do dump matrix")],
1105 "",
1106 )?;
1107 r.add_string_option(
1108 "ma97_solve_blas3",
1109 "Controls if blas2 or blas3 routines are used for solve",
1110 "no",
1111 &[
1112 (
1113 "no",
1114 "Use BLAS2 (faster, some implementations bit incompatible)",
1115 ),
1116 ("yes", "Use BLAS3 (slower)"),
1117 ],
1118 "",
1119 )?;
1120
1121 r.set_registering_category("Mumps Linear Solver");
1123 r.add_lower_bounded_integer_option("mumps_print_level", "Debug printing level for the linear solver MUMPS", 0, 0, "0: no printing; 1: Error messages only; 2: Error, warning, and main statistic messages; 3: Error and warning messages and terse diagnostics; >=4: All information.")?;
1124 r.add_bounded_number_option(
1125 "mumps_pivtol",
1126 "Pivot tolerance for the linear solver MUMPS.",
1127 0.0,
1128 false,
1129 1.0,
1130 false,
1131 1e-6,
1132 "A smaller number pivots for sparsity, a larger number pivots for stability.",
1133 )?;
1134 r.add_bounded_number_option("mumps_pivtolmax", "Maximum pivot tolerance for the linear solver MUMPS.", 0.0, false, 1.0, false, 0.1, "Ipopt may increase pivtol as high as pivtolmax to get a more accurate solution to the linear system.")?;
1135 r.add_lower_bounded_integer_option("mumps_mem_percent", "Percentage increase in the estimated working space for MUMPS.", 0, 1000, "When significant extra fill-in is caused by numerical pivoting, larger values of mumps_mem_percent may help use the workspace more efficiently. On the other hand, if memory requirement are too large at the very beginning of the optimization, choosing a much smaller value for this option, such as 5, might reduce memory requirements.")?;
1136 r.add_bounded_integer_option(
1137 "mumps_permuting_scaling",
1138 "Controls permuting and scaling in MUMPS",
1139 0,
1140 7,
1141 7,
1142 "This is ICNTL(6) in MUMPS.",
1143 )?;
1144 r.add_bounded_integer_option(
1145 "mumps_pivot_order",
1146 "Controls pivot order in MUMPS",
1147 0,
1148 7,
1149 7,
1150 "This is ICNTL(7) in MUMPS.",
1151 )?;
1152 r.add_bounded_integer_option(
1153 "mumps_scaling",
1154 "Controls scaling in MUMPS",
1155 -2,
1156 77,
1157 77,
1158 "This is ICNTL(8) in MUMPS.",
1159 )?;
1160 r.add_number_option("mumps_dep_tol", "Threshold to consider a pivot at zero in detection of linearly dependent constraints with MUMPS.", 0.0, "This is CNTL(3) in MUMPS.")?;
1161 r.add_integer_option("mumps_mpi_communicator", "MPI communicator used for matrix operations", -987654, "This sets the MPI communicator. MPI_COMM_WORLD is the default. Any other value should be the return value from MPI_Comm_c2f. This option is only available if MUMPS's libseq/mpi.h is not used.")?;
1162
1163 r.set_registering_category("Pardiso (pardiso-project.org) Linear Solver");
1165 r.add_string_option(
1166 "pardiso_matching_strategy",
1167 "Matching strategy to be used by Pardiso",
1168 "complete+2x2",
1169 &[
1170 ("complete", "Match complete (IPAR(13)=1)"),
1171 ("complete+2x2", "Match complete+2x2 (IPAR(13)=2)"),
1172 ("constraints", "Match constraints (IPAR(13)=3)"),
1173 ],
1174 "This is IPAR(13) in Pardiso manual.",
1175 )?;
1176 r.add_string_option("pardiso_redo_symbolic_fact_only_if_inertia_wrong", "Toggle for handling case when elements were perturbed by Pardiso.", "no", &[("no", "Always redo symbolic factorization when elements were perturbed"), ("yes", "Only redo symbolic factorization when elements were perturbed if also the inertia was wrong")], "")?;
1177 r.add_bool_option("pardiso_repeated_perturbation_means_singular", "Whether to assume that matrix is singular if elements were perturbed after recent symbolic factorization.", false, "")?;
1178 r.add_lower_bounded_integer_option(
1179 "pardiso_msglvl",
1180 "Pardiso message level",
1181 0,
1182 0,
1183 "This is MSGLVL in the Pardiso manual.",
1184 )?;
1185 r.add_bool_option("pardiso_skip_inertia_check", "Whether to pretend that inertia is correct.", false, "Setting this option to \"yes\" essentially disables inertia check. This option makes the algorithm non-robust and easily fail, but it might give some insight into the necessity of inertia control.")?;
1186 r.add_integer_option("pardiso_max_iterative_refinement_steps", "Limit on number of iterative refinement steps.", 0, "The solver does not perform more than the absolute value of this value steps of iterative refinement and stops the process if a satisfactory level of accuracy of the solution in terms of backward error is achieved. If negative, the accumulation of the residue uses extended precision real and complex data types. Perturbed pivots result in iterative refinement. The solver automatically performs two steps of iterative refinements when perturbed pivots are obtained during the numerical factorization and this option is set to 0.")?;
1187 r.add_string_option(
1188 "pardiso_order",
1189 "Controls the fill-in reduction ordering algorithm for the input matrix.",
1190 "metis",
1191 &[
1192 ("amd", "minimum degree algorithm"),
1193 ("one", ""),
1194 ("metis", "MeTiS nested dissection algorithm"),
1195 (
1196 "pmetis",
1197 "parallel (OpenMP) version of MeTiS nested dissection algorithm",
1198 ),
1199 ("four", ""),
1200 ("five", ""),
1201 ],
1202 "",
1203 )?;
1204 r.add_lower_bounded_integer_option(
1205 "pardiso_max_iter",
1206 "Maximum number of Krylov-Subspace Iteration",
1207 1,
1208 500,
1209 "DPARM(1)",
1210 )?;
1211 r.add_bounded_number_option(
1212 "pardiso_iter_relative_tol",
1213 "Relative Residual Convergence",
1214 0.0,
1215 true,
1216 1.0,
1217 true,
1218 1e-6,
1219 "DPARM(2)",
1220 )?;
1221 r.add_lower_bounded_integer_option(
1222 "pardiso_iter_coarse_size",
1223 "Maximum Size of Coarse Grid Matrix",
1224 1,
1225 5000,
1226 "DPARM(3)",
1227 )?;
1228 r.add_lower_bounded_integer_option(
1229 "pardiso_iter_max_levels",
1230 "Maximum Size of Grid Levels",
1231 1,
1232 10,
1233 "DPARM(4)",
1234 )?;
1235 r.add_bounded_number_option(
1236 "pardiso_iter_dropping_factor",
1237 "dropping value for incomplete factor",
1238 0.0,
1239 true,
1240 1.0,
1241 true,
1242 0.5,
1243 "DPARM(5)",
1244 )?;
1245 r.add_bounded_number_option(
1246 "pardiso_iter_dropping_schur",
1247 "dropping value for sparsify schur complement factor",
1248 0.0,
1249 true,
1250 1.0,
1251 true,
1252 1e-1,
1253 "DPARM(6)",
1254 )?;
1255 r.add_lower_bounded_integer_option(
1256 "pardiso_iter_max_row_fill",
1257 "max fill for each row",
1258 1,
1259 10000000,
1260 "DPARM(7)",
1261 )?;
1262 r.add_lower_bounded_number_option(
1263 "pardiso_iter_inverse_norm_factor",
1264 "",
1265 1.0,
1266 true,
1267 5000000.0,
1268 "DPARM(8)",
1269 )?;
1270 r.add_bool_option(
1271 "pardiso_iterative",
1272 "Switch for iterative solver in Pardiso library",
1273 false,
1274 "",
1275 )?;
1276 r.add_lower_bounded_integer_option(
1277 "pardiso_max_droptol_corrections",
1278 "Maximal number of decreases of drop tolerance during one solve.",
1279 1,
1280 4,
1281 "This is relevant only for iterative Pardiso options.",
1282 )?;
1283
1284 r.set_registering_category("Pardiso (MKL) Linear Solver");
1286 r.add_string_option(
1287 "pardisomkl_matching_strategy",
1288 "Matching strategy to be used by Pardiso",
1289 "complete+2x2",
1290 &[
1291 ("complete", "Match complete (IPAR(13)=1)"),
1292 ("complete+2x2", "Match complete+2x2 (IPAR(13)=2)"),
1293 ("constraints", "Match constraints (IPAR(13)=3)"),
1294 ],
1295 "This is IPAR(13) in Pardiso manual.",
1296 )?;
1297 r.add_string_option("pardisomkl_redo_symbolic_fact_only_if_inertia_wrong", "Toggle for handling case when elements were perturbed by Pardiso.", "no", &[("no", "Always redo symbolic factorization when elements were perturbed"), ("yes", "Only redo symbolic factorization when elements were perturbed if also the inertia was wrong")], "")?;
1298 r.add_bool_option("pardisomkl_repeated_perturbation_means_singular", "Whether to assume that matrix is singular if elements were perturbed after recent symbolic factorization.", false, "")?;
1299 r.add_lower_bounded_integer_option(
1300 "pardisomkl_msglvl",
1301 "Pardiso message level",
1302 0,
1303 0,
1304 "This is MSGLVL in the Pardiso manual.",
1305 )?;
1306 r.add_bool_option("pardisomkl_skip_inertia_check", "Whether to pretend that inertia is correct.", false, "Setting this option to \"yes\" essentially disables inertia check. This option makes the algorithm non-robust and easily fail, but it might give some insight into the necessity of inertia control.")?;
1307 r.add_integer_option("pardisomkl_max_iterative_refinement_steps", "Limit on number of iterative refinement steps.", 1, "The solver does not perform more than the absolute value of this value steps of iterative refinement and stops the process if a satisfactory level of accuracy of the solution in terms of backward error is achieved. If negative, the accumulation of the residue uses extended precision real and complex data types. Perturbed pivots result in iterative refinement. The solver automatically performs two steps of iterative refinements when perturbed pivots are obtained during the numerical factorization and this option is set to 0.")?;
1308 r.add_string_option(
1309 "pardisomkl_order",
1310 "Controls the fill-in reduction ordering algorithm for the input matrix.",
1311 "metis",
1312 &[
1313 ("amd", "minimum degree algorithm"),
1314 ("one", "undocumented"),
1315 ("metis", "MeTiS nested dissection algorithm"),
1316 (
1317 "pmetis",
1318 "parallel (OpenMP) version of MeTiS nested dissection algorithm",
1319 ),
1320 ],
1321 "",
1322 )?;
1323
1324 r.set_registering_category("SPRAL Linear Solver");
1326 r.add_lower_bounded_integer_option(
1327 "spral_cpu_block_size",
1328 "CPU Parallelization Block Size",
1329 1,
1330 256,
1331 "Block size to use for parallelization of large nodes on CPU resources.",
1332 )?;
1333 r.add_lower_bounded_number_option(
1334 "spral_gpu_perf_coeff",
1335 "GPU Performance Coefficient",
1336 0.0,
1337 true,
1338 1.0,
1339 "How many times faster a GPU is than a CPU at factoring a subtree.",
1340 )?;
1341 r.add_string_option(
1342 "spral_ignore_numa",
1343 "Non-uniform memory access (NUMA) region setting.",
1344 "yes",
1345 &[
1346 (
1347 "no",
1348 "Do not treat CPUs and GPUs as belonging to a single NUMA region.",
1349 ),
1350 (
1351 "yes",
1352 "Treat CPUs and GPUs as belonging to a single NUMA region.",
1353 ),
1354 ],
1355 "",
1356 )?;
1357 r.add_lower_bounded_number_option(
1358 "spral_max_load_inbalance",
1359 "Maximum Permissible Load",
1360 1.0,
1361 true,
1362 1.2,
1363 "Maximum permissible load inbalance for leaf subtree allocations.",
1364 )?;
1365 r.add_lower_bounded_number_option(
1366 "spral_min_gpu_work",
1367 "Minimum GPU Work",
1368 0.0,
1369 false,
1370 5.0e9,
1371 "Minimum number of FLOPS in subtree before scheduling on GPU.",
1372 )?;
1373 r.add_lower_bounded_integer_option("spral_nemin", "Node Amalgamation Parameter", 1, 32, "Two nodes in the elimination tree are merged if the result has fewer than spral_nemin variables.")?;
1374 r.add_string_option(
1375 "spral_order",
1376 "Controls type of ordering used by SPRAL",
1377 "matching",
1378 &[
1379 ("metis", "Use METIS with default settings."),
1380 ("matching", "Use matching-based elimination ordering."),
1381 ],
1382 "",
1383 )?;
1384 r.add_string_option(
1385 "spral_pivot_method",
1386 "Specifies strategy for scaling in SPRAL linear solver.",
1387 "block",
1388 &[
1389 ("aggressive", "Aggressive a posteori pivoting."),
1390 ("block", "Block a posteori pivoting."),
1391 ("threshold", "Threshold partial pivoting (not parallel)."),
1392 ],
1393 "",
1394 )?;
1395 r.add_integer_option("spral_print_level", "Print level for the linear solver SPRAL", -1, "<0: no printing, 0: errors and warning messages, 1: limited diagnostics, >1: additional diagnostics")?;
1396 r.add_string_option(
1397 "spral_scaling",
1398 "Specifies strategy for scaling in SPRAL linear solver.",
1399 "matching",
1400 &[
1401 ("none", "Do not scale the linear system matrix."),
1402 ("mc64", "Scale using weighted bipartite matching (MC64)."),
1403 ("auction", "Scale using the auction algorithm."),
1404 ("matching", "Scale using the matching-based ordering."),
1405 (
1406 "ruiz",
1407 "Scale using the norm-equilibration algorithm of Ruiz (MC77).",
1408 ),
1409 (
1410 "dynamic",
1411 "Dynamically select scaling according to switch options.",
1412 ),
1413 ],
1414 "",
1415 )?;
1416 r.add_string_option("spral_scaling_1", "First scaling strategy.", "matching", &[("none", "Do not scale the linear system matrix."), ("mc64", "Scale using weighted bipartite matching (MC64)."), ("auction", "Scale using the auction algorithm."), ("matching", "Scale using the matching-based ordering."), ("ruiz", "Scale using the norm-equilibration algorithm of Ruiz (MC77).")], "If spral_scaling = dynamic, this scaling is used according to the trigger spral_switch_1. If spral_switch_2 is triggered, it is disabled.")?;
1417 r.add_string_option("spral_scaling_2", "Second scaling strategy.", "mc64", &[("none", "Do not scale the linear system matrix."), ("mc64", "Scale using weighted bipartite matching (MC64)."), ("auction", "Scale using the auction algorithm."), ("matching", "Scale using the matching-based ordering."), ("ruiz", "Scale using the norm-equilibration algorithm of Ruiz (MC77).")], "If spral_scaling = dynamic, this scaling is used according to the trigger spral_switch_2. If spral_switch_3 is triggered, it is disabled.")?;
1418 r.add_string_option(
1419 "spral_scaling_3",
1420 "Third scaling strategy.",
1421 "none",
1422 &[
1423 ("none", "Do not scale the linear system matrix."),
1424 ("mc64", "Scale using weighted bipartite matching (MC64)."),
1425 ("auction", "Scale using the auction algorithm."),
1426 ("matching", "Scale using the matching-based ordering."),
1427 (
1428 "ruiz",
1429 "Scale using the norm-equilibration algorithm of Ruiz (MC77).",
1430 ),
1431 ],
1432 "If spral_scaling = dynamic, this scaling is used according to the trigger spral_switch_3.",
1433 )?;
1434 r.add_string_option("spral_switch_1", "First switch, determining when spral_scaling_1 is enabled.", "at_start", &[("never", "Scaling is never enabled."), ("at_start", "Scaling is used from the very start."), ("at_start_reuse", "Scaling is used on the first iteration, then reused thereafter."), ("on_demand", "Scaling is used when iterative refinement has failed."), ("on_demand_reuse", "As on_demand, but scaling from previous iteration is reused."), ("high_delay", "Scaling is used after more than 0.05*n delays are present."), ("high_delay_reuse", "Scaling is used only when previous iteration created more that 0.05*n additional delays; otherwise, reuse scaling from the previous iteration."), ("od_hd", "Combination of on_demand and high_delay."), ("od_hd_reuse", "Combination of on_demand_reuse and high_delay_reuse")], "If spral_scaling = dynamic, spral_scaling_1 is enabled according to this condition. If spral_switch_2 occurs, this option is henceforth ignored.")?;
1435 r.add_string_option("spral_switch_2", "Second switch, determining when spral_scaling_2 is enabled.", "on_demand", &[("never", "Scaling is never enabled."), ("at_start", "Scaling is used from the very start."), ("at_start_reuse", "Scaling is used on the first iteration, then reused thereafter."), ("on_demand", "Scaling is used when iterative refinement has failed."), ("on_demand_reuse", "As on_demand, but scaling from previous iteration is reused."), ("high_delay", "Scaling is used after more than 0.05*n delays are present."), ("high_delay_reuse", "Scaling is used only when previous iteration created more that 0.05*n additional delays; otherwise, reuse scaling from the previous iteration."), ("od_hd", "Combination of on_demand and high_delay."), ("od_hd_reuse", "Combination of on_demand_reuse and high_delay_reuse")], "If spral_scaling = dynamic, spral_scaling_2 is enabled according to this condition. If spral_switch_3 occurs, this option is henceforth ignored.")?;
1436 r.add_string_option("spral_switch_3", "Third switch, determining when spral_scaling_3 is enabled.", "never", &[("never", "Scaling is never enabled."), ("at_start", "Scaling is used from the very start."), ("at_start_reuse", "Scaling is used on the first iteration, then reused thereafter."), ("on_demand", "Scaling is used when iterative refinement has failed."), ("on_demand_reuse", "As on_demand, but scaling from previous iteration is reused."), ("high_delay", "Scaling is used after more than 0.05*n delays are present."), ("high_delay_reuse", "Scaling is used only when previous iteration created more that 0.05*n additional delays; otherwise, reuse scaling from the previous iteration."), ("od_hd", "Combination of on_demand and high_delay."), ("od_hd_reuse", "Combination of on_demand_reuse and high_delay_reuse")], "If spral_scaling = dynamic, spral_scaling_3 is enabled according to this condition.")?;
1437 r.add_lower_bounded_number_option(
1438 "spral_small",
1439 "Zero Pivot Threshold",
1440 0.0,
1441 true,
1442 1.0e-20,
1443 "Any pivot less than spral_small is treated as zero.",
1444 )?;
1445 r.add_lower_bounded_number_option(
1446 "spral_small_subtree_threshold",
1447 "Small Subtree Threshold",
1448 0.0,
1449 true,
1450 4.0e6,
1451 "Maximum number of FLOPS in a subtree treated as a single task.",
1452 )?;
1453 r.add_bounded_number_option(
1454 "spral_u",
1455 "Pivoting Threshold",
1456 0.0,
1457 true,
1458 0.5,
1459 false,
1460 1.0e-8,
1461 "Relative pivot threshold used in symmetric indefinite case.",
1462 )?;
1463 r.add_bounded_number_option(
1464 "spral_umax",
1465 "Maximum Pivoting Threshold",
1466 0.0,
1467 true,
1468 0.5,
1469 false,
1470 1.0e-4,
1471 "See SPRAL documentation.",
1472 )?;
1473 r.add_bool_option("spral_use_gpu", "Specifies whether or not graphics processing units (GPUs) are used by the SPRAL linear solver if present.", true, "")?;
1474
1475 r.set_registering_category("WSMP Linear Solver");
1477 r.add_integer_option(
1478 "wsmp_num_threads",
1479 "Number of threads to be used in WSMP",
1480 1,
1481 "",
1482 )?;
1483 r.add_bounded_integer_option(
1484 "wsmp_ordering_option",
1485 "Determines how ordering is done in WSMP",
1486 -2,
1487 3,
1488 1,
1489 "This corresponds to the value of WSSMP's IPARM(16).",
1490 )?;
1491 r.add_bounded_integer_option(
1492 "wsmp_ordering_option2",
1493 "Determines how ordering is done in WSMP",
1494 0,
1495 3,
1496 1,
1497 "This corresponds to the value of WSSMP's IPARM(20).",
1498 )?;
1499 r.add_bounded_number_option(
1500 "wsmp_pivtol",
1501 "Pivot tolerance for the linear solver WSMP.",
1502 0.0,
1503 true,
1504 1.0,
1505 true,
1506 1e-4,
1507 "A smaller number pivots for sparsity, a larger number pivots for stability.",
1508 )?;
1509 r.add_bounded_number_option("wsmp_pivtolmax", "Maximum pivot tolerance for the linear solver WSMP.", 0.0, true, 1.0, true, 1e-1, "Ipopt may increase pivtol as high as pivtolmax to get a more accurate solution to the linear system.")?;
1510 r.add_bounded_integer_option(
1511 "wsmp_scaling",
1512 "Determines how the matrix is scaled by WSMP.",
1513 0,
1514 3,
1515 0,
1516 "This corresponds to the value of WSSMP's IPARM(10).",
1517 )?;
1518 r.add_bounded_number_option("wsmp_singularity_threshold", "WSMP's singularity threshold.", 0.0, true, 1.0, true, 1e-18, "WSMP's DPARM(10) parameter. The smaller this value the less likely a matrix is declared singular.")?;
1519 r.add_lower_bounded_integer_option("wsmp_write_matrix_iteration", "Iteration in which the matrices are written to files.", -1, -1, "If non-negative, this option determines the iteration in which all matrices given to WSMP are written to files.")?;
1520 r.add_bool_option("wsmp_skip_inertia_check", "Whether to always pretend that inertia is correct.", false, "Setting this option to \"yes\" essentially disables inertia check. This option makes the algorithm non-robust and easily fail, but it might give some insight into the necessity of inertia control.")?;
1521 r.add_string_option("wsmp_no_pivoting", "Whether to use the static pivoting option of WSMP.", "no", &[("no", "use the regular version"), ("yes", "use static pivoting")], "Setting this option to \"yes\" means that WSMP is instructed not to do pivoting. This works only in certain situations (when the Hessian block is known to be positive definite or when we are using L-BFGS). It can also lead to a lot of fill-in.")?;
1522
1523 r.set_registering_category("WSMP Linear Solver");
1525 r.add_lower_bounded_integer_option(
1526 "wsmp_max_iter",
1527 "Maximal number of iterations in iterative WISMP",
1528 1,
1529 1000,
1530 "",
1531 )?;
1532 r.add_lower_bounded_number_option(
1533 "wsmp_inexact_droptol",
1534 "Drop tolerance for inexact factorization preconditioner in WISMP.",
1535 0.0,
1536 false,
1537 0.0,
1538 "DPARM(14) in WISMP",
1539 )?;
1540 r.add_lower_bounded_number_option(
1541 "wsmp_inexact_fillin_limit",
1542 "Fill-in limit for inexact factorization preconditioner in WISMP.",
1543 0.0,
1544 false,
1545 0.0,
1546 "DPARM(15) in WISMP",
1547 )?;
1548
1549 r.set_registering_category("MA28 Linear Solver");
1551 r.add_bounded_number_option(
1552 "ma28_pivtol",
1553 "Pivot tolerance for linear solver MA28.",
1554 0.0,
1555 true,
1556 1.0,
1557 false,
1558 0.01,
1559 "",
1560 )?;
1561
1562 r.set_registering_category("L1 Exact Penalty-Barrier Wrapper");
1569 r.add_bool_option(
1570 "l1_exact_penalty_barrier",
1571 "Wrap the NLP in the Thierry-Biegler ℓ₁ penalty-barrier reformulation before solving.",
1572 false,
1573 "When set, every equality row c_i(x)=g_i is rewritten as c_i(x)-p_i+n_i=g_i with non-negative slack pair (p_i, n_i), and the objective is augmented by ρ·Σ(p+n). The augmented NLP automatically satisfies LICQ on the slack variables, which makes the standard interior-point machinery handle degenerate / MPCC-like cases that the stock filter line search thrashes on. Default off; the solve trajectory is byte-identical to pre-l1 pounce when off.",
1574 )?;
1575 r.add_lower_bounded_number_option(
1576 "l1_penalty_init",
1577 "Initial value of the penalty weight ρ in the ℓ₁ wrapper.",
1578 0.0,
1579 true,
1580 1.0,
1581 "Initial ρ. After each inner solve the Byrd-Nocedal-Waltz steering rule escalates ρ until the slacks collapse or the maximum is reached.",
1582 )?;
1583 r.add_lower_bounded_number_option(
1584 "l1_penalty_max",
1585 "Upper cap on the ℓ₁ penalty weight ρ.",
1586 0.0,
1587 true,
1588 1.0e6,
1589 "BNW steering increases ρ but never above this cap. If the cap is reached with non-collapsed slacks, the original problem is locally infeasible at the returned ℓ₁-best point and the status is upgraded to LocalInfeasibility / Infeasible_Problem_Detected.",
1590 )?;
1591 r.add_lower_bounded_number_option(
1592 "l1_penalty_increase_factor",
1593 "Geometric ρ-escalation factor.",
1594 1.0,
1595 false,
1596 8.0,
1597 "Multiplicative floor on ρ growth between outer iterations. The BNW rule sets ρ_new = max(ρ·factor, τ·‖y_eq‖∞ + ε), so factor sets the slowest sustained growth rate.",
1598 )?;
1599 r.add_lower_bounded_integer_option(
1600 "l1_penalty_max_outer_iter",
1601 "Maximum number of outer ρ-escalation steps.",
1602 1,
1603 8,
1604 "Caps the number of inner-solve cycles the wrapper runs. Slack-collapse termination is the usual exit; this is a safety bound for pathological problems where the BNW rule plateaus.",
1605 )?;
1606 r.add_lower_bounded_number_option(
1607 "l1_slack_tol",
1608 "Slack-sum tolerance for termination and honest-infeasibility upgrade.",
1609 0.0,
1610 true,
1611 1.0e-6,
1612 "Σ(p+n) ≤ tol counts as the original constraints being satisfied. Σ(p+n) > tol after ρ saturates triggers the honest-infeasibility upgrade — the returned point is the ℓ₁-best least-infeasible iterate, status is overridden to Infeasible_Problem_Detected.",
1613 )?;
1614 r.add_lower_bounded_number_option(
1615 "l1_steering_factor",
1616 "BNW steering factor τ relating ρ to ‖y_eq‖∞.",
1617 0.0,
1618 true,
1619 10.0,
1620 "BNW chooses ρ_new = max(ρ·factor, τ·‖y_eq‖∞ + ε). τ>1 ensures the augmented (p,n) bound multipliers z_p = ρ-y_eq, z_n = ρ+y_eq remain strictly positive and bounded away from 0, which is the property the slack-collapse argument relies on.",
1621 )?;
1622 r.add_bool_option(
1623 "l1_fallback_on_restoration_failure",
1624 "Auto-retry with the ℓ₁ wrapper when the standard solve hits a non-success terminal status.",
1625 false,
1626 "When set, optimize_tnlp first runs the standard solve. If it terminates in Restoration_Failed / Infeasible_Problem_Detected / Solved_To_Acceptable_Level / Maximum_Iterations_Exceeded / Not_Enough_Degrees_Of_Freedom, the wrapper is enabled and the solve is repeated. The retry's status replaces the original ONLY if the retry returns Solve_Succeeded (promotion); otherwise the original status is returned. NOTE: the user TNLP's finalize_solution is called once per attempt, so when the retry doesn't promote the user's captured fields hold the retry's iterate (the ℓ₁-best least-infeasible point) even though the returned status is the original's — pounce#10 Phase-4 note.",
1627 )?;
1628
1629 register_sipopt_options(r)?;
1630
1631 Ok(())
1632}
1633
1634fn register_sipopt_options(r: &RegisteredOptions) -> Result<(), SolverException> {
1644 r.set_registering_category("sIPOPT");
1645 r.add_lower_bounded_integer_option(
1646 "n_sens_steps",
1647 "Number of sensitivity steps to perform per converged solve.",
1648 0,
1649 1,
1650 "Number of parameter perturbations to step through. Mirrors upstream `n_sens_steps` (SensApplication.cpp:60).",
1651 )?;
1652 r.add_bool_option(
1653 "compute_red_hessian",
1654 "Compute the reduced Hessian at the converged solution.",
1655 false,
1656 "When set, after the IPM converges pounce-sensitivity assembles `H_R = obj_scal · B K⁻¹ Bᵀ` with B selecting the free variables. Output is written to the user via the sIPOPT C ABI (Phase D follow-up). Mirrors upstream `compute_red_hessian` (SensApplication.cpp:73).",
1657 )?;
1658 r.add_bool_option(
1659 "run_sens",
1660 "Run the sensitivity step calc after convergence.",
1661 false,
1662 "When set, pounce-sensitivity computes a forward-sensitivity step for the parameter perturbation declared via TNLP suffixes. Mirrors upstream `run_sens` (SensApplication.cpp:80).",
1663 )?;
1664 r.add_bool_option(
1665 "sens_boundcheck",
1666 "Verify the sensitivity step does not violate bound multipliers.",
1667 false,
1668 "Mirrors upstream `sens_boundcheck` (SensApplication.cpp:63).",
1669 )?;
1670 r.add_lower_bounded_number_option(
1671 "sens_bound_eps",
1672 "Safety margin enforced when sens_boundcheck is set.",
1673 0.0,
1674 true,
1675 1.0e-3,
1676 "Mirrors upstream `sens_bound_eps` (SensApplication.cpp:67).",
1677 )?;
1678 r.add_lower_bounded_number_option(
1679 "sens_max_pdpert",
1680 "Maximum primal-dual perturbation accepted in the sensitivity step.",
1681 0.0,
1682 true,
1683 1.0e-3,
1684 "Mirrors upstream `sens_max_pdpert` (SensApplication.cpp:98).",
1685 )?;
1686 r.add_bool_option(
1687 "rh_eigendecomp",
1688 "Compute eigendecomposition of the reduced Hessian.",
1689 false,
1690 "Mirrors upstream `rh_eigendecomp` (SensApplication.cpp:106). Pounce ships the option key for ipopt.opt-compatibility; the eigendecomposition itself is a Phase-D follow-up.",
1691 )?;
1692 Ok(())
1693}