From da151176fe2a6628601b0dcc7c3beba26ac0fc4d Mon Sep 17 00:00:00 2001 From: Owen Troke-Billard Date: Mon, 16 Sep 2024 10:46:47 -0600 Subject: [PATCH] Change VF2++ to VF2 --- README.md | 23 +++++--------- src/builder.rs | 70 +++++++++++++++++++++---------------------- src/graph.rs | 4 +-- tests/isomorphisms.rs | 4 +-- 4 files changed, 47 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 8af69a2..27ec443 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# `gb_vf2pp` — VF2++ in Rust +# `vf2` — VF2 subgraph isomorphism algorithm in Rust -This crate implements the VF2++ subgraph isomorphism algorithm [1]. +This crate implements the VF2 subgraph isomorphism algorithm [1]. It can find [graph isomorphisms](https://en.wikipedia.org/wiki/Graph_isomorphism), [subgraph isomorphisms](https://en.wikipedia.org/wiki/Subgraph_isomorphism_problem), @@ -8,35 +8,28 @@ and [induced subgraph isomorphisms](https://en.wikipedia.org/wiki/Induced_subgra # Features -This is a work in progress. Some features are not yet implemented. - - [x] Enumerate graph isomorphisms - [x] Enumerate subgraph isomorphisms - [x] Enumerate induced subgraph isomorphisms -- [ ] Find minimum cost isomorphism - [x] Support directed graphs - [x] Support undirected graphs - [x] Support disconnected graphs - [x] Support node labels - [x] Support edge labels - [x] Graph trait -- [ ] Performance benchmarks -- [ ] Test databases -- [ ] Examples # Remaining work - [ ] Implement VF2 cutting rules -- [ ] Implement all of VF2++ (only VF2 implemented so far) # References -[1] A. Jüttner and P. Madarasi, -“VF2++—An improved subgraph isomorphism algorithm,” -Discrete Applied Mathematics, vol. 242, pp. 69–81, -Jun. 2018, doi: https://doi.org/10.1016/j.dam.2018.02.018. - -[2] L. P. Cordella, P. Foggia, C. Sansone, and M. Vento, +[1] L. P. Cordella, P. Foggia, C. Sansone, and M. Vento, “A (sub)graph isomorphism algorithm for matching large graphs,” IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 26, no. 10, pp. 1367–1372, Oct. 2004, doi: https://doi.org/10.1109/tpami.2004.75. + +[2] A. Jüttner and P. Madarasi, +“VF2++—An improved subgraph isomorphism algorithm,” +Discrete Applied Mathematics, vol. 242, pp. 69–81, +Jun. 2018, doi: https://doi.org/10.1016/j.dam.2018.02.018. diff --git a/src/builder.rs b/src/builder.rs index 9ab37de..d602a90 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,72 +1,72 @@ use crate::{Graph, Isomorphism, IsomorphismIter}; use std::fmt::Debug; -/// Creates a new [`Vf2ppBuilder`] to find +/// Creates a new [`Vf2Builder`] to find /// isomorphisms from `query` to `data`. /// /// Node and edge equality are not checked by default. /// Use [`node_eq`], [`edge_eq`], and [`default_eq`] /// on the builder to set equality functions. /// -/// [`node_eq`]: Vf2ppBuilder::node_eq -/// [`edge_eq`]: Vf2ppBuilder::edge_eq -/// [`default_eq`]: Vf2ppBuilder::default_eq +/// [`node_eq`]: Vf2Builder::node_eq +/// [`edge_eq`]: Vf2Builder::edge_eq +/// [`default_eq`]: Vf2Builder::default_eq pub fn isomorphisms<'a, Query, Data>( query: &'a Query, data: &'a Data, -) -> DefaultVf2ppBuilder<'a, Query, Data> +) -> DefaultVf2Builder<'a, Query, Data> where Query: Graph, Data: Graph, { - DefaultVf2ppBuilder::new(Problem::Isomorphism, query, data) + DefaultVf2Builder::new(Problem::Isomorphism, query, data) } -/// Creates a new [`Vf2ppBuilder`] to find +/// Creates a new [`Vf2Builder`] to find /// subgraph isomorphisms from `query` to `data`. /// /// Node and edge equality are not checked by default. /// Use [`node_eq`], [`edge_eq`], and [`default_eq`] /// on the builder to set equality functions. /// -/// [`node_eq`]: Vf2ppBuilder::node_eq -/// [`edge_eq`]: Vf2ppBuilder::edge_eq -/// [`default_eq`]: Vf2ppBuilder::default_eq +/// [`node_eq`]: Vf2Builder::node_eq +/// [`edge_eq`]: Vf2Builder::edge_eq +/// [`default_eq`]: Vf2Builder::default_eq pub fn subgraph_isomorphisms<'a, Query, Data>( query: &'a Query, data: &'a Data, -) -> DefaultVf2ppBuilder<'a, Query, Data> +) -> DefaultVf2Builder<'a, Query, Data> where Query: Graph, Data: Graph, { - DefaultVf2ppBuilder::new(Problem::SubgraphIsomorphism, query, data) + DefaultVf2Builder::new(Problem::SubgraphIsomorphism, query, data) } -/// Creates a new [`Vf2ppBuilder`] to find +/// Creates a new [`Vf2Builder`] to find /// induced subgraph isomorphisms from `query` to `data`. /// /// Node and edge equality are not checked by default. /// Use [`node_eq`], [`edge_eq`], and [`default_eq`] /// on the builder to set equality functions. /// -/// [`node_eq`]: Vf2ppBuilder::node_eq -/// [`edge_eq`]: Vf2ppBuilder::edge_eq -/// [`default_eq`]: Vf2ppBuilder::default_eq +/// [`node_eq`]: Vf2Builder::node_eq +/// [`edge_eq`]: Vf2Builder::edge_eq +/// [`default_eq`]: Vf2Builder::default_eq pub fn induced_subgraph_isomorphisms<'a, Query, Data>( query: &'a Query, data: &'a Data, -) -> DefaultVf2ppBuilder<'a, Query, Data> +) -> DefaultVf2Builder<'a, Query, Data> where Query: Graph, Data: Graph, { - DefaultVf2ppBuilder::new(Problem::InducedSubgraphIsomorphism, query, data) + DefaultVf2Builder::new(Problem::InducedSubgraphIsomorphism, query, data) } -/// A VF2++ builder. +/// A VF2 builder. #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct Vf2ppBuilder<'a, Query, Data, NodeEq, EdgeEq> { +pub struct Vf2Builder<'a, Query, Data, NodeEq, EdgeEq> { /// Problem type. problem: Problem, /// Query graph. @@ -79,11 +79,11 @@ pub struct Vf2ppBuilder<'a, Query, Data, NodeEq, EdgeEq> { edge_eq: Option, } -/// Default VF2++ builder type. +/// Default VF2 builder type. /// -/// This is [`Vf2ppBuilder`] with function pointers as +/// This is [`Vf2Builder`] with function pointers as /// the node and edge equality function types. -pub type DefaultVf2ppBuilder<'a, Query, Data> = Vf2ppBuilder< +pub type DefaultVf2Builder<'a, Query, Data> = Vf2Builder< 'a, Query, Data, @@ -91,12 +91,12 @@ pub type DefaultVf2ppBuilder<'a, Query, Data> = Vf2ppBuilder< fn(&::EdgeLabel, &::EdgeLabel) -> bool, >; -impl<'a, Query, Data> DefaultVf2ppBuilder<'a, Query, Data> +impl<'a, Query, Data> DefaultVf2Builder<'a, Query, Data> where Query: Graph, Data: Graph, { - /// Creates a new [`Vf2ppBuilder`] that does not check + /// Creates a new [`Vf2Builder`] that does not check /// node and edge equality. fn new(problem: Problem, query: &'a Query, data: &'a Data) -> Self { Self { @@ -109,21 +109,21 @@ where } } -impl<'a, Query, Data, NodeEq, EdgeEq> Vf2ppBuilder<'a, Query, Data, NodeEq, EdgeEq> +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, { - /// Configures VF2++ to use the [`PartialEq`] implementations + /// Configures VF2 to use the [`PartialEq`] implementations /// for node and edge equalities. - pub fn default_eq(self) -> DefaultVf2ppBuilder<'a, Query, Data> + pub fn default_eq(self) -> DefaultVf2Builder<'a, Query, Data> where Query::NodeLabel: PartialEq, Query::EdgeLabel: PartialEq, { - Vf2ppBuilder { + Vf2Builder { problem: self.problem, query: self.query, data: self.data, @@ -132,15 +132,15 @@ where } } - /// Configures VF2++ to use `node_eq` as the node equality function. + /// Configures VF2 to use `node_eq` as the node equality function. pub fn node_eq( self, node_eq: NewNodeEq, - ) -> Vf2ppBuilder<'a, Query, Data, NewNodeEq, EdgeEq> + ) -> Vf2Builder<'a, Query, Data, NewNodeEq, EdgeEq> where NewNodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool, { - Vf2ppBuilder { + Vf2Builder { problem: self.problem, query: self.query, data: self.data, @@ -149,15 +149,15 @@ where } } - /// Configures VF2++ to use `edge_eq` as the edge equality function. + /// Configures VF2 to use `edge_eq` as the edge equality function. pub fn edge_eq( self, edge_eq: NewEdgeEq, - ) -> Vf2ppBuilder<'a, Query, Data, NodeEq, NewEdgeEq> + ) -> Vf2Builder<'a, Query, Data, NodeEq, NewEdgeEq> where NewEdgeEq: Fn(&Query::EdgeLabel, &Data::EdgeLabel) -> bool, { - Vf2ppBuilder { + Vf2Builder { problem: self.problem, query: self.query, data: self.data, diff --git a/src/graph.rs b/src/graph.rs index e50fd44..a6c6264 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -24,13 +24,13 @@ pub trait Graph { /// Returns `true` if there is an edge from `source` to `target`. /// - /// If the graph is directed, the edge must must go from `source` to `target`. + /// If the graph is directed, the edge must go from `source` to `target`. /// If undirected, an edge must exist between `source` and `target`. fn contains_edge(&self, source: NodeIndex, target: NodeIndex) -> bool; /// Returns a reference to the label of the edge from `source` to `target`. /// - /// If the graph is directed, the edge must must go from `source` to `target`. + /// If the graph is directed, the edge must go from `source` to `target`. /// If undirected, the edge must be between `source` and `target`. fn edge_label(&self, source: NodeIndex, target: NodeIndex) -> Option<&Self::EdgeLabel>; } diff --git a/tests/isomorphisms.rs b/tests/isomorphisms.rs index 0fc2e64..befa7c6 100644 --- a/tests/isomorphisms.rs +++ b/tests/isomorphisms.rs @@ -261,9 +261,9 @@ fn isomorphisms_same_size() { vf2::isomorphisms(&query, &data).vec(); } -/// Tests that [`Debug`] is implemented for [`Vf2ppBuilder`]. +/// Tests that [`Debug`] is implemented for [`Vf2Builder`]. /// -/// [`Vf2ppBuilder`]: vf2::Vf2ppBuilder +/// [`Vf2Builder`]: vf2::Vf2Builder #[test] fn builder_debug() { let (query, data) = small_graphs::();