Asymptotic Ring#

This module provides a ring (called AsymptoticRing) for computations with asymptotic expansions.

(Informal) Definition#

An asymptotic expansion is a sum such as

\[5z^3 + 4z^2 + O(z)\]

as \(z \to \infty\) or

\[3x^{42}y^2 + 7x^3y^3 + O(x^2) + O(y)\]

as \(x\) and \(y\) tend to \(\infty\). It is a truncated series (after a finite number of terms), which approximates a function.

The summands of the asymptotic expansions are partially ordered. In this module these summands are the following:

  • Exact terms \(c\cdot g\) with a coefficient \(c\) and an element \(g\) of a growth group (see below).

  • \(O\)-terms \(O(g)\) (see Big O notation; also called Bachmann–Landau notation) for a growth group element \(g\) (again see below).

See the Wikipedia article on asymptotic expansions for more details. Further examples of such elements can be found here.

Growth Groups and Elements#

The elements of a growth group are equipped with a partial order and usually contain a variable. Examples—the order is described below these examples—are

  • elements of the form \(z^q\) for some integer or rational \(q\) (growth groups with description strings z^ZZ or z^QQ),

  • elements of the form \(\log(z)^q\) for some integer or rational \(q\) (growth groups log(z)^ZZ or log(z)^QQ),

  • elements of the form \(a^z\) for some rational \(a\) (growth group QQ^z), or

  • more sophisticated constructions like products \(x^r \cdot \log(x)^s \cdot a^y \cdot y^q\) (this corresponds to an element of the growth group x^QQ * log(x)^ZZ * QQ^y * y^QQ).

The order in all these examples is induced by the magnitude of the elements as \(x\), \(y\), or \(z\) (independently) tend to \(\infty\). For elements only using the variable \(z\) this means that \(g_1 \leq g_2\) if

\[\lim_{z\to\infty} \frac{g_1}{g_2} \leq 1.\]

Note

Asymptotic rings where the variable tend to some value distinct from \(\infty\) are not yet implemented.

To find out more about

  • growth groups,

  • on how they are created and

  • about the above used descriptions strings

see the top of the module growth group.

Introductory Examples#

We start this series of examples by defining two asymptotic rings.

Two Rings#

A Univariate Asymptotic Ring#

First, we construct the following (very simple) asymptotic ring in the variable \(z\):

sage: A.<z> = AsymptoticRing(growth_group='z^QQ', coefficient_ring=ZZ); A
Asymptotic Ring <z^QQ> over Integer Ring

A typical element of this ring is

sage: A.an_element()
z^(3/2) + O(z^(1/2))

This element consists of two summands: the exact term with coefficient \(1\) and growth \(z^{3/2}\) and the \(O\)-term \(O(z^{1/2})\). Note that the growth of \(z^{3/2}\) is larger than the growth of \(z^{1/2}\) as \(z\to\infty\), thus this expansion cannot be simplified (which would be done automatically, see below).

Elements can be constructed via the generator \(z\) and the function O(), for example

sage: 4*z^2 + O(z)
4*z^2 + O(z)

A Multivariate Asymptotic Ring#

Next, we construct a more sophisticated asymptotic ring in the variables \(x\) and \(y\) by

sage: B.<x, y> = AsymptoticRing(growth_group='x^QQ * log(x)^ZZ * (QQ_+)^y * y^QQ', coefficient_ring=QQ); B
Asymptotic Ring <x^QQ * log(x)^ZZ * QQ^y * y^QQ> over Rational Field

Again, we can look at a typical (nontrivial) element:

sage: B.an_element()
1/8*x^(3/2)*log(x)^3*(1/8)^y*y^(3/2) + O(x^(1/2)*log(x)*(1/2)^y*y^(1/2))

Again, elements can be created using the generators \(x\) and \(y\), as well as the function O():

sage: log(x)*y/42 + O(1/2^y)
1/42*log(x)*y + O((1/2)^y)

Arithmetical Operations#

In this section we explain how to perform various arithmetical operations with the elements of the asymptotic rings constructed above.

The Ring Operations Plus and Times#

We start our calculations in the ring

sage: A
Asymptotic Ring <z^QQ> over Integer Ring

Of course, we can perform the usual ring operations \(+\) and \(*\):

sage: z^2 + 3*z*(1-z)
-2*z^2 + 3*z
sage: (3*z + 2)^3
27*z^3 + 54*z^2 + 36*z + 8

In addition to that, special powers—our growth group z^QQ allows the exponents to be out of \(\QQ\)—can also be computed:

sage: (z^(5/2)+z^(1/7)) * z^(-1/5)
z^(23/10) + z^(-2/35)

The central concepts of computations with asymptotic expansions is that the \(O\)-notation can be used. For example, we have

sage: z^3 + z^2 + z + O(z^2)
z^3 + O(z^2)

where the result is simplified automatically. A more sophisticated example is

sage: (z+2*z^2+3*z^3+4*z^4) * (O(z)+z^2)
4*z^6 + O(z^5)

Division#

The asymptotic expansions support division. For example, we can expand \(1/(z-1)\) to a geometric series:

sage: 1 / (z-1)
z^(-1) + z^(-2) + z^(-3) + z^(-4) + ... + z^(-20) + O(z^(-21))

A default precision (parameter default_prec of AsymptoticRing) is predefined. Thus, only the first \(20\) summands are calculated. However, if we only want the first \(5\) exact terms, we cut of the rest by using

sage: (1 / (z-1)).truncate(5)
z^(-1) + z^(-2) + z^(-3) + z^(-4) + z^(-5) + O(z^(-6))

or

sage: 1 / (z-1) + O(z^(-6))
z^(-1) + z^(-2) + z^(-3) + z^(-4) + z^(-5) + O(z^(-6))

Of course, we can work with more complicated expansions as well:

sage: (4*z+1) / (z^3+z^2+z+O(z^0))
4*z^(-2) - 3*z^(-3) - z^(-4) + O(z^(-5))

Not all elements are invertible, for instance,

sage: 1 / O(z)
Traceback (most recent call last):
...
ZeroDivisionError: Cannot invert O(z).

is not invertible, since it includes \(0\).

Powers, Exponentials and Logarithms#

It works as simple as it can be; just use the usual operators ^, exp and log. For example, we obtain the usual series expansion of the logarithm

sage: -log(1-1/z)
z^(-1) + 1/2*z^(-2) + 1/3*z^(-3) + ... + O(z^(-21))

as \(z \to \infty\).

Similarly, we can apply the exponential function of an asymptotic expansion:

sage: exp(1/z)
1 + z^(-1) + 1/2*z^(-2) + 1/6*z^(-3) + 1/24*z^(-4) + ... + O(z^(-20))

Arbitrary powers work as well; for example, we have

sage: (1 + 1/z + O(1/z^5))^(1 + 1/z)
1 + z^(-1) + z^(-2) + 1/2*z^(-3) + 1/3*z^(-4) + O(z^(-5))

Multivariate Arithmetic#

Now let us move on to arithmetic in the multivariate ring

sage: B
Asymptotic Ring <x^QQ * log(x)^ZZ * QQ^y * y^QQ> over Rational Field

