Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" 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 ============================== """
#***************************************************************************** # Copyright (C) 2015 Daniel Krenn <dev@danielkrenn.at> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
r""" Helper method for the growth group factory, which converts a short representation string to a parent.
INPUT:
- ``s`` -- a 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
TESTS::
sage: repr_short_to_parent('abcdef') Traceback (most recent call last): ... ValueError: Cannot create a parent out of 'abcdef'. > *previous* NameError: name 'abcdef' is not defined """ ValueError("Cannot create a parent out of '%s'." % (s,)), e)
r""" Helper method which generates a short(er) representation string out of a parent.
INPUT:
- ``P`` -- a parent.
OUTPUT:
A 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(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' """
multi_power_series_ring.is_MPowerSeriesRing(P)
else: else:
r""" Split the given string into a tuple of substrings arising by splitting by ``op`` and taking care of parentheses.
INPUT:
- ``string`` -- a string.
- ``op`` -- a string. This is used by :python:`str.split <library/stdtypes.html#str.split>`. Thus, if this is ``None``, then any whitespace string is a separator and empty strings are removed from the result.
- ``strip_parentheses`` -- (default: ``True``) a boolean.
OUTPUT:
A tuple of strings.
TESTS::
sage: from sage.rings.asymptotic.misc import split_str_by_op sage: split_str_by_op('x^ZZ', '*') ('x^ZZ',) sage: split_str_by_op('log(x)^ZZ * y^QQ', '*') ('log(x)^ZZ', 'y^QQ') sage: split_str_by_op('log(x)**ZZ * y**QQ', '*') ('log(x)**ZZ', 'y**QQ') sage: split_str_by_op('a^b * * c^d', '*') Traceback (most recent call last): ... ValueError: 'a^b * * c^d' is invalid since a '*' follows a '*'. sage: split_str_by_op('a^b * (c*d^e)', '*') ('a^b', 'c*d^e')
::
sage: split_str_by_op('(a^b)^c', '^') ('a^b', 'c') sage: split_str_by_op('a^(b^c)', '^') ('a', 'b^c')
::
sage: split_str_by_op('(a) + (b)', op='+', strip_parentheses=True) ('a', 'b') sage: split_str_by_op('(a) + (b)', op='+', strip_parentheses=False) ('(a)', '(b)') sage: split_str_by_op(' ( t ) ', op='+', strip_parentheses=False) ('( t )',)
::
sage: split_str_by_op(' ( t ) ', op=None) ('t',) sage: split_str_by_op(' ( t )s', op=None) ('(t)s',) sage: split_str_by_op(' ( t ) s', op=None) ('t', 's')
::
sage: split_str_by_op('(e^(n*log(n)))^SR.subring(no_variables=True)', '*') ('(e^(n*log(n)))^SR.subring(no_variables=True)',) """
raise ValueError("'%s' is invalid since it starts with a '%s'." % (string, op)) (string, op, op))
raise ValueError("Parentheses in '%s' are not balanced." % (string,))
return s
r""" Create a string ``left op right`` with taking care of parentheses in its operands.
INPUT:
- ``left`` -- an element.
- ``op`` -- a string.
- ``right`` -- an alement.
- ``latex`` -- (default: ``False``) a boolean. If set, then LaTeX-output is returned.
OUTPUT:
A string.
EXAMPLES::
sage: from sage.rings.asymptotic.misc import repr_op sage: repr_op('a^b', '^', 'c') '(a^b)^c'
TESTS::
sage: repr_op('a-b', '^', 'c') '(a-b)^c' sage: repr_op('a+b', '^', 'c') '(a+b)^c'
::
sage: print(repr_op(r'\frac{1}{2}', '^', 'c', latex=True)) \left(\frac{1}{2}\right)^c """
else: return s else: else:
r""" 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. """ '\n *and* '.join("%s: %s" % (ff.__class__.__name__, str(ff)) for ff in f))
r""" 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``.
TESTS::
sage: from sage.rings.asymptotic.misc import substitute_raise_exception sage: substitute_raise_exception(x, Exception('blub')) Traceback (most recent call last): ... Exception: Cannot substitute in x in Symbolic Ring. > *previous* Exception: blub """ type(e)('Cannot substitute in %s in %s.' % (element, element.parent())), e)
r""" Merge the two overlapping tuples/lists.
INPUT:
- ``A`` -- a list or tuple (type has to coincide with type of ``B``).
- ``B`` -- a 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 :func:`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 :func:`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.
TESTS::
sage: from sage.rings.asymptotic.misc import merge_overlapping sage: def f(L, s): ....: return list((ell, s) for ell in L) sage: key = lambda k: k[0] sage: merge_overlapping(f([0..3], 'a'), f([5..7], 'b'), key) Traceback (most recent call last): ... ValueError: Input does not have an overlap. sage: merge_overlapping(f([0..2], 'a'), f([4..7], 'b'), key) Traceback (most recent call last): ... ValueError: Input does not have an overlap. sage: merge_overlapping(f([4..7], 'a'), f([0..2], 'b'), key) Traceback (most recent call last): ... ValueError: Input does not have an overlap. sage: merge_overlapping(f([0..3], 'a'), f([3..4], 'b'), key) ([(0, 'a'), (1, 'a'), (2, 'a'), (3, 'a'), (4, 'b')], [(0, 'a'), (1, 'a'), (2, 'a'), (3, 'b'), (4, 'b')]) sage: merge_overlapping(f([3..4], 'a'), f([0..3], 'b'), key) ([(0, 'b'), (1, 'b'), (2, 'b'), (3, 'a'), (4, 'a')], [(0, 'b'), (1, 'b'), (2, 'b'), (3, 'b'), (4, 'a')]) sage: merge_overlapping(f([0..1], 'a'), f([0..4], 'b'), key) ([(0, 'a'), (1, 'a'), (2, 'b'), (3, 'b'), (4, 'b')], [(0, 'b'), (1, 'b'), (2, 'b'), (3, 'b'), (4, 'b')]) sage: merge_overlapping(f([0..3], 'a'), f([0..1], 'b'), key) ([(0, 'a'), (1, 'a'), (2, 'a'), (3, 'a')], [(0, 'b'), (1, 'b'), (2, 'a'), (3, 'a')]) sage: merge_overlapping(f([0..3], 'a'), f([1..3], 'b'), key) ([(0, 'a'), (1, 'a'), (2, 'a'), (3, 'a')], [(0, 'a'), (1, 'b'), (2, 'b'), (3, 'b')]) sage: merge_overlapping(f([1..3], 'a'), f([0..3], 'b'), key) ([(0, 'b'), (1, 'a'), (2, 'a'), (3, 'a')], [(0, 'b'), (1, 'b'), (2, 'b'), (3, 'b')]) sage: merge_overlapping(f([0..6], 'a'), f([3..4], 'b'), key) ([(0, 'a'), (1, 'a'), (2, 'a'), (3, 'a'), (4, 'a'), (5, 'a'), (6, 'a')], [(0, 'a'), (1, 'a'), (2, 'a'), (3, 'b'), (4, 'b'), (5, 'a'), (6, 'a')]) sage: merge_overlapping(f([0..3], 'a'), f([1..2], 'b'), key) ([(0, 'a'), (1, 'a'), (2, 'a'), (3, 'a')], [(0, 'a'), (1, 'b'), (2, 'b'), (3, 'a')]) sage: merge_overlapping(f([1..2], 'a'), f([0..3], 'b'), key) ([(0, 'b'), (1, 'a'), (2, 'a'), (3, 'b')], [(0, 'b'), (1, 'b'), (2, 'b'), (3, 'b')]) sage: merge_overlapping(f([1..3], 'a'), f([1..3], 'b'), key) ([(1, 'a'), (2, 'a'), (3, 'a')], [(1, 'b'), (2, 'b'), (3, 'b')]) """ Akeys = A Bkeys = B else:
if A[i:i+len(B)] == B)
""" Return in index i where to merge two overlapping tuples/lists ``A`` and ``B``.
Then ``A + B[i:]`` or ``A[:-i] + B`` are the merged tuples/lists.
Adapted from http://stackoverflow.com/a/30056066/1052778. """ if A[-i:] == B[:i])
else:
else:
r""" Return a representation of the log of the given element to the given base.
INPUT:
- ``element`` -- an object.
- ``base`` -- an object or ``None``.
OUTPUT:
A 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)' """
r""" A special :python:`NotImplementedError<library/exceptions.html#exceptions.NotImplementedError>` which is raised when the result is O(0) which means 0 for sufficiently large values of the variable. """ r""" INPUT:
- ``data`` -- (default: ``None``) an :class:`AsymptoticRing` or a string.
- ``var`` -- (default: ``None``) a string.
TESTS::
sage: A = AsymptoticRing('n^ZZ', ZZ) sage: from sage.rings.asymptotic.misc import NotImplementedOZero sage: raise NotImplementedOZero(A) Traceback (most recent call last): ... NotImplementedOZero: The error term in the result is O(0) which means 0 for sufficiently large n. sage: raise NotImplementedOZero('something') Traceback (most recent call last): ... NotImplementedOZero: something sage: raise NotImplementedOZero(var='m') Traceback (most recent call last): ... NotImplementedOZero: The error term in the result is O(0) which means 0 for sufficiently large m. """ 'which means 0 for sufficiently ' 'large {}.'.format(var)) else:
subcategory_mapping, axiom_mapping, initial_category=None): r""" Transform ``category`` to a new category according to the given mappings.
INPUT:
- ``category`` -- a category.
- ``subcategory_mapping`` -- a list (or other iterable) of triples ``(from, to, mandatory)``, where
- ``from`` and ``to`` are categories and - ``mandatory`` is a boolean.
- ``axiom_mapping`` -- a 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 :class:`category of objects <sage.categories.objects.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
::
sage: transform_category(AdditiveGroups().AdditiveCommutative(), S, A, ....: initial_category=Posets()) Join of Category of commutative groups and Category of 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
::
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. """ else:
(category, A))
(category, A))
|