Map colouring
The seven Australian states and territories, neighbours in different colours. Three colours are enough; for two the solver exhausts the search space and reports Infeasible.
Map colouring
examples/map_coloring.rs//! Map colouring of the Australian states and territories, the classic CSP from Russell &
//! Norvig, *Artificial Intelligence: A Modern Approach*, chapter 6.
//!
//! Every region gets a colour; neighbouring regions must differ (`NotEqual`). With three colours
//! the solver finds a colouring. With two it proves that none exists: Western Australia,
//! Northern Territory and South Australia all border each other.
//!
//! Run with `cargo run --example map_coloring`.
use unifier::VariableId;
use unifier::dsl::ModelBuilder;
use unifier::solver::{BacktrackingSolver, SolveStatus, SolverOptions};
const REGIONS: [&str; 7] = ["WA", "NT", "SA", "Q", "NSW", "V", "T"];
const BORDERS: [(&str, &str); 9] = [
("WA", "NT"),
("WA", "SA"),
("NT", "SA"),
("NT", "Q"),
("SA", "Q"),
("SA", "NSW"),
("SA", "V"),
("Q", "NSW"),
("NSW", "V"),
];
const COLOURS: [&str; 3] = ["red", "green", "blue"];
fn solve(colours: usize) {
let mut builder = ModelBuilder::new();
let vars: Vec<VariableId> = REGIONS
.iter()
.map(|region| builder.new_var(*region, 0..=(colours as i64 - 1)))
.collect();
let var = |name: &str| {
vars[REGIONS
.iter()
.position(|r| *r == name)
.expect("known region")]
};
for (a, b) in BORDERS {
builder.add_not_equal(var(a), var(b));
}
let graph = builder.build().expect("map colouring model validates");
let outcome = BacktrackingSolver::new().solve(&graph, &SolverOptions::default());
println!("{colours} colours: {:?}", outcome.status);
match (outcome.status, outcome.solution) {
(_, Some(solution)) => {
for (region, &v) in REGIONS.iter().zip(&vars) {
println!(
" {region:<4} {}",
COLOURS[solution.assignment[&v] as usize]
);
}
}
(SolveStatus::Infeasible, None) => {
println!(" No colouring exists: WA, NT and SA border each other.");
}
(status, None) => println!(" No result: {status:?}"),
}
}
fn main() {
println!(
"Map of Australia: {} regions, {} borders\n",
REGIONS.len(),
BORDERS.len()
);
solve(3);
println!();
solve(2);
}Map of Australia: 7 regions, 9 borders 3 colours: Feasible WA blue NT green SA red Q blue NSW green V blue T red 2 colours: Infeasible No colouring exists: WA, NT and SA border each other.