pub struct PresolveOptions {Show 20 fields
pub enabled: bool,
pub bound_tightening: bool,
pub redundant_constraint_removal: bool,
pub linear_eq_reduction: bool,
pub licq_check: bool,
pub print_level: Index,
pub max_passes: Index,
pub licq_action: LicqAction,
pub warm_z_bounds: bool,
pub bound_mult_init_val: Number,
pub auxiliary: bool,
pub auxiliary_tol: Number,
pub auxiliary_max_block_dim: Index,
pub auxiliary_wall_time_fraction: Number,
pub auxiliary_coupling: AuxiliaryCouplingPolicy,
pub auxiliary_diagnostics: bool,
pub fbbt: bool,
pub fbbt_tol: Number,
pub fbbt_max_iter: Index,
pub fbbt_max_constraints: Index,
}Expand description
Resolved presolve options, materialised from an OptionsList.
Keeping this as a plain Copy struct makes Phase 0’s no-op path
branch-free; later phases that grow more state can promote it to
a Clone struct without API churn.
Fields§
§enabled: boolMaster switch (presolve). When false, the wrapper is a
no-op and wrap_with_presolve returns the inner TNLP.
bound_tightening: boolpresolve_bound_tightening — Phase 1.
redundant_constraint_removal: boolpresolve_redundant_constraint_removal — Phase 2.
linear_eq_reduction: boolpresolve_linear_eq_reduction — Phase ≥2, off by default.
licq_check: boolpresolve_licq_check — Phase 3.
print_level: Indexpresolve_print_level — 0 silent, 5 per-pass, 8 per-xform.
max_passes: Indexpresolve_max_passes — fixed-point iteration cap.
licq_action: LicqActionpresolve_licq_action — what to do on degenerate equality
rows. Phase 3 honours auto_l1; Phase 0 just stores it.
warm_z_bounds: boolpresolve_warm_z_bounds — Phase 4: hint bound-multiplier
warm starts for variables whose bounds were tightened.
bound_mult_init_val: Numberpresolve_bound_mult_init_val — value used for those hints.
auxiliary: boolpresolve_auxiliary — master switch for the Phase-0
auxiliary-equality preprocessing pass (issue #53). When
false (the default), Phase 0 is a no-op even if the outer
enabled master switch is on.
auxiliary_tol: Numberpresolve_auxiliary_tol — residual tolerance for accepting a
candidate block solve (full-space KKT residual after the
reduction must stay within this).
auxiliary_max_block_dim: Indexpresolve_auxiliary_max_block_dim — the lightweight Newton
solver only handles blocks up to this dimension. PR 11 lifts
this by injecting an IPM-backed fallback.
auxiliary_wall_time_fraction: Numberpresolve_auxiliary_wall_time_fraction — fraction of the
solver’s overall wall-time budget Phase 0 is allowed to spend.
auxiliary_coupling: AuxiliaryCouplingPolicypresolve_auxiliary_coupling — which coupling classes are
eligible for elimination.
auxiliary_diagnostics: boolpresolve_auxiliary_diagnostics — emit the diagnostics struct
via the journalist.
fbbt: boolpresolve_fbbt — Feasibility-Based Bound Tightening over
nonlinear constraint expression DAGs (issue #62). Off by
default until benchmark evidence justifies a flip.
fbbt_tol: Numberfbbt_tol — minimum bound improvement to keep iterating.
fbbt_max_iter: Indexfbbt_max_iter — outer sweep cap.
fbbt_max_constraints: Indexfbbt_max_constraints — cap on constraints examined per
sweep; 0 means unlimited.
Implementations§
Source§impl PresolveOptions
impl PresolveOptions
Sourcepub fn defaults() -> Self
pub fn defaults() -> Self
All-default settings, matching the registered defaults.
Examples found in repository?
78fn main() {
79 let opts = PresolveOptions {
80 enabled: true,
81 auxiliary: true,
82 auxiliary_coupling: AuxiliaryCouplingPolicy::Safe,
83 auxiliary_diagnostics: true,
84 ..PresolveOptions::defaults()
85 };
86 let inner: Rc<RefCell<dyn TNLP>> = Rc::new(RefCell::new(Mini));
87 let wrapped = wrap_with_presolve(inner, opts).expect("wrap ok");
88
89 // Trigger lazy init through any TNLP method.
90 let info = wrapped.borrow_mut().get_nlp_info().expect("get_nlp_info");
91
92 // Force one Jacobian-values call so the example exercises the
93 // forwarding path (the wrapper does not change anything in PR 1).
94 let mut values = vec![0.0; info.nnz_jac_g as usize];
95 let ok = wrapped.borrow_mut().eval_jac_g(
96 Some(&[0.5, 0.5]),
97 true,
98 SparsityRequest::Values {
99 values: &mut values,
100 },
101 );
102 assert!(ok, "eval_jac_g(Values) must succeed");
103
104 // Downcast back to PresolveTnlp via a typed handle would require
105 // a different constructor; instead, build a second wrapper using
106 // PresolveTnlp::new so we can read the diagnostics.
107 let inner2: Rc<RefCell<dyn TNLP>> = Rc::new(RefCell::new(Mini));
108 let mut typed = PresolveTnlp::new(inner2, opts);
109 let _ = typed.get_nlp_info();
110 let d = typed.auxiliary_diagnostics();
111
112 println!("auxiliary_noop example — PR 1 of pounce#53");
113 println!(
114 "inner shape: n={}, m={}, nnz_jac_g={}",
115 info.n, info.m, info.nnz_jac_g
116 );
117 println!("jac values at (0.5, 0.5): {:?}", values);
118 println!(
119 "diagnostics: blocks_eliminated={}, vars_eliminated={}, rows_eliminated={}, total_time_ms={}",
120 d.blocks_eliminated, d.vars_eliminated, d.rows_eliminated, d.total_time_ms,
121 );
122 println!("rejection_reasons: {:?}", d.rejection_reasons);
123}More examples
121fn main() {
122 let opts = PresolveOptions {
123 enabled: true,
124 auxiliary: true,
125 // Aggressive lets us eliminate even when grad_f is non-zero
126 // at the block variables at the probe (ObjectiveCoupled).
127 auxiliary_coupling: AuxiliaryCouplingPolicy::Aggressive,
128 ..PresolveOptions::defaults()
129 };
130 let inner: Rc<RefCell<dyn TNLP>> = Rc::new(RefCell::new(Mini));
131 let wrapped = wrap_with_presolve(inner, opts).expect("wrap ok");
132
133 let info = wrapped.borrow_mut().get_nlp_info().expect("init");
134 println!("phase0_via_tnlp — PR 8 of pounce#53");
135 println!("====================================");
136 println!("Inner TNLP: n=2, m=2 (two equalities).");
137 println!("After PresolveTnlp wrapping with presolve_auxiliary=yes:");
138 println!(" outer n = {}", info.n);
139 println!(" outer m = {}", info.m);
140 println!(" outer nnz_jac_g = {}", info.nnz_jac_g);
141
142 // Read the clamped bounds.
143 let mut x_l = vec![0.0; info.n as usize];
144 let mut x_u = vec![0.0; info.n as usize];
145 let mut g_l = vec![0.0; info.m as usize];
146 let mut g_u = vec![0.0; info.m as usize];
147 wrapped.borrow_mut().get_bounds_info(BoundsInfo {
148 x_l: &mut x_l,
149 x_u: &mut x_u,
150 g_l: &mut g_l,
151 g_u: &mut g_u,
152 });
153 println!("\nClamped bounds (from PresolveTnlp):");
154 println!(" x_l = {:?}", x_l);
155 println!(" x_u = {:?}", x_u);
156 println!(" g_l = {:?}", g_l);
157
158 // Simulate the IPM handing back a solution: the eliminated vars
159 // are pinned to their clamps; outer lambda is empty (no rows).
160 let sol_x = [x_l[0], x_l[1]];
161 let sol_z_l = vec![0.0; info.n as usize];
162 let sol_z_u = vec![0.0; info.n as usize];
163 let sol_lambda: Vec<Number> = Vec::new(); // outer m == 0
164 let sol_g: Vec<Number> = Vec::new();
165 let ip_data = IpoptData::default();
166 let ip_cq = IpoptCq::default();
167 wrapped.borrow_mut().finalize_solution(
168 Solution {
169 status: SolverReturn::Success,
170 x: &sol_x,
171 z_l: &sol_z_l,
172 z_u: &sol_z_u,
173 g: &sol_g,
174 lambda: &sol_lambda,
175 obj_value: 0.0,
176 },
177 &ip_data,
178 &ip_cq,
179 );
180
181 println!("\n✓ End-to-end orchestrator path exercised.");
182}Sourcepub fn from_options_list(opts: &OptionsList) -> Result<Self, SolverException>
pub fn from_options_list(opts: &OptionsList) -> Result<Self, SolverException>
Read every presolve_* key out of an OptionsList, falling
back to registered defaults where unset.
Trait Implementations§
Source§impl Clone for PresolveOptions
impl Clone for PresolveOptions
Source§fn clone(&self) -> PresolveOptions
fn clone(&self) -> PresolveOptions
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more