#[cfg(test)]
mod approx_graph_search {
use crate::{
factories::{penalize_zero, random},
init,
};
use rand::prelude::*;
use rand_pcg::Pcg64;
use soco::{
algorithms::offline::{
multi_dimensional::approx_graph_search::{
approx_graph_search, Options,
},
CachedPath, OfflineAlgorithm, OfflineOptions,
},
config::Config,
problem::{Problem, SimplifiedSmoothedConvexOptimization},
schedule::Schedule,
verifiers::VerifiableProblem,
};
#[test]
fn _1() {
init();
let p = SimplifiedSmoothedConvexOptimization {
d: 2,
t_end: 2,
bounds: vec![2, 1],
switching_cost: vec![1.5, 1.],
hitting_cost: penalize_zero(),
};
p.verify().unwrap();
let CachedPath { path, .. } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::default())
.unwrap();
path.xs.verify(p.t_end, &p.bounds).unwrap();
let CachedPath { path: inv_path, .. } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::inverted())
.unwrap();
inv_path.xs.verify(p.t_end, &p.bounds).unwrap();
assert_eq!(path.xs, inv_path.xs);
assert_abs_diff_eq!(path.cost, inv_path.cost);
assert_eq!(
path.xs,
Schedule::new(vec![
Config::new(vec![0, 1]),
Config::new(vec![0, 1])
])
);
assert_abs_diff_eq!(path.cost, 1.);
assert_abs_diff_eq!(
path.cost,
p.objective_function(&path.xs).unwrap().cost.raw()
);
}
#[test]
fn _2() {
init();
let p = SimplifiedSmoothedConvexOptimization {
d: 2,
t_end: 100,
bounds: vec![8, 8],
switching_cost: vec![1., 3.],
hitting_cost: random(),
};
p.verify().unwrap();
let CachedPath { path, .. } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::default())
.unwrap();
path.xs.verify(p.t_end, &p.bounds).unwrap();
let CachedPath { path: inv_path, .. } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::inverted())
.unwrap();
inv_path.xs.verify(p.t_end, &p.bounds).unwrap();
assert_abs_diff_eq!(path.cost, inv_path.cost);
assert_abs_diff_eq!(
path.cost,
p.objective_function(&path.xs).unwrap().cost.raw()
);
}
#[test]
fn _3() {
init();
let d = 4;
let t_end = 100;
let p = SimplifiedSmoothedConvexOptimization {
d,
t_end,
bounds: (0..d)
.map(|_| {
Pcg64::seed_from_u64((d * t_end) as u64).gen_range(1..10)
})
.collect(),
switching_cost: (0..d)
.map(|_| {
Pcg64::seed_from_u64((d * t_end) as u64).gen_range(1.0..5.)
})
.collect(),
hitting_cost: random(),
};
p.verify().unwrap();
let CachedPath { path, .. } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::default())
.unwrap();
path.xs.verify(p.t_end, &p.bounds).unwrap();
let CachedPath { path: inv_path, .. } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::inverted())
.unwrap();
inv_path.xs.verify(p.t_end, &p.bounds).unwrap();
assert_relative_eq!(path.cost, inv_path.cost, max_relative = 1e-4);
assert_relative_eq!(
path.cost,
p.objective_function(&path.xs).unwrap().cost.raw(),
max_relative = 1e-4
);
}
#[test]
fn _4() {
init();
let mut p = SimplifiedSmoothedConvexOptimization {
d: 2,
t_end: 25,
bounds: vec![8, 8],
switching_cost: vec![1., 3.],
hitting_cost: random(),
};
p.verify().unwrap();
let CachedPath { path, cache } = approx_graph_search
.solve(p.clone(), Options::new(2.), OfflineOptions::default())
.unwrap();
path.xs.verify(p.t_end, &p.bounds).unwrap();
assert_abs_diff_eq!(
path.cost,
p.objective_function(&path.xs).unwrap().cost.raw()
);
p.t_end = 100;
p.verify().unwrap();
let CachedPath { path, .. } = approx_graph_search
.solve(
p.clone(),
Options {
cache: Some(cache),
gamma: 2.,
},
OfflineOptions::default(),
)
.unwrap();
path.xs.verify(p.t_end, &p.bounds).unwrap();
assert_abs_diff_eq!(
path.cost,
p.objective_function(&path.xs).unwrap().cost.raw()
);
}
}