You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Niko Abeler 456e027824 version bump 10 months ago
.github/workflows adjust test action. 4 10 months ago
.vscode formatting 10 months ago
src initial position 10 months ago
tests initial position 10 months ago
.gitignore more tests + allowing generators as input 10 months ago
Cargo.lock version bump 10 months ago
Cargo.toml version bump 10 months ago install and dev 10 months ago readme update 10 months ago
pyproject.toml adjust test action. 2 10 months ago
requirements.txt more tests + allowing generators as input 10 months ago

Graph Force

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


pip install graph_force


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)


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(
    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