Skip to main content

Immutable graph library with 56+ algorithms, transformers, selectors, and lazy views

Project description

AlgoGraph

Immutable graph data structures and algorithms library with functional transformers, declarative selectors, and lazy views.

PyPI version Python 3.8+ License: MIT

Installation

pip install AlgoGraph

Overview

AlgoGraph provides immutable graph data structures with a clean, functional API. Version 2.0.0 brings AlgoTree-level API elegance with pipe-based transformers, declarative selectors, and lazy views—achieving ~90% code reduction for common operations.

Key Features

  • Immutable by default: All operations return new graph objects
  • 56+ algorithms: Traversal, shortest path, centrality, flow, matching, coloring
  • Pipe-based transformers: Composable operations with | operator (v2.0.0)
  • Declarative selectors: Pattern matching with logical operators (v2.0.0)
  • Lazy views: Memory-efficient filtering without copying (v2.0.0)
  • Fluent builder API: Construct graphs with 82% less code
  • Type-safe: Full type hints for IDE support
  • Optional AlgoTree integration: Convert between trees and graphs

Quick Start

from AlgoGraph import Graph, Vertex, Edge

# Create a graph
g = (Graph.builder()
     .add_vertex('A', age=30)
     .add_vertex('B', age=25)
     .add_edge('A', 'B', weight=5.0)
     .build())

# Query the graph
g.has_edge('A', 'B')  # True
g.neighbors('A')       # {'B'}

# Run algorithms
from AlgoGraph.algorithms import dijkstra, pagerank
distances = dijkstra(g, source='A')

Advanced Features (v2.0.0)

Transformer Pipelines

Compose graph operations using the | pipe operator:

from AlgoGraph.transformers import filter_vertices, largest_component, stats

# Filter → extract component → compute stats
result = (graph
    | filter_vertices(lambda v: v.get('active'))
    | largest_component()
    | stats())

# result: {'vertex_count': 42, 'edge_count': 156, 'density': 0.18, ...}

Available Transformers:

  • filter_vertices(pred), filter_edges(pred) - Filter by predicate
  • map_vertices(fn), map_edges(fn) - Transform attributes
  • reverse(), to_undirected() - Structure transformations
  • largest_component(), minimum_spanning_tree() - Algorithm-based
  • to_dict(), to_adjacency_list(), stats() - Export operations

Declarative Selectors

Query vertices and edges with logical operators:

from AlgoGraph.graph_selectors import vertex as v, edge as e

# Find active users with high degree
power_users = graph.select_vertices(
    v.attrs(active=True) & v.degree(min_degree=10)
)

# Find heavy edges from admin nodes
admin_edges = graph.select_edges(
    e.source(v.attrs(role='admin')) & e.weight(min_weight=100)
)

# Complex queries with OR, NOT, XOR
special = graph.select_vertices(
    (v.attrs(vip=True) | v.degree(min_degree=50)) & ~v.attrs(banned=True)
)

Selector Types:

  • vertex.id(pattern) - Match by ID (glob/regex)
  • vertex.attrs(**attrs) - Match attributes (supports callables)
  • vertex.degree(min/max/exact) - Match by degree
  • edge.weight(min/max/exact) - Match by weight
  • edge.source(selector), edge.target(selector) - Match endpoints

Lazy Views

Efficient filtering without copying data:

from AlgoGraph.views import filtered_view, neighborhood_view

# Create view without copying
view = filtered_view(
    large_graph,
    vertex_filter=lambda v: v.get('active'),
    edge_filter=lambda e: e.weight > 5.0
)

# Iterate lazily
for vertex in view.vertices():
    process(vertex)

# Materialize only when needed
small_graph = view.materialize()

# Explore k-hop neighborhood
local = neighborhood_view(graph, center='Alice', k=2)

