Removed Candidates::None variant
This commit is contained in:
parent
d8323a144f
commit
dc20c9aa76
@ -279,8 +279,8 @@ mod tests {
|
|||||||
#[allow(clippy::identity_op, clippy::eq_op)]
|
#[allow(clippy::identity_op, clippy::eq_op)]
|
||||||
fn test_ops() {
|
fn test_ops() {
|
||||||
let mut puzzle = Puzzle::new();
|
let mut puzzle = Puzzle::new();
|
||||||
let x = puzzle.new_var();
|
let x = puzzle.new_var_with_range(10..=10);
|
||||||
let y = puzzle.new_var();
|
let y = puzzle.new_var_with_range(10..=10);
|
||||||
|
|
||||||
// expr = var + const;
|
// expr = var + const;
|
||||||
let _ = x + 1;
|
let _ = x + 1;
|
||||||
@ -337,8 +337,8 @@ mod tests {
|
|||||||
#[allow(clippy::erasing_op, clippy::eq_op)]
|
#[allow(clippy::erasing_op, clippy::eq_op)]
|
||||||
fn test_coef_zero() {
|
fn test_coef_zero() {
|
||||||
let mut puzzle = Puzzle::new();
|
let mut puzzle = Puzzle::new();
|
||||||
let x = puzzle.new_var();
|
let x = puzzle.new_var_with_range(10..10);
|
||||||
let y = puzzle.new_var();
|
let y = puzzle.new_var_with_range(10..10);
|
||||||
|
|
||||||
let expr = x * 0;
|
let expr = x * 0;
|
||||||
assert_eq!(expr.coef.len(), 0);
|
assert_eq!(expr.coef.len(), 0);
|
||||||
|
@ -11,15 +11,14 @@ use std::ops::RangeBounds;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::constraint;
|
use crate::constraint;
|
||||||
use crate::Error;
|
|
||||||
use crate::{Constraint, PsResult, Solution, Val, VarToken};
|
|
||||||
use crate::linexpr::LinExpr;
|
use crate::linexpr::LinExpr;
|
||||||
use crate::ranges::Ranges;
|
use crate::ranges::Ranges;
|
||||||
|
use crate::Error;
|
||||||
|
use crate::{Constraint, PsResult, Solution, Val, VarToken};
|
||||||
|
|
||||||
/// A collection of candidates.
|
/// A collection of candidates.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
enum Candidates {
|
enum Candidates {
|
||||||
None, // A variable with no candidates.
|
|
||||||
Value(Val), // A variable set to its initial value.
|
Value(Val), // A variable set to its initial value.
|
||||||
Set(Rc<BTreeSet<Val>>), // A variable with a list of candidates.
|
Set(Rc<BTreeSet<Val>>), // A variable with a list of candidates.
|
||||||
Range(Ranges), // A variable with candidate ranges.
|
Range(Ranges), // A variable with candidate ranges.
|
||||||
@ -76,7 +75,6 @@ impl Candidates {
|
|||||||
/// Count the number of candidates for a variable.
|
/// Count the number of candidates for a variable.
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Candidates::None => 0,
|
|
||||||
Candidates::Value(_) => 1,
|
Candidates::Value(_) => 1,
|
||||||
Candidates::Set(ref rc) => rc.len(),
|
Candidates::Set(ref rc) => rc.len(),
|
||||||
Candidates::Range(rc) => rc.len(),
|
Candidates::Range(rc) => rc.len(),
|
||||||
@ -86,7 +84,6 @@ impl Candidates {
|
|||||||
/// Get an iterator over all of the candidates of a variable.
|
/// Get an iterator over all of the candidates of a variable.
|
||||||
fn iter(&self) -> Box<dyn Iterator<Item = Val> + '_> {
|
fn iter(&self) -> Box<dyn Iterator<Item = Val> + '_> {
|
||||||
match self {
|
match self {
|
||||||
Candidates::None => Box::new(iter::empty()),
|
|
||||||
Candidates::Value(val) => Box::new(iter::once(*val)),
|
Candidates::Value(val) => Box::new(iter::once(*val)),
|
||||||
Candidates::Set(ref rc) => Box::new(rc.iter().cloned()),
|
Candidates::Set(ref rc) => Box::new(rc.iter().cloned()),
|
||||||
Candidates::Range(range) => Box::new(range.iter()),
|
Candidates::Range(range) => Box::new(range.iter()),
|
||||||
@ -113,19 +110,10 @@ impl Puzzle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a new puzzle variable, without inserting any
|
fn new_var(&mut self, candidates: Candidates) -> VarToken {
|
||||||
/// candidates.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// let mut puzzle = puzzle_solver::Puzzle::new();
|
|
||||||
/// puzzle.new_var();
|
|
||||||
/// ```
|
|
||||||
pub fn new_var(&mut self) -> VarToken {
|
|
||||||
let var = VarToken(self.num_vars);
|
let var = VarToken(self.num_vars);
|
||||||
self.num_vars += 1;
|
self.num_vars += 1;
|
||||||
self.candidates.push(Candidates::None);
|
self.candidates.push(candidates);
|
||||||
var
|
var
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,9 +127,9 @@ impl Puzzle {
|
|||||||
/// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]);
|
/// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new_var_with_candidates(&mut self, candidates: &[Val]) -> VarToken {
|
pub fn new_var_with_candidates(&mut self, candidates: &[Val]) -> VarToken {
|
||||||
let var = self.new_var();
|
self.new_var(Candidates::Set(Rc::new(BTreeSet::from_iter(
|
||||||
self.insert_candidates(var, candidates);
|
candidates.iter().copied(),
|
||||||
var
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a new puzzle variable, initialising it with potential
|
/// Allocate a new puzzle variable, initialising it with potential
|
||||||
@ -154,9 +142,10 @@ impl Puzzle {
|
|||||||
/// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]);
|
/// send_more_money.new_var_with_candidates(&[0,1,2,3,4,5,6,7,8,9]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new_var_with_range<R: RangeBounds<Val>>(&mut self, range: R) -> VarToken {
|
pub fn new_var_with_range<R: RangeBounds<Val>>(&mut self, range: R) -> VarToken {
|
||||||
let var = self.new_var();
|
self.new_var(Candidates::Range(Ranges::new(
|
||||||
self.insert_range(var, range);
|
range.start_bound().cloned(),
|
||||||
var
|
range.end_bound().cloned(),
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a 1d vector of puzzle variables, each initialised to
|
/// Allocate a 1d vector of puzzle variables, each initialised to
|
||||||
@ -285,11 +274,6 @@ impl Puzzle {
|
|||||||
match self.candidates[idx] {
|
match self.candidates[idx] {
|
||||||
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
||||||
Candidates::Range(_) => panic!("attempt to insert candidates into range"),
|
Candidates::Range(_) => panic!("attempt to insert candidates into range"),
|
||||||
|
|
||||||
Candidates::None => {
|
|
||||||
self.candidates[idx] = Candidates::Set(Rc::new(BTreeSet::new()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Candidates::Set(_) => (),
|
Candidates::Set(_) => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +301,6 @@ impl Puzzle {
|
|||||||
let VarToken(idx) = var;
|
let VarToken(idx) = var;
|
||||||
|
|
||||||
match self.candidates[idx] {
|
match self.candidates[idx] {
|
||||||
Candidates::None => (),
|
|
||||||
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
||||||
Candidates::Range(_) => panic!("attempt to remove candidates from range"),
|
Candidates::Range(_) => panic!("attempt to remove candidates from range"),
|
||||||
Candidates::Set(ref mut rc) => {
|
Candidates::Set(ref mut rc) => {
|
||||||
@ -346,7 +329,6 @@ impl Puzzle {
|
|||||||
let VarToken(idx) = var;
|
let VarToken(idx) = var;
|
||||||
|
|
||||||
match self.candidates[idx] {
|
match self.candidates[idx] {
|
||||||
Candidates::None => (),
|
|
||||||
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
||||||
Candidates::Range(_) => panic!("attempt to intersect candidates on the range"),
|
Candidates::Range(_) => panic!("attempt to intersect candidates on the range"),
|
||||||
Candidates::Set(ref mut rc) => {
|
Candidates::Set(ref mut rc) => {
|
||||||
@ -366,12 +348,6 @@ impl Puzzle {
|
|||||||
let VarToken(idx) = var;
|
let VarToken(idx) = var;
|
||||||
|
|
||||||
match self.candidates[idx] {
|
match self.candidates[idx] {
|
||||||
ref mut x @ Candidates::None => {
|
|
||||||
*x = Candidates::Range(Ranges::new(
|
|
||||||
range.start_bound().cloned(),
|
|
||||||
range.end_bound().cloned(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
Candidates::Value(_) => panic!("attempt to set fixed variable"),
|
||||||
Candidates::Range(ref mut r) => {
|
Candidates::Range(ref mut r) => {
|
||||||
r.insert(range.start_bound().cloned(), range.end_bound().cloned());
|
r.insert(range.start_bound().cloned(), range.end_bound().cloned());
|
||||||
@ -653,7 +629,6 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
match &self.vars[idx] {
|
match &self.vars[idx] {
|
||||||
VarState::Assigned(val) => Ok((*val, *val)),
|
VarState::Assigned(val) => Ok((*val, *val)),
|
||||||
VarState::Unassigned(ref cs) => match cs {
|
VarState::Unassigned(ref cs) => match cs {
|
||||||
Candidates::None => Err(Error::Default),
|
|
||||||
Candidates::Value(val) => Ok((*val, *val)),
|
Candidates::Value(val) => Ok((*val, *val)),
|
||||||
Candidates::Range(r) => r.get_bounds().ok_or(Error::Default),
|
Candidates::Range(r) => r.get_bounds().ok_or(Error::Default),
|
||||||
Candidates::Set(ref rc) => rc
|
Candidates::Set(ref rc) => rc
|
||||||
@ -676,7 +651,6 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
match self.vars[idx] {
|
match self.vars[idx] {
|
||||||
VarState::Assigned(v) => bool_to_result(v == val),
|
VarState::Assigned(v) => bool_to_result(v == val),
|
||||||
VarState::Unassigned(ref mut cs) => match cs {
|
VarState::Unassigned(ref mut cs) => match cs {
|
||||||
Candidates::None => Err(Error::Default),
|
|
||||||
Candidates::Value(v) => bool_to_result(*v == val),
|
Candidates::Value(v) => bool_to_result(*v == val),
|
||||||
Candidates::Range(ref mut r) => {
|
Candidates::Range(ref mut r) => {
|
||||||
if r.contains(val) {
|
if r.contains(val) {
|
||||||
@ -711,7 +685,6 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
match self.vars[idx] {
|
match self.vars[idx] {
|
||||||
VarState::Assigned(v) => bool_to_result(v != val),
|
VarState::Assigned(v) => bool_to_result(v != val),
|
||||||
VarState::Unassigned(ref mut cs) => match cs {
|
VarState::Unassigned(ref mut cs) => match cs {
|
||||||
Candidates::None => Err(Error::Default),
|
|
||||||
Candidates::Value(v) => bool_to_result(*v != val),
|
Candidates::Value(v) => bool_to_result(*v != val),
|
||||||
Candidates::Range(r) => {
|
Candidates::Range(r) => {
|
||||||
if r.contains(val) {
|
if r.contains(val) {
|
||||||
@ -753,7 +726,6 @@ impl<'a> PuzzleSearch<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VarState::Unassigned(ref mut cs) => match cs {
|
VarState::Unassigned(ref mut cs) => match cs {
|
||||||
Candidates::None => Err(Error::Default),
|
|
||||||
Candidates::Value(v) => {
|
Candidates::Value(v) => {
|
||||||
if min <= *v && *v <= max {
|
if min <= *v && *v <= max {
|
||||||
Ok((*v, *v))
|
Ok((*v, *v))
|
||||||
|
Loading…
Reference in New Issue
Block a user