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}