A fast, lightweight and extensible implementation of a graph data structure.

Related tags

Graphics fast-graph
Overview

fast-graph

A fast, lightweight and extensible implementation of a graph data structure.

Crates.io docs.rs Discord chat Rust CI MSRV

Note

⚠️ There will be some breaking changes in the coming 1-2 weeks at the very least until version 1.0.0 arrives.

Lightweight & fast.

By default, SlotMaps are used to store the nodes and edges which solves the ABA problem while also providing O(1) insertion, deletion and lookup times.

Extensible & Generic

The Graph is generic over the node and edge data types. There's also traits for making even more customized graph-like data structures if the need arises.

Serde & Specta

There's optional features to enable [serde] & [specta] support.

Categories

The CategorizedGraph struct uses a hash map to map category names (String) to a category node (NodeID) (where the node's edges are the nodes belonging to the category). There's also some useful extra functions to query categories and their nodes, and a Categorized trait that can be implemented for a custom struct if needed.

In other words a simple extension to the graph that allows for efficient and easy grouping of nodes by strings.

Structure

Node - Struct representing a node in the graph. Contains a NodeID which is a key to the node in the slotmap, which has a generic data field and a list of edges.

Edge - Struct representing an edge in the graph. Contains an EdgeID which is a key to the edge in the slotmap, and two NodeIDs which are the nodes the edge connects (from & to). An edge can also have "data", which could be anything or nothing; for example the weight of the connection or a struct or enum representing something else.

GraphInterface - Trait defining methods to alter a graph, i.e. adding, removing, and editing nodes and edges.

Graph - The default graph struct which implements GraphInterface. It only contains two slotmaps, one for nodes and one for edges.

Categorized - Trait that extends the Graph with category specific methods.

CategorizedGraph - A graph with categories. Categories are normal nodes (which can contain edges & data), but the graph also contains a hashmap that maps category names to category nodes for easy access.

Roadmap

Check out the ROADMAP.md file

Examples

Simple Graph and the ABA problem.

use fast_graph::{Graph, Node, Edge};
/* We need to have this trait in scope: */
use fast_graph::{GraphInterface};

#[derive(Debug)]
struct EdgeData(String);

#[derive(Debug)]
struct NodeData(String);

let mut graph: Graph<NodeData, EdgeData> = Graph::new();

let node1 = graph.add_node(NodeData("Node 1".into()));
let node2 = graph.add_node(NodeData("Node 2".into()));
let edge1 = graph.add_edge(node1.id, node2.id, EdgeData("Edge 1".into()));

assert_eq!(graph.node(node1.id).unwrap().id, node1.id);
assert_eq!(graph.edge(edge1.id).unwrap().id, edge1.id);

graph.remove_node(node1.id).unwrap();

// Since we just removed node 1, it should be None now.
assert_eq!(graph.node(node1.id), None);
// And node 2 still points to node 2.
assert_eq!(graph.node(node2.id).unwrap().id, node2.id);

println!("{:#?}", graph);
use fast_graph::*;

#[derive(Clone, Debug, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
enum NodeData {
    Number(u32),
    CategoryData(String),
    #[default]
    None,
}

let mut graph: CategorizedGraph<NodeData, ()> = CategorizedGraph::new();

let node1 = graph.add_node(NodeData::Number(1)).id;
let node2 = graph.add_node(NodeData::Number(2)).id;
let node3 = graph.add_node(NodeData::Number(3)).id;

let category1 = graph.create_category("Category 1", vec![node1, node2],
    NodeData::CategoryData("Category 1".into())
).unwrap();

assert_eq!(graph.category("Category 1").unwrap().connections.len(), 2);

// The category node should have the same data as the one we passed in.
let category1_data = graph.category("Category 1").unwrap().data;
if let NodeData::CategoryData(category1_name) = category1_data {
   assert_eq!(category1_name, "Category 1".to_string());
}

// Adding to a category that doesn't exist will create it. 
let category2 = graph.add_to_category("Category 2", vec![node2]);
assert_eq!(graph.all_categories().len(), 2);

// Adding to the same category twice will return the same category node.
let category2_1 = graph.add_to_category("Category 2", vec![node3]);
assert_eq!(graph.all_categories().len(), 2);
assert_eq!(category2, category2_1);

// The "Category 2" node should have two connections, one to node2 and one to node3.
let category2_node = graph.category("Category 2").unwrap();
assert_eq!(
// this:
    category2_node.connections.iter()
        .map(|edge_id|
            graph.edge(*edge_id).unwrap().to
        )
        .collect::<Vec<NodeID>>(),
// should equal:
    vec![node2, node3]
);

// Creating a category twice will error.
assert!(
    graph.create_category("Category 1",
        vec![node3], NodeData::CategoryData("Category 1".into())
    ).is_err()
);
You might also like...
Simple, performant graph generator for Feynman diagrams* ⚛️
Simple, performant graph generator for Feynman diagrams* ⚛️

Feynman diagram generator ⚛️ A simple generator of "Feynman diagram" permutations (as defined by problem 781). Incrementally builds isomorphically uni

Pathfinding library for calculating all node pairs' shortest paths in an unweighted undirected graph.

bit_gossip bit_gossip, named after its implementation technique, is a simple pathfinding library for calculating all node pairs' shortest paths in an

Small, lightweight and fast library for rendering text with wgpu.

wgpu-text wgpu-text is a wrapper over glyph-brush for fast and easy text rendering in wgpu. This project was inspired by and is similar to wgpu_glyph,

svgcleaner could help you to clean up your SVG files from the unnecessary data.

svgcleaner svgcleaner helps you clean up your SVG files, keeping them free from unnecessary data. Table of Contents Purpose Goals Alternatives Charts

Compact, efficient data structures in contiguous byte arrays

Sokoban Compact, efficient data structures in contiguous byte arrays. Benchmarks Based on simple benchmarks, the naive performance of Sokoban data str

A cool, fast maze generator and solver written in Rust
A cool, fast maze generator and solver written in Rust

MazeCruncher Welcome to maze cruncher! Download Standalone Here Usage To get started, just run the standalone .exe in target/release or compile and ru

A fast isosurface extraction algorithm.
A fast isosurface extraction algorithm.

fast-surface-nets A fast, chunk-friendly implementation of Naive Surface Nets on regular grids. Surface Nets is an algorithm for extracting an isosurf

Baryon is a compact 3D engine focused on fast prototyping in code.
Baryon is a compact 3D engine focused on fast prototyping in code.

baryon Baryon is a compact 3D engine focused on fast prototyping in code. No big dependencies, no fancy run-times, GUI editors, or other magic. Depend

Native WebGPU implementation based on gfx-hal
Native WebGPU implementation based on gfx-hal

This is an active GitHub mirror of the WebGPU implementation in Rust, which now lives in "gfx/wgpu" of Mozilla-central. Issues and pull requests are a

Comments
  • Cleanup Specta integration

    Cleanup Specta integration

    Changes:

    • Don't depend on tauri-specta, specta is enough and means this crate is compatible with any Specta compatible library (rspc, taurpc, Tauri Specta)
    • cfg attribute on module not export. This is so when the Specta feature isn't enabled the crate doesn't try and import Specta.
    • Remove pub use specta_derives::*. Implementations don't need to be publically exposed to work.
    • Import rest of crate into specta_derives module so it can refer to the crates types.
    opened by oscartbeaumont 1
  • refactor/smallish-refactoring-and-documentation-improvements

    refactor/smallish-refactoring-and-documentation-improvements

    Breaking changes

    • None, hopefully.

    Description

    • Moved a really big specta impl (expanded a derive) into a separate file and improved some documentation.
    opened by henke443 0
Owner
Henrik
Henrik
A simple and elegant, pipewire graph editor

pw-viz A simple and elegant, pipewire graph editor This is still a WIP, node layouting is kinda jank at the moment. Installation A compiled binary is

null 180 Dec 27, 2022
Theorem relational dependencies automatic extraction and visualization as a graph for Lean4.

Lean Graph Interactive visualization of dependencies for any theorem/definitions in your Lean project. How to use In your browser: lean-graph.com Or r

Patrik Číhal 8 Jan 3, 2024
GraphScope: A One-Stop Large-Scale Graph Computing System from Alibaba

A One-Stop Large-Scale Graph Computing System from Alibaba GraphScope is a unified distributed graph computing platform that provides a one-stop envir

Alibaba 2.2k Jan 1, 2023
A graph library for Rust.

Gamma A graph library for Rust. Gamma provides primitives and traversals for working with graphs. It is based on ideas presented in A Minimal Graph AP

Metamolecular, LLC 122 Dec 29, 2022
Simple but powerful graph library for Rust

Graphlib Graphlib is a simple and powerful Rust graph library. This library attempts to provide a generic api for building, mutating and iterating ove

Purple Protocol 177 Nov 22, 2022
🦀 Rust Graph Routing runtime for Apollo Federation 🚀

Apollo Router The Apollo Router is a configurable, high-performance graph router for a federated graph. Getting started Follow the quickstart tutorial

Apollo GraphQL 502 Jan 8, 2023
A graph crate with simplicity in mind

A graph crate with simplicity in mind. Prepona aims to be simple to use (for users of the crate) and develop further (for contributors). Nearly every

Mohamad Amin Rayej 80 Dec 15, 2022
Graph API client writen in Rust

graph-rs Now available on stable Rust at crates.io graph-rs-sdk = "0.1.0" 0.1.0 and above use stable Rust. Anything before 0.1.0 uses nightly Rust. M

Sean Reeise 56 Jan 3, 2023
Rust library for of graph ensembles

Rust library for random graph ensembles Minimal Rust version: 1.55.0 Implements simple sampling and monte carlo (or rather markov-) steps, that can be

Yannick Feld 2 Dec 14, 2022
A Graph implemented using nothing but `Vec`s in rust

VecGraph A Graph implemented using nothing but Vecs in rust. Details The graph is implemented using two Vecs: nodes and edges. nodes stores "nodes". w

null 1 Jan 27, 2022