use crate::graph::edge::Edge;
use crate::graph::graph::Graph;
use crate::graph::vertex::Vertex;
use crate::service::colour::colouriser::Colouriser;
use std::collections::HashMap;
use std::iter::FromIterator;
#[derive(Debug, Clone)]
pub struct SATColourizerCadical {}
impl Colouriser for SATColourizerCadical {
fn is_colorable<G>(graph: &G) -> bool
where
G: Graph,
{
let mut solver = Self::graph_to_cnf_sat(graph);
solver.solve().unwrap()
}
fn new() -> Self {
SATColourizerCadical {}
}
}
impl SATColourizerCadical {
fn graph_to_cnf_sat<G: Graph>(graph: &G) -> cadical::Solver {
let mut solver: cadical::Solver = Default::default();
let mut edge_lits = EdgeLits::new();
for edge in graph.edges() {
let (xij1, xij2, xij3) = edge_lits.next_lits(edge.from(), edge.to());
solver.add_clause([xij1, xij2, xij3].iter().copied());
solver.add_clause([-xij1, -xij2, xij3].iter().copied());
solver.add_clause([-xij1, xij2, -xij3].iter().copied());
solver.add_clause([xij1, -xij2, -xij3].iter().copied());
solver.add_clause([-xij1, -xij2, -xij3].iter().copied());
}
for vertex in graph.vertices() {
let edges = graph.edges_of_vertex(vertex.index());
let edges: Vec<&G::E> = Vec::from_iter(edges);
if edges.is_empty() || edges.len() == 1 {
continue;
}
let lits_first = edge_lits
.lits_of_edge(edges[0].from(), edges[0].to())
.unwrap();
let lits_second = edge_lits
.lits_of_edge(edges[1].from(), edges[1].to())
.unwrap();
solver.add_clause([-lits_first.0, -lits_second.0].iter().copied());
solver.add_clause([-lits_first.1, -lits_second.1].iter().copied());
solver.add_clause([-lits_first.2, -lits_second.2].iter().copied());
if edges.len() == 3 {
let lits_third = edge_lits
.lits_of_edge(edges[2].from(), edges[2].to())
.unwrap();
solver.add_clause([-lits_first.0, -lits_third.0].iter().copied());
solver.add_clause([-lits_first.1, -lits_third.1].iter().copied());
solver.add_clause([-lits_first.2, -lits_third.2].iter().copied());
solver.add_clause([-lits_second.0, -lits_third.0].iter().copied());
solver.add_clause([-lits_second.1, -lits_third.1].iter().copied());
solver.add_clause([-lits_second.2, -lits_third.2].iter().copied());
}
}
solver
}
}
struct EdgeLits {
edge_lits: HashMap<(usize, usize), (i32, i32, i32)>,
lits: Vec<usize>,
}
impl EdgeLits {
pub fn new() -> Self {
let mut lits = EdgeLits {
edge_lits: HashMap::new(),
lits: Vec::new(),
};
lits.lits.push(0);
lits
}
pub fn next_lits(&mut self, from: usize, to: usize) -> (i32, i32, i32) {
let mut lits = (0, 0, 0);
lits.0 = self.lits.len() as i32;
self.lits.push(self.lits.len());
lits.1 = self.lits.len() as i32;
self.lits.push(self.lits.len());
lits.2 = self.lits.len() as i32;
self.lits.push(self.lits.len());
self.edge_lits.insert((from, to), lits);
lits
}
pub fn lits_of_edge(&self, from: usize, to: usize) -> Option<&(i32, i32, i32)> {
self.edge_lits.get(&(from, to))
}
}