ConstraintPoster

Struct ConstraintPoster 

Source
pub struct ConstraintPoster<'solver, ConstraintImpl> { /* private fields */ }
Expand description

A structure which is responsible for adding the created Constraints to the Solver. For an example on how to use this, see crate::constraints.

Implementations§

Source§

impl<ConstraintImpl> ConstraintPoster<'_, ConstraintImpl>
where ConstraintImpl: Constraint,

Source

pub fn post(self) -> Result<(), ConstraintOperationError>

Add the Constraint to the Solver.

This method returns a ConstraintOperationError if the addition of the Constraint led to a root-level conflict.

Examples found in repository?
examples/nqueens.rs (line 65)
25fn main() {
26    let Cli {
27        n,
28        proof: proof_path,
29    } = Cli::parse();
30
31    if n < 2 {
32        println!("Please provide an 'n > 1'");
33        return;
34    }
35
36    let Ok(proof_log) = proof_path
37        .as_ref()
38        .map(|path| ProofLog::cp(path, true))
39        .transpose()
40        .map(|proof| proof.unwrap_or_default())
41    else {
42        eprintln!(
43            "Failed to create proof file at {}",
44            proof_path.unwrap().display()
45        );
46        return;
47    };
48
49    let mut solver = Solver::with_options(SolverOptions {
50        proof_log,
51        ..Default::default()
52    });
53
54    // Create the constraint tags for the three all_different constraints.
55    let c1_tag = solver.new_constraint_tag();
56    let c2_tag = solver.new_constraint_tag();
57    let c3_tag = solver.new_constraint_tag();
58
59    let variables = (0..n)
60        .map(|i| solver.new_named_bounded_integer(0, n as i32 - 1, format!("q{i}")))
61        .collect::<Vec<_>>();
62
63    let _ = solver
64        .add_constraint(constraints::all_different(variables.clone(), c1_tag))
65        .post();
66
67    let diag1 = variables
68        .iter()
69        .cloned()
70        .enumerate()
71        .map(|(i, var)| var.offset(i as i32))
72        .collect::<Vec<_>>();
73    let diag2 = variables
74        .iter()
75        .cloned()
76        .enumerate()
77        .map(|(i, var)| var.offset(-(i as i32)))
78        .collect::<Vec<_>>();
79
80    let _ = solver
81        .add_constraint(constraints::all_different(diag1, c2_tag))
82        .post();
83    let _ = solver
84        .add_constraint(constraints::all_different(diag2, c3_tag))
85        .post();
86
87    let mut brancher = solver.default_brancher();
88    match solver.satisfy(&mut brancher, &mut Indefinite) {
89        SatisfactionResult::Satisfiable(satisfiable) => {
90            let solution = satisfiable.solution();
91
92            let row_separator = format!("{}+", "+---".repeat(n as usize));
93
94            for row in 0..n {
95                println!("{row_separator}");
96
97                let queen_col = solution.get_integer_value(variables[row as usize]) as u32;
98
99                for col in 0..n {
100                    let string = if queen_col == col { "| * " } else { "|   " };
101
102                    print!("{string}");
103                }
104
105                println!("|");
106            }
107
108            println!("{row_separator}");
109        }
110        SatisfactionResult::Unsatisfiable(_, _) => {
111            println!("{n}-queens is unsatisfiable.");
112        }
113        SatisfactionResult::Unknown(_, _) => {
114            println!("Timeout.");
115        }
116    };
117}
More examples
Hide additional examples
examples/bibd.rs (line 105)
75fn main() {
76    env_logger::init();
77
78    let Some(bibd) = Bibd::from_args() else {
79        eprintln!("Usage: {} <v> <k> <l>", std::env::args().next().unwrap());
80        return;
81    };
82
83    println!(
84        "bibd: (v = {}, b = {}, r = {}, k = {}, l = {})",
85        bibd.rows, bibd.columns, bibd.row_sum, bibd.column_sum, bibd.max_dot_product
86    );
87
88    let mut solver = Solver::default();
89
90    // Creates a dummy constraint tag; since this example does not support proof logging the
91    // constraint tag does not matter.
92    let constraint_tag = solver.new_constraint_tag();
93
94    // Create 0-1 integer variables that make up the matrix.
95    let matrix = create_matrix(&mut solver, &bibd);
96
97    // Enforce the row sum.
98    for row in matrix.iter() {
99        let _ = solver
100            .add_constraint(constraints::equals(
101                row.clone(),
102                bibd.row_sum as i32,
103                constraint_tag,
104            ))
105            .post();
106    }
107
108    // Enforce the column sum.
109    for row in transpose(&matrix) {
110        let _ = solver
111            .add_constraint(constraints::equals(
112                row,
113                bibd.column_sum as i32,
114                constraint_tag,
115            ))
116            .post();
117    }
118
119    // Enforce the dot product constraint.
120    // pairwise_product[r1][r2][col] = matrix[r1][col] * matrix[r2][col]
121    let pairwise_product = (0..bibd.rows)
122        .map(|_| create_matrix(&mut solver, &bibd))
123        .collect::<Vec<_>>();
124
125    for r1 in 0..bibd.rows as usize {
126        for r2 in r1 + 1..bibd.rows as usize {
127            for col in 0..bibd.columns as usize {
128                let _ = solver
129                    .add_constraint(constraints::times(
130                        matrix[r1][col],
131                        matrix[r2][col],
132                        pairwise_product[r1][r2][col],
133                        constraint_tag,
134                    ))
135                    .post();
136            }
137
138            let _ = solver
139                .add_constraint(constraints::less_than_or_equals(
140                    pairwise_product[r1][r2].clone(),
141                    bibd.max_dot_product as i32,
142                    constraint_tag,
143                ))
144                .post();
145        }
146    }
147
148    let mut brancher = solver.default_brancher();
149    match solver.satisfy(&mut brancher, &mut Indefinite) {
150        SatisfactionResult::Satisfiable(satisfiable) => {
151            let solution = satisfiable.solution();
152
153            let row_separator = format!("{}+", "+---".repeat(bibd.columns as usize));
154
155            for row in matrix.iter() {
156                let line = row
157                    .iter()
158                    .map(|var| {
159                        if solution.get_integer_value(*var) == 1 {
160                            String::from("| * ")
161                        } else {
162                            String::from("|   ")
163                        }
164                    })
165                    .collect::<String>();
166
167                println!("{row_separator}\n{line}|");
168            }
169
170            println!("{row_separator}");
171        }
172        SatisfactionResult::Unsatisfiable(_, _) => {
173            println!("UNSATISFIABLE")
174        }
175        SatisfactionResult::Unknown(_, _) => {
176            println!("UNKNOWN")
177        }
178    };
179}
Source