Todo

write this part

More Examples#

The mathematical constant e as a limit#

The base of the natural logarithm \(e\) satisfies the equation

\[e = \lim_{n\to\infty} \left(1+\frac{1}{n}\right)^n\]

By using asymptotic expansions, we obtain the more precise result

sage: E.<n> = AsymptoticRing(growth_group='n^ZZ', coefficient_ring=SR, default_prec=5); E
Asymptotic Ring <n^ZZ> over Symbolic Ring
sage: (1 + 1/n)^n
e - 1/2*e*n^(-1) + 11/24*e*n^(-2) - 7/16*e*n^(-3) + 2447/5760*e*n^(-4) + O(n^(-5))

Selected Technical Details#

Coercions and Functorial Constructions#

The AsymptoticRing fully supports coercion. For example, the coefficient ring is automatically extended when needed:

sage: A
Asymptotic Ring <z^QQ> over Integer Ring
sage: (z + 1/2).parent()
Asymptotic Ring <z^QQ> over Rational Field

Here, the coefficient ring was extended to allow \(1/2\) as a coefficient. Another example is

sage: C.<c> = AsymptoticRing(growth_group='c^ZZ', coefficient_ring=ZZ['e'])
sage: C.an_element()
e^3*c^3 + O(c)
sage: C.an_element() / 7
1/7*e^3*c^3 + O(c)

Here the result’s coefficient ring is the newly found

sage: (C.an_element() / 7).parent()
Asymptotic Ring <c^ZZ> over
Univariate Polynomial Ring in e over Rational Field

Not only the coefficient ring can be extended, but the growth group as well. For example, we can add/multiply elements of the asymptotic rings A and C to get an expansion of new asymptotic ring:

sage: r = c*z + c/2 + O(z); r
c*z + 1/2*c + O(z)
sage: r.parent()
Asymptotic Ring <c^ZZ * z^QQ> over
Univariate Polynomial Ring in e over Rational Field

Data Structures#

The summands of an asymptotic expansion are wrapped growth group elements. This wrapping is done by the term monoid module. However, inside an asymptotic expansion these summands (terms) are stored together with their growth-relationship, i.e., each summand knows its direct predecessors and successors. As a data structure a special poset (namely a mutable poset) is used. We can have a look at this:

sage: b = x^3*y + x^2*y + x*y^2 + O(x) + O(y)
sage: print(b.summands.repr_full(reverse=True))
poset(x*y^2, x^3*y, x^2*y, O(x), O(y))
+-- oo
|   +-- no successors
|   +-- predecessors:   x*y^2, x^3*y
+-- x*y^2
|   +-- successors:   oo
|   +-- predecessors:   O(x), O(y)
+-- x^3*y
|   +-- successors:   oo
|   +-- predecessors:   x^2*y
+-- x^2*y
|   +-- successors:   x^3*y
|   +-- predecessors:   O(x), O(y)
+-- O(x)
|   +-- successors:   x*y^2, x^2*y
|   +-- predecessors:   null
+-- O(y)
|   +-- successors:   x*y^2, x^2*y
|   +-- predecessors:   null
+-- null
|   +-- successors:   O(x), O(y)
|   +-- no predecessors

Various#

AUTHORS:

  • Benjamin Hackl (2015)

  • Daniel Krenn (2015)

  • Clemens Heuberger (2016)

ACKNOWLEDGEMENT:

  • Benjamin Hackl, Clemens Heuberger and Daniel Krenn are supported by the Austrian Science Fund (FWF): P 24644-N26.

  • Benjamin Hackl is supported by the Google Summer of Code 2015.

Classes and Methods#

class sage.rings.asymptotic.asymptotic_ring.AsymptoticExpansion(parent, summands, simplify=True, convert=True)#

Bases: CommutativeAlgebraElement

Class for asymptotic expansions, i.e., the elements of an AsymptoticRing.

INPUT:

  • parent – the parent of the asymptotic expansion.

  • summands – the summands as a MutablePoset, which represents the underlying structure.

  • simplify – a boolean (default: True). It controls automatic simplification (absorption) of the asymptotic expansion.

  • convert – a boolean (default: True). If set, then the summands are converted to the asymptotic ring (the parent of this expansion). If not, then the summands are taken as they are. In that case, the caller must ensure that the parent of the terms is set correctly.

EXAMPLES:

There are several ways to create asymptotic expansions; usually this is done by using the corresponding asymptotic rings:

sage: R_x.<x> = AsymptoticRing(growth_group='x^QQ', coefficient_ring=QQ); R_x
Asymptotic Ring <x^QQ> over Rational Field
sage: R_y.<y> = AsymptoticRing(growth_group='y^ZZ', coefficient_ring=ZZ); R_y
Asymptotic Ring <y^ZZ> over Integer Ring

At this point, \(x\) and \(y\) are already asymptotic expansions:

sage: type(x)
<class 'sage.rings.asymptotic.asymptotic_ring.AsymptoticRing_with_category.element_class'>

The usual ring operations, but allowing rational exponents (growth group x^QQ) can be performed:

sage: x^2 + 3*(x - x^(2/5))
x^2 + 3*x - 3*x^(2/5)
sage: (3*x^(1/3) + 2)^3
27*x + 54*x^(2/3) + 36*x^(1/3) + 8

One of the central ideas behind computing with asymptotic expansions is that the \(O\)-notation (see Wikipedia article Big_O_notation) can be used. For example, we have:

sage: (x+2*x^2+3*x^3+4*x^4) * (O(x)+x^2)
4*x^6 + O(x^5)

In particular, O() can be used to construct the asymptotic expansions. With the help of the summands(), we can also have a look at the inner structure of an asymptotic expansion:

sage: expr1 = x + 2*x^2 + 3*x^3 + 4*x^4; expr2 = O(x) + x^2
sage: print(expr1.summands.repr_full())
poset(x, 2*x^2, 3*x^3, 4*x^4)
+-- null
|   +-- no predecessors
|   +-- successors:   x
+-- x
|   +-- predecessors:   null
|   +-- successors:   2*x^2
+-- 2*x^2
|   +-- predecessors:   x
|   +-- successors:   3*x^3
+-- 3*x^3
|   +-- predecessors:   2*x^2
|   +-- successors:   4*x^4
+-- 4*x^4
|   +-- predecessors:   3*x^3
|   +-- successors:   oo
+-- oo
|   +-- predecessors:   4*x^4
|   +-- no successors
sage: print(expr2.summands.repr_full())
poset(O(x), x^2)
+-- null
|   +-- no predecessors
|   +-- successors:   O(x)
+-- O(x)
|   +-- predecessors:   null
|   +-- successors:   x^2
+-- x^2
|   +-- predecessors:   O(x)
|   +-- successors:   oo
+-- oo
|   +-- predecessors:   x^2
|   +-- no successors
sage: print((expr1 * expr2).summands.repr_full())
poset(O(x^5), 4*x^6)
+-- null
|   +-- no predecessors
|   +-- successors:   O(x^5)
+-- O(x^5)
|   +-- predecessors:   null
|   +-- successors:   4*x^6
+-- 4*x^6
|   +-- predecessors:   O(x^5)
|   +-- successors:   oo
+-- oo
|   +-- predecessors:   4*x^6
|   +-- no successors

