Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Trac #20053: Merge branch #19540 to resolve merge conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
cheuberg committed Feb 16, 2016
2 parents 7f8c745 + 23948e4 commit 7acc487
Show file tree
Hide file tree
Showing 5 changed files with 369 additions and 5 deletions.
10 changes: 10 additions & 0 deletions src/sage/rings/asymptotic/asymptotic_expansion_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ def Stirling(var, precision=None, skip_constant_factor=False):
Asymptotic Ring <(e^(n*log(n)))^QQ * (e^n)^QQ * n^QQ * log(n)^QQ>
over Symbolic Constants Subring
.. SEEALSO::
:meth:`log_Stirling`,
:meth:`~sage.rings.asymptotic.asymptotic_ring.AsymptoticExpansion.factorial`.
TESTS::
sage: expansion = asymptotic_expansions.Stirling('n', precision=5)
Expand Down Expand Up @@ -218,6 +223,11 @@ def log_Stirling(var, precision=None, skip_constant_summand=False):
n*log(n) - n + 1/2*log(n) + 1/2*log(2*pi) + 1/12*n^(-1)
- 1/360*n^(-3) + 1/1260*n^(-5) + O(n^(-7))
.. SEEALSO::
:meth:`Stirling`,
:meth:`~sage.rings.asymptotic.asymptotic_ring.AsymptoticExpansion.factorial`.
TESTS::
sage: expansion = asymptotic_expansions.log_Stirling('n', precision=7)
Expand Down
142 changes: 141 additions & 1 deletion src/sage/rings/asymptotic/asymptotic_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ class AsymptoticExpansion(CommutativeAlgebraElement):
sage: (x+2*x^2+3*x^3+4*x^4) * (O(x)+x^2)
4*x^6 + O(x^5)
In particular, :meth:`~sage.rings.big_oh.O` can be used to
In particular, :func:`~sage.rings.big_oh.O` can be used to
construct the asymptotic expansions. With the help of the
:meth:`summands`, we can also have a look at the inner structure
of an asymptotic expansion::
Expand Down Expand Up @@ -2852,6 +2852,146 @@ def mapping(term):
return P(S, simplify=False, convert=False)


def factorial(self):
r"""
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)))^(Symbolic Constants Subring) *
(e^n)^(Symbolic Constants Subring) *
n^(Symbolic Constants Subring) *
log(n)^(Symbolic Constants Subring)>
over Symbolic Constants Subring
:wikipedia:`Catalan numbers <Catalan_number>`
`\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.
...
.. SEEALSO::
:meth:`~sage.rings.asymptotic.asymptotic_expansion_generators.AsymptoticExpansionGenerators.Stirling`
TESTS::
sage: A.<m> = AsymptoticRing(growth_group='m^ZZ * log(m)^ZZ', coefficient_ring=QQ, default_prec=5)
sage: m.factorial()
sqrt(2)*sqrt(pi)*e^(m*log(m))*(e^m)^(-1)*m^(1/2)
+ 1/12*sqrt(2)*sqrt(pi)*e^(m*log(m))*(e^m)^(-1)*m^(-1/2)
+ 1/288*sqrt(2)*sqrt(pi)*e^(m*log(m))*(e^m)^(-1)*m^(-3/2)
+ O(e^(m*log(m))*(e^m)^(-1)*m^(-5/2))
::
sage: A(1/2).factorial()
1/2*sqrt(pi)
sage: _.parent()
Asymptotic Ring <m^ZZ * log(m)^ZZ> over Symbolic Ring
::
sage: B.<a, b> = AsymptoticRing('a^ZZ * b^ZZ', QQ, default_prec=3)
sage: b.factorial()
O(e^(b*log(b))*(e^b)^(-1)*b^(1/2))
sage: (a*b).factorial()
Traceback (most recent call last):
...
ValueError: Cannot build the factorial of a*b
since it is not univariate.
"""
vars = self.variable_names()

if len(vars) == 0:
if self.is_zero():
return self.parent().one()
assert len(self.summands) == 1
element = next(self.summands.elements())
return self.parent()._create_element_in_extension_(
element._factorial_(), element.parent())

