Spaces:
Sleeping
Sleeping
| import torch | |
| import numpy as np | |
| from ideal_poly_volume_toolkit.geometry import triangle_volume_from_points_torch, _angles_for_triangle_torch, lob_fast | |
| # Test at theta = 0.5 | |
| theta = torch.tensor(0.5, dtype=torch.float64, requires_grad=True) | |
| z0 = torch.tensor(0+0j, dtype=torch.complex128) | |
| z1 = torch.tensor(1+0j, dtype=torch.complex128) | |
| z2 = torch.exp(1j * theta.to(torch.complex128)) | |
| # Get the angles | |
| a1, a2, a3 = _angles_for_triangle_torch(z0, z1, z2) | |
| print(f"Triangle angles at theta=0.5:") | |
| print(f" a1 = {a1.item():.4f} rad ({a1.item()*180/np.pi:.2f}°)") | |
| print(f" a2 = {a2.item():.4f} rad ({a2.item()*180/np.pi:.2f}°)") | |
| print(f" a3 = {a3.item():.4f} rad ({a3.item()*180/np.pi:.2f}°)") | |
| print(f" Sum = {(a1+a2+a3).item():.4f} rad ({(a1+a2+a3).item()*180/np.pi:.2f}°)") | |
| # Compute volume | |
| volume = triangle_volume_from_points_torch(z0, z1, z2, series_terms=96) | |
| print(f"\nVolume = {volume.item():.6f}") | |
| # Compute gradient | |
| volume.backward() | |
| print(f"Gradient of volume w.r.t. theta = {theta.grad.item():.6f}") | |
| # Now let's manually check which angle changes how | |
| print("\n\nManual gradient check:") | |
| eps = 1e-6 | |
| # Reset for manual computation | |
| theta.grad = None | |
| theta_plus = theta + eps | |
| theta_minus = theta - eps | |
| # Compute z2 at theta +/- eps | |
| z2_plus = torch.exp(1j * theta_plus.to(torch.complex128)) | |
| z2_minus = torch.exp(1j * theta_minus.to(torch.complex128)) | |
| # Get angles at both points | |
| a1_plus, a2_plus, a3_plus = _angles_for_triangle_torch(z0, z1, z2_plus) | |
| a1_minus, a2_minus, a3_minus = _angles_for_triangle_torch(z0, z1, z2_minus) | |
| # Volume at both points | |
| vol_plus = lob_fast(a1_plus, 96) + lob_fast(a2_plus, 96) + lob_fast(a3_plus, 96) | |
| vol_minus = lob_fast(a1_minus, 96) + lob_fast(a2_minus, 96) + lob_fast(a3_minus, 96) | |
| fd_grad = (vol_plus - vol_minus) / (2 * eps) | |
| print(f"Finite difference gradient = {fd_grad.item():.6f}") | |
| # Check how each angle changes | |
| print(f"\nAngle derivatives w.r.t. theta:") | |
| print(f" da1/dθ ≈ {((a1_plus - a1_minus) / (2*eps)).item():.4f}") | |
| print(f" da2/dθ ≈ {((a2_plus - a2_minus) / (2*eps)).item():.4f}") | |
| print(f" da3/dθ ≈ {((a3_plus - a3_minus) / (2*eps)).item():.4f}") | |
| # The issue might be with the loss = -volume in the optimizer | |
| print("\n\nThe issue:") | |
| print("In the optimizer, we use loss = -volume (to maximize)") | |
| print(f"So gradient of loss w.r.t. theta = -{theta.grad.item():.6f} = {-theta.grad.item():.6f}") | |
| print("LBFGS moves in direction opposite to gradient of loss") | |
| print(f"So it should move theta by approximately +{-theta.grad.item():.6f}") | |
| # But wait, let's check what the optimizer actually sees | |
| theta2 = torch.tensor(0.5, dtype=torch.float64, requires_grad=True) | |
| z0 = torch.tensor(0+0j, dtype=torch.complex128) | |
| z1 = torch.tensor(1+0j, dtype=torch.complex128) | |
| z2 = torch.exp(1j * theta2.to(torch.complex128)) | |
| volume2 = triangle_volume_from_points_torch(z0, z1, z2, series_terms=96) | |
| loss = -volume2 | |
| loss.backward() | |
| print(f"\nWhat the optimizer sees:") | |
| print(f" theta.grad after loss.backward() = {theta2.grad.item():.6f}") |