Skip to main content

sbm_game

Function sbm_game 

Source
pub fn sbm_game(
    pref_matrix: &[Vec<f64>],
    block_sizes: &[u32],
    directed: bool,
    loops: bool,
    multiple: bool,
    seed: u64,
) -> IgraphResult<Graph>
Expand description

Generate a random graph from the Stochastic Block Model.

Each pair (u, v) is sampled with probability pref_matrix[block(u)][block(v)] (!multiple mode) or with Pascal-distributed multiplicity (multiple mode). Sampling happens block-pair by block-pair using the Batagelj–Brandes geometric-skip algorithm — total cost is O(n + m + k²).

  • pref_matrixk × k preference matrix. Each row must have the same length as the outer vector. In !multiple mode every entry must lie in [0, 1]; in multiple mode every entry must be a non-negative finite real.
  • block_sizes — length-k vector of per-block vertex counts. The resulting graph has n = block_sizes.iter().sum() vertices.
  • directed — generate a directed graph. When false, pref_matrix must be symmetric.
  • loops — allow self-loop edges.
  • multiple — switch to multigraph semantics (pref entries are expected multiplicities, not probabilities).
  • seed — initialises an internal SplitMix64 PRNG.

§Errors

Returns IgraphError::InvalidArgument if:

  • a row of pref_matrix has the wrong length,
  • block_sizes.len() != pref_matrix.len(),
  • any pref-matrix entry is non-finite,
  • any entry is outside [0, 1] when !multiple,
  • any entry is negative when multiple,
  • pref_matrix is not symmetric when !directed,
  • sum(block_sizes) overflows u32.

§Examples

use rust_igraph::sbm_game;

// Two equally-sized blocks: dense inside, sparse between.
let pref = vec![vec![0.2, 0.01], vec![0.01, 0.2]];
let sizes = vec![50, 50];
let g = sbm_game(&pref, &sizes, false, false, false, 42).unwrap();
assert_eq!(g.vcount(), 100);
// Expected ecount ≈ 0.2·(50·49/2) + 0.2·(50·49/2) + 0.01·(50·50)
//               = 245 + 245 + 25 = 515.
let m = g.ecount();
assert!((350..650).contains(&m), "ecount = {m}");