In addition to the monomial growth elements from above, we can also compute with logarithmic terms (simply by constructing the appropriate growth group):

sage: R_log = AsymptoticRing(growth_group='log(x)^QQ', coefficient_ring=QQ)
sage: lx = R_log(log(SR.var('x')))
sage: (O(lx) + lx^3)^4
log(x)^12 + O(log(x)^10)
B(valid_from=0)#

Convert all terms in this asymptotic expansion to \(B\)-terms.

INPUT:

  • valid_from – dictionary mapping variable names to lower bounds for the corresponding variable. The bound implied by this term is valid when all variables are at least their corresponding lower bound. If a number is passed to valid_from, then the lower bounds for all variables of the asymptotic expansion are set to this number

OUTPUT:

An asymptotic expansion

EXAMPLES:

sage: AR.<x, z> = AsymptoticRing(growth_group='x^ZZ * z^ZZ', coefficient_ring=ZZ)
sage: AR.B(2*x^2, {x: 10}) # indirect doctest
B(2*x^2, x >= 10)
sage: expr = 42*x^42 + x^10 + AR.B(x^2, 20); expr # indirect doctest
42*x^42 + x^10 + B(x^2, x >= 20, z >= 20)
sage: type(AR.B(x, 10)) # indirect doctest
<class 'sage.rings.asymptotic.asymptotic_ring.AsymptoticRing_with_category.element_class'>
sage: 2*z^3 + AR.B(5*z^2, {z: 20}) # indirect doctest
2*z^3 + B(5*z^2, z >= 20)
sage: (2*x).B({x: 20})
B(2*x, x >= 20)
sage: AR.B(4*x^2*z^3, valid_from=10) # indirect doctest
B(4*x^2*z^3, x >= 10, z >= 10)
sage: AR.B(42*x^2) # indirect doctest
B(42*x^2, x >= 0, z >= 0)
O()#

Convert all terms in this asymptotic expansion to \(O\)-terms.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: AR.<x> = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: O(x)
O(x)
sage: type(O(x))
<class 'sage.rings.asymptotic.asymptotic_ring.AsymptoticRing_with_category.element_class'>
sage: expr = 42*x^42 + x^10 + O(x^2); expr
42*x^42 + x^10 + O(x^2)
sage: expr.O()
O(x^42)
sage: (2*x).O()
O(x)

See also

sage.rings.power_series_ring.PowerSeriesRing(), sage.rings.laurent_series_ring.LaurentSeriesRing().

compare_with_values(variable, function, values, rescaled=True, ring=Real Interval Field with 53 bits of precision)#

Compute the (rescaled) difference between this asymptotic expansion and the given values.

INPUT:

  • variable – an asymptotic expansion or a string.

  • function – a callable or symbolic expression giving the comparison values.

  • values – a list or iterable of values where the comparison shall be carried out.

  • rescaled – (default: True) determines whether the difference is divided by the error term of the asymptotic expansion.

  • ring – (default: RIF) the parent into which the difference is converted.

OUTPUT:

A list of pairs containing comparison points and (rescaled) difference values.

EXAMPLES:

sage: assume(SR.an_element() > 0)
sage: A.<n> = AsymptoticRing('QQ^n * n^ZZ', SR)
sage: catalan = binomial(2*x, x)/(x+1)
sage: expansion = 4^n*(1/sqrt(pi)*n^(-3/2)
....:     - 9/8/sqrt(pi)*n^(-5/2)
....:     + 145/128/sqrt(pi)*n^(-7/2) + O(n^(-9/2)))
sage: expansion.compare_with_values(n, catalan, srange(5, 10))
[(5, 0.5303924444775?),
 (6, 0.5455279498787?),
 (7, 0.556880411050?),
 (8, 0.565710587724?),
 (9, 0.572775029098?)]
sage: expansion.exact_part().compare_with_values(n, catalan, [5, 10, 20])
Traceback (most recent call last):
...
NotImplementedError: exactly one error term required
sage: expansion.exact_part().compare_with_values(n, catalan, [5, 10, 20], rescaled=False)
[(5, 0.3886263699387?), (10, 19.1842458318?), (20, 931314.63637?)]
sage: expansion.compare_with_values(n, catalan, [5, 10, 20], rescaled=False, ring=SR)
[(5, 168/5*sqrt(5)/sqrt(pi) - 42),
 (10, 1178112/125*sqrt(10)/sqrt(pi) - 16796),
 (20, 650486218752/125*sqrt(5)/sqrt(pi) - 6564120420)]

Instead of a symbolic expression, a callable function can be specified as well:

sage: A.<n> = AsymptoticRing('n^ZZ * log(n)^ZZ', SR)
sage: def H(n):
....:     return sum(1/k for k in srange(1, n+1))
sage: H_expansion = (log(n) + euler_gamma + 1/(2*n)
....:                - 1/(12*n^2) + O(n^-4))
sage: H_expansion.compare_with_values(n, H, srange(25, 30)) # rel tol 1e-6
[(25, -0.008326995?),
 (26, -0.008327472?),
 (27, -0.008327898?),
 (28, -0.00832828?),
 (29, -0.00832862?)]
sage: forget()
error_part()#

Return the expansion consisting of all error terms of this expansion.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: R.<x,y> = AsymptoticRing('x^QQ * log(x)^QQ * y^QQ', QQ)
sage: (x*log(x) + y^2 + O(x) + O(y)).error_part()
O(x) + O(y)
exact_part()#

Return the expansion consisting of all exact terms of this expansion.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: R.<x> = AsymptoticRing('x^QQ * log(x)^QQ', QQ)
sage: (x^2 + O(x)).exact_part()
x^2
sage: (x + log(x)/2 + O(log(x)/x)).exact_part()
x + 1/2*log(x)
exp(precision=None)#

Return the exponential of (i.e., the power of \(e\) to) this asymptotic expansion.

INPUT:

  • precision – the precision used for truncating the expansion. If None (default value) is used, the default precision of the parent is used.

OUTPUT:

An asymptotic expansion.

Note

The exponential function of this expansion can only be computed exactly if the respective growth element can be constructed in the underlying growth group.

ALGORITHM:

If the corresponding growth can be constructed, return the exact exponential function. Otherwise, if this term is \(o(1)\), try to expand the series and truncate according to the given precision.

Todo

As soon as \(L\)-terms are implemented, this implementation has to be adapted as well in order to yield correct results.

EXAMPLES:

sage: A.<x> = AsymptoticRing('(e^x)^ZZ * x^ZZ * log(x)^ZZ', SR)
sage: exp(x)
e^x
sage: exp(2*x)
(e^x)^2
sage: exp(x + log(x))
e^x*x
sage: (x^(-1)).exp(precision=7)
1 + x^(-1) + 1/2*x^(-2) + 1/6*x^(-3) + ... + O(x^(-7))
factorial()#

