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
|
||||
[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.
|
||||
|
|
|
@ -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<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.
|
||||
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(&<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
|
||||
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<Data::NodeLabel>,
|
||||
Query::EdgeLabel: PartialEq<Data::EdgeLabel>,
|
||||
{
|
||||
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<NewNodeEq>(
|
||||
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<NewEdgeEq>(
|
||||
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,
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -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::<Directed>();
|
||||
|
|
Loading…
Reference in New Issue