Asymptotic Expansions — Miscellaneous

AUTHORS:

  • Daniel Krenn (2015)

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.

Functions, Classes and Methods

class sage.rings.asymptotic.misc.Locals[source]

Bases: dict

A frozen dictionary-like class for storing locals of an AsymptoticRing.

EXAMPLES:

sage: from sage.rings.asymptotic.misc import Locals
sage: locals = Locals({'a': 42})
sage: locals['a']
42
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import Locals
>>> locals = Locals({'a': Integer(42)})
>>> locals['a']
42
from sage.rings.asymptotic.misc import Locals
locals = Locals({'a': 42})
locals['a']

The object contains default values (see default_locals()) for some keys:

sage: locals['log']
<function log at 0x...>
>>> from sage.all import *
>>> locals['log']
<function log at 0x...>
locals['log']
default_locals()[source]

Return the default locals used in the AsymptoticRing.

OUTPUT: a dictionary

EXAMPLES:

sage: from sage.rings.asymptotic.misc import Locals
sage: locals = Locals({'a': 2, 'b': 1})
sage: locals
{'a': 2, 'b': 1}
sage: locals.default_locals()
{'log': <function log at 0x...>}
sage: locals['log']
<function log at 0x...>
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import Locals
>>> locals = Locals({'a': Integer(2), 'b': Integer(1)})
>>> locals
{'a': 2, 'b': 1}
>>> locals.default_locals()
{'log': <function log at 0x...>}
>>> locals['log']
<function log at 0x...>
from sage.rings.asymptotic.misc import Locals
locals = Locals({'a': 2, 'b': 1})
locals
locals.default_locals()
locals['log']
exception sage.rings.asymptotic.misc.NotImplementedBZero(asymptotic_ring=None, var=None, exact_part=0)[source]

Bases: NotImplementedError

A special NotImplementedError which is raised when the result is B(0) which means 0 for sufficiently large values of the variable.

exception sage.rings.asymptotic.misc.NotImplementedOZero(asymptotic_ring=None, var=None, exact_part=0)[source]

Bases: NotImplementedError

A special NotImplementedError which is raised when the result is O(0) which means 0 for sufficiently large values of the variable.

class sage.rings.asymptotic.misc.WithLocals[source]

Bases: SageObject

A class extensions for handling local values; see also Locals.

This is used in the AsymptoticRing.

EXAMPLES:

sage: A.<n> = AsymptoticRing('n^ZZ', QQ, locals={'a': 42})
sage: A.locals()
{'a': 42}
>>> from sage.all import *
>>> A = AsymptoticRing('n^ZZ', QQ, locals={'a': Integer(42)}, names=('n',)); (n,) = A._first_ngens(1)
>>> A.locals()
{'a': 42}
A.<n> = AsymptoticRing('n^ZZ', QQ, locals={'a': 42})
A.locals()
locals(locals=None)[source]

Return the actual Locals object to be used.

INPUT:

  • locals – an object

    If locals is not None, then a Locals object is created and returned. If locals is None, then a stored Locals object, if any, is returned. Otherwise, an empty (i.e. no values except the default values) Locals object is created and returned.

OUTPUT: a Locals object

sage.rings.asymptotic.misc.bidirectional_merge_overlapping(A, B, key=None)[source]

Merge the two overlapping tuples/lists.

INPUT:

  • A – list or tuple (type has to coincide with type of B)

  • B – list or tuple (type has to coincide with type of A)

  • key – (default: None) a function. If None, then the identity is used. This key-function applied on an element of the list/tuple is used for comparison. Thus elements with the same key are considered as equal.

OUTPUT:

A pair of lists or tuples (depending on the type of A and B).

Note

Suppose we can decompose the list \(A=ac\) and \(B=cb\) with lists \(a\), \(b\), \(c\), where \(c\) is nonempty. Then bidirectional_merge_overlapping() returns the pair \((acb, acb)\).

Suppose a key-function is specified and \(A=ac_A\) and \(B=c_Bb\), where the list of keys of the elements of \(c_A\) equals the list of keys of the elements of \(c_B\). Then bidirectional_merge_overlapping() returns the pair \((ac_Ab, ac_Bb)\).

After unsuccessfully merging \(A=ac\) and \(B=cb\), a merge of \(A=ca\) and \(B=bc\) is tried.

sage.rings.asymptotic.misc.bidirectional_merge_sorted(A, B, key=None)[source]

Merge the two tuples/lists, keeping the orders provided by them.

