topo-align / equilib /analytics.py
omesbah's picture
chore: initial commit for Hugging Face publication
8797abf
import numpy as np
def calculate_frustration_score(path_vertices):
"""
Analyzes the 'winding' of the Sperner Walk to detect topological frustration.
Frustration Score is defined as the ratio of Total Path Length to Net Displacement.
Interpretability:
- ~1.0: Perfect Alignment. The solver moved directly to the consensus.
- 1.5 - 3.0: Moderate Complexity. Non-linear trade-offs.
- > 3.0: High Topological Frustration. Objectives are conflicting or orthogonally opposed.
Args:
path_vertices (list of array-like): Sequence of points (centroids) visited by the solver.
Returns:
float: The Frustration Score. Returns 1.0 for short paths (<2 steps).
Returns 999.0 if net displacement is effectively zero (loop).
"""
if not path_vertices or len(path_vertices) < 2:
return 1.0
path = np.array(path_vertices)
# 1. Calculate total distance walked (sum of Euclidean steps)
diffs = path[1:] - path[:-1]
distances = np.linalg.norm(diffs, axis=1)
total_dist = np.sum(distances)
# 2. Calculate displacement (Start to Finish)
start = path[0]
end = path[-1]
displacement = np.linalg.norm(end - start)
# Avoid division by zero
if displacement < 1e-9:
return 999.0 # Loop detected or returned to start
# Ratio: How much did we wander?
frustration_index = total_dist / displacement
return float(frustration_index)