File size: 2,779 Bytes
82a8f4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import torch
import numpy as np
from ideal_poly_volume_toolkit.geometry import delaunay_triangulation_indices

# Test gradient computation for the original version
def build_Z_complex(thetas):
    Z = torch.empty(thetas.numel() + 2, dtype=torch.complex128, device=thetas.device)
    Z[0] = 1 + 0j
    Z[1] = 0 + 0j
    Z[2:] = torch.exp(1j * thetas.to(torch.complex128))
    return Z

# Test gradient computation for the fixed version
def build_Z_real(thetas):
    real_parts = torch.zeros(thetas.numel() + 2, dtype=torch.float64, device=thetas.device)
    imag_parts = torch.zeros(thetas.numel() + 2, dtype=torch.float64, device=thetas.device)
    real_parts[0] = 1.0
    imag_parts[0] = 0.0
    real_parts[1] = 0.0
    imag_parts[1] = 0.0
    real_parts[2:] = torch.cos(thetas)
    imag_parts[2:] = torch.sin(thetas)
    return real_parts, imag_parts

# Simple test
thetas = torch.tensor([0.5, 1.0, 1.5], dtype=torch.float64, requires_grad=True)

print("Testing gradient flow for complex version:")
Z_complex = build_Z_complex(thetas)
# Try to compute a simple function and backprop
loss_complex = (Z_complex.real**2).sum() + (Z_complex.imag**2).sum()
print(f"Loss value: {loss_complex.item()}")
loss_complex.backward()
print(f"Gradients on thetas: {thetas.grad}")

# Reset
thetas.grad = None

print("\nTesting gradient flow for real version:")
real_parts, imag_parts = build_Z_real(thetas)
loss_real = (real_parts**2).sum() + (imag_parts**2).sum()
print(f"Loss value: {loss_real.item()}")
loss_real.backward()
print(f"Gradients on thetas: {thetas.grad}")

# Now test with actual triangle computation
print("\n\nTesting with actual triangle volume computation:")

# Reset
thetas = torch.tensor([0.5, 1.0, 1.5], dtype=torch.float64, requires_grad=True)

# Build points and get triangulation
with torch.no_grad():
    real_np, imag_np = build_Z_real(thetas)
    Z_np = real_np.numpy() + 1j * imag_np.numpy()
    idx = delaunay_triangulation_indices(Z_np)
    print(f"Triangulation indices: {idx}")

# Test if we can compute angles with gradients
from ideal_poly_volume_toolkit.examples.optimize_lbfgs_delaunay_fixed import (
    _angles_for_triangle_real, lob_fast
)

real_parts, imag_parts = build_Z_real(thetas)

# Pick first triangle
i, j, k = idx[0]
a1, a2, a3 = _angles_for_triangle_real(
    real_parts[i], imag_parts[i],
    real_parts[j], imag_parts[j],
    real_parts[k], imag_parts[k]
)

print(f"\nAngles: {a1.item():.4f}, {a2.item():.4f}, {a3.item():.4f}")

# Test Lobachevsky function
lob1 = lob_fast(a1, 10)
print(f"Lob value: {lob1.item()}")

# Test full volume
volume = lob_fast(a1, 10) + lob_fast(a2, 10) + lob_fast(a3, 10)
print(f"Triangle volume: {volume.item()}")

# Compute gradients
loss = -volume
loss.backward()
print(f"Gradients on thetas: {thetas.grad}")