# HG changeset patch
# User Frederic Chapoton <chapoton at math.univlyon1.fr>
# Date 1307044885 7200
# Node ID b1724e72c36076c0c22e20cc62b8eb42d5979b9a
# Parent 42904573cc300e7d25bd5cc5f5db75c45de82e14
#11411 changes in qanalogues
* restricts the qfactorial to nonnegative integers
* restricts the qbinomial to nonnegative top argument
* little speedup of qbinomial
* new function q_catalan
* * *
#11411: Review patch for qanalogue fix.
diff git a/sage/combinat/q_analogues.py b/sage/combinat/q_analogues.py
a

b

from dyck_word import DyckWords 
22  22  
23  23  def q_int(n, p=None): 
24  24  """ 
25   Returns the qanalogue of the integer n. 
26   
27   If p is unspecified, then it defaults to using the generator q for 
 25  Returns the ``q``analogue of the integer ``n``. 
 26  
 27  If ``p`` is unspecified, then it defaults to using the generator ``q`` for 
28  28  a univariate polynomial ring over the integers. 
29   
 29  
30  30  EXAMPLES:: 
31   
 31  
32  32  sage: import sage.combinat.q_analogues as q_analogues 
33  33  sage: q_analogues.q_int(3) 
34  34  q^2 + q + 1 
35  35  sage: p = ZZ['p'].0 
36  36  sage: q_analogues.q_int(3,p) 
37  37  p^2 + p + 1 
 38  
 39  The ``q``analogue of ``n`` is only defined for ``n`` a nonnegative 
 40  integer (trac #11411):: 
 41  
 42  sage: q_analogues.q_int(2) 
 43  Traceback (most recent call last): 
 44  ... 
 45  ValueError: Argument (2) must be a nonnegative integer. 
38  46  """ 
39   if p == None: 
40   p = ZZ['q'].gens()[0] 
41   #pass 
42   return sum([p**i for i in range(n)]) 
 47  if n in ZZ and n >= 0: 
 48  if p == None: 
 49  p = ZZ['q'].gens()[0] 
 50  return sum([p**i for i in range(n)]) 
 51  else: 
 52  raise ValueError, "Argument (%s) must be a nonnegative integer." %n 
43  53  
44  54  def q_factorial(n, p=None): 
45  55  """ 
46   Returns the qanalogue of the n!. 
47   
48   If p is unspecified, then it defaults to using the generator q for 
 56  Returns the ``q``analogue of the factorial ``n!``. 
 57  
 58  If ``p`` is unspecified, then it defaults to using the generator ``q`` for 
49  59  a univariate polynomial ring over the integers. 
50   
 60  
51  61  EXAMPLES:: 
52   
 62  
53  63  sage: import sage.combinat.q_analogues as q_analogues 
54  64  sage: q_analogues.q_factorial(3) 
55  65  q^3 + 2*q^2 + 2*q + 1 
56  66  sage: p = ZZ['p'].0 
57  67  sage: q_analogues.q_factorial(3, p) 
58  68  p^3 + 2*p^2 + 2*p + 1 
 69  
 70  The ``q``analogue of ``n!`` is only defined for ``n`` a nonnegative 
 71  integer (trac #11411):: 
 72  
 73  sage: q_analogues.q_factorial(2) 
 74  Traceback (most recent call last): 
 75  ... 
 76  ValueError: Argument (2) must be a nonnegative integer. 
59  77  """ 
60   return prod([q_int(i,p) for i in range(1, n+1)]) 
 78  if n in ZZ and n >= 0: 
 79  return prod([q_int(i, p) for i in range(1, n+1)]) 
 80  else: 
 81  raise ValueError, "Argument (%s) must be a nonnegative integer." %n 
61  82  
62  83  def q_binomial(n,k,p=None): 
63  84  """ 
64   Returns the qbinomial coefficient. 
65   
66   If p is unspecified, then it defaults to using the generator q for 
 85  Returns the ``q``binomial coefficient. 
 86  
 87  If ``p`` is unspecified, then it defaults to using the generator ``q`` for 
67  88  a univariate polynomial ring over the integers. 
68   
 89  
69  90  EXAMPLES:: 
70   
 91  
71  92  sage: import sage.combinat.q_analogues as q_analogues 
72  93  sage: q_analogues.q_binomial(4,2) 
73  94  q^4 + q^3 + 2*q^2 + q + 1 
74  95  sage: p = ZZ['p'].0 
75  96  sage: q_analogues.q_binomial(4,2,p) 
76  97  p^4 + p^3 + 2*p^2 + p + 1 
 98  
 99  The ``q``analogue of ``binomial(n,k)`` is currently only defined for 
 100  ``n`` a nonnegative integer, it is zero for negative k (trac #11411):: 
 101  
 102  sage: q_analogues.q_binomial(5, 1) 
 103  0 
77  104  """ 
 105  if not (n in ZZ and k in ZZ): 
 106  raise ValueError, "Argument (%s, %s) must be integers."%(n, k) 
 107  if n < 0: 
 108  raise NotImplementedError 
 109  if 0 <= k and k <= n: 
 110  k=min(k, nk) 
 111  return (prod(q_int(j, p) for j in range(nk+1, n+1)) / 
 112  prod(q_int(j, p) for j in range(1, k+1))) 
 113  else: 
 114  return 0 
