use std::marker::PhantomData; use std::sync::Arc; use std::rc::Rc; use std::cell::{RefMut, RefCell}; use std::sync::{MutexGuard, Mutex}; type B = CopyingBacktracker; type C = DFSController<::Node>; pub struct CPLabelChoice { pub x: i64, pub val: i64, } pub trait CPPropagator { fn post(&mut self, solver: Arc) -> Result<(),()>; } impl CPHeuristicFactory for FirstFailFactory { type H = FirstFailSearch; } pub struct Model { } unsafe impl Sync for Model {} pub struct CopyingBacktracker { } impl Backtracker for CopyingBacktracker { type Node = CPCopyingSearchNode; } pub struct CPCopyingSearchNode { } pub struct TrailingBacktracker { } #[derive(Clone)] pub struct FirstFailFactory {} pub trait Solver { fn solve(self); } impl Solver for CPSequentialSolver where H: CPHeuristicFactory> + 'static { fn solve(mut self) { } } pub trait CPScheduledPropagation where K: CPSolverKernel { fn propagate(&mut self, &mut K) -> Result<(),()>; fn is_scheduled(&self, solver: &K) -> bool; fn notify_scheduled(&mut self, solver: &K); } /// A trait defining a backtrackable value pub trait Backtrackable { type B: Backtracker; type V: Copy; fn new(val: Self::V, backtracker: &mut Self::B) -> Self; fn set(&mut self, val: Self::V, backtracker: &mut Self::B); fn get(&self) -> Self::V; } pub struct CPKernelEvents { presolve_begin: Vec>, search_begin: Vec>, search_end: Vec>, fixedpoint: Vec>, fail: Vec>, } pub trait CPSearchExplorer { fn domain_size(&self, x: i64) -> usize; fn is_domain_bound(&self, x: i64) -> bool; fn domain_min(&self, x: i64) -> i64; fn domain_max(&self, x: i64) -> i64; } pub trait CPLabelingHeuristic { fn next_for(&mut self, x: i64, solver: &mut S) -> Option; fn next(&mut self, solver: &mut S) -> Option; } pub trait CPHeuristicFactory: Clone + Send + Sync { type H: CPLabelingHeuristic; } pub struct CustomSearch { p: PhantomData } pub trait HeuristicBuilder { type H: CPLabelingHeuristic; fn finalize(self) -> Self::H; } pub struct FirstFailSearch {} pub struct CustomSearchFactory where E: CPSearchExplorer, F: 'static + Fn(&mut HeuristicBuilder>) { build_func: Arc, _phantom: PhantomData, } impl CPHeuristicFactory for CustomSearchFactory where E: CPSearchExplorer + CPSolverKernel, F: 'static + Fn(&mut HeuristicBuilder>) { type H = CustomSearch; } pub struct CPWorker where B: Backtracker + 'static, C: SearchController { pub props: PhantomData, pub backtracker: B, pub events: Mutex, } pub trait Backtracker where Self: Sized { type Node: CPSearchNode; } pub trait CPSolverKernel { type B: Backtracker; type C: SearchController<::Node>; fn backtracker(&self) -> &Self::B; fn backtracker_mut(&mut self) -> &mut Self::B; fn min(&self, y: i64) -> i64; fn max(&self, y: i64) -> i64; fn contains(&self, y: i64, val: i64) -> bool; fn count(&self, y: i64) -> i64; fn is_bound(&self, y: i64) -> bool; fn bind(&mut self, y: i64, val: i64) -> Result<(),()>; fn remove(&mut self, y: i64, val: i64) -> Result<(),()>; fn remove_lt(&mut self, y: i64, val: i64)->Result<(),()>; fn remove_gt(&mut self, y: i64, val: i64)->Result<(),()>; fn enforce_choice(&mut self, choice: CPLabelChoice) -> Result<(), ()>; fn enforce_objective_bounds(&mut self) -> Result<(), ()>; fn capture_objective_bounds(&self) -> (Option, Option); fn schedule(&mut self, propagation: Rc>>); fn new_scheduled_propagation(&mut self, f: F) where F: 'static + FnMut(&mut Self) -> Result<(),()>; fn print_domain(&self, y: i64); } impl CPSolverKernel for CPWorker where B: Backtracker, C: SearchController + 'static { type B = B; type C = C; #[inline] fn backtracker(&self) -> &B { &self.backtracker } #[inline] fn backtracker_mut(&mut self) -> &mut B { &mut self.backtracker } #[inline] fn min(&self, y: i64) -> i64 { 0 } #[inline] fn max(&self, y: i64) -> i64 { 0 } #[inline] fn contains(&self, y: i64, val: i64) -> bool { true } #[inline] fn count(&self, y: i64) -> i64 { 0 } #[inline] fn is_bound(&self, y: i64) -> bool { true } #[inline] fn bind(&mut self, y: i64, val: i64) -> Result<(),()> { Ok(()) } #[inline] fn remove(&mut self, y: i64, val: i64) -> Result<(),()> { Ok(()) } #[inline] fn remove_lt(&mut self, y: i64, val: i64) -> Result<(),()> { Ok(()) } #[inline] fn remove_gt(&mut self, y: i64, val: i64) -> Result<(),()> { Ok(()) } #[inline] fn enforce_choice(&mut self, choice: CPLabelChoice) -> Result<(), ()> { Ok(()) } #[inline] fn enforce_objective_bounds(&mut self) -> Result<(), ()> { Ok(()) } #[inline] fn capture_objective_bounds(&self) -> (Option, Option) { (None, None) } #[inline] fn schedule(&mut self, propagation: Rc>>) { } fn new_scheduled_propagation(&mut self, f: F) where F: 'static + FnMut(&mut Self) -> Result<(),()> { } fn print_domain(&self, y: i64) { } } impl Clone for CustomSearchFactory where E: CPSearchExplorer + CPSolverKernel, F: 'static + Fn(&mut HeuristicBuilder>) { fn clone(&self) -> CustomSearchFactory { CustomSearchFactory { build_func: self.build_func.clone(), _phantom: PhantomData, } } } pub trait CPSearchNode where Self: Sized { fn label_choice(&self) -> Option; fn objective_bounds(&self) -> (Option, Option); fn restore(self, solver: &mut K) -> Result<(), ()> where K: CPSolverKernel, K::B: Backtracker, K::C: SearchController; } impl CPLabelingHeuristic for CustomSearch where S: CPSearchExplorer + CPSolverKernel { fn next_for(&mut self, x: i64, solver: &mut S) -> Option { None } fn next(&mut self, solver: &mut S) -> Option { None } } impl CPSearchNode for CPCopyingSearchNode { #[inline] fn label_choice(&self) -> Option { None } #[inline] fn objective_bounds(&self) -> (Option, Option) { (None, None) } #[inline] fn restore(self, solver: &mut K) -> Result<(), ()> where K: CPSolverKernel, K::B: Backtracker, K::C: SearchController { Ok(()) } } pub trait SearchController { fn set_root(&mut self, n: N); fn push_node(&mut self, n: N); fn pop_node(&mut self) -> Option; fn node_count(&self) -> usize; fn objective_bounds(&self) -> (Option, Option); fn update_primal_bound(&mut self, bnd: i64); } pub trait CPSolver : Solver where H: CPHeuristicFactory { type E: CPSearchExplorer; fn new(model: Arc) -> Self where Self: CPSolver; fn with_heuristic(model: Arc, heuristic: H) -> Self; } pub struct CPSequentialSolver where H: CPHeuristicFactory> { controller: PhantomData, heuristic: H, } impl CPSolver for CPSequentialSolver where H: CPHeuristicFactory> + 'static { type E = CPWorker; fn new(model: Arc) -> Self where Self: CPSolver { let heur = FirstFailFactory::new(); CPSequentialSolver::with_heuristic(model, heur) } fn with_heuristic(model: Arc, heuristic: H) -> CPSequentialSolver { let solver: CPSequentialSolver = CPSequentialSolver { controller: PhantomData, heuristic: heuristic, }; solver } } impl FirstFailFactory { pub fn new() -> FirstFailFactory { FirstFailFactory {} } } impl CPLabelingHeuristic for FirstFailSearch where S: CPSearchExplorer { fn next_for(&mut self, x: i64, solver: &mut S) -> Option { None } fn next(&mut self, solver: &mut S) -> Option { None } } pub struct DFSController { stack: Vec, objective_bounds: (Option, Option), } impl DFSController { pub fn new() -> DFSController { DFSController { stack: vec![], objective_bounds: (None, None), } } } impl SearchController for DFSController { fn set_root(&mut self, n: N) { self.stack.push(n); } #[inline] fn push_node(&mut self, n: N) { self.stack.push(n); } #[inline] fn pop_node(&mut self) -> Option { self.stack.pop() } #[inline] fn node_count(&self) -> usize { self.stack.len() } #[inline] fn objective_bounds(&self) -> (Option, Option) { self.objective_bounds } #[inline] fn update_primal_bound(&mut self, bnd: i64) { self.objective_bounds.1 = Some(bnd) } } pub trait CPSolverWithSearch : CPSolver> where E: CPSearchExplorer, F: 'static + Fn(&mut HeuristicBuilder>), CustomSearchFactory: CPHeuristicFactory< >>::E> { fn with_search(model: Arc, search: F) -> Self; } impl CPSolverWithSearch, F> for CPSequentialSolver, F>> where F: Fn(&mut HeuristicBuilder, H=CustomSearch>>) { fn with_search(model: Arc, search: F) -> Self { let heur = CustomSearchFactory::new(search); , F>>> ::with_heuristic(model, heur) } } impl CustomSearchFactory where E: CPSearchExplorer, F: 'static + Fn(&mut HeuristicBuilder>) { pub fn new(f: F) -> CustomSearchFactory { CustomSearchFactory { build_func: Arc::new(f), _phantom: PhantomData, } } } // Implement Send unsafe impl Send for CustomSearchFactory where E: CPSearchExplorer + CPSolverKernel, F: 'static + Fn(&mut HeuristicBuilder>) {} // Implement Sync unsafe impl Sync for CustomSearchFactory where E: CPSearchExplorer + CPSolverKernel, F: 'static + Fn(&mut HeuristicBuilder>) {} unsafe impl Send for FirstFailFactory {} unsafe impl Sync for FirstFailFactory {} impl CPSearchExplorer for CPWorker where B: Backtracker, C: SearchController + 'static { #[inline] fn domain_size(&self, x: i64) -> usize { self.count(x as i64) as usize } #[inline] fn is_domain_bound(&self, x: i64) -> bool { self.is_bound(x as i64) } #[inline] fn domain_min(&self, x: i64) -> i64 { self.min(x as i64) } #[inline] fn domain_max(&self, x: i64) -> i64 { self.max(x as i64) } } // This code is editable and runnable! fn main() { // A simple integer calculator: // `+` or `-` means add or subtract by 1 // `*` or `/` means multiply or divide by 2 let program = "+ + + +"; let mut accumulator = 0; for token in program.chars() { match token { '+' => accumulator += 1, '-' => accumulator -= 1, '*' => accumulator *= 2, '/' => accumulator /= 2, _ => { /* ignore everything else */ } } } println!("The program \"{}\" calculates the value {}", program, accumulator); }