hypergraphx/
macros.rs

1/*
2    appellation: hypergraph <module>
3    authors: @FL03
4*/
5//! This module is heavily inspired by the `rshyper` crate.
6//!
7
8/// the [`hypergraph`] macro works to aide the in the creation of hypergraphs by allowing
9/// users to define nodes and edges in a hypergraph in a more declarative way.
10///
11/// ## Example
12///
13/// ### Basic Usage
14///
15/// The `hypergraph` macro allows you to define nodes and edges in a hypergraph
16///
17/// ```rust
18/// use hypergraph::prelude::*;
19/// // initialize a new undirected hypergraph
20/// let mut graph = UndirectedHypergraph::<usize, usize>::new();
21/// // use the macro to insert nodes and edges into the graph
22/// hypergraph! {
23///     graph {
24///         nodes: {
25///             let v0 = 0;
26///             let v1 = 1;
27///             let v2 = 10;
28///         };
29///         edges: {
30///             let e0: [v0, v1];
31///             [v0, v1, v2] = 10;
32///         };
33///     }
34/// }
35/// ```
36///
37/// or
38///
39/// ```rust
40/// use hypergraph::prelude::*;
41///
42/// // use the macro to initialize a new hypergraph, then insert nodes and edges
43/// hypergraph! {
44///     let mut graph: UndirectedHypergraph<usize, usize> {
45///         nodes: {
46///             let v0 = 0;
47///             let v1 = 1;
48///             let v2 = 2;
49///         };
50///         edges: {
51///             let e0: [v0, v1] = 5;
52///             let e1: [v0, v2] = 7;
53///             [v0, v1, v2] = 10;
54///         };
55///     }
56/// }
57#[cfg(feature = "macros")]
58#[macro_export]
59macro_rules! hypergraph {
60    (
61        let mut $graph:ident: $H:ty {
62            nodes: {$($nodes:tt)*};
63            edges: {$($edges:tt)*};
64        }
65    ) => {
66        // initialize a new hypergraph with the given type
67        let mut $graph: $H = <$H>::new();
68        // insert nodes into the graph
69        $crate::hypernode!($graph {$($nodes)*});
70        // insert edges into the graph
71        $crate::hyperedge!($graph {$($edges)*});
72    };
73    (
74        $graph:ident {
75            nodes: {$($nodes:tt)*};
76            edges: {$($edges:tt)*};
77        }
78    ) => {
79        // insert nodes into the graph
80        $crate::hypernode!($graph {$($nodes)*});
81        // insert edges into the graph
82        $crate::hyperedge!($graph {$($edges)*});
83    };
84}
85/// The `hyperedge` macro streamlines the definition of hyperedges in a hypergraph.
86///
87/// ## Usage
88///
89/// The macro requires that you to pass a mutable reference to some hypergraph by first
90/// defining the ident of the associated graph. Once declared, hyperedges are defined as `let`
91/// statement within a block, where each statement defines a hyperedge by its name and the
92/// vertices it connects. Instead of specifying the type of hyperedge, a slice of node indices
93/// is used to define the edge consituents.
94///
95/// Edges may be declared without a binding as well.
96///
97/// ```ignore
98/// hyperedge! {
99///     ${graph} {
100///         let ${edge_name}: [${vertex1}, ${vertex2}, ...] = ${weight};
101///     },
102///     ${graph} {
103///         [${vertex1}, ${vertex2}, ...] = ${weight};
104///     }
105/// }
106/// ```
107///
108
109#[cfg(feature = "macros")]
110#[macro_export]
111macro_rules! hyperedge {
112    ($src:ident {
113        $($(let $edge:ident:)? [$($var:ident),*] = $w:expr);* $(;)?
114    }) => {
115        // #[allow(unused_variables)]
116        $(
117            $crate::hyperedge!(@new $src$(.$edge:)? [$($var),*] = $w);
118        )*
119    };
120    // (@impl let $src:ident.$edge:ident: [$($var:ident),*] = $w:expr) => {
121    //     $crate::hyperedge!(@new let $src.$edge = [$($var),*] => $w);
122    // };
123    (@new $src:ident.$edge:ident: [$($var:ident),*] = $w:expr) => {
124        let $edge = $src.add_edge($w, vec![$($var),*]).expect("Failed to insert edge");
125    };
126    (@new $src:ident [$($var:ident),*] = $w:expr) => {
127        $src.add_edge($w, vec![$($var),*]).expect("Failed to insert edge");
128    };
129}
130/// the [`hypernode`] macro streamlines the process of inserting nodes into a hypergraph.
131///
132/// ## Usage
133///
134/// The macro requires that you to pass a mutable reference to some hypergraph by first
135/// defining the ident of the associated graph. Once declared, hypernodes are defined as `let`
136/// statement within a block, where each statement defines the identifier of a node.
137/// Optionally, a weight may be specified for the hypernode by appending `= <weight>`.
138///
139/// ```ignore
140/// hypernode! {
141///     $graph: {
142///         let $var:ident $(= $w:expr)?;
143///     }
144/// }
145/// ```
146///
147/// ### Example
148///
149/// ```rust
150/// use rshyper::HyperMap;
151/// // initialize a new, undirected hypergraph
152/// let mut graph = HyperMap::<usize, usize>::undirected();
153/// // use the macro to insert nodes into the graph
154/// rshyper::hypernode! {
155///     graph {
156///         let v0;
157///         let v1;
158///         let v2;
159///         let v3 = 1;
160///         let v4 = 2;
161///         let v5 = 3;
162///     }
163///  }
164/// ```
165#[cfg(feature = "macros")]
166#[macro_export]
167macro_rules! hypernode {
168    ($src:ident { $(let $var:ident = $w:expr);* $(;)? }) => {
169        $($crate::hypernode!(@new $src.$var = $w);)*
170    };
171    // (@impl $src:ident.$var:ident $(= $w:expr)?) => {
172    //     $crate::hypernode!(@new $src.$var $(= $w)?);
173    // };
174    (@new $src:ident.$var:ident = $w:expr) => {
175        let $var = $src.add_node($w);
176    };
177}