process-geometry 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aeg_shakespeare/__init__.py +52 -0
- aeg_shakespeare/_legacy_api.py +299 -0
- aeg_shakespeare/analysis/__init__.py +12 -0
- aeg_shakespeare/analysis/abelian.py +69 -0
- aeg_shakespeare/analysis/algebraic.py +11 -0
- aeg_shakespeare/analysis/am.py +19 -0
- aeg_shakespeare/analysis/connection.py +74 -0
- aeg_shakespeare/analysis/decomposition.py +37 -0
- aeg_shakespeare/analysis/module.py +5 -0
- aeg_shakespeare/central.py +20 -0
- aeg_shakespeare/constraints.py +121 -0
- aeg_shakespeare/construction.py +303 -0
- aeg_shakespeare/core.py +59 -0
- aeg_shakespeare/cost.py +51 -0
- aeg_shakespeare/discovery/__init__.py +53 -0
- aeg_shakespeare/discovery/coefficient_extension.py +75 -0
- aeg_shakespeare/discovery/polynomial.py +342 -0
- aeg_shakespeare/discovery/selection.py +146 -0
- aeg_shakespeare/discovery/structured.py +201 -0
- aeg_shakespeare/families.py +31 -0
- aeg_shakespeare/frame.py +5 -0
- aeg_shakespeare/function_theory/__init__.py +100 -0
- aeg_shakespeare/function_theory/abel_jacobi.py +246 -0
- aeg_shakespeare/function_theory/abelian.py +129 -0
- aeg_shakespeare/function_theory/algebraic.py +105 -0
- aeg_shakespeare/function_theory/am.py +266 -0
- aeg_shakespeare/function_theory/intersection.py +321 -0
- aeg_shakespeare/function_theory/module.py +118 -0
- aeg_shakespeare/function_theory/period_matrix.py +155 -0
- aeg_shakespeare/function_theory/periods.py +216 -0
- aeg_shakespeare/function_theory/real_branch_cycles.py +286 -0
- aeg_shakespeare/function_theory/weierstrass.py +136 -0
- aeg_shakespeare/grammar.py +225 -0
- aeg_shakespeare/history_geometry.py +276 -0
- aeg_shakespeare/linear.py +70 -0
- aeg_shakespeare/presentation/__init__.py +23 -0
- aeg_shakespeare/presentation/budget.py +27 -0
- aeg_shakespeare/presentation/canonicalization.py +143 -0
- aeg_shakespeare/presentation/constraints.py +5 -0
- aeg_shakespeare/presentation/construction.py +19 -0
- aeg_shakespeare/presentation/grammar.py +15 -0
- aeg_shakespeare/presentation/history.py +45 -0
- aeg_shakespeare/presentation/morphism.py +66 -0
- aeg_shakespeare/presentation/relations.py +31 -0
- aeg_shakespeare/presentation/search.py +31 -0
- aeg_shakespeare/process/__init__.py +16 -0
- aeg_shakespeare/process/finite/__init__.py +43 -0
- aeg_shakespeare/process/finite/cocycle.py +166 -0
- aeg_shakespeare/process/finite/families.py +318 -0
- aeg_shakespeare/process/history.py +53 -0
- aeg_shakespeare/process/local/__init__.py +7 -0
- aeg_shakespeare/process/local/direction.py +88 -0
- aeg_shakespeare/process/local/frame.py +73 -0
- aeg_shakespeare/process/local/system.py +43 -0
- aeg_shakespeare/relations.py +374 -0
- aeg_shakespeare/rewrite.py +157 -0
- aeg_shakespeare/search.py +286 -0
- aeg_shakespeare/signature.py +155 -0
- process_geometry-0.0.3.dist-info/METADATA +305 -0
- process_geometry-0.0.3.dist-info/RECORD +63 -0
- process_geometry-0.0.3.dist-info/WHEEL +5 -0
- process_geometry-0.0.3.dist-info/licenses/LICENSE +24 -0
- process_geometry-0.0.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Compatibility shim for the pre-refactor finite-family module path.
|
|
2
|
+
|
|
3
|
+
New code should import from ``aeg_shakespeare.process.finite``. The
|
|
4
|
+
implementation now physically lives under that semantic namespace.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .process.finite.families import (
|
|
8
|
+
CharacterVerification,
|
|
9
|
+
FamilyAction,
|
|
10
|
+
FamilyActionVerification,
|
|
11
|
+
FamilyStep,
|
|
12
|
+
ProcessCharacter,
|
|
13
|
+
ProcessFamily,
|
|
14
|
+
character_invariance_residual,
|
|
15
|
+
transport_process_character,
|
|
16
|
+
verify_family_action,
|
|
17
|
+
verify_process_character,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"ProcessFamily",
|
|
22
|
+
"FamilyStep",
|
|
23
|
+
"ProcessCharacter",
|
|
24
|
+
"CharacterVerification",
|
|
25
|
+
"verify_process_character",
|
|
26
|
+
"FamilyAction",
|
|
27
|
+
"FamilyActionVerification",
|
|
28
|
+
"verify_family_action",
|
|
29
|
+
"transport_process_character",
|
|
30
|
+
"character_invariance_residual",
|
|
31
|
+
]
|
aeg_shakespeare/frame.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Optional process-generated function-theory layers.
|
|
2
|
+
|
|
3
|
+
Addition/Multiplication (A/M) is the first concrete arithmetic theory.
|
|
4
|
+
Algebraic quotient profiles provide a second route for processes whose reduced
|
|
5
|
+
geometry forces elliptic/Abelian or higher-genus function languages. The
|
|
6
|
+
Abelian layer then exposes canonical holomorphic differentials, history lifts,
|
|
7
|
+
cycle intersections, branch-cut cycle constructions, period data, and finally
|
|
8
|
+
normalized history coordinates modulo the measured period lattice.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .abel_jacobi import (
|
|
12
|
+
AbelJacobiHistoryIncrement,
|
|
13
|
+
NormalizedAbelianTorus,
|
|
14
|
+
abel_jacobi_history_increment,
|
|
15
|
+
normalized_abelian_torus,
|
|
16
|
+
)
|
|
17
|
+
from .abelian import (
|
|
18
|
+
AbelianIntegralProfile,
|
|
19
|
+
HyperellipticDifferential,
|
|
20
|
+
abelian_integral_profile,
|
|
21
|
+
holomorphic_differential_basis,
|
|
22
|
+
)
|
|
23
|
+
from .algebraic import HyperellipticProfile, hyperelliptic_profile
|
|
24
|
+
from .am import (
|
|
25
|
+
AMFunctionTheory,
|
|
26
|
+
AMPathFlow,
|
|
27
|
+
AMPowerWeight,
|
|
28
|
+
AMPrimitive,
|
|
29
|
+
AMState,
|
|
30
|
+
affine_am_frame,
|
|
31
|
+
)
|
|
32
|
+
from .intersection import (
|
|
33
|
+
LiftedCycleIntersection,
|
|
34
|
+
SampledIntersectionForm,
|
|
35
|
+
SampledRiemannProfile,
|
|
36
|
+
canonical_symplectic_form,
|
|
37
|
+
lifted_path_intersections,
|
|
38
|
+
sampled_intersection_form,
|
|
39
|
+
sampled_intersection_number,
|
|
40
|
+
sampled_riemann_profile,
|
|
41
|
+
)
|
|
42
|
+
from .module import ProcessFunctionModule, polynomial_am_module
|
|
43
|
+
from .period_matrix import AbelianCycleSystem, AbelianPeriodMatrix, compute_period_matrix
|
|
44
|
+
from .periods import (
|
|
45
|
+
GenusOneLattice,
|
|
46
|
+
LiftedSquareRootPath,
|
|
47
|
+
integrate_lifted_differential,
|
|
48
|
+
lift_square_root_path,
|
|
49
|
+
)
|
|
50
|
+
from .real_branch_cycles import (
|
|
51
|
+
ConstructedRealBranchCycles,
|
|
52
|
+
RealBranchCutPresentation,
|
|
53
|
+
RealBranchCycleSpec,
|
|
54
|
+
construct_real_branch_cycles,
|
|
55
|
+
real_branch_cut_presentation,
|
|
56
|
+
)
|
|
57
|
+
from .weierstrass import WeierstrassCubicProfile, weierstrass_cubic_profile
|
|
58
|
+
|
|
59
|
+
__all__ = [
|
|
60
|
+
"AbelJacobiHistoryIncrement",
|
|
61
|
+
"NormalizedAbelianTorus",
|
|
62
|
+
"abel_jacobi_history_increment",
|
|
63
|
+
"normalized_abelian_torus",
|
|
64
|
+
"AbelianIntegralProfile",
|
|
65
|
+
"HyperellipticDifferential",
|
|
66
|
+
"abelian_integral_profile",
|
|
67
|
+
"holomorphic_differential_basis",
|
|
68
|
+
"HyperellipticProfile",
|
|
69
|
+
"hyperelliptic_profile",
|
|
70
|
+
"AMFunctionTheory",
|
|
71
|
+
"AMPathFlow",
|
|
72
|
+
"AMPowerWeight",
|
|
73
|
+
"AMPrimitive",
|
|
74
|
+
"AMState",
|
|
75
|
+
"affine_am_frame",
|
|
76
|
+
"LiftedCycleIntersection",
|
|
77
|
+
"SampledIntersectionForm",
|
|
78
|
+
"SampledRiemannProfile",
|
|
79
|
+
"canonical_symplectic_form",
|
|
80
|
+
"lifted_path_intersections",
|
|
81
|
+
"sampled_intersection_form",
|
|
82
|
+
"sampled_intersection_number",
|
|
83
|
+
"sampled_riemann_profile",
|
|
84
|
+
"ProcessFunctionModule",
|
|
85
|
+
"polynomial_am_module",
|
|
86
|
+
"AbelianCycleSystem",
|
|
87
|
+
"AbelianPeriodMatrix",
|
|
88
|
+
"compute_period_matrix",
|
|
89
|
+
"GenusOneLattice",
|
|
90
|
+
"LiftedSquareRootPath",
|
|
91
|
+
"integrate_lifted_differential",
|
|
92
|
+
"lift_square_root_path",
|
|
93
|
+
"ConstructedRealBranchCycles",
|
|
94
|
+
"RealBranchCutPresentation",
|
|
95
|
+
"RealBranchCycleSpec",
|
|
96
|
+
"construct_real_branch_cycles",
|
|
97
|
+
"real_branch_cut_presentation",
|
|
98
|
+
"WeierstrassCubicProfile",
|
|
99
|
+
"weierstrass_cubic_profile",
|
|
100
|
+
]
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"""Normalized Abelian history coordinates and the period-lattice quotient.
|
|
2
|
+
|
|
3
|
+
Primitive question
|
|
4
|
+
------------------
|
|
5
|
+
Once a process quotient has emitted canonical holomorphic differentials, a
|
|
6
|
+
symplectic cycle system, and a Riemann-shaped period matrix, what does a lifted
|
|
7
|
+
history *measure* globally?
|
|
8
|
+
|
|
9
|
+
For a path ``gamma`` on a genus-``g`` curve the vector
|
|
10
|
+
|
|
11
|
+
u(gamma) = (integral_gamma omega_1, ..., integral_gamma omega_g)
|
|
12
|
+
|
|
13
|
+
records the Abelian-integral increment carried by that history. If ``A`` is
|
|
14
|
+
the A-period block, the normalized increment is
|
|
15
|
+
|
|
16
|
+
u_hat = A^{-1} u.
|
|
17
|
+
|
|
18
|
+
Closed A- and B-cycle histories then shift the normalized coordinate by
|
|
19
|
+
|
|
20
|
+
e_j and tau[:, j],
|
|
21
|
+
|
|
22
|
+
respectively. Thus the residual ambiguity after quotienting closed histories
|
|
23
|
+
is the lattice
|
|
24
|
+
|
|
25
|
+
Z^g + tau Z^g subset C^g.
|
|
26
|
+
|
|
27
|
+
Classical lineage
|
|
28
|
+
-----------------
|
|
29
|
+
This is the analytic construction underlying the Abel--Jacobi map and the
|
|
30
|
+
Jacobian of a compact Riemann surface. Choosing a base point and integrating a
|
|
31
|
+
basis of holomorphic one-forms sends points/divisors to ``C^g`` modulo the
|
|
32
|
+
period lattice. With A-normalized differentials the Jacobian has the standard
|
|
33
|
+
presentation
|
|
34
|
+
|
|
35
|
+
C^g / (Z^g + tau Z^g).
|
|
36
|
+
|
|
37
|
+
See Farkas--Kra, Forster, and Mumford in ``docs/REFERENCES.md``. Historically,
|
|
38
|
+
Abel's theorem and Jacobi inversion are the higher-genus continuation of the
|
|
39
|
+
elliptic-integral inversion story; Baker is retained in the bibliography as a
|
|
40
|
+
classical historical source.
|
|
41
|
+
|
|
42
|
+
Shakespeare reconstruction
|
|
43
|
+
---------------------------
|
|
44
|
+
The package does not insert a ``Jacobian`` object merely because the curve has
|
|
45
|
+
genus ``g``. This module is enabled only after earlier executable layers have
|
|
46
|
+
produced:
|
|
47
|
+
|
|
48
|
+
1. actual lifted histories;
|
|
49
|
+
2. their period matrix;
|
|
50
|
+
3. a sampled canonical symplectic intersection form; and
|
|
51
|
+
4. the Riemann symmetry/positive-imaginary-part checks.
|
|
52
|
+
|
|
53
|
+
``NormalizedAbelianTorus`` therefore accepts a *passing* ``SampledRiemannProfile``.
|
|
54
|
+
It is a numerical period-lattice presentation, not a claim that Shakespeare has
|
|
55
|
+
implemented divisor arithmetic or an algebraic Jacobian model.
|
|
56
|
+
|
|
57
|
+
``AbelJacobiHistoryIncrement`` likewise represents the integral accumulated by
|
|
58
|
+
one lifted path. A genuine point-valued Abel--Jacobi map additionally requires
|
|
59
|
+
a chosen base point and a path from that base point. Keeping the object as a
|
|
60
|
+
history increment makes the dependence on path history explicit rather than
|
|
61
|
+
silently hiding it modulo periods.
|
|
62
|
+
|
|
63
|
+
Executable contract
|
|
64
|
+
-------------------
|
|
65
|
+
``abel_jacobi_history_increment`` integrates the canonical differential basis
|
|
66
|
+
along a lifted path and normalizes by the measured A-period block. For the
|
|
67
|
+
cycle system that generated the period matrix:
|
|
68
|
+
|
|
69
|
+
A_j -> e_j,
|
|
70
|
+
B_j -> tau[:,j].
|
|
71
|
+
|
|
72
|
+
``NormalizedAbelianTorus.lattice_shift(m,n)`` returns ``m + tau n`` for integer
|
|
73
|
+
vectors ``m,n``. ``matches_lattice_shift`` checks a *declared* lattice
|
|
74
|
+
relation; it deliberately does not solve the hard inverse problem of deciding
|
|
75
|
+
an arbitrary nearest/exact period relation.
|
|
76
|
+
|
|
77
|
+
Boundary
|
|
78
|
+
--------
|
|
79
|
+
All data inherit the numerical/sampling limitations of the current continuation,
|
|
80
|
+
intersection, and quadrature layers. The class is not a full Jacobian: it has
|
|
81
|
+
no divisor classes, theta functions, polarization machinery beyond the already
|
|
82
|
+
checked cycle pairing, algebraic group law, or Jacobi inversion solver. The
|
|
83
|
+
name ``NormalizedAbelianTorus`` is intentional. The classical identification
|
|
84
|
+
with the Jacobian is the shadow when the supplied Riemann-surface data are
|
|
85
|
+
mathematically valid.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
from __future__ import annotations
|
|
89
|
+
|
|
90
|
+
from dataclasses import dataclass
|
|
91
|
+
from typing import Sequence
|
|
92
|
+
|
|
93
|
+
import sympy as sp
|
|
94
|
+
|
|
95
|
+
from .abelian import holomorphic_differential_basis
|
|
96
|
+
from .intersection import SampledRiemannProfile
|
|
97
|
+
from .period_matrix import AbelianPeriodMatrix
|
|
98
|
+
from .periods import LiftedSquareRootPath, integrate_lifted_differential
|
|
99
|
+
|
|
100
|
+
ComplexVector = tuple[complex, ...]
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _complex_matrix(rows: Sequence[Sequence[complex]]) -> sp.Matrix:
|
|
104
|
+
return sp.Matrix([[complex(value) for value in row] for row in rows])
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _complex_vector(values: Sequence[complex]) -> sp.Matrix:
|
|
108
|
+
return sp.Matrix([complex(value) for value in values])
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _as_complex_tuple(column: sp.Matrix) -> ComplexVector:
|
|
112
|
+
return tuple(complex(sp.N(column[index], 30)) for index in range(column.rows))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dataclass(frozen=True)
|
|
116
|
+
class AbelJacobiHistoryIncrement:
|
|
117
|
+
"""Raw and A-normalized Abelian-integral increment of one lifted history."""
|
|
118
|
+
|
|
119
|
+
periods: AbelianPeriodMatrix
|
|
120
|
+
path: LiftedSquareRootPath
|
|
121
|
+
raw: ComplexVector
|
|
122
|
+
normalized: ComplexVector
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def dimension(self) -> int:
|
|
126
|
+
return len(self.normalized)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class NormalizedAbelianTorus:
|
|
131
|
+
"""Numerical normalized lattice ``C^g / (Z^g + tau Z^g)``.
|
|
132
|
+
|
|
133
|
+
Construction is intentionally gated by a passing sampled Riemann profile so
|
|
134
|
+
callers cannot turn an arbitrary complex matrix into a Shakespeare
|
|
135
|
+
``Jacobian-like`` representation without the currently available topology
|
|
136
|
+
and Riemann-shape evidence.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
riemann: SampledRiemannProfile
|
|
140
|
+
|
|
141
|
+
def __post_init__(self) -> None:
|
|
142
|
+
if not self.riemann.passes:
|
|
143
|
+
raise ValueError("normalized Abelian torus requires a passing Riemann profile")
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def periods(self) -> AbelianPeriodMatrix:
|
|
147
|
+
return self.riemann.periods
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def dimension(self) -> int:
|
|
151
|
+
return self.periods.genus
|
|
152
|
+
|
|
153
|
+
@property
|
|
154
|
+
def tau(self) -> tuple[tuple[complex, ...], ...]:
|
|
155
|
+
return self.periods.tau
|
|
156
|
+
|
|
157
|
+
def a_shift(self, index: int) -> ComplexVector:
|
|
158
|
+
"""Return the normalized lattice shift generated by A_index."""
|
|
159
|
+
|
|
160
|
+
if not 0 <= index < self.dimension:
|
|
161
|
+
raise IndexError("A-cycle index out of range")
|
|
162
|
+
return tuple(1.0 + 0j if row == index else 0j for row in range(self.dimension))
|
|
163
|
+
|
|
164
|
+
def b_shift(self, index: int) -> ComplexVector:
|
|
165
|
+
"""Return the normalized lattice shift generated by B_index."""
|
|
166
|
+
|
|
167
|
+
if not 0 <= index < self.dimension:
|
|
168
|
+
raise IndexError("B-cycle index out of range")
|
|
169
|
+
return tuple(self.tau[row][index] for row in range(self.dimension))
|
|
170
|
+
|
|
171
|
+
def lattice_shift(
|
|
172
|
+
self,
|
|
173
|
+
a_coefficients: Sequence[int],
|
|
174
|
+
b_coefficients: Sequence[int],
|
|
175
|
+
) -> ComplexVector:
|
|
176
|
+
"""Return ``m + tau*n`` for integer coefficient vectors ``m,n``."""
|
|
177
|
+
|
|
178
|
+
if len(a_coefficients) != self.dimension or len(b_coefficients) != self.dimension:
|
|
179
|
+
raise ValueError("lattice coefficient vectors must have length g")
|
|
180
|
+
if any(not isinstance(value, int) for value in tuple(a_coefficients) + tuple(b_coefficients)):
|
|
181
|
+
raise TypeError("lattice coefficients must be integers")
|
|
182
|
+
|
|
183
|
+
return tuple(
|
|
184
|
+
complex(a_coefficients[row])
|
|
185
|
+
+ sum(
|
|
186
|
+
self.tau[row][column] * b_coefficients[column]
|
|
187
|
+
for column in range(self.dimension)
|
|
188
|
+
)
|
|
189
|
+
for row in range(self.dimension)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
def matches_lattice_shift(
|
|
193
|
+
self,
|
|
194
|
+
left: Sequence[complex],
|
|
195
|
+
right: Sequence[complex],
|
|
196
|
+
a_coefficients: Sequence[int],
|
|
197
|
+
b_coefficients: Sequence[int],
|
|
198
|
+
*,
|
|
199
|
+
tolerance: float = 1e-8,
|
|
200
|
+
) -> bool:
|
|
201
|
+
"""Check ``right-left = m+tau*n`` for caller-declared integer vectors."""
|
|
202
|
+
|
|
203
|
+
if tolerance <= 0:
|
|
204
|
+
raise ValueError("tolerance must be positive")
|
|
205
|
+
if len(left) != self.dimension or len(right) != self.dimension:
|
|
206
|
+
raise ValueError("torus coordinates must have length g")
|
|
207
|
+
shift = self.lattice_shift(a_coefficients, b_coefficients)
|
|
208
|
+
return max(
|
|
209
|
+
abs((complex(right[index]) - complex(left[index])) - shift[index])
|
|
210
|
+
for index in range(self.dimension)
|
|
211
|
+
) <= tolerance
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def normalized_abelian_torus(riemann: SampledRiemannProfile) -> NormalizedAbelianTorus:
|
|
215
|
+
"""Construct the normalized period-lattice quotient from checked Riemann data."""
|
|
216
|
+
|
|
217
|
+
return NormalizedAbelianTorus(riemann=riemann)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def abel_jacobi_history_increment(
|
|
221
|
+
path: LiftedSquareRootPath,
|
|
222
|
+
periods: AbelianPeriodMatrix,
|
|
223
|
+
) -> AbelJacobiHistoryIncrement:
|
|
224
|
+
"""Integrate and A-normalize the canonical differential vector on ``path``."""
|
|
225
|
+
|
|
226
|
+
if path.curve != periods.cycles.curve:
|
|
227
|
+
raise ValueError("history path and period matrix must belong to the same curve")
|
|
228
|
+
|
|
229
|
+
differentials = holomorphic_differential_basis(path.curve)
|
|
230
|
+
raw = tuple(
|
|
231
|
+
integrate_lifted_differential(path, differential)
|
|
232
|
+
for differential in differentials
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
a_matrix = _complex_matrix(periods.a_periods)
|
|
236
|
+
if a_matrix.rows != len(raw) or a_matrix.cols != len(raw):
|
|
237
|
+
raise ValueError("A-period block and Abelian history dimension disagree")
|
|
238
|
+
normalized_column = a_matrix.inv() * _complex_vector(raw)
|
|
239
|
+
normalized = _as_complex_tuple(normalized_column)
|
|
240
|
+
|
|
241
|
+
return AbelJacobiHistoryIncrement(
|
|
242
|
+
periods=periods,
|
|
243
|
+
path=path,
|
|
244
|
+
raw=tuple(complex(value) for value in raw),
|
|
245
|
+
normalized=normalized,
|
|
246
|
+
)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Abelian-integral structure emitted by a hyperelliptic process quotient.
|
|
2
|
+
|
|
3
|
+
Mathematical lineage
|
|
4
|
+
--------------------
|
|
5
|
+
Once an algebraic curve ``y^2 = P(x)`` has appeared, classical analysis does
|
|
6
|
+
not stop at its genus. One studies holomorphic differentials, integrates them
|
|
7
|
+
along paths, and compares the values after continuation around closed cycles.
|
|
8
|
+
For a genus-``g`` hyperelliptic curve a standard holomorphic basis is
|
|
9
|
+
|
|
10
|
+
dx/y, x dx/y, ..., x^(g-1) dx/y.
|
|
11
|
+
|
|
12
|
+
The first homology has rank ``2g``; integrating the ``g`` differentials over a
|
|
13
|
+
homology basis produces the period data behind the Jacobian. In genus one the
|
|
14
|
+
same construction gives the two-period lattice of elliptic-function theory.
|
|
15
|
+
See Forster, *Lectures on Riemann Surfaces*, and Farkas--Kra, *Riemann
|
|
16
|
+
Surfaces*. For an explicit hyperelliptic differential basis see also the
|
|
17
|
+
references collected in ``docs/REFERENCES.md``.
|
|
18
|
+
|
|
19
|
+
Shakespeare reconstruction
|
|
20
|
+
---------------------------
|
|
21
|
+
The process-first order is deliberately the reverse of a named special-function
|
|
22
|
+
solver. A process first emits an algebraic quotient. This module then asks
|
|
23
|
+
which canonical differentials the quotient itself carries and how many global
|
|
24
|
+
cycle directions can contribute history residuals.
|
|
25
|
+
|
|
26
|
+
A ``HyperellipticDifferential`` is intentionally represented as a coefficient
|
|
27
|
+
of ``dx`` rather than as a SymPy differential object. This keeps the algebraic
|
|
28
|
+
backend simple while retaining the exact mathematical form ``x^k dx/y``. Its
|
|
29
|
+
``pullback_coefficient`` method asks what the differential becomes along a
|
|
30
|
+
chosen process ``dx/dt``. For example, if a reduced process satisfies
|
|
31
|
+
``dx/dt = y``, then ``dx/y`` pulls back to ``dt`` exactly.
|
|
32
|
+
|
|
33
|
+
Boundary
|
|
34
|
+
--------
|
|
35
|
+
This module does not choose homology cycles, analytically continue square-root
|
|
36
|
+
branches, compute period matrices, prove uniformization, or construct a
|
|
37
|
+
Jacobian as a complex torus. ``homology_rank = 2g`` is topological structure;
|
|
38
|
+
it is not a numerically computed period lattice. Concrete cycle integrals
|
|
39
|
+
belong in cited calibration tests until a genuinely reusable period engine is
|
|
40
|
+
forced by more than one example.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
from __future__ import annotations
|
|
44
|
+
|
|
45
|
+
from dataclasses import dataclass
|
|
46
|
+
|
|
47
|
+
import sympy as sp
|
|
48
|
+
|
|
49
|
+
from .algebraic import HyperellipticProfile
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class HyperellipticDifferential:
|
|
54
|
+
"""One canonical differential ``x^power dx / y`` on a hyperelliptic curve."""
|
|
55
|
+
|
|
56
|
+
curve: HyperellipticProfile
|
|
57
|
+
power: int
|
|
58
|
+
|
|
59
|
+
def __post_init__(self) -> None:
|
|
60
|
+
if self.power < 0:
|
|
61
|
+
raise ValueError("differential power must be non-negative")
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def numerator(self) -> sp.Expr:
|
|
65
|
+
return self.curve.x ** self.power
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def coefficient(self) -> sp.Expr:
|
|
69
|
+
"""Return the coefficient of ``dx`` in ``x^power dx/y``."""
|
|
70
|
+
|
|
71
|
+
return self.numerator / self.curve.y
|
|
72
|
+
|
|
73
|
+
def pullback_coefficient(self, dx_dt: sp.Expr) -> sp.Expr:
|
|
74
|
+
"""Return the coefficient of ``dt`` after substituting ``dx=dx_dt*dt``."""
|
|
75
|
+
|
|
76
|
+
return sp.cancel(sp.sympify(dx_dt) * self.numerator / self.curve.y)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True)
|
|
80
|
+
class AbelianIntegralProfile:
|
|
81
|
+
"""Canonical differential/homology profile of a generic smooth quotient.
|
|
82
|
+
|
|
83
|
+
``abelian_dimension`` is the genus ``g`` and hence the number of independent
|
|
84
|
+
holomorphic differentials. ``homology_rank`` is ``2g``. These two numbers
|
|
85
|
+
are the dimensions that later enter the Abel--Jacobi/Jacobian construction;
|
|
86
|
+
no period values are claimed here.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
curve: HyperellipticProfile
|
|
90
|
+
differentials: tuple[HyperellipticDifferential, ...]
|
|
91
|
+
abelian_dimension: int
|
|
92
|
+
homology_rank: int
|
|
93
|
+
|
|
94
|
+
def pullback_coefficients(self, dx_dt: sp.Expr) -> tuple[sp.Expr, ...]:
|
|
95
|
+
"""Pull every canonical differential back along one reduced process."""
|
|
96
|
+
|
|
97
|
+
return tuple(
|
|
98
|
+
differential.pullback_coefficient(dx_dt)
|
|
99
|
+
for differential in self.differentials
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def holomorphic_differential_basis(
|
|
104
|
+
curve: HyperellipticProfile,
|
|
105
|
+
) -> tuple[HyperellipticDifferential, ...]:
|
|
106
|
+
"""Return ``dx/y, x dx/y, ..., x^(g-1) dx/y`` for generic genus ``g``.
|
|
107
|
+
|
|
108
|
+
The routine requires the curve profile to have a generic smooth genus. For
|
|
109
|
+
genus zero the returned basis is empty.
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
genus = curve.generic_genus
|
|
113
|
+
if genus is None:
|
|
114
|
+
raise ValueError("holomorphic basis requires a generically smooth curve")
|
|
115
|
+
return tuple(HyperellipticDifferential(curve, power) for power in range(genus))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def abelian_integral_profile(curve: HyperellipticProfile) -> AbelianIntegralProfile:
|
|
119
|
+
"""Attach canonical differential and first-homology dimensions to a curve."""
|
|
120
|
+
|
|
121
|
+
basis = holomorphic_differential_basis(curve)
|
|
122
|
+
genus = curve.generic_genus
|
|
123
|
+
assert genus is not None
|
|
124
|
+
return AbelianIntegralProfile(
|
|
125
|
+
curve=curve,
|
|
126
|
+
differentials=basis,
|
|
127
|
+
abelian_dimension=genus,
|
|
128
|
+
homology_rank=2 * genus,
|
|
129
|
+
)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Algebraic-curve profiles for process quotients.
|
|
2
|
+
|
|
3
|
+
Mathematical lineage
|
|
4
|
+
--------------------
|
|
5
|
+
Elliptic and Abelian function theory historically did not begin as a catalogue
|
|
6
|
+
of special functions. Elliptic integrals led to inversion; inversion exposed
|
|
7
|
+
periods; periods produced complex tori; and the resulting function theory was
|
|
8
|
+
then algebraized by relations such as the Weierstrass cubic. Riemann surfaces,
|
|
9
|
+
algebraic curves, Abelian integrals, and Jacobians grew from this analytic and
|
|
10
|
+
geometric circle of ideas.
|
|
11
|
+
|
|
12
|
+
Shakespeare uses the same history in reverse as a calibration principle. A
|
|
13
|
+
primitive process may first force a constraint/invariant quotient. Only after
|
|
14
|
+
that quotient is visible do we ask what geometry and what function language are
|
|
15
|
+
adequate. Thus a relation ``y**2 = P(x)`` is not introduced because we already
|
|
16
|
+
know the answer is elliptic or hyperelliptic; it is an algebraic shadow emitted
|
|
17
|
+
by the process reduction.
|
|
18
|
+
|
|
19
|
+
Implementation
|
|
20
|
+
--------------
|
|
21
|
+
This module deliberately implements only a small, exact observable:
|
|
22
|
+
``HyperellipticProfile`` records degree, discriminant, generic genus, and the
|
|
23
|
+
degeneration condition for ``y**2 = P(x)``. That is enough for classical tests
|
|
24
|
+
to distinguish genus-zero, genus-one, and higher-genus quotient regimes without
|
|
25
|
+
preloading the corresponding named function theory.
|
|
26
|
+
|
|
27
|
+
Boundary
|
|
28
|
+
--------
|
|
29
|
+
Genus is not a complete process normal form, and this module is not a general
|
|
30
|
+
algebraic-geometry engine. Period lattices, Abel-Jacobi maps, Jacobians, and
|
|
31
|
+
function-field compression belong to later layers and should be derived when a
|
|
32
|
+
calibration actually requires them.
|
|
33
|
+
|
|
34
|
+
See ``docs/08-function-theory-genus-hierarchy.md`` and
|
|
35
|
+
``docs/09-literate-programming-and-mathematical-lineage.md``.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
from dataclasses import dataclass
|
|
41
|
+
|
|
42
|
+
import sympy as sp
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class HyperellipticProfile:
|
|
47
|
+
"""Exact profile of ``y**2 = polynomial(x)`` over symbolic parameters."""
|
|
48
|
+
|
|
49
|
+
x: sp.Symbol
|
|
50
|
+
y: sp.Symbol
|
|
51
|
+
polynomial: sp.Expr
|
|
52
|
+
degree: int
|
|
53
|
+
discriminant: sp.Expr
|
|
54
|
+
generic_genus: int | None
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def relation(self) -> sp.Expr:
|
|
58
|
+
return sp.expand(self.y**2 - self.polynomial)
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def generically_smooth(self) -> bool:
|
|
62
|
+
"""Whether the discriminant is not identically zero."""
|
|
63
|
+
|
|
64
|
+
return sp.simplify(self.discriminant) != 0
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def degeneration_condition(self) -> sp.Expr:
|
|
68
|
+
"""Parameter expression whose vanishing marks repeated branch points."""
|
|
69
|
+
|
|
70
|
+
return sp.factor(self.discriminant)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def hyperelliptic_profile(
|
|
74
|
+
x: sp.Symbol,
|
|
75
|
+
y: sp.Symbol,
|
|
76
|
+
polynomial: sp.Expr,
|
|
77
|
+
) -> HyperellipticProfile:
|
|
78
|
+
"""Analyze a process quotient in hyperelliptic form ``y**2 = P(x)``.
|
|
79
|
+
|
|
80
|
+
For square-free ``P`` of degree ``d >= 1``, the smooth projective
|
|
81
|
+
hyperelliptic curve has genus ``floor((d-1)/2)``. With symbolic parameters,
|
|
82
|
+
a nonzero discriminant means that this is the *generic* genus away from the
|
|
83
|
+
displayed degeneration locus.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
polynomial = sp.expand(sp.sympify(polynomial))
|
|
87
|
+
try:
|
|
88
|
+
poly = sp.Poly(polynomial, x)
|
|
89
|
+
except sp.PolynomialError as exc:
|
|
90
|
+
raise ValueError("hyperelliptic polynomial must be polynomial in x") from exc
|
|
91
|
+
|
|
92
|
+
degree = int(poly.degree())
|
|
93
|
+
if degree < 1:
|
|
94
|
+
raise ValueError("hyperelliptic polynomial must have positive degree")
|
|
95
|
+
discriminant = sp.factor(sp.discriminant(poly.as_expr(), x))
|
|
96
|
+
generic_genus = (degree - 1) // 2 if discriminant != 0 else None
|
|
97
|
+
|
|
98
|
+
return HyperellipticProfile(
|
|
99
|
+
x=x,
|
|
100
|
+
y=y,
|
|
101
|
+
polynomial=polynomial,
|
|
102
|
+
degree=degree,
|
|
103
|
+
discriminant=discriminant,
|
|
104
|
+
generic_genus=generic_genus,
|
|
105
|
+
)
|