Stress Majorization
This example demonstrates how to use the Stress Majorization layout algorithm.
Basic Stress Majorization Example
import networkx as nx
import egraph as eg
import matplotlib.pyplot as plt
# Create a graph from NetworkX
nx_graph = nx.les_miserables_graph()
graph = eg.Graph()
indices = {}
for u in nx_graph.nodes:
indices[u] = graph.add_node(u)
for u, v in nx_graph.edges:
graph.add_edge(indices[u], indices[v], (u, v))
# Create an initial drawing
drawing = eg.DrawingEuclidean2d.initial_placement(graph)
# Create a StressMajorization instance
sm = eg.StressMajorization(graph, drawing, lambda _: 100)
# Set convergence parameters
sm.epsilon = 1e-4 # Convergence threshold
sm.max_iterations = 200 # Maximum number of iterations
# Run the algorithm
sm.run(drawing)
# Extract node positions
pos = {u: (drawing.x(i), drawing.y(i)) for u, i in indices.items()}
# Visualize with NetworkX
nx.draw(nx_graph, pos)
Using a Distance Matrix
For more control, you can create a StressMajorization instance from a distance matrix:
# Create a distance matrix
distance_matrix = eg.DistanceMatrix(graph)
# Optionally, modify distances
for i in range(graph.node_count()):
for j in range(i + 1, graph.node_count()):
# Set custom distances
distance = distance_matrix.get(i, j)
# Modify the distance if needed
distance_matrix.set(i, j, distance)
distance_matrix.set(j, i, distance) # For undirected graphs
# Create a StressMajorization instance from the distance matrix
sm = eg.StressMajorization.with_distance_matrix(drawing, distance_matrix)
# Run the algorithm
sm.run(drawing)
Applying a Single Iteration
You can also apply a single iteration of the algorithm and check the stress value:
# Create a fresh drawing for this example
drawing_fresh = eg.DrawingEuclidean2d.initial_placement(graph)
sm_fresh = eg.StressMajorization(graph, drawing_fresh, lambda _: 100)
# Apply a single iteration
stress = sm_fresh.apply(drawing_fresh)
# Apply multiple iterations manually
for i in range(10):
stress = sm_fresh.apply(drawing_fresh)