ore_algebra.analytic.path

Analytic continuation paths

Functions

local_monodromy_path(sing)
polygon_around(point[, size])

Classes

EvaluationPoint(pt[, jet_order, branch, rad]) Series evaluation point/jet.
Path(vert, dop) A path in ℂ or on the Riemann surface of some operator.
Point(point[, dop, singular]) A point on the complex plane with an associated differential operator.
Step(start, end[, branch]) Analytic continuation step from a Point to another

Exceptions

PathPrecisionError
class ore_algebra.analytic.path.EvaluationPoint(pt, jet_order=1, branch=(0, ), rad=None)

Series evaluation point/jet.

A ring element (a complex number, a polynomial indeterminate, perhaps someday a matrix) where to evaluate the partial sum of a series, along with a “jet order” used to compute derivatives and a bound on the norm of the mathematical quantity it represents that can be used to bound the truncation error.

  • branch - branch of the logarithm to use; (0,) means the standard branch, (k,) means log(z) + 2kπi, a tuple of length > 1 averages over the corresponding branches
class ore_algebra.analytic.path.Path(vert, dop)

A path in ℂ or on the Riemann surface of some operator.

Note that paths are not the only potentially interesting analytic continuation plans: we may reuse already computed transition matrices!

EXAMPLES:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Path
sage: Dops, x, Dx = DifferentialOperators()
sage: dop = (x^2 + 1)*Dx^2 + 2*x*Dx

sage: path = Path([0, 1+I, CBF(2*I)], dop)
sage: path
0 --> I + 1 --> 2.000...*I
sage: path[0]
0 --> I + 1
sage: path.vert[0]
0
sage: len(path)
2
sage: path.dop
(x^2 + 1)*Dx^2 + 2*x*Dx

sage: path.check_singularity()
sage: path.check_convergence()
Traceback (most recent call last):
...
ValueError: Step 0 --> I + 1 escapes from the disk of (guaranteed)
convergence of the solutions at 0
bypass_singularities()

TESTS:

sage: from ore_algebra import *
sage: Dops, x, Dx = DifferentialOperators()
sage: ((x-1)*Dx - 1).numerical_solution([1], [0,2], assume_analytic=True)
[-1.0000000000000...] + [+/- ...]*I

sage: dop = ((x - 1)*Dx - 1)*((x - 2)*Dx - 2)
sage: dop.numerical_solution([1, 0], [0, 3], assume_analytic=True)
[-3.5000000000000...] + [+/- ...]*I

sage: QQi.<i> = QuadraticField(-1)
sage: dop = ((x - i - 1)*Dx - 1)*((x - 2*i - 2)*Dx - 2)
sage: dop.numerical_solution([1, 0], [0, 3*i + 3], assume_analytic=True)
[-3.5000000000000...] + [+/- ...]*I
check_convergence()

EXAMPLES:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Path
sage: Dops, x, Dx = DifferentialOperators()
sage: dop = (x^2 + 1)*Dx^2 + 2*x*Dx
sage: Path([0, 1], dop).check_convergence()
Traceback (most recent call last):
...
ValueError: Step 0 --> 1 escapes from the disk of (guaranteed)
convergence of the solutions at 0
sage: Path([1, 0], dop).check_convergence()
check_singularity()

EXAMPLES:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Path
sage: Dops, x, Dx = DifferentialOperators()
sage: QQi.<i> = QuadraticField(-1, 'i')
sage: dop = (x^2 + 1)*Dx^2 + 2*x*Dx

sage: Path([0], dop).check_singularity()
sage: Path([1,3], dop).check_singularity()
sage: Path([0, i], dop).check_singularity()

sage: Path([42, 1+i/2, -1+3*i/2], dop).check_singularity()
Traceback (most recent call last):
...
ValueError: Step 1/2*i + 1 --> 3/2*i - 1 passes through or too close
to singular point 1*I (to compute the connection to a singular
point, make it a vertex of the path)

TESTS:

Check that we detect additional singular points on path segments with regular singular endpoints. Adapted from a NumGfun bug found by Christoph Koutschan.

sage: dop = (-8*x^3+4*x^4+5*x^2-x)*Dx + 10*x^2-4*x-8*x^3+1
sage: dop.numerical_transition_matrix([0,1])
Traceback (most recent call last):
...
ValueError: ...

