-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Dorogovtsev-Goltsev-Mendes graph generator (#1206)
* Add DGM graph generator to rustworkx-core * Add DGM graph generator to Python library * Change parameter t to n (state to transitions) * Add rust tests and docs * Add stubs and release notes * Improve python tests
- Loading branch information
Showing
7 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
releasenotes/notes/dorogovtsev-goltsev-mendes-generator-d7fd575b693bd652.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
features: | ||
- | | ||
Added :func:`rustworkx.generators.dorogovtsev_goltsev_mendes_graph` that generates | ||
deterministic scale-free graphs using the Dorogovtsev-Goltsev-Mendes iterative procedure. | ||
- | | ||
Added to rustworkx-for ``generators::dorogovtsev_goltsev_mendes_graph`` function that generates, | ||
deterministic scale-free graphs using the Dorogovtsev-Goltsev-Mendes iterative procedure. |
130 changes: 130 additions & 0 deletions
130
rustworkx-core/src/generators/dorogovtsev_goltsev_mendes_graph.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
// not use this file except in compliance with the License. You may obtain | ||
// a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
use petgraph::{data::Create, visit::Data}; | ||
|
||
use super::InvalidInputError; | ||
|
||
/// Generate a Dorogovtsev-Goltsev-Mendes graph | ||
/// | ||
/// Generate a graph following the recursive procedure in [1]. | ||
/// Starting from the two-node, one-edge graph, iterating `n` times generates | ||
/// a graph with `(3**n + 3) // 2` nodes and `3**n` edges. | ||
/// | ||
/// | ||
/// Arguments: | ||
/// | ||
/// * `n` - The number of iterations to perform. n=0 returns the two-node, one-edge graph. | ||
/// * `default_node_weight` - A callable that will return the weight to use for newly created nodes. | ||
/// * `default_edge_weight` - A callable that will return the weight object to use for newly created edges. | ||
/// | ||
/// # Example | ||
/// ```rust | ||
/// use rustworkx_core::petgraph; | ||
/// use rustworkx_core::generators::dorogovtsev_goltsev_mendes_graph; | ||
/// use rustworkx_core::petgraph::visit::EdgeRef; | ||
/// | ||
/// let g: petgraph::graph::UnGraph<(), ()> = dorogovtsev_goltsev_mendes_graph(2, || (), || ()).unwrap(); | ||
/// assert_eq!(g.node_count(), 6); | ||
/// assert_eq!( | ||
/// vec![(0, 1), (0, 2), (1, 2), (0, 3), (1, 3), (0, 4), (2, 4), (1, 5), (2, 5)], | ||
/// g.edge_references() | ||
/// .map(|edge| (edge.source().index(), edge.target().index())) | ||
/// .collect::<Vec<(usize, usize)>>(), | ||
/// ); | ||
/// ``` | ||
/// | ||
/// .. [1] S. N. Dorogovtsev, A. V. Goltsev and J. F. F. Mendes | ||
/// “Pseudofractal scale-free web” | ||
/// Physical Review E 65, 066122, 2002 | ||
/// https://arxiv.org/abs/cond-mat/0112143 | ||
/// | ||
pub fn dorogovtsev_goltsev_mendes_graph<G, T, F, H, M>( | ||
n: usize, | ||
mut default_node_weight: F, | ||
mut default_edge_weight: H, | ||
) -> Result<G, InvalidInputError> | ||
where | ||
G: Create + Data<NodeWeight = T, EdgeWeight = M>, | ||
F: FnMut() -> T, | ||
H: FnMut() -> M, | ||
{ | ||
let n_edges = usize::pow(3, n as u32); | ||
let n_nodes = (n_edges + 3) / 2; | ||
let mut graph = G::with_capacity(n_nodes, n_edges); | ||
|
||
let node_0 = graph.add_node(default_node_weight()); | ||
let node_1 = graph.add_node(default_node_weight()); | ||
graph | ||
.add_edge(node_0, node_1, default_edge_weight()) | ||
.unwrap(); | ||
let mut current_endpoints = vec![(node_0, node_1)]; | ||
|
||
for _ in 0..n { | ||
let mut new_endpoints = vec![]; | ||
for (source, target) in current_endpoints.iter() { | ||
let new_node = graph.add_node(default_node_weight()); | ||
graph.add_edge(*source, new_node, default_edge_weight()); | ||
new_endpoints.push((*source, new_node)); | ||
graph.add_edge(*target, new_node, default_edge_weight()); | ||
new_endpoints.push((*target, new_node)); | ||
} | ||
current_endpoints.extend(new_endpoints); | ||
} | ||
Ok(graph) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::generators::dorogovtsev_goltsev_mendes_graph; | ||
use crate::petgraph::graph::Graph; | ||
use crate::petgraph::visit::EdgeRef; | ||
|
||
#[test] | ||
fn test_dorogovtsev_goltsev_mendes_graph() { | ||
for n in 0..6 { | ||
let graph: Graph<(), ()> = match dorogovtsev_goltsev_mendes_graph(n, || (), || ()) { | ||
Ok(graph) => graph, | ||
Err(_) => panic!("Error generating graph"), | ||
}; | ||
assert_eq!(graph.node_count(), (usize::pow(3, n as u32) + 3) / 2); | ||
assert_eq!(graph.edge_count(), usize::pow(3, n as u32)); | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_dorogovtsev_goltsev_mendes_graph_edges() { | ||
let n = 2; | ||
let expected_edge_list = vec![ | ||
(0, 1), | ||
(0, 2), | ||
(1, 2), | ||
(0, 3), | ||
(1, 3), | ||
(0, 4), | ||
(2, 4), | ||
(1, 5), | ||
(2, 5), | ||
]; | ||
let graph: Graph<(), ()> = match dorogovtsev_goltsev_mendes_graph(n, || (), || ()) { | ||
Ok(graph) => graph, | ||
Err(_) => panic!("Error generating graph"), | ||
}; | ||
assert_eq!( | ||
expected_edge_list, | ||
graph | ||
.edge_references() | ||
.map(|edge| (edge.source().index(), edge.target().index())) | ||
.collect::<Vec<(usize, usize)>>(), | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
import unittest | ||
|
||
import rustworkx | ||
|
||
|
||
class TestDorogovtsevGoltsevMendesGraph(unittest.TestCase): | ||
def test_dorogovtsev_goltsev_mendes_graph(self): | ||
for n in range(0, 6): | ||
with self.subTest(n=n): | ||
graph = rustworkx.generators.dorogovtsev_goltsev_mendes_graph(n) | ||
self.assertEqual(len(graph), (3**n + 3) // 2) | ||
self.assertEqual(len(graph.edges()), 3**n) | ||
self.assertTrue(rustworkx.is_planar(graph)) | ||
|
||
def test_dorogovstev_goltsev_mendes_graph_error(self): | ||
self.assertRaises(OverflowError, rustworkx.generators.dorogovtsev_goltsev_mendes_graph, -1) |