pub fn implied_by( self, reification_literal: Literal, ) -> Result<(), ConstraintOperationError>

Add the half-reified version of the Constraint to the Solver; i.e. post the constraint r -> constraint where r is a reification literal.

This method returns a ConstraintOperationError if the addition of the Constraint led to a root-level conflict.

Source§

impl<ConstraintImpl> ConstraintPoster<'_, ConstraintImpl>
where ConstraintImpl: NegatableConstraint,

Source

pub fn reify( self, reification_literal: Literal, ) -> Result<(), ConstraintOperationError>

Add the reified version of the Constraint to the Solver; i.e. post the constraint r <-> constraint where r is a reification literal.

This method returns a ConstraintOperationError if the addition of the Constraint led to a root-level conflict.

Trait Implementations§

Source§

impl<'solver, ConstraintImpl> Debug for ConstraintPoster<'solver, ConstraintImpl>
where ConstraintImpl: Debug,

Source§

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

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

impl<ConstraintImpl> Drop for ConstraintPoster<'_, ConstraintImpl>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<'solver, ConstraintImpl> Freeze for ConstraintPoster<'solver, ConstraintImpl>
where ConstraintImpl: Freeze,

§

impl<'solver, ConstraintImpl> !RefUnwindSafe for ConstraintPoster<'solver, ConstraintImpl>

§

impl<'solver, ConstraintImpl> !Send for ConstraintPoster<'solver, ConstraintImpl>

§

impl<'solver, ConstraintImpl> !Sync for ConstraintPoster<'solver, ConstraintImpl>

§

impl<'solver, ConstraintImpl> Unpin for ConstraintPoster<'solver, ConstraintImpl>
where ConstraintImpl: Unpin,

§

impl<'solver, ConstraintImpl> !UnwindSafe for ConstraintPoster<'solver, ConstraintImpl>

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> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<'src, T> IntoMaybe<'src, T> for T
where T: 'src,

Source§

type Proj<U: 'src> = U

Source§

fn map_maybe<R>( self, _f: impl FnOnce(&'src T) -> &'src R, g: impl FnOnce(T) -> R, ) -> <T as IntoMaybe<'src, T>>::Proj<R>
where R: 'src,

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<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V