Multiple singular points along a single edge:

sage: (((x-1)*Dx-1)*((x-2)*Dx-2)).numerical_transition_matrix([0,3])
Traceback (most recent call last):
...
ValueError: Step 0 --> 3 passes through or too close to singular
points 1, 2...
class ore_algebra.analytic.path.Point(point, dop=None, singular=None, **kwds)

A point on the complex plane with an associated differential operator.

A point can be exact (a number field element) or inexact (a real or complex interval or ball). It can be classified as ordinary, regular singular, etc. The main reason for making the operator part of the definition of Points is that this gives a convenient place to cache information that depend on both, with an appropriate lifetime. Note however that the point is considered to lie on the complex plane, not on the Riemann surface of the operator.

approx_abs_real(prec)

Compute an approximation with absolute error about 2^(-prec).

dist_to_sing()

Distance of self to the singularities of self.dop other than self.

TESTS:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Point
sage: Dops, x, Dx = DifferentialOperators()
sage: dop = (x^2 + 1)*Dx^2 + 2*x*Dx
sage: Point(1, dop).dist_to_sing()
[1.41421356237309...]
sage: Point(i, dop).dist_to_sing()
2.00...
sage: Point(1+i, dop).dist_to_sing()
1.00...
exact()

sage: from ore_algebra import * sage: from ore_algebra.analytic.path import Point sage: Dops, x, Dx = DifferentialOperators() sage: QQi.<i> = QuadraticField(-1) sage: [Point(z, Dx).exact() for z in [1, 1/2, 1+i, QQbar(I)]] [1, 1/2, i + 1, I] sage: [Point(z, Dx).exact() for z in [RBF(3/4), RBF(1) + I]] [3/4, i + 1] sage: Point(RIF(1/3), Dx).exact() Traceback (most recent call last): … ValueError

is_ordinary

File: /home/staff/mkauers/software/own/symbCompPackages/sage/ore_algebra/src/ore_algebra/analytic/path.py (starting at line 267)

is_regular

File: /home/staff/mkauers/software/own/symbCompPackages/sage/ore_algebra/src/ore_algebra/analytic/path.py (starting at line 286)

iv

File: /home/staff/mkauers/software/own/symbCompPackages/sage/ore_algebra/src/ore_algebra/analytic/path.py (starting at line 177)

sage: from ore_algebra import * sage: from ore_algebra.analytic.path import Point sage: Dops, x, Dx = DifferentialOperators() sage: [Point(z, Dx).iv() ….: for z in [1, 1/2, 1+I, QQbar(I), RIF(1/3), CIF(1/3), pi]] [1.000000000000000, 0.5000000000000000, 1.000000000000000 + 1.000000000000000*I, 1.000000000000000*I, [0.333333333333333 +/- 3.99e-16], [0.333333333333333 +/- 3.99e-16], [3.141592653589793 +/- 7.83e-16]]

local_basis_structure()

EXAMPLES:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Point
sage: Dops, x, Dx = DifferentialOperators()
sage: Point(0, x*Dx^2 + Dx + x).local_basis_structure()
[FundamentalSolution(leftmost=0, shift=0, log_power=1, value=None),
 FundamentalSolution(leftmost=0, shift=0, log_power=0, value=None)]
sage: Point(0, Dx^3 + x*Dx + x).local_basis_structure()
[FundamentalSolution(leftmost=0, shift=0, log_power=0, value=None),
 FundamentalSolution(leftmost=0, shift=1, log_power=0, value=None),
 FundamentalSolution(leftmost=0, shift=2, log_power=0, value=None)]
singularity_type(short=False)

EXAMPLES:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Point
sage: Dops, x, Dx = DifferentialOperators()

sage: dop = (x^2 + 1)*Dx^2 + 2*x*Dx
sage: Point(1, dop).singularity_type()
'ordinary point'
sage: Point(i, dop).singularity_type()
'regular singular point'
sage: Point(0, x^2*Dx + 1).singularity_type()
'irregular singular point'
sage: Point(CIF(1/3), x^2*Dx + 1).singularity_type()
'ordinary point'
sage: Point(CIF(1/3)-1/3, x^2*Dx + 1).singularity_type()
'point of unknown singularity type'
class ore_algebra.analytic.path.Step(start, end, branch=(0, ))

Analytic continuation step from a Point to another

