Skip to main content

Crate igraph

Crate igraph 

Source
Expand description

§igraph for Rust

Rust bindings to igraph, the fast and battle-tested C library for the analysis of complex networks, targeting igraph 1.0.1.

igraph implements hundreds of graph algorithms: generators (deterministic and random), shortest paths, centralities, community detection, layouts, flows and cuts, cliques, isomorphism, motifs, spectral methods, file formats and much more. This crate offers two layers on top of it:

  • raw FFI (ffi, also re-exported at the crate root): every function, type and constant of the C API, generated by bindgen from the installed headers at build time;
  • a Rusty API: safe methods, owned containers, Results, enums, options structs and named result structs, covering the public (non-deprecated) functions of the C headers module by module.
use igraph::prelude::*;

// Zachary's karate club, one of the famous graphs shipped with igraph.
let karate = Graph::famous("Zachary")?;
assert_eq!((karate.vcount(), karate.ecount()), (34, 78));

// The two leaders of the club are the most "in-between" members.
let btw = karate.betweenness(None, .., false, false)?;
let mut ranking: Vec<usize> = (0..btw.len()).collect();
ranking.sort_by(|&a, &b| btw[b].total_cmp(&btw[a]));
assert_eq!(&ranking[..2], &[0, 33]);

// Louvain community detection finds a strongly modular partition. It visits
// the vertices in random order: seed the generator for a reproducible result.
rng::seed(42)?;
let louvain = karate.community_multilevel(None, 1.0)?;
assert!(louvain.modularity() > 0.41);

§Design

The Rusty layer is built directly on the C types, not on wrappers around them: Graph is a type alias of igraph_t and the safe API is a set of inherent impl igraph_t blocks spread over the modules below. The same holds for the containers (Vector is igraph_vector_t, Matrix is igraph_matrix_t, and so on). Hence a value of the safe API can always be handed to a raw C function, and raw bindings and safe methods can be mixed freely when some corner of the C API is needed.

  • Ownership. Owned igraph objects (Graph, vectors, matrices, typed lists, StrVector, sparse matrices, …) release their C memory on Drop; Graph and the containers are Clone (deep copies) and Send. Struct fields of the raw C types are crate-private, so safe code cannot break their invariants.
  • Errors. Every fallible call returns a Result, whose Error carries an ErrorKind (mirroring igraph_error_t) and the message, source file and line reported by igraph; warnings are collected per thread and retrieved with take_warnings. igraph’s default error handler, which aborts the process, is replaced on every thread before its first call into igraph.
  • Per-thread state. igraph’s error handlers and default random number generator are thread-local. Each thread is initialized on its first call into the crate, and gets its own randomly seeded default RNG: seeding with rng::seed affects the calling thread only, and Rng::scoped runs a closure with an explicit generator. Tests running in parallel therefore never interfere. This relies on igraph being built thread-safe, i.e. with thread-local storage and its vendored ARPACK (see Installation).
  • Callbacks. Rust closures are accepted wherever igraph takes a callback (BFS/DFS visitors, clique, cycle and isomorphism enumeration, isomorphism compatibility functions, A* heuristics, ARPACK matrix-vector products, progress, status and interruption handlers, …). A panic inside a closure never unwinds through C: it is caught, igraph is asked to stop and clean up, and the panic resumes in Rust once the C function has returned. Returning ControlFlow::Break (or false where documented) stops the enumeration early.
  • Nesting. A closure passed to a function (an enumeration callback, a visitor, a compatibility function, a heuristic, a matrix-vector product, a filter) or installed as a progress, status or interruption handler through misc may itself call into igraph, including functions that take callbacks of their own, e.g. a BFS started from a clique visitor. Every closure runs in its own level of igraph’s cleanup (“finally”) stack: a nested call that fails just returns its Err to the closure, which may ignore it, and the computation that invoked the closure goes on unaffected. A panic in a nested closure unwinds to the enclosing closure, and from there, unless caught, to the outermost caller. Two kinds of computation keep global per-thread state and are therefore refused, with an error, when started while another one of the same kind runs on the thread: igraph’s Cliquer-based searches (see cliques), and ARPACK eigensolvers (the linalg solvers, eigenvector and hub and authority centralities, ARPACK PageRank and leading eigenvector communities).
  • Zero copy. Owned vectors dereference to slices; inputs are borrowed Rust slices (&[f64], &[i64], Option<&[f64]> for weights) passed to C through read-only views, without copying. Outputs come back as Vecs, Matrixes or named result structs.
  • Selectors. Functions working on a set of vertices or edges accept anything convertible into a VertexSelector or EdgeSelector: .. for all of them, a single id, a slice or Vec of ids, a range, or a structured selector such as “the neighbors of vertex 3”.
  • Enums and options. C constants become Rust enums (constants and module-specific ones); functions with many tuning knobs take an options struct whose Default follows igraph’s documented defaults, e.g. &FruchtermanReingoldOptions::default(). The igraph_edge_type_sw_t flags (which of self-loops and multi-edges a generator or a graphicality test may use) are the single bit-flag type constants::AllowedEdgeTypes, shared by games, constructors and mixing, and convertible from EdgeTypeSw.

