Commits (1)
 ... ... @@ -15,11 +15,10 @@ Characteristic Species # # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from species import GenericCombinatorialSpecies, SpeciesTermStream from generating_series import factorial_stream from structure import GenericSpeciesStructure from set_species import SetSpecies from sage.misc.cachefunc import cached_function from sage.structure.unique_representation import UniqueRepresentation class CharacteristicSpeciesStructure(GenericSpeciesStructure): ... ... @@ -157,18 +156,6 @@ class CharacteristicSpecies(GenericCombinatorialSpecies, UniqueRepresentation): _isotypes = _structures def _gs_term(self, base_ring): """ EXAMPLES:: sage: F = species.CharacteristicSpecies(2) sage: F.generating_series().coefficients(5) [0, 0, 1/2, 0, 0] sage: F.generating_series().count(2) 1 """ return base_ring(self._weight)/base_ring(factorial_stream[self._n]) def _order(self): """ Returns the order of the generating series. ... ... @@ -181,36 +168,52 @@ class CharacteristicSpecies(GenericCombinatorialSpecies, UniqueRepresentation): """ return self._n def _itgs_term(self, base_ring): """ EXAMPLES:: sage: F = species.CharacteristicSpecies(2) sage: F.isotype_generating_series().coefficients(5) [0, 0, 1, 0, 0] Here we test out weighting each structure by q. :: sage: R. = ZZ[] sage: Fq = species.CharacteristicSpecies(2, weight=q) sage: Fq.isotype_generating_series().coefficients(5) [0, 0, q, 0, 0] """ return base_ring(self._weight) def _cis_term(self, base_ring): """ EXAMPLES:: sage: F = species.CharacteristicSpecies(2) sage: g = F.cycle_index_series() sage: g.coefficients(5) [0, 0, 1/2*p[1, 1] + 1/2*p[2], 0, 0] """ cis = SetSpecies(weight=self._weight).cycle_index_series(base_ring) return cis.coefficient(self._n) class GeneratingSeriesStream(SpeciesTermStream): def value(self, base_ring, weight): """ EXAMPLES:: sage: F = species.CharacteristicSpecies(2) sage: F.generating_series().coefficients(5) [0, 0, 1/2, 0, 0] sage: F.generating_series().count(2) 1 """ return base_ring(weight)/factorial_stream[self._n] class IsotypeGeneratingSeriesStream(SpeciesTermStream): def value(self, base_ring, weight): """ EXAMPLES:: sage: F = species.CharacteristicSpecies(2) sage: F.isotype_generating_series().coefficients(5) [0, 0, 1, 0, 0] Here we test out weighting each structure by q. :: sage: R. = ZZ[] sage: Fq = species.CharacteristicSpecies(2, weight=q) sage: Fq.isotype_generating_series().coefficients(5) [0, 0, q, 0, 0] """ return base_ring(weight) class CycleIndexSeriesStream(SpeciesTermStream): def value(self, base_ring, weight): """ EXAMPLES:: sage: F = species.CharacteristicSpecies(2) sage: g = F.cycle_index_series() sage: g.coefficients(5) [0, 0, 1/2*p[1, 1] + 1/2*p[2], 0, 0] """ cis = SetSpecies(weight=weight).cycle_index_series(base_ring.base_ring()) return cis.coefficient(self._n) def _equation(self, var_mapping): """ ... ...
 """ Combinatorial Logarithm This file provides the cycle index series for the virtual species \Omega, the 'combinatorial logarithm', defined to be the compositional inverse of the species E^{+} of nonempty sets: .. MATH:: \Omega \circ E^{+} = E^{+} \circ \Omega = X. .. warning:: This module is now deprecated. Please use :meth:sage.combinat.species.generating_series.CycleIndexSeriesRing.exponential instead of :func:CombinatorialLogarithmSeries. AUTHORS: - Andrew Gainer-Dewar (2013): initial version """ #***************************************************************************** # Copyright (C) 2013 Andrew Gainer-Dewar # # Distributed under the terms of the GNU General Public License (GPL) # 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/ #***************************************************************************** from sage.combinat.species.generating_series import CycleIndexSeriesRing, LogarithmCycleIndexSeries from sage.rings.all import QQ from sage.misc.cachefunc import cached_function from sage.misc.superseded import deprecation @cached_function def CombinatorialLogarithmSeries(R=QQ): r""" Return the cycle index series of the virtual species \Omega, the compositional inverse of the species E^{+} of nonempty sets. The notion of virtual species is treated thoroughly in [BLL]_. The specific algorithm used here to compute the cycle index of \Omega is found in [Labelle]_. EXAMPLES: The virtual species \Omega is 'properly virtual', in the sense that its cycle index has negative coefficients:: sage: from sage.combinat.species.combinatorial_logarithm import CombinatorialLogarithmSeries sage: CombinatorialLogarithmSeries().coefficients(4) doctest:...: DeprecationWarning: CombinatorialLogarithmSeries is deprecated, use CycleIndexSeriesRing(R).logarithm_series() or CycleIndexSeries().logarithm() instead See http://trac.sagemath.org/14846 for details. [0, p[1], -1/2*p[1, 1] - 1/2*p[2], 1/3*p[1, 1, 1] - 1/3*p[3]] Its defining property is that \Omega \circ E^{+} = E^{+} \circ \Omega = X (that is, that composition with E^{+} in both directions yields the multiplicative identity X):: sage: Eplus = sage.combinat.species.set_species.SetSpecies(min=1).cycle_index_series() sage: CombinatorialLogarithmSeries().compose(Eplus).coefficients(4) [0, p[1], 0, 0] """ deprecation(14846, "CombinatorialLogarithmSeries is deprecated, use CycleIndexSeriesRing(R).logarithm_series() or CycleIndexSeries().logarithm() instead") return LogarithmCycleIndexSeries(R)
 ... ... @@ -15,12 +15,11 @@ Cycle Species # # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from species import GenericCombinatorialSpecies, SpeciesSeriesStream from series import SeriesStreamFromList from structure import GenericSpeciesStructure from generating_series import _integers_from from sage.structure.unique_representation import UniqueRepresentation from sage.rings.all import ZZ, divisors, euler_phi from sage.misc.cachefunc import cached_function from sage.combinat.species.misc import accept_size class CycleSpeciesStructure(GenericSpeciesStructure): ... ... @@ -58,7 +57,7 @@ class CycleSpeciesStructure(GenericSpeciesStructure): sage: a.permutation_group_element() (1,2,3) """ from sage.groups.all import PermutationGroupElement, SymmetricGroup from sage.groups.all import PermutationGroupElement return PermutationGroupElement(tuple(self._list)) def transport(self, perm): ... ... @@ -180,30 +179,6 @@ class CycleSpecies(GenericCombinatorialSpecies, UniqueRepresentation): if len(labels) != 0: yield structure_class(self, labels, range(1, len(labels)+1)) def _gs_iterator(self, base_ring): r""" The generating series for cyclic permutations is -\log(1-x) = \sum_{n=1}^\infty x^n/n. EXAMPLES:: sage: P = species.CycleSpecies() sage: g = P.generating_series() sage: g.coefficients(10) [0, 1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9] TESTS:: sage: P = species.CycleSpecies() sage: g = P.generating_series(RR) sage: g.coefficients(3) [0.000000000000000, 1.00000000000000, 0.500000000000000] """ one = base_ring(1) yield base_ring(0) for n in _integers_from(ZZ(1)): yield self._weight*one/n def _order(self): """ Returns the order of the generating series. ... ... @@ -216,70 +191,92 @@ class CycleSpecies(GenericCombinatorialSpecies, UniqueRepresentation): """ return 1 def _itgs_list(self, base_ring): """ The isomorphism type generating series for cyclic permutations is given by x/(1-x). class GeneratingSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" The generating series for cyclic permutations is -\log(1-x) = \sum_{n=1}^\infty x^n/n. EXAMPLES:: EXAMPLES:: sage: P = species.CycleSpecies() sage: g = P.isotype_generating_series() sage: g.coefficients(5) [0, 1, 1, 1, 1] sage: P = species.CycleSpecies() sage: g = P.generating_series() sage: g.coefficients(10) [0, 1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9] TESTS:: TESTS:: sage: P = species.CycleSpecies() sage: g = P.isotype_generating_series(RR) sage: g.coefficients(3) [0.000000000000000, 1.00000000000000, 1.00000000000000] """ return [base_ring(0), self._weight*base_ring(1)] sage: P = species.CycleSpecies() sage: g = P.generating_series(RR) sage: g.coefficients(3) [0.000000000000000, 1.00000000000000, 0.500000000000000] """ if n == 0: return self._zero else: return self._base_ring(self._weight) / n def _cis_iterator(self, base_ring): r""" The cycle index series of the species of cyclic permutations is given by class IsotypeGeneratingSeriesStream(SeriesStreamFromList, SpeciesSeriesStream): def list(self): """ The isomorphism type generating series for cyclic permutations is given by x/(1-x). .. math:: EXAMPLES:: -\sum_{k=1}^\infty \phi(k)/k * log(1 - x_k) sage: P = species.CycleSpecies() sage: g = P.isotype_generating_series() sage: g.coefficients(5) [0, 1, 1, 1, 1] TESTS:: which is equal to sage: P = species.CycleSpecies() sage: g = P.isotype_generating_series(RR) sage: g.coefficients(3) [0.000000000000000, 1.00000000000000, 1.00000000000000] """ return [self._zero, self._weight*self._base_ring(1)] .. math:: class CycleIndexSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" The cycle index series of the species of cyclic permutations is given by \sum_{n=1}^\infty \frac{1}{n} * \sum_{k|n} \phi(k) * x_k^{n/k} .. math:: . -\sum_{k=1}^\infty \phi(k)/k * log(1 - x_k) EXAMPLES:: sage: P = species.CycleSpecies() sage: cis = P.cycle_index_series() sage: cis.coefficients(7) [0, p[1], 1/2*p[1, 1] + 1/2*p[2], 1/3*p[1, 1, 1] + 2/3*p[3], 1/4*p[1, 1, 1, 1] + 1/4*p[2, 2] + 1/2*p[4], 1/5*p[1, 1, 1, 1, 1] + 4/5*p[5], 1/6*p[1, 1, 1, 1, 1, 1] + 1/6*p[2, 2, 2] + 1/3*p[3, 3] + 1/3*p[6]] """ from sage.combinat.sf.sf import SymmetricFunctions p = SymmetricFunctions(base_ring).power() which is equal to .. math:: \sum_{n=1}^\infty \frac{1}{n} * \sum_{k|n} \phi(k) * x_k^{n/k} . EXAMPLES:: zero = base_ring(0) sage: P = species.CycleSpecies() sage: cis = P.cycle_index_series() sage: cis.coefficients(7) [0, p[1], 1/2*p[1, 1] + 1/2*p[2], 1/3*p[1, 1, 1] + 2/3*p[3], 1/4*p[1, 1, 1, 1] + 1/4*p[2, 2] + 1/2*p[4], 1/5*p[1, 1, 1, 1, 1] + 4/5*p[5], 1/6*p[1, 1, 1, 1, 1, 1] + 1/6*p[2, 2, 2] + 1/3*p[3, 3] + 1/3*p[6]] """ if n == 0: return self._zero yield zero for n in _integers_from(1): res = zero res = self._zero for k in divisors(n): res += euler_phi(k)*p([k])**(n//k) res /= n yield self._weight*res res += euler_phi(k)*self._base_ring([k])**(n//k) return self._weight * res / n #Backward compatibility CycleSpecies_class = CycleSpecies
 ... ... @@ -16,7 +16,6 @@ Empty Species # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from sage.misc.cachefunc import cached_function from series_order import inf from sage.structure.unique_representation import UniqueRepresentation ... ...
 ... ... @@ -17,13 +17,12 @@ Functorial composition species #***************************************************************************** from species import GenericCombinatorialSpecies from structure import GenericSpeciesStructure from sage.misc.cachefunc import cached_function from sage.structure.unique_representation import UniqueRepresentation class FunctorialCompositionStructure(GenericSpeciesStructure): pass class FunctorialCompositionSpecies(GenericCombinatorialSpecies): class FunctorialCompositionSpecies(GenericCombinatorialSpecies, UniqueRepresentation): def __init__(self, F, G, min=None, max=None, weight=None): """ Returns the functorial composition of two species. ... ...
