1use crate::logdet_bounds::{LogdetEnclosure, MarginVerdict};
21use crate::model_types::CriterionCertificate;
22use crate::row_sampling_measure::{CoresetCertificate, CoresetMarginVerdict};
23use crate::structure_search::{CollapseAction, CollapseEvent};
24use gam_problem::topology_certificates::{Certificate, Claim, Evidence, Verdict};
25
26fn put_finite(evidence: &mut Evidence, key: &'static str, value: f64) {
29 if value.is_finite() {
30 evidence.insert(key, value.into());
31 } else {
32 evidence.insert(key, "n/a".into());
33 }
34}
35
36impl Certificate for CriterionCertificate {
39 fn claim(&self) -> Claim {
40 Claim::new(
41 "outer-optimality",
42 concat!(
43 "the returned outer optimum is a genuine stationary point: the ", "analytic gradient agrees with the finite-difference of the criterion ", "value, the final Hessian is not indefinite, and no smoothing ",
46 "coordinate is railed at a box bound",
47 ),
48 )
49 }
50
51 fn evidence(&self) -> Evidence {
52 let mut e = Evidence::new();
53 put_finite(&mut e, "grad_norm", self.grad_norm);
54 put_finite(&mut e, "analytic_directional", self.analytic_directional);
55 put_finite(&mut e, "fd_directional", self.fd_directional); put_finite(&mut e, "fd_error", self.fd_error); put_finite(&mut e, "agreement_z", self.agreement_z);
58 put_finite(&mut e, "fd_step", self.fd_step); e.insert(
60 "hessian_pd",
61 match self.hessian_pd {
62 Some(pd) => pd.into(),
63 None => "n/a".into(),
64 },
65 );
66 e.insert("lambdas_railed_count", self.lambdas_railed.len().into());
67 e.insert(
68 "first_order_consistent",
69 self.first_order_consistent().into(),
70 );
71 e.insert("summary", self.summary().into());
72 e
73 }
74
75 fn verdict(&self) -> Verdict {
76 if self.is_clean() {
81 Verdict::Certified
82 } else {
83 Verdict::Insufficient
84 }
85 }
86}
87
88impl Certificate for CoresetCertificate {
91 fn claim(&self) -> Claim {
92 Claim::new(
93 "coreset-budget",
94 "the selected row coreset reproduces the full-corpus evidence within \
95 a certified spectral + likelihood error budget; a race decision \
96 inherits the full-corpus verdict only when its margin clears this \
97 budget",
98 )
99 }
100
101 fn evidence(&self) -> Evidence {
102 let mut e = Evidence::new();
103 put_finite(&mut e, "eps_spectral", self.eps_spectral);
104 put_finite(&mut e, "eps_likelihood", self.eps_likelihood);
105 e.insert("dim_effective", self.dim_effective.into());
106 e.insert("n_selected", self.n_selected.into());
107 put_finite(&mut e, "logdet_error_bound", self.logdet_error_bound());
108 put_finite(&mut e, "race_transfer_margin", self.race_transfer_margin());
109 e
110 }
111
112 fn verdict(&self) -> Verdict {
113 if self.race_transfer_margin().is_finite() {
120 Verdict::Insufficient
121 } else {
122 Verdict::Unavailable
123 }
124 }
125}
126
127pub fn coreset_race_verdict(verdict: CoresetMarginVerdict) -> Verdict {
134 match verdict {
135 CoresetMarginVerdict::Certified { .. } => Verdict::Certified,
136 CoresetMarginVerdict::InsufficientMargin { .. } => Verdict::Insufficient,
137 }
138}
139
140pub fn enclosure_margin_verdict(enclosure: &LogdetEnclosure, decision_margin: f64) -> Verdict {
143 match enclosure.decide_within_margin(decision_margin) {
144 MarginVerdict::Decided { .. } => Verdict::Certified,
145 MarginVerdict::InsufficientMargin { .. } => Verdict::Insufficient,
146 }
147}
148
149impl Certificate for LogdetEnclosure {
152 fn claim(&self) -> Claim {
153 Claim::new(
154 "logdet-enclosure",
155 "the log-determinant is enclosed in a certified [lower, upper] \
156 interval whose midpoint is interchangeable with the exact value for \
157 any decision whose margin exceeds the enclosure gap",
158 )
159 }
160
161 fn evidence(&self) -> Evidence {
162 let mut e = Evidence::new();
163 put_finite(&mut e, "block_diag_logdet", self.block_diag_logdet);
164 put_finite(&mut e, "lower", self.lower);
165 put_finite(&mut e, "upper", self.upper);
166 put_finite(&mut e, "gap", self.gap());
167 put_finite(&mut e, "rho", self.rho);
168 put_finite(&mut e, "p2", self.p2);
169 match self.p3 {
170 Some(p3) => put_finite(&mut e, "p3", p3),
171 None => {
172 e.insert("p3", "n/a".into());
173 }
174 }
175 e
176 }
177
178 fn verdict(&self) -> Verdict {
179 if self.lower.is_finite() && self.upper.is_finite() && self.gap().is_finite() {
184 Verdict::Insufficient
185 } else {
186 Verdict::Unavailable
187 }
188 }
189}
190
191impl Certificate for CollapseEvent {
194 fn claim(&self) -> Claim {
195 Claim::new(
196 "structure-collapse",
197 "an atom's active mass fell below the collapse floor during the joint \
198 fit; the guard either reseeded it from a fresh basin or, once the \
199 reseed budget was exhausted, recorded the collapse as the objective's \
200 terminal verdict",
201 )
202 }
203
204 fn evidence(&self) -> Evidence {
205 let mut e = Evidence::new();
206 e.insert("iteration", self.iteration.into());
207 e.insert("atom", self.atom.into());
208 put_finite(&mut e, "max_active_mass", self.max_active_mass);
209 put_finite(&mut e, "floor", self.floor);
210 e.insert(
211 "action",
212 match self.action {
213 CollapseAction::Reseeded => "reseeded",
214 CollapseAction::Terminal => "terminal",
215 }
216 .into(),
217 );
218 e
219 }
220
221 fn verdict(&self) -> Verdict {
222 match self.action {
228 CollapseAction::Reseeded => Verdict::Insufficient,
229 CollapseAction::Terminal => Verdict::Unavailable,
230 }
231 }
232}
233
234#[cfg(test)]
235mod tests {
236 use super::*;
237 use gam_problem::topology_certificates::CertificateLedger;
238
239 #[test]
240 fn criterion_clean_certifies_desync_is_insufficient() {
241 let clean = CriterionCertificate {
242 grad_norm: 1e-8,
243 analytic_directional: 1.0,
244 fd_directional: 1.0,
245 fd_error: 1e-6,
246 agreement_z: 0.0,
247 fd_step: 1e-4,
248 hessian_pd: Some(true),
249 lambdas_railed: Vec::new(),
250 };
251 assert_eq!(clean.verdict(), Verdict::Certified);
252 assert!(clean.verdict().is_certified());
253
254 let desync = CriterionCertificate {
255 analytic_directional: 1.0,
256 fd_directional: 5.0,
257 fd_error: 1e-6,
258 agreement_z: 4.0e6,
259 ..clean
260 };
261 assert_eq!(desync.verdict(), Verdict::Insufficient);
262 assert!(!desync.verdict().is_certified());
263 assert_eq!(desync.claim().id, "outer-optimality");
265 assert!(desync.evidence().contains_key("summary"));
266 }
267
268 #[test]
269 fn coreset_budget_alone_is_insufficient_but_decides_with_margin() {
270 let cert = CoresetCertificate::new(0.1, 0.0, 4, 32).expect("coreset cert");
271 assert_eq!(cert.verdict(), Verdict::Insufficient);
272 let req = cert.race_transfer_margin();
274 assert_eq!(
275 coreset_race_verdict(cert.certify_margin(req * 0.5)),
276 Verdict::Insufficient
277 );
278 assert_eq!(
279 coreset_race_verdict(cert.certify_margin(req * 2.0 + 1.0)),
280 Verdict::Certified
281 );
282 }
283
284 #[test]
285 fn enclosure_certifies_only_when_margin_clears_gap() {
286 let enc = LogdetEnclosure {
287 block_diag_logdet: 10.0,
288 lower: 9.9,
289 upper: 10.1,
290 rho: 0.3,
291 p2: 0.01,
292 p3: None,
293 };
294 assert_eq!(enc.verdict(), Verdict::Insufficient);
295 assert_eq!(enclosure_margin_verdict(&enc, 0.5), Verdict::Certified);
297 assert_eq!(enclosure_margin_verdict(&enc, 0.1), Verdict::Insufficient);
298 }
299
300 #[test]
301 fn collapse_terminal_is_unavailable_reseeded_is_insufficient() {
302 let reseeded = CollapseEvent {
303 iteration: 3,
304 atom: 1,
305 max_active_mass: 1e-4,
306 floor: 1e-3,
307 action: CollapseAction::Reseeded,
308 };
309 assert_eq!(reseeded.verdict(), Verdict::Insufficient);
310 let terminal = CollapseEvent {
311 action: CollapseAction::Terminal,
312 ..reseeded
313 };
314 assert_eq!(terminal.verdict(), Verdict::Unavailable);
315 }
316
317 #[test]
318 fn ledger_rolls_up_to_weakest_member() {
319 let mut ledger = CertificateLedger::new();
320 let clean = CriterionCertificate {
321 grad_norm: 1e-8,
322 analytic_directional: 1.0,
323 fd_directional: 1.0,
324 fd_error: 1e-6,
325 agreement_z: 0.0,
326 fd_step: 1e-4,
327 hessian_pd: Some(true),
328 lambdas_railed: Vec::new(),
329 };
330 let cert = CoresetCertificate::new(0.1, 0.0, 4, 32).expect("coreset");
331 ledger.record(&clean); ledger.record(&cert); assert_eq!(ledger.overall(), Verdict::Insufficient);
334 assert_eq!(ledger.verdict_of("outer-optimality"), Verdict::Certified);
335 assert_eq!(ledger.verdict_of("coreset-budget"), Verdict::Insufficient);
336 }
337}