use crate::graph::edge::Edge;
use crate::graph::graph::Graph;
use crate::service::colour::colouriser::Colouriser;
use crate::service::matching::perfect_matchings::{
Matching, MatchingGraph, MatchingGraphVerticesIter,
};
#[derive(Debug, Clone)]
pub struct MatchingColouriser {}
impl Colouriser for MatchingColouriser {
fn is_colorable<G: Graph>(graph: &G) -> bool {
let mut match_graph = MatchingGraph::from_graph(graph);
let matchings = match_graph.perfect_matchings();
let is_col = Self::is_col(graph, &matchings);
is_col
}
fn new() -> Self {
Self {}
}
}
impl MatchingColouriser {
fn is_col<G: Graph>(graph: &G, matchings: &Vec<Matching>) -> bool {
let mut local_graph = MatchingGraph::from_graph(graph);
for matching in matchings {
for edge in matching.edges.iter() {
local_graph.remove_edge(edge.from(), edge.to());
}
let mut cd = CycleDiscovery::new(&local_graph);
let has_odd_cycle = cd.has_odd_cycle();
if !has_odd_cycle {
return true;
}
for edge in matching.edges.iter() {
local_graph.add_edge(edge.from(), edge.to());
}
}
false
}
}
pub struct CycleDiscovery<'a> {
graph: &'a MatchingGraph,
visited: Vec<bool>,
to_visit: Vec<usize>,
vert_iter: MatchingGraphVerticesIter<'a>,
}
impl<'a> CycleDiscovery<'a> {
pub fn new(graph: &'a MatchingGraph) -> Self {
let visited = vec![false; graph.max_vertex_index()];
let discovery = CycleDiscovery {
graph,
visited,
to_visit: vec![],
vert_iter: graph.vertices(),
};
discovery
}
fn visit(&mut self, vertex: usize) -> bool {
let old_val = self.visited[vertex];
self.visited[vertex] = true;
!old_val
}
fn dfs_next(&mut self) -> Option<usize> {
if let Some(vertex) = self.to_visit.pop() {
for neighbor in self.graph.neighbors(vertex) {
if self.visit(*neighbor) {
self.to_visit.push(*neighbor);
}
}
return Some(vertex);
}
None
}
pub fn has_odd_cycle(&mut self) -> bool {
self.visited = vec![false; self.graph.max_vertex_index()];
while let Some(component) = self.next_component() {
if component.len() % 2 == 1 {
if self.is_cycle(&component) {
return true;
}
}
}
false
}
fn is_cycle(&self, component: &Vec<usize>) -> bool {
let mut edges_count = 0;
for vertex in component.iter() {
let neighbors = self.graph.neighbors(*vertex);
edges_count += neighbors.len();
}
edges_count = edges_count / 2;
if edges_count == component.len() {
return true;
}
false
}
fn next_component(&mut self) -> Option<Vec<usize>> {
self.to_visit = vec![];
while let Some(vertex) = self.vert_iter.next() {
if self.visited[*vertex.index()] {
continue;
}
self.to_visit.push(*vertex.index());
self.visit(*vertex.index());
let mut chain = vec![];
while let Some(dfs_next_vertex) = self.dfs_next() {
chain.push(dfs_next_vertex);
}
return Some(chain);
}
None
}
pub fn cycles(&mut self) -> Vec<Vec<usize>> {
self.visited = vec![false; self.graph.max_vertex_index()];
let mut cycles = vec![];
while let Some(component) = self.next_component() {
if self.is_cycle(&component) {
cycles.push(component);
}
}
cycles
}
}