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}