diff --git a/ddo/examples/alp/main.rs b/ddo/examples/alp/main.rs index e5684d84..ac545d48 100644 --- a/ddo/examples/alp/main.rs +++ b/ddo/examples/alp/main.rs @@ -86,7 +86,7 @@ fn main() { let cutoff = cutoff(args.duration); let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/alp/tests.rs b/ddo/examples/alp/tests.rs index f50f574e..7e6d6c49 100644 --- a/ddo/examples/alp/tests.rs +++ b/ddo/examples/alp/tests.rs @@ -45,7 +45,7 @@ pub fn solve_id(id: &str) -> isize { let cutoff = NoCutoff; let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &ranking, diff --git a/ddo/examples/golomb/main.rs b/ddo/examples/golomb/main.rs index 90cc2723..032a3405 100644 --- a/ddo/examples/golomb/main.rs +++ b/ddo/examples/golomb/main.rs @@ -235,7 +235,7 @@ fn main() { let cutoff = TimeBudget::new(Duration::from_secs(args.timeout));//NoCutoff; let mut fringe = SimpleFringe::new(MaxUB::new(&heuristic)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &heuristic, diff --git a/ddo/examples/golomb/tests.rs b/ddo/examples/golomb/tests.rs index f74d0506..0dad4d59 100644 --- a/ddo/examples/golomb/tests.rs +++ b/ddo/examples/golomb/tests.rs @@ -32,7 +32,7 @@ pub fn solve_golomb(n: usize) -> isize { let cutoff = NoCutoff; let mut fringe = SimpleFringe::new(MaxUB::new(&heuristic)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &heuristic, diff --git a/ddo/examples/knapsack/main.rs b/ddo/examples/knapsack/main.rs index b3629d16..60a6ccfb 100644 --- a/ddo/examples/knapsack/main.rs +++ b/ddo/examples/knapsack/main.rs @@ -321,7 +321,7 @@ fn main() { let cutoff = TimeBudget::new(Duration::from_secs(15));//NoCutoff; let mut fringe = SimpleFringe::new(MaxUB::new(&heuristic)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &heuristic, diff --git a/ddo/examples/knapsack/tests.rs b/ddo/examples/knapsack/tests.rs index 1e9547c0..22fb4e86 100644 --- a/ddo/examples/knapsack/tests.rs +++ b/ddo/examples/knapsack/tests.rs @@ -47,7 +47,7 @@ pub fn solve_id(id: &str) -> isize { let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); // This solver compile DD that allow the definition of long arcs spanning over several layers. - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &ranking, diff --git a/ddo/examples/lcs/main.rs b/ddo/examples/lcs/main.rs index 359ea48a..f9b79ec7 100644 --- a/ddo/examples/lcs/main.rs +++ b/ddo/examples/lcs/main.rs @@ -88,7 +88,7 @@ fn main() { let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); // This solver compile DD that allow the definition of long arcs spanning over several layers. - let mut solver = ParBarrierSolverPooled::custom( + let mut solver = ParCachingSolverPooled::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/lcs/tests.rs b/ddo/examples/lcs/tests.rs index bf8e26c8..d146456f 100644 --- a/ddo/examples/lcs/tests.rs +++ b/ddo/examples/lcs/tests.rs @@ -47,7 +47,7 @@ pub fn solve_id(id: &str) -> isize { let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); // This solver compile DD that allow the definition of long arcs spanning over several layers. - let mut solver = ParBarrierSolverPooled::new( + let mut solver = ParCachingSolverPooled::new( &problem, &relaxation, &ranking, diff --git a/ddo/examples/misp/main.rs b/ddo/examples/misp/main.rs index 50e955a8..bf49957a 100644 --- a/ddo/examples/misp/main.rs +++ b/ddo/examples/misp/main.rs @@ -351,7 +351,7 @@ fn main() { let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); // This solver compile DD that allow the definition of long arcs spanning over several layers. - let mut solver = ParNoBarrierSolverLel::custom( + let mut solver = ParNoCachingSolverLel::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/psp/main.rs b/ddo/examples/psp/main.rs index bcaca86b..3e83d8eb 100644 --- a/ddo/examples/psp/main.rs +++ b/ddo/examples/psp/main.rs @@ -97,7 +97,7 @@ fn main() { let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); // This solver compile DD that allow the definition of long arcs spanning over several layers. - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/psp/tests.rs b/ddo/examples/psp/tests.rs index 5c5fc09d..cd9bcc2f 100644 --- a/ddo/examples/psp/tests.rs +++ b/ddo/examples/psp/tests.rs @@ -48,7 +48,7 @@ mod psp_test_utils { let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); // This solver compile DD that allow the definition of long arcs spanning over several layers. - let mut solver = DefaultBarrierSolver::::custom( + let mut solver = DefaultCachingSolver::::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/sop/main.rs b/ddo/examples/sop/main.rs index 50ec8dde..2f2ed1d8 100644 --- a/ddo/examples/sop/main.rs +++ b/ddo/examples/sop/main.rs @@ -83,7 +83,7 @@ fn main() { let cutoff = cutoff(args.duration); let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/sop/tests.rs b/ddo/examples/sop/tests.rs index 115357a0..7df98de8 100644 --- a/ddo/examples/sop/tests.rs +++ b/ddo/examples/sop/tests.rs @@ -47,7 +47,7 @@ pub fn solve_id(id: &str) -> isize { let cutoff = NoCutoff; let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &ranking, diff --git a/ddo/examples/srflp/main.rs b/ddo/examples/srflp/main.rs index d9e4760b..5ddab32a 100644 --- a/ddo/examples/srflp/main.rs +++ b/ddo/examples/srflp/main.rs @@ -92,7 +92,7 @@ fn main() { let cutoff = cutoff(args.duration); let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/srflp/tests.rs b/ddo/examples/srflp/tests.rs index faf2836d..499e1e3b 100644 --- a/ddo/examples/srflp/tests.rs +++ b/ddo/examples/srflp/tests.rs @@ -45,7 +45,7 @@ pub fn solve_id(id: &str) -> f64 { let cutoff = NoCutoff; let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &ranking, diff --git a/ddo/examples/talentsched/main.rs b/ddo/examples/talentsched/main.rs index 32078e07..d0810a2f 100644 --- a/ddo/examples/talentsched/main.rs +++ b/ddo/examples/talentsched/main.rs @@ -86,7 +86,7 @@ fn main() { let cutoff = cutoff(args.duration); let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &problem, &relaxation, &ranking, diff --git a/ddo/examples/talentsched/tests.rs b/ddo/examples/talentsched/tests.rs index e3de1bba..aa411777 100644 --- a/ddo/examples/talentsched/tests.rs +++ b/ddo/examples/talentsched/tests.rs @@ -47,7 +47,7 @@ pub fn solve_id(id: &str) -> isize { let cutoff = NoCutoff; let mut fringe = NoDupFringe::new(MaxUB::new(&ranking)); - let mut solver = DefaultBarrierSolver::new( + let mut solver = DefaultCachingSolver::new( &problem, &relaxation, &ranking, diff --git a/ddo/examples/tsptw/main.rs b/ddo/examples/tsptw/main.rs index 00d14560..89d49950 100644 --- a/ddo/examples/tsptw/main.rs +++ b/ddo/examples/tsptw/main.rs @@ -23,7 +23,7 @@ use std::{fs::File, path::Path, time::{Duration, Instant}}; use clap::Parser; -use ddo::{Completion, TimeBudget, NoDupFringe, MaxUB, Solution, SimpleDominanceChecker, Problem, DefaultBarrierSolver, Solver}; +use ddo::{Completion, TimeBudget, NoDupFringe, MaxUB, Solution, SimpleDominanceChecker, Problem, DefaultCachingSolver, Solver}; use dominance::TsptwDominance; use heuristics::{TsptwWidth, TsptwRanking}; use instance::TsptwInstance; @@ -76,7 +76,7 @@ fn main() { let dominance = SimpleDominanceChecker::new(TsptwDominance); let cutoff = TimeBudget::new(Duration::from_secs(args.duration.unwrap_or(u64::MAX))); let mut fringe = NoDupFringe::new(MaxUB::new(&TsptwRanking)); - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &pb, &relax, &TsptwRanking, diff --git a/ddo/examples/tsptw/tests.rs b/ddo/examples/tsptw/tests.rs index 3887c190..1e104eae 100644 --- a/ddo/examples/tsptw/tests.rs +++ b/ddo/examples/tsptw/tests.rs @@ -19,7 +19,7 @@ use std::{fs::File, path::PathBuf}; -use ddo::{MaxUB, NoDupFringe, Problem, Solver, DefaultBarrierSolver, SimpleDominanceChecker, NoCutoff}; +use ddo::{MaxUB, NoDupFringe, Problem, Solver, DefaultCachingSolver, SimpleDominanceChecker, NoCutoff}; use crate::{dominance::TsptwDominance, heuristics::{TsptwRanking, TsptwWidth}, instance::TsptwInstance, model::Tsptw, relax::TsptwRelax}; @@ -39,7 +39,7 @@ pub fn solve(instance: &str, width: Option, threads: Option) -> f3 let width = TsptwWidth::new(pb.nb_variables(), width.unwrap_or(1)); let dominance = SimpleDominanceChecker::new(TsptwDominance); let cutoff = NoCutoff; - let mut solver = DefaultBarrierSolver::custom( + let mut solver = DefaultCachingSolver::custom( &pb, &relax, &TsptwRanking, diff --git a/ddo/examples/visualisation/main.rs b/ddo/examples/visualisation/main.rs index fadbbcb2..d62690b5 100644 --- a/ddo/examples/visualisation/main.rs +++ b/ddo/examples/visualisation/main.rs @@ -261,8 +261,8 @@ fn main() { let problem = read_instance(fname).unwrap(); let relaxation = KPRelax{pb: &problem}; let ranking = KPranking; - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&problem); + let mut cache = SimpleCache::default(); + cache.initialize(&problem); let dominance = EmptyDominanceChecker::default(); let residual = SubProblem { @@ -281,7 +281,7 @@ fn main() { max_width: 5, residual: &residual, best_lb: isize::MIN, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; diff --git a/ddo/src/abstraction/barrier.rs b/ddo/src/abstraction/cache.rs similarity index 91% rename from ddo/src/abstraction/barrier.rs rename to ddo/src/abstraction/cache.rs index 4e5d6dea..75f9c9dc 100644 --- a/ddo/src/abstraction/barrier.rs +++ b/ddo/src/abstraction/cache.rs @@ -21,14 +21,14 @@ use std::sync::Arc; use crate::{Threshold, SubProblem, Problem}; -/// This trait abstracts away the implementation details of the solver barrier. -/// That is, a Barrier represents the data structure that stores thresholds that +/// This trait abstracts away the implementation details of the solver cache. +/// That is, a Cache represents the data structure that stores thresholds that /// condition the re-exploration of nodes with a state already reached previously. -pub trait Barrier { +pub trait Cache { type State; /// Returns true if the subproblem still must be explored, - /// given the thresholds contained in the barrier. + /// given the thresholds contained in the cache. fn must_explore(&self, subproblem: &SubProblem) -> bool { let threshold = self.get_threshold(subproblem.state.as_ref(), subproblem.depth); if let Some(threshold) = threshold { @@ -38,7 +38,7 @@ pub trait Barrier { } } - /// Prepare the barrier to be used with the given problem + /// Prepare the cache to be used with the given problem fn initialize(&mut self, problem: &dyn Problem); /// Returns the threshold currently associated with the given state, if any. diff --git a/ddo/src/abstraction/mdd.rs b/ddo/src/abstraction/mdd.rs index 80c5427b..3cf13831 100644 --- a/ddo/src/abstraction/mdd.rs +++ b/ddo/src/abstraction/mdd.rs @@ -17,7 +17,7 @@ // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -use crate::{SubProblem, Completion, Reason, Problem, Relaxation, StateRanking, Solution, Cutoff, Barrier, DominanceChecker}; +use crate::{SubProblem, Completion, Reason, Problem, Relaxation, StateRanking, Solution, Cutoff, Cache, DominanceChecker}; // FIXME: Replace that with the following enum definition when const generics allow enum types /// What type of cut-set are we using for relaxed DDs ? @@ -66,7 +66,7 @@ pub struct CompilationInput<'a, State> { /// The best known lower bound at the time when the dd is being compiled pub best_lb: isize, /// Data structure containing info about past compilations used to prune the search - pub barrier: &'a dyn Barrier, + pub cache: &'a dyn Cache, pub dominance: &'a dyn DominanceChecker, } diff --git a/ddo/src/abstraction/mod.rs b/ddo/src/abstraction/mod.rs index 8053b3b3..47eaa202 100644 --- a/ddo/src/abstraction/mod.rs +++ b/ddo/src/abstraction/mod.rs @@ -29,7 +29,7 @@ mod heuristics; mod solver; mod fringe; mod mdd; -mod barrier; +mod cache; mod dominance; pub use dp::*; @@ -37,5 +37,5 @@ pub use heuristics::*; pub use solver::*; pub use fringe::*; pub use mdd::*; -pub use barrier::*; +pub use cache::*; pub use dominance::*; \ No newline at end of file diff --git a/ddo/src/implementation/barrier/empty.rs b/ddo/src/implementation/cache/empty.rs similarity index 89% rename from ddo/src/implementation/barrier/empty.rs rename to ddo/src/implementation/cache/empty.rs index ada8f8d0..1a456524 100644 --- a/ddo/src/implementation/barrier/empty.rs +++ b/ddo/src/implementation/cache/empty.rs @@ -28,23 +28,23 @@ use std::{sync::Arc, marker::PhantomData}; use crate::*; -/// Dummy implementation of Barrier with no information stored at all. +/// Dummy implementation of Cache with no information stored at all. #[derive(Debug, Clone, Copy)] -pub struct EmptyBarrier { +pub struct EmptyCache { phantom: PhantomData, } -impl Default for EmptyBarrier { +impl Default for EmptyCache { fn default() -> Self { - EmptyBarrier { phantom: Default::default() } + EmptyCache { phantom: Default::default() } } } -impl EmptyBarrier { +impl EmptyCache { pub fn new() -> Self { Default::default() } } -impl Barrier for EmptyBarrier { +impl Cache for EmptyCache { type State = T; #[inline(always)] diff --git a/ddo/src/implementation/barrier/mod.rs b/ddo/src/implementation/cache/mod.rs similarity index 100% rename from ddo/src/implementation/barrier/mod.rs rename to ddo/src/implementation/cache/mod.rs diff --git a/ddo/src/implementation/barrier/simple.rs b/ddo/src/implementation/cache/simple.rs similarity index 92% rename from ddo/src/implementation/barrier/simple.rs rename to ddo/src/implementation/cache/simple.rs index 1f2c2901..6881c0ad 100644 --- a/ddo/src/implementation/barrier/simple.rs +++ b/ddo/src/implementation/cache/simple.rs @@ -28,23 +28,23 @@ use std::{sync::Arc, hash::Hash}; use dashmap::DashMap; -use crate::{Barrier, Threshold}; +use crate::{Cache, Threshold}; -/// Simple implementation of the Barrier using one hashmap for each layer, +/// Simple implementation of Cache using one hashmap for each layer, /// each protected with a read-write lock. #[derive(Debug)] -pub struct SimpleBarrier +pub struct SimpleCache where T: Hash + Eq { thresholds_by_layer: Vec, Threshold, fxhash::FxBuildHasher>>, } -impl Default for SimpleBarrier +impl Default for SimpleCache where T: Hash + Eq { fn default() -> Self { Self { thresholds_by_layer: vec![] } } } -impl Barrier for SimpleBarrier +impl Cache for SimpleCache where T: Hash + Eq { type State = T; diff --git a/ddo/src/implementation/mdd/clean.rs b/ddo/src/implementation/mdd/clean.rs index 24ea0d19..8a5eee6e 100644 --- a/ddo/src/implementation/mdd/clean.rs +++ b/ddo/src/implementation/mdd/clean.rs @@ -2,8 +2,8 @@ //! the pruning techniques that I have proposed in my PhD thesis (RUB, LocB, EBPO). //! It also implements the techniques we proposed in //! -//! ``Branch-and-Bound with Barrier: Dominance and Suboptimality Detection for -//! DD-Based Branch-and-Bound''. +//! ``Decision Diagram-Based Branch-and-Bound with Caching +//! for Dominance and Suboptimality Detection''. use std::{sync::Arc, hash::Hash, collections::hash_map::Entry, fmt::Debug}; @@ -53,7 +53,7 @@ struct Node { inbound: EdgesListId, // The rough upper bound associated to this node rub: isize, - /// A threshold value to be stored in the barrier that conditions the + /// A threshold value to be stored in the cache that conditions the /// re-exploration of other nodes with the same state. /// /// ### Note @@ -454,7 +454,7 @@ where } // traverse bottom-up - // note: barrier requires that all nodes have an associated locb. not only those below cutset + // note: cache requires that all nodes have an associated locb. not only those below cutset for Layer{from, to} in self.layers.iter().rev().copied() { for id in from..to { let id = NodeId(id); @@ -497,8 +497,8 @@ where continue; } - // ATTENTION: YOU WANT TO PROPAGATE THETA EVEN IF THE NODE WAS PRUNED BY BARRIER - if !node.flags.is_pruned_by_barrier() { + // ATTENTION: YOU WANT TO PROPAGATE THETA EVEN IF THE NODE WAS PRUNED BY THE CACHE + if !node.flags.is_pruned_by_cache() { let tot_rub = node.value_top.saturating_add(node.rub); if tot_rub <= best_known { node.theta = Some(best_known.saturating_sub(node.rub)); @@ -514,7 +514,7 @@ where node.theta = Some(isize::MAX); } - Self::_maybe_update_barrier(node, input); + Self::_maybe_update_cache(node, input); } // only propagate if you have an actual threshold if let Some(my_theta) = node.theta { @@ -529,11 +529,11 @@ where } } - fn _maybe_update_barrier(node: &Node, input: &CompilationInput) { - // A node can only be added to the barrier if it belongs to the cutset or is above it + fn _maybe_update_cache(node: &Node, input: &CompilationInput) { + // A node can only be added to the cache if it belongs to the cutset or is above it if let Some(theta) = node.theta { if node.flags.is_above_cutset() { - input.barrier.update_threshold( + input.cache.update_threshold( node.state.clone(), node.depth, theta, @@ -666,7 +666,7 @@ where false } else { if !self.layers.is_empty() { - self._filter_with_barrier(input, curr_l); + self._filter_with_cache(input, curr_l); } self._filter_with_dominance(input, curr_l); @@ -701,15 +701,15 @@ where }); } - fn _filter_with_barrier(&mut self, input: &CompilationInput, curr_l: &mut Vec) { + fn _filter_with_cache(&mut self, input: &CompilationInput, curr_l: &mut Vec) { curr_l.retain(|id| { let node = get!(mut node id, self); - let threshold = input.barrier.get_threshold(node.state.as_ref(), node.depth); + let threshold = input.cache.get_threshold(node.state.as_ref(), node.depth); if let Some(threshold) = threshold { if node.value_top > threshold.value { true } else { - node.flags.set_pruned_by_barrier(true); + node.flags.set_pruned_by_cache(true); node.theta = Some(threshold.value); // set theta for later propagation false } @@ -1092,7 +1092,7 @@ mod test_default_mdd { use fxhash::FxHashMap; - use crate::{Variable, DecisionDiagram, SubProblem, CompilationInput, Problem, Decision, Relaxation, StateRanking, NoCutoff, CompilationType, Cutoff, Reason, DecisionCallback, EmptyBarrier, SimpleBarrier, Barrier, LAST_EXACT_LAYER, Mdd, FRONTIER, VizConfigBuilder, Threshold, EmptyDominanceChecker}; + use crate::{Variable, DecisionDiagram, SubProblem, CompilationInput, Problem, Decision, Relaxation, StateRanking, NoCutoff, CompilationType, Cutoff, Reason, DecisionCallback, EmptyCache, SimpleCache, Cache, LAST_EXACT_LAYER, Mdd, FRONTIER, VizConfigBuilder, Threshold, EmptyDominanceChecker}; type DefaultMDD = DefaultMDDLEL; type DefaultMDDLEL = Mdd; @@ -1107,7 +1107,7 @@ mod test_default_mdd { #[test] fn root_remembers_the_pa_from_the_fringe_node() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let mut input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1124,7 +1124,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 1, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; @@ -1144,7 +1144,7 @@ mod test_default_mdd { // In an exact setup, the dummy problem would be 3*3*3 = 9 large at the bottom level #[test] fn exact_completely_unrolls_the_mdd_no_matter_its_width() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1161,7 +1161,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1180,7 +1180,7 @@ mod test_default_mdd { #[test] fn restricted_drops_the_less_interesting_nodes() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1197,7 +1197,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1216,7 +1216,7 @@ mod test_default_mdd { #[test] fn exact_no_cutoff_completion_must_be_coherent_with_outcome() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1233,7 +1233,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1246,7 +1246,7 @@ mod test_default_mdd { } #[test] fn restricted_no_cutoff_completion_must_be_coherent_with_outcome_() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1263,7 +1263,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1276,7 +1276,7 @@ mod test_default_mdd { } #[test] fn relaxed_no_cutoff_completion_must_be_coherent_with_outcome() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1293,7 +1293,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1312,7 +1312,7 @@ mod test_default_mdd { } #[test] fn exact_fails_with_cutoff_when_cutoff_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1329,7 +1329,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1340,7 +1340,7 @@ mod test_default_mdd { #[test] fn restricted_fails_with_cutoff_when_cutoff_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1357,7 +1357,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1367,7 +1367,7 @@ mod test_default_mdd { } #[test] fn relaxed_fails_with_cutoff_when_cutoff_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1384,7 +1384,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1395,7 +1395,7 @@ mod test_default_mdd { #[test] fn relaxed_merges_the_less_interesting_nodes() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1412,7 +1412,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1432,7 +1432,7 @@ mod test_default_mdd { #[test] fn relaxed_populates_the_cutset_and_will_not_squash_first_layer() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1449,7 +1449,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1463,7 +1463,7 @@ mod test_default_mdd { #[test] fn an_exact_mdd_must_be_exact() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1480,7 +1480,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1492,7 +1492,7 @@ mod test_default_mdd { #[test] fn a_relaxed_mdd_is_exact_as_long_as_no_merge_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1509,7 +1509,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1521,7 +1521,7 @@ mod test_default_mdd { #[test] fn a_relaxed_mdd_is_not_exact_when_a_merge_occurred() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1538,7 +1538,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1549,7 +1549,7 @@ mod test_default_mdd { } #[test] fn a_restricted_mdd_is_exact_as_long_as_no_restriction_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1566,7 +1566,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1577,7 +1577,7 @@ mod test_default_mdd { } #[test] fn a_restricted_mdd_is_not_exact_when_a_restriction_occurred() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1594,7 +1594,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1605,7 +1605,7 @@ mod test_default_mdd { } #[test] fn when_the_problem_is_infeasible_there_is_no_solution() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1622,7 +1622,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1632,7 +1632,7 @@ mod test_default_mdd { } #[test] fn when_the_problem_is_infeasible_there_is_no_best_value() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1649,7 +1649,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1659,7 +1659,7 @@ mod test_default_mdd { } #[test] fn exact_skips_node_with_an_ub_less_than_best_known_lb() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1676,7 +1676,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1686,7 +1686,7 @@ mod test_default_mdd { } #[test] fn relaxed_skips_node_with_an_ub_less_than_best_known_lb() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1703,7 +1703,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1713,7 +1713,7 @@ mod test_default_mdd { } #[test] fn restricted_skips_node_with_an_ub_less_than_best_known_lb() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1730,7 +1730,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1740,11 +1740,11 @@ mod test_default_mdd { } #[test] fn exact_skips_nodes_with_a_value_less_than_known_threshold() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1761,7 +1761,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1771,11 +1771,11 @@ mod test_default_mdd { } #[test] fn relaxed_skips_nodes_with_a_value_less_than_known_threshold() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1792,7 +1792,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1802,11 +1802,11 @@ mod test_default_mdd { } #[test] fn restricted_skips_nodes_with_a_value_less_than_known_threshold() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1823,7 +1823,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1834,8 +1834,8 @@ mod test_default_mdd { #[test] fn restricted_mdd_computes_thresholds_when_exact() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1852,7 +1852,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1881,14 +1881,14 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } #[test] fn relaxed_mdd_computes_thresholds_when_exact() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1905,7 +1905,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1934,14 +1934,14 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } #[test] fn restricted_mdd_computes_thresholds_when_all_pruned() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1958,7 +1958,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1987,14 +1987,14 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } #[test] fn relaxed_mdd_computes_thresholds_when_all_pruned() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2011,7 +2011,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -2040,7 +2040,7 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } @@ -2173,8 +2173,8 @@ mod test_default_mdd { #[test] fn relaxed_computes_local_bounds_and_thresholds_1() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2191,7 +2191,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDLEL::new(); @@ -2208,34 +2208,34 @@ mod test_default_mdd { assert_eq!(14, v[&'b']); assert_eq!(2, v.len()); - assert!(barrier.get_threshold(&'r', 0).is_some()); - assert!(barrier.get_threshold(&'a', 1).is_some()); - assert!(barrier.get_threshold(&'b', 1).is_some()); - assert!(barrier.get_threshold(&'M', 2).is_none()); - assert!(barrier.get_threshold(&'e', 2).is_none()); - assert!(barrier.get_threshold(&'f', 2).is_none()); - assert!(barrier.get_threshold(&'g', 3).is_none()); - assert!(barrier.get_threshold(&'h', 3).is_none()); - assert!(barrier.get_threshold(&'i', 3).is_none()); - assert!(barrier.get_threshold(&'t', 4).is_none()); - - let mut threshold = barrier.get_threshold(&'r', 0).unwrap(); + assert!(cache.get_threshold(&'r', 0).is_some()); + assert!(cache.get_threshold(&'a', 1).is_some()); + assert!(cache.get_threshold(&'b', 1).is_some()); + assert!(cache.get_threshold(&'M', 2).is_none()); + assert!(cache.get_threshold(&'e', 2).is_none()); + assert!(cache.get_threshold(&'f', 2).is_none()); + assert!(cache.get_threshold(&'g', 3).is_none()); + assert!(cache.get_threshold(&'h', 3).is_none()); + assert!(cache.get_threshold(&'i', 3).is_none()); + assert!(cache.get_threshold(&'t', 4).is_none()); + + let mut threshold = cache.get_threshold(&'r', 0).unwrap(); assert_eq!(0, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'a', 1).unwrap(); + threshold = cache.get_threshold(&'a', 1).unwrap(); assert_eq!(10, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'b', 1).unwrap(); + threshold = cache.get_threshold(&'b', 1).unwrap(); assert_eq!(7, threshold.value); assert!(!threshold.explored); } #[test] fn relaxed_computes_local_bounds_and_thresholds_2() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2252,7 +2252,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDFC::new(); @@ -2271,50 +2271,50 @@ mod test_default_mdd { assert_eq!(14, v[&'i']); assert_eq!(4, v.len()); - assert!(barrier.get_threshold(&'r', 0).is_some()); - assert!(barrier.get_threshold(&'a', 1).is_some()); - assert!(barrier.get_threshold(&'b', 1).is_some()); - assert!(barrier.get_threshold(&'M', 2).is_none()); - assert!(barrier.get_threshold(&'e', 2).is_some()); - assert!(barrier.get_threshold(&'f', 2).is_some()); - assert!(barrier.get_threshold(&'g', 3).is_none()); - assert!(barrier.get_threshold(&'h', 3).is_some()); - assert!(barrier.get_threshold(&'i', 3).is_some()); - assert!(barrier.get_threshold(&'t', 4).is_none()); - - let mut threshold = barrier.get_threshold(&'r', 0).unwrap(); + assert!(cache.get_threshold(&'r', 0).is_some()); + assert!(cache.get_threshold(&'a', 1).is_some()); + assert!(cache.get_threshold(&'b', 1).is_some()); + assert!(cache.get_threshold(&'M', 2).is_none()); + assert!(cache.get_threshold(&'e', 2).is_some()); + assert!(cache.get_threshold(&'f', 2).is_some()); + assert!(cache.get_threshold(&'g', 3).is_none()); + assert!(cache.get_threshold(&'h', 3).is_some()); + assert!(cache.get_threshold(&'i', 3).is_some()); + assert!(cache.get_threshold(&'t', 4).is_none()); + + let mut threshold = cache.get_threshold(&'r', 0).unwrap(); assert_eq!(0, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'a', 1).unwrap(); + threshold = cache.get_threshold(&'a', 1).unwrap(); assert_eq!(10, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'b', 1).unwrap(); + threshold = cache.get_threshold(&'b', 1).unwrap(); assert_eq!(7, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'e', 2).unwrap(); + threshold = cache.get_threshold(&'e', 2).unwrap(); assert_eq!(13, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'f', 2).unwrap(); + threshold = cache.get_threshold(&'f', 2).unwrap(); assert_eq!(12, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'h', 3).unwrap(); + threshold = cache.get_threshold(&'h', 3).unwrap(); assert_eq!(13, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'i', 3).unwrap(); + threshold = cache.get_threshold(&'i', 3).unwrap(); assert_eq!(14, threshold.value); assert!(!threshold.explored); } #[test] fn relaxed_computes_local_bounds_and_thresholds_with_pruning() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2331,7 +2331,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDFC::new(); @@ -2348,50 +2348,50 @@ mod test_default_mdd { assert_eq!(14, v[&'b']); assert_eq!(2, v.len()); - assert!(barrier.get_threshold(&'r', 0).is_some()); - assert!(barrier.get_threshold(&'a', 1).is_some()); - assert!(barrier.get_threshold(&'b', 1).is_some()); - assert!(barrier.get_threshold(&'M', 2).is_none()); - assert!(barrier.get_threshold(&'e', 2).is_some()); - assert!(barrier.get_threshold(&'f', 2).is_some()); - assert!(barrier.get_threshold(&'g', 3).is_none()); - assert!(barrier.get_threshold(&'h', 3).is_some()); - assert!(barrier.get_threshold(&'i', 3).is_some()); - assert!(barrier.get_threshold(&'t', 4).is_none()); - - let mut threshold = barrier.get_threshold(&'r', 0).unwrap(); + assert!(cache.get_threshold(&'r', 0).is_some()); + assert!(cache.get_threshold(&'a', 1).is_some()); + assert!(cache.get_threshold(&'b', 1).is_some()); + assert!(cache.get_threshold(&'M', 2).is_none()); + assert!(cache.get_threshold(&'e', 2).is_some()); + assert!(cache.get_threshold(&'f', 2).is_some()); + assert!(cache.get_threshold(&'g', 3).is_none()); + assert!(cache.get_threshold(&'h', 3).is_some()); + assert!(cache.get_threshold(&'i', 3).is_some()); + assert!(cache.get_threshold(&'t', 4).is_none()); + + let mut threshold = cache.get_threshold(&'r', 0).unwrap(); assert_eq!(0, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'a', 1).unwrap(); + threshold = cache.get_threshold(&'a', 1).unwrap(); assert_eq!(10, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'b', 1).unwrap(); + threshold = cache.get_threshold(&'b', 1).unwrap(); assert_eq!(8, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'e', 2).unwrap(); + threshold = cache.get_threshold(&'e', 2).unwrap(); assert_eq!(15, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'f', 2).unwrap(); + threshold = cache.get_threshold(&'f', 2).unwrap(); assert_eq!(13, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'h', 3).unwrap(); + threshold = cache.get_threshold(&'h', 3).unwrap(); assert_eq!(15, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'i', 3).unwrap(); + threshold = cache.get_threshold(&'i', 3).unwrap(); assert_eq!(15, threshold.value); assert!(threshold.explored); } #[test] fn test_default_visualisation() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2408,7 +2408,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDFC::new(); @@ -2423,8 +2423,8 @@ mod test_default_mdd { #[test] fn test_terse_visualisation() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2441,7 +2441,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDFC::new(); @@ -2461,8 +2461,8 @@ mod test_default_mdd { #[test] fn test_show_deleted_viz() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2479,7 +2479,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDFC::new(); @@ -2499,8 +2499,8 @@ mod test_default_mdd { #[test] fn test_show_group_merged() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2517,7 +2517,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDDFC::new(); diff --git a/ddo/src/implementation/mdd/node_flags.rs b/ddo/src/implementation/mdd/node_flags.rs index 4774094d..8d21a86b 100644 --- a/ddo/src/implementation/mdd/node_flags.rs +++ b/ddo/src/implementation/mdd/node_flags.rs @@ -57,8 +57,8 @@ impl NodeFlags { pub const F_CUTSET: u8 = 8; /// The position of the deleted flag. pub const F_DELETED: u8 = 16; - /// The position of the barrier flag. - pub const F_BARRIER: u8 = 32; + /// The position of the cache flag. + pub const F_CACHE: u8 = 32; /// The position of the above cut-set flag. pub const F_ABOVE_CUTSET: u8 = 64; @@ -113,10 +113,10 @@ impl NodeFlags { pub fn is_deleted(self) -> bool { self.test(NodeFlags::F_DELETED) } - /// Returns true iff the barrier flag is turned on + /// Returns true iff the cache flag is turned on #[inline] - pub fn is_pruned_by_barrier(self) -> bool { - self.test(NodeFlags::F_BARRIER) + pub fn is_pruned_by_cache(self) -> bool { + self.test(NodeFlags::F_CACHE) } /// Sets the exact flag to the given value #[inline] @@ -146,10 +146,10 @@ impl NodeFlags { pub fn set_deleted(&mut self, deleted: bool) { self.set(NodeFlags::F_DELETED, deleted) } - /// Sets the barrier flag to the given value + /// Sets the cache flag to the given value #[inline] - pub fn set_pruned_by_barrier(&mut self, barrier: bool) { - self.set(NodeFlags::F_BARRIER, barrier) + pub fn set_pruned_by_cache(&mut self, cache: bool) { + self.set(NodeFlags::F_CACHE, cache) } /// Checks whether all the flags encoded in the given mask are turned on. /// Otherwise, it returns false @@ -299,18 +299,18 @@ mod test_node_flags { assert_eq!(true, tested.is_deleted()); } #[test] - fn is_pruned_by_barrier_iff_marked_so() { + fn is_pruned_by_cache_iff_marked_so() { let mut tested = NodeFlags::new_exact(); - assert_eq!(false, tested.is_pruned_by_barrier()); + assert_eq!(false, tested.is_pruned_by_cache()); - tested.set_pruned_by_barrier(true); - assert_eq!(true, tested.is_pruned_by_barrier()); + tested.set_pruned_by_cache(true); + assert_eq!(true, tested.is_pruned_by_cache()); - tested.set_pruned_by_barrier(false); - assert_eq!(false, tested.is_pruned_by_barrier()); + tested.set_pruned_by_cache(false); + assert_eq!(false, tested.is_pruned_by_cache()); - tested.set_pruned_by_barrier(true); - assert_eq!(true, tested.is_pruned_by_barrier()); + tested.set_pruned_by_cache(true); + assert_eq!(true, tested.is_pruned_by_cache()); } #[test] fn test_yields_the_value_of_the_flag() { @@ -320,7 +320,7 @@ mod test_node_flags { assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); tested.set_relaxed(true); assert_eq!(true, tested.test(NodeFlags::F_EXACT)); @@ -328,7 +328,7 @@ mod test_node_flags { assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); tested.set_marked(true); assert_eq!(true, tested.test(NodeFlags::F_EXACT)); @@ -336,7 +336,7 @@ mod test_node_flags { assert_eq!(true, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); tested.set_exact(false); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); @@ -344,7 +344,7 @@ mod test_node_flags { assert_eq!(true, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); tested.set_relaxed(false); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); @@ -352,7 +352,7 @@ mod test_node_flags { assert_eq!(true, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); tested.set_marked(false); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); @@ -360,7 +360,7 @@ mod test_node_flags { assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); tested.set_deleted(true); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); @@ -368,15 +368,15 @@ mod test_node_flags { assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(true, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); - tested.set_pruned_by_barrier(true); + tested.set_pruned_by_cache(true); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); assert_eq!(false, tested.test(NodeFlags::F_RELAXED)); assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(true, tested.test(NodeFlags::F_DELETED)); - assert_eq!(true, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(true, tested.test(NodeFlags::F_CACHE)); tested.set_deleted(false); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); @@ -384,15 +384,15 @@ mod test_node_flags { assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(true, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(true, tested.test(NodeFlags::F_CACHE)); - tested.set_pruned_by_barrier(false); + tested.set_pruned_by_cache(false); assert_eq!(false, tested.test(NodeFlags::F_EXACT)); assert_eq!(false, tested.test(NodeFlags::F_RELAXED)); assert_eq!(false, tested.test(NodeFlags::F_MARKED)); assert_eq!(false, tested.test(NodeFlags::F_CUTSET)); assert_eq!(false, tested.test(NodeFlags::F_DELETED)); - assert_eq!(false, tested.test(NodeFlags::F_BARRIER)); + assert_eq!(false, tested.test(NodeFlags::F_CACHE)); } #[test] fn test_checks_the_value_of_more_than_one_flag() { @@ -714,6 +714,6 @@ mod test_node_flags { assert_eq!(false, NodeFlags::default().test(NodeFlags::F_MARKED)); assert_eq!(false, NodeFlags::default().test(NodeFlags::F_CUTSET)); assert_eq!(false, NodeFlags::default().test(NodeFlags::F_DELETED)); - assert_eq!(false, NodeFlags::default().test(NodeFlags::F_BARRIER)); + assert_eq!(false, NodeFlags::default().test(NodeFlags::F_CACHE)); } } diff --git a/ddo/src/implementation/mdd/pooled.rs b/ddo/src/implementation/mdd/pooled.rs index 5ccfb9eb..301c7161 100644 --- a/ddo/src/implementation/mdd/pooled.rs +++ b/ddo/src/implementation/mdd/pooled.rs @@ -2,8 +2,8 @@ //! the pruning techniques that I have proposed in my PhD thesis (RUB, LocB, EBPO). //! It also implements the techniques we proposed in //! -//! ``Branch-and-Bound with Barrier: Dominance and Suboptimality Detection for -//! DD-Based Branch-and-Bound''. +//! ``Decision Diagram-Based Branch-and-Bound with Caching +//! for Dominance and Suboptimality Detection''. use std::{sync::Arc, hash::Hash, collections::{hash_map::Entry, BTreeMap}, fmt::Debug}; @@ -52,7 +52,7 @@ struct Node { inbound: EdgesListId, // The rough upper bound associated to this node rub: isize, - /// A threshold value to be stored in the barrier that conditions the + /// A threshold value to be stored in the cache that conditions the /// re-exploration of other nodes with the same state. /// /// ### Note @@ -445,7 +445,7 @@ where } // traverse bottom-up - // note: barrier requires that all nodes have an associated locb. not only those below cutset + // note: cache requires that all nodes have an associated locb. not only those below cutset for Layer { nodes } in self.layers.values().rev() { for id in nodes.iter() { let node = get!(node id, self); @@ -487,8 +487,8 @@ where continue; } - // ATTENTION: YOU WANT TO PROPAGATE THETA EVEN IF THE NODE WAS PRUNED BY BARRIER - if !node.flags.is_pruned_by_barrier() { + // ATTENTION: YOU WANT TO PROPAGATE THETA EVEN IF THE NODE WAS PRUNED BY THE CACHE + if !node.flags.is_pruned_by_cache() { let tot_rub = node.value_top.saturating_add(node.rub); if tot_rub <= best_known { node.theta = Some(best_known.saturating_sub(node.rub)); @@ -504,7 +504,7 @@ where node.theta = Some(isize::MAX); } - Self::_maybe_update_barrier(node, input); + Self::_maybe_update_cache(node, input); } // only propagate if you have an actual threshold if let Some(my_theta) = node.theta { @@ -519,11 +519,11 @@ where } } - fn _maybe_update_barrier(node: &Node, input: &CompilationInput) { - // A node can only be added to the barrier if it belongs to the cutset or is above it + fn _maybe_update_cache(node: &Node, input: &CompilationInput) { + // A node can only be added to the cache if it belongs to the cutset or is above it if let Some(theta) = node.theta { if node.flags.is_above_cutset() { - input.barrier.update_threshold( + input.cache.update_threshold( node.state.clone(), node.depth, theta, @@ -620,9 +620,9 @@ where to_remove.drain(..).for_each(|s| { self.pool.remove(s.as_ref()); }); - let mut to_expand = curr_l.clone(); // need to preserve layer to remember nodes pruned by barrier + let mut to_expand = curr_l.clone(); // need to preserve layer to remember nodes pruned by cache if !self.layers.is_empty() { - self._filter_with_barrier(input, &mut to_expand); + self._filter_with_cache(input, &mut to_expand); } self._filter_with_dominance(input, &mut to_expand); @@ -657,15 +657,15 @@ where }); } - fn _filter_with_barrier(&mut self, input: &CompilationInput, curr_l: &mut Vec) { + fn _filter_with_cache(&mut self, input: &CompilationInput, curr_l: &mut Vec) { curr_l.retain(|id| { let node = get!(mut node id, self); - let threshold = input.barrier.get_threshold(node.state.as_ref(), node.depth); + let threshold = input.cache.get_threshold(node.state.as_ref(), node.depth); if let Some(threshold) = threshold { if node.value_top > threshold.value { true } else { - node.flags.set_pruned_by_barrier(true); + node.flags.set_pruned_by_cache(true); node.theta = Some(threshold.value); // set theta for later propagation false } @@ -1011,7 +1011,7 @@ mod test_default_mdd { use fxhash::FxHashMap; - use crate::{Variable, DecisionDiagram, SubProblem, CompilationInput, Problem, Decision, Relaxation, StateRanking, NoCutoff, CompilationType, Cutoff, Reason, DecisionCallback, EmptyBarrier, SimpleBarrier, Barrier, Pooled, VizConfigBuilder, Threshold, EmptyDominanceChecker}; + use crate::{Variable, DecisionDiagram, SubProblem, CompilationInput, Problem, Decision, Relaxation, StateRanking, NoCutoff, CompilationType, Cutoff, Reason, DecisionCallback, EmptyCache, SimpleCache, Cache, Pooled, VizConfigBuilder, Threshold, EmptyDominanceChecker}; type DefaultMDD = Pooled; @@ -1024,7 +1024,7 @@ mod test_default_mdd { #[test] fn root_remembers_the_pa_from_the_fringe_node() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let mut input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1041,7 +1041,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 1, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; @@ -1061,7 +1061,7 @@ mod test_default_mdd { // In an exact setup, the dummy problem would be 3*3*3 = 9 large at the bottom level #[test] fn exact_completely_unrolls_the_mdd_no_matter_its_width() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1078,7 +1078,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1097,7 +1097,7 @@ mod test_default_mdd { #[test] fn restricted_drops_the_less_interesting_nodes() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1114,7 +1114,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1133,7 +1133,7 @@ mod test_default_mdd { #[test] fn exact_no_cutoff_completion_must_be_coherent_with_outcome() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1150,7 +1150,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1163,7 +1163,7 @@ mod test_default_mdd { } #[test] fn restricted_no_cutoff_completion_must_be_coherent_with_outcome_() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1180,7 +1180,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1193,7 +1193,7 @@ mod test_default_mdd { } #[test] fn relaxed_no_cutoff_completion_must_be_coherent_with_outcome() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1210,7 +1210,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1229,7 +1229,7 @@ mod test_default_mdd { } #[test] fn exact_fails_with_cutoff_when_cutoff_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1246,7 +1246,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1257,7 +1257,7 @@ mod test_default_mdd { #[test] fn restricted_fails_with_cutoff_when_cutoff_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1274,7 +1274,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1284,7 +1284,7 @@ mod test_default_mdd { } #[test] fn relaxed_fails_with_cutoff_when_cutoff_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1301,7 +1301,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1312,7 +1312,7 @@ mod test_default_mdd { #[test] fn relaxed_merges_the_less_interesting_nodes() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1329,7 +1329,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1349,7 +1349,7 @@ mod test_default_mdd { #[test] fn relaxed_populates_the_cutset_and_will_not_squash_first_layer() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1366,7 +1366,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1380,7 +1380,7 @@ mod test_default_mdd { #[test] fn an_exact_mdd_must_be_exact() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1397,7 +1397,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1409,7 +1409,7 @@ mod test_default_mdd { #[test] fn a_relaxed_mdd_is_exact_as_long_as_no_merge_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1426,7 +1426,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1438,7 +1438,7 @@ mod test_default_mdd { #[test] fn a_relaxed_mdd_is_not_exact_when_a_merge_occurred() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1455,7 +1455,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1466,7 +1466,7 @@ mod test_default_mdd { } #[test] fn a_restricted_mdd_is_exact_as_long_as_no_restriction_occurs() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1483,7 +1483,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1494,7 +1494,7 @@ mod test_default_mdd { } #[test] fn a_restricted_mdd_is_not_exact_when_a_restriction_occurred() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1511,7 +1511,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1522,7 +1522,7 @@ mod test_default_mdd { } #[test] fn when_the_problem_is_infeasible_there_is_no_solution() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1539,7 +1539,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1549,7 +1549,7 @@ mod test_default_mdd { } #[test] fn when_the_problem_is_infeasible_there_is_no_best_value() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1566,7 +1566,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1576,7 +1576,7 @@ mod test_default_mdd { } #[test] fn exact_skips_node_with_an_ub_less_than_best_known_lb() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1593,7 +1593,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1603,7 +1603,7 @@ mod test_default_mdd { } #[test] fn relaxed_skips_node_with_an_ub_less_than_best_known_lb() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1620,7 +1620,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1630,7 +1630,7 @@ mod test_default_mdd { } #[test] fn restricted_skips_node_with_an_ub_less_than_best_known_lb() { - let barrier = EmptyBarrier::new(); + let cache = EmptyCache::new(); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1647,7 +1647,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1657,11 +1657,11 @@ mod test_default_mdd { } #[test] fn exact_skips_nodes_with_a_value_less_than_known_threshold() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Exact, @@ -1678,7 +1678,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1688,11 +1688,11 @@ mod test_default_mdd { } #[test] fn relaxed_skips_nodes_with_a_value_less_than_known_threshold() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1709,7 +1709,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1719,11 +1719,11 @@ mod test_default_mdd { } #[test] fn restricted_skips_nodes_with_a_value_less_than_known_threshold() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); - barrier.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 0}), 1, 0, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 1}), 1, 1, true); + cache.update_threshold(Arc::new(DummyState{depth: 1, value: 2}), 1, 2, true); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1740,7 +1740,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1751,8 +1751,8 @@ mod test_default_mdd { #[test] fn restricted_mdd_computes_thresholds_when_exact() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1769,7 +1769,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1798,14 +1798,14 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } #[test] fn relaxed_mdd_computes_thresholds_when_exact() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1822,7 +1822,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1851,14 +1851,14 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } #[test] fn restricted_mdd_computes_thresholds_when_all_pruned() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Restricted, @@ -1875,7 +1875,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1904,14 +1904,14 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } #[test] fn relaxed_mdd_computes_thresholds_when_all_pruned() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&DummyProblem); + let mut cache = SimpleCache::default(); + cache.initialize(&DummyProblem); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -1928,7 +1928,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -1957,7 +1957,7 @@ mod test_default_mdd { ]; for (state, threshold) in expected.iter().copied() { - assert_eq!(threshold, barrier.get_threshold(&state, state.depth)); + assert_eq!(threshold, cache.get_threshold(&state, state.depth)); } } @@ -2090,8 +2090,8 @@ mod test_default_mdd { #[test] fn relaxed_computes_local_bounds_and_thresholds() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2108,7 +2108,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -2127,50 +2127,50 @@ mod test_default_mdd { assert_eq!(14, v[&'i']); assert_eq!(4, v.len()); - assert!(barrier.get_threshold(&'r', 0).is_some()); - assert!(barrier.get_threshold(&'a', 1).is_some()); - assert!(barrier.get_threshold(&'b', 1).is_some()); - assert!(barrier.get_threshold(&'M', 2).is_none()); - assert!(barrier.get_threshold(&'e', 2).is_some()); - assert!(barrier.get_threshold(&'f', 2).is_some()); - assert!(barrier.get_threshold(&'g', 3).is_none()); - assert!(barrier.get_threshold(&'h', 3).is_some()); - assert!(barrier.get_threshold(&'i', 3).is_some()); - assert!(barrier.get_threshold(&'t', 4).is_none()); - - let mut threshold = barrier.get_threshold(&'r', 0).unwrap(); + assert!(cache.get_threshold(&'r', 0).is_some()); + assert!(cache.get_threshold(&'a', 1).is_some()); + assert!(cache.get_threshold(&'b', 1).is_some()); + assert!(cache.get_threshold(&'M', 2).is_none()); + assert!(cache.get_threshold(&'e', 2).is_some()); + assert!(cache.get_threshold(&'f', 2).is_some()); + assert!(cache.get_threshold(&'g', 3).is_none()); + assert!(cache.get_threshold(&'h', 3).is_some()); + assert!(cache.get_threshold(&'i', 3).is_some()); + assert!(cache.get_threshold(&'t', 4).is_none()); + + let mut threshold = cache.get_threshold(&'r', 0).unwrap(); assert_eq!(0, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'a', 1).unwrap(); + threshold = cache.get_threshold(&'a', 1).unwrap(); assert_eq!(10, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'b', 1).unwrap(); + threshold = cache.get_threshold(&'b', 1).unwrap(); assert_eq!(7, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'e', 2).unwrap(); + threshold = cache.get_threshold(&'e', 2).unwrap(); assert_eq!(13, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'f', 2).unwrap(); + threshold = cache.get_threshold(&'f', 2).unwrap(); assert_eq!(12, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'h', 3).unwrap(); + threshold = cache.get_threshold(&'h', 3).unwrap(); assert_eq!(13, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'i', 3).unwrap(); + threshold = cache.get_threshold(&'i', 3).unwrap(); assert_eq!(14, threshold.value); assert!(!threshold.explored); } #[test] fn relaxed_computes_local_bounds_and_thresholds_with_pruning() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2187,7 +2187,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -2204,50 +2204,50 @@ mod test_default_mdd { assert_eq!(14, v[&'b']); assert_eq!(2, v.len()); - assert!(barrier.get_threshold(&'r', 0).is_some()); - assert!(barrier.get_threshold(&'a', 1).is_some()); - assert!(barrier.get_threshold(&'b', 1).is_some()); - assert!(barrier.get_threshold(&'M', 2).is_none()); - assert!(barrier.get_threshold(&'e', 2).is_some()); - assert!(barrier.get_threshold(&'f', 2).is_some()); - assert!(barrier.get_threshold(&'g', 3).is_none()); - assert!(barrier.get_threshold(&'h', 3).is_some()); - assert!(barrier.get_threshold(&'i', 3).is_some()); - assert!(barrier.get_threshold(&'t', 4).is_none()); - - let mut threshold = barrier.get_threshold(&'r', 0).unwrap(); + assert!(cache.get_threshold(&'r', 0).is_some()); + assert!(cache.get_threshold(&'a', 1).is_some()); + assert!(cache.get_threshold(&'b', 1).is_some()); + assert!(cache.get_threshold(&'M', 2).is_none()); + assert!(cache.get_threshold(&'e', 2).is_some()); + assert!(cache.get_threshold(&'f', 2).is_some()); + assert!(cache.get_threshold(&'g', 3).is_none()); + assert!(cache.get_threshold(&'h', 3).is_some()); + assert!(cache.get_threshold(&'i', 3).is_some()); + assert!(cache.get_threshold(&'t', 4).is_none()); + + let mut threshold = cache.get_threshold(&'r', 0).unwrap(); assert_eq!(0, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'a', 1).unwrap(); + threshold = cache.get_threshold(&'a', 1).unwrap(); assert_eq!(10, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'b', 1).unwrap(); + threshold = cache.get_threshold(&'b', 1).unwrap(); assert_eq!(8, threshold.value); assert!(!threshold.explored); - threshold = barrier.get_threshold(&'e', 2).unwrap(); + threshold = cache.get_threshold(&'e', 2).unwrap(); assert_eq!(15, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'f', 2).unwrap(); + threshold = cache.get_threshold(&'f', 2).unwrap(); assert_eq!(13, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'h', 3).unwrap(); + threshold = cache.get_threshold(&'h', 3).unwrap(); assert_eq!(15, threshold.value); assert!(threshold.explored); - threshold = barrier.get_threshold(&'i', 3).unwrap(); + threshold = cache.get_threshold(&'i', 3).unwrap(); assert_eq!(15, threshold.value); assert!(threshold.explored); } #[test] fn test_default_visualisation() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2264,7 +2264,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -2279,8 +2279,8 @@ mod test_default_mdd { #[test] fn test_terse_visualisation() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2297,7 +2297,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -2317,8 +2317,8 @@ mod test_default_mdd { #[test] fn test_show_deleted_viz() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2335,7 +2335,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); @@ -2355,8 +2355,8 @@ mod test_default_mdd { #[test] fn test_show_group_merged() { - let mut barrier = SimpleBarrier::default(); - barrier.initialize(&LocBoundsAndThresholdsExamplePb); + let mut cache = SimpleCache::default(); + cache.initialize(&LocBoundsAndThresholdsExamplePb); let dominance = EmptyDominanceChecker::default(); let input = CompilationInput { comp_type: crate::CompilationType::Relaxed, @@ -2373,7 +2373,7 @@ mod test_default_mdd { ub: isize::MAX, depth: 0, }, - barrier: &barrier, + cache: &cache, dominance: &dominance, }; let mut mdd = DefaultMDD::new(); diff --git a/ddo/src/implementation/mod.rs b/ddo/src/implementation/mod.rs index df3187f4..cf04b4ad 100644 --- a/ddo/src/implementation/mod.rs +++ b/ddo/src/implementation/mod.rs @@ -23,13 +23,13 @@ mod heuristics; mod fringe; mod mdd; -mod barrier; +mod cache; mod dominance; mod solver; pub use heuristics::*; pub use fringe::*; pub use mdd::*; -pub use barrier::*; +pub use cache::*; pub use dominance::*; pub use solver::*; \ No newline at end of file diff --git a/ddo/src/implementation/solver/mod.rs b/ddo/src/implementation/solver/mod.rs index b5331f3b..7d530e9e 100644 --- a/ddo/src/implementation/solver/mod.rs +++ b/ddo/src/implementation/solver/mod.rs @@ -23,25 +23,25 @@ mod sequential; pub use parallel::*; pub use sequential::*; -use crate::{DefaultMDDLEL, EmptyBarrier, SimpleBarrier, DefaultMDDFC, Pooled}; +use crate::{DefaultMDDLEL, EmptyCache, SimpleCache, DefaultMDDFC, Pooled}; /// A type alias to emphasize that this is the solver that should be used by default. -pub type DefaultSolver<'a, State> = ParNoBarrierSolverLel<'a, State>; -pub type DefaultBarrierSolver<'a, State> = ParBarrierSolverFc<'a, State>; +pub type DefaultSolver<'a, State> = ParNoCachingSolverLel<'a, State>; +pub type DefaultCachingSolver<'a, State> = ParCachingSolverFc<'a, State>; -pub type ParNoBarrierSolverLel<'a, State> = ParallelSolver<'a, State, DefaultMDDLEL, EmptyBarrier>; -pub type ParNoBarrierSolverFc<'a, State> = ParallelSolver<'a, State, DefaultMDDFC, EmptyBarrier>; -pub type ParNoBarrierSolverPooled<'a, State>= ParallelSolver<'a, State, Pooled, EmptyBarrier>; +pub type ParNoCachingSolverLel<'a, State> = ParallelSolver<'a, State, DefaultMDDLEL, EmptyCache>; +pub type ParNoCachingSolverFc<'a, State> = ParallelSolver<'a, State, DefaultMDDFC, EmptyCache>; +pub type ParNoCachingSolverPooled<'a, State>= ParallelSolver<'a, State, Pooled, EmptyCache>; -pub type ParBarrierSolverLel<'a, State> = ParallelSolver<'a, State, DefaultMDDLEL, SimpleBarrier>; -pub type ParBarrierSolverFc<'a, State> = ParallelSolver<'a, State, DefaultMDDFC, SimpleBarrier>; -pub type ParBarrierSolverPooled<'a, State>= ParallelSolver<'a, State, Pooled, SimpleBarrier>; +pub type ParCachingSolverLel<'a, State> = ParallelSolver<'a, State, DefaultMDDLEL, SimpleCache>; +pub type ParCachingSolverFc<'a, State> = ParallelSolver<'a, State, DefaultMDDFC, SimpleCache>; +pub type ParCachingSolverPooled<'a, State>= ParallelSolver<'a, State, Pooled, SimpleCache>; -pub type SeqNoBarrierSolverLel<'a, State> = SequentialSolver<'a, State, DefaultMDDLEL, EmptyBarrier>; -pub type SeqNoBarrierSolverFc<'a, State> = SequentialSolver<'a, State, DefaultMDDFC, EmptyBarrier>; -pub type SeqNoBarrierSolverPooled<'a, State>= SequentialSolver<'a, State, Pooled, EmptyBarrier>; +pub type SeqNoCachingSolverLel<'a, State> = SequentialSolver<'a, State, DefaultMDDLEL, EmptyCache>; +pub type SeqNoCachingSolverFc<'a, State> = SequentialSolver<'a, State, DefaultMDDFC, EmptyCache>; +pub type SeqNoCachingSolverPooled<'a, State>= SequentialSolver<'a, State, Pooled, EmptyCache>; -pub type SeqBarrierSolverLel<'a, State> = SequentialSolver<'a, State, DefaultMDDLEL, SimpleBarrier>; -pub type SeqBarrierSolverFc<'a, State> = SequentialSolver<'a, State, DefaultMDDFC, SimpleBarrier>; -pub type SeqBarrierSolverPooled<'a, State>= SequentialSolver<'a, State, Pooled, SimpleBarrier>; \ No newline at end of file +pub type SeqCachingSolverLel<'a, State> = SequentialSolver<'a, State, DefaultMDDLEL, SimpleCache>; +pub type SeqCachingSolverFc<'a, State> = SequentialSolver<'a, State, DefaultMDDFC, SimpleCache>; +pub type SeqCachingSolverPooled<'a, State>= SequentialSolver<'a, State, Pooled, SimpleCache>; \ No newline at end of file diff --git a/ddo/src/implementation/solver/parallel.rs b/ddo/src/implementation/solver/parallel.rs index 055cfdb3..7a516e13 100644 --- a/ddo/src/implementation/solver/parallel.rs +++ b/ddo/src/implementation/solver/parallel.rs @@ -26,7 +26,7 @@ use std::{marker::PhantomData, sync::Arc, hash::Hash}; use parking_lot::{Condvar, Mutex}; -use crate::{Fringe, Decision, Problem, Relaxation, StateRanking, WidthHeuristic, Cutoff, SubProblem, DecisionDiagram, CompilationInput, CompilationType, Solver, Solution, Completion, Reason, Barrier, DominanceChecker}; +use crate::{Fringe, Decision, Problem, Relaxation, StateRanking, WidthHeuristic, Cutoff, SubProblem, DecisionDiagram, CompilationInput, CompilationType, Solver, Solution, Completion, Reason, Cache, DominanceChecker}; /// The shared data that may only be manipulated within critical sections struct Critical<'a, State> { @@ -82,8 +82,8 @@ struct Critical<'a, State> { /// The state which is shared among the many running threads: it provides an /// access to the critical data (protected by a mutex) as well as a monitor /// (condvar) to park threads in case of node-starvation. -struct Shared<'a, State, B> where - B : Barrier + Send + Sync + Default, +struct Shared<'a, State, C> where + C : Cache + Send + Sync + Default, { /// A reference to the problem being solved with branch-and-bound MDD problem: &'a (dyn Problem + Send + Sync), @@ -100,7 +100,7 @@ struct Shared<'a, State, B> where cutoff: &'a (dyn Cutoff + Send + Sync), /// Data structure containing info about past compilations used to prune the search - barrier: B, + cache: C, dominance: &'a (dyn DominanceChecker + Send + Sync), /// This is the shared state data which can only be accessed within critical @@ -284,12 +284,12 @@ enum WorkLoad { /// } /// } /// ``` -pub struct ParallelSolver<'a, State, D, B> +pub struct ParallelSolver<'a, State, D, C> where D: DecisionDiagram + Default, - B: Barrier + Send + Sync + Default, + C: Cache + Send + Sync + Default, { /// This is the shared state. Each thread is going to take a reference to it. - shared: Shared<'a, State, B>, + shared: Shared<'a, State, C>, /// This is a configuration parameter that tunes the number of threads that /// will be spawned to solve the problem. By default, this number amounts /// to the number of hardware threads available on the machine. @@ -299,11 +299,11 @@ where D: DecisionDiagram + Default, _phantom: PhantomData, } -impl<'a, State, D, B> ParallelSolver<'a, State, D, B> +impl<'a, State, D, C> ParallelSolver<'a, State, D, C> where State: Eq + Hash + Clone, D: DecisionDiagram + Default, - B: Barrier + Send + Sync + Default, + C: Cache + Send + Sync + Default, { pub fn new( problem: &'a (dyn Problem + Send + Sync), @@ -334,7 +334,7 @@ where ranking, width_heu, cutoff, - barrier: B::default(), + cache: C::default(), dominance, // monitor: Condvar::new(), @@ -367,7 +367,7 @@ where /// can pick it up and the processing can be bootstrapped. fn initialize(&mut self) { let root = self.root_node(); - self.shared.barrier.initialize(self.shared.problem); + self.shared.cache.initialize(self.shared.problem); let mut critical = self.shared.critical.lock(); critical.fringe.push(root); critical.open_by_layer[0] += 1; @@ -390,7 +390,7 @@ where /// it stores cut-set nodes onto the fringe for further parallel processing. fn process_one_node( mdd: &mut D, - shared: &Shared<'a, State, B>, + shared: &Shared<'a, State, C>, node: SubProblem, ) -> Result<(), Reason> { // 1. RESTRICTION @@ -412,7 +412,7 @@ where residual: &node, // best_lb, - barrier: &shared.barrier, + cache: &shared.cache, dominance: shared.dominance, }; @@ -436,14 +436,14 @@ where Ok(()) } - fn best_lb(shared: &Shared<'a, State, B>) -> isize { + fn best_lb(shared: &Shared<'a, State, C>) -> isize { shared.critical.lock().best_lb } /// This private method updates the shared best known node and lower bound in /// case the best value of the current `mdd` expansion improves the current /// bounds. - fn maybe_update_best(mdd: &D, shared: &Shared<'a, State, B>) { + fn maybe_update_best(mdd: &D, shared: &Shared<'a, State, C>) { let mut shared = shared.critical.lock(); let dd_best_value = mdd.best_exact_value().unwrap_or(isize::MIN); if dd_best_value > shared.best_lb { @@ -453,7 +453,7 @@ where } /// If necessary, tightens the bound of nodes in the cut-set of `mdd` and /// then add the relevant nodes to the shared fringe. - fn enqueue_cutset(mdd: &mut D, shared: &Shared<'a, State, B>, ub: isize) { + fn enqueue_cutset(mdd: &mut D, shared: &Shared<'a, State, C>, ub: isize) { let mut critical = shared.critical.lock(); let best_lb = critical.best_lb; mdd.drain_cutset(|mut cutset_node| { @@ -468,7 +468,7 @@ where }); } /// Acknowledges that a thread finished processing its node. - fn notify_node_finished(shared: &Shared<'a, State, B>, thread_id: usize, depth: usize) { + fn notify_node_finished(shared: &Shared<'a, State, C>, thread_id: usize, depth: usize) { let mut critical = shared.critical.lock(); critical.ongoing -= 1; critical.upper_bounds[thread_id] = isize::MAX; @@ -476,7 +476,7 @@ where shared.monitor.notify_all(); } - fn abort_search(shared: &Shared<'a, State, B>, reason: Reason, current_ub: isize) { + fn abort_search(shared: &Shared<'a, State, C>, reason: Reason, current_ub: isize) { let mut critical = shared.critical.lock(); critical.abort_proof = Some(reason); if critical.best_ub == isize::MAX { @@ -485,7 +485,7 @@ where critical.best_ub = current_ub.max(critical.best_ub); } critical.fringe.clear(); - shared.barrier.clear(); + shared.cache.clear(); } /// Consults the shared state to fetch a workload. Depending on the current @@ -497,14 +497,14 @@ where /// and thus the problem cannot be considered solved). /// + WorkItem, when the thread successfully obtained a subproblem to /// process. - fn get_workload(shared: &Shared<'a, State, B>, thread_id: usize) -> WorkLoad + fn get_workload(shared: &Shared<'a, State, C>, thread_id: usize) -> WorkLoad { let mut critical = shared.critical.lock(); - // Can we clean up the barrier? + // Can we clean up the cache? while critical.first_active_layer < shared.problem.nb_variables() && critical.open_by_layer[critical.first_active_layer] + critical.ongoing_by_layer[critical.first_active_layer] == 0 { - shared.barrier.clear_layer(critical.first_active_layer); + shared.cache.clear_layer(critical.first_active_layer); critical.first_active_layer += 1; } @@ -534,8 +534,8 @@ where return WorkLoad::Starvation; } - if shared.barrier.must_explore(&nn) { - shared.barrier.update_threshold(nn.state.clone(), nn.depth, nn.value, true); + if shared.cache.must_explore(&nn) { + shared.cache.update_threshold(nn.state.clone(), nn.depth, nn.value, true); break; } else { critical.open_by_layer[nn.depth] -= 1; @@ -559,11 +559,11 @@ where } } -impl<'a, State, D, B> Solver for ParallelSolver<'a, State, D, B> +impl<'a, State, D, C> Solver for ParallelSolver<'a, State, D, C> where State: Eq + PartialEq + Hash + Clone, D: DecisionDiagram + Default, - B: Barrier + Send + Sync + Default, + C: Cache + Send + Sync + Default, { /// Applies the branch and bound algorithm proposed by Bergman et al. to /// solve the problem to optimality. To do so, it spawns `nb_threads` workers @@ -650,8 +650,8 @@ where mod test_solver { use crate::*; - type DdLel<'a, T> = ParallelSolver<'a, T, DefaultMDDLEL, EmptyBarrier>; - type DdFc <'a, T> = ParallelSolver<'a, T, DefaultMDDFC, SimpleBarrier>; + type DdLel<'a, T> = ParallelSolver<'a, T, DefaultMDDLEL, EmptyCache>; + type DdFc <'a, T> = ParallelSolver<'a, T, DefaultMDDFC, SimpleCache>; #[test] fn by_default_best_lb_is_min_infinity() { diff --git a/ddo/src/implementation/solver/sequential.rs b/ddo/src/implementation/solver/sequential.rs index 0a70c1ee..76fed103 100644 --- a/ddo/src/implementation/solver/sequential.rs +++ b/ddo/src/implementation/solver/sequential.rs @@ -28,7 +28,7 @@ use std::clone::Clone; use std::{sync::Arc, hash::Hash}; -use crate::{Fringe, Decision, Problem, Relaxation, StateRanking, WidthHeuristic, Cutoff, SubProblem, DecisionDiagram, CompilationInput, CompilationType, Solver, Solution, Completion, Reason, Barrier, EmptyBarrier, DefaultMDDLEL, DominanceChecker}; +use crate::{Fringe, Decision, Problem, Relaxation, StateRanking, WidthHeuristic, Cutoff, SubProblem, DecisionDiagram, CompilationInput, CompilationType, Solver, Solution, Completion, Reason, Cache, EmptyCache, DefaultMDDLEL, DominanceChecker}; /// The workload a thread can get from the shared state enum WorkLoad { @@ -199,9 +199,9 @@ enum WorkLoad { /// } /// } /// ``` -pub struct SequentialSolver<'a, State, D = DefaultMDDLEL, B = EmptyBarrier> +pub struct SequentialSolver<'a, State, D = DefaultMDDLEL, C = EmptyCache> where D: DecisionDiagram + Default, - B: Barrier + Default, + C: Cache + Default, { /// A reference to the problem being solved with branch-and-bound MDD problem: &'a (dyn Problem), @@ -250,15 +250,15 @@ where D: DecisionDiagram + Default, /// mdds to be instantiated. mdd: D, /// Data structure containing info about past compilations used to prune the search - barrier: B, + cache: C, dominance: &'a (dyn DominanceChecker), } -impl<'a, State, D, B> SequentialSolver<'a, State, D, B> +impl<'a, State, D, C> SequentialSolver<'a, State, D, C> where State: Eq + Hash + Clone, D: DecisionDiagram + Default, - B: Barrier + Default, + C: Cache + Default, { pub fn new( problem: &'a (dyn Problem), @@ -297,7 +297,7 @@ where first_active_layer: 0, abort_proof: None, mdd: D::default(), - barrier: B::default(), + cache: C::default(), dominance, } } @@ -307,7 +307,7 @@ where /// can pick it up and the processing can be bootstrapped. fn initialize(&mut self) { let root = self.root_node(); - self.barrier.initialize(self.problem); + self.cache.initialize(self.problem); self.fringe.push(root); self.open_by_layer[0] += 1; } @@ -338,7 +338,7 @@ where return Ok(()); } - if !self.barrier.must_explore(&node) { + if !self.cache.must_explore(&node) { return Ok(()); } @@ -350,7 +350,7 @@ where relaxation: self.relaxation, ranking: self.ranking, cutoff: self.cutoff, - barrier: &self.barrier, + cache: &self.cache, dominance: self.dominance, residual: &node, // @@ -372,7 +372,7 @@ where relaxation: self.relaxation, ranking: self.ranking, cutoff: self.cutoff, - barrier: &self.barrier, + cache: &self.cache, dominance: self.dominance, residual: &node, // @@ -418,7 +418,7 @@ where fn abort_search(&mut self, reason: Reason) { self.abort_proof = Some(reason); self.fringe.clear(); - self.barrier.clear(); + self.cache.clear(); } /// Consults the shared state to fetch a workload. Depending on the current @@ -432,10 +432,10 @@ where /// process. fn get_workload(&mut self) -> WorkLoad { - // Can we clean up the barrier? + // Can we clean up the cache? while self.first_active_layer < self.problem.nb_variables() && self.open_by_layer[self.first_active_layer] == 0 { - self.barrier.clear_layer(self.first_active_layer); + self.cache.clear_layer(self.first_active_layer); self.first_active_layer += 1; } @@ -461,11 +461,11 @@ where } } -impl<'a, State, D, B> Solver for SequentialSolver<'a, State, D, B> +impl<'a, State, D, C> Solver for SequentialSolver<'a, State, D, C> where State: Eq + PartialEq + Hash + Clone, D: DecisionDiagram + Default, - B: Barrier + Default, + C: Cache + Default, { /// Applies the branch and bound algorithm proposed by Bergman et al. to /// solve the problem to optimality. To do so, it spawns `nb_threads` workers @@ -535,8 +535,8 @@ where mod test_solver { use crate::*; - type SeqSolver<'a, T> = SequentialSolver<'a, T, DefaultMDDLEL, EmptyBarrier>; - type SeqBarrierSolver<'a, T> = SequentialSolver<'a, T, DefaultMDDFC, SimpleBarrier>; + type SeqSolver<'a, T> = SequentialSolver<'a, T, DefaultMDDLEL, EmptyCache>; + type SeqCachingSolver<'a, T> = SequentialSolver<'a, T, DefaultMDDFC, SimpleCache>; #[test] fn by_default_best_lb_is_min_infinity() { @@ -792,7 +792,7 @@ mod test_solver { let width = NbUnassignedWidth(problem.nb_variables()); let dominance = EmptyDominanceChecker::default(); let mut fringe = SimpleFringe::new(MaxUB::new(&ranking)); - let mut solver = SeqBarrierSolver::custom( + let mut solver = SeqCachingSolver::custom( &problem, &relax, &ranking, @@ -872,7 +872,7 @@ mod test_solver { let width = NbUnassignedWidth(problem.nb_variables()); let dominance = EmptyDominanceChecker::default(); let mut fringe = SimpleFringe::new(MaxUB::new(&ranking)); - let mut solver = SeqBarrierSolver::new( + let mut solver = SeqCachingSolver::new( &problem, &relax, &ranking, diff --git a/py_ddo/src/lib.rs b/py_ddo/src/lib.rs index 09ccbaf7..37710076 100644 --- a/py_ddo/src/lib.rs +++ b/py_ddo/src/lib.rs @@ -1,6 +1,6 @@ use std::{time::{Duration, Instant}, hash::Hash, collections::HashMap}; -use ::ddo::{Problem, Cutoff, TimeBudget, NoCutoff, Fringe, NoDupFringe, StateRanking, MaxUB, SimpleFringe, WidthHeuristic, FixedWidth, NbUnassignedWidth, Variable, Decision, Relaxation, Solver, Completion, SeqNoBarrierSolverLel, SeqBarrierSolverLel, SeqBarrierSolverFc, SeqNoBarrierSolverFc}; +use ::ddo::{Problem, Cutoff, TimeBudget, NoCutoff, Fringe, NoDupFringe, StateRanking, MaxUB, SimpleFringe, WidthHeuristic, FixedWidth, NbUnassignedWidth, Variable, Decision, Relaxation, Solver, Completion, SeqNoCachingSolverLel, SeqCachingSolverLel, SeqCachingSolverFc, SeqNoCachingSolverFc}; use pyo3::{prelude::*, types::{PyBool}}; @@ -50,7 +50,7 @@ fn maximize( relax : PyObject, ranking : PyObject, lel : bool, - use_barrier: bool, + use_cache : bool, dedup : bool, width : Option, timeout : Option, @@ -71,7 +71,7 @@ fn maximize( cutoff.as_ref(), fringe.as_mut(), lel, - use_barrier + use_cache ); let start = Instant::now(); @@ -105,17 +105,17 @@ fn solver<'a, 'b>( cutoff : &'a dyn Cutoff, fringe : &'a mut dyn Fringe>, lel : bool, - use_barrier: bool, + use_cache : bool, ) -> Box { - match (lel, use_barrier) { + match (lel, use_cache) { (true, true) => - Box::new(SeqBarrierSolverLel::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), + Box::new(SeqCachingSolverLel::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), (true, false) => - Box::new(SeqNoBarrierSolverLel::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), + Box::new(SeqNoCachingSolverLel::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), (false, true) => - Box::new(SeqBarrierSolverFc::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), + Box::new(SeqCachingSolverFc::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), (false, false) => - Box::new(SeqNoBarrierSolverFc::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), + Box::new(SeqNoCachingSolverFc::custom(problem, relaxation, ranking, width_heu, cutoff, fringe)), } } diff --git a/seminar/ddo_seminar.ipynb b/seminar/ddo_seminar.ipynb index f8167c3f..254f3a30 100644 --- a/seminar/ddo_seminar.ipynb +++ b/seminar/ddo_seminar.ipynb @@ -67,7 +67,11 @@ "cell_type": "code", "execution_count": 2, "id": "09bcce95-9024-44b1-a327-d7f1bf494722", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ ":dep ddo = \"1.2.0\"\n", @@ -86,7 +90,11 @@ "cell_type": "code", "execution_count": 3, "id": "91c5ace0-08f8-4ed2-9fde-515773a1a4af", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "use ddo::*;\n", @@ -107,7 +115,11 @@ "cell_type": "code", "execution_count": 4, "id": "6ebfebb2-9734-4270-ac8f-b9715b506b56", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// In our DP model, we consider a state that simply consists of the remaining \n", @@ -137,7 +149,11 @@ "cell_type": "code", "execution_count": 5, "id": "81f36ebf-4dd8-4258-98f2-d17078a9a2ec", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// This structure represents a particular instance of the knapsack problem.\n", @@ -189,7 +205,11 @@ "cell_type": "code", "execution_count": 6, "id": "e925fef2-f17d-4b28-a2c1-bd90027f4b2b", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// For each variable in the decision problem, there are two possible choices:\n", @@ -262,7 +282,11 @@ "cell_type": "code", "execution_count": 7, "id": "b448adb3-39bb-4208-9e8b-afcf308ab8e2", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// First we define a structure to the relaxation.\n", @@ -297,7 +321,11 @@ "cell_type": "code", "execution_count": 8, "id": "a16dffa6-6f24-4e31-9519-eacb213cedc8", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "pub struct KPRanking;\n", @@ -322,7 +350,11 @@ "cell_type": "code", "execution_count": 9, "id": "bdb46038-9a09-4b00-8e20-1ba00b3dc077", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// This is your executable's entry point. It is the place where all the pieces are put together\n", @@ -355,7 +387,7 @@ " let dominance = EmptyDominanceChecker::default();\n", "\n", " // Create your solver object\n", - " let mut solver = DefaultBarrierSolver::new(\n", + " let mut solver = DefaultCachingSolver::new(\n", " &problem, \n", " &relaxation, \n", " &heuristic, \n", @@ -401,7 +433,11 @@ "cell_type": "code", "execution_count": 10, "id": "ff372bef-3d3d-4dd4-a920-4eae36c53faa", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [ { "name": "stdout", @@ -435,7 +471,11 @@ "cell_type": "code", "execution_count": 11, "id": "c4de9c94-7ffe-427c-8551-a1ac677487d9", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// First we define a structure to the relaxation.\n", @@ -491,7 +531,11 @@ "cell_type": "code", "execution_count": 12, "id": "16ba3e9c-a141-463d-8126-a880c48814f8", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [ { "name": "stdout", @@ -527,7 +571,11 @@ "cell_type": "code", "execution_count": 13, "id": "33860567-b2c0-47d5-9d8f-bf247361261d", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "pub struct KPDominance;\n", @@ -565,7 +613,11 @@ "cell_type": "code", "execution_count": 14, "id": "9e1d45c4-091a-46a4-9411-d852ea6cb408", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [ "/// This is your executable's entry point. It is the place where all the pieces are put together\n", @@ -597,7 +649,7 @@ " let dominance = SimpleDominanceChecker::new(KPDominance);\n", "\n", " // Create your solver object\n", - " let mut solver = DefaultBarrierSolver::new(\n", + " let mut solver = DefaultCachingSolver::new(\n", " &problem, \n", " &relaxation, \n", " &heuristic, \n", @@ -635,7 +687,11 @@ "cell_type": "code", "execution_count": 15, "id": "be793e6b-f60f-4584-80f9-af6b84c8dfe7", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [ { "name": "stdout", @@ -687,7 +743,11 @@ "cell_type": "code", "execution_count": null, "id": "53c16a22-408f-435e-9807-c601f0cc2caa", - "metadata": {}, + "metadata": { + "vscode": { + "languageId": "rust" + } + }, "outputs": [], "source": [] }