Vertex and edge ids are i64 (VertexId, EdgeId, as igraph_int_t), counts are usize. Most programs only need use igraph::prelude::*;.

§A quick tour

§Building graphs

use igraph::prelude::*;

// From an edge list: a directed triangle with a pendant vertex.
let mut g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0), (2, 3)], 4, true)?;
g.add_edge(3, 0)?;
assert_eq!(g.ecount(), 5);
assert_eq!(g.neighbors(0, NeighborMode::Out)?, vec![1]);
assert_eq!(g.degree(.., NeighborMode::In, Loops::Twice)?, vec![2, 1, 1, 1]);

// Deterministic constructors: famous graphs, lattices, rings, trees...
let petersen = Graph::famous("Petersen")?;
let grid = Graph::square_lattice(&[3, 4], 1, false, false, None)?;
assert_eq!((petersen.vcount(), grid.ecount()), (10, 17));

// Errors carry a kind and igraph's own message.
let err = g.add_edge(0, 42).unwrap_err();
assert_eq!(err.kind(), ErrorKind::InvalidVertexId);

§Random graphs, reproducibly

use igraph::{games::BarabasiOptions, prelude::*};

let sample = || -> igraph::Result<Vec<(i64, i64)>> {
    rng::seed(42)?; // seeds the calling thread's default generator
    let g = Graph::erdos_renyi_game_gnm(100, 250, false, EdgeTypeSw::Simple, false)?;
    Ok(g.edge_list())
};
assert_eq!(sample()?, sample()?);

// A scale-free network grown by preferential attachment.
let ba = Graph::barabasi_game(1000, &BarabasiOptions::default().with_m(2))?;
assert_eq!(ba.vcount(), 1000);

§Paths and traversals

use igraph::{prelude::*, visitor::BfsOptions};
use std::ops::ControlFlow;

// A weighted "diamond": 0 → 1 → 3, 0 → 2 → 3 and the heavy shortcut 0 → 3.
let g = Graph::from_edges(&[(0, 1), (1, 3), (0, 2), (2, 3), (0, 3)], 4, true)?;
let w = [1.0, 1.0, 2.0, 2.0, 5.0];
let p = g.get_shortest_path(0, 3, Some(&w), NeighborMode::Out)?;
assert_eq!(p.vertices, vec![0, 1, 3]);
assert_eq!(g.distances(0, .., Some(&w), NeighborMode::Out)?.row(0), vec![0.0, 1.0, 2.0, 2.0]);

// Breadth-first search with a closure as visitor, stopped early.
let path = Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 4)], 5, false)?;
let mut seen = vec![];
path.bfs_with(&[0], &BfsOptions::default(), |v| {
    seen.push(v.vid);
    if v.dist == 2 { ControlFlow::Break(()) } else { ControlFlow::Continue(()) }
})?;
assert_eq!(seen, [0, 1, 2]);

