Change VF2++ to VF2
This commit is contained in:
parent
8a4c88eff9
commit
da151176fe
23
README.md
23
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
|
It can find
|
||||||
[graph isomorphisms](https://en.wikipedia.org/wiki/Graph_isomorphism),
|
[graph isomorphisms](https://en.wikipedia.org/wiki/Graph_isomorphism),
|
||||||
[subgraph isomorphisms](https://en.wikipedia.org/wiki/Subgraph_isomorphism_problem),
|
[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
|
# Features
|
||||||
|
|
||||||
This is a work in progress. Some features are not yet implemented.
|
|
||||||
|
|
||||||
- [x] Enumerate graph isomorphisms
|
- [x] Enumerate graph isomorphisms
|
||||||
- [x] Enumerate subgraph isomorphisms
|
- [x] Enumerate subgraph isomorphisms
|
||||||
- [x] Enumerate induced subgraph isomorphisms
|
- [x] Enumerate induced subgraph isomorphisms
|
||||||
- [ ] Find minimum cost isomorphism
|
|
||||||
- [x] Support directed graphs
|
- [x] Support directed graphs
|
||||||
- [x] Support undirected graphs
|
- [x] Support undirected graphs
|
||||||
- [x] Support disconnected graphs
|
- [x] Support disconnected graphs
|
||||||
- [x] Support node labels
|
- [x] Support node labels
|
||||||
- [x] Support edge labels
|
- [x] Support edge labels
|
||||||
- [x] Graph trait
|
- [x] Graph trait
|
||||||
- [ ] Performance benchmarks
|
|
||||||
- [ ] Test databases
|
|
||||||
- [ ] Examples
|
|
||||||
|
|
||||||
# Remaining work
|
# Remaining work
|
||||||
|
|
||||||
- [ ] Implement VF2 cutting rules
|
- [ ] Implement VF2 cutting rules
|
||||||
- [ ] Implement all of VF2++ (only VF2 implemented so far)
|
|
||||||
|
|
||||||
# References
|
# References
|
||||||
|
|
||||||
[1] A. Jüttner and P. Madarasi,
|
[1] L. P. Cordella, P. Foggia, C. Sansone, and M. Vento,
|
||||||
“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,
|
|
||||||
“A (sub)graph isomorphism algorithm for matching large graphs,”
|
“A (sub)graph isomorphism algorithm for matching large graphs,”
|
||||||
IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 26, no. 10, pp. 1367–1372,
|
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.
|
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.
|
||||||
|
|
|
@ -1,72 +1,72 @@
|
||||||
use crate::{Graph, Isomorphism, IsomorphismIter};
|
use crate::{Graph, Isomorphism, IsomorphismIter};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
/// Creates a new [`Vf2ppBuilder`] to find
|
/// Creates a new [`Vf2Builder`] to find
|
||||||
/// isomorphisms from `query` to `data`.
|
/// isomorphisms from `query` to `data`.
|
||||||
///
|
///
|
||||||
/// Node and edge equality are not checked by default.
|
/// Node and edge equality are not checked by default.
|
||||||
/// Use [`node_eq`], [`edge_eq`], and [`default_eq`]
|
/// Use [`node_eq`], [`edge_eq`], and [`default_eq`]
|
||||||
/// on the builder to set equality functions.
|
/// on the builder to set equality functions.
|
||||||
///
|
///
|
||||||
/// [`node_eq`]: Vf2ppBuilder::node_eq
|
/// [`node_eq`]: Vf2Builder::node_eq
|
||||||
/// [`edge_eq`]: Vf2ppBuilder::edge_eq
|
/// [`edge_eq`]: Vf2Builder::edge_eq
|
||||||
/// [`default_eq`]: Vf2ppBuilder::default_eq
|
/// [`default_eq`]: Vf2Builder::default_eq
|
||||||
pub fn isomorphisms<'a, Query, Data>(
|
pub fn isomorphisms<'a, Query, Data>(
|
||||||
query: &'a Query,
|
query: &'a Query,
|
||||||
data: &'a Data,
|
data: &'a Data,
|
||||||
) -> DefaultVf2ppBuilder<'a, Query, Data>
|
) -> DefaultVf2Builder<'a, Query, Data>
|
||||||
where
|
where
|
||||||
Query: Graph,
|
Query: Graph,
|
||||||
Data: 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`.
|
/// subgraph isomorphisms from `query` to `data`.
|
||||||
///
|
///
|
||||||
/// Node and edge equality are not checked by default.
|
/// Node and edge equality are not checked by default.
|
||||||
/// Use [`node_eq`], [`edge_eq`], and [`default_eq`]
|
/// Use [`node_eq`], [`edge_eq`], and [`default_eq`]
|
||||||
/// on the builder to set equality functions.
|
/// on the builder to set equality functions.
|
||||||
///
|
///
|
||||||
/// [`node_eq`]: Vf2ppBuilder::node_eq
|
/// [`node_eq`]: Vf2Builder::node_eq
|
||||||
/// [`edge_eq`]: Vf2ppBuilder::edge_eq
|
/// [`edge_eq`]: Vf2Builder::edge_eq
|
||||||
/// [`default_eq`]: Vf2ppBuilder::default_eq
|
/// [`default_eq`]: Vf2Builder::default_eq
|
||||||
pub fn subgraph_isomorphisms<'a, Query, Data>(
|
pub fn subgraph_isomorphisms<'a, Query, Data>(
|
||||||
query: &'a Query,
|
query: &'a Query,
|
||||||
data: &'a Data,
|
data: &'a Data,
|
||||||
) -> DefaultVf2ppBuilder<'a, Query, Data>
|
) -> DefaultVf2Builder<'a, Query, Data>
|
||||||
where
|
where
|
||||||
Query: Graph,
|
Query: Graph,
|
||||||
Data: 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`.
|
/// induced subgraph isomorphisms from `query` to `data`.
|
||||||
///
|
///
|
||||||
/// Node and edge equality are not checked by default.
|
/// Node and edge equality are not checked by default.
|
||||||
/// Use [`node_eq`], [`edge_eq`], and [`default_eq`]
|
/// Use [`node_eq`], [`edge_eq`], and [`default_eq`]
|
||||||
/// on the builder to set equality functions.
|
/// on the builder to set equality functions.
|
||||||
///
|
///
|
||||||
/// [`node_eq`]: Vf2ppBuilder::node_eq
|
/// [`node_eq`]: Vf2Builder::node_eq
|
||||||
/// [`edge_eq`]: Vf2ppBuilder::edge_eq
|
/// [`edge_eq`]: Vf2Builder::edge_eq
|
||||||
/// [`default_eq`]: Vf2ppBuilder::default_eq
|
/// [`default_eq`]: Vf2Builder::default_eq
|
||||||
pub fn induced_subgraph_isomorphisms<'a, Query, Data>(
|
pub fn induced_subgraph_isomorphisms<'a, Query, Data>(
|
||||||
query: &'a Query,
|
query: &'a Query,
|
||||||
data: &'a Data,
|
data: &'a Data,
|
||||||
) -> DefaultVf2ppBuilder<'a, Query, Data>
|
) -> DefaultVf2Builder<'a, Query, Data>
|
||||||
where
|
where
|
||||||
Query: Graph,
|
Query: Graph,
|
||||||
Data: 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)]
|
#[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 type.
|
||||||
problem: Problem,
|
problem: Problem,
|
||||||
/// Query graph.
|
/// Query graph.
|
||||||
|
@ -79,11 +79,11 @@ pub struct Vf2ppBuilder<'a, Query, Data, NodeEq, EdgeEq> {
|
||||||
edge_eq: Option<EdgeEq>,
|
edge_eq: Option<EdgeEq>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
/// the node and edge equality function types.
|
||||||
pub type DefaultVf2ppBuilder<'a, Query, Data> = Vf2ppBuilder<
|
pub type DefaultVf2Builder<'a, Query, Data> = Vf2Builder<
|
||||||
'a,
|
'a,
|
||||||
Query,
|
Query,
|
||||||
Data,
|
Data,
|
||||||
|
@ -91,12 +91,12 @@ pub type DefaultVf2ppBuilder<'a, Query, Data> = Vf2ppBuilder<
|
||||||
fn(&<Query as Graph>::EdgeLabel, &<Data as Graph>::EdgeLabel) -> bool,
|
fn(&<Query as Graph>::EdgeLabel, &<Data as Graph>::EdgeLabel) -> bool,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
impl<'a, Query, Data> DefaultVf2ppBuilder<'a, Query, Data>
|
impl<'a, Query, Data> DefaultVf2Builder<'a, Query, Data>
|
||||||
where
|
where
|
||||||
Query: Graph,
|
Query: Graph,
|
||||||
Data: Graph,
|
Data: Graph,
|
||||||
{
|
{
|
||||||
/// Creates a new [`Vf2ppBuilder`] that does not check
|
/// Creates a new [`Vf2Builder`] that does not check
|
||||||
/// node and edge equality.
|
/// node and edge equality.
|
||||||
fn new(problem: Problem, query: &'a Query, data: &'a Data) -> Self {
|
fn new(problem: Problem, query: &'a Query, data: &'a Data) -> Self {
|
||||||
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
|
where
|
||||||
Query: Graph,
|
Query: Graph,
|
||||||
Data: Graph,
|
Data: Graph,
|
||||||
NodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool,
|
NodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool,
|
||||||
EdgeEq: Fn(&Query::EdgeLabel, &Data::EdgeLabel) -> 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.
|
/// for node and edge equalities.
|
||||||
pub fn default_eq(self) -> DefaultVf2ppBuilder<'a, Query, Data>
|
pub fn default_eq(self) -> DefaultVf2Builder<'a, Query, Data>
|
||||||
where
|
where
|
||||||
Query::NodeLabel: PartialEq<Data::NodeLabel>,
|
Query::NodeLabel: PartialEq<Data::NodeLabel>,
|
||||||
Query::EdgeLabel: PartialEq<Data::EdgeLabel>,
|
Query::EdgeLabel: PartialEq<Data::EdgeLabel>,
|
||||||
{
|
{
|
||||||
Vf2ppBuilder {
|
Vf2Builder {
|
||||||
problem: self.problem,
|
problem: self.problem,
|
||||||
query: self.query,
|
query: self.query,
|
||||||
data: self.data,
|
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<NewNodeEq>(
|
pub fn node_eq<NewNodeEq>(
|
||||||
self,
|
self,
|
||||||
node_eq: NewNodeEq,
|
node_eq: NewNodeEq,
|
||||||
) -> Vf2ppBuilder<'a, Query, Data, NewNodeEq, EdgeEq>
|
) -> Vf2Builder<'a, Query, Data, NewNodeEq, EdgeEq>
|
||||||
where
|
where
|
||||||
NewNodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool,
|
NewNodeEq: Fn(&Query::NodeLabel, &Data::NodeLabel) -> bool,
|
||||||
{
|
{
|
||||||
Vf2ppBuilder {
|
Vf2Builder {
|
||||||
problem: self.problem,
|
problem: self.problem,
|
||||||
query: self.query,
|
query: self.query,
|
||||||
data: self.data,
|
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<NewEdgeEq>(
|
pub fn edge_eq<NewEdgeEq>(
|
||||||
self,
|
self,
|
||||||
edge_eq: NewEdgeEq,
|
edge_eq: NewEdgeEq,
|
||||||
) -> Vf2ppBuilder<'a, Query, Data, NodeEq, NewEdgeEq>
|
) -> Vf2Builder<'a, Query, Data, NodeEq, NewEdgeEq>
|
||||||
where
|
where
|
||||||
NewEdgeEq: Fn(&Query::EdgeLabel, &Data::EdgeLabel) -> bool,
|
NewEdgeEq: Fn(&Query::EdgeLabel, &Data::EdgeLabel) -> bool,
|
||||||
{
|
{
|
||||||
Vf2ppBuilder {
|
Vf2Builder {
|
||||||
problem: self.problem,
|
problem: self.problem,
|
||||||
query: self.query,
|
query: self.query,
|
||||||
data: self.data,
|
data: self.data,
|
||||||
|
|
|
@ -24,13 +24,13 @@ pub trait Graph {
|
||||||
|
|
||||||
/// Returns `true` if there is an edge from `source` to `target`.
|
/// 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`.
|
/// If undirected, an edge must exist between `source` and `target`.
|
||||||
fn contains_edge(&self, source: NodeIndex, target: NodeIndex) -> bool;
|
fn contains_edge(&self, source: NodeIndex, target: NodeIndex) -> bool;
|
||||||
|
|
||||||
/// Returns a reference to the label of the edge from `source` to `target`.
|
/// 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`.
|
/// If undirected, the edge must be between `source` and `target`.
|
||||||
fn edge_label(&self, source: NodeIndex, target: NodeIndex) -> Option<&Self::EdgeLabel>;
|
fn edge_label(&self, source: NodeIndex, target: NodeIndex) -> Option<&Self::EdgeLabel>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,9 +261,9 @@ fn isomorphisms_same_size() {
|
||||||
vf2::isomorphisms(&query, &data).vec();
|
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]
|
#[test]
|
||||||
fn builder_debug() {
|
fn builder_debug() {
|
||||||
let (query, data) = small_graphs::<Directed>();
|
let (query, data) = small_graphs::<Directed>();
|
||||||
|
|
Loading…
Reference in New Issue