pub trait Constraint {
type Var;
type Solution: Assignment;
type ConflictErr: Debug;
// Required methods
fn size(&self) -> usize;
fn variables(&self) -> impl Iterator<Item = Self::Var>;
fn decompositions(&self) -> impl Iterator<Item = Self>;
fn reduce(&mut self, other: &Self) -> Result<bool, Self::ConflictErr>;
fn pop_solution(&mut self) -> Option<Self::Solution>;
}
Expand description
A constraint that affects given variables in a system
A given constriant can be satisfied by multiple possible assignments.
§Invariants
- if
self.variables().count() == 0
, thenself.size() == 1
i.e. if a constraint affects no variables, it should have 1 solution, the empty solution - if
this.variables().count() > 0
, thenthis.decompositions().count() >= 1
i.e. if a constraint affects any variables, it should have at least 1 decomposition
§Formal definition
Formally, a constraint is a set of possible assignments for the variables within a problem.
For example, in a minesweeper game:
- the variables would be
[x, y]
positions for a tile - the values to assign would be
true
/false
for whether a mine is in a tile
And a possible constraint could be:
{
{ [2, 3]: true, [3, 3]: false },
// position [2, 3] is a mine
// position [3, 3] is safe
// or
{ [2, 3]: false, [3, 3]: true },
// position [2, 3] is safe
// position [3, 3] is a mine
}
Required Associated Types§
Sourcetype Solution: Assignment
type Solution: Assignment
Any solution to a Constraint
Sourcetype ConflictErr: Debug
type ConflictErr: Debug
The error raised when 2 constraints conflict with each other
Required Methods§
Sourcefn size(&self) -> usize
fn size(&self) -> usize
An approximation to the number of unique assignments that self
has.
This doesn’t have to be exact, but should at least:
return 1
when there’s only one unique solutionreturn 0
when no solutions are possible
Sourcefn decompositions(&self) -> impl Iterator<Item = Self>
fn decompositions(&self) -> impl Iterator<Item = Self>
Possible decompositions for this constraint.
A decomposition is a constraint that:
- affects a subset of
self.variables()
- has a single unique solution that
self
allows
§Returns
An iterator over the possible decompositions of self
Sourcefn reduce(&mut self, other: &Self) -> Result<bool, Self::ConflictErr>
fn reduce(&mut self, other: &Self) -> Result<bool, Self::ConflictErr>
Removes the overlap between another constraint and this one.
This is useful as it lets us remove uncertainty from the system
and make it simpler to solve.
§Arguments
other
: the other constraint to attempt reduction with
§Returns
Whether other
successfully reduced self
,
or a conflict error if other
conflicts with this constraint.
Constraints conflict if there’s no assignment that satisfies both.
Sourcefn pop_solution(&mut self) -> Option<Self::Solution>
fn pop_solution(&mut self) -> Option<Self::Solution>
Pops all variables that have a unique assignment in this constraint
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.