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>) -> bool

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

pub fn option_count(&self) -> usize

Returns the number of options in the solution.

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

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.