#!/usr/bin/env python3 """ Fix the 7-vertex analysis - check which vertices are actually used. """ import numpy as np import torch from ideal_poly_volume_toolkit.geometry import ( delaunay_triangulation_indices, triangle_volume_from_points_torch, ) from scipy.optimize import differential_evolution # Run a single good optimization def compute_volume(params): """Compute volume from spherical parameters.""" # Fixed vertices Z = [complex(0, 0), complex(1, 0)] # Add 4 parameterized vertices for i in range(4): theta = params[2*i] phi = params[2*i + 1] z = np.tan(theta/2) * np.exp(1j * phi) Z.append(z) Z_np = np.array(Z, dtype=np.complex128) try: idx = delaunay_triangulation_indices(Z_np) # Check if all 7 vertices are used vertices_used = set() for (i, j, k) in idx: vertices_used.update([i, j, k]) if len(vertices_used) < 7: return 1000.0 # Penalty if not all vertices used Z_torch = torch.tensor(Z_np, dtype=torch.complex128) total = 0 for (i, j, k) in idx: vol = triangle_volume_from_points_torch(Z_torch[i], Z_torch[j], Z_torch[k], series_terms=96) total += vol.item() return -total # Negative for minimization except: return 1000.0 # Penalty print("Running constrained optimization (all 7 vertices must be used)...") bounds = [(0.1, np.pi-0.1), (0, 2*np.pi)] * 4 result = differential_evolution( compute_volume, bounds, maxiter=200, popsize=20, seed=42 ) volume = -result.fun print(f"Optimal volume: {volume:.6f}") # Analyze the result Z = [complex(0, 0), complex(1, 0)] for i in range(4): theta = result.x[2*i] phi = result.x[2*i + 1] z = np.tan(theta/2) * np.exp(1j * phi) Z.append(z) print("\nVertex positions:") for i, z in enumerate(Z): print(f"z[{i}] = {z.real:+.4f} + {z.imag:+.4f}i") Z_np = np.array(Z, dtype=np.complex128) idx = delaunay_triangulation_indices(Z_np) # Check which vertices are used vertices_used = set() for (i, j, k) in idx: vertices_used.update([i, j, k]) print(f"\nVertices used: {sorted(vertices_used)}") print(f"Number of faces: {len(idx)}") # Count edges properly edges = set() for (a, b, c) in idx: edges.add(tuple(sorted([a, b]))) edges.add(tuple(sorted([b, c]))) edges.add(tuple(sorted([a, c]))) V = len(vertices_used) E = len(edges) F = len(idx) chi = V - E + F print(f"\nEuler characteristic: V - E + F = {V} - {E} + {F} = {chi}") # Vertex degrees degrees = [0] * 7 for edge in edges: if edge[0] < 7 and edge[1] < 7: degrees[edge[0]] += 1 degrees[edge[1]] += 1 print(f"Vertex degrees: {degrees}") # Volume Z_torch = torch.tensor(Z_np, dtype=torch.complex128) total_volume = 0 for (a, b, c) in idx: vol = triangle_volume_from_points_torch(Z_torch[a], Z_torch[b], Z_torch[c], series_terms=96) total_volume += vol.item() print(f"\nTotal volume: {total_volume:.6f}") print(f"Regular octahedron: ≈ 5.333") print(f"Ratio: {total_volume/5.333:.3f}")