use crate::problem::LpView;
pub const EPS_RAY: f64 = 1e-6;
pub const EPS_GAIN: f64 = 1e-6;
pub const STREAK_K: u32 = 3;
pub const GROWTH: f64 = 1.02;
pub const STALL: f64 = 0.9;
pub fn verify_infeasible(orig: &LpView, y: &[f64]) -> Option<f64> {
let (m, n) = (orig.op.n_rows(), orig.op.n_cols());
assert_eq!(y.len(), m);
let mut ray: Vec<f64> = y.to_vec();
for (i, ri) in ray.iter_mut().enumerate() {
if !orig.row_upper[i].is_finite() && *ri > 0.0 {
*ri = 0.0;
}
if !orig.row_lower[i].is_finite() && *ri < 0.0 {
*ri = 0.0;
}
}
let norm = ray.iter().map(|v| v * v).sum::<f64>().sqrt();
if norm <= 1e-12 {
return None;
}
ray.iter_mut().for_each(|v| *v /= norm);
let zeros_c = vec![0.0; n];
let view0 = LpView {
op: orig.op,
c: &zeros_c,
obj_offset: 0.0,
row_lower: orig.row_lower,
row_upper: orig.row_upper,
col_lower: orig.col_lower,
col_upper: orig.col_upper,
};
let x0 = vec![0.0; n];
let r = crate::kkt::residuals_view(&view0, &x0, &ray);
(r.rel_dual <= EPS_RAY && r.dual_obj >= EPS_GAIN).then_some(r.dual_obj)
}
pub fn verify_unbounded(orig: &LpView, x: &[f64]) -> Option<f64> {
let (m, n) = (orig.op.n_rows(), orig.op.n_cols());
assert_eq!(x.len(), n);
let norm = x.iter().map(|v| v * v).sum::<f64>().sqrt();
if norm <= 1e-12 {
return None;
}
let ray: Vec<f64> = x.iter().map(|v| v / norm).collect();
for (j, &rj) in ray.iter().enumerate() {
if orig.col_lower[j].is_finite() && rj < -EPS_RAY {
return None;
}
if orig.col_upper[j].is_finite() && rj > EPS_RAY {
return None;
}
}
let map0 = |b: &f64| if b.is_finite() { 0.0 } else { *b };
let rl: Vec<f64> = orig.row_lower.iter().map(map0).collect();
let ru: Vec<f64> = orig.row_upper.iter().map(map0).collect();
let cl: Vec<f64> = orig.col_lower.iter().map(map0).collect();
let cu: Vec<f64> = orig.col_upper.iter().map(map0).collect();
let view_rec = LpView {
op: orig.op,
c: orig.c,
obj_offset: 0.0,
row_lower: &rl,
row_upper: &ru,
col_lower: &cl,
col_upper: &cu,
};
let y0 = vec![0.0; m];
let r = crate::kkt::residuals_view(&view_rec, &ray, &y0);
(r.rel_primal <= EPS_RAY && r.primal_obj <= -EPS_GAIN).then_some(-r.primal_obj)
}