if len(vars) == 1:
from asymptotic_expansion_generators import \
asymptotic_expansions
var = vars[0]
S = asymptotic_expansions.Stirling(
var, precision=self.parent().default_prec)
from sage.structure.element import get_coercion_model
cm = get_coercion_model()
P = cm.common_parent(self, S)
return S.subs({var: P.coerce(self)})

else:
raise ValueError(
'Cannot build the factorial of {} since it is not '
'univariate.'.format(self))


def variable_names(self):
r"""
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',)
"""
vars = sorted(sum(iter(s.variable_names()
for s in self.summands),
tuple()))
from itertools import groupby
return tuple(v for v, _ in groupby(vars))


def _singularity_analysis_(self, var, zeta, precision=None):
r"""
Return the asymptotic growth of the coefficients of some
Expand Down
64 changes: 64 additions & 0 deletions src/sage/rings/asymptotic/growth_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,24 @@ def _substitute_(self, rules):
'base class %s.' % (self.parent(),)))


def variable_names(self):
r"""
Return the names of the variables of this generic growth element.
OUTPUT:
A tuple of strings.
EXAMPLES::
sage: from sage.rings.asymptotic.growth_group import GenericGrowthGroup
sage: G = GenericGrowthGroup(QQ)
sage: G(raw_element=2).variable_names()
()
"""
return self.parent()._var_.variable_names()


def _singularity_analysis_(self, var, zeta, precision):
r"""
Perform singularity analysis on this growth element.
Expand Down Expand Up @@ -2857,6 +2875,29 @@ def _substitute_(self, rules):
substitute_raise_exception(self, e)


def variable_names(self):
r"""
Return the names of the variables of this monomial growth element.
OUTPUT:
A tuple of strings.
EXAMPLES::
sage: from sage.rings.asymptotic.growth_group import GrowthGroup
sage: G = GrowthGroup('m^QQ')
sage: G('m^2').variable_names()
('m',)
sage: G('m^0').variable_names()
()
"""
if self.is_one():
return tuple()
else:
return self.parent()._var_.variable_names()


def _singularity_analysis_(self, var, zeta, precision):
r"""
Perform singularity analysis on this monomial growth element.
Expand Down Expand Up @@ -3630,6 +3671,29 @@ def _substitute_(self, rules):
substitute_raise_exception(self, e)


def variable_names(self):
r"""
Return the names of the variables of this exponential growth element.
OUTPUT:
A tuple of strings.
EXAMPLES::
sage: from sage.rings.asymptotic.growth_group import GrowthGroup
sage: G = GrowthGroup('QQ^m')
sage: G('2^m').variable_names()
('m',)
sage: G('1^m').variable_names()
()
"""
if self.is_one():
return tuple()
else:
return self.parent()._var_.variable_names()


class ExponentialGrowthGroup(GenericGrowthGroup):
r"""
A growth group dealing with expressions involving a fixed
Expand Down
32 changes: 31 additions & 1 deletion src/sage/rings/asymptotic/growth_group_cartesian.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ def factors(self):
"""
return sum(iter(f.factors()
for f in self.cartesian_factors()
if f != f.parent().one()),
if not f.is_one()),
tuple())


Expand Down Expand Up @@ -1285,6 +1285,36 @@ def _singularity_analysis_(self, var, zeta, precision):
'since it has more than two factors'.format(self))


def variable_names(self):
r"""
Return the names of the variables of this growth element.
OUTPUT:
A tuple of strings.
EXAMPLES::
sage: from sage.rings.asymptotic.growth_group import GrowthGroup
sage: G = GrowthGroup('QQ^m * m^QQ * log(n)^ZZ')
sage: G('2^m * m^4 * log(n)').variable_names()
('m', 'n')
sage: G('2^m * m^4').variable_names()
('m',)
sage: G('log(n)').variable_names()
('n',)
sage: G('m^3').variable_names()
('m',)
sage: G('m^0').variable_names()
()
"""
vars = sum(iter(factor.variable_names()
for factor in self.factors()),
tuple())
from itertools import groupby
return tuple(v for v, _ in groupby(vars))


CartesianProduct = CartesianProductGrowthGroups


Expand Down
Loading

0 comments on commit 7acc487

Please sign in to comment.