Return the factorial of this asymptotic expansion.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: A.<n> = AsymptoticRing(growth_group='n^ZZ * log(n)^ZZ', coefficient_ring=ZZ, default_prec=5)
sage: n.factorial()
sqrt(2)*sqrt(pi)*e^(n*log(n))*(e^n)^(-1)*n^(1/2)
+ 1/12*sqrt(2)*sqrt(pi)*e^(n*log(n))*(e^n)^(-1)*n^(-1/2)
+ 1/288*sqrt(2)*sqrt(pi)*e^(n*log(n))*(e^n)^(-1)*n^(-3/2)
+ O(e^(n*log(n))*(e^n)^(-1)*n^(-5/2))
sage: _.parent()
Asymptotic Ring <(e^(n*log(n)))^QQ * (e^n)^QQ * n^QQ * log(n)^QQ>
over Symbolic Constants Subring

Catalan numbers \(\frac{1}{n+1}\binom{2n}{n}\):

sage: (2*n).factorial() / n.factorial()^2 / (n+1)  # long time
1/sqrt(pi)*(e^n)^(2*log(2))*n^(-3/2)
- 9/8/sqrt(pi)*(e^n)^(2*log(2))*n^(-5/2)
+ 145/128/sqrt(pi)*(e^n)^(2*log(2))*n^(-7/2)
+ O((e^n)^(2*log(2))*n^(-9/2))

Note that this method substitutes the asymptotic expansion into Stirling’s formula. This substitution has to be possible which is not always guaranteed:

sage: S.<s> = AsymptoticRing(growth_group='s^QQ * log(s)^QQ', coefficient_ring=QQ, default_prec=4)
sage: log(s).factorial()
Traceback (most recent call last):
...
TypeError: Cannot apply the substitution rules {s: log(s)} on
sqrt(2)*sqrt(pi)*e^(s*log(s))*(e^s)^(-1)*s^(1/2)
+ O(e^(s*log(s))*(e^s)^(-1)*s^(-1/2)) in
Asymptotic Ring <(e^(s*log(s)))^QQ * (e^s)^QQ * s^QQ * log(s)^QQ>
over Symbolic Constants Subring.
...

See also

Stirling()

has_same_summands(other)#

Return whether this asymptotic expansion and other have the same summands.

INPUT:

  • other – an asymptotic expansion.

OUTPUT:

A boolean.

Note

While for example O(x) == O(x) yields False, these expansions do have the same summands and this method returns True.

Moreover, this method uses the coercion model in order to find a common parent for this asymptotic expansion and other.

EXAMPLES:

sage: R_ZZ.<x_ZZ> = AsymptoticRing('x^ZZ', ZZ)
sage: R_QQ.<x_QQ> = AsymptoticRing('x^ZZ', QQ)
sage: sum(x_ZZ^k for k in range(5)) == sum(x_QQ^k for k in range(5))  # indirect doctest
True
sage: O(x_ZZ) == O(x_QQ)
False
invert(precision=None)#

Return the multiplicative inverse of this element.

INPUT:

  • precision – the precision used for truncating the expansion. If None (default value) is used, the default precision of the parent is used.

OUTPUT:

An asymptotic expansion.

Warning

Due to truncation of infinite expansions, the element returned by this method might not fulfill el * ~el == 1.

Todo

As soon as \(L\)-terms are implemented, this implementation has to be adapted as well in order to yield correct results.

EXAMPLES:

sage: R.<x> = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=QQ, default_prec=4)
sage: ~x
x^(-1)
sage: ~(x^42)
x^(-42)
sage: ex = ~(1 + x); ex
x^(-1) - x^(-2) + x^(-3) - x^(-4) + O(x^(-5))
sage: ex * (1+x)
1 + O(x^(-4))
sage: ~(1 + O(1/x))
1 + O(x^(-1))
is_exact()#

Return whether all terms of this expansion are exact.

OUTPUT:

A boolean.

EXAMPLES:

sage: A.<x> = AsymptoticRing('x^QQ * log(x)^QQ', QQ)
sage: (x^2 + O(x)).is_exact()
False
sage: (x^2 - x).is_exact()
True
is_little_o_of_one()#

Return whether this expansion is of order \(o(1)\).

OUTPUT:

A boolean.

EXAMPLES:

sage: A.<x> = AsymptoticRing('x^ZZ * log(x)^ZZ', QQ)
sage: (x^4 * log(x)^(-2) + x^(-4) * log(x)^2).is_little_o_of_one()
False
sage: (x^(-1) * log(x)^1234 + x^(-2) + O(x^(-3))).is_little_o_of_one()
True
sage: (log(x) - log(x-1)).is_little_o_of_one()
True
sage: A.<x, y> = AsymptoticRing('x^QQ * y^QQ * log(y)^ZZ', QQ)
sage: (x^(-1/16) * y^32 + x^32 * y^(-1/16)).is_little_o_of_one()
False
sage: (x^(-1) * y^(-3) + x^(-3) * y^(-1)).is_little_o_of_one()
True
sage: (x^(-1) * y / log(y)).is_little_o_of_one()
False
sage: (log(y-1)/log(y) - 1).is_little_o_of_one()
True

See also

limit()

limit()#

Compute the limit of this asymptotic expansion.

OUTPUT:

An element of the coefficient ring.

EXAMPLES:

sage: A.<s> = AsymptoticRing("s^ZZ", SR, default_prec=3)
sage: (3 + 1/s + O(1/s^2)).limit()
3
sage: ((1+1/s)^s).limit()
e
sage: (1/s).limit()
0
sage: (s + 3 + 1/s + O(1/s^2)).limit()
Traceback (most recent call last):
...
ValueError: Cannot determine limit of s + 3 + s^(-1) + O(s^(-2))
sage: (O(s^0)).limit()
Traceback (most recent call last):
...
ValueError: Cannot determine limit of O(1)
log(base=None, precision=None, locals=None)#

The logarithm of this asymptotic expansion.

INPUT:

  • base – the base of the logarithm. If None (default value) is used, the natural logarithm is taken.

  • precision – the precision used for truncating the expansion. If None (default value) is used, the default precision of the parent is used.

  • locals – a dictionary which may contain the following keys and values:

    • 'log' – value: a function. If not used, then the usual log is taken.

OUTPUT:

An asymptotic expansion.

Note

Computing the logarithm of an asymptotic expansion is possible if and only if there is exactly one maximal summand in the expansion.

ALGORITHM:

If the expansion has more than one summand, the asymptotic expansion for \(\log(1+t)\) as \(t\) tends to \(0\) is used.

Todo

As soon as \(L\)-terms are implemented, this implementation has to be adapted as well in order to yield correct results.

EXAMPLES:

sage: R.<x> = AsymptoticRing(growth_group='x^ZZ * log(x)^ZZ', coefficient_ring=QQ)
sage: log(x)
log(x)
sage: log(x^2)
2*log(x)
sage: log(x-1)
log(x) - x^(-1) - 1/2*x^(-2) - 1/3*x^(-3) - ... + O(x^(-21))

The coefficient ring is automatically extended if needed:

sage: R.<x> = AsymptoticRing(growth_group='x^ZZ * log(x)^ZZ', coefficient_ring=ZZ, default_prec=3)
sage: (49*x^3-1).log()
3*log(x) + 2*log(7) - 1/49*x^(-3) - 1/4802*x^(-6) ... + O(x^(-12))
sage: _.parent()
Asymptotic Ring <x^ZZ * log(x)^ZZ> over Symbolic Ring

If one wants to avoid this extending to the Symbolic Ring, then the following helps:

sage: L.<log7> = ZZ[]
sage: def mylog(z, base=None):
....:     try:
....:         if ZZ(z).is_power_of(7):
....:             return log(ZZ(z), 7) * log7
....:     except (TypeError, ValueError):
....:         pass
....:     return log(z, base)
sage: R.<x> = AsymptoticRing(growth_group='x^ZZ * log(x)^ZZ', coefficient_ring=L, default_prec=3)
sage: (49*x^3-1).log(locals={'log': mylog})
3*log(x) + 2*log7 - 1/49*x^(-3) - 1/4802*x^(-6) ... + O(x^(-12))

A log-function can also be specified to always be used with the asymptotic ring:

sage: R.<x> = AsymptoticRing(growth_group='x^ZZ * log(x)^ZZ', coefficient_ring=L, default_prec=3, locals={'log': mylog})
sage: log(49*x^3-1)
3*log(x) + 2*log7 - 1/49*x^(-3) - 1/4802*x^(-6) - 1/352947*x^(-9) + O(x^(-12))
map_coefficients(f, new_coefficient_ring=None)#

Return the asymptotic expansion obtained by applying f to each coefficient of this asymptotic expansion.

INPUT:

  • f – a callable. A coefficient \(c\) will be mapped to \(f(c)\).

  • new_coefficient_ring – (default: None) a ring.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: A.<n> = AsymptoticRing(growth_group='n^ZZ', coefficient_ring=ZZ)
sage: a = n^4 + 2*n^3 + 3*n^2 + O(n)
sage: a.map_coefficients(lambda c: c+1)
2*n^4 + 3*n^3 + 4*n^2 + O(n)
sage: a.map_coefficients(lambda c: c-2)
-n^4 + n^2 + O(n)
monomial_coefficient(monomial)#

Return the coefficient in the base ring of the given monomial in this expansion.

INPUT:

  • monomial – a monomial element which can be converted into the asymptotic ring of this element

OUTPUT:

An element of the coefficient ring.

EXAMPLES:

sage: R.<m, n> = AsymptoticRing("m^QQ*n^QQ", QQ)
sage: ae = 13 + 42/n + 2/n/m + O(n^-2)
sage: ae.monomial_coefficient(1/n)
42
sage: ae.monomial_coefficient(1/n^3)
0
sage: R.<n> = AsymptoticRing("n^QQ", ZZ)
sage: ae.monomial_coefficient(1/n)
42
sage: ae.monomial_coefficient(1)
13
plot_comparison(variable, function, values, rescaled=True, ring=Real Interval Field with 53 bits of precision, relative_tolerance=0.025, **kwargs)#

Plot the (rescaled) difference between this asymptotic expansion and the given values.

INPUT:

  • variable – an asymptotic expansion or a string.

  • function – a callable or symbolic expression giving the comparison values.

  • values – a list or iterable of values where the comparison shall be carried out.

  • rescaled – (default: True) determines whether the difference is divided by the error term of the asymptotic expansion.

  • ring – (default: RIF) the parent into which the difference is converted.

  • relative_tolerance – (default: 0.025). Raise error when relative error exceeds this tolerance.

Other keyword arguments are passed to list_plot().

OUTPUT:

A graphics object.

Note

If rescaled (i.e. divided by the error term), the output should be bounded.

This method is mainly meant to have an easily usable plausibility check for asymptotic expansion created in some way.

EXAMPLES:

We want to check the quality of the asymptotic expansion of the harmonic numbers:

sage: A.<n> = AsymptoticRing('n^ZZ * log(n)^ZZ', SR)
sage: def H(n):
....:     return sum(1/k for k in srange(1, n+1))
sage: H_expansion = (log(n) + euler_gamma + 1/(2*n)
....:                - 1/(12*n^2) + O(n^-4))
sage: H_expansion.plot_comparison(n, H, srange(1, 30))
Graphics object consisting of 1 graphics primitive

Alternatively, the unscaled (absolute) difference can be plotted as well:

sage: H_expansion.plot_comparison(n, H, srange(1, 30),
....:                             rescaled=False)
Graphics object consisting of 1 graphics primitive

Additional keywords are passed to list_plot():

sage: H_expansion.plot_comparison(n, H, srange(1, 30),
....:                             plotjoined=True, marker='o',
....:                             color='green')
Graphics object consisting of 1 graphics primitive
pow(exponent, precision=None)#

Calculate the power of this asymptotic expansion to the given exponent.

INPUT:

  • exponent – an element.

  • precision – the precision used for truncating the expansion. If None (default value) is used, the default precision of the parent is used.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: Q.<x> = AsymptoticRing(growth_group='x^QQ', coefficient_ring=QQ)
sage: x^(1/7)
x^(1/7)
sage: (x^(1/2) + O(x^0))^15
x^(15/2) + O(x^7)
sage: Z.<y> = AsymptoticRing(growth_group='y^ZZ', coefficient_ring=ZZ)
sage: y^(1/7)
y^(1/7)
sage: _.parent()
Asymptotic Ring <y^QQ> over Rational Field
sage: (y^2 + O(y))^(1/2)
y + O(1)
sage: (y^2 + O(y))^(-2)
y^(-4) + O(y^(-5))
sage: (1 + 1/y + O(1/y^3))^pi
1 + pi*y^(-1) + (1/2*pi*(pi - 1))*y^(-2) + O(y^(-3))
sage: B.<z> = AsymptoticRing(growth_group='z^QQ * log(z)^QQ', coefficient_ring=QQ)
sage: (z^2 + O(z))^(1/2)
z + O(1)
sage: A.<x> = AsymptoticRing('QQ^x * x^SR * log(x)^ZZ', QQ)
sage: x * 2^x
2^x*x
sage: 5^x * 2^x
10^x
sage: 2^log(x)
x^(log(2))
sage: 2^(x + 1/x)
2^x + log(2)*2^x*x^(-1) + 1/2*log(2)^2*2^x*x^(-2) + ... + O(2^x*x^(-20))
sage: _.parent()
Asymptotic Ring <QQ^x * x^SR * log(x)^QQ * Signs^x> over Symbolic Ring
sage: C.<c> = AsymptoticRing(growth_group='QQ^c * c^QQ', coefficient_ring=QQ, default_prec=5)
sage: (3 + 1/c^2)^c
3^c + 1/3*3^c*c^(-1) + 1/18*3^c*c^(-2) - 4/81*3^c*c^(-3)
- 35/1944*3^c*c^(-4) + O(3^c*c^(-5))
sage: _.parent()
Asymptotic Ring <QQ^c * c^QQ * Signs^c> over Rational Field
sage: (2 + (1/3)^c)^c
2^c + 1/2*(2/3)^c*c + 1/8*(2/9)^c*c^2 - 1/8*(2/9)^c*c
+ 1/48*(2/27)^c*c^3 + O((2/27)^c*c^2)
sage: _.parent()
Asymptotic Ring <QQ^c * c^QQ * Signs^c> over Rational Field
rpow(base, precision=None, locals=None)#