View Types:

  • filtered_view() - Filter vertices/edges
  • subgraph_view() - View specific vertices
  • reversed_view() - Reverse edge directions
  • undirected_view() - View as undirected
  • neighborhood_view() - k-hop neighborhood

Core Classes

Vertex

from AlgoGraph import Vertex

v = Vertex('A', attrs={'value': 10, 'color': 'red'})
v2 = v.with_attrs(value=20)      # Immutable update
v3 = v.without_attrs('color')    # Remove attribute

Edge

from AlgoGraph import Edge

e = Edge('A', 'B', directed=True, weight=5.0)
e2 = e.with_weight(10.0)  # Immutable update
e3 = e.reversed()         # B -> A

Graph

from AlgoGraph import Graph, Vertex, Edge

# Direct construction
g = Graph({Vertex('A'), Vertex('B')}, {Edge('A', 'B')})

# Fluent builder
g = (Graph.builder()
     .add_vertex('A', age=30)
     .add_edge('A', 'B', weight=5.0)
     .add_path('B', 'C', 'D')
     .add_cycle('X', 'Y', 'Z')
     .build())

# From edges (auto-creates vertices)
g = Graph.from_edges(('A', 'B'), ('B', 'C'), ('C', 'A'))

# Immutable operations
g2 = g.add_vertex(Vertex('D'))
g3 = g.remove_vertex('A')
g4 = g.subgraph({'B', 'C', 'D'})

Algorithms

Traversal

from AlgoGraph.algorithms import dfs, bfs, topological_sort, has_cycle, find_path

visited = dfs(graph, start_vertex='A')
levels = bfs(graph, start_vertex='A')
order = topological_sort(graph)  # DAG only
path = find_path(graph, 'A', 'Z')

Shortest Paths

from AlgoGraph.algorithms import dijkstra, bellman_ford, floyd_warshall, a_star

distances = dijkstra(graph, source='A')
distances = bellman_ford(graph, source='A')  # Handles negative weights
all_pairs = floyd_warshall(graph)
path = a_star(graph, 'A', 'Z', heuristic=h)

Connectivity

from AlgoGraph.algorithms import (
    connected_components, strongly_connected_components,
    is_connected, is_bipartite, find_bridges, find_articulation_points
)

components = connected_components(graph)
scc = strongly_connected_components(graph)
bridges = find_bridges(graph)
articulation = find_articulation_points(graph)

Spanning Trees

from AlgoGraph.algorithms import minimum_spanning_tree, kruskal, prim

mst = minimum_spanning_tree(graph)
mst = kruskal(graph)
mst = prim(graph, start='A')

Centrality

from AlgoGraph.algorithms import (
    pagerank, betweenness_centrality, closeness_centrality,
    degree_centrality, eigenvector_centrality
)

pr = pagerank(social_network)
bc = betweenness_centrality(network)
cc = closeness_centrality(network)

Flow Networks

from AlgoGraph.algorithms import max_flow, min_cut, edmonds_karp

flow_value = max_flow(network, 'Source', 'Sink')
cut_value, source_set, sink_set = min_cut(network, 'Source', 'Sink')

Matching

from AlgoGraph.algorithms import hopcroft_karp, maximum_bipartite_matching, is_perfect_matching

matching = hopcroft_karp(bipartite_graph, left_set, right_set)
max_matching = maximum_bipartite_matching(graph, left, right)

Graph Coloring

from AlgoGraph.algorithms import welsh_powell, chromatic_number, dsatur, is_k_colorable

coloring = welsh_powell(graph)
num_colors = chromatic_number(graph)
coloring = dsatur(graph)  # Often better than greedy

Serialization

from AlgoGraph import save_graph, load_graph

# Save/load JSON
save_graph(graph, 'network.json')
graph = load_graph('network.json')

AlgoTree Integration (Optional)

from AlgoTree import Node, Tree
from AlgoGraph import tree_to_graph, graph_to_tree

# Tree to Graph
tree = Tree(Node('root', Node('child1'), Node('child2')))
graph = tree_to_graph(tree)