This diff is collapsed.
 ... ... @@ -15,11 +15,10 @@ Linear-order Species # # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from species import GenericCombinatorialSpecies, SpeciesSeriesStream from series import SeriesStreamFromList from structure import GenericSpeciesStructure from generating_series import _integers_from from sage.structure.unique_representation import UniqueRepresentation from sage.misc.cachefunc import cached_function from sage.combinat.species.misc import accept_size class LinearOrderSpeciesStructure(GenericSpeciesStructure): ... ... @@ -123,48 +122,48 @@ class LinearOrderSpecies(GenericCombinatorialSpecies, UniqueRepresentation): """ yield structure_class(self, labels, range(1, len(labels)+1)) def _gs_list(self, base_ring): r""" The generating series for the species of linear orders is \frac{1}{1-x}. EXAMPLES:: sage: L = species.LinearOrderSpecies() sage: g = L.generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [base_ring(1)] def _itgs_list(self, base_ring): r""" The isomorphism type generating series is given by \frac{1}{1-x}. EXAMPLES:: sage: L = species.LinearOrderSpecies() sage: g = L.isotype_generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [base_ring(1)] def _cis_iterator(self, base_ring): """ EXAMPLES:: sage: L = species.LinearOrderSpecies() sage: g = L.cycle_index_series() sage: g.coefficients(5) [p[], p[1], p[1, 1], p[1, 1, 1], p[1, 1, 1, 1]] """ from sage.combinat.sf.sf import SymmetricFunctions p = SymmetricFunctions(base_ring).power() for n in _integers_from(0): yield p([1]*n) class GeneratingSeriesStream(SeriesStreamFromList, SpeciesSeriesStream): def list(self): r""" The generating series for the species of linear orders is \frac{1}{1-x}. EXAMPLES:: sage: L = species.LinearOrderSpecies() sage: g = L.generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [self._base_ring(1)] class IsotypeGeneratingSeriesStream(SeriesStreamFromList, SpeciesSeriesStream): def list(self): r""" The isomorphism type generating series is given by \frac{1}{1-x}. EXAMPLES:: sage: L = species.LinearOrderSpecies() sage: g = L.isotype_generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [self._base_ring(1)] class CycleIndexSeriesStream(SpeciesSeriesStream): def compute(self, n): """ EXAMPLES:: sage: L = species.LinearOrderSpecies() sage: g = L.cycle_index_series() sage: g.coefficients(5) [p[], p[1], p[1, 1], p[1, 1, 1], p[1, 1, 1, 1]] """ return self._base_ring([1]*n) #Backward compatibility LinearOrderSpecies_class = LinearOrderSpecies
 """ (New) Streams This code provides a new implementation of the streams found at :mod:sage.combinat.species.stream. """ #***************************************************************************** # Copyright (C) 2013 Mike Hansen , # # Distributed under the terms of the GNU General Public License (GPL) # # This code is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ #***************************************************************************** from sage.structure.sage_object import SageObject from sage.misc.misc import is_iterator from sage.misc.abstract_method import abstract_method def check_constant_decorator(func): """ A method decorator for __getitem__ which checks is the stream is (eventually) constant before computing the $n$-th coefficient. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream, check_constant_decorator sage: s = Stream() sage: def foo(self, n): ....: return self.compute(n) sage: import types sage: s.foo = types.MethodType(check_constant_decorator(foo), s) sage: s.set_constant(1, 3) sage: s.compute(5) Traceback (most recent call last): ... NotImplementedError: sage: s.foo(5) 3 """ from sage.misc.all import sage_wraps @sage_wraps(func) def wrapper(self, n): if self._constant is not False or self.is_constant(): if self._constant is False: self.set_constant(self.get_constant_position(), self.get_constant()) pos, value = self._constant if n >= pos: return value return func(self, n) return wrapper class Stream(SageObject): """ A base class for streams. This class is typically subclassed. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: class NNStream(Stream): ....: def compute(self, n): ....: return n sage: s = NNStream() sage: [s[i] for i in range(10)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] """ def __init__(self): """ TESTS:: sage: from sage.combinat.species.new_stream import Stream sage: class NNStream(Stream): ....: def compute(self, n): ....: pass ....: def __setitem__(self, n, value): ....: pass sage: import __main__; __main__.NNStream = NNStream # fakes NNStream being defined in a Python module sage: s = NNStream() sage: s.is_constant() False Pickling fails because equality is not implemented:: sage: TestSuite(s).run() Failure in _test_pickling: ... AssertionError: != ------------------------------------------------------------ The following tests failed: _test_pickling """ self._constant = False @abstract_method def compute(self, n): """ Compute the $n$-th coefficient of this stream. This should be overridden by subclasses. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s.compute(2) Traceback (most recent call last): ... NotImplementedError: """ @abstract_method def __setitem__(self, n, value): """ Sets the $n$-th coefficient of this stream to value. This should be overridden by subclasses. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s[0] = 2 Traceback (most recent call last): ... NotImplementedError: """ @check_constant_decorator def __getitem__(self, n): """ Return the $n$-th coefficient of this stream. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: class MyStream(Stream): ....: def compute(self, n): ....: return n sage: s = MyStream() sage: s[10] 10 """ return self.compute(n) def is_constant(self): """ Return True if this stream is eventually constant. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s.is_constant() False sage: s.set_constant(2, 4) sage: s.is_constant() True """ return self._constant is not False def set_constant(self, n, value): """ Set this stream to be eventually constant at coefficient n with value value. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s.set_constant(0, 2) sage: s.get_constant() 2 sage: s.get_constant_position() 0 sage: s[3] 2 """ self._constant = (n, value) def get_constant(self): """ Return the constant value if this stream is constant. Precondition: Assume that the stream is constant. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s.set_constant(0, 2) sage: s.get_constant() 2 """ assert self._constant is not False return self._constant[1] def get_constant_position(self): """ Return the position where this stream is constant. Precondition: Assume that this stream is constant. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s.set_constant(1, 2) sage: s.get_constant_position() 1 """ assert self._constant is not False return self._constant[0] def __iter__(self): """ Return an iterator for this stream. EXAMPLES:: sage: from sage.combinat.species.new_stream import Stream sage: s = Stream() sage: s.set_constant(0, 2) sage: it = iter(s) sage: [it.next() for i in range(5)] [2, 2, 2, 2, 2] """ i = 0 while True: try: yield self[i] except IndexError: break i += 1 raise StopIteration class ListCachedStream(Stream): """ A stream whose computed values are cached in a list. Additionally, when the $n$-th coefficient is requested, it guarantees that all the coefficients up to $n$ have been computed. EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromFunction, ListCachedStream sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: isinstance(s, ListCachedStream) True sage: s[5] 8 sage: s._cache [1, 1, 2, 3, 5, 8] """ def __init__(self, **kwds): """ TESTS:: sage: from sage.combinat.species.new_stream import StreamFromFunction, ListCachedStream sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: isinstance(s, ListCachedStream) True sage: s[5] 8 sage: s._cache [1, 1, 2, 3, 5, 8] Pickling fails because we can not pickle a lambda:: sage: TestSuite(s).run() Failure in _test_pickling: ... PicklingError: Can't pickle : attribute lookup __builtin__.function failed ------------------------------------------------------------ The following tests failed: _test_pickling """ self._cache = [] super(ListCachedStream, self).__init__(**kwds) def __setitem__(self, n, value): """ EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromFunction, ListCachedStream sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: isinstance(s, ListCachedStream) True sage: s[1] 1 sage: s[0] = 2 sage: s[0] 2 sage: s[10] 123 sage: s[15] = 100 sage: s[15] 100 """ pos = len(self._cache) while n >= pos: self[pos] pos += 1 self._cache[n] = value def length_of_cache(self): """ Return the number of coefficients that have been computed so far. EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromFunction, ListCachedStream sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: isinstance(s, ListCachedStream) True sage: s[5] 8 sage: s.length_of_cache() 6 """ return len(self._cache) __len__ = length_of_cache @check_constant_decorator def __getitem__(self, n): """ Return the $n$-th coefficient of this stream, checking the cache before trying to compute the value. This method guarantees that all of the coefficients up to $n$ have been computed first. EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromFunction, ListCachedStream sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: isinstance(s, ListCachedStream) True sage: s[5] 8 sage: s._cache [1, 1, 2, 3, 5, 8] We check to see that values are indeed returned from the cache if already computed:: sage: def foo(self, n): ....: raise NotImplementedError sage: s.compute = foo sage: s[2] 2 """ pos = len(self._cache) while pos <= n: value = self.compute(pos) self._cache.append(value) pos += 1 return self._cache[n] class StreamFromIterator(ListCachedStream): """ A ListCachedStream initialized by an iterator EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromIterator sage: s = StreamFromIterator(iterator=NN) sage: s[0] 0 sage: s[10] 10 """ def __init__(self, iterator=None, **kwds): """ TESTS:: sage: from sage.combinat.species.new_stream import StreamFromIterator sage: s = StreamFromIterator(iterator=NN) sage: s[0] 0 sage: s[10] 10 Pickling fails because we can not pickle a generator:: sage: TestSuite(s).run() Failure in _test_pickling: ... PicklingError: Can't pickle : attribute lookup __builtin__.generator failed ------------------------------------------------------------ The following tests failed: _test_pickling """ self._it = iterator if is_iterator(iterator) else iter(iterator) super(StreamFromIterator, self).__init__(**kwds) def compute(self, n): """ EXAMPLES: We test to make sure that iterator which finish iterating are constant for the rest of the values:: sage: from sage.combinat.species.new_stream import StreamFromIterator sage: s = StreamFromIterator(iter([1,2,3])) sage: s[0] 1 sage: s.is_constant() False sage: s[2], s[10] # indirect doctest (3, 3) sage: s.is_constant() True """ # ListCachedStream verifies that compute will be called with n in order assert n == len(self._cache), "compute called out of order" try: return self._it.next() except StopIteration: value = self._cache[-1] self.set_constant(len(self._cache) - 1, value) return value class StreamFromFunction(ListCachedStream): """ A ListCachedStream initialized by a function of $n$ which return the $n$-th coefficient. EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromFunction sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: s[0] 1 sage: s[1] 1 sage: s[2] 2 sage: s[10] 89 """ def __init__(self, func=None, **kwds): """ TESTS:: sage: from sage.combinat.species.new_stream import StreamFromFunction sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: s[0] 1 sage: s[1] 1 sage: s[2] 2 sage: s[10] 89 Pickling fails because we can not pickle a lambda:: sage: TestSuite(s).run() Failure in _test_pickling: ... PicklingError: Can't pickle : attribute lookup __builtin__.function failed ------------------------------------------------------------ The following tests failed: _test_pickling """ self._func = func super(StreamFromFunction, self).__init__(**kwds) def compute(self, n): """ .. note:: This should not be called directly. Instead, you should use :meth:__getitem__. EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromFunction sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = StreamFromFunction(h) sage: s.compute(0) 1 sage: s.compute(2) Traceback (most recent call last): ... AssertionError: compute called out of order """ # ListCachedStream verifies that compute will be called with n in order assert n == len(self._cache), "compute called out of order" return self._func(self._cache) class StreamFromList(ListCachedStream): """ A ListCachedStream initialized by a list. EXAMPLES:: sage: from sage.combinat.species.new_stream import StreamFromList sage: s = StreamFromList([1,2,3]) sage: s[0] 1 sage: s[5] 3 """ def __init__(self, list=None, **kwds): """ TESTS:: sage: from sage.combinat.species.new_stream import StreamFromList sage: s = StreamFromList([1,2,3]) sage: s[0] 1 sage: s[5] 3 :methcompute does not need to be implemented for this kind of stream. Pickling fails because equality is not implemented:: sage: TestSuite(s).run() Failure in _test_not_implemented_methods: ... AssertionError: Not implemented method: compute ------------------------------------------------------------ Failure in _test_pickling: ... AssertionError: != ------------------------------------------------------------ The following tests failed: _test_not_implemented_methods, _test_pickling """ super(StreamFromList, self).__init__(**kwds) if list is None: list = self.list() if len(list) < 0: raise ValueError("list cannot be empty") self._cache = list[:] self.set_constant(len(list) - 1, list[-1]) def OldStreamBehavior(x=None, const=None): """ A function which emulates the behavior of :func:sage.combinat.species.stream.Stream using :class:sage.combinat.species.new_stream.Stream. EXAMPLES:: sage: from sage.combinat.species.new_stream import OldStreamBehavior sage: s = OldStreamBehavior(const=3) sage: [s[i] for i in range(5)] [3, 3, 3, 3, 3] sage: s = OldStreamBehavior([1,2,3]) sage: [s[i] for i in range(5)] [1, 2, 3, 3, 3] sage: s = OldStreamBehavior(iter([1,2,3])) sage: [s[i] for i in range(5)] [1, 2, 3, 3, 3] sage: h = lambda l: 1 if len(l) < 2 else l[-1] + l[-2] sage: s = OldStreamBehavior(h) sage: [s[i] for i in range(10)] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] sage: s = OldStreamBehavior(4) sage: [s[i] for i in range(5)] [4, 0, 0, 0, 0] """ import types if const is not None: s = Stream() s.set_constant(0, const) return s elif isinstance(x, list): return StreamFromList(x) elif hasattr(x, '__iter__'): return StreamFromIterator(iter(x)) elif isinstance(x, (types.FunctionType, types.LambdaType)): return StreamFromFunction(x) else: return StreamFromIterator(iter([x,0]))
 ... ... @@ -16,14 +16,14 @@ Partition Species # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from generating_series import _integers_from, factorial_stream from species import GenericCombinatorialSpecies, SpeciesSeriesStream from generating_series import factorial_stream from subset_species import SubsetSpeciesStructure from set_species import SetSpecies from structure import GenericSpeciesStructure from sage.structure.unique_representation import UniqueRepresentation from sage.rings.all import ZZ from sage.misc.cachefunc import cached_function from sage.sets.all import PositiveIntegers from sage.combinat.species.misc import accept_size from functools import reduce ... ... @@ -123,7 +123,7 @@ class PartitionSpeciesStructure(GenericSpeciesStructure): return PartitionSpeciesStructure(self.parent(), labels, [block.change_labels(labels) for block in self._list]) class PartitionSpecies(GenericCombinatorialSpecies): class PartitionSpecies(GenericCombinatorialSpecies, UniqueRepresentation): @staticmethod @accept_size def __classcall__(cls, *args, **kwds): ... ... @@ -223,34 +223,34 @@ class PartitionSpecies(GenericCombinatorialSpecies): breaks = [sum(p[:i]) for i in range(len(p)+1)] return structure_class(self, labels, [range(breaks[i]+1, breaks[i+1]+1) for i in range(len(p))]) def _gs_iterator(self, base_ring): r""" EXAMPLES:: sage: P = species.PartitionSpecies() sage: g = P.generating_series() sage: g.coefficients(5) [1, 1, 1, 5/6, 5/8] """ from sage.combinat.combinat import bell_number for n in _integers_from(0): yield self._weight*base_ring(bell_number(n)/factorial_stream[n]) def _itgs_iterator(self, base_ring): r""" The isomorphism type generating series is given by \frac{1}{1-x}. EXAMPLES:: sage: P = species.PartitionSpecies() sage: g = P.isotype_generating_series() sage: g.coefficients(10) [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ from sage.combinat.partitions import number_of_partitions for n in _integers_from(0): yield self._weight*base_ring(number_of_partitions(n)) class GeneratingSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" EXAMPLES:: sage: P = species.PartitionSpecies() sage: g = P.generating_series() sage: g.coefficients(5) [1, 1, 1, 5/6, 5/8] """ from sage.combinat.combinat import bell_number return self._weight*self._base_ring(bell_number(n)/factorial_stream[n]) class IsotypeGeneratingSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" The isomorphism type generating series is given by \frac{1}{1-x}. EXAMPLES:: sage: P = species.PartitionSpecies() sage: g = P.isotype_generating_series() sage: g.coefficients(10) [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ from sage.combinat.partitions import number_of_partitions return self._weight * self._base_ring(number_of_partitions(n)) def _cis(self, series_ring, base_ring): r""" ... ... @@ -260,8 +260,6 @@ class PartitionSpecies(GenericCombinatorialSpecies): exp \sum_{n \ge 1} \frac{1}{n} \left( exp \left( \sum_{k \ge 1} \frac{x_{kn}}{k} \right) -1 \right). EXAMPLES:: sage: P = species.PartitionSpecies() ... ... @@ -273,6 +271,7 @@ class PartitionSpecies(GenericCombinatorialSpecies): 5/6*p[1, 1, 1] + 3/2*p[2, 1] + 2/3*p[3], 5/8*p[1, 1, 1, 1] + 7/4*p[2, 1, 1] + 7/8*p[2, 2] + p[3, 1] + 3/4*p[4]] """ PP = PositiveIntegers() ciset = SetSpecies().cycle_index_series(base_ring) res = ciset.composition(ciset - 1) if self.is_weighted(): ... ...
 ... ... @@ -15,13 +15,12 @@ Permutation species # # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from species import GenericCombinatorialSpecies, SpeciesSeriesStream from series import SeriesStreamFromList from structure import GenericSpeciesStructure from generating_series import _integers_from from sage.structure.unique_representation import UniqueRepresentation from sage.rings.all import ZZ from sage.misc.cachefunc import cached_function from sage.combinat.permutation import Permutation, Permutations from sage.combinat.partition import Partitions from sage.combinat.species.misc import accept_size class PermutationSpeciesStructure(GenericSpeciesStructure): ... ... @@ -55,7 +54,6 @@ class PermutationSpeciesStructure(GenericSpeciesStructure): sage: a.permutation_group_element() (2,3) """ from sage.groups.all import PermutationGroupElement return Permutation(self._list).to_permutation_group_element() def transport(self, perm): ... ... @@ -162,7 +160,6 @@ class PermutationSpecies(GenericCombinatorialSpecies, UniqueRepresentation): sage: P.isotypes([1,2,3]).list() [[2, 3, 1], [2, 1, 3], [1, 2, 3]] """ from sage.combinat.partition import Partitions if labels == []: yield structure_class(self, labels, []) return ... ... @@ -186,83 +183,59 @@ class PermutationSpecies(GenericCombinatorialSpecies, UniqueRepresentation): return structure_class(self, labels, perm) def _gs_list(self, base_ring): r""" The generating series for the species of linear orders is \frac{1}{1-x}. class GeneratingSeriesStream(SeriesStreamFromList, SpeciesSeriesStream): def list(self): r""" The generating series for the species of linear orders is \frac{1}{1-x}. EXAMPLES:: sage: P = species.PermutationSpecies() sage: g = P.generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [base_ring(1)] def _itgs_iterator(self, base_ring): r""" The isomorphism type generating series is given by \frac{1}{1-x}. EXAMPLES:: sage: P = species.PermutationSpecies() sage: g = P.isotype_generating_series() sage: g.coefficients(10) [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ from sage.combinat.partitions import number_of_partitions for n in _integers_from(0): yield base_ring(number_of_partitions(n)) EXAMPLES:: sage: P = species.PermutationSpecies() sage: g = P.generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [self._base_ring(1)] def _cis(self, series_ring, base_ring): r""" The cycle index series for the species of permutations is given by class IsotypeGeneratingSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" The isomorphism type generating series is given by \frac{1}{1-x}. .. math:: EXAMPLES:: \prod{n=1}^\infty \frac{1}{1-x_n}. sage: P = species.PermutationSpecies() sage: g = P.isotype_generating_series() sage: g.coefficients(10) [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ from sage.combinat.partitions import number_of_partitions return self._base_ring(number_of_partitions(n)) class CycleIndexSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" The cycle index series for the species of permutations is given by EXAMPLES:: sage: P = species.PermutationSpecies() sage: g = P.cycle_index_series() sage: g.coefficients(5) [p[], p[1], p[1, 1] + p[2], p[1, 1, 1] + p[2, 1] + p[3], p[1, 1, 1, 1] + p[2, 1, 1] + p[2, 2] + p[3, 1] + p[4]] """ CIS = series_ring return CIS.product_generator( CIS(self._cis_gen(base_ring, i)) for i in _integers_from(ZZ(1)) ) def _cis_gen(self, base_ring, n): """ EXAMPLES:: sage: P = species.PermutationSpecies() sage: g = P._cis_gen(QQ, 2) sage: [next(g) for i in range(10)] [p[], 0, p[2], 0, p[2, 2], 0, p[2, 2, 2], 0, p[2, 2, 2, 2], 0] """ from sage.combinat.sf.sf import SymmetricFunctions p = SymmetricFunctions(base_ring).power() .. math:: pn = p([n]) \prod{n=1}^\infty \frac{1}{1-x_n}. n = n - 1 yield p(1) EXAMPLES:: for k in _integers_from(1): for i in range(n): yield base_ring(0) yield pn**k sage: P = species.PermutationSpecies() sage: g = P.cycle_index_series() sage: g.coefficients(5) [p[], p[1], p[1, 1] + p[2], p[1, 1, 1] + p[2, 1] + p[3], p[1, 1, 1, 1] + p[2, 1, 1] + p[2, 2] + p[3, 1] + p[4]] """ return self._base_ring.sum_of_monomials(Partitions(n)) #Backward compatibility PermutationSpecies_class = PermutationSpecies
 ... ... @@ -18,7 +18,6 @@ Sum species from species import GenericCombinatorialSpecies from structure import GenericSpeciesStructure from subset_species import SubsetSpecies from sage.misc.cachefunc import cached_function from sage.structure.unique_representation import UniqueRepresentation class ProductSpeciesStructure(GenericSpeciesStructure): ... ... @@ -165,12 +164,11 @@ class ProductSpeciesStructure(GenericSpeciesStructure): sage: [a.transport(g) for g in a.automorphism_group()] [{2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}] """ from sage.groups.all import PermutationGroupElement, PermutationGroup, SymmetricGroup from sage.groups.all import PermutationGroupElement, PermutationGroup from sage.misc.misc import uniq from sage.combinat.species.misc import change_support left, right = self._list n = len(self._labels) #Get the supports for each of the sides l_support = self._subset._list ... ...
 ... ... @@ -209,7 +209,7 @@ class CombinatorialSpecies(GenericCombinatorialSpecies): sage: F = CombinatorialSpecies() sage: F.generating_series() Uninitialized lazy power series O(1) """ if base_ring not in self._generating_series: self._generating_series[base_ring] = series_ring() ... ... @@ -226,7 +226,7 @@ class CombinatorialSpecies(GenericCombinatorialSpecies): sage: F = CombinatorialSpecies() sage: F.isotype_generating_series() Uninitialized lazy power series O(1) """ if base_ring not in self._isotype_generating_series: self._isotype_generating_series[base_ring] = series_ring() ... ... @@ -243,7 +243,7 @@ class CombinatorialSpecies(GenericCombinatorialSpecies): sage: F = CombinatorialSpecies() sage: F.cycle_index_series() Uninitialized lazy power series O(1) """ if base_ring not in self._cycle_index_series: self._cycle_index_series[base_ring] = series_ring() ... ...