Closures may call igraph again, and a failing nested call does not disturb the running search:

use igraph::prelude::*;
use std::ops::ControlFlow;

let g = Graph::famous("Petersen")?;
let (mut edge_cliques, mut errors) = (0, 0);
g.maximal_cliques_callback(.., |clique| {
    // A nested call that fails (vertex 99 does not exist) returns an `Err`...
    if g.neighbors(99, NeighborMode::All).is_err() {
        errors += 1;
    }
    // ...and a nested call that succeeds works as usual.
    let sub = g.induced_subgraph(clique, SubgraphImplementation::Auto).unwrap();
    if sub.ecount() == 1 { edge_cliques += 1; }
    ControlFlow::Continue(())
})?;
// The Petersen graph has no triangles: its 15 maximal cliques are its edges.
assert_eq!((edge_cliques, errors), (15, 15));

A panic inside such a closure is carried safely across the C code:

use igraph::{prelude::*, visitor::BfsOptions};
use std::ops::ControlFlow;

let g = Graph::famous("Petersen").unwrap();
let outcome = std::panic::catch_unwind(|| {
    g.bfs_with(&[0], &BfsOptions::default(), |v| -> ControlFlow<()> {
        if v.vid == 5 { panic!("boom") } else { ControlFlow::Continue(()) }
    })
});
assert!(outcome.is_err()); // the panic reached us, after igraph cleaned up
assert_eq!(g.vcount(), 10); // and the graph is still perfectly usable

§Centrality and communities

use igraph::{centrality::PageRankOptions, prelude::*};

let karate = Graph::famous("Zachary")?;
let pr = karate.pagerank(None, .., &PageRankOptions::default())?;
assert!((pr.scores.iter().sum::<f64>() - 1.0).abs() < 1e-9);

let closeness = karate.closeness(.., NeighborMode::All, None, true)?;
assert_eq!(closeness.len(), 34);

// Two cliques joined by a single edge: two communities, found by Louvain.
let mut edges = vec![];
for base in [0, 5] {
    for i in 0..5 {
        for j in i + 1..5 {
            edges.push((base + i, base + j));
        }
    }
}
edges.push((0, 5));
let g = Graph::from_edges(&edges, 10, false)?;
let clusters = g.community_multilevel(None, 1.0)?;
assert_eq!(clusters.membership, vec![0, 0, 0, 0, 0, 1, 1, 1, 1, 1]);
assert!((g.modularity(&clusters.membership, None, 1.0, false)? - 0.4524).abs() < 1e-4);

§Layouts

use igraph::{layout::FruchtermanReingoldOptions, prelude::*};

let g = Graph::famous("Petersen")?;
let circle = g.layout_circle(..)?; // one (x, y) row per vertex
assert_eq!(circle.shape(), (10, 2));
assert!(circle.rows().all(|p| (p[0].hypot(p[1]) - 1.0).abs() < 1e-12));

rng::seed(1)?; // force-directed layouts are randomized: seed for reproducibility
let fr = g.layout_fruchterman_reingold(&FruchtermanReingoldOptions::default())?;
assert_eq!(fr.shape(), (10, 2));

§Reading and writing graphs

use igraph::prelude::*;

let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0), (2, 3)], 4, true)?;
let text = g.write_graph_edgelist_to_string()?;
assert_eq!(text, "0 1\n1 2\n2 0\n2 3\n");
let h = Graph::read_graph_edgelist_from_str(&text, 0, true)?;
assert!(g.is_same_graph(&h)?);

The other formats are in foreign: NCOL, LGL, Pajek, GML, GraphML and DIMACS (read and write), DL and the graph database format (read only), DOT and LEDA (write only).

§Flows and isomorphism

use igraph::prelude::*;

