1use pounce_common::types::{Index, Number};
16use pounce_nlp::tnlp::{
17 BoundsInfo, InfeasibilityProof, IpoptCq, IpoptData, IterStats, Linearity, MetaData, NlpInfo,
18 ScalingRequest, Solution, SparsityRequest, StartingPoint, TNLP,
19};
20use std::cell::{Cell, RefCell};
21use std::rc::Rc;
22
23pub struct CountingTnlp {
24 inner: Rc<RefCell<dyn TNLP>>,
25 pub n_obj: Cell<i32>,
26 pub n_grad_f: Cell<i32>,
27 pub n_g: Cell<i32>,
28 pub n_jac_g: Cell<i32>,
29 pub n_h: Cell<i32>,
30 captured_solution: RefCell<Option<(Vec<Number>, Vec<Number>)>>,
36 captured_bound_mults: RefCell<Option<(Vec<Number>, Vec<Number>)>>,
49}
50
51impl CountingTnlp {
52 pub fn new(inner: Rc<RefCell<dyn TNLP>>) -> Self {
53 Self {
54 inner,
55 n_obj: Cell::new(0),
56 n_grad_f: Cell::new(0),
57 n_g: Cell::new(0),
58 n_jac_g: Cell::new(0),
59 n_h: Cell::new(0),
60 captured_solution: RefCell::new(None),
61 captured_bound_mults: RefCell::new(None),
62 }
63 }
64
65 pub fn captured_solution(&self) -> Option<(Vec<Number>, Vec<Number>)> {
67 self.captured_solution.borrow().clone()
68 }
69
70 pub fn captured_bound_mults(&self) -> Option<(Vec<Number>, Vec<Number>)> {
76 self.captured_bound_mults.borrow().clone()
77 }
78}
79
80impl TNLP for CountingTnlp {
81 fn get_nlp_info(&mut self) -> Option<NlpInfo> {
82 self.inner.borrow_mut().get_nlp_info()
83 }
84
85 fn get_bounds_info(&mut self, b: BoundsInfo<'_>) -> bool {
86 self.inner.borrow_mut().get_bounds_info(b)
87 }
88
89 fn get_starting_point(&mut self, sp: StartingPoint<'_>) -> bool {
90 self.inner.borrow_mut().get_starting_point(sp)
91 }
92
93 fn eval_f(&mut self, x: &[Number], new_x: bool) -> Option<Number> {
94 self.n_obj.set(self.n_obj.get() + 1);
95 self.inner.borrow_mut().eval_f(x, new_x)
96 }
97
98 fn eval_grad_f(&mut self, x: &[Number], new_x: bool, grad_f: &mut [Number]) -> bool {
99 self.n_grad_f.set(self.n_grad_f.get() + 1);
100 self.inner.borrow_mut().eval_grad_f(x, new_x, grad_f)
101 }
102
103 fn eval_g(&mut self, x: &[Number], new_x: bool, g: &mut [Number]) -> bool {
104 self.n_g.set(self.n_g.get() + 1);
105 self.inner.borrow_mut().eval_g(x, new_x, g)
106 }
107
108 fn eval_jac_g(&mut self, x: Option<&[Number]>, new_x: bool, mode: SparsityRequest<'_>) -> bool {
109 if matches!(mode, SparsityRequest::Values { .. }) {
112 self.n_jac_g.set(self.n_jac_g.get() + 1);
113 }
114 self.inner.borrow_mut().eval_jac_g(x, new_x, mode)
115 }
116
117 fn eval_h(
118 &mut self,
119 x: Option<&[Number]>,
120 new_x: bool,
121 obj_factor: Number,
122 lambda: Option<&[Number]>,
123 new_lambda: bool,
124 mode: SparsityRequest<'_>,
125 ) -> bool {
126 if matches!(mode, SparsityRequest::Values { .. }) {
127 self.n_h.set(self.n_h.get() + 1);
128 }
129 self.inner
130 .borrow_mut()
131 .eval_h(x, new_x, obj_factor, lambda, new_lambda, mode)
132 }
133
134 fn finalize_solution(&mut self, sol: Solution<'_>, ip_data: &IpoptData, ip_cq: &IpoptCq) {
135 *self.captured_solution.borrow_mut() = Some((sol.x.to_vec(), sol.lambda.to_vec()));
136 *self.captured_bound_mults.borrow_mut() = Some((sol.z_l.to_vec(), sol.z_u.to_vec()));
137 self.inner
138 .borrow_mut()
139 .finalize_solution(sol, ip_data, ip_cq);
140 }
141
142 fn get_var_con_metadata(&mut self, var: &mut MetaData, con: &mut MetaData) -> bool {
143 self.inner.borrow_mut().get_var_con_metadata(var, con)
144 }
145
146 fn get_scaling_parameters(&mut self, req: ScalingRequest<'_>) -> bool {
147 self.inner.borrow_mut().get_scaling_parameters(req)
148 }
149
150 fn get_variables_linearity(&mut self, types: &mut [Linearity]) -> bool {
151 self.inner.borrow_mut().get_variables_linearity(types)
152 }
153
154 fn get_objective_variables_linearity(&mut self, types: &mut [Linearity]) -> bool {
155 self.inner
156 .borrow_mut()
157 .get_objective_variables_linearity(types)
158 }
159
160 fn get_constraints_linearity(&mut self, types: &mut [Linearity]) -> bool {
165 self.inner.borrow_mut().get_constraints_linearity(types)
166 }
167
168 fn get_number_of_nonlinear_variables(&mut self) -> Index {
169 self.inner.borrow_mut().get_number_of_nonlinear_variables()
170 }
171
172 fn derivative_proofs(&mut self) -> pounce_nlp::constant_derivatives::DerivativeProofs {
179 self.inner.borrow_mut().derivative_proofs()
180 }
181
182 fn get_list_of_nonlinear_variables(&mut self, pos: &mut [Index]) -> bool {
183 self.inner.borrow_mut().get_list_of_nonlinear_variables(pos)
184 }
185
186 fn intermediate_callback(
187 &mut self,
188 stats: IterStats,
189 ip_data: &IpoptData,
190 ip_cq: &IpoptCq,
191 ) -> bool {
192 self.inner
193 .borrow_mut()
194 .intermediate_callback(stats, ip_data, ip_cq)
195 }
196
197 fn finalize_metadata(&mut self, var: &MetaData, con: &MetaData) {
198 self.inner.borrow_mut().finalize_metadata(var, con)
199 }
200
201 fn presolve_infeasibility_proof(&self) -> Option<InfeasibilityProof> {
206 self.inner.borrow().presolve_infeasibility_proof()
207 }
208}