Browse Source

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

karmarkar
Thomas Johnson 3 years ago
parent
commit
decc7f6e1a
  1. 109
      src/karmarkar.rs

109
src/karmarkar.rs

@ -610,6 +610,7 @@ pub struct Karmarkar {
nvars: usize,
nconstr: usize,
αr: Fl,
: Fl,
a0: Fl,
Dc: DVector<Fl>,
B: DMatrix<Fl>,
@ -642,6 +643,7 @@ impl Karmarkar {
nvars: Ashape.1,
nconstr: Ashape.0,
αr: α * r,
: 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.;
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::<LeqInequality>::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);

Loading…
Cancel
Save