diff --git a/src/constraint/equality.rs b/src/constraint/equality.rs index 8e66676..99f079d 100644 --- a/src/constraint/equality.rs +++ b/src/constraint/equality.rs @@ -4,7 +4,7 @@ use num_rational::Ratio; use num_traits::Zero; use std::rc::Rc; -use crate::{Constraint, Error, LinExpr, PsResult, PuzzleSearch, Val, VarToken}; +use crate::{Constraint, Error, linexpr::LinExpr, PsResult, PuzzleSearch, Val, VarToken}; #[derive(Debug)] pub struct Equality { diff --git a/src/lib.rs b/src/lib.rs index ff41472..c1eaae2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,16 +8,14 @@ mod linexpr; mod puzzle; mod ranges; -use core::fmt; use num_rational::Rational32; -use num_traits::Signed; -use std::collections::HashMap; use std::ops; pub use constraint::Constraint; pub use error::Error; pub use puzzle::Puzzle; pub use puzzle::PuzzleSearch; +pub use linexpr::LinExpr; /// A puzzle variable token. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)] @@ -29,48 +27,6 @@ pub type Val = i32; /// The type of the coefficients in a linear expression. pub type Coef = Rational32; -/// A linear expression. -/// -/// ```text -/// constant + coef1 * var1 + coef2 * var2 + ... -/// ``` -#[derive(Clone)] -pub struct LinExpr { - constant: Coef, - - // The non-zero coefficients in the linear expression. If, after - // some manipulations, the coefficient is 0, then it must be - // removed from the map. - coef: HashMap, -} - -impl fmt::Display for LinExpr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.constant)?; - - for (tok, coef) in self.coef.iter() { - if coef.is_negative() { - if coef.abs() == Rational32::from_integer(1) { - write!(f, " - x{}", tok.0)?; - } else { - write!(f, " - {} * x{}", coef.abs(), tok.0)?; - } - } else if coef.abs() == Rational32::from_integer(1) { - write!(f, " + x{}", tok.0)?; - } else { - write!(f, " + {} * x{}", coef, tok.0)?; - } - } - - Ok(()) - } -} - -impl fmt::Debug for LinExpr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "LinExpr {{ {} }}", self) - } -} /// A result during a puzzle solution search (Err = contradiction). pub type PsResult = Result; diff --git a/src/linexpr.rs b/src/linexpr.rs index 09c23c0..35a55b3 100644 --- a/src/linexpr.rs +++ b/src/linexpr.rs @@ -1,13 +1,57 @@ //! Linear expressions. use num_rational::{Ratio, Rational32}; -use num_traits::{One, Zero}; +use num_traits::{One, Signed, Zero}; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::convert::From; +use std::fmt; use std::ops::{Add, Mul, Neg, Sub}; -use crate::{Coef, LinExpr, VarToken}; +use crate::{Coef, VarToken}; + +/// A linear expression. +/// +/// ```text +/// constant + coef1 * var1 + coef2 * var2 + ... +/// ``` +#[derive(Clone)] +pub struct LinExpr { + pub(crate) constant: Coef, + + // The non-zero coefficients in the linear expression. If, after + // some manipulations, the coefficient is 0, then it must be + // removed from the map. + pub(crate) coef: HashMap, +} + +impl fmt::Display for LinExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.constant)?; + + for (tok, coef) in self.coef.iter() { + if coef.is_negative() { + if coef.abs() == Rational32::from_integer(1) { + write!(f, " - x{}", tok.0)?; + } else { + write!(f, " - {} * x{}", coef.abs(), tok.0)?; + } + } else if coef.abs() == Rational32::from_integer(1) { + write!(f, " + x{}", tok.0)?; + } else { + write!(f, " + {} * x{}", coef, tok.0)?; + } + } + + Ok(()) + } +} + +impl fmt::Debug for LinExpr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "LinExpr {{ {} }}", self) + } +} macro_rules! impl_commutative_op { ($LHS:ident + $RHS:ident) => { diff --git a/src/puzzle.rs b/src/puzzle.rs index 75143b9..3e7fc40 100644 --- a/src/puzzle.rs +++ b/src/puzzle.rs @@ -12,8 +12,8 @@ use std::rc::Rc; use crate::constraint; use crate::Error; -use crate::{Constraint, LinExpr, PsResult, Solution, Val, VarToken}; - +use crate::{Constraint, PsResult, Solution, Val, VarToken}; +use crate::linexpr::LinExpr; use crate::ranges::Ranges; /// A collection of candidates. diff --git a/tests/nonogram.rs b/tests/nonogram.rs index f8ee245..273465f 100644 --- a/tests/nonogram.rs +++ b/tests/nonogram.rs @@ -183,6 +183,10 @@ impl Constraint for Nonogram { fn substitute(&self, _search: VarToken, _replace: VarToken) -> PsResult> { unimplemented!(); } + + fn propagate(&self, _search: &mut PuzzleSearch, _var: VarToken, _val: Val) -> PsResult<()> { + Ok(()) + } } /*--------------------------------------------------------------*/