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        $(
116            $crate::hyperedge!(@new $src$(.$edge:)? [$($var),*] = $w);
117        )*
118    };
119    (@new $src:ident.$edge:ident: [$($var:ident),*] = $w:expr) => {
120        #[allow(unused_variables)]
121        let $edge = $src.add_edge($w, vec![$($var),*]).expect("Failed to insert edge");
122    };
123    (@new $src:ident [$($var:ident),*] = $w:expr) => {
124        $src.add_edge($w, vec![$($var),*]).expect("Failed to insert edge");
125    };
126    ($src:ident {
127        $($(let $edge:ident:)? ([$($var:ident),*] -> [$($dst:ident),*]) = $w:expr);* $(;)?
128    }) => {
129        $(
130            $crate::hyperedge!(@new $src$(.$edge:)? ([$($var),*] -> [$($dst),*]) = $w);
131        )*
132    };
133    (@new $src:ident.$edge:ident: ([$($var:ident),*] -> [$($dst:ident),*]) = $w:expr) => {
134        #[allow(unused_variables)]
135        let $edge = $src.add_edge($w, vec![$($var),*]).expect("Failed to insert edge");
136    };
137    (@new $src:ident ([$($var:ident),*] -> [$($dst:ident),*]) = $w:expr) => {
138        $src.add_edge($w, vec![$($var),*], vec![$($dst),*]).expect("Failed to insert edge");
139    };
140}
141/// the [`hypernode`] macro streamlines the process of inserting nodes into a hypergraph.
142///
143/// ## Usage
144///
145/// The macro requires that you to pass a mutable reference to some hypergraph by first
146/// defining the ident of the associated graph. Once declared, hypernodes are defined as `let`
147/// statement within a block, where each statement defines the identifier of a node.
148/// Optionally, a weight may be specified for the hypernode by appending `= <weight>`.
149///
150/// ```ignore
151/// hypernode! {
152///     $graph: {
153///         let $var:ident $(= $w:expr)?;
154///     }
155/// }
156/// ```
157///
158/// ### Example
159///
160/// ```rust
161/// use rshyper::HyperMap;
162/// // initialize a new, undirected hypergraph
163/// let mut graph = HyperMap::<usize, usize>::undirected();
164/// // use the macro to insert nodes into the graph
165/// rshyper::hypernode! {
166///     graph {
167///         let v0;
168///         let v1;
169///         let v2;
170///         let v3 = 1;
171///         let v4 = 2;
172///         let v5 = 3;
173///     }
174///  }
175/// ```
176#[cfg(feature = "macros")]
177#[macro_export]
178macro_rules! hypernode {
179    ($src:ident { $(let $var:ident = $w:expr);* $(;)? }) => {
180        $($crate::hypernode!(@new $src.$var = $w);)*
181    };
182    // (@impl $src:ident.$var:ident $(= $w:expr)?) => {
183    //     $crate::hypernode!(@new $src.$var $(= $w)?);
184    // };
185    (@new $src:ident.$var:ident = $w:expr) => {
186        let $var = $src.add_node($w);
187    };
188}