#[cfg(test)] mod optimal_graph_search { use crate::factories::{penalize_zero, random}; use crate::init; use rand::prelude::*; use rand_pcg::Pcg64; use soco::algorithms::offline::multi_dimensional::optimal_graph_search::optimal_graph_search; use soco::algorithms::offline::multi_dimensional::optimal_graph_search::Options; use soco::algorithms::offline::CachedPath; use soco::algorithms::offline::{OfflineAlgorithm, OfflineOptions}; use soco::config::Config; use soco::problem::{Problem, SimplifiedSmoothedConvexOptimization}; use soco::schedule::Schedule; use soco::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, .. } = optimal_graph_search .solve_with_default_options(p.clone(), OfflineOptions::default()) .unwrap(); path.xs.verify(p.t_end, &p.bounds).unwrap(); let CachedPath { path: inv_path, .. } = optimal_graph_search .solve_with_default_options(p.clone(), 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_relative_eq!( path.cost, p.objective_function(&path.xs).unwrap().cost.raw(), max_relative = 1e-4 ); } #[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, .. } = optimal_graph_search .solve_with_default_options(p.clone(), OfflineOptions::default()) .unwrap(); path.xs.verify(p.t_end, &p.bounds).unwrap(); let CachedPath { path: inv_path, .. } = optimal_graph_search .solve_with_default_options(p.clone(), OfflineOptions::inverted()) .unwrap(); inv_path.xs.verify(p.t_end, &p.bounds).unwrap(); assert_abs_diff_eq!(path.cost, inv_path.cost); assert_relative_eq!( path.cost, p.objective_function(&path.xs).unwrap().cost.raw(), max_relative = 1e-4 ); } #[test] fn _3() { init(); let d = 4; let t_end = 10; let p = SimplifiedSmoothedConvexOptimization { d, t_end, bounds: (0..d) .map(|_| { Pcg64::seed_from_u64((d * t_end) as u64).gen_range(1..5) }) .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, .. } = optimal_graph_search .solve_with_default_options(p.clone(), OfflineOptions::default()) .unwrap(); path.xs.verify(p.t_end, &p.bounds).unwrap(); let CachedPath { path: inv_path, .. } = optimal_graph_search .solve_with_default_options(p.clone(), 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 d = 4; let t_end = 5; let mut p = SimplifiedSmoothedConvexOptimization { d, t_end, bounds: (0..d) .map(|_| { Pcg64::seed_from_u64((d * t_end) as u64).gen_range(1..5) }) .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, cache } = optimal_graph_search .solve_with_default_options(p.clone(), OfflineOptions::default()) .unwrap(); path.xs.verify(p.t_end, &p.bounds).unwrap(); assert_relative_eq!( path.cost, p.objective_function(&path.xs).unwrap().cost.raw(), max_relative = 1e-4 ); p.t_end = 10; p.verify().unwrap(); let CachedPath { path, .. } = optimal_graph_search .solve( p.clone(), Options { cache: Some(cache) }, OfflineOptions::default(), ) .unwrap(); path.xs.verify(p.t_end, &p.bounds).unwrap(); assert_relative_eq!( path.cost, p.objective_function(&path.xs).unwrap().cost.raw(), max_relative = 1e-4 ); } }