arboretum-td 0.1.0

A library and CLI for obtaining exact and heuristc tree decompositions for arbitrary graphs
Documentation
use crate::datastructures::BitSet;
use crate::graph::base_graph::BaseGraph;
use fxhash::FxHashMap;
use std::borrow::Borrow;
use std::cmp::Ordering;

#[derive(Clone, Debug)]
pub struct BitGraph {
    graph: Vec<BitSet>,
}

impl From<Vec<BitSet>> for BitGraph {
    fn from(graph: Vec<BitSet>) -> Self {
        Self { graph }
    }
}

impl From<&[BitSet]> for BitGraph {
    fn from(slice: &[BitSet]) -> Self {
        Self {
            graph: Vec::from(slice),
        }
    }
}

impl BitGraph {
    pub fn from_graph<G: BaseGraph>(og_graph: &G, og_to_self: &FxHashMap<u32, u32>) -> Self {
        let mut graph = vec![BitSet::new(og_graph.order()); og_graph.order()];

        for v in og_graph.vertices() {
            for u in og_graph.neighborhood(v) {
                let a = (*og_to_self.get(&(v as u32)).unwrap()) as usize;
                let b = (*og_to_self.get(&(u as u32)).unwrap()) as usize;
                graph[a].set_bit(b);
            }
        }
        Self { graph }
    }

    pub fn neighborhood_as_bitset(&self, u: usize) -> &BitSet {
        self.graph[u].borrow()
    }

    pub fn exterior_border(&self, c: &BitSet) -> BitSet {
        let mut border = BitSet::new(c.len());

        for v in c.iter() {
            border.or(&self.graph[v])
        }
        border.and_not(c);
        border
    }
}

impl BaseGraph for BitGraph {
    fn degree(&self, u: usize) -> usize {
        self.graph[u].cardinality()
    }

    fn order(&self) -> usize {
        self.graph.len()
    }

    fn is_clique(&self, vertices: &[usize]) -> bool {
        for u in vertices {
            for v in vertices {
                if u < v && !self.graph[*u][*v] {
                    return false;
                }
            }
        }
        true
    }

    fn is_neighborhood_clique(&self, u: usize) -> bool {
        for u in self.graph[u].iter() {
            for v in self.graph[u].iter() {
                if u < v && !self.graph[u][v] {
                    return false;
                }
            }
        }
        true
    }

    fn has_edge(&self, u: usize, v: usize) -> bool {
        self.graph[u][v]
    }

    fn is_simplicial(&self, u: usize) -> bool {
        self.is_neighborhood_clique(u)
    }

    fn is_almost_simplicial(&self, u: usize) -> bool {
        for ignore in self.graph[u].iter() {
            for u in self.graph[u].iter() {
                for v in self.graph[u].iter() {
                    if u < v && u != ignore && !self.graph[u][v] {
                        return false;
                    }
                }
            }
        }
        true
    }

    fn vertices(&self) -> Box<dyn Iterator<Item = usize>> {
        Box::new(0..self.graph.len())
    }

    fn neighborhood(&self, u: usize) -> Box<dyn Iterator<Item = usize> + '_> {
        Box::new(self.graph[u].iter())
    }

    fn fill_in_count(&self, u: usize) -> usize {
        let mut cnt = 0;
        for u in self.graph[u].iter() {
            for v in self.graph[u].iter() {
                if u < v && !self.graph[u][v] {
                    cnt += 1;
                }
            }
        }
        cnt
    }

    fn min_vertex_by<F: FnMut(&usize, &usize) -> Ordering>(&self, cmp: F) -> Option<usize> {
        (0..self.graph.len()).min_by(cmp)
    }

    fn max_vertex_by<F: FnMut(&usize, &usize) -> Ordering>(&self, cmp: F) -> Option<usize> {
        (0..self.graph.len()).max_by(cmp)
    }

    fn min_neighbor_by<F: FnMut(&usize, &usize) -> Ordering>(
        &self,
        u: usize,
        cmp: F,
    ) -> Option<usize> {
        self.graph[u].iter().min_by(cmp)
    }

    fn max_neighbor_by<F: FnMut(&usize, &usize) -> Ordering>(
        &self,
        u: usize,
        cmp: F,
    ) -> Option<usize> {
        self.graph[u].iter().max_by(cmp)
    }
}