Implementing moving origin of ideal
CI / lint (push) Successful in 23s
CI / lint (pull_request) Successful in 15s
CI / test (push) Successful in 1m59s
CI / test (pull_request) Successful in 1m57s

This commit is contained in:
Julian Piribauer
2026-09-09 21:53:58 +02:00
parent 51a5612fe1
commit 82765b201c
2 changed files with 177 additions and 25 deletions
+32 -23
View File
@@ -125,42 +125,39 @@ def test_find_power_series_solution_handles_rational_indicial():
def test_ideal_finds_power_series_solution_and_recovers_first_operator():
# Picard--Fuchs ideal for P_{22211}[8]:
# M1 = theta2*(-2*theta1+2*theta2-1) + 2*(theta1-2*theta2-1)*(theta1-2*theta2)*z2
# M2 = theta1^2*(2*(theta1-2*theta2)*z2-theta2) - 16*(2*theta1+1)*(4*theta1+1)*(4*theta1+3)*z1*z2
M1 = PFOperator(
"theta1*(-2*theta0 + 2*theta1 - 1) + 2*(theta0 - 2*theta1 - 1)*(theta0 - 2*theta1)*z1",
# Picard--Fuchs ideal for P_{22211}[8] at the MUM point:
# D1 = Theta_x^2*(Theta_x - 2*Theta_y) - 4*x*(4*Theta_x + 3)*(4*Theta_x + 2)*(4*Theta_x + 1)
# D2 = Theta_y^2 - y*(2*Theta_y - Theta_x + 1)*(2*Theta_y - Theta_x)
#
# We test moving the ideal to the intersection with the locus of Strong Coupling.
D1 = PFOperator(
"theta0^2*(theta0 - 2*theta1) - 4*z0*(4*theta0 + 3)*(4*theta0 + 2)*(4*theta0 + 1)",
no_variables=2,
)
M2 = PFOperator(
"theta0^2*(2*(theta0 - 2*theta1)*z1 - theta1) - 16*(2*theta0 + 1)*(4*theta0 + 1)*(4*theta0 + 3)*z0*z1",
D2 = PFOperator(
"theta1^2 - z1*(2*theta1 - theta0 + 1)*(2*theta1 - theta0)",
no_variables=2,
)
ideal = PFIdeal([M1, M2])
moved = PFIdeal([D1, D2]).change_coordinates("z0", "z1 - 1/4")
op1, op2 = moved.operators
solutions = ideal.find_power_series_solution(indicials=[0, QQ(1) / 2], order=6)
solutions = moved.find_power_series_solution(indicials=[0, QQ(1) / 2], order=14)
assert len(solutions) == 1
period = solutions[0]
assert period.apply_operator(M1).coefficients == {}
assert period.apply_operator(M2).coefficients == {}
assert period.apply_operator(op1).coefficients == {}
assert period.apply_operator(op2).coefficients == {}
# Normalisation convention: the free parameter at the leading (0, 0) coefficient is 1.
assert period.coefficients[(0, 0)][(0, 0)] == 1
assert period.coefficients[(0, 0)][(1, 1)] == -32
assert period.coefficients[(0, 0)][(1, 0)] == 0
# M1 lives entirely within z_degree <= 1, theta_degree <= 2 (a single bare factor of
# z2, quadratic in theta), so this is the natural Ansatz level to look for it at.
recovered = period.find_annihilating_operators(z_degree=1, theta_degree=2)
assert len(recovered) == 1
# recovered[0] should be a scalar multiple of M1 - compare via the coefficient of the
# bare theta2 (theta1 in code) monomial, which is nonzero in M1.
ratio = (
recovered[0].operator.monomial_coefficient(M1.theta_gens[1])
/ M1.operator.monomial_coefficient(M1.theta_gens[1])
)
assert ratio != 0
assert recovered[0].operator == ratio * M1.operator
assert recovered[0].operator == PFOperator(
"-2*z1*theta0^2 + 8*z1*theta0*theta1 - 8*z1*theta1^2 + 2*z1*theta0 - 4*z1*theta1 "
"+ 2*theta0*theta1 - 2*theta1^2 + theta1",
no_variables=2,
).operator
def test_single_operator_recovers_itself_from_its_holomorphic_period():
@@ -192,3 +189,15 @@ def test_single_operator_recovers_itself_from_its_holomorphic_period():
)
assert ratio != 0
assert recovered[0].operator == ratio * L.operator
def test_change_coordinates_handles_non_monomial_denominator():
op = PFOperator("theta0^2 - z0", no_variables=1)
result = op.change_coordinates("z0/(1-z0)")
expected = PFOperator(
"(1+z0)^3*theta0^2 + z0*(1+z0)^2*theta0 - z0",
no_variables=1,
)
assert result.operator == expected.operator