use crate::{Graph, Isomorphism, IsomorphismIter};
use std::fmt::Debug;
pub fn isomorphisms<'a, Query, Data>(
query: &'a Query,
data: &'a Data,
) -> DefaultVf2Builder<'a, Query, Data>
where
Query: Graph,
Data: Graph,
{
DefaultVf2Builder::new(Problem::Isomorphism, query, data)
}
pub fn subgraph_isomorphisms<'a, Query, Data>(
query: &'a Query,
data: &'a Data,
) -> DefaultVf2Builder<'a, Query, Data>
where
Query: Graph,
Data: Graph,
{
DefaultVf2Builder::new(Problem::SubgraphIsomorphism, query, data)
}
pub fn induced_subgraph_isomorphisms<'a, Query, Data>(
query: &'a Query,
data: &'a Data,
) -> DefaultVf2Builder<'a, Query, Data>
where
Query: Graph,
Data: Graph,
{
DefaultVf2Builder::new(Problem::InducedSubgraphIsomorphism, query, data)
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Vf2Builder<'a, Query, Data, NodeEq, EdgeEq> {
problem: Problem,
query: &'a Query,
data: &'a Data,
node_eq: Option<NodeEq>,
edge_eq: Option<EdgeEq>,
}
pub type DefaultVf2Builder<'a, Query, Data> = Vf2Builder<
'a,
Query,
Data,
fn(&<Query as Graph>::NodeLabel, &<Data as Graph>::NodeLabel) -> bool,
fn(&<Query as Graph>::EdgeLabel, &<Data as Graph>::EdgeLabel) -> bool,
>;
impl<'a, Query, Data> DefaultVf2Builder<'a, Query, Data>
where
Query: Graph,
Data: Graph,
{
fn new(problem: Problem, query: &'a Query, data: &'a Data) -> Self {
Self {
problem,
query,
data,
node_eq: None,
edge_eq: None,
}
}
}
impl<'a, Query, Data, NodeEq, EdgeEq> Vf2Builder<'a, Query, Data, NodeEq, EdgeEq>
where
Query: Graph,
Data: Graph,
NodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool,
EdgeEq: Fn(&Query::EdgeLabel, &Data::EdgeLabel) -> bool,
{
pub fn default_eq(self) -> DefaultVf2Builder<'a, Query, Data>
where
Query::NodeLabel: PartialEq<Data::NodeLabel>,
Query::EdgeLabel: PartialEq<Data::EdgeLabel>,
{
Vf2Builder {
problem: self.problem,
query: self.query,
data: self.data,
node_eq: Some(<Query::NodeLabel as PartialEq<Data::NodeLabel>>::eq),
edge_eq: Some(<Query::EdgeLabel as PartialEq<Data::EdgeLabel>>::eq),
}
}
pub fn node_eq<NewNodeEq>(
self,
node_eq: NewNodeEq,
) -> Vf2Builder<'a, Query, Data, NewNodeEq, EdgeEq>
where
NewNodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool,
{
Vf2Builder {
problem: self.problem,
query: self.query,
data: self.data,
node_eq: Some(node_eq),
edge_eq: self.edge_eq,
}
}
pub fn edge_eq<NewEdgeEq>(
self,
edge_eq: NewEdgeEq,
) -> Vf2Builder<'a, Query, Data, NodeEq, NewEdgeEq>
where
NewEdgeEq: Fn(&Query::EdgeLabel, &Data::EdgeLabel) -> bool,
{
Vf2Builder {
problem: self.problem,
query: self.query,
data: self.data,
node_eq: self.node_eq,
edge_eq: Some(edge_eq),
}
}
pub fn first(self) -> Option<Isomorphism> {
self.iter().into_next()
}
pub fn vec(self) -> Vec<Isomorphism> {
self.iter().collect()
}
pub fn iter(self) -> IsomorphismIter<'a, Query, Data, NodeEq, EdgeEq> {
if self.problem == Problem::Isomorphism {
assert_eq!(
self.query.node_count(),
self.data.node_count(),
"graphs must be the same size"
);
}
let induced = match self.problem {
Problem::Isomorphism => true,
Problem::SubgraphIsomorphism => false,
Problem::InducedSubgraphIsomorphism => true,
};
IsomorphismIter::new(self.query, self.data, self.node_eq, self.edge_eq, induced)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Problem {
Isomorphism,
SubgraphIsomorphism,
InducedSubgraphIsomorphism,
}