# Graph to Tree (extracts spanning tree)
tree = graph_to_tree(graph, root='root')

Interactive Shell

Explore graphs with a filesystem-like interface:

pip install AlgoGraph
algograph                    # Start with sample graph
algograph network.json       # Load from file
graph(5v):/$ ls
Alice/  [2 neighbors]
Bob/    [3 neighbors]

graph(5v):/$ cd Alice
graph(5v):/Alice$ ls
Attributes:
  age = 30
neighbors/  [2 vertices]

graph(5v):/Alice$ path Bob Eve
Path found: Alice -> Bob -> Diana -> Eve

Examples

Social Network Analysis

from AlgoGraph import Graph
from AlgoGraph.algorithms import pagerank, betweenness_centrality
from AlgoGraph.transformers import filter_vertices, stats
from AlgoGraph.graph_selectors import vertex as v

# Build network
network = (Graph.builder()
    .add_vertex('Alice', followers=1000)
    .add_vertex('Bob', followers=500)
    .add_vertex('Charlie', followers=2000)
    .add_edge('Alice', 'Bob', directed=False)
    .add_edge('Bob', 'Charlie', directed=False)
    .add_edge('Alice', 'Charlie', directed=False)
    .build())

# Find influencers
pr = pagerank(network)
top_influencer = max(pr, key=pr.get)

# Find power users with selector
power_users = network.select_vertices(
    v.attrs(followers=lambda f: f > 800)
)

# Analyze active subgraph
analysis = (network
    | filter_vertices(lambda v: v.get('followers', 0) > 500)
    | stats())

Road Network

from AlgoGraph import Graph
from AlgoGraph.algorithms import dijkstra, minimum_spanning_tree

roads = (Graph.builder()
    .add_edge('NYC', 'Boston', weight=215, directed=False)
    .add_edge('NYC', 'DC', weight=225, directed=False)
    .add_edge('Boston', 'DC', weight=440, directed=False)
    .build())

# Shortest routes from NYC
distances = dijkstra(roads, 'NYC')

# Minimum cost network
mst = minimum_spanning_tree(roads)

Design Philosophy

  1. Immutability: All operations return new objects
  2. Composability: Chain operations with | pipe operator
  3. Declarative: Express what, not how (selectors vs lambdas)
  4. Lazy evaluation: Views defer computation until needed
  5. Type safety: Full type hints throughout

Related Projects

  • AlgoTree: Tree data structures and algorithms
  • NetworkX: Comprehensive Python graph library (mutable)
  • graph-tool: High-performance graph analysis

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

algograph-2.1.0.tar.gz (90.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

algograph-2.1.0-py3-none-any.whl (70.7 kB view details)

Uploaded Python 3

File details

Details for the file algograph-2.1.0.tar.gz.

File metadata

  • Download URL: algograph-2.1.0.tar.gz
  • Upload date:
  • Size: 90.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for algograph-2.1.0.tar.gz
Algorithm Hash digest
SHA256 eec29673d2223088f6f63cc4851fc9655054725e4139da6115bab224252512ca
MD5 ec5828f8f7485ba3057022df28d85953
BLAKE2b-256 7f2d350816df9e3bc39924b3038b4cd943320949775c9a3ffea0e0f00b533fe9

See more details on using hashes here.

File details

Details for the file algograph-2.1.0-py3-none-any.whl.

File metadata

  • Download URL: algograph-2.1.0-py3-none-any.whl
  • Upload date:
  • Size: 70.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.3

File hashes

Hashes for algograph-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 43b4cc40148ffdc94ed1cec69c955a031cda8b61db4b5b42a83fc0e73a19e3b8
MD5 40036d119e9d1ef756ae838ef76320b1
BLAKE2b-256 245db4c2ba8f3a8bec69a4888289f0517c00095bfa1e0aeff5740ece5dd8f535

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page