Return the power of base to this asymptotic expansion.

INPUT:

  • base – an element or 'e'.

  • precision – the precision used for truncating the expansion. If None (default value) is used, the default precision of the parent is used.

  • locals – a dictionary which may contain the following keys and values:

    • 'log' – value: a function. If not used, then the usual log is taken.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: A.<x> = AsymptoticRing('x^ZZ', QQ)
sage: (1/x).rpow('e', precision=5)
1 + x^(-1) + 1/2*x^(-2) + 1/6*x^(-3) + 1/24*x^(-4) + O(x^(-5))
show()#

Pretty-print this asymptotic expansion.

OUTPUT:

Nothing, the representation is printed directly on the screen.

EXAMPLES:

sage: A.<x> = AsymptoticRing('QQ^x * x^QQ * log(x)^QQ', SR.subring(no_variables=True))
sage: (pi/2 * 5^x * x^(42/17) - sqrt(euler_gamma) * log(x)^(-7/8)).show()
1/2*pi*5^x*x^(42/17) - sqrt(euler_gamma)*log(x)^(-7/8)
sqrt(precision=None)#

Return the square root of this asymptotic expansion.

INPUT:

  • precision – the precision used for truncating the expansion. If None (default value) is used, the default precision of the parent is used.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: A.<s> = AsymptoticRing(growth_group='s^QQ', coefficient_ring=QQ)
sage: s.sqrt()
s^(1/2)
sage: a = (1 + 1/s).sqrt(precision=6); a
1 + 1/2*s^(-1) - 1/8*s^(-2) + 1/16*s^(-3)
- 5/128*s^(-4) + 7/256*s^(-5) + O(s^(-6))

See also

pow(), rpow(), exp().

subs(rules=None, domain=None, **kwds)#

Substitute the given rules in this asymptotic expansion.

INPUT:

  • rules – a dictionary.

  • kwds – keyword arguments will be added to the substitution rules.

  • domain – (default: None) a parent. The neutral elements \(0\) and \(1\) (rules for the keys '_zero_' and '_one_', see note box below) are taken out of this domain. If None, then this is determined automatically.

OUTPUT:

An object.

Note

The neutral element of the asymptotic ring is replaced by the value to the key '_zero_'; the neutral element of the growth group is replaced by the value to the key '_one_'.

EXAMPLES:

sage: A.<x> = AsymptoticRing(growth_group='(e^x)^QQ * x^ZZ * log(x)^ZZ', coefficient_ring=QQ, default_prec=5)
sage: (e^x * x^2 + log(x)).subs(x=SR('s'))
s^2*e^s + log(s)
sage: _.parent()
Symbolic Ring
sage: (x^3 + x + log(x)).subs(x=x+5).truncate(5)
x^3 + 15*x^2 + 76*x + log(x) + 130 + O(x^(-1))
sage: _.parent()
Asymptotic Ring <(e^x)^QQ * x^ZZ * log(x)^ZZ> over Rational Field
sage: (e^x * x^2 + log(x)).subs(x=2*x)
4*(e^x)^2*x^2 + log(x) + log(2)
sage: _.parent()
Asymptotic Ring <(e^x)^QQ * x^QQ * log(x)^QQ> over Symbolic Ring
sage: (x^2 + log(x)).subs(x=4*x+2).truncate(5)
16*x^2 + 16*x + log(x) + 2*log(2) + 4 + 1/2*x^(-1) + O(x^(-2))
sage: _.parent()
Asymptotic Ring <(e^x)^QQ * x^ZZ * log(x)^ZZ> over Symbolic Ring
sage: (e^x * x^2 + log(x)).subs(x=RIF(pi))
229.534211738584?
sage: _.parent()
Real Interval Field with 53 bits of precision
property summands#

The summands of this asymptotic expansion stored in the underlying data structure (a MutablePoset).

EXAMPLES:

sage: R.<x> = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: expr = 7*x^12 + x^5 + O(x^3)
sage: expr.summands
poset(O(x^3), x^5, 7*x^12)
symbolic_expression(R=None)#

Return this asymptotic expansion as a symbolic expression.

INPUT:

  • R – (a subring of) the symbolic ring or None. The output will be an element of R. If None, then the symbolic ring is used.

OUTPUT:

A symbolic expression.

EXAMPLES:

sage: A.<x, y, z> = AsymptoticRing(growth_group='x^ZZ * y^QQ * log(y)^QQ * (QQ_+)^z * z^QQ', coefficient_ring=QQ)
sage: SR(A.an_element())  # indirect doctest
1/8*(1/8)^z*x^3*y^(3/2)*z^(3/2)*log(y)^(3/2) +
Order((1/2)^z*x*sqrt(y)*sqrt(z)*sqrt(log(y)))

sage: A.<x, y, z> = AsymptoticRing(growth_group='x^ZZ * y^QQ * log(y)^QQ * (QQ_+)^z * z^QQ', coefficient_ring=QQ)
sage: SR(A.an_element())  # indirect doctest
1/8*(1/8)^z*x^3*y^(3/2)*z^(3/2)*log(y)^(3/2) +
Order((1/2)^z*x*sqrt(y)*sqrt(z)*sqrt(log(y)))
truncate(precision=None)#

Truncate this asymptotic expansion.

INPUT:

  • precision – a positive integer or None. Number of summands that are kept. If None (default value) is given, then default_prec from the parent is used.

OUTPUT:

An asymptotic expansion.

Note

For example, truncating an asymptotic expansion with precision=20 does not yield an expansion with exactly 20 summands! Rather than that, it keeps the 20 summands with the largest growth, and adds appropriate \(O\)-Terms.

EXAMPLES:

sage: R.<x> = AsymptoticRing('x^ZZ', QQ)
sage: ex = sum(x^k for k in range(5)); ex
x^4 + x^3 + x^2 + x + 1
sage: ex.truncate(precision=2)
x^4 + x^3 + O(x^2)
sage: ex.truncate(precision=0)
O(x^4)
sage: ex.truncate()
x^4 + x^3 + x^2 + x + 1
variable_names()#

Return the names of the variables of this asymptotic expansion.

OUTPUT:

A tuple of strings.

EXAMPLES:

sage: A.<m, n> = AsymptoticRing('QQ^m * m^QQ * n^ZZ * log(n)^ZZ', QQ)
sage: (4*2^m*m^4*log(n)).variable_names()
('m', 'n')
sage: (4*2^m*m^4).variable_names()
('m',)
sage: (4*log(n)).variable_names()
('n',)
sage: (4*m^3).variable_names()
('m',)
sage: (4*m^0).variable_names()
()
sage: (4*2^m*m^4 + log(n)).variable_names()
('m', 'n')
sage: (2^m + m^4 + log(n)).variable_names()
('m', 'n')
sage: (2^m + m^4).variable_names()
('m',)
class sage.rings.asymptotic.asymptotic_ring.AsymptoticRing(growth_group, coefficient_ring, category, default_prec, term_monoid_factory, locals)#

