use pumpkin_conflict_resolvers::resolvers::ResolutionResolver;
use pumpkin_core::constraints::NegatableConstraint;
use pumpkin_solver::Solver;
use pumpkin_solver::core::results::ProblemSolution;
use pumpkin_solver::core::results::SatisfactionResult;
use pumpkin_solver::core::termination::Indefinite;
use pumpkin_solver::core::variables::TransformableVariable;
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 constraint_tag = solver.new_constraint_tag();
let start_variables = (0..n_tasks)
.map(|i| solver.new_bounded_integer(0, (horizon - processing_times[i]) as i32))
.collect::<Vec<_>>();
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)];
pumpkin_constraints::less_than_or_equals(
variables,
-(processing_times[x] as i32),
constraint_tag,
)
.reify(&mut solver, literal);
solver.add_clause(
[
literal.get_true_predicate(),
precedence_literals[y][x].get_true_predicate(),
],
constraint_tag,
);
}
}
let mut brancher = solver.default_brancher();
let mut resolver = ResolutionResolver::default();
if matches!(
solver.satisfy(&mut brancher, &mut Indefinite, &mut resolver),
SatisfactionResult::Unsatisfiable(_, _, _),
) {
panic!("Infeasibility Detected")
}
match solver.satisfy(&mut brancher, &mut Indefinite, &mut resolver) {
SatisfactionResult::Satisfiable(satisfiable) => {
let solution = 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."),
};
}