MCPcopy Index your code
hub / github.com/H4kor/graph-force

github.com/H4kor/graph-force @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
48 symbols 132 edges 9 files 2 documented · 4%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Graph Force

A python/rust library for embedding graphs in 2D space, using force-directed layouts.

Installation

pip install graph_force

Usage

The first parameter defines the number of nodes in graph. The second parameter is an iterable of edges, where each edge is a tuple of two integers representing the nodes it connects. Node ids start at 0.

import graph_force

edges = [(0, 1), (1, 2), (2, 3), (3, 0)]
pos = graph_force.layout_from_edge_list(4, edges)

Example with networkx

This library does not have a function to consume a networkx graph directly, but it is easy to convert it to an edge list.

import networkx as nx
import graph_force

G = nx.grid_2d_graph(10, 10)
# we have to map the names to integers
# as graph_force only supports integers as node ids at the moment
edges = []
mapping = {n: i for i, n in enumerate(G.nodes)}
i = 0
for edge in G.edges:
    edges.append((mapping[edge[0]], mapping[edge[1]]))

pos = graph_force.layout_from_edge_list(len(G.nodes), edges, iter=1000)
nx.draw(G, {n: pos[i] for n, i in mapping.items()}, node_size=2, width=0.1)

Example with edge file

This methods can be used with large graphs, where the edge list does not fit into memory.

Format of the file: - Little endian - 4 bytes: number of nodes(int) - 12 bytes: nodeA(int), nodeB(int), weight(float)

import graph_force
import struct

with open("edges.bin", "rb") as f:
    n = 10
    f.write(struct.pack("i", n))
    for x in range(n-1):
        f.write(struct.pack("iif", x, x+1, 1))

pos = graph_force.layout_from_edge_file("edges.bin", iter=50)

Options

iter, threads and model, initial_pos are optional parameters, supported by layout_from_edge_list and layout_from_edge_file.

pos = graph_force.layout_from_edge_list(
    number_of_nodes,
    edges,
    iter=500,  # number of iterations, default 500
    threads=0,  # number of threads, default 0 (all available)
    model="spring_model", # model to use, default "spring_model", other option is "networkx_model"
    initial_pos=[(0.4, 0.7), (0.7, 0.2), ...], # initial positions, default None (random)
)

Available models

Contributing

Extension points exported contracts — how you extend this code

ForceModel (Interface)
(no doc) [3 implementers]
src/model.rs

Core symbols most depended-on inside this repo

new_edge_matrix
called by 11
src/graph.rs
new_node_vector
called by 8
src/graph.rs
gen_chunks
called by 5
src/utils.rs
add_edge
called by 5
src/graph.rs
layout
called by 3
src/runner.rs
pick_model
called by 2
src/lib.rs
initial_pos_to_node_vector
called by 2
src/lib.rs
init
called by 2
src/spring_model.rs

Shape

Function 28
Method 13
Class 6
Interface 1

Languages

Rust88%
Python12%

Modules by API surface

src/runner.rs8 symbols
src/graph.rs8 symbols
src/spring_model.rs7 symbols
src/networkx_model.rs7 symbols
tests/test_e2e.py6 symbols
src/utils.rs5 symbols
src/lib.rs5 symbols
src/reader.rs1 symbols
src/model.rs1 symbols

For agents

$ claude mcp add graph-force \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact