"""Module for performing tutte embeddings""" import math from typing import Any import numpy as np from sage.all import Graph # type: ignore def tutte_embedding(g: Graph, outer: list[Any]) -> dict[Any, tuple[float, float]]: """Compute a Tutte embedding fixing outer on a convex polygon, solving for inner vertices.""" outer_set = set(outer) inner = [v for v in g.vertices() if v not in outer_set] pos: dict[Any, tuple[float, float]] = {} for i, v in enumerate(outer): angle = 2 * math.pi * i / len(outer) pos[v] = (math.cos(angle), math.sin(angle)) if not inner: return pos inner_idx = {v: i for i, v in enumerate(inner)} n = len(inner) A = np.zeros((n, n)) bx = np.zeros(n) by = np.zeros(n) for i, v in enumerate(inner): neighbors = g.neighbors(v) deg = len(neighbors) A[i, i] = 1.0 for w in neighbors: if w in inner_idx: A[i, inner_idx[w]] = -1.0 / deg else: bx[i] += pos[w][0] / deg by[i] += pos[w][1] / deg x = np.linalg.solve(A, bx) y = np.linalg.solve(A, by) for i, v in enumerate(inner): pos[v] = (float(x[i]), float(y[i])) return pos