From 5bb52b03f2ffc2c9551c04848e2db5b9659ede1f Mon Sep 17 00:00:00 2001 From: David Wang Date: Thu, 9 Mar 2017 07:42:09 +1100 Subject: [PATCH] Add simple variable substitution for constraints. Constraints must now implement the substitution of "from" with "to". The implementations can be sanity checked when we come to build the list of constraints that each variable wakes up. In the future, we would like to make the more general substitution: from -> scale * to + constant. --- src/constraint/alldifferent.rs | 14 ++++++++++++++ src/constraint/equality.rs | 12 ++++++++++++ src/constraint/mod.rs | 16 +++++++++++++--- tests/queens.rs | 6 ++++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/constraint/alldifferent.rs b/src/constraint/alldifferent.rs index 98f9627..d9a6871 100644 --- a/src/constraint/alldifferent.rs +++ b/src/constraint/alldifferent.rs @@ -1,6 +1,7 @@ //! All different implementation. use std::collections::HashMap; +use std::rc::Rc; use ::{Constraint,PuzzleSearch,Val,VarToken}; @@ -75,6 +76,19 @@ impl Constraint for AllDifferent { true } + + fn substitute(&self, from: VarToken, to: VarToken) + -> Option> { + if let Some(idx) = self.vars.iter().position(|&var| var == from) { + if !self.vars.contains(&to) { + let mut new_vars = self.vars.clone(); + new_vars[idx] = to; + return Some(Rc::new(AllDifferent{ vars: new_vars })); + } + } + + None + } } #[cfg(test)] diff --git a/src/constraint/equality.rs b/src/constraint/equality.rs index 24d4f4d..b35aaba 100644 --- a/src/constraint/equality.rs +++ b/src/constraint/equality.rs @@ -1,5 +1,7 @@ //! Equality implementation. +use std::rc::Rc; + use ::{Constraint,LinExpr,PuzzleSearch,Val,VarToken}; use intdiv::IntDiv; @@ -140,6 +142,16 @@ impl Constraint for Equality { true } + + fn substitute(&self, from: VarToken, to: VarToken) + -> Option> { + let mut eqn = self.eqn.clone(); + if let Some(coef) = eqn.coef.remove(&from) { + eqn = eqn + coef * to; + } + + Some(Rc::new(Equality{ eqn: eqn })) + } } #[cfg(test)] diff --git a/src/constraint/mod.rs b/src/constraint/mod.rs index a7ae8f8..3ae214f 100644 --- a/src/constraint/mod.rs +++ b/src/constraint/mod.rs @@ -1,9 +1,11 @@ //! Constraint trait, and some common constraints. //! //! Note that all puzzle states visited during the solution search -//! share the same set of constraints. This means that you cannot -//! store additional information about the state (e.g. caches) in the -//! constraint to reuse later. +//! share the same set of constraint objects. This means that you +//! cannot store additional information about the state (e.g. caches) +//! in the constraint to reuse later. + +use std::rc::Rc; use ::{PuzzleSearch,Val,VarToken}; @@ -28,6 +30,14 @@ pub trait Constraint { fn on_updated(&self, _search: &mut PuzzleSearch) -> bool { true } + + /// Substitute the "from" variable with the "to" variable. + /// + /// Returns a new constraint with all instances of "from" replaced + /// with "to", or None if a contradiction was found in the + /// process. + fn substitute(&self, from: VarToken, to: VarToken) + -> Option>; } pub use self::alldifferent::AllDifferent; diff --git a/tests/queens.rs b/tests/queens.rs index 788fda5..1fc60a0 100644 --- a/tests/queens.rs +++ b/tests/queens.rs @@ -4,6 +4,7 @@ extern crate puzzle_solver; +use std::rc::Rc; use puzzle_solver::{Constraint,Puzzle,PuzzleSearch,Solution,Val,VarToken}; struct NoDiagonal { @@ -29,6 +30,11 @@ impl Constraint for NoDiagonal { true } + + fn substitute(&self, _from: VarToken, _to: VarToken) + -> Option> { + unimplemented!(); + } } fn make_queens(n: usize) -> (Puzzle, Vec) {