1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Rust Programmable Interface for Domain-Independent Dynamic Programming (RPID)
//!
//! With RPID, you can formulate dynamic programming by implementing traits and
//! solve it by calling a solver.
//! You need to implement the [Dp] trait to define a dynamic programming model,
//! and a solver may require the [Dominance] and [Bound] traits to enable dominance checking and pruning with bounds.
//!
//! ## Example
//!
//! Solving the traveling salesperson problem (TSP) with the CABS solver.
//!
//! ```
//! use fixedbitset::FixedBitSet;
//! use rpid::prelude::*;
//! use rpid::solvers;
//!
//! 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, _: &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 mut solver
//! = solvers::create_cabs(tsp, SearchParameters::default(), CabsParameters::default());
//! 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));
//! ```
//!
//! For more examples, see <https://github.com/Kurorororo/didp-rust-models>.
//!
//! ## References
//!
//! Ryo Kuroiwa and J. Christopher Beck. RPID: Rust Programmable Interface for Domain-Independent Dynamic Programming.
//! In *31st International Conference on Principles and Practice of Constraint Programming (CP 2025)*,
//! volume 340 of Leibniz International Proceedings in Informatics (LIPIcs), pages 23:1-23:21.
//! Schloss Dagstuhl - Leibniz-Zentrum für Informatik, 2025.
//! [doi:10.4230/LIPIcs.CP.2025.23](https://doi.org/10.4230/LIPIcs.CP.2025.23)
pub use ;
pub use Solution;