Skip to main content

create_cabs

Function create_cabs 

Source
pub fn create_cabs<'a, D, S, C, L, K>(
    dp: D,
    parameters: SearchParameters<C>,
    cabs_parameters: CabsParameters,
) -> Box<dyn Search<CostType = C, Label = L> + 'a>
where D: DpMut<State = S, CostType = C, Label = L> + Dominance<State = S, Key = K> + BoundMut<State = S, CostType = C> + 'a, C: Ord + Copy + Signed + Display + 'a, L: Default + Copy + 'a, K: Hash + Eq,
Expand description

Creates complete anytime beam search (CABS) solver.

Search nodes are ordered by the f-value, which is the combination of the cost and the dual bound.

The DP model must implement the Dominance and DualBound traits.

§Panic

When threads argument takes 0 value.

§Examples

use rpid::prelude::*;
use rpid::solvers;
use fixedbitset::FixedBitSet;

struct Tsp {
    c: Vec<Vec<i32>>,
}

struct TspState {
    unvisited: FixedBitSet,
    current: usize,
}

impl Dp for Tsp {
    type State = TspState;
    type CostType = i32;
    type Label = usize;

    fn get_target(&self) -> Self::State {
        let mut unvisited = FixedBitSet::with_capacity(self.c.len());
        unvisited.insert_range(1..);

        TspState {
            unvisited,
            current: 0,
       }
    }

    fn get_successors(
        &self,
        state: &Self::State,
    ) -> impl IntoIterator<Item = (Self::State, Self::CostType, Self::Label)> {
        state.unvisited.ones().map(|next| {
            let mut unvisited = state.unvisited.clone();
            unvisited.remove(next);

            let successor = TspState {
                unvisited,
                current: next,
            };
            let weight = self.c[state.current][next];
             
            (successor, weight, next)
        })
    }

    fn get_base_cost(&self, state: &Self::State) -> Option<Self::CostType> {
        if state.unvisited.is_clear() {
            Some(self.c[state.current][0])
        } else {
            None
        }
    }
}

impl Dominance for Tsp {
    type State = TspState;
    type Key = (FixedBitSet, usize);

    fn get_key(&self, state: &Self::State) -> Self::Key {
        (state.unvisited.clone(), state.current)
    }
}

impl Bound for Tsp {
    type State = TspState;
    type CostType = i32;

    fn get_dual_bound(&self, state: &Self::State) -> Option<Self::CostType> {
        Some(0)
    }
}

let tsp = Tsp { c: vec![vec![0, 1, 2], vec![1, 0, 3], vec![2, 3, 0]] };
let parameters = SearchParameters {
    quiet: true,
    ..Default::default()
};
let cabs_parameters = CabsParameters::default();
let mut solver = solvers::create_cabs(tsp, parameters, cabs_parameters);
let solution = solver.search();
assert_eq!(solution.cost, Some(6));
assert_eq!(solution.transitions, vec![1, 2]);
assert!(solution.is_optimal);
assert!(!solution.is_infeasible);
assert_eq!(solution.best_bound, Some(6));