Spaces:
Sleeping
Sleeping
File size: 5,712 Bytes
f9b644c 3bf2012 f9b644c 3bf2012 f9b644c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
#!/usr/bin/env python3
"""
Optimize ideal polyhedron volume for 7 vertices.
User hypothesis: Maximum might be octahedron with one stellated face.
"""
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
import time
def spherical_to_complex(theta, phi):
"""Convert spherical coordinates to complex via stereographic projection."""
return np.tan(theta/2) * np.exp(1j * phi)
def compute_volume_numpy(params):
"""Compute volume for numpy array input."""
# First 3 points fixed to break symmetry
z1 = complex(0, 0)
z2 = complex(1, 0)
# Other 4 points from parameters (spherical coords)
complex_points = [z1, z2]
for i in range(4):
theta = params[2*i]
phi = params[2*i + 1]
z = spherical_to_complex(theta, phi)
complex_points.append(z)
# Convert to numpy array
Z_np = np.array(complex_points, dtype=np.complex128)
# Delaunay triangulation
try:
idx = delaunay_triangulation_indices(Z_np)
except:
return 1000.0 # Penalty for degenerate configuration
# Convert to torch for volume computation
Z_torch = torch.tensor(Z_np, dtype=torch.complex128)
# Compute total volume
total_volume = 0
for (i, j, k) in idx:
try:
vol = triangle_volume_from_points_torch(Z_torch[i], Z_torch[j], Z_torch[k], series_terms=96)
total_volume += vol.item()
except:
return 1000.0 # Penalty for invalid configuration
return -total_volume # Negative for minimization
def analyze_hull_structure(Z_np, idx):
"""Analyze the combinatorial structure of the triangulation."""
n_vertices = len(Z_np)
n_faces = len(idx)
# Count edges
edges = set()
for (i, j, k) in idx:
edges.add((min(i,j), max(i,j)))
edges.add((min(i,k), max(i,k)))
edges.add((min(j,k), max(j,k)))
n_edges = len(edges)
# Vertex degrees
vertex_degrees = [0] * n_vertices
for edge in edges:
vertex_degrees[edge[0]] += 1
vertex_degrees[edge[1]] += 1
# Classify polyhedron
polyhedron_type = "Unknown"
if n_vertices == 6 and n_faces == 8:
polyhedron_type = "Octahedron"
elif n_vertices == 7 and n_faces == 10:
polyhedron_type = "Pentagonal bipyramid"
elif n_vertices == 7 and n_faces == 9:
polyhedron_type = "Stellated octahedron (likely)"
return {
'n_vertices': n_vertices,
'n_faces': n_faces,
'n_edges': n_edges,
'vertex_degrees': sorted(vertex_degrees),
'triangles': idx,
'polyhedron_type': polyhedron_type
}
# Run optimization with multiple random starts
print("Optimizing 7-vertex ideal polyhedron volume...")
print("="*70)
best_volume = 0
best_params = None
best_hull_info = None
best_complex_points = None
n_trials = 20
for trial in range(n_trials):
print(f"\nTrial {trial+1}/{n_trials}...")
# Bounds: theta in (0, pi), phi in [0, 2*pi)
bounds = [(0.1, np.pi-0.1), (0, 2*np.pi)] * 4
result = differential_evolution(
compute_volume_numpy,
bounds,
maxiter=500,
popsize=30,
polish=True,
workers=1,
seed=42 + trial * 13
)
volume = -result.fun
if volume > best_volume:
best_volume = volume
best_params = result.x
# Reconstruct best configuration for analysis
z1 = complex(0, 0)
z2 = complex(1, 0)
complex_points = [z1, z2]
for i in range(4):
theta = best_params[2*i]
phi = best_params[2*i + 1]
z = spherical_to_complex(theta, phi)
complex_points.append(z)
Z_np = np.array(complex_points, dtype=np.complex128)
try:
idx = delaunay_triangulation_indices(Z_np)
except:
continue # Skip degenerate configurations
best_hull_info = analyze_hull_structure(Z_np, idx)
best_complex_points = complex_points
print(f" Volume: {volume:.6f}")
print("\n" + "="*70)
print("RESULTS:")
print("="*70)
print(f"Best volume found: {best_volume:.6f}")
# Analyze the best configuration
if best_hull_info:
print(f"\nCombinatorial structure:")
print(f" Vertices: {best_hull_info['n_vertices']}")
print(f" Triangular faces: {best_hull_info['n_faces']}")
print(f" Edges: {best_hull_info['n_edges']}")
print(f" Vertex degrees: {best_hull_info['vertex_degrees']}")
print(f" Classification: {best_hull_info['polyhedron_type']}")
# Print configuration details
print(f"\nVertex configuration:")
for i, z in enumerate(best_complex_points):
print(f" z[{i}] = {z.real:.4f} + {z.imag:.4f}i")
# Save configuration
np.savez('optimal_7vertex.npz',
params=best_params,
volume=best_volume,
hull_info=best_hull_info,
complex_points=best_complex_points)
print(f"\nConfiguration saved to optimal_7vertex.npz")
# Compare with regular octahedron
regular_octahedron_vol = 5.3333 # Approximate
print(f"\nComparison:")
print(f" Regular octahedron (6 vertices): ≈ {regular_octahedron_vol:.4f}")
print(f" Optimal 7-vertex configuration: {best_volume:.6f}")
if best_volume > regular_octahedron_vol:
print(f" ✓ 7-vertex configuration exceeds regular octahedron by {(best_volume/regular_octahedron_vol - 1)*100:.1f}%")
else:
print(f" Regular octahedron is {(regular_octahedron_vol/best_volume - 1)*100:.1f}% larger") |