This diff is collapsed.
This diff is collapsed.
 ... ... @@ -15,12 +15,14 @@ Set Species # # http://www.gnu.org/licenses/ #***************************************************************************** from species import GenericCombinatorialSpecies from generating_series import factorial_stream, _integers_from from species import GenericCombinatorialSpecies, SpeciesSeriesStream from generating_series import factorial_stream from series import SeriesStreamFromList from sage.combinat.species.structure import GenericSpeciesStructure from sage.misc.cachefunc import cached_function from sage.combinat.species.misc import accept_size from sage.combinat.sf.sf import SymmetricFunctions from sage.structure.unique_representation import UniqueRepresentation from sage.sets.all import PositiveIntegers class SetSpeciesStructure(GenericSpeciesStructure): def __repr__(self): ... ... @@ -128,38 +130,51 @@ class SetSpecies(GenericCombinatorialSpecies, UniqueRepresentation): _isotypes = _structures def _gs_iterator(self, base_ring): r""" The generating series for the species of sets is given by e^x. EXAMPLES:: sage: S = species.SetSpecies() sage: g = S.generating_series() sage: g.coefficients(10) [1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040, 1/40320, 1/362880] sage: [g.count(i) for i in range(10)] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] def _order(self): """ for n in _integers_from(0): yield base_ring(self._weight/factorial_stream[n]) def _itgs_list(self, base_ring): r""" The isomorphism type generating series for the species of sets is \frac{1}{1-x}. Returns the order of the species. EXAMPLES:: sage: S = species.SetSpecies() sage: g = S.isotype_generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] sage: [g.count(i) for i in range(10)] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [base_ring(self._weight)] sage: S._order() 0 """ return 0 class GeneratingSeriesStream(SpeciesSeriesStream): def compute(self, n): r""" The generating series for the species of sets is given by e^x. EXAMPLES:: sage: S = species.SetSpecies() sage: g = S.generating_series() sage: g.coefficients(10) [1, 1, 1/2, 1/6, 1/24, 1/120, 1/720, 1/5040, 1/40320, 1/362880] sage: [g.count(i) for i in range(10)] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return self._base_ring(self._weight) / factorial_stream[n] class IsotypeGeneratingSeriesStream(SeriesStreamFromList, SpeciesSeriesStream): def list(self): r""" The isomorphism type generating series for the species of sets is \frac{1}{1-x}. EXAMPLES:: sage: S = species.SetSpecies() sage: g = S.isotype_generating_series() sage: g.coefficients(10) [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] sage: [g.count(i) for i in range(10)] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ return [self._base_ring(self._weight)] def _cis(self, series_ring, base_ring): r""" ... ... @@ -177,12 +192,9 @@ class SetSpecies(GenericCombinatorialSpecies, UniqueRepresentation): 1/6*p[1, 1, 1] + 1/2*p[2, 1] + 1/3*p[3], 1/24*p[1, 1, 1, 1] + 1/4*p[2, 1, 1] + 1/8*p[2, 2] + 1/3*p[3, 1] + 1/4*p[4]] """ from generating_series import ExponentialCycleIndexSeries res = ExponentialCycleIndexSeries(base_ring) res = series_ring.exponential() if self.is_weighted(): res *= self._weight return res ... ...
 ... ... @@ -50,7 +50,9 @@ three internal nodes. # # http://www.gnu.org/licenses/ #***************************************************************************** from generating_series import OrdinaryGeneratingSeriesRing, ExponentialGeneratingSeriesRing, CycleIndexSeriesRing from generating_series import (OrdinaryGeneratingSeriesRing, ExponentialGeneratingSeriesRing, CycleIndexSeriesRing) from series import SeriesStream, TermStream from sage.rings.all import QQ from sage.structure.sage_object import SageObject from sage.misc.cachefunc import cached_method ... ... @@ -58,6 +60,55 @@ from sage.combinat.species.misc import accept_size from sage.combinat.species.structure import StructuresWrapper, IsotypesWrapper from functools import reduce class SpeciesSeriesStream(SeriesStream): def __init__(self, weight=None, species=None, **kwds): """ A SeriesStream which knows about the weight of the species as well as its order. EXAMPLES:: sage: from sage.combinat.species.species import SpeciesSeriesStream sage: S = species.SetSpecies(min=2) sage: s = SpeciesSeriesStream(weight=S.weight(), species=S, base_ring=QQ) """ assert species is not None self._species = species