mod cost_node;
mod dual_bound_node;
mod id_tree;
mod state_registry;
pub use crate::dp::DpMut;
pub use cost_node::CostNode;
pub use dual_bound_node::DualBoundNode;
pub use id_tree::IdTree;
pub use state_registry::{InsertionResult, StateRegistry};
pub trait SearchNode: Sized {
type DpData: DpMut<State = Self::State, CostType = Self::CostType>;
type State;
type CostType;
type Label;
fn get_state(&self, dp: &Self::DpData) -> &Self::State;
fn get_state_mut(&mut self, dp: &Self::DpData) -> &mut Self::State;
fn get_cost(&self, dp: &Self::DpData) -> Self::CostType;
fn get_bound(&self, dp: &Self::DpData) -> Option<Self::CostType>;
fn is_closed(&self) -> bool;
fn close(&self);
fn get_transitions(&self, dp: &Self::DpData) -> Vec<Self::Label>;
fn check_solution(&self, dp: &mut Self::DpData) -> Option<(Self::CostType, Vec<Self::Label>)> {
let state = self.get_state(dp);
let cost = self.get_cost(dp);
if let Some(solution_cost) = dp
.get_base_cost(state)
.map(|base_cost| dp.combine_cost_weights(cost, base_cost))
{
let transitions = self.get_transitions(dp);
Some((solution_cost, transitions))
} else {
None
}
}
fn ordered_by_bound() -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::dp::Dp;
struct MockDp;
impl Dp for MockDp {
type State = i32;
type CostType = i32;
type Label = usize;
fn get_target(&self) -> Self::State {
2
}
fn get_successors(
&self,
_: &Self::State,
) -> impl IntoIterator<Item = (Self::State, Self::CostType, Self::Label)> {
vec![]
}
fn get_base_cost(&self, state: &Self::State) -> Option<Self::CostType> {
if *state == 0 { Some(0) } else { None }
}
fn combine_cost_weights(&self, a: Self::CostType, b: Self::CostType) -> Self::CostType {
a + b
}
}
struct MockNode(i32);
impl SearchNode for MockNode {
type DpData = MockDp;
type State = i32;
type CostType = i32;
type Label = usize;
fn get_state(&self, _: &Self::DpData) -> &Self::State {
&self.0
}
fn get_state_mut(&mut self, _: &Self::DpData) -> &mut Self::State {
&mut self.0
}
fn get_cost(&self, _: &Self::DpData) -> Self::CostType {
2
}
fn get_bound(&self, _: &Self::DpData) -> Option<Self::CostType> {
Some(0)
}
fn is_closed(&self) -> bool {
false
}
fn close(&self) {}
fn get_transitions(&self, _: &Self::DpData) -> Vec<Self::Label> {
vec![0, 1]
}
}
#[test]
fn test_check_solution() {
let mut dp = MockDp;
let node = MockNode(0);
assert_eq!(node.check_solution(&mut dp), Some((2, vec![0, 1])));
}
#[test]
fn test_check_solution_none() {
let mut dp = MockDp;
let node = MockNode(1);
assert_eq!(node.check_solution(&mut dp), None);
}
}