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.
This commit is contained in:
David Wang 2017-03-09 07:42:09 +11:00
parent bae1138501
commit 5bb52b03f2
4 changed files with 45 additions and 3 deletions

View File

@ -1,6 +1,7 @@
//! All different implementation. //! All different implementation.
use std::collections::HashMap; use std::collections::HashMap;
use std::rc::Rc;
use ::{Constraint,PuzzleSearch,Val,VarToken}; use ::{Constraint,PuzzleSearch,Val,VarToken};
@ -75,6 +76,19 @@ impl Constraint for AllDifferent {
true true
} }
fn substitute(&self, from: VarToken, to: VarToken)
-> Option<Rc<Constraint>> {
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)] #[cfg(test)]

View File

@ -1,5 +1,7 @@
//! Equality implementation. //! Equality implementation.
use std::rc::Rc;
use ::{Constraint,LinExpr,PuzzleSearch,Val,VarToken}; use ::{Constraint,LinExpr,PuzzleSearch,Val,VarToken};
use intdiv::IntDiv; use intdiv::IntDiv;
@ -140,6 +142,16 @@ impl Constraint for Equality {
true true
} }
fn substitute(&self, from: VarToken, to: VarToken)
-> Option<Rc<Constraint>> {
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)] #[cfg(test)]

View File

@ -1,9 +1,11 @@
//! Constraint trait, and some common constraints. //! Constraint trait, and some common constraints.
//! //!
//! Note that all puzzle states visited during the solution search //! Note that all puzzle states visited during the solution search
//! share the same set of constraints. This means that you cannot //! share the same set of constraint objects. This means that you
//! store additional information about the state (e.g. caches) in the //! cannot store additional information about the state (e.g. caches)
//! constraint to reuse later. //! in the constraint to reuse later.
use std::rc::Rc;
use ::{PuzzleSearch,Val,VarToken}; use ::{PuzzleSearch,Val,VarToken};
@ -28,6 +30,14 @@ pub trait Constraint {
fn on_updated(&self, _search: &mut PuzzleSearch) -> bool { fn on_updated(&self, _search: &mut PuzzleSearch) -> bool {
true 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<Rc<Constraint>>;
} }
pub use self::alldifferent::AllDifferent; pub use self::alldifferent::AllDifferent;

View File

@ -4,6 +4,7 @@
extern crate puzzle_solver; extern crate puzzle_solver;
use std::rc::Rc;
use puzzle_solver::{Constraint,Puzzle,PuzzleSearch,Solution,Val,VarToken}; use puzzle_solver::{Constraint,Puzzle,PuzzleSearch,Solution,Val,VarToken};
struct NoDiagonal { struct NoDiagonal {
@ -29,6 +30,11 @@ impl Constraint for NoDiagonal {
true true
} }
fn substitute(&self, _from: VarToken, _to: VarToken)
-> Option<Rc<Constraint>> {
unimplemented!();
}
} }
fn make_queens(n: usize) -> (Puzzle, Vec<VarToken>) { fn make_queens(n: usize) -> (Puzzle, Vec<VarToken>) {