INPUT:

  • A – list or tuple (type has to coincide with type of B)

  • B – list or tuple (type has to coincide with type of A)

  • key – (default: None) a function. If None, then the identity is used. This key-function applied on an element of the list/tuple is used for comparison. Thus elements with the same key are considered as equal.

Note

The two tuples/list need to overlap, i.e. need at least one key in common.

OUTPUT:

A pair of lists containing all elements totally ordered. (The first component uses A as a merge base, the second component B.)

If merging fails, then a RuntimeError is raised.

sage.rings.asymptotic.misc.combine_exceptions(e, *f)[source]

Helper function which combines the messages of the given exceptions.

INPUT:

  • e – an exception

  • *f – exceptions

OUTPUT: an exception

EXAMPLES:

sage: from sage.rings.asymptotic.misc import combine_exceptions
sage: raise combine_exceptions(ValueError('Outer.'), TypeError('Inner.'))
Traceback (most recent call last):
...
ValueError: Outer.
> *previous* TypeError: Inner.
sage: raise combine_exceptions(ValueError('Outer.'),
....:                          TypeError('Inner1.'), TypeError('Inner2.'))
Traceback (most recent call last):
...
ValueError: Outer.
> *previous* TypeError: Inner1.
> *and* TypeError: Inner2.
sage: raise combine_exceptions(ValueError('Outer.'),
....:                          combine_exceptions(TypeError('Middle.'),
....:                                             TypeError('Inner.')))
Traceback (most recent call last):
...
ValueError: Outer.
> *previous* TypeError: Middle.
>> *previous* TypeError: Inner.
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import combine_exceptions
>>> raise combine_exceptions(ValueError('Outer.'), TypeError('Inner.'))
Traceback (most recent call last):
...
ValueError: Outer.
> *previous* TypeError: Inner.
>>> raise combine_exceptions(ValueError('Outer.'),
...                          TypeError('Inner1.'), TypeError('Inner2.'))
Traceback (most recent call last):
...
ValueError: Outer.
> *previous* TypeError: Inner1.
> *and* TypeError: Inner2.
>>> raise combine_exceptions(ValueError('Outer.'),
...                          combine_exceptions(TypeError('Middle.'),
...                                             TypeError('Inner.')))
Traceback (most recent call last):
...
ValueError: Outer.
> *previous* TypeError: Middle.
>> *previous* TypeError: Inner.
from sage.rings.asymptotic.misc import combine_exceptions
raise combine_exceptions(ValueError('Outer.'), TypeError('Inner.'))
raise combine_exceptions(ValueError('Outer.'),
                         TypeError('Inner1.'), TypeError('Inner2.'))
raise combine_exceptions(ValueError('Outer.'),
                         combine_exceptions(TypeError('Middle.'),
                                            TypeError('Inner.')))
sage.rings.asymptotic.misc.log_string(element, base=None)[source]

Return a representation of the log of the given element to the given base.

INPUT:

  • element – an object

  • base – an object or None

OUTPUT: string

EXAMPLES:

sage: from sage.rings.asymptotic.misc import log_string
sage: log_string(3)
'log(3)'
sage: log_string(3, base=42)
'log(3, base=42)'
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import log_string
>>> log_string(Integer(3))
'log(3)'
>>> log_string(Integer(3), base=Integer(42))
'log(3, base=42)'
from sage.rings.asymptotic.misc import log_string
log_string(3)
log_string(3, base=42)
sage.rings.asymptotic.misc.parent_to_repr_short(P)[source]

Helper method which generates a short(er) representation string out of a parent.

INPUT:

  • P – a parent

OUTPUT: string

EXAMPLES:

sage: from sage.rings.asymptotic.misc import parent_to_repr_short
sage: parent_to_repr_short(ZZ)
'ZZ'
sage: parent_to_repr_short(QQ)
'QQ'
sage: parent_to_repr_short(SR)
'SR'
sage: parent_to_repr_short(RR)
'RR'
sage: parent_to_repr_short(CC)
'CC'
sage: parent_to_repr_short(ZZ['x'])
'ZZ[x]'
sage: parent_to_repr_short(QQ['d, k'])
'QQ[d, k]'
sage: parent_to_repr_short(QQ['e'])
'QQ[e]'
sage: parent_to_repr_short(SR[['a, r']])
'SR[[a, r]]'
sage: parent_to_repr_short(Zmod(3))
'Ring of integers modulo 3'
sage: parent_to_repr_short(Zmod(3)['g'])
'Univariate Polynomial Ring in g over Ring of integers modulo 3'
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import parent_to_repr_short
>>> parent_to_repr_short(ZZ)
'ZZ'
>>> parent_to_repr_short(QQ)
'QQ'
>>> parent_to_repr_short(SR)
'SR'
>>> parent_to_repr_short(RR)
'RR'
>>> parent_to_repr_short(CC)
'CC'
>>> parent_to_repr_short(ZZ['x'])
'ZZ[x]'
>>> parent_to_repr_short(QQ['d, k'])
'QQ[d, k]'
>>> parent_to_repr_short(QQ['e'])
'QQ[e]'
>>> parent_to_repr_short(SR[['a, r']])
'SR[[a, r]]'
>>> parent_to_repr_short(Zmod(Integer(3)))
'Ring of integers modulo 3'
>>> parent_to_repr_short(Zmod(Integer(3))['g'])
'Univariate Polynomial Ring in g over Ring of integers modulo 3'
from sage.rings.asymptotic.misc import parent_to_repr_short
parent_to_repr_short(ZZ)
parent_to_repr_short(QQ)
parent_to_repr_short(SR)
parent_to_repr_short(RR)
parent_to_repr_short(CC)
parent_to_repr_short(ZZ['x'])
parent_to_repr_short(QQ['d, k'])
parent_to_repr_short(QQ['e'])
parent_to_repr_short(SR[['a, r']])
parent_to_repr_short(Zmod(3))
parent_to_repr_short(Zmod(3)['g'])
sage.rings.asymptotic.misc.repr_op(left, op, right=None, latex=False)[source]

Create a string left op right with taking care of parentheses in its operands.

INPUT:

  • left – an element

  • op – string

  • right – an element

  • latex – boolean (default: False); if set, then LaTeX-output is returned

OUTPUT: string

EXAMPLES:

sage: from sage.rings.asymptotic.misc import repr_op
sage: repr_op('a^b', '^', 'c')
'(a^b)^c'
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import repr_op
>>> repr_op('a^b', '^', 'c')
'(a^b)^c'
from sage.rings.asymptotic.misc import repr_op
repr_op('a^b', '^', 'c')
sage.rings.asymptotic.misc.repr_short_to_parent(s)[source]

Helper method for the growth group factory, which converts a short representation string to a parent.

INPUT:

  • s – string; short representation of a parent

OUTPUT: a parent

The possible short representations are shown in the examples below.

EXAMPLES:

sage: from sage.rings.asymptotic.misc import repr_short_to_parent
sage: repr_short_to_parent('ZZ')
Integer Ring
sage: repr_short_to_parent('QQ')
Rational Field
sage: repr_short_to_parent('SR')
Symbolic Ring
sage: repr_short_to_parent('NN')
Non negative integer semiring
sage: repr_short_to_parent('UU')
Group of Roots of Unity
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import repr_short_to_parent
>>> repr_short_to_parent('ZZ')
Integer Ring
>>> repr_short_to_parent('QQ')
Rational Field
>>> repr_short_to_parent('SR')
Symbolic Ring
>>> repr_short_to_parent('NN')
Non negative integer semiring
>>> repr_short_to_parent('UU')
Group of Roots of Unity
from sage.rings.asymptotic.misc import repr_short_to_parent
repr_short_to_parent('ZZ')
repr_short_to_parent('QQ')
repr_short_to_parent('SR')
repr_short_to_parent('NN')
repr_short_to_parent('UU')
sage.rings.asymptotic.misc.split_str_by_op(string, op, strip_parentheses=True)[source]

Split the given string into a tuple of substrings arising by splitting by op and taking care of parentheses.

INPUT:

  • string – string

  • op – string; this is used by str.split. Thus, if this is None, then any whitespace string is a separator and empty strings are removed from the result.

  • strip_parentheses – boolean (default: True)

OUTPUT: a tuple of strings

sage.rings.asymptotic.misc.strip_symbolic(expression)[source]

Return, if possible, the underlying (numeric) object of the symbolic expression.

If expression is not symbolic, then expression is returned.

INPUT:

  • expression – an object

OUTPUT: an object

EXAMPLES:

sage: from sage.rings.asymptotic.misc import strip_symbolic
sage: strip_symbolic(SR(2)); _.parent()
2
Integer Ring
sage: strip_symbolic(SR(2/3)); _.parent()
2/3
Rational Field
sage: strip_symbolic(SR('x')); _.parent()
x
Symbolic Ring
sage: strip_symbolic(pi); _.parent()
pi
Symbolic Ring
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import strip_symbolic
>>> strip_symbolic(SR(Integer(2))); _.parent()
2
Integer Ring
>>> strip_symbolic(SR(Integer(2)/Integer(3))); _.parent()
2/3
Rational Field
>>> strip_symbolic(SR('x')); _.parent()
x
Symbolic Ring
>>> strip_symbolic(pi); _.parent()
pi
Symbolic Ring
from sage.rings.asymptotic.misc import strip_symbolic
strip_symbolic(SR(2)); _.parent()
strip_symbolic(SR(2/3)); _.parent()
strip_symbolic(SR('x')); _.parent()
strip_symbolic(pi); _.parent()
sage.rings.asymptotic.misc.substitute_raise_exception(element, e)[source]

Raise an error describing what went wrong with the substitution.

INPUT:

  • element – an element

  • e – an exception which is included in the raised error message

OUTPUT: raise an exception of the same type as e

sage.rings.asymptotic.misc.transform_category(category, subcategory_mapping, axiom_mapping, initial_category=None)[source]

Transform category to a new category according to the given mappings.

INPUT:

  • category – a category

  • subcategory_mapping – list (or other iterable) of triples (from, to, mandatory), where

    • from and to are categories and

    • mandatory is a boolean.

  • axiom_mapping – list (or other iterable) of triples (from, to, mandatory), where

    • from and to are strings describing axioms and

    • mandatory is a boolean.

  • initial_category – (default: None) a category. When transforming the given category, this initial_category is used as a starting point of the result. This means the resulting category will be a subcategory of initial_category. If initial_category is None, then the category of objects is used.

OUTPUT: a category

Note

Consider a subcategory mapping (from, to, mandatory). If category is a subcategory of from, then the returned category will be a subcategory of to. Otherwise and if mandatory is set, then an error is raised.

Consider an axiom mapping (from, to, mandatory). If category is has axiom from, then the returned category will have axiom to. Otherwise and if mandatory is set, then an error is raised.

EXAMPLES:

sage: from sage.rings.asymptotic.misc import transform_category
sage: from sage.categories.additive_semigroups import AdditiveSemigroups
sage: from sage.categories.additive_monoids import AdditiveMonoids
sage: from sage.categories.additive_groups import AdditiveGroups
sage: S = [
....:     (Sets(), Sets(), True),
....:     (Posets(), Posets(), False),
....:     (AdditiveMagmas(), Magmas(), False)]
sage: A = [
....:     ('AdditiveAssociative', 'Associative', False),
....:     ('AdditiveUnital', 'Unital', False),
....:     ('AdditiveInverse', 'Inverse', False),
....:     ('AdditiveCommutative', 'Commutative', False)]
sage: transform_category(Objects(), S, A)
Traceback (most recent call last):
...
ValueError: Category of objects is not
a subcategory of Category of sets.
sage: transform_category(Sets(), S, A)
Category of sets
sage: transform_category(Posets(), S, A)
Category of posets
sage: transform_category(AdditiveSemigroups(), S, A)
Category of semigroups
sage: transform_category(AdditiveMonoids(), S, A)
Category of monoids
sage: transform_category(AdditiveGroups(), S, A)
Category of groups
sage: transform_category(AdditiveGroups().AdditiveCommutative(), S, A)
Category of commutative groups
>>> from sage.all import *
>>> from sage.rings.asymptotic.misc import transform_category
>>> from sage.categories.additive_semigroups import AdditiveSemigroups
>>> from sage.categories.additive_monoids import AdditiveMonoids
>>> from sage.categories.additive_groups import AdditiveGroups
>>> S = [
...     (Sets(), Sets(), True),
...     (Posets(), Posets(), False),
...     (AdditiveMagmas(), Magmas(), False)]
>>> A = [
...     ('AdditiveAssociative', 'Associative', False),
...     ('AdditiveUnital', 'Unital', False),
...     ('AdditiveInverse', 'Inverse', False),
...     ('AdditiveCommutative', 'Commutative', False)]
>>> transform_category(Objects(), S, A)
Traceback (most recent call last):
...
ValueError: Category of objects is not
a subcategory of Category of sets.
>>> transform_category(Sets(), S, A)
Category of sets
>>> transform_category(Posets(), S, A)
Category of posets
>>> transform_category(AdditiveSemigroups(), S, A)
Category of semigroups
>>> transform_category(AdditiveMonoids(), S, A)
Category of monoids
>>> transform_category(AdditiveGroups(), S, A)
Category of groups
>>> transform_category(AdditiveGroups().AdditiveCommutative(), S, A)
Category of commutative groups
from sage.rings.asymptotic.misc import transform_category
from sage.categories.additive_semigroups import AdditiveSemigroups
from sage.categories.additive_monoids import AdditiveMonoids
from sage.categories.additive_groups import AdditiveGroups
S = [
    (Sets(), Sets(), True),
    (Posets(), Posets(), False),
    (AdditiveMagmas(), Magmas(), False)]