Bases: Algebra, UniqueRepresentation, WithLocals

A ring consisting of asymptotic expansions.

INPUT:

  • growth_group – either a partially ordered group (see (Asymptotic) Growth Groups) or a string describing such a growth group (see GrowthGroupFactory).

  • coefficient_ring – the ring which contains the coefficients of the expansions.

  • default_prec – a positive integer. This is the number of summands that are kept before truncating an infinite series.

  • category – the category of the parent can be specified in order to broaden the base structure. It has to be a subcategory of Category of rings. This is also the default category if None is specified.

  • term_monoid_factory – a TermMonoidFactory. If None, then DefaultTermMonoidFactory is used.

  • locals – a dictionary which may contain the following keys and values:

EXAMPLES:

We begin with the construction of an asymptotic ring in various ways. First, we simply pass a string specifying the underlying growth group:

sage: R1_x.<x> = AsymptoticRing(growth_group='x^QQ', coefficient_ring=QQ); R1_x
Asymptotic Ring <x^QQ> over Rational Field
sage: x
x

This is equivalent to the following code, which explicitly specifies the underlying growth group:

sage: from sage.rings.asymptotic.growth_group import GrowthGroup
sage: G_QQ = GrowthGroup('x^QQ')
sage: R2_x.<x> = AsymptoticRing(growth_group=G_QQ, coefficient_ring=QQ); R2_x
Asymptotic Ring <x^QQ> over Rational Field

Of course, the coefficient ring of the asymptotic ring and the base ring of the underlying growth group do not need to coincide:

sage: R_ZZ_x.<x> = AsymptoticRing(growth_group='x^QQ', coefficient_ring=ZZ); R_ZZ_x
Asymptotic Ring <x^QQ> over Integer Ring

Note, we can also create and use logarithmic growth groups:

sage: R_log = AsymptoticRing(growth_group='log(x)^ZZ', coefficient_ring=QQ); R_log
Asymptotic Ring <log(x)^ZZ> over Rational Field

Other growth groups are available. See Asymptotic Ring for more examples.

Below there are some technical details.

According to the conventions for parents, uniqueness is ensured:

sage: R1_x is R2_x
True

Furthermore, the coercion framework is also involved. Coercion between two asymptotic rings is possible (given that the underlying growth groups and coefficient rings are chosen appropriately):

sage: R1_x.has_coerce_map_from(R_ZZ_x)
True

Additionally, for the sake of convenience, the coefficient ring also coerces into the asymptotic ring (representing constant quantities):

sage: R1_x.has_coerce_map_from(QQ)
True

It is possible to customize the terms in an asymptotic expansion:

sage: from sage.rings.asymptotic.term_monoid import ExactTermMonoid, OTermMonoid
sage: from sage.rings.asymptotic.term_monoid import TermMonoidFactory
sage: class MyExactTermMonoid(ExactTermMonoid):
....:     pass
sage: class MyOTermMonoid(OTermMonoid):
....:     pass
sage: MyTermMonoid = TermMonoidFactory('MyTermMonoid',
....:                                  exact_term_monoid_class=MyExactTermMonoid,
....:                                  O_term_monoid_class=MyOTermMonoid)
sage: G = GrowthGroup('x^ZZ')
sage: A.<n> = AsymptoticRing(growth_group=G, coefficient_ring=QQ, term_monoid_factory=MyTermMonoid)
sage: a = A.an_element(); a
1/8*x^3 + O(x)
sage: for t in a.summands.elements_topological(reverse=True):
....:     print(t, type(t))
1/8*x^3 <class '__main__.MyExactTermMonoid_with_category.element_class'>
O(x) <class '__main__.MyOTermMonoid_with_category.element_class'>
static B(expression, valid_from=0)#

Create a B-term.

INPUT:

  • valid_from – dictionary mapping variable names to lower bounds for the corresponding variable. The bound implied by this term is valid when all variables are at least their corresponding lower bound. If a number is passed to valid_from, then the lower bounds for all variables of the asymptotic expansion are set to this number

OUTPUT:

A B-term

EXAMPLES:

sage: A.<x> = AsymptoticRing(growth_group='x^ZZ * QQ^y', coefficient_ring=QQ)
sage: A.B(2*x^3, {x: 5})
B(2*x^3, x >= 5)
Element#

alias of AsymptoticExpansion

change_parameter(**kwds)#

Return an asymptotic ring with a change in one or more of the given parameters.

INPUT:

  • growth_group – (default: None) the new growth group.

  • coefficient_ring – (default: None) the new coefficient ring.

  • category – (default: None) the new category.

  • default_prec – (default: None) the new default precision.

OUTPUT:

An asymptotic ring.

EXAMPLES:

sage: A = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: A.change_parameter(coefficient_ring=QQ)
Asymptotic Ring <x^ZZ> over Rational Field
property coefficient_ring#

The coefficient ring of this asymptotic ring.

EXAMPLES:

sage: AR = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.coefficient_ring
Integer Ring
coefficients_of_generating_function(function, singularities, precision=None, return_singular_expansions=False, error_term=None)#

Return the asymptotic growth of the coefficients of some generating function by means of Singularity Analysis.

INPUT:

  • function – a callable function in one variable.

  • singularities – list of dominant singularities of the function.

  • precision – (default: None) an integer. If None, then the default precision of the asymptotic ring is used.

  • return_singular_expansions – (default: False) a boolean. If set, the singular expansions are also returned.

  • error_term – (default: None) an asymptotic expansion. If None, then this is interpreted as zero. The contributions of the coefficients are added to error_term during Singularity Analysis.

OUTPUT:

  • If return_singular_expansions=False: An asymptotic expansion from this ring.

  • If return_singular_expansions=True: A named tuple with components asymptotic_expansion and singular_expansions. The former contains an asymptotic expansion from this ring, the latter is a dictionary which contains the singular expansions around the singularities.

Todo

Make this method more usable by implementing the processing of symbolic expressions.

EXAMPLES:

Catalan numbers:

sage: def catalan(z):
....:     return (1-(1-4*z)^(1/2))/(2*z)
sage: B.<n> = AsymptoticRing('QQ^n * n^QQ', QQ)
sage: B.coefficients_of_generating_function(catalan, (1/4,), precision=3)
1/sqrt(pi)*4^n*n^(-3/2) - 9/8/sqrt(pi)*4^n*n^(-5/2)
+ 145/128/sqrt(pi)*4^n*n^(-7/2) + O(4^n*n^(-4))
sage: B.coefficients_of_generating_function(catalan, (1/4,), precision=2,
....:                        return_singular_expansions=True)
SingularityAnalysisResult(asymptotic_expansion=1/sqrt(pi)*4^n*n^(-3/2)
- 9/8/sqrt(pi)*4^n*n^(-5/2) + O(4^n*n^(-3)),
singular_expansions={1/4: 2 - 2*T^(-1/2)
+ 2*T^(-1) - 2*T^(-3/2) + O(T^(-2))})

Unit fractions:

sage: def logarithmic(z):
....:     return -log(1-z)
sage: B.coefficients_of_generating_function(logarithmic, (1,), precision=5)
n^(-1) + O(n^(-3))

