odeanalysis 0.1.0__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.
- odeanalysis/__init__.py +296 -0
- odeanalysis/_api_policy.py +179 -0
- odeanalysis/_assumptions.py +89 -0
- odeanalysis/_block_common.py +106 -0
- odeanalysis/_formal_gauge.py +115 -0
- odeanalysis/_local.py +166 -0
- odeanalysis/_moser.py +271 -0
- odeanalysis/_power_simplify.py +32 -0
- odeanalysis/_spectral.py +215 -0
- odeanalysis/_symbolic_compare.py +16 -0
- odeanalysis/_symbolic_errors.py +19 -0
- odeanalysis/_zero.py +28 -0
- odeanalysis/analytic_continuation.py +343 -0
- odeanalysis/bell.py +87 -0
- odeanalysis/block_decomposition.py +1144 -0
- odeanalysis/canonical.py +471 -0
- odeanalysis/certified_continuation.py +160 -0
- odeanalysis/diagnostics.py +17 -0
- odeanalysis/dominance.py +134 -0
- odeanalysis/factorization.py +88 -0
- odeanalysis/formal.py +1028 -0
- odeanalysis/formal_basis.py +1009 -0
- odeanalysis/frobenius.py +349 -0
- odeanalysis/fuchsian.py +400 -0
- odeanalysis/interchange.py +604 -0
- odeanalysis/interoperability.py +143 -0
- odeanalysis/irregular.py +250 -0
- odeanalysis/kovacic.py +478 -0
- odeanalysis/levelt.py +679 -0
- odeanalysis/local_analysis.py +386 -0
- odeanalysis/local_structure.py +290 -0
- odeanalysis/matrix_series.py +357 -0
- odeanalysis/newton.py +501 -0
- odeanalysis/operator.py +193 -0
- odeanalysis/parameter_wkb.py +92 -0
- odeanalysis/py.typed +0 -0
- odeanalysis/series.py +199 -0
- odeanalysis/singularities.py +279 -0
- odeanalysis/stokes.py +782 -0
- odeanalysis/system.py +347 -0
- odeanalysis/system_analysis.py +615 -0
- odeanalysis/transition_loci.py +302 -0
- odeanalysis/turning.py +516 -0
- odeanalysis/wronskian.py +110 -0
- odeanalysis-0.1.0.dist-info/METADATA +180 -0
- odeanalysis-0.1.0.dist-info/RECORD +49 -0
- odeanalysis-0.1.0.dist-info/WHEEL +5 -0
- odeanalysis-0.1.0.dist-info/licenses/LICENSE +677 -0
- odeanalysis-0.1.0.dist-info/top_level.txt +1 -0
odeanalysis/__init__.py
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""Primary public API for symbolic structural ODE analysis.
|
|
2
|
+
|
|
3
|
+
Expert APIs remain available from their defining submodules; see
|
|
4
|
+
``docs/api-classification.md`` for the stability policy.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
__version__ = "0.25.2"
|
|
8
|
+
|
|
9
|
+
from ._moser import moser_reduce
|
|
10
|
+
from .analytic_continuation import (
|
|
11
|
+
CanonicalBasis,
|
|
12
|
+
ConnectionMatrix,
|
|
13
|
+
LocalMonodromy,
|
|
14
|
+
StokesMatrix,
|
|
15
|
+
connection_matrix,
|
|
16
|
+
hypergeometric_connection_matrix,
|
|
17
|
+
kummer_connection_matrices,
|
|
18
|
+
local_monodromy,
|
|
19
|
+
stokes_matrices,
|
|
20
|
+
)
|
|
21
|
+
from .block_decomposition import (
|
|
22
|
+
LeveltTurrittinReduction,
|
|
23
|
+
formal_block_diagonalize,
|
|
24
|
+
levelt_turrittin_reduce,
|
|
25
|
+
)
|
|
26
|
+
from .canonical import (
|
|
27
|
+
CanonicalEquationFamily,
|
|
28
|
+
CanonicalEquationRecognition,
|
|
29
|
+
recognize_canonical_equation,
|
|
30
|
+
transform_to_canonical,
|
|
31
|
+
)
|
|
32
|
+
from .certified_continuation import (
|
|
33
|
+
CertifiedContinuationResult,
|
|
34
|
+
CertifiedMatrixEnclosure,
|
|
35
|
+
certified_system_continuation,
|
|
36
|
+
)
|
|
37
|
+
from .dominance import (
|
|
38
|
+
SolutionDominanceAnalysis,
|
|
39
|
+
classify_solution_dominance,
|
|
40
|
+
)
|
|
41
|
+
from .factorization import (
|
|
42
|
+
FirstOrderFactorization,
|
|
43
|
+
factor_differential_operator,
|
|
44
|
+
is_reducible_operator,
|
|
45
|
+
)
|
|
46
|
+
from .formal import complete_formal_exponential_parts, formal_asymptotic_solutions
|
|
47
|
+
from .formal_basis import formal_monodromy, logarithmic_frobenius_basis
|
|
48
|
+
from .frobenius import FrobeniusAnalysis, frobenius_analysis
|
|
49
|
+
from .fuchsian import (
|
|
50
|
+
ApparentSingularityAnalysis,
|
|
51
|
+
FuchsRelation,
|
|
52
|
+
RiemannScheme,
|
|
53
|
+
apparent_singularity_analysis,
|
|
54
|
+
fuchs_relation,
|
|
55
|
+
is_apparent_singularity,
|
|
56
|
+
riemann_scheme,
|
|
57
|
+
)
|
|
58
|
+
from .interchange import FormalODEData, formal_ode_data
|
|
59
|
+
from .interoperability import (
|
|
60
|
+
CyclicScalarization,
|
|
61
|
+
ScalarSystemCorrespondence,
|
|
62
|
+
scalar_system_correspondence,
|
|
63
|
+
scalarize_system,
|
|
64
|
+
)
|
|
65
|
+
from .irregular import formal_exponential_parts, wkb_ansatze
|
|
66
|
+
from .kovacic import KovacicAnalysis, KovacicOutcome, kovacic_analysis
|
|
67
|
+
from .levelt import LeveltStructure, levelt_structure
|
|
68
|
+
from .local_analysis import (
|
|
69
|
+
LocalAnalysisStratum,
|
|
70
|
+
ParameterizedLocalAnalysis,
|
|
71
|
+
ResonanceStratum,
|
|
72
|
+
local_parameter_analysis,
|
|
73
|
+
)
|
|
74
|
+
from .local_structure import (
|
|
75
|
+
FrobeniusConvergence,
|
|
76
|
+
FrobeniusLocalMonodromy,
|
|
77
|
+
SingularityPointStructure,
|
|
78
|
+
SingularityStructure,
|
|
79
|
+
frobenius_convergence,
|
|
80
|
+
frobenius_local_monodromy,
|
|
81
|
+
singularity_structure,
|
|
82
|
+
)
|
|
83
|
+
from .matrix_series import MatrixLaurentSeries
|
|
84
|
+
from .newton import (
|
|
85
|
+
DifferentialNewtonPolygon,
|
|
86
|
+
SlopeFiltration,
|
|
87
|
+
differential_newton_polygon,
|
|
88
|
+
katz_rank,
|
|
89
|
+
newton_slopes,
|
|
90
|
+
poincare_rank,
|
|
91
|
+
slope_filtration,
|
|
92
|
+
)
|
|
93
|
+
from .operator import LinearDifferentialOperator
|
|
94
|
+
from .parameter_wkb import (
|
|
95
|
+
ParameterizedTurningAnalysis,
|
|
96
|
+
ParameterizedTurningStratum,
|
|
97
|
+
parameterized_turning_analysis,
|
|
98
|
+
)
|
|
99
|
+
from .singularities import (
|
|
100
|
+
ODESingularityAnalysis,
|
|
101
|
+
ODESingularityKind,
|
|
102
|
+
analyze_ode_singularities,
|
|
103
|
+
classify_ode_point,
|
|
104
|
+
ode_singular_points,
|
|
105
|
+
)
|
|
106
|
+
from .stokes import StokesGeometry, stokes_geometry
|
|
107
|
+
from .system import FirstOrderSystem
|
|
108
|
+
from .system_analysis import (
|
|
109
|
+
FormalReductionCertificate,
|
|
110
|
+
FormalSystemAnalysis,
|
|
111
|
+
ParameterizedSystemAnalysis,
|
|
112
|
+
ParameterizedSystemFormalTypes,
|
|
113
|
+
SystemFormalTypeSignature,
|
|
114
|
+
SystemFormalTypeStratum,
|
|
115
|
+
SystemParameterStratum,
|
|
116
|
+
SystemResonance,
|
|
117
|
+
SystemSingularityAnalysis,
|
|
118
|
+
SystemStokesGeometry,
|
|
119
|
+
SystemStokesPair,
|
|
120
|
+
analyze_system_singularity,
|
|
121
|
+
formal_system_analysis,
|
|
122
|
+
system_formal_type_stratification,
|
|
123
|
+
system_parameter_analysis,
|
|
124
|
+
system_stokes_geometry,
|
|
125
|
+
)
|
|
126
|
+
from .transition_loci import (
|
|
127
|
+
LeadingMatrixRankAnalysis,
|
|
128
|
+
ProjectivePolynomialStratum,
|
|
129
|
+
leading_rank_analysis,
|
|
130
|
+
newton_loci,
|
|
131
|
+
singularity_loci,
|
|
132
|
+
singularity_projective_strata,
|
|
133
|
+
stokes_formal_loci,
|
|
134
|
+
stokes_ray_loci,
|
|
135
|
+
turning_loci,
|
|
136
|
+
turning_point_projective_strata,
|
|
137
|
+
)
|
|
138
|
+
from .turning import (
|
|
139
|
+
LiouvilleNormalForm,
|
|
140
|
+
TurningPoint,
|
|
141
|
+
TurningPointAnalysis,
|
|
142
|
+
TurningPointKind,
|
|
143
|
+
UniformWKBReduction,
|
|
144
|
+
WKBExpansion,
|
|
145
|
+
airy_uniformization,
|
|
146
|
+
analyze_turning_points,
|
|
147
|
+
classify_turning_point,
|
|
148
|
+
liouville_normal_form,
|
|
149
|
+
turning_points,
|
|
150
|
+
weber_uniformization,
|
|
151
|
+
wkb_expansion,
|
|
152
|
+
)
|
|
153
|
+
from .wronskian import WronskianAnalysis, abel_wronskian, wronskian_analysis
|
|
154
|
+
|
|
155
|
+
__all__ = (
|
|
156
|
+
"ApparentSingularityAnalysis",
|
|
157
|
+
"CanonicalBasis",
|
|
158
|
+
"CanonicalEquationFamily",
|
|
159
|
+
"CanonicalEquationRecognition",
|
|
160
|
+
"CertifiedContinuationResult",
|
|
161
|
+
"CertifiedMatrixEnclosure",
|
|
162
|
+
"ConnectionMatrix",
|
|
163
|
+
"CyclicScalarization",
|
|
164
|
+
"DifferentialNewtonPolygon",
|
|
165
|
+
"FirstOrderFactorization",
|
|
166
|
+
"FirstOrderSystem",
|
|
167
|
+
"FormalODEData",
|
|
168
|
+
"FormalReductionCertificate",
|
|
169
|
+
"FormalSystemAnalysis",
|
|
170
|
+
"FrobeniusAnalysis",
|
|
171
|
+
"FrobeniusConvergence",
|
|
172
|
+
"FrobeniusLocalMonodromy",
|
|
173
|
+
"FuchsRelation",
|
|
174
|
+
"KovacicAnalysis",
|
|
175
|
+
"KovacicOutcome",
|
|
176
|
+
"LeadingMatrixRankAnalysis",
|
|
177
|
+
"LeveltStructure",
|
|
178
|
+
"LeveltTurrittinReduction",
|
|
179
|
+
"LinearDifferentialOperator",
|
|
180
|
+
"LiouvilleNormalForm",
|
|
181
|
+
"LocalAnalysisStratum",
|
|
182
|
+
"LocalMonodromy",
|
|
183
|
+
"MatrixLaurentSeries",
|
|
184
|
+
"ODESingularityAnalysis",
|
|
185
|
+
"ODESingularityKind",
|
|
186
|
+
"ParameterizedLocalAnalysis",
|
|
187
|
+
"ParameterizedSystemAnalysis",
|
|
188
|
+
"ParameterizedSystemFormalTypes",
|
|
189
|
+
"ParameterizedTurningAnalysis",
|
|
190
|
+
"ParameterizedTurningStratum",
|
|
191
|
+
"ProjectivePolynomialStratum",
|
|
192
|
+
"ResonanceStratum",
|
|
193
|
+
"RiemannScheme",
|
|
194
|
+
"ScalarSystemCorrespondence",
|
|
195
|
+
"SingularityPointStructure",
|
|
196
|
+
"SingularityStructure",
|
|
197
|
+
"SlopeFiltration",
|
|
198
|
+
"SolutionDominanceAnalysis",
|
|
199
|
+
"StokesGeometry",
|
|
200
|
+
"StokesMatrix",
|
|
201
|
+
"SystemFormalTypeSignature",
|
|
202
|
+
"SystemFormalTypeStratum",
|
|
203
|
+
"SystemParameterStratum",
|
|
204
|
+
"SystemResonance",
|
|
205
|
+
"SystemSingularityAnalysis",
|
|
206
|
+
"SystemStokesGeometry",
|
|
207
|
+
"SystemStokesPair",
|
|
208
|
+
"TurningPoint",
|
|
209
|
+
"TurningPointAnalysis",
|
|
210
|
+
"TurningPointKind",
|
|
211
|
+
"UniformWKBReduction",
|
|
212
|
+
"WKBExpansion",
|
|
213
|
+
"WronskianAnalysis",
|
|
214
|
+
"__version__",
|
|
215
|
+
"abel_wronskian",
|
|
216
|
+
"airy_uniformization",
|
|
217
|
+
"analyze_ode_singularities",
|
|
218
|
+
"analyze_system_singularity",
|
|
219
|
+
"analyze_turning_points",
|
|
220
|
+
"apparent_singularity_analysis",
|
|
221
|
+
"certified_system_continuation",
|
|
222
|
+
"classify_ode_point",
|
|
223
|
+
"classify_solution_dominance",
|
|
224
|
+
"classify_turning_point",
|
|
225
|
+
"complete_formal_exponential_parts",
|
|
226
|
+
"connection_matrix",
|
|
227
|
+
"differential_newton_polygon",
|
|
228
|
+
"factor_differential_operator",
|
|
229
|
+
"formal_asymptotic_solutions",
|
|
230
|
+
"formal_block_diagonalize",
|
|
231
|
+
"formal_exponential_parts",
|
|
232
|
+
"formal_monodromy",
|
|
233
|
+
"formal_ode_data",
|
|
234
|
+
"formal_system_analysis",
|
|
235
|
+
"frobenius_analysis",
|
|
236
|
+
"frobenius_convergence",
|
|
237
|
+
"frobenius_local_monodromy",
|
|
238
|
+
"fuchs_relation",
|
|
239
|
+
"hypergeometric_connection_matrix",
|
|
240
|
+
"is_apparent_singularity",
|
|
241
|
+
"is_reducible_operator",
|
|
242
|
+
"katz_rank",
|
|
243
|
+
"kovacic_analysis",
|
|
244
|
+
"kummer_connection_matrices",
|
|
245
|
+
"leading_rank_analysis",
|
|
246
|
+
"levelt_structure",
|
|
247
|
+
"levelt_turrittin_reduce",
|
|
248
|
+
"liouville_normal_form",
|
|
249
|
+
"local_monodromy",
|
|
250
|
+
"local_parameter_analysis",
|
|
251
|
+
"logarithmic_frobenius_basis",
|
|
252
|
+
"moser_reduce",
|
|
253
|
+
"newton_loci",
|
|
254
|
+
"newton_slopes",
|
|
255
|
+
"ode_singular_points",
|
|
256
|
+
"parameterized_turning_analysis",
|
|
257
|
+
"poincare_rank",
|
|
258
|
+
"recognize_canonical_equation",
|
|
259
|
+
"riemann_scheme",
|
|
260
|
+
"scalar_system_correspondence",
|
|
261
|
+
"scalarize_system",
|
|
262
|
+
"singularity_loci",
|
|
263
|
+
"singularity_projective_strata",
|
|
264
|
+
"singularity_structure",
|
|
265
|
+
"slope_filtration",
|
|
266
|
+
"stokes_formal_loci",
|
|
267
|
+
"stokes_geometry",
|
|
268
|
+
"stokes_matrices",
|
|
269
|
+
"stokes_ray_loci",
|
|
270
|
+
"system_formal_type_stratification",
|
|
271
|
+
"system_parameter_analysis",
|
|
272
|
+
"system_stokes_geometry",
|
|
273
|
+
"transform_to_canonical",
|
|
274
|
+
"turning_loci",
|
|
275
|
+
"turning_point_projective_strata",
|
|
276
|
+
"turning_points",
|
|
277
|
+
"weber_uniformization",
|
|
278
|
+
"wkb_ansatze",
|
|
279
|
+
"wkb_expansion",
|
|
280
|
+
"wronskian_analysis",
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def __dir__() -> list[str]:
|
|
285
|
+
"""Return the documented root API and standard module metadata."""
|
|
286
|
+
|
|
287
|
+
metadata = {
|
|
288
|
+
"__doc__",
|
|
289
|
+
"__file__",
|
|
290
|
+
"__loader__",
|
|
291
|
+
"__name__",
|
|
292
|
+
"__package__",
|
|
293
|
+
"__path__",
|
|
294
|
+
"__spec__",
|
|
295
|
+
}
|
|
296
|
+
return sorted(metadata | set(__all__))
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""Classification of the supported public API surface.
|
|
2
|
+
|
|
3
|
+
Primary names are available directly from :mod:`odeanalysis`. Expert names
|
|
4
|
+
remain public from their defining submodules. Private modules and helpers are
|
|
5
|
+
implementation details and carry no compatibility contract.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
PRIMARY_EXPORTS: dict[str, str] = {
|
|
11
|
+
"FormalSystemAnalysis": ".system_analysis",
|
|
12
|
+
"ParameterizedSystemAnalysis": ".system_analysis",
|
|
13
|
+
"SystemParameterStratum": ".system_analysis",
|
|
14
|
+
"SystemResonance": ".system_analysis",
|
|
15
|
+
"SystemSingularityAnalysis": ".system_analysis",
|
|
16
|
+
"SystemStokesGeometry": ".system_analysis",
|
|
17
|
+
"SystemStokesPair": ".system_analysis",
|
|
18
|
+
"analyze_system_singularity": ".system_analysis",
|
|
19
|
+
"formal_system_analysis": ".system_analysis",
|
|
20
|
+
"system_parameter_analysis": ".system_analysis",
|
|
21
|
+
"system_stokes_geometry": ".system_analysis",
|
|
22
|
+
"FrobeniusConvergence": ".local_structure",
|
|
23
|
+
"FrobeniusLocalMonodromy": ".local_structure",
|
|
24
|
+
"ResonanceStratum": ".local_analysis",
|
|
25
|
+
"SingularityPointStructure": ".local_structure",
|
|
26
|
+
"SingularityStructure": ".local_structure",
|
|
27
|
+
"WronskianAnalysis": ".wronskian",
|
|
28
|
+
"abel_wronskian": ".wronskian",
|
|
29
|
+
"frobenius_convergence": ".local_structure",
|
|
30
|
+
"frobenius_local_monodromy": ".local_structure",
|
|
31
|
+
"singularity_structure": ".local_structure",
|
|
32
|
+
"wronskian_analysis": ".wronskian",
|
|
33
|
+
"CanonicalBasis": ".analytic_continuation",
|
|
34
|
+
"ConnectionMatrix": ".analytic_continuation",
|
|
35
|
+
"LocalAnalysisStratum": ".local_analysis",
|
|
36
|
+
"LocalMonodromy": ".analytic_continuation",
|
|
37
|
+
"StokesMatrix": ".analytic_continuation",
|
|
38
|
+
"connection_matrix": ".analytic_continuation",
|
|
39
|
+
"hypergeometric_connection_matrix": ".analytic_continuation",
|
|
40
|
+
"kummer_connection_matrices": ".analytic_continuation",
|
|
41
|
+
"local_monodromy": ".analytic_continuation",
|
|
42
|
+
"stokes_matrices": ".analytic_continuation",
|
|
43
|
+
"LiouvilleNormalForm": ".turning",
|
|
44
|
+
"TurningPoint": ".turning",
|
|
45
|
+
"TurningPointAnalysis": ".turning",
|
|
46
|
+
"TurningPointKind": ".turning",
|
|
47
|
+
"UniformWKBReduction": ".turning",
|
|
48
|
+
"WKBExpansion": ".turning",
|
|
49
|
+
"airy_uniformization": ".turning",
|
|
50
|
+
"analyze_turning_points": ".turning",
|
|
51
|
+
"classify_turning_point": ".turning",
|
|
52
|
+
"liouville_normal_form": ".turning",
|
|
53
|
+
"turning_points": ".turning",
|
|
54
|
+
"weber_uniformization": ".turning",
|
|
55
|
+
"wkb_expansion": ".turning",
|
|
56
|
+
"CanonicalEquationFamily": ".canonical",
|
|
57
|
+
"CanonicalEquationRecognition": ".canonical",
|
|
58
|
+
"FirstOrderFactorization": ".factorization",
|
|
59
|
+
"KovacicAnalysis": ".kovacic",
|
|
60
|
+
"KovacicOutcome": ".kovacic",
|
|
61
|
+
"factor_differential_operator": ".factorization",
|
|
62
|
+
"is_reducible_operator": ".factorization",
|
|
63
|
+
"kovacic_analysis": ".kovacic",
|
|
64
|
+
"recognize_canonical_equation": ".canonical",
|
|
65
|
+
"transform_to_canonical": ".canonical",
|
|
66
|
+
"DifferentialNewtonPolygon": ".newton",
|
|
67
|
+
"differential_newton_polygon": ".newton",
|
|
68
|
+
"ApparentSingularityAnalysis": ".fuchsian",
|
|
69
|
+
"FormalODEData": ".interchange",
|
|
70
|
+
"FrobeniusAnalysis": ".frobenius",
|
|
71
|
+
"FirstOrderSystem": ".system",
|
|
72
|
+
"FuchsRelation": ".fuchsian",
|
|
73
|
+
"LeveltStructure": ".levelt",
|
|
74
|
+
"LeveltTurrittinReduction": ".block_decomposition",
|
|
75
|
+
"LinearDifferentialOperator": ".operator",
|
|
76
|
+
"MatrixLaurentSeries": ".matrix_series",
|
|
77
|
+
"ODESingularityAnalysis": ".singularities",
|
|
78
|
+
"ODESingularityKind": ".singularities",
|
|
79
|
+
"ParameterizedLocalAnalysis": ".local_analysis",
|
|
80
|
+
"RiemannScheme": ".fuchsian",
|
|
81
|
+
"SlopeFiltration": ".newton",
|
|
82
|
+
"SolutionDominanceAnalysis": ".dominance",
|
|
83
|
+
"StokesGeometry": ".stokes",
|
|
84
|
+
"analyze_ode_singularities": ".singularities",
|
|
85
|
+
"apparent_singularity_analysis": ".fuchsian",
|
|
86
|
+
"classify_ode_point": ".singularities",
|
|
87
|
+
"classify_solution_dominance": ".dominance",
|
|
88
|
+
"complete_formal_exponential_parts": ".formal",
|
|
89
|
+
"formal_asymptotic_solutions": ".formal",
|
|
90
|
+
"formal_block_diagonalize": ".block_decomposition",
|
|
91
|
+
"formal_exponential_parts": ".irregular",
|
|
92
|
+
"formal_monodromy": ".formal_basis",
|
|
93
|
+
"formal_ode_data": ".interchange",
|
|
94
|
+
"frobenius_analysis": ".frobenius",
|
|
95
|
+
"fuchs_relation": ".fuchsian",
|
|
96
|
+
"is_apparent_singularity": ".fuchsian",
|
|
97
|
+
"katz_rank": ".newton",
|
|
98
|
+
"levelt_structure": ".levelt",
|
|
99
|
+
"levelt_turrittin_reduce": ".block_decomposition",
|
|
100
|
+
"logarithmic_frobenius_basis": ".formal_basis",
|
|
101
|
+
"moser_reduce": "._moser",
|
|
102
|
+
"newton_slopes": ".newton",
|
|
103
|
+
"ode_singular_points": ".singularities",
|
|
104
|
+
"local_parameter_analysis": ".local_analysis",
|
|
105
|
+
"LeadingMatrixRankAnalysis": ".transition_loci",
|
|
106
|
+
"ProjectivePolynomialStratum": ".transition_loci",
|
|
107
|
+
"leading_rank_analysis": ".transition_loci",
|
|
108
|
+
"newton_loci": ".transition_loci",
|
|
109
|
+
"singularity_loci": ".transition_loci",
|
|
110
|
+
"singularity_projective_strata": ".transition_loci",
|
|
111
|
+
"stokes_formal_loci": ".transition_loci",
|
|
112
|
+
"stokes_ray_loci": ".transition_loci",
|
|
113
|
+
"turning_point_projective_strata": ".transition_loci",
|
|
114
|
+
"turning_loci": ".transition_loci",
|
|
115
|
+
"poincare_rank": ".newton",
|
|
116
|
+
"riemann_scheme": ".fuchsian",
|
|
117
|
+
"slope_filtration": ".newton",
|
|
118
|
+
"stokes_geometry": ".stokes",
|
|
119
|
+
"wkb_ansatze": ".irregular",
|
|
120
|
+
"CertifiedContinuationResult": ".certified_continuation",
|
|
121
|
+
"CertifiedMatrixEnclosure": ".certified_continuation",
|
|
122
|
+
"certified_system_continuation": ".certified_continuation",
|
|
123
|
+
"CyclicScalarization": ".interoperability",
|
|
124
|
+
"ScalarSystemCorrespondence": ".interoperability",
|
|
125
|
+
"scalarize_system": ".interoperability",
|
|
126
|
+
"scalar_system_correspondence": ".interoperability",
|
|
127
|
+
"FormalReductionCertificate": ".system_analysis",
|
|
128
|
+
"ParameterizedSystemFormalTypes": ".system_analysis",
|
|
129
|
+
"SystemFormalTypeSignature": ".system_analysis",
|
|
130
|
+
"SystemFormalTypeStratum": ".system_analysis",
|
|
131
|
+
"system_formal_type_stratification": ".system_analysis",
|
|
132
|
+
"ParameterizedTurningAnalysis": ".parameter_wkb",
|
|
133
|
+
"ParameterizedTurningStratum": ".parameter_wkb",
|
|
134
|
+
"parameterized_turning_analysis": ".parameter_wkb",
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
EXPERT_EXPORTS: dict[str, str] = {
|
|
138
|
+
"KovacicCase2Certificate": ".kovacic",
|
|
139
|
+
"KovacicCase3Certificate": ".kovacic",
|
|
140
|
+
"CompleteFormalExponentialPart": ".formal",
|
|
141
|
+
"DifferentialNewtonEdge": ".newton",
|
|
142
|
+
"DifferentialNewtonPoint": ".newton",
|
|
143
|
+
"ExponentialBlockDecomposition": ".block_decomposition",
|
|
144
|
+
"FormalAmplitudeSeries": ".formal",
|
|
145
|
+
"FormalAsymptoticSolution": ".formal",
|
|
146
|
+
"FormalBlockDiagonalization": ".block_decomposition",
|
|
147
|
+
"FormalBlockPartition": ".system",
|
|
148
|
+
"FormalExponentialPart": ".irregular",
|
|
149
|
+
"FormalLogarithmicBasis": ".formal_basis",
|
|
150
|
+
"FormalMonodromy": ".formal_basis",
|
|
151
|
+
"IrregularSingularityInvariants": ".irregular",
|
|
152
|
+
"RamificationStep": ".block_decomposition",
|
|
153
|
+
"RegularSingularLeveltReduction": ".levelt",
|
|
154
|
+
"SparseLaurentSeries": ".series",
|
|
155
|
+
"StokesConnectionPattern": ".stokes",
|
|
156
|
+
"StokesPairGeometry": ".stokes",
|
|
157
|
+
"StokesRay": ".stokes",
|
|
158
|
+
"StokesSector": ".stokes",
|
|
159
|
+
"WKBAnsatz": ".irregular",
|
|
160
|
+
"companion_system": ".system",
|
|
161
|
+
"complete_exponential_bell_polynomial": ".bell",
|
|
162
|
+
"complete_exponential_bell_via_sympy": ".bell",
|
|
163
|
+
"differential_bell_laurent_series": ".formal",
|
|
164
|
+
"differential_bell_polynomials": ".formal",
|
|
165
|
+
"exponential_block_decomposition": ".block_decomposition",
|
|
166
|
+
"formal_amplitude_series": ".formal",
|
|
167
|
+
"formal_block_partition": ".system",
|
|
168
|
+
"formal_logarithmic_basis": ".formal_basis",
|
|
169
|
+
"green_operator_data": ".interchange",
|
|
170
|
+
"irregular_singularity_invariants": ".irregular",
|
|
171
|
+
"levelt_reduce_regular_singular": ".levelt",
|
|
172
|
+
"local_order_and_leading_coefficient": ".newton",
|
|
173
|
+
"localize_operator": ".newton",
|
|
174
|
+
"ramified_pullback": ".block_decomposition",
|
|
175
|
+
"reduce_to_fuchsian": ".levelt",
|
|
176
|
+
"riccati_expression": ".formal",
|
|
177
|
+
"stokes_connection_patterns": ".stokes",
|
|
178
|
+
"stokes_geometry_from_exponential_parts": ".stokes",
|
|
179
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Shared assumptions and proof-oriented zero decisions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sympy as sp
|
|
6
|
+
from funcprops import entails, normalize_assumptions
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from exprtest import zerotest as _exprtest_zerotest
|
|
10
|
+
except ImportError: # Optional stronger oracle; funcprops remains sufficient.
|
|
11
|
+
_exprtest_zerotest = None
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def zero_status(expr: sp.Expr, assumptions: sp.Expr | bool = True) -> bool | None:
|
|
15
|
+
"""Prove zero/nonzero when cheap, returning ``None`` when unresolved.
|
|
16
|
+
|
|
17
|
+
Fast structural and SymPy assumption checks run first. ``funcprops`` handles
|
|
18
|
+
bounded logical entailment. If installed, ``exprtest`` is used last and
|
|
19
|
+
only with ``confidence='certified'`` so heuristic nonzero evidence can never
|
|
20
|
+
steer an ODE classification branch.
|
|
21
|
+
"""
|
|
22
|
+
assumptions = normalize_assumptions(assumptions)
|
|
23
|
+
value = sp.sympify(expr)
|
|
24
|
+
if value == 0 or value.is_zero is True:
|
|
25
|
+
return True
|
|
26
|
+
if value.is_zero is False:
|
|
27
|
+
return False
|
|
28
|
+
simplified = sp.cancel(sp.together(value)) if sp.count_ops(value) <= 24 else value
|
|
29
|
+
if simplified == 0 or simplified.is_zero is True:
|
|
30
|
+
return True
|
|
31
|
+
if simplified.is_zero is False:
|
|
32
|
+
return False
|
|
33
|
+
if sp.count_ops(simplified) <= 24:
|
|
34
|
+
try:
|
|
35
|
+
decision = entails(sp.Eq(simplified, 0, evaluate=False), assumptions)
|
|
36
|
+
except (RecursionError, TypeError, ValueError):
|
|
37
|
+
decision = None
|
|
38
|
+
if decision is not None:
|
|
39
|
+
return decision
|
|
40
|
+
use_exprtest = _exprtest_zerotest is not None and not simplified.has(
|
|
41
|
+
sp.nan, sp.zoo, sp.oo, -sp.oo
|
|
42
|
+
)
|
|
43
|
+
if simplified.free_symbols and simplified.is_rational_function(
|
|
44
|
+
*simplified.free_symbols
|
|
45
|
+
):
|
|
46
|
+
use_exprtest = False
|
|
47
|
+
if use_exprtest:
|
|
48
|
+
try:
|
|
49
|
+
return _exprtest_zerotest(
|
|
50
|
+
simplified, assumptions=assumptions, confidence="certified"
|
|
51
|
+
)
|
|
52
|
+
except (RecursionError, TypeError, ValueError):
|
|
53
|
+
return None
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def nonzero_status(expr: sp.Expr, assumptions: sp.Expr | bool = True) -> bool | None:
|
|
58
|
+
z = zero_status(expr, assumptions)
|
|
59
|
+
return None if z is None else not z
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def assumption_substitutions(
|
|
63
|
+
assumptions: sp.Expr | bool = True,
|
|
64
|
+
) -> dict[sp.Symbol, sp.Expr]:
|
|
65
|
+
"""Extract direct symbol equalities from a conjunction of assumptions."""
|
|
66
|
+
assumptions = normalize_assumptions(assumptions)
|
|
67
|
+
result: dict[sp.Symbol, sp.Expr] = {}
|
|
68
|
+
for clause in sp.And.make_args(assumptions):
|
|
69
|
+
if not isinstance(clause, sp.Equality):
|
|
70
|
+
continue
|
|
71
|
+
lhs, rhs = clause.lhs, clause.rhs
|
|
72
|
+
if isinstance(lhs, sp.Symbol) and lhs not in rhs.free_symbols:
|
|
73
|
+
result[lhs] = rhs
|
|
74
|
+
elif isinstance(rhs, sp.Symbol) and rhs not in lhs.free_symbols:
|
|
75
|
+
result[rhs] = lhs
|
|
76
|
+
continue
|
|
77
|
+
expr = sp.expand(lhs - rhs)
|
|
78
|
+
for symbol in sorted(expr.free_symbols, key=sp.default_sort_key, reverse=True):
|
|
79
|
+
try:
|
|
80
|
+
poly = sp.Poly(expr, symbol)
|
|
81
|
+
except (sp.PolynomialError, TypeError, ValueError):
|
|
82
|
+
continue
|
|
83
|
+
if poly.degree() == 1:
|
|
84
|
+
aa, bb = poly.all_coeffs()
|
|
85
|
+
value = sp.cancel(-bb / aa)
|
|
86
|
+
if symbol not in value.free_symbols:
|
|
87
|
+
result[symbol] = value
|
|
88
|
+
break
|
|
89
|
+
return result
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Shared exact helpers for formal block reduction."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
import sympy as sp
|
|
8
|
+
|
|
9
|
+
from .matrix_series import MatrixLaurentSeries
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BlockDecompositionError(NotImplementedError):
|
|
13
|
+
"""Raised when an exact formal block split cannot be certified."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def is_zero_matrix(matrix: sp.MatrixBase) -> bool:
|
|
17
|
+
"""Return whether every matrix entry simplifies exactly to zero."""
|
|
18
|
+
|
|
19
|
+
return all(sp.simplify(entry) == 0 for entry in matrix)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def is_scalar_matrix(matrix: sp.MatrixBase) -> tuple[bool, sp.Expr]:
|
|
23
|
+
"""Return whether ``matrix`` is scalar and, when so, its scalar value."""
|
|
24
|
+
|
|
25
|
+
matrix = sp.Matrix(matrix)
|
|
26
|
+
if matrix.rows != matrix.cols:
|
|
27
|
+
return False, sp.S.Zero
|
|
28
|
+
if matrix.rows == 0:
|
|
29
|
+
return True, sp.S.Zero
|
|
30
|
+
scalar = sp.simplify(matrix[0, 0])
|
|
31
|
+
for i in range(matrix.rows):
|
|
32
|
+
for j in range(matrix.cols):
|
|
33
|
+
expected = scalar if i == j else sp.S.Zero
|
|
34
|
+
if sp.simplify(matrix[i, j] - expected) != 0:
|
|
35
|
+
return False, sp.S.Zero
|
|
36
|
+
return True, scalar
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def matrix_block(
|
|
40
|
+
matrix: sp.MatrixBase,
|
|
41
|
+
row_start: int,
|
|
42
|
+
row_stop: int,
|
|
43
|
+
col_start: int,
|
|
44
|
+
col_stop: int,
|
|
45
|
+
) -> sp.Matrix:
|
|
46
|
+
"""Extract a dense matrix block."""
|
|
47
|
+
|
|
48
|
+
return sp.Matrix(matrix)[row_start:row_stop, col_start:col_stop]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def series_block(
|
|
52
|
+
series: MatrixLaurentSeries,
|
|
53
|
+
row_start: int,
|
|
54
|
+
row_stop: int,
|
|
55
|
+
col_start: int,
|
|
56
|
+
col_stop: int,
|
|
57
|
+
) -> MatrixLaurentSeries:
|
|
58
|
+
"""Extract a block from every coefficient of a Laurent matrix series."""
|
|
59
|
+
|
|
60
|
+
rows = row_stop - row_start
|
|
61
|
+
cols = col_stop - col_start
|
|
62
|
+
coefficients: dict[int, sp.Matrix] = {}
|
|
63
|
+
for power, coefficient in series.terms:
|
|
64
|
+
block = matrix_block(coefficient, row_start, row_stop, col_start, col_stop)
|
|
65
|
+
if not is_zero_matrix(block):
|
|
66
|
+
coefficients[power] = block
|
|
67
|
+
return MatrixLaurentSeries.from_mapping(
|
|
68
|
+
series.variable,
|
|
69
|
+
coefficients,
|
|
70
|
+
shape=(rows, cols),
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def block_diag_series(
|
|
75
|
+
variable: sp.Symbol,
|
|
76
|
+
series_list: Sequence[MatrixLaurentSeries],
|
|
77
|
+
) -> MatrixLaurentSeries:
|
|
78
|
+
"""Assemble Laurent matrix series as a block diagonal series."""
|
|
79
|
+
|
|
80
|
+
if not series_list:
|
|
81
|
+
return MatrixLaurentSeries.zero(variable, 0, 0)
|
|
82
|
+
if any(series.variable != variable for series in series_list):
|
|
83
|
+
raise ValueError("all block series must use the same variable")
|
|
84
|
+
total_rows = sum(series.rows for series in series_list)
|
|
85
|
+
total_cols = sum(series.cols for series in series_list)
|
|
86
|
+
powers = sorted({power for series in series_list for power, _ in series.terms})
|
|
87
|
+
coefficients: dict[int, sp.Matrix] = {}
|
|
88
|
+
for power in powers:
|
|
89
|
+
blocks = [sp.Matrix(series.coefficient(power)) for series in series_list]
|
|
90
|
+
coefficient = sp.diag(*blocks)
|
|
91
|
+
if not is_zero_matrix(coefficient):
|
|
92
|
+
coefficients[power] = coefficient
|
|
93
|
+
return MatrixLaurentSeries.from_mapping(
|
|
94
|
+
variable,
|
|
95
|
+
coefficients,
|
|
96
|
+
shape=(total_rows, total_cols),
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def partition_offsets(dimensions: Sequence[int]) -> tuple[int, ...]:
|
|
101
|
+
"""Return cumulative block offsets for ``dimensions``."""
|
|
102
|
+
|
|
103
|
+
offsets = [0]
|
|
104
|
+
for dimension in dimensions:
|
|
105
|
+
offsets.append(offsets[-1] + dimension)
|
|
106
|
+
return tuple(offsets)
|