// A small pipeline network from source 0 to sink 3.
let net = Graph::from_edges(&[(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)], 4, true)?;
let capacity = [3.0, 2.0, 1.0, 2.0, 3.0];
let mf = net.maxflow(0, 3, Some(&capacity))?;
assert_eq!(mf.value, 5.0);
// Max-flow = min-cut.
assert_eq!(mf.cut.iter().map(|&e| capacity[e as usize]).sum::<f64>(), mf.value);

// The Petersen graph is the generalized Petersen graph G(5, 2)...
let petersen = Graph::famous("Petersen")?;
assert!(petersen.isomorphic(&Graph::generalized_petersen(5, 2)?)?);
// ...and has 120 automorphisms.
assert_eq!(petersen.count_automorphisms(None)?, 120.0);

§Containers and raw calls

use igraph::prelude::*;

// Owned igraph vectors behave like Rust slices...
let mut v: VectorInt = (0..5).collect();
v.push(10);
assert_eq!(v.iter().sum::<i64>(), 20);
assert_eq!(Vec::from(v), vec![0, 1, 2, 3, 4, 10]);

// ...and borrowed slices are handed to C as read-only views, without copies.
let weights = [0.5, 1.5, 2.5];
let view = Vector::view(&weights);
assert_eq!(unsafe { igraph::igraph_vector_sum(view.as_ptr()) }, 4.5);

// A safe `Graph` is an `igraph_t`: raw functions accept it directly.
let g = Graph::famous("Petersen")?;
assert_eq!(unsafe { igraph::igraph_vcount(&g) }, 10);

§Module map

ModuleContentC headers
graphGraph (igraph_t), creation, editing, queries, property cacheigraph_interface.h, igraph_datatype.h
selectorvertex and edge selectorsigraph_iterators.h
errorError, ErrorKind, warnings, panic safety, per-thread setupigraph_error.h, igraph_setup.h
vectorowned vectors and zero-copy viewsigraph_vector.h, igraph_complex.h
matrixowned column-major matricesigraph_matrix.h
listtyped lists of vectors, matrices, graphsigraph_vector_list.h, igraph_matrix_list.h, igraph_graph_list.h
strvectorowned vectors of stringsigraph_strvector.h
bitsetfixed-size bit sets and lists of themigraph_bitset.h, igraph_bitset_list.h
rngper-thread random number generationigraph_random.h
constantsRust enums for the C constantsigraph_constants.h
adjlistadjacency and incidence listsigraph_adjlist.h
attributesgraph, vertex and edge attributesigraph_attributes.h
bipartitebipartite graphs, projections, matchingsigraph_bipartite.h, igraph_matching.h
centralitycentralities, centralization, scan statisticsigraph_centrality.h, igraph_scan.h
cliquescliques, independent sets, coloringsigraph_cliques.h, igraph_coloring.h
cocitationvertex similarity: cocitation, bibliographic coupling, Jaccard, Dice, inverse log-weightedigraph_cocitation.h
communitycommunity detection, modularity, HRGigraph_community.h, igraph_hrg.h
componentscomponents, cut vertices, separators, cohesion, reachability, neighborhoodsigraph_components.h, igraph_separators.h, igraph_cohesive_blocks.h, igraph_reachability.h, igraph_neighborhood.h
constructorsdeterministic generators, famous graphsigraph_constructors.h
conversionadjacency/Laplacian matrices, edge lists, Prüfer codes, (un)directedigraph_conversion.h
cyclesDAGs, cycle enumeration and bases, feedback sets, Eulerian pathsigraph_cycles.h, igraph_eulerian.h
flowmaximum flows, minimum cuts, connectivity, dominator treesigraph_flow.h
foreignreading and writing file formatsigraph_foreign.h
gamesrandom graph modelsigraph_games.h
isomorphismisomorphism, automorphisms, motifs, graphletsigraph_isomorphism.h, igraph_motifs.h, igraph_graphlets.h
layout2D and 3D layoutsigraph_layout.h
linalgsparse matrices, eigensolvers, spectral embeddingsigraph_sparsemat.h, igraph_arpack.h, igraph_lapack.h, igraph_blas.h, igraph_eigen.h, igraph_embedding.h
miscepidemics, spatial graphs, non-graph utilities, library hooksigraph_epidemics.h, igraph_spatial.h, igraph_nongraph.h, igraph_lsap.h, igraph_sampling.h, igraph_psumtree.h, igraph_version.h, igraph_progress.h, igraph_statusbar.h, igraph_interrupt.h
mixingtransitivity, assortativity, graphicalityigraph_transitivity.h, igraph_mixing.h, igraph_graphicality.h
operatorsunions, complements, subgraphs, rewiring, productsigraph_operators.h
pathsshortest paths, distances, eccentricity, random walksigraph_paths.h
structuraldegrees, density, reciprocity, spanning trees and other structural propertiesigraph_structural.h
visitorBFS and DFS with closures as visitorsigraph_visitor.h
tutorialthe igraph C tutorial, translated—
ffithe raw bindingsigraph.h

