# HG changeset patch
# User darij grinberg <darijgrinberg@gmail.com>
# Date 1375120438 25200
# Node ID aed403aadf7c282d83d42eb084e8dde6e4c2ec04
# Parent e3a9833b4d47d4fdc055b9fd24d647cb36565478
trac #14542: review patch
diff git a/sage/combinat/species/generating_series.py b/sage/combinat/species/generating_series.py
a

b

class CycleIndexSeries(LazyPowerSeries): 
597  597  yield res 
598  598  n += 1 
599  599  
600   def arithmetic_product(self, g): 
 600  def arithmetic_product(self, g, check_input = True): 
601  601  """ 
602   Returns the arithmetic product of ``self`` with ``g``. 
603   
 602  Return the arithmetic product of ``self`` with ``g``. 
 603  
604  604  For species `M` and `N` such that `M[\\varnothing] = N[\\varnothing] = \\varnothing`, 
605  605  their arithmetic product is the species `M \\boxdot N` of "`M`assemblies of cloned `N`structures". 
606  606  This operation is defined and several examples are given in [MM]_. 
607  607  
608  608  The cycle index series for `M \\boxdot N` can be computed in terms of the component series `Z_M` and `Z_N`, 
609  609  as implemented in this method. 
610   
 610  
 611  INPUT: 
 612  
 613   ``g``  a cycle index series having the same parent as ``self``. 
 614  
 615   ``check_input``  (default: ``True``) a Boolean which, when set 
 616  to ``False``, will cause input checks to be skipped. 
 617  
 618  OUTPUT: 
 619  
 620  The arithmetic product of ``self`` with ``g``. This is a cycle 
 621  index series defined in terms of ``self`` and ``g`` such that 
 622  if ``self`` and ``g`` are the cycle index series of two species 
 623  `M` and `N`, their arithmetic product is the cycle index series 
 624  of the species `M \\boxdot N`. 
 625  
611  626  EXAMPLES: 
612  627  
613  628  For `C` the species of (oriented) cycles and `L_{+}` the species of nonempty linear orders, `C \\boxdot L_{+}` corresponds 
… 
… 
class CycleIndexSeries(LazyPowerSeries): 
635  650  
636  651  REFERENCES: 
637  652  
638   .. [MM] M. Maia and M. Mendez. "On the arithmetic product of combinatorial species." Discrete Mathematics, vol. 308, issue 23, 2008, pp. 54075427. 
639   http://arxiv.org/abs/math/0503436. 
 653  .. [MM] M. Maia and M. Mendez. "On the arithmetic product of combinatorial species". 
 654  Discrete Mathematics, vol. 308, issue 23, 2008, pp. 54075427. 
 655  :arXiv:`math/0503436v2`. 
640  656  
641  657  """ 
642  658  from sage.combinat.partition import Partition, Partitions 
… 
… 
class CycleIndexSeries(LazyPowerSeries): 
646  662  
647  663  p = self.base_ring() 
648  664  
649   assert self.coefficient(0) == p.zero() 
650   assert g.coefficient(0) == p.zero() 
 665  if check_input: 
 666  assert self.coefficient(0) == p.zero() 
 667  assert g.coefficient(0) == p.zero() 
651  668  
652  669  # We first define an operation `\\boxtimes` on partitions as in Lemma 2.1 of [MM]_. 
653   def arith_prod_of_partitions (l1, l2): 
 670  def arith_prod_of_partitions(l1, l2): 
654  671  # Given two partitions `l_1` and `l_2`, we construct a new partition `l_1 \\boxtimes l_2` by 
655   # the following procedure: each pair of parts `a \\in l_1` and `b \\in l_2` contributes a part 
656   # `\\lcm (a, b)` to `l_1 \\boxtimes l_2` with multiplicity `\\gcm (l_1, l_2)``. 
 672  # the following procedure: each pair of parts `a \\in l_1` and `b \\in l_2` contributes 
 673  # `\\gcd (a, b)`` parts of size `\\lcm (a, b)` to `l_1 \\boxtimes l_2`. If `l_1` and `l_2` 
 674  # are partitions of integers `n` and `m`, respectively, then `l_1 \\boxtimes l_2` is a 
 675  # partition of `nm`. 
657  676  term_iterable = chain.from_iterable( repeat(lcm(pair), times=gcd(pair)) for pair in product(l1, l2) ) 
658  677  term_list = sorted(term_iterable, reverse=True) 
659  678  res = Partition(term_list) 
660  679  return res 
661  680  
662   # We then extend this to an operation on symmetric functions as per eq. 52 of [MM]_. 
663   def arith_prod_sf (x, y): 
 681  # We then extend this to an operation on symmetric functions as per eq. (52) of [MM]_. 
 682  # (Maia and Mendez, in [MM]_, are talking about polynomials instead of symmetric 
 683  # functions, but this boils down to the same: Their x_i corresponds to the ith power 
 684  # sum symmetric function.) 
 685  def arith_prod_sf(x, y): 
664  686  ap_sf_wrapper = lambda l1, l2: p(arith_prod_of_partitions(l1, l2)) 
665  687  return p._apply_multi_module_morphism(x, y, ap_sf_wrapper) 
666  688  
667  689  # Sage stores cycle index series by degree. 
668  690  # Thus, to compute the arithmetic product `Z_M \\boxdot Z_N` it is useful 
669  691  # to compute all terms of a given degree `n` at once. 
670   def arith_prod_coeff (n): 
 692  def arith_prod_coeff(n): 
671  693  if n == 0: 
672  694  res = p.zero() 
673  695  else: 
674   index_set = ((d, n/d) for d in divisors(n)) 
 696  index_set = ((d, n // d) for d in divisors(n)) 
675  697  res = sum(arith_prod_sf(self.coefficient(i), g.coefficient(j)) for i,j in index_set) 
676  698  
677   # Build a list which has res in the nth slot and 0's before and after 
 699  # Build a list which has res in the `n`th slot and 0's before and after 
678  700  # to feed to sum_generator 
679  701  res_in_seq = [p.zero()]*n + [res, p.zero()] 
680  702  