A = [
    ('AdditiveAssociative', 'Associative', False),
    ('AdditiveUnital', 'Unital', False),
    ('AdditiveInverse', 'Inverse', False),
    ('AdditiveCommutative', 'Commutative', False)]
transform_category(Objects(), S, A)
transform_category(Sets(), S, A)
transform_category(Posets(), S, A)
transform_category(AdditiveSemigroups(), S, A)
transform_category(AdditiveMonoids(), S, A)
transform_category(AdditiveGroups(), S, A)
transform_category(AdditiveGroups().AdditiveCommutative(), S, A)
sage: transform_category(AdditiveGroups().AdditiveCommutative(), S, A,
....:     initial_category=Posets())
Join of Category of commutative groups
    and Category of posets
>>> from sage.all import *
>>> transform_category(AdditiveGroups().AdditiveCommutative(), S, A,
...     initial_category=Posets())
Join of Category of commutative groups
    and Category of posets
transform_category(AdditiveGroups().AdditiveCommutative(), S, A,
    initial_category=Posets())
>>> from sage.all import *
>>> transform_category(AdditiveGroups().AdditiveCommutative(), S, A,
...     initial_category=Posets())
Join of Category of commutative groups
    and Category of posets
transform_category(AdditiveGroups().AdditiveCommutative(), S, A,
    initial_category=Posets())
sage: transform_category(ZZ.category(), S, A)
Category of commutative groups
sage: transform_category(QQ.category(), S, A)
Category of commutative groups
sage: transform_category(SR.category(), S, A)
Category of commutative groups
sage: transform_category(Fields(), S, A)
Category of commutative groups
sage: transform_category(ZZ['t'].category(), S, A)
Category of commutative groups
>>> from sage.all import *
>>> transform_category(ZZ.category(), S, A)
Category of commutative groups
>>> transform_category(QQ.category(), S, A)
Category of commutative groups
>>> transform_category(SR.category(), S, A)
Category of commutative groups
>>> transform_category(Fields(), S, A)
Category of commutative groups
>>> transform_category(ZZ['t'].category(), S, A)
Category of commutative groups
transform_category(ZZ.category(), S, A)
transform_category(QQ.category(), S, A)
transform_category(SR.category(), S, A)
transform_category(Fields(), S, A)
transform_category(ZZ['t'].category(), S, A)
>>> from sage.all import *
>>> transform_category(ZZ.category(), S, A)
Category of commutative groups
>>> transform_category(QQ.category(), S, A)
Category of commutative groups
>>> transform_category(SR.category(), S, A)
Category of commutative groups
>>> transform_category(Fields(), S, A)
Category of commutative groups
>>> transform_category(ZZ['t'].category(), S, A)
Category of commutative groups
transform_category(ZZ.category(), S, A)
transform_category(QQ.category(), S, A)
transform_category(SR.category(), S, A)
transform_category(Fields(), S, A)
transform_category(ZZ['t'].category(), S, A)
sage: A[-1] = ('Commutative', 'AdditiveCommutative', True)
sage: transform_category(Groups(), S, A)
Traceback (most recent call last):
...
ValueError: Category of groups does not have
axiom Commutative.
>>> from sage.all import *
>>> A[-Integer(1)] = ('Commutative', 'AdditiveCommutative', True)
>>> transform_category(Groups(), S, A)
Traceback (most recent call last):
...
ValueError: Category of groups does not have
axiom Commutative.
A[-1] = ('Commutative', 'AdditiveCommutative', True)
transform_category(Groups(), S, A)
>>> from sage.all import *
>>> A[-Integer(1)] = ('Commutative', 'AdditiveCommutative', True)
>>> transform_category(Groups(), S, A)
Traceback (most recent call last):
...
ValueError: Category of groups does not have
axiom Commutative.
A[-1] = ('Commutative', 'AdditiveCommutative', True)
transform_category(Groups(), S, A)