soco 1.0.1

Algorithms for Smoothed Online Convex Optimization
Documentation
#[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()
        );
    }
}