pub trait NegatableConstraint: Constraint {
type NegatedConstraint: NegatableConstraint + 'static;
// Required method
fn negation(&self) -> Self::NegatedConstraint;
// Provided method
fn reify(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError>
where Self: Sized { ... }
}Expand description
A Constraint which has a well-defined negation.
Having a negation means the Constraint can be fully reified; i.e., a constraint C can be
turned into r <-> C where r is a reification literal.
For example, the negation of the Constraint a = b is (well-)defined as a != b.
Required Associated Types§
type NegatedConstraint: NegatableConstraint + 'static
Required Methods§
fn negation(&self) -> Self::NegatedConstraint
Provided Methods§
Sourcefn reify(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError>where
Self: Sized,
fn reify(
self,
solver: &mut Solver,
reification_literal: Literal,
) -> Result<(), ConstraintOperationError>where
Self: Sized,
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.
The tag allows inferences to be traced to the constraint that implies them. They will
show up in the proof log.
Examples found in repository?
examples/disjunctive_scheduling.rs (line 77)
20fn main() {
21 let mut args = std::env::args();
22
23 let n_tasks = args
24 .nth(1)
25 .expect("Please provide a number of tasks")
26 .parse::<usize>()
27 .expect("Not a valid usized");
28 let processing_times = args
29 .take(n_tasks)
30 .map(|arg| arg.parse::<usize>())
31 .collect::<Result<Vec<_>, _>>()
32 .expect("The provided processing times are not valid unsigned integers");
33 assert_eq!(
34 processing_times.len(),
35 n_tasks,
36 "Provided fewer than `n_tasks` processing times."
37 );
38
39 let horizon = processing_times.iter().sum::<usize>();
40
41 let mut solver = Solver::default();
42
43 // Creates a dummy constraint tag; since this example does not support proof logging the
44 // constraint tag does not matter.
45 let constraint_tag = solver.new_constraint_tag();
46
47 let start_variables = (0..n_tasks)
48 .map(|i| solver.new_bounded_integer(0, (horizon - processing_times[i]) as i32))
49 .collect::<Vec<_>>();
50
51 // Literal which indicates precedence (i.e. precedence_literals[x][y] <=> x ends before y
52 // starts)
53 let precedence_literals = (0..n_tasks)
54 .map(|_| {
55 (0..n_tasks)
56 .map(|_| solver.new_literal())
57 .collect::<Vec<_>>()
58 })
59 .collect::<Vec<_>>();
60
61 for x in 0..n_tasks {
62 for y in 0..n_tasks {
63 if x == y {
64 continue;
65 }
66 // precedence_literals[x][y] <=> x ends before y starts
67 let literal = precedence_literals[x][y];
68 // literal <=> (s_x + p_x <= s_y)
69 // equivelent to literal <=> (s_x - s_y <= -p_x)
70 // So the variables are -s_y and s_x, and the rhs is -p_x
71 let variables = vec![start_variables[y].scaled(-1), start_variables[x].scaled(1)];
72 let _ = constraints::less_than_or_equals(
73 variables,
74 -(processing_times[x] as i32),
75 constraint_tag,
76 )
77 .reify(&mut solver, literal);
78
79 // Either x starts before y or y start before x
80 let _ = solver.add_clause(
81 [
82 literal.get_true_predicate(),
83 precedence_literals[y][x].get_true_predicate(),
84 ],
85 constraint_tag,
86 );
87 }
88 }
89
90 let mut brancher = solver.default_brancher();
91 if matches!(
92 solver.satisfy(&mut brancher, &mut Indefinite),
93 SatisfactionResult::Unsatisfiable(_, _),
94 ) {
95 panic!("Infeasibility Detected")
96 }
97 match solver.satisfy(&mut brancher, &mut Indefinite) {
98 SatisfactionResult::Satisfiable(satisfiable) => {
99 let solution = satisfiable.solution();
100
101 let mut start_variables_and_processing_times = start_variables
102 .iter()
103 .zip(processing_times)
104 .collect::<Vec<_>>();
105 start_variables_and_processing_times.sort_by(|(s1, _), (s2, _)| {
106 solution
107 .get_integer_value(**s1)
108 .cmp(&solution.get_integer_value(**s2))
109 });
110
111 println!(
112 "{}",
113 start_variables_and_processing_times
114 .iter()
115 .map(|(var, processing_time)| format!(
116 "[{}, {}]",
117 solution.get_integer_value(**var),
118 solution.get_integer_value(**var) + *processing_time as i32
119 ))
120 .collect::<Vec<_>>()
121 .join(" - ")
122 );
123 }
124 SatisfactionResult::Unsatisfiable(_, _) => panic!("Infeasibility Detected"),
125 SatisfactionResult::Unknown(_, _) => println!("Timeout."),
126 };
127}