File size: 6,131 Bytes
f9b644c
 
 
d7d27f0
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
import numpy as np
import json
from scipy.spatial import Delaunay
from ideal_poly_volume_toolkit.rivin_holonomy import Triangulation, generators_from_triangulation

def compute_holonomy_traces(vertices_complex, triangles):
    """
    Compute holonomy generators and their traces for an ideal polyhedron.
    
    Returns traces and checks if they're close to integers.
    """
    # Convert complex vertices to 2D points for triangulation
    vertices_2d = np.array([[z['real'], z['imag']] for z in vertices_complex if isinstance(z, dict)])
    
    # Build adjacency structure from Delaunay triangulation
    F = len(triangles)  # number of triangles
    adjacency = {}
    edge_id_map = {}
    edge_id = 0
    
    # Build adjacency between triangles
    for i, tri_i in enumerate(triangles):
        for side_i in range(3):
            v1_i, v2_i = tri_i[side_i], tri_i[(side_i + 1) % 3]
            edge = tuple(sorted([v1_i, v2_i]))
            
            # Find matching triangle
            for j, tri_j in enumerate(triangles):
                if i == j:
                    continue
                for side_j in range(3):
                    v1_j, v2_j = tri_j[side_j], tri_j[(side_j + 1) % 3]
                    if set([v1_j, v2_j]) == set([v1_i, v2_i]):
                        # Found matching edge
                        if (i, side_i) not in adjacency:
                            if edge not in edge_id_map:
                                edge_id_map[edge] = edge_id
                                edge_id += 1
                            adjacency[(i, side_i)] = (j, side_j, edge_id_map[edge])
    
    # Define order (counterclockwise) for each triangle
    order = {t: [0, 1, 2] for t in range(F)}
    
    # Define orientations for edges
    orientation = {}
    for edge, eid in edge_id_map.items():
        # Find triangles containing this edge
        for (t, s), (u, su, e) in adjacency.items():
            if e == eid:
                orientation[eid] = ((t, s), (u, su))
                break
    
    # Create triangulation object
    T = Triangulation(F, adjacency, order, orientation)
    
    # Zero shears (ideal polyhedra have no shearing)
    Z = {eid: 0.0 for eid in range(edge_id)}
    
    # Compute generators
    gens = generators_from_triangulation(T, Z, root=0)
    
    # Extract traces
    traces = []
    trace_analysis = []
    
    print(f"\nHolonomy analysis for {F} triangles:")
    print("-" * 70)
    print(f"Number of generators: {len(gens)}")
    print("\nTraces of holonomy generators:")
    
    for i, (u, v, tokens, M) in enumerate(gens):
        trace = M[0][0] + M[1][1]
        traces.append(trace)
        
        # Check proximity to integers
        nearest_int = round(trace)
        distance = abs(trace - nearest_int)
        is_close = distance < 0.01
        
        trace_analysis.append({
            'generator': i,
            'edge': (u, v),
            'trace': trace,
            'nearest_integer': nearest_int,
            'distance': distance,
            'possibly_integral': is_close
        })
        
        print(f"  Generator {i} (edge {u}-{v}): trace = {trace:.6f}")
        print(f"    Nearest integer: {nearest_int}, distance: {distance:.6f}")
        if is_close:
            print(f"    *** CLOSE TO INTEGER! ***")
    
    return traces, trace_analysis

# Load optimal configurations
with open('optimal_configurations.json', 'r') as f:
    data = json.load(f)

print("="*70)
print("ARITHMETICITY CHECK FOR MAXIMAL IDEAL POLYHEDRA")
print("="*70)

# Check the maximal 8-vertex configuration
print("\n1. MAXIMAL 8-VERTEX CONFIGURATION (volume = 6.488)")
print("-"*70)

config = data['discovered_configurations']['maximal_8vertex']
vertices = []
for k, v in config['vertices_complex'].items():
    if isinstance(v, dict):
        vertices.append(v)
triangles = config['delaunay_triangles']

traces1, analysis1 = compute_holonomy_traces(vertices, triangles)

# Check for arithmetic patterns
integral_count = sum(1 for a in analysis1 if a['possibly_integral'])
print(f"\nSummary: {integral_count}/{len(analysis1)} traces are close to integers")

# Check the golden ratio configuration
print("\n\n2. GOLDEN RATIO 8-VERTEX CONFIGURATION (volume = 6.002)")
print("-"*70)

config = data['discovered_configurations']['golden_ratio_8vertex']
vertices = []
for k, v in config['vertices_complex'].items():
    if isinstance(v, dict):
        vertices.append(v)
triangles = config['delaunay_triangles']

traces2, analysis2 = compute_holonomy_traces(vertices, triangles)

integral_count = sum(1 for a in analysis2 if a['possibly_integral'])
print(f"\nSummary: {integral_count}/{len(analysis2)} traces are close to integers")

# Check trace field generation
print("\n\n3. TRACE FIELD ANALYSIS")
print("-"*70)

def analyze_trace_field(traces):
    """Check if traces generate an algebraic number field close to integers."""
    # Look for algebraic relations
    products = []
    sums = []
    
    for i in range(len(traces)):
        for j in range(i, len(traces)):
            products.append(traces[i] * traces[j])
            sums.append(traces[i] + traces[j])
    
    all_values = traces + products + sums
    integral_values = []
    
    for val in all_values:
        nearest = round(val)
        if abs(val - nearest) < 0.01:
            integral_values.append((val, nearest))
    
    return integral_values

print("\nMaximal configuration trace field:")
integral_vals1 = analyze_trace_field(traces1)
print(f"Found {len(integral_vals1)} values close to integers in trace field")

print("\nGolden ratio configuration trace field:")
integral_vals2 = analyze_trace_field(traces2)
print(f"Found {len(integral_vals2)} values close to integers in trace field")

print("\n\nCONCLUSION:")
print("-"*70)
print("If many traces are close to integers, the polyhedron may be arithmetic.")
print("Arithmetic hyperbolic 3-manifolds have holonomies in PSL(2,O_K) where")
print("O_K is the ring of integers in a number field K.")
print("\nFor ideal polyhedra, arithmeticity would mean the configuration")
print("has deep number-theoretic significance!")