pub trait ProblemSolution: HasAssignments {
// Provided methods
fn num_propositional_variables(&self) -> usize { ... }
fn num_domains(&self) -> usize { ... }
fn get_propositional_variable_value(
&self,
propositional_variable: PropositionalVariable,
) -> bool { ... }
fn get_literal_value(&self, literal: Literal) -> bool { ... }
fn get_integer_value(&self, variable: impl IntegerVariable) -> i32 { ... }
}Expand description
A trait which specifies the common behaviours of Solution and SolutionReference.
Provided Methods§
Sourcefn num_propositional_variables(&self) -> usize
fn num_propositional_variables(&self) -> usize
Returns the number of defined PropositionalVariables
Sourcefn num_domains(&self) -> usize
fn num_domains(&self) -> usize
Returns the number of domains.
Sourcefn get_propositional_variable_value(
&self,
propositional_variable: PropositionalVariable,
) -> bool
fn get_propositional_variable_value( &self, propositional_variable: PropositionalVariable, ) -> bool
Returns the assigned boolean value of the provided PropositionalVariable.
Sourcefn get_literal_value(&self, literal: Literal) -> bool
fn get_literal_value(&self, literal: Literal) -> bool
Returns the assigned boolean value of the provided Literal.
Sourcefn get_integer_value(&self, variable: impl IntegerVariable) -> i32
fn get_integer_value(&self, variable: impl IntegerVariable) -> i32
Returns the assigned integer value of the provided variable.
Examples found in repository?
examples/nqueens.rs (line 98)
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
fn main() {
let Cli {
n,
proof: proof_path,
} = Cli::parse();
if n < 2 {
println!("Please provide an 'n > 1'");
return;
}
let Ok(proof_log) = proof_path
.as_ref()
.map(|path| ProofLog::cp(path, Format::Text, true, true))
.transpose()
.map(|proof| proof.unwrap_or_default())
else {
eprintln!(
"Failed to create proof file at {}",
proof_path.unwrap().display()
);
return;
};
let mut solver = Solver::with_options(
LearningOptions::default(),
pumpkin_solver::options::SolverOptions {
proof_log,
..Default::default()
},
);
let variables = (0..n)
.map(|i| solver.new_named_bounded_integer(0, n as i32 - 1, format!("q{i}")))
.collect::<Vec<_>>();
let _ = solver
.add_constraint(constraints::all_different(variables.clone()))
.with_tag(NonZero::new(1).unwrap())
.post();
let diag1 = variables
.iter()
.cloned()
.enumerate()
.map(|(i, var)| var.offset(i as i32))
.collect::<Vec<_>>();
let diag2 = variables
.iter()
.cloned()
.enumerate()
.map(|(i, var)| var.offset(-(i as i32)))
.collect::<Vec<_>>();
let _ = solver
.add_constraint(constraints::all_different(diag1))
.with_tag(NonZero::new(2).unwrap())
.post();
let _ = solver
.add_constraint(constraints::all_different(diag2))
.with_tag(NonZero::new(3).unwrap())
.post();
let mut brancher = solver.default_brancher_over_all_propositional_variables();
match solver.satisfy(&mut brancher, &mut Indefinite) {
SatisfactionResult::Satisfiable(solution) => {
let row_separator = format!("{}+", "+---".repeat(n as usize));
for row in 0..n {
println!("{row_separator}");
let queen_col = solution.get_integer_value(variables[row as usize]) as u32;
for col in 0..n {
let string = if queen_col == col { "| * " } else { "| " };
print!("{string}");
}
println!("|");
}
println!("{row_separator}");
}
SatisfactionResult::Unsatisfiable => {
println!("{n}-queens is unsatisfiable.");
}
SatisfactionResult::Unknown => {
println!("Timeout.");
}
}
}More examples
examples/bibd.rs (line 144)
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
fn main() {
env_logger::init();
let Some(bibd) = BIBD::from_args() else {
eprintln!("Usage: {} <v> <k> <l>", std::env::args().next().unwrap());
return;
};
println!(
"bibd: (v = {}, b = {}, r = {}, k = {}, l = {})",
bibd.rows, bibd.columns, bibd.row_sum, bibd.column_sum, bibd.max_dot_product
);
let mut solver = Solver::default();
// Create 0-1 integer variables that make up the matrix.
let matrix = create_matrix(&mut solver, &bibd);
// Enforce the row sum.
for row in matrix.iter() {
let _ = solver
.add_constraint(constraints::equals(row.clone(), bibd.row_sum as i32))
.post();
}
// Enforce the column sum.
for row in transpose(&matrix) {
let _ = solver
.add_constraint(constraints::equals(row, bibd.column_sum as i32))
.post();
}
// Enforce the dot product constraint.
// pairwise_product[r1][r2][col] = matrix[r1][col] * matrix[r2][col]
let pairwise_product = (0..bibd.rows)
.map(|_| create_matrix(&mut solver, &bibd))
.collect::<Vec<_>>();
for r1 in 0..bibd.rows as usize {
for r2 in r1 + 1..bibd.rows as usize {
for col in 0..bibd.columns as usize {
let _ = solver
.add_constraint(constraints::times(
matrix[r1][col],
matrix[r2][col],
pairwise_product[r1][r2][col],
))
.post();
}
let _ = solver
.add_constraint(constraints::less_than_or_equals(
pairwise_product[r1][r2].clone(),
bibd.max_dot_product as i32,
))
.post();
}
}
let mut brancher = solver.default_brancher_over_all_propositional_variables();
match solver.satisfy(&mut brancher, &mut Indefinite) {
SatisfactionResult::Satisfiable(solution) => {
let row_separator = format!("{}+", "+---".repeat(bibd.columns as usize));
for row in matrix.iter() {
let line = row
.iter()
.map(|var| {
if solution.get_integer_value(*var) == 1 {
String::from("| * ")
} else {
String::from("| ")
}
})
.collect::<String>();
println!("{row_separator}\n{line}|");
}
println!("{row_separator}");
}
SatisfactionResult::Unsatisfiable => {
println!("UNSATISFIABLE")
}
SatisfactionResult::Unknown => {
println!("UNKNOWN")
}
}
}examples/disjunctive_scheduling.rs (line 88)
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
fn main() {
let mut args = std::env::args();
let n_tasks = args
.nth(1)
.expect("Please provide a number of tasks")
.parse::<usize>()
.expect("Not a valid usized");
let processing_times = args
.take(n_tasks)
.map(|arg| arg.parse::<usize>())
.collect::<Result<Vec<_>, _>>()
.expect("The provided processing times are not valid unsigned integers");
assert_eq!(
processing_times.len(),
n_tasks,
"Provided fewer than `n_tasks` processing times."
);
let horizon = processing_times.iter().sum::<usize>();
let mut solver = Solver::default();
let start_variables = (0..n_tasks)
.map(|i| solver.new_bounded_integer(0, (horizon - processing_times[i]) as i32))
.collect::<Vec<_>>();
// Literal which indicates precedence (i.e. if precedence_literals[x][y] => s_y + p_y <= s_x
// which is equal to s_y - s_x <= -p_y)
let precedence_literals = (0..n_tasks)
.map(|_| {
(0..n_tasks)
.map(|_| solver.new_literal())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>();
for x in 0..n_tasks {
for y in 0..n_tasks {
if x == y {
continue;
}
let literal = precedence_literals[x][y];
let variables = vec![start_variables[y].scaled(1), start_variables[x].scaled(-1)];
// literal => s_y - s_x <= -p_y)
let _ =
constraints::less_than_or_equals(variables.clone(), -(processing_times[y] as i32))
.implied_by(&mut solver, literal, None);
//-literal => -s_y + s_x <= p_y)
let variables = vec![start_variables[y].scaled(-1), start_variables[x].scaled(1)];
let _ = constraints::less_than_or_equals(variables.clone(), processing_times[y] as i32)
.implied_by(&mut solver, literal, None);
// Either x starts before y or y start before x
let _ = solver.add_clause([literal, precedence_literals[y][x]]);
}
}
let mut brancher = solver.default_brancher_over_all_propositional_variables();
if matches!(
solver.satisfy(&mut brancher, &mut Indefinite),
SatisfactionResult::Unsatisfiable,
) {
panic!("Infeasibility Detected")
}
match solver.satisfy(&mut brancher, &mut Indefinite) {
SatisfactionResult::Satisfiable(solution) => {
let mut start_variables_and_processing_times = start_variables
.iter()
.zip(processing_times)
.collect::<Vec<_>>();
start_variables_and_processing_times.sort_by(|(s1, _), (s2, _)| {
solution
.get_integer_value(**s1)
.cmp(&solution.get_integer_value(**s2))
});
println!(
"{}",
start_variables_and_processing_times
.iter()
.map(|(var, processing_time)| format!(
"[{}, {}]",
solution.get_integer_value(**var),
solution.get_integer_value(**var) + *processing_time as i32
))
.collect::<Vec<_>>()
.join(" - ")
);
}
SatisfactionResult::Unsatisfiable => panic!("Infeasibility Detected"),
SatisfactionResult::Unknown => println!("Timeout."),
}
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.