pub mod many_patterns;
pub mod single_pattern;
use std::hash::Hash;
pub use many_patterns::{ManyMatcher, NaiveManyMatcher, PatternID, UnweightedManyMatcher};
use petgraph::visit::{GraphBase, IntoNodeIdentifiers};
use portgraph::{LinkView, NodeIndex};
pub use single_pattern::SinglePatternMatcher;
use crate::{
patterns::UnweightedEdge,
utils::{always_true, validate_unweighted_edge},
HashMap, NodeProperty, Pattern, Universe,
};
pub trait PortMatcher<GraphRef, NodeId, U: Universe> {
type PNode;
type PEdge: Eq + Hash;
fn find_rooted_matches(
&self,
graph: GraphRef,
root: NodeId,
) -> Vec<PatternMatch<PatternID, NodeId>>;
fn get_pattern(&self, id: PatternID) -> Option<&Pattern<U, Self::PNode, Self::PEdge>>;
fn find_matches(&self, graph: GraphRef) -> Vec<PatternMatch<PatternID, NodeId>>
where
GraphRef: IntoNodeIdentifiers + GraphBase<NodeId = NodeId>,
{
let mut matches = Vec::new();
for root in graph.node_identifiers() {
matches.append(&mut self.find_rooted_matches(graph, root));
}
matches
}
}
type Match = PatternMatch<PatternID, NodeIndex>;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct PatternMatch<P, N> {
pub pattern: P,
pub root: N,
}
impl<P, N> PatternMatch<P, N> {
pub fn new(pattern: P, root: N) -> Self {
Self { pattern, root }
}
pub fn from_tuple((pattern, root): (P, N)) -> Self {
Self { pattern, root }
}
}
impl<'p, P, N> PatternMatch<&'p P, N> {
pub fn clone_pattern(&self) -> PatternMatch<P, N>
where
P: Clone,
N: Copy,
{
PatternMatch {
pattern: self.pattern.clone(),
root: self.root,
}
}
}
impl<U: Universe, PNode: NodeProperty> PatternMatch<Pattern<U, PNode, UnweightedEdge>, NodeIndex> {
pub fn as_ref(&self) -> PatternMatch<&Pattern<U, PNode, UnweightedEdge>, NodeIndex> {
PatternMatch {
pattern: &self.pattern,
root: self.root,
}
}
pub fn to_match_map<G: LinkView + Copy>(&self, graph: G) -> Option<HashMap<U, NodeIndex>> {
self.as_ref().to_match_map(graph)
}
}
impl<'p, U: Universe, PNode: NodeProperty>
PatternMatch<&'p Pattern<U, PNode, UnweightedEdge>, NodeIndex>
{
pub fn to_match_map<G: LinkView + Copy>(&self, graph: G) -> Option<HashMap<U, NodeIndex>> {
Some(
SinglePatternMatcher::from_pattern(self.pattern.clone())
.get_match_map(self.root, always_true, validate_unweighted_edge(graph))?
.into_iter()
.collect(),
)
}
}
impl PatternMatch<PatternID, NodeIndex> {
pub fn to_match_map<G, M, U>(&self, graph: G, matcher: &M) -> Option<HashMap<U, NodeIndex>>
where
G: LinkView + Copy,
M::PNode: NodeProperty,
M: PortMatcher<G, NodeIndex, U, PEdge = UnweightedEdge>,
U: Universe,
{
PatternMatch::new(matcher.get_pattern(self.pattern)?, self.root).to_match_map(graph)
}
}