§Not wrapped

Every public, non-deprecated function of the headers above has a safe wrapper or a Rust equivalent (*_init/*_destroy pairs are constructors and Drop, selectors are built by selector, the variadic igraph_small and igraph_lcf_small take slices), except for a few families of C plumbing that have no use in Rust. They remain available, unsafe, in ffi:

  • C memory management: igraph_memory.h (igraph_malloc, igraph_calloc, igraph_realloc, igraph_free) and the untyped pointer vectors of igraph_vector_ptr.h. Rust owns its memory; the few places where igraph hands out such memory or pointer vectors are handled privately by the wrappers that need them.
  • C sorting: igraph_qsort.h (igraph_qsort, igraph_qsort_r); use slice::sort_by and friends.
  • Printing to C streams: the *printf, *fprint and *print functions of igraph_types.h (igraph_real_printf and family), igraph_complex.h, igraph_bitset.h, igraph_strvector.h and the containers. Use Display and Debug instead; vector::format_real formats a real number exactly like igraph does.
  • Variadic reporting: igraph_progressf and igraph_statusf, the printf-style variants of igraph_progress and igraph_status; use misc::progress and misc::status with format!.
  • Raising errors from C: igraph_errorf, igraph_errorvf, igraph_warning, igraph_warningf, igraph_fatal, igraph_fatalf and igraph_set_fatal_handler, meant for C code extending igraph. Rust code returns an Error instead; fatal errors (internal igraph bugs) keep igraph’s default handler, which aborts the process.

§Tutorial

The tutorial module translates the lessons of the igraph C tutorial:

  • lesson 1: create an Erdős–Rényi random graph, compute its diameter and mean degree;
  • lesson 2: build a periodic square lattice, measure its average path length, then add a few random edges and watch the paths shrink;
  • lesson 3: construct Zachary’s karate club and find its most central members by degree, closeness and betweenness.

Runnable use cases live in the examples/ directory, e.g. cargo run --example community_karate.

§Installation

The crate links against a shared build of igraph 1.0.1, the latest release. The crate’s version follows the igraph version it binds, so igraph 1.0.1 on the Rust side wraps igraph 1.0.1 on the C side. Build and install it with CMake:

wget https://github.com/igraph/igraph/releases/download/1.0.1/igraph-1.0.1.tar.gz
tar xf igraph-1.0.1.tar.gz
cd igraph-1.0.1
cmake -S . -B build -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release \
      -DIGRAPH_ENABLE_TLS=ON -DIGRAPH_USE_INTERNAL_ARPACK=ON \
      -DCMAKE_INSTALL_PREFIX=/usr/local
# Recent compilers (e.g. clang) may emit warnings that igraph turns into errors;
# add -DIGRAPH_WARNINGS_AS_ERRORS=OFF to the line above if the build stops.
cmake --build build --parallel
sudo cmake --install build   # or -DCMAKE_INSTALL_PREFIX=$HOME/.local and no sudo

Thread-local storage (IGRAPH_ENABLE_TLS, on by default whenever the compiler supports it) and the vendored ARPACK (the system ARPACK is not thread-safe) make igraph thread-safe, and this crate requires it: with a build lacking either of them, using igraph from several threads at once (which safe code may do, since Graph is Send) is a data race inside the C library. Every thread gets its own error handlers and random number generator, and cargo test runs tests in parallel. The configuration summary printed by CMake should show Thread-local storage: yes and ARPACK: vendored.

igraph also vendors its other dependencies (GMP, BLAS, LAPACK, GLPK, plfit), but CMake prefers system copies when it finds them; the IGRAPH_USE_INTERNAL_XXX options force either choice. Reading GraphML files needs libxml2 (libxml2-dev on Debian/Ubuntu and Alpine, brew install libxml2 on macOS).

The crate needs Rust 1.88 or newer (edition 2024). The bindings are generated by bindgen, which needs libclang (packages libclang-dev on Debian/Ubuntu, clang-dev on Alpine, Xcode command line tools on macOS; set LIBCLANG_PATH if it lives in a non-standard place).

The build script looks for igraph in /usr/local and then in ~/.local. Other locations are configured through environment variables:

VariableMeaning
IGRAPH_DIRinstallation prefix: headers in $IGRAPH_DIR/include/igraph, library in $IGRAPH_DIR/lib
IGRAPH_INCLUDE_DIRdirectory containing igraph.h (overrides the prefix)
IGRAPH_LIB_DIRdirectory containing libigraph.so/.dylib (overrides the prefix)

The library directory is embedded as an rpath in the crate’s own tests and examples, so they run without touching LD_LIBRARY_PATH. On ELF platforms (Linux, the BSDs) it is written as a DT_RPATH entry (the linker is passed --disable-new-dtags), which the dynamic loader searches before LD_LIBRARY_PATH: the library loaded at run time is the one found at the discovered prefix, i.e. the one whose headers generated the bindings, even when LD_LIBRARY_PATH points to another igraph build (ldd on a test binary shows which one is picked). Cargo does not forward that rpath to the programs of crates depending on this one: for them, install igraph where the dynamic loader looks (on Linux, /usr/local followed by sudo ldconfig) or set LD_LIBRARY_PATH (DYLD_LIBRARY_PATH on macOS). Then add the crate to your project:

[dependencies]
igraph = { git = "https://github.com/massimo-nocentini/igraph-rs" }

A Dockerfile building igraph 1.0.1 and the crate on Alpine Linux is provided as well (make docker-build, make docker-run).

§Testing and documentation

make test      # cargo test: unit, integration and documentation tests
make compile   # release build and tests
make doc       # cargo doc, copied into ./docs (served as GitHub pages)

Pass IGRAPH_DIR=... to make when igraph is installed elsewhere than /usr/local or ~/.local. The tests check known values from textbooks and from igraph’s own test suite, mathematical identities and seeded randomness.

§Safety notes

  • The safe API is sound under the usual Rust rules: owned igraph objects are freed exactly once, borrowed slices outlive the C calls they are lent to, and panics never cross the FFI boundary.
  • The raw bindings in ffi are unsafe and follow the C contracts: initialize before use, destroy exactly once, never call igraph_*_destroy on a value owned by a Rust wrapper (its Drop does it), and never build owned types over memory igraph does not own.
  • Always go through the crate once per thread before calling raw functions that may fail (any safe call does, e.g. rng::seed): it installs the error handler that turns igraph errors into Errors instead of aborting.
  • igraph’s attribute handler is process-wide, see attributes for how it is enabled.

§Publications

If you use igraph in research, please cite:

Csardi, G., & Nepusz, T. (2006). The igraph software package for complex network research. InterJournal, Complex Systems, 1695.

Antonov, M., Csárdi, G., Horvát, Sz., Müller, K., Nepusz, T., Noom, D., Salmon, M., Traag, V., Welles, B. F., & Zanini, F. (2023). igraph enables fast and robust network analysis across programming languages. arXiv:2311.10260.

Re-exports§

pub use error::Error;
pub use error::ErrorKind;
pub use error::Result;
pub use graph::EdgeId;
pub use graph::Graph;
pub use graph::VertexId;
pub use ffi::*;

Modules§

adjlist
Adjacency and incidence lists (igraph_adjlist.h).
attributes
Graph, vertex and edge attributes (igraph_attributes.h).
bipartite
Bipartite (two-mode) graphs and matchings (igraph_bipartite.h, igraph_matching.h).
bitset
Fixed-size sets of bits (igraph_bitset.h, igraph_bitset_list.h).
centrality
Centrality measures, graph centralization and local scan statistics (igraph_centrality.h, igraph_scan.h).
cliques
Cliques, independent vertex sets and vertex/edge colorings (igraph_cliques.h, igraph_coloring.h).
cocitation
Cocitation, bibliographic coupling and vertex similarity (igraph_cocitation.h).
community
Community detection, modularity, partition comparison and hierarchical random graphs (igraph_community.h, igraph_hrg.h).
components
Connectivity: connected components, cut vertices and bridges, vertex separators, cohesive blocks, reachability and neighborhoods.
constants
Rust enumerations for igraph’s C constants (igraph_constants.h).
constructors
Deterministic graph generators (igraph_constructors.h).
conversion
Conversion of graphs to matrices, edge lists, Prüfer sequences, and between directed and undirected graphs (igraph_conversion.h).
cycles
Graph cycles: acyclicity, topological orders, feedback sets, cycle enumeration, cycle bases and Eulerian paths.
error
Error handling: turning igraph error codes into Rust Results.
ffi
Raw FFI bindings to the igraph C library, generated by bindgen at build time from the installed headers.
flow
Maximum flows, minimum cuts and graph connectivity (igraph_flow.h).
foreign
Reading and writing graphs in foreign file formats (igraph_foreign.h).
games
Random graph generators, a.k.a. games (igraph_games.h).
graph
The Graph type and igraph’s basic interface (igraph_interface.h).
isomorphism
Graph isomorphism, motifs and graphlets (igraph_isomorphism.h, igraph_motifs.h, igraph_graphlets.h).
layout
Graph layouts: placing vertices in the plane or in 3D space (igraph_layout.h).
linalg
Linear algebra: sparse matrices, eigensolvers (ARPACK, LAPACK), BLAS helpers and spectral embeddings of graphs.
list
Owned typed lists (igraph_typed_list_pmt.h): VectorIntList, VectorList, MatrixList, GraphList and BitsetList.
matrix
Owned, column-major igraph matrices.
misc
Epidemics, spatial graphs, non-graph utilities and library-level hooks.
mixing
Clustering, degree correlations and graphicality: transitivity, assortativity, mixing matrices and degree-sequence realizability.
operators
Graph operators: unions, intersections, complements, subgraphs, simplification, rewiring and graph products (igraph_operators.h).
paths
Shortest paths, distances, eccentricity, efficiency, random walks and related path algorithms (igraph_paths.h).
prelude
The most commonly used types, traits and enums: use igraph::prelude::*;.
rng
Random number generation (igraph_random.h).
selector
Vertex and edge selectors.
structural
Basic structural properties of graphs (igraph_structural.h).
strvector
Owned vectors of strings (igraph_strvector_t, igraph_strvector.h).
tutorial
Translations of the igraph C tutorial into Rust.
vector
Owned igraph vectors that behave like Rust slices.
visitor
Breadth-first and depth-first traversals, with Rust closures as visitors (igraph_visitor.h).

Macros§

ffi_enum
Declares a Rust enum mirroring a C enum, together with From/TryFrom conversions to and from the raw type.
igraph_call
Calls an igraph function returning an igraph_error_t and converts the outcome into a Result<()>, making sure the calling thread is initialized first (see ensure_init).