EXAMPLES:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Point, Step
sage: QQi.<i> = QuadraticField(-1)
sage: Dops, x, Dx = DifferentialOperators()

sage: s1 = Step(Point(0, x*Dx-1), Point(i/7, x*Dx-1))
sage: s2 = Step(Point(RIF(1/3), x*Dx-1), Point(pi, x*Dx-1))
sage: s3 = Step(Point(-i, x*Dx-1), Point(i, x*Dx-1))

sage: s1, s2
(0 --> 1/7*i, [0.333333333333333 +/- 3.99e-16] --> 3.141592653589794?)

sage: list(s1), list(s2)
([0, 1/7*i], [[0.333333333333333 +/- 3.99e-16], 3.141592653589794?])

sage: s1.is_exact(), s2.is_exact()
(True, False)

sage: s1.delta(), s2.delta()
(1/7*i, [2.80825932025646 +/- 1.56e-15])

sage: s1.length(), s2.length()
([0.142857142857142...], [2.8082593202564...])

sage: s1.check_singularity()
sage: s2.check_singularity()
sage: s3.check_singularity()
Traceback (most recent call last):
...
ValueError: Step -i --> i passes through or too close to singular point
0 (to compute the connection to a singular point, make it a vertex of
the path)

sage: s2.check_convergence()
Traceback (most recent call last):
...
ValueError: Step ... escapes from the disk of (guaranteed)
convergence of the solutions at ...

sage: s2.plot()
Graphics object consisting of 1 graphics primitive

TESTS:

Check that we can handle connections between points in ℚ[i] and in other complex number fields in spite of various weaknesses of the coercion system. Thanks to Armin Straub for the example:

sage: dop = ((81*x^4 + 14*x^3 + x^2)*Dx^3 + (486*x^3 + 63*x^2 +
....: 3*x)*Dx^2 + (567*x^2 + 48*x + 1)*Dx + 81*x + 3)
sage: dop.numerical_transition_matrix([0,QQbar((4*sqrt(2)*I-7)/81)])[0,0]
[-3.17249673357...] + [-4.486587907205...]*I
check_convergence()

TESTS:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import *
sage: Dops, x, Dx = DifferentialOperators()

sage: Path([0, 1], x*(x^2+1)*Dx).check_convergence()
Traceback (most recent call last):
...
ValueError: Step 0 --> 1 escapes from the disk of (guaranteed)
convergence of the solutions at regular singular point 0

sage: Path([1, 0], x*(x^2+1)*Dx).check_convergence()
Traceback (most recent call last):
...
ValueError: Step 1 --> 0 escapes from the disk of (guaranteed)
convergence of the solutions at regular singular point 0
check_singularity()

Raise an error if this step goes through a singular point or seems to do so at our working precision.

TESTS:

sage: from ore_algebra import *
sage: from ore_algebra.analytic.path import Point, Step
sage: Dops, x, Dx = DifferentialOperators(); i = QuadraticField(-1, 'i').gen()
sage: dop = (x^2 + 1)*Dx
sage: Step(Point(0, dop), Point(0, dop)).check_singularity()
sage: Step(Point(0, dop), Point(1, dop)).check_singularity()
sage: Step(Point(1, dop), Point(1, dop)).check_singularity()
sage: Step(Point(1, dop), Point(i, dop)).check_singularity()
sage: Step(Point(i, dop), Point(0, dop)).check_singularity()
sage: Step(Point(i, dop), Point(i, dop)).check_singularity()
sage: Step(Point(2*i+1, dop), Point(-11/10, dop)).check_singularity()
sage: Step(Point(2*i, dop), Point(0, dop)).check_singularity()
Traceback (most recent call last):
...
ValueError: Step 2*i --> 0 passes through or too close to singular
point 1*I (to compute the connection to a singular point, make it a
vertex of the path)
sage: Step(Point(2*i+1, dop), Point(-1, dop)).check_singularity()
Traceback (most recent call last):
...
ValueError: Step 2*i + 1 --> -1 passes through or too close to
singular point 1*I (to compute the connection to a singular point,
make it a vertex of the path)
delta()

TESTS:

sage: from ore_algebra import *
sage: Dops, x, Dx = DifferentialOperators()
sage: (Dx - 1).numerical_solution([1], [0, RealField(10)(.33), 1])
[2.71828182845904...]