[][src]Crate net_ensembles

This lib is intended for scientific simulations

Example 1

use net_ensembles::{ErEnsembleC, EmptyNode, rand::SeedableRng};
use net_ensembles::traits::{WithGraph, SimpleSample, Dot};
use net_ensembles::{dot_options, dot_constants::*};
// Note: you might have to enable serde for rand_pcg
// to do that, write the following in your Cargo.toml:
// rand_pcg = { version = "*", features = ["serde1"]}
use rand_pcg::Pcg64;
use std::fs::File;

let rng = Pcg64::seed_from_u64(75676526);
// create graph with 50 vertices and target connectivity of 2.7
// using Pcg64 as random number generator
// NOTE: you can exchange `EmptyNode` with anything implementing the `Node` trait
let mut er = ErEnsembleC::<EmptyNode, _>::new(50, 2.7, rng);

// create dot file to visualize the graph
let mut f = File::create("50.dot")
                   .expect("Unable to create file");
// look at Dot trait
     "" // you do not have to use dot_options

// randomize the graph, uses SimpleSample trait

let mut f = File::create("50_1.dot")
                   .expect("Unable to create file");
    dot_options!(NO_OVERLAP, MARGIN_0)

// Note, you can also create a String this way:
let s =  er.graph().dot_string("");

To visualize, you can use something like

twopi 50.dot -Tpdf > 50.pdf
circo 50_1.dot -Tpdf > 50_1.pdf

You can also try some of the other roadmaps.

Example 2

You can also compute different measurable quantities, look at GenericGraph for more.

use net_ensembles::{traits::*, EmptyNode, ErEnsembleC};
use rand_pcg::Pcg64;
use rand::SeedableRng;

let rng = Pcg64::seed_from_u64(26);
// create graph with 50 vertices and target connectivity of 2.7
// using Pcg64 as random number generator
let er = ErEnsembleC::<EmptyNode, Pcg64>::new(50, 2.7, rng);
println!("Number of vertices: {}",      er.vertex_count());
println!("Number of edges: {}",         er.edge_count());
println!("Average degree: {}",          er.average_degree());
println!("connected components: {:?}",  er.connected_components());
println!("transitivity: {}",            er.transitivity());

Note: Also works for small-world ensemble, i.e. for SwEnsemble

Example 3

Simple sample for small-world ensemble

use net_ensembles::{SwEnsemble, EmptyNode};
use net_ensembles::traits::*; // I recommend always using this
use rand_pcg::Pcg64; //or whatever you want to use as rng
use rand::SeedableRng; // I use this to seed my rng, but you can use whatever
use std::fs::File;
use std::io::{BufWriter, Write};

let rng = Pcg64::seed_from_u64(1822);

// now create small-world ensemble with 100 nodes
// and a rewiring probability of 0.3 for each edge
let mut sw_ensemble = SwEnsemble::<EmptyNode, Pcg64>::new(100, 0.3, rng);

// setup file for writing
let f = File::create("simple_sample_sw.dat")
    .expect("Unable to create file");
let mut f = BufWriter::new(f);
f.write_all(b"#diameter bi_connect_max average_degree\n")

// simple sample for 10 steps
        let diameter = ensemble

        let bi_connect_max = ensemble.graph().clone()

        let average_degree = ensemble.graph()

        write!(f, "{} {} {}\n", diameter, bi_connect_max, average_degree)

// or just collect this into a vector to print or do whatever
let vec = sw_ensemble.simple_sample_vec(10,
        let diameter = ensemble.graph()

        let transitivity = ensemble.graph()
        (diameter, transitivity)
println!("{:?}", vec);

Example 4: Save and load

use net_ensembles::traits::*; // I recommend always using this
use serde_json;
use rand_pcg::Pcg64;
use net_ensembles::{ErEnsembleC, EmptyNode, rand::SeedableRng};
use std::fs::File;

let rng = Pcg64::seed_from_u64(95);
// create Erdős-Rényi ensemble
let ensemble = ErEnsembleC::<EmptyNode, Pcg64>::new(200, 3.1, rng);

#[cfg(feature = "serde_support")]
    // storing the ensemble in a file:

    let er_file = File::create("erC_save.dat")
          .expect("Unable to create file");

    // or serde_json::to_writer(er_file, &ensemble);
    serde_json::to_writer_pretty(er_file, &ensemble);

    // loading ensemble from file:

    let mut read = File::open("erC_save.dat")
        .expect("Unable to open file");

    let er: ErEnsembleC::<EmptyNode, Pcg64> = serde_json::from_reader(read).unwrap();

Example 5: Marcov Chain

use net_ensembles::{EmptyNode, ErEnsembleM, traits::*};
use rand_pcg::Pcg64;
use net_ensembles::rand::SeedableRng; // rand is reexported

// first create the ensemble
let rng = Pcg64::seed_from_u64(8745);
let mut e = ErEnsembleM::<EmptyNode, Pcg64>::new(30, 70, rng);

// ensure initial graph is connected
while !e.graph()
    .is_connected().unwrap() {

// Create marcov chain, e.g., of connected graphs
// only need to create step vector once
let mut steps = Vec::with_capacity(10);
for _ in 0..100 {
    e.m_steps(10, &mut steps);

    // reject, if the resulting graph is not connected
    if !e.graph().is_connected().unwrap() {
    // mesure whatever you want

Example 6: Define your own Data

use net_ensembles::{traits::*, rand::SeedableRng, SwEnsemble};
use rand_pcg::Pcg64;

#[cfg(feature = "serde_support")]
use serde::{Serialize, Deserialize};

#[derive(Clone, PartialEq)]
#[cfg_attr(feature = "serde_support", derive(Serialize, Deserialize))]
pub enum SirState{

impl SirState {
    fn setState(&mut self, state: Self) {
        *self = state;

impl Node for SirState {
    fn new_from_index(index: usize) -> Self {

// create the rng:
let rng = Pcg64::seed_from_u64(45);

let mut ensemble = SwEnsemble::<SirState, Pcg64>::new(10, 0.1, rng);

// you can access or change your additional information, e.g., at vertex 0

// you can also iterate over your additional information:
let count = ensemble
    .filter(|&state| *state == SirState::Susceptible)
assert!(count == 9);

// or count how many Susceptible nodes are connected to a specific node, i.e., to node 0
let s_count = ensemble
    .filter(|&state| *state == SirState::Susceptible)

println!("{}", s_count);

// or advance the states:
for state in ensemble.contained_iter_mut() {
    match *state {
        SirState::Infective     => { *state = SirState::Removed },
        _                       => { },


pub use sw::SwEnsemble;
pub use sw_graph::SwGraph;
pub use er_m::ErEnsembleM;
pub use er_c::ErEnsembleC;
pub use graph::Graph;
pub use generic_graph::GenericGraph;
pub use example_nodes::EmptyNode;
pub use traits::*;
pub use iter::IterWrapper;
pub use step_structs::*;
pub use rand;



constants for dot options


Erdős-Rényi ensemble with target connectivity


Erdős-Rényi with constant number of edges


Example nodes implementing trait Node


Generic implementation for Topology




Contains definitions of a few iterators. Not All of them though.


For sampling ensembles


Spacial ensemble


The structs returned by the mc steps


Small-world ensemble


Topology for SwEnsemble


You should use net_ensembles::traits::*



You can chain/combine options with the dot_options! macro:



Implements a Barabási-Albert Graph ensemble


Generate networks with a given degree distribution



Markov step of configuration model


Error messages


Result of undoing a step via Markov Chain method of ConfigurationModel