Use quadproj instead of the local quadric module
The quadric, x(mu), f, f', mu* and the degenerate points now come from quadproj; the script keeps small helpers for what quadproj does not provide: mu**, the asymptotes and the ellipse boundary. The tests check these helpers against brute-force sampling and quadproj.project. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
55cb27c8de
commit
f1d5a73cc6
7 files changed
+142
-209
No files matched your search
@@ -0,0 +1,50 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
from quadproj.fun import Fun
|
||||
from quadproj.project import project
|
||||
from quadproj.quadrics import Quadric
|
||||
|
||||
from plot_mu_trajectories import degenerate_point, ellipse_boundary, kkt_roots, pole_line
|
||||
|
||||
ROTATED_ELLIPSE = Quadric(np.array([[3.0, 1.0], [1.0, 2.0]]), np.array([1.0, -1.0]), -4.0)
|
||||
|
||||
|
||||
def trajectory(Q, x0):
|
||||
return Fun(Q, Q.to_normalized(x0)).x_not_std
|
||||
|
||||
|
||||
def boundary_distances(Q, x0):
|
||||
return np.linalg.norm(ellipse_boundary(Q, 200_000) - x0, axis=1)
|
||||
|
||||
|
||||
def test_boundary_is_on_the_ellipse():
|
||||
assert np.all([abs(ROTATED_ELLIPSE.evaluate_point(x)) < 1e-10 for x in ellipse_boundary(ROTATED_ELLIPSE)])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('x0', [[0.3, 0.2], [2.0, -1.5], [-0.1, 0.4]])
|
||||
def test_kkt_roots_give_nearest_and_farthest_points(x0):
|
||||
Q, x0 = ROTATED_ELLIPSE, np.array(x0)
|
||||
mu_star, mu_star_star = kkt_roots(Q, x0)
|
||||
x = trajectory(Q, x0)
|
||||
|
||||
distances = boundary_distances(Q, x0)
|
||||
assert abs(Q.evaluate_point(x(mu_star_star))) < 1e-8
|
||||
assert np.linalg.norm(x(mu_star) - x0) == pytest.approx(distances.min(), abs=1e-6)
|
||||
assert np.linalg.norm(x(mu_star_star) - x0) == pytest.approx(distances.max(), abs=1e-6)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('eig, x0', [([2.0, 1.0], [0.0, -0.1]), ([2.0, 0.75], [0.0, -0.6])])
|
||||
def test_degenerate_point_is_the_projection(eig, x0):
|
||||
Q, x0 = Quadric(np.diag(eig), np.zeros(2), -1.0), np.array(x0)
|
||||
xd = degenerate_point(Q, x0, 0)
|
||||
np.testing.assert_allclose(xd, project(Q, x0))
|
||||
assert np.linalg.norm(xd - x0) == pytest.approx(boundary_distances(Q, x0).min(), abs=1e-6)
|
||||
assert degenerate_point(Q, x0, 1) is None
|
||||
|
||||
|
||||
def test_pole_line_is_the_asymptote():
|
||||
Q, x0 = ROTATED_ELLIPSE, np.array([0.3, 0.2])
|
||||
point, direction = pole_line(Q, x0, 1)
|
||||
x = trajectory(Q, x0)(-1 / Q.eig[1] + 1e-9)
|
||||
residual = (x - point) - ((x - point) @ direction) * direction
|
||||
np.testing.assert_allclose(residual, 0, atol=1e-6)
|
||||
Reference in new issue
Block a user