Skip to main content

Problem

Struct Problem 

Source
pub struct Problem<P: PieceKind, C: ColorKind = SquareColor> {
    pub num_squares: usize,
    pub square_colors: Vec<C>,
    pub pieces: Vec<P>,
    pub constraint: Constraint<P, C>,
}
Expand description

A constraint-satisfaction problem: a fixed board (size + per-square colour from a user-defined colour set), an alphabet of available piece kinds, and a constraint to satisfy.

pieces is the alphabet — the set of distinct kinds available. Duplicate entries are silently deduplicated; first-appearance order is preserved.

C is the colour kind. The default is SquareColor — the binary light/dark partition used by chess. For N-way partitions define your own enum and use it as the C type parameter.

square_colors must either be empty (no colour partition declared; colour-keyed constraints always see zero matches) or have length exactly num_squares. Call validate to check this and that every constraint references only declared pieces, colours, and squares.

Solve by calling Problem::count for the population size or Problem::iter to stream all satisfying arrangements.

If pieces is empty or num_squares == 0, the problem has no arrangements to enumerate and count() returns 0.

Fields§

§num_squares: usize

Number of squares (e.g. 8 for a chess back rank).

§square_colors: Vec<C>

Colour of each square. square_colors.len() == num_squares.

§pieces: Vec<P>

Alphabet of available piece kinds. Duplicates are silently deduped by the solver; size doesn’t have to equal num_squares.

§constraint: Constraint<P, C>

Root constraint. Use Constraint::And for conjunctions.

Implementations§

Source§

impl<P: PieceKind, C: ColorKind> Problem<P, C>

Source

pub fn validate(&self) -> Result<(), ValidationError>

Checks self is internally consistent and returns a ValidationError if not.

Specifically:

  • square_colors is either empty or num_squares long.
  • Every piece referenced by a constraint is in self.pieces.
  • Every colour referenced by a CountOnColor is in self.square_colors. An empty square_colors is valid only for problems that have no CountOnColor constraints; otherwise the colour reference is treated as unknown.
  • Every At / NotAt square index is < num_squares.
  • Every Order / Relative instance index is < declared count for that piece (only checked when the piece has a Constraint::Count { Eq, n } constraint declaring its count).

count() / iter() / sample() do not auto-validate; if you need correctness up front, call this first or use ProblemBuilder::try_build.

Source

pub fn builder() -> ProblemBuilder<P, C>

Returns a fresh empty ProblemBuilder for fluent construction.

use chess_startpos_rs::{chess, Constraint, CountOp, Problem, SquareColor};

let problem: Problem<chess::Piece> = Problem::builder()
    .squares(8)
    .alternating_colors(SquareColor::Dark, SquareColor::Light)
    .pieces([chess::Piece::King, chess::Piece::Queen])
    .constraint(Constraint::Count {
        piece: chess::Piece::King,
        op: CountOp::Eq,
        value: 1,
    })
    .constraint(Constraint::Count {
        piece: chess::Piece::Queen,
        op: CountOp::Eq,
        value: 7,
    })
    .build();
assert_eq!(problem.count(), 8); // 1 king × 8 placements over 7 queens

The struct-literal API (Problem is a regular public-fields struct) remains a fully supported alternative.

Source

pub fn count(&self) -> u64

Number of distinct arrangements satisfying the constraint.

Source

pub fn iter(&self) -> impl Iterator<Item = Vec<P>> + '_

Streams all distinct arrangements satisfying the constraint in canonical lexicographic order.

Source

pub fn at(&self, index: u64) -> Option<Vec<P>>

Returns the index-th satisfying arrangement in canonical lexicographic order, or None if index >= self.count().

Equivalent to self.iter().nth(index) with u64 indexing. O(index) — for repeated indexed lookup prefer iterating once.

Source

pub fn sample(&self, seed: u64) -> Option<Vec<P>>

Returns a uniformly-random arrangement satisfying the constraint, deterministic in seed. None if the constraint is unsatisfiable.

Single pass over self.iter() using reservoir-of-size-1 sampling: each satisfying arrangement is selected with probability 1 / k where k is its 1-based index in the iterator. The result is uniformly random over the satisfying arrangements without materialising them all.

Source

pub fn with_constraint(&self, c: Constraint<P, C>) -> Self

Returns a copy of self with c added via AND-composition.

Trait Implementations§

Source§

impl<P: Clone + PieceKind, C: Clone + ColorKind> Clone for Problem<P, C>

Source§

fn clone(&self) -> Problem<P, C>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<P: Debug + PieceKind, C: Debug + ColorKind> Debug for Problem<P, C>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de, P, C> Deserialize<'de> for Problem<P, C>
where P: Deserialize<'de> + PieceKind, C: Deserialize<'de> + ColorKind,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<P, C> Serialize for Problem<P, C>

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<P, C> Freeze for Problem<P, C>
where P: Freeze, C: Freeze,

§

impl<P, C> RefUnwindSafe for Problem<P, C>

§

impl<P, C> Send for Problem<P, C>
where P: Send, C: Send,

§

impl<P, C> Sync for Problem<P, C>
where P: Sync, C: Sync,

§

impl<P, C> Unpin for Problem<P, C>
where P: Unpin, C: Unpin,

§

impl<P, C> UnsafeUnpin for Problem<P, C>
where P: UnsafeUnpin, C: UnsafeUnpin,

§

impl<P, C> UnwindSafe for Problem<P, C>
where P: UnwindSafe, C: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,