Harmonic numbers:

sage: def harmonic(z):
....:     return -log(1-z)/(1-z)
sage: B.<n> = AsymptoticRing('QQ^n * n^QQ * log(n)^QQ', QQ)
sage: ex = B.coefficients_of_generating_function(harmonic, (1,), precision=13); ex
log(n) + euler_gamma + 1/2*n^(-1) - 1/12*n^(-2) + 1/120*n^(-4)
+ O(n^(-6))
sage: ex.has_same_summands(asymptotic_expansions.HarmonicNumber(
....:    'n', precision=5))
True

Warning

Once singular expansions around points other than infinity are implemented (github issue #20050), the output in the case return_singular_expansions will change to return singular expansions around the singularities.

In the following example, the result is an exact asymptotic expression for sufficiently large \(n\) (i.e., there might be finitely many exceptional values). This is encoded by an \(O(0)\) error term:

sage: def f(z):
....:     return z/(1-z)
sage: B.coefficients_of_generating_function(f, (1,), precision=3)
Traceback (most recent call last):
...
NotImplementedOZero: got 1 + O(0)
The error term O(0) means 0 for sufficiently large n.

In this case, we can manually intervene by adding an error term that suits us:

sage: B.coefficients_of_generating_function(f, (1,), precision=3,
....:                                       error_term=O(n^-100))
1 + O(n^(-100))
construction()#

Return the construction of this asymptotic ring.

OUTPUT:

A pair whose first entry is an asymptotic ring construction functor and its second entry the coefficient ring.

EXAMPLES:

sage: A = AsymptoticRing(growth_group='x^ZZ * QQ^y', coefficient_ring=QQ)
sage: A.construction()
(AsymptoticRing<x^ZZ * QQ^y * Signs^y>, Rational Field)
create_summand(type, data=None, **kwds)#

Create a simple asymptotic expansion consisting of a single summand.

INPUT:

  • type – ‘O’ or ‘exact’.

  • data – the element out of which a summand has to be created.

  • growth – an element of the growth_group().

  • coefficient – an element of the coefficient_ring().

Note

Either growth and coefficient or data have to be specified.

OUTPUT:

An asymptotic expansion.

Note

This method calls the factory TermMonoid with the appropriate arguments.

EXAMPLES:

sage: R = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: R.create_summand('O', x^2)
O(x^2)
sage: R.create_summand('exact', growth=x^456, coefficient=123)
123*x^456
sage: R.create_summand('exact', data=12*x^13)
12*x^13
property default_prec#

The default precision of this asymptotic ring.

This is the parameter used to determine how many summands are kept before truncating an infinite series (which occur when inverting asymptotic expansions).

EXAMPLES:

sage: AR = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.default_prec
20
sage: AR = AsymptoticRing('x^ZZ', ZZ, default_prec=123)
sage: AR.default_prec
123
gen(n=0)#

Return the n-th generator of this asymptotic ring.

INPUT:

  • n – (default: \(0\)) a non-negative integer.

OUTPUT:

An asymptotic expansion.

EXAMPLES:

sage: R.<x> = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: R.gen()
x
gens()#

Return a tuple with generators of this asymptotic ring.

OUTPUT:

A tuple of asymptotic expansions.

Note

Generators do not necessarily exist. This depends on the underlying growth group. For example, monomial growth groups have a generator, and exponential growth groups do not.

EXAMPLES:

sage: AR.<x> = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.gens()
(x,)
sage: B.<y,z> = AsymptoticRing(growth_group='y^ZZ * z^ZZ', coefficient_ring=QQ)
sage: B.gens()
(y, z)
property growth_group#

The growth group of this asymptotic ring.

EXAMPLES:

sage: AR = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.growth_group
Growth Group x^ZZ
ngens()#

Return the number of generators of this asymptotic ring.

OUTPUT:

An integer.

EXAMPLES:

sage: AR.<x> = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.ngens()
1
some_elements()#

Return some elements of this term monoid.

See TestSuite for a typical use case.

OUTPUT:

An iterator.

EXAMPLES:

sage: from itertools import islice
sage: A = AsymptoticRing(growth_group='z^QQ', coefficient_ring=ZZ)
sage: tuple(islice(A.some_elements(), int(10)))
(z^(3/2) + O(z^(1/2)),
 O(z^(1/2)),
 z^(3/2) + O(z^(-1/2)),
 -z^(3/2) + O(z^(1/2)),
 O(z^(-1/2)),
 O(z^2),
 z^6 + O(z^(1/2)),
 -z^(3/2) + O(z^(-1/2)),
 O(z^2),
 z^(3/2) + O(z^(-2)))
term_monoid(type)#

Return the term monoid of this asymptotic ring of specified type.

INPUT:

  • type – ‘O’ or ‘exact’, or an instance of an existing term monoid. See TermMonoidFactory for more details.

OUTPUT:

A term monoid object derived from GenericTermMonoid.

EXAMPLES:

sage: AR = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.term_monoid('exact')
Exact Term Monoid x^ZZ with coefficients in Integer Ring
sage: AR.term_monoid('O')
O-Term Monoid x^ZZ with implicit coefficients in Integer Ring
sage: AR.term_monoid(AR.term_monoid('exact'))
Exact Term Monoid x^ZZ with coefficients in Integer Ring
property term_monoid_factory#

The term monoid factory of this asymptotic ring.

EXAMPLES:

sage: AR = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=ZZ)
sage: AR.term_monoid_factory
Term Monoid Factory 'sage.rings.asymptotic.term_monoid.DefaultTermMonoidFactory'
variable_names()#

Return the names of the variables.

OUTPUT:

A tuple of strings.

EXAMPLES:

sage: A = AsymptoticRing(growth_group='x^ZZ * QQ^y', coefficient_ring=QQ)
sage: A.variable_names()
('x', 'y')
class sage.rings.asymptotic.asymptotic_ring.AsymptoticRingFunctor(growth_group, default_prec=None, category=None, term_monoid_factory=None, locals=None, cls=None)#

Bases: ConstructionFunctor

A construction functor for asymptotic rings.

INPUT:

EXAMPLES:

sage: AsymptoticRing(growth_group='x^ZZ', coefficient_ring=QQ).construction()  # indirect doctest
(AsymptoticRing<x^ZZ>, Rational Field)
merge(other)#

Merge this functor with other if possible.

INPUT:

  • other – a functor.

OUTPUT:

A functor or None.

EXAMPLES:

sage: X = AsymptoticRing(growth_group='x^ZZ', coefficient_ring=QQ)
sage: Y = AsymptoticRing(growth_group='y^ZZ', coefficient_ring=QQ)
sage: F_X = X.construction()[0]
sage: F_Y = Y.construction()[0]
sage: F_X.merge(F_X)
AsymptoticRing<x^ZZ>
sage: F_X.merge(F_Y)
AsymptoticRing<x^ZZ * y^ZZ>
rank = 13#
exception sage.rings.asymptotic.asymptotic_ring.NoConvergenceError#

Bases: RuntimeError

A special RuntimeError which is raised when an algorithm does not converge/stop.