use super::*;
use crate::options::{SimplexMethod, SolverOptions};
use crate::problem::{LpProblem, SolveStatus};
use crate::sparse::CscMatrix;
use crate::test_kkt::assert_solver_invariants_lp;
fn make_lp(
c: Vec<f64>,
rows: &[usize],
cols: &[usize],
vals: &[f64],
nrows: usize,
ncols: usize,
b: Vec<f64>,
) -> LpProblem {
let a = CscMatrix::from_triplets(rows, cols, vals, nrows, ncols).unwrap();
LpProblem::new(c, a, b).unwrap()
}
#[test]
fn test_dual_advanced_warm_start_rhs_change() {
let lp1 = make_lp(
vec![-1.0, -2.0],
&[0, 0, 1, 2],
&[0, 1, 0, 1],
&[1.0, 1.0, 1.0, 1.0],
3,
2,
vec![4.0, 3.0, 3.0],
);
let result1 = solve_with(&lp1, &SolverOptions::default());
assert_eq!(result1.status, SolveStatus::Optimal);
assert_solver_invariants_lp(&result1, &lp1);
assert!(
result1.warm_start_basis.is_some(),
"LP1 は warm_start_basis を返すべき"
);
let lp2 = make_lp(
vec![-1.0, -2.0],
&[0, 0, 1, 2],
&[0, 1, 0, 1],
&[1.0, 1.0, 1.0, 1.0],
3,
2,
vec![5.0, 3.0, 3.0],
);
let result2_cold = solve_with(&lp2, &SolverOptions::default());
assert_eq!(result2_cold.status, SolveStatus::Optimal);
assert_solver_invariants_lp(&result2_cold, &lp2);
let opts_warm = SolverOptions {
warm_start: result1.warm_start_basis.clone(),
simplex_method: SimplexMethod::DualAdvanced,
..SolverOptions::default()
};
let result2_warm = solve_with(&lp2, &opts_warm);
assert_eq!(
result2_warm.status,
SolveStatus::Optimal,
"DualAdvanced warm-start は Optimal を返すべき"
);
assert_solver_invariants_lp(&result2_warm, &lp2);
assert!(
(result2_warm.objective - result2_cold.objective).abs() < 1e-6,
"DualAdvanced warm-start obj={}, cold-start obj={}",
result2_warm.objective,
result2_cold.objective
);
}
#[test]
fn test_dual_advanced_warm_start_larger_rhs() {
let lp1 = make_lp(
vec![-1.0, -1.0],
&[0, 0, 1, 2],
&[0, 1, 0, 1],
&[1.0, 1.0, 1.0, 1.0],
3,
2,
vec![4.0, 3.0, 3.0],
);
let result1 = solve_with(&lp1, &SolverOptions::default());
assert_eq!(result1.status, SolveStatus::Optimal);
assert_solver_invariants_lp(&result1, &lp1);
assert!(
result1.warm_start_basis.is_some(),
"LP1 は warm_start_basis を返すべき"
);
let lp2 = make_lp(
vec![-1.0, -1.0],
&[0, 0, 1, 2],
&[0, 1, 0, 1],
&[1.0, 1.0, 1.0, 1.0],
3,
2,
vec![6.0, 4.0, 4.0],
);
let result2_cold = solve_with(&lp2, &SolverOptions::default());
assert_eq!(result2_cold.status, SolveStatus::Optimal);
assert_solver_invariants_lp(&result2_cold, &lp2);
let opts_warm = SolverOptions {
warm_start: result1.warm_start_basis.clone(),
simplex_method: SimplexMethod::DualAdvanced,
..SolverOptions::default()
};
let result2_warm = solve_with(&lp2, &opts_warm);
assert_eq!(
result2_warm.status,
SolveStatus::Optimal,
"DualAdvanced warm-start (larger RHS) は Optimal を返すべき"
);
assert!(
(result2_warm.objective - result2_cold.objective).abs() < 1e-6,
"DualAdvanced warm-start obj={}, cold-start obj={}",
result2_warm.objective,
result2_cold.objective
);
}