Solution

Struct Solution 

Source
pub struct Solution<'s, 'i: 's, I, C, S> { /* private fields */ }
Expand description

An iterator over the options of a solution to an XCC problem.

Implementations§

Source§

impl<'s, 'i, S, I, C> Solution<'s, 'i, I, C, S>
where S: Solver<'i, I, C>, I: Eq,

Source

pub fn next(&mut self, result: &mut Vec<(&'i I, Option<C>)>) -> bool

Places the items in the next option of the solution and their color assignments under that same option into result.

Returns false and leaves the vector untouched if and only if all options have already been enumerated.

Examples found in repository?
examples/langford_pairs.rs (line 62)
39fn main() {
40    let numbers = (1..=N).map(Item::Number);
41    let slots = (1..=2 * N).map(Item::Slot);
42    let items: Vec<_> = numbers.chain(slots).collect();
43
44    let mut solver: DlSolver<Item, ()> = DlSolver::new(&items, &[]);
45    for i in 1..=N {
46        // Optimization: half of the Langford pairs for a given value of $n$
47        // are the reverses of the others. Reduce the search space by placing
48        // the first 1 in position $1\le s_j<n$.
49        let first_slot_range = 1..if i == 1 { N } else { 2 * N - i };
50        for j in first_slot_range {
51            let k = i + j + 1;
52            let items = [Item::Number(i), Item::Slot(j), Item::Slot(k)];
53            solver.add_option(items, []);
54        }
55    }
56
57    let mut options = Vec::new();
58    solver.solve(|mut solution| {
59        assert_eq!(solution.option_count(), N);
60        // Convert the set of options into the corresponding placement.
61        let mut placement = [0usize; 2 * N];
62        while solution.next(&mut options) {
63            // Sort the items in `options` so we can perform pattern matching.
64            // Note that `Item` derives `Ord`, so item variants are ordered by
65            // their discriminants: numbers come before slots.
66            options.sort();
67            if let &[(&Item::Number(i), _), (&Item::Slot(j), _), (&Item::Slot(k), _)] = &options[..]
68            {
69                placement[j - 1] = i;
70                placement[k - 1] = i;
71            } else {
72                unreachable!("ordered option should match (number, slot, slot) pattern");
73            }
74        }
75        // Print the found Langford sequence, and its reverse.
76        println!("{:?}", placement);
77        placement.reverse();
78        println!("{:?}", placement);
79        ControlFlow::Continue(())
80    });
81}
More examples
Hide additional examples
examples/polycube_packing.rs (line 187)
150fn main() {
151    // Define the items of the exact cover problem, namely the $lmn$ cells of
152    // the $l\times m\times n$ cuboid.
153    let (l, m, n) = (5i8, 5i8, 5i8);
154    let positions = (0..l)
155        .flat_map(|x| iter::repeat(x).zip(0..m))
156        .flat_map(|y| iter::repeat(y).zip(0..n))
157        .map(|((x, y), z)| (x, y, z))
158        .collect::<Vec<_>>();
159
160    let mut solver: DlSolver<Position, ()> = DlSolver::new(&positions, &[]);
161    // For each base placement $P$ of the Y pentacube, and for each offset
162    // $(x_0,y_0,z_0)$ such that the piece $P'=P+(x_0,y_0,z_0)$ lies within the
163    // $l\times m\times n$ cuboid cornered at the origin, define an option whose
164    // primary items are the cells of $P'$. We break symmetry by constraining
165    // a particular cubie of the first pentacube to be at $L_\infty$ distance
166    // $\le2$ from the origin.
167    let placements = Y.base_placements();
168    let mut first = true;
169    for placement in placements {
170        for (x_0, y_0, z_0) in &positions {
171            if first && (*x_0 > 2 || *y_0 > 2 || *z_0 > 2) {
172                continue;
173            }
174            let shifted = placement.transform(|(x, y, z)| (x + x_0, y + y_0, z + z_0));
175            if is_in_bounds(&shifted, l, m, n) {
176                solver.add_option(&shifted.0, []);
177            }
178        }
179        first = false;
180    }
181
182    let mut count = 0;
183    let mut polycube = Vec::with_capacity(Y.cubie_count());
184    solver.solve(|mut solution| {
185        // Print the solution, which consists of a set of 25 pentacubes.
186        print!("[");
187        while solution.next(&mut polycube) {
188            print!("[");
189            if let Some(((&last, _), elements)) = polycube.split_last() {
190                for (&cubie, _) in elements {
191                    print!("[{},{},{}],", cubie.0, cubie.1, cubie.2);
192                }
193                print!("[{},{},{}]", last.0, last.1, last.2);
194            }
195            print!("],");
196        }
197        println!("]");
198        count += 1;
199        ControlFlow::Continue(())
200    });
201    println!("found {count} packings");
202}
Source

pub fn option_count(&self) -> usize

Returns the number of options in the solution.

Examples found in repository?
examples/langford_pairs.rs (line 59)
39fn main() {
40    let numbers = (1..=N).map(Item::Number);
41    let slots = (1..=2 * N).map(Item::Slot);
42    let items: Vec<_> = numbers.chain(slots).collect();
43
44    let mut solver: DlSolver<Item, ()> = DlSolver::new(&items, &[]);
45    for i in 1..=N {
46        // Optimization: half of the Langford pairs for a given value of $n$
47        // are the reverses of the others. Reduce the search space by placing
48        // the first 1 in position $1\le s_j<n$.
49        let first_slot_range = 1..if i == 1 { N } else { 2 * N - i };
50        for j in first_slot_range {
51            let k = i + j + 1;
52            let items = [Item::Number(i), Item::Slot(j), Item::Slot(k)];
53            solver.add_option(items, []);
54        }
55    }
56
57    let mut options = Vec::new();
58    solver.solve(|mut solution| {
59        assert_eq!(solution.option_count(), N);
60        // Convert the set of options into the corresponding placement.
61        let mut placement = [0usize; 2 * N];
62        while solution.next(&mut options) {
63            // Sort the items in `options` so we can perform pattern matching.
64            // Note that `Item` derives `Ord`, so item variants are ordered by
65            // their discriminants: numbers come before slots.
66            options.sort();
67            if let &[(&Item::Number(i), _), (&Item::Slot(j), _), (&Item::Slot(k), _)] = &options[..]
68            {
69                placement[j - 1] = i;
70                placement[k - 1] = i;
71            } else {
72                unreachable!("ordered option should match (number, slot, slot) pattern");
73            }
74        }
75        // Print the found Langford sequence, and its reverse.
76        println!("{:?}", placement);
77        placement.reverse();
78        println!("{:?}", placement);
79        ControlFlow::Continue(())
80    });
81}

Auto Trait Implementations§

§

impl<'s, 'i, I, C, S> Freeze for Solution<'s, 'i, I, C, S>

§

impl<'s, 'i, I, C, S> RefUnwindSafe for Solution<'s, 'i, I, C, S>

§

impl<'s, 'i, I, C, S> Send for Solution<'s, 'i, I, C, S>
where S: Send, C: Send, I: Sync,

§

impl<'s, 'i, I, C, S> Sync for Solution<'s, 'i, I, C, S>
where S: Sync, C: Sync, I: Sync,

§

impl<'s, 'i, I, C, S> Unpin for Solution<'s, 'i, I, C, S>
where C: Unpin,

§

impl<'s, 'i, I, C, S> !UnwindSafe for Solution<'s, 'i, I, C, S>

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> 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, 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.