### Added accuracy estimation to Karmarkar's algorithm, by making some possibly incorrect assumptions

karmarkar
Thomas Johnson 3 years ago
parent
commit
decc7f6e1a
1 changed files with 53 additions and 56 deletions
1. 109
src/karmarkar.rs

#### 109 src/karmarkar.rs View File

 @ -610,6 +610,7 @@ pub struct Karmarkar { nvars: usize, nconstr: usize, αr: Fl, nα: Fl, a0: Fl, Dc: DVector, B: DMatrix, @ -642,6 +643,7 @@ impl Karmarkar { nvars: Ashape.1, nconstr: Ashape.0, αr: α * r, nα: Ashape.1 as Fl / α, a0, Dc: DVector::zeros(Ashape.1), B: DMatrix::zeros(Ashape.0 + 1, Ashape.1), @ -662,7 +664,7 @@ impl Karmarkar { #[cfg(debug_karmarkar)] { // print!("infeasiblity: {}", &self.problem.A * &self.guess); print!("infeasiblity: {}", &self.problem.A * &self.guess); } // First transform c, giving Dc @ -698,12 +700,38 @@ impl Karmarkar { let scale = 1.0 / self.cp.sum(); self.cp *= scale; if self.cp.iter().all(|x| !x.is_nan()) { let est_dist = self.guess.metric_distance(&self.cp) * self.nα; self.guess.copy_from(&self.cp); Indeterminate() Distance(est_dist) } else { Failed() } } /// Iterates until either the iteration fails (usually indicating the edge of the simplex, and /// therefore a solution) or the desired precision is reached. If `unproject` is true, try to /// get accurate to within ε in the unprojected space, assuming the problem this instance is /// solving is the result of projecting a lower-dimensional one. Otherwise, just try to be /// accurate within ε in this space. pub fn iterate_until_failed_or_precise(&mut self, unproject: bool) { use IterationResult::*; loop { match self.iterate() { Failed() => break, Distance(d) => { let tolerance = if unproject { self.guess[self.guess.len() - 1] * self.ε } else { self.ε }; if d < tolerance { break; } } _ => {} } } } } #[derive(Debug, Clone, Copy)] @ -732,44 +760,7 @@ macro_rules! linear_vars { mod test { use super::*; // #[test] // fn inequality_test() { // linear_vars![x, y, z, w]; // let mut constraints = Vec::::new(); // constraints.push(Expr::from(&x) + &y + &z + &w << 5.0.into()); // constraints.push(Expr::from(&x) << 4.0.into()); // constraints.push(Expr::from(&y) << 4.0.into()); // constraints.push(Expr::from(&z) << 4.0.into()); // constraints.push(Expr::from(&w) << 4.0.into()); // let mut objective = LinearCombination::new(); // objective.insert_variable(x.clone(), 1.0); // objective.insert_variable(y.clone(), 2.0); // objective.insert_variable(z.clone(), 3.0); // objective.insert_variable(w.clone(), 4.0); // println!("Maximize {}", objective); // println!("subject to"); // for constraint in constraints.iter() { // println!("{}", constraint); // } // // let sf = StandardFormLP::from_ineqs_and_objective(constraints, objective); // println!(""); // println!("{}", sf); // let frp = sf.clone().to_feasible_region_problem(); // println!(""); // println!("{}", frp); // let len = frp.vars.len(); // let mut fras = // AffineScaling::from_feasible_point(frp, DVector::from_element(len, 1.0)).unwrap(); // println!(""); // println!("{}", fras); // // for _ in 0..10 { // println!("{:?}", fras.iterate()); // println!("{}", fras.x); // } // } // Designed to be a --nocapture test for human analysis. Pretty much just for debugging. #[test] fn inequality_test() { linear_vars![x, y]; @ -811,14 +802,15 @@ mod test { let mut km = Karmarkar::from_feasible_value(proj_frp.clone(), proj_frp_feasible_point).unwrap(); loop { let oldx = km.guess.clone(); if let IterationResult::Failed() = km.iterate() { break; } // print!("x: {}", km.guess); // println!("distance: {}", (&km.guess - oldx).norm()); } //loop { // //let oldx = km.guess.clone(); // if let IterationResult::Failed() = km.iterate() { // break; // } // // print!("x: {}", km.guess); // // println!("distance: {}", (&km.guess - oldx).norm()); //} km.iterate_until_failed_or_precise(true); let a0 = (km.guess.len() as Fl).recip(); print!("final x': {}", km.guess); println!("sum of elements: {}", km.guess.sum()); @ -847,14 +839,19 @@ mod test { let proj_feasible_point = HomogenousLP::project_point(&feasible_point); let proj = HomogenousLP::project_from_sflp(sf.clone()); let mut km = Karmarkar::from_feasible_value(proj.clone(), proj_feasible_point).unwrap(); for _ in 0..1000 { let oldx = km.guess.clone(); if let IterationResult::Failed() = km.iterate() { break; } print!("x: {}", km.guess); println!("distance: {}", (&km.guess - oldx).norm()); } //let mut olddist = 0.0; // for _ in 0..100 { // let oldx = km.guess.clone(); // if let IterationResult::Failed() = km.iterate() { // break; // } // let dist = (&km.guess - oldx).norm(); // print!("x: {}", km.guess); // println!("distance: {}", dist); // println!("distance ratio: {}", dist / olddist); // olddist = dist; // } km.iterate_until_failed_or_precise(true); print!("final x': {}", km.guess); let solution = HomogenousLP::project_point_inv(&km.guess); println!("vars: {:?}", sf.vars);