78  115  
79   return q_factorial(n,p)/(q_factorial(k,p)*q_factorial(nk,p)) 
 116  def q_catalan_number(n,p=None): 
 117  """ 
 118  Returns the ``q``Catalan number of index ``n``. 
80  119  
 120  If ``p`` is unspecified, then it defaults to using the generator ``q`` for 
 121  a univariate polynomial ring over the integers. 
 122  
 123  There are several ``q``Catalan numbers. This procedure 
 124  returns the one which can be written using the ``q``binomial coefficients. 
 125  
 126  EXAMPLES:: 
 127  
 128  sage: import sage.combinat.q_analogues as q_analogues 
 129  sage: q_analogues.q_catalan_number(4) 
 130  q^12 + q^10 + q^9 + 2*q^8 + q^7 + 2*q^6 + q^5 + 2*q^4 + q^3 + q^2 + 1 
 131  sage: p = ZZ['p'].0 
 132  sage: q_analogues.q_catalan_number(4,p) 
 133  p^12 + p^10 + p^9 + 2*p^8 + p^7 + 2*p^6 + p^5 + 2*p^4 + p^3 + p^2 + 1 
 134  
 135  The ``q``Catalan number of index ``n`` is only defined for ``n`` a 
 136  nonnegative integer (trac #11411):: 
 137  
 138  sage: q_analogues.q_catalan_number(2) 
 139  Traceback (most recent call last): 
 140  ... 
 141  ValueError: Argument (2) must be a nonnegative integer. 
 142  """ 
 143  if n in ZZ and n >= 0: 
 144  return prod(q_int(j, p) for j in range(n+2, 2*n+1)) / prod(q_int(j, p) for j in range(2,n+1)) 
 145  else: 
 146  raise ValueError, "Argument (%s) must be a nonnegative integer." %n 
81  147  
82  148  def qt_catalan_number(n): 
83  149  """ 
84   Returns the q,tCatalan number. 
85   
 150  Returns the ``q,t``Catalan number of index ``n``. 
 151  
86  152  EXAMPLES:: 
87   
 153  
88  154  sage: import sage.combinat.q_analogues as q_analogues 
89  155  sage: q_analogues.qt_catalan_number(1) 
90  156  1 
… 
… 
def qt_catalan_number(n): 
94  160  q^3 + q^2*t + q*t^2 + t^3 + q*t 
95  161  sage: q_analogues.qt_catalan_number(4) 
96  162  q^6 + q^5*t + q^4*t^2 + q^3*t^3 + q^2*t^4 + q*t^5 + t^6 + q^4*t + q^3*t^2 + q^2*t^3 + q*t^4 + q^3*t + q^2*t^2 + q*t^3 
 163  
 164  The ``q,t``Catalan number of index ``n`` is only defined for ``n`` a 
 165  nonnegative integer (trac #11411):: 
 166  
 167  sage: q_analogues.qt_catalan_number(2) 
 168  Traceback (most recent call last): 
 169  ... 
 170  ValueError: Argument (2) must be a nonnegative integer. 
97  171  """ 
98   ZZqt = ZZ['q','t'] 
 172  if n in ZZ and n >= 0: 
 173  ZZqt = ZZ['q','t'] 
 174  d = {} 
 175  for dw in DyckWords(n): 
 176  tup = (dw.a_statistic(),dw.b_statistic()) 
 177  d[tup] = d.get(tup,0)+1 
 178  return ZZqt(d) 
 179  else: 
 180  raise ValueError, "Argument (%s) must be a nonnegative integer." %n 
99  181  
100   d = {} 
101   for dw in DyckWords(n): 
102   tup = (dw.a_statistic(),dw.b_statistic()) 
103   d[tup] = d.get(tup,0)+1 
104   return ZZqt(d) 