# HG changeset patch
# User Frederic Chapoton <chapoton at math.univlyon1.fr>
# Date 1368819378 7200
# Node ID e1bd7bedc6784d47392b50195e80b43486ffa634
# Parent 8708a5383e0f4e1130a037a7389118dd9c74e3fa
trac #9890 review and remove <>
diff git a/sage/combinat/perfect_matching.py b/sage/combinat/perfect_matching.py
a

b

EXAMPLES: 
15  15  
16  16  Create a perfect matching:: 
17  17  
18   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
 18  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
19  19  [('a', 'e'), ('b', 'c'), ('d', 'f')] 
20  20  
21  21  Count its crossings, if the ground set is totally ordered:: 
22  22  
23   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 23  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
24  24  [(1, 3), (2, 8), (4, 7), (5, 6)] 
25  25  sage: n.number_of_crossings() 
26  26  1 
… 
… 
REFERENCES: 
42  42  VII). 
43  43  
44  44  .. [CM] Benoit Collins, Sho Matsumoto, On some properties of 
45   orthogonal Weingarten functions, arXiv:0903.5143. 
 45  orthogonal Weingarten functions, :arxiv:`0903.5143`. 
46  46  """ 
47  47  
48   #***************************************************************************** 
 48  #***************************************************************************** 
49  49  # Copyright (C) 2010 Valentin Feray <feray@labri.fr> 
50  50  # 
51  51  # Distributed under the terms of the GNU General Public License (GPL) 
… 
… 
from sage.misc.misc_c import prod 
68  68  from sage.matrix.constructor import Matrix 
69  69  from sage.combinat.combinatorial_map import combinatorial_map 
70  70  
 71  
71  72  class PerfectMatching(ElementWrapper): 
72  73  r""" 
73  74  Class of perfect matching. 
… 
… 
class PerfectMatching(ElementWrapper): 
75  76  An instance of the class can be created from a list of pairs or from a 
76  77  fixed pointfree involution as follows:: 
77  78  
78   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
 79  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
79  80  [('a', 'e'), ('b', 'c'), ('d', 'f')] 
80   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]);n 
 81  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]);n 
81  82  [(1, 3), (2, 8), (4, 7), (5, 6)] 
82  83  sage: isinstance(m,PerfectMatching) 
83  84  True 
84  85  
85   The parent, which is the set of perfect matching of the ground set, is 
86   automaticly created:: 
 86  The parent, which is the set of perfect matchings of the ground set, is 
 87  automatically created:: 
87  88  
88  89  sage: n.parent() 
89  90  Set of perfect matchings of {1, 2, 3, 4, 5, 6, 7, 8} 
… 
… 
class PerfectMatching(ElementWrapper): 
96  97  
97  98  TESTS:: 
98  99  
99   sage: m=PerfectMatching([]); m 
 100  sage: m = PerfectMatching([]); m 
100  101  [] 
101  102  sage: m.parent() 
102  103  Set of perfect matchings of {} 
… 
… 
class PerfectMatching(ElementWrapper): 
109  110  __metaclass__ = ClasscallMetaclass 
110  111  
111  112  @staticmethod 
112   def __classcall_private__(cls,p): 
 113  def __classcall_private__(cls, p): 
113  114  r""" 
114  115  This function tries to recognize the input (it can be either a list or 
115  116  a tuple of pairs, or a fixpoint free involution given as a list or as 
… 
… 
class PerfectMatching(ElementWrapper): 
119  120  
120  121  EXAMPLES:: 
121  122  
122   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
 123  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
123  124  [('a', 'e'), ('b', 'c'), ('d', 'f')] 
124  125  sage: isinstance(m,PerfectMatching) 
125  126  True 
126   sage: n=PerfectMatching([3, 8, 1, 7, 6, 5, 4, 2]);n 
 127  sage: n = PerfectMatching([3, 8, 1, 7, 6, 5, 4, 2]);n 
127  128  [(1, 3), (2, 8), (4, 7), (5, 6)] 
128  129  sage: n.parent() 
129  130  Set of perfect matchings of {1, 2, 3, 4, 5, 6, 7, 8} 
… 
… 
class PerfectMatching(ElementWrapper): 
144  145  
145  146  TESTS:: 
146  147  
147   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]) 
 148  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]) 
148  149  sage: TestSuite(m).run() 
149   sage: m=PerfectMatching([]) 
 150  sage: m = PerfectMatching([]) 
150  151  sage: TestSuite(m).run() 
151  152  sage: PerfectMatching(6) 
152  153  Traceback (most recent call last): 
… 
… 
class PerfectMatching(ElementWrapper): 
170  171  # we have to extract from the argument p the set of objects of the 
171  172  # matching and the list of pairs. 
172  173  # First case: p is a list (resp tuple) of lists (resp tuple). 
173   if (isinstance(p,list) or isinstance(p,tuple)) and ( 
174   all([isinstance(x,list) or isinstance(x,tuple) for x in p])): 
175   objects=Set(flatten(p)) 
176   data=(map(tuple,p)) 
 174  if (isinstance(p, list) or isinstance(p, tuple)) and ( 
 175  all([isinstance(x, list) or isinstance(x, tuple) for x in p])): 
 176  objects = Set(flatten(p)) 
 177  data = (map(tuple, p)) 
177  178  #check if the data are correct 
178   if not all([len(t)==2 for t in data]): 
179   raise ValueError, ("%s is not a valid perfect matching:\n" 
180   "all elements of the list must be pairs"%p) 
 179  if not all([len(t) == 2 for t in data]): 
 180  raise ValueError("%s is not a valid perfect matching:\n" 
 181  "all elements of the list must be pairs" % p) 
181  182  if len(objects) < 2*len(data): 
182   raise ValueError, ("%s is not a valid perfect matching:\n" 
183   "there are some repetitions"%p) 
 183  raise ValueError("%s is not a valid perfect matching:\n" 
 184  "there are some repetitions" % p) 
184  185  # Second case: p is a permutation or a list of integers, we have to 
185  186  # check if it is a fixpointfree involution. 
186   elif ((isinstance(p,list) and 
187   all(map(lambda x: (isinstance(x,Integer) or isinstance(x,int)),p ))) 
188   or isinstance(p,Permutation_class)): 
189   p=Permutation(p) 
190   n=len(p) 
191   if not(p.cycle_type()==[2 for i in range(n//2)]): 
192   raise ValueError, ("The permutation p (= %s) is not a " 
193   "fixed point free involution"%p) 
194   objects=Set(range(1,n+1)) 
195   data=p.to_cycles() 
 187  elif ((isinstance(p, list) and 
 188  all(map(lambda x: (isinstance(x, Integer) or isinstance(x, int)), p))) 
 189  or isinstance(p, Permutation_class)): 
 190  p = Permutation(p) 
 191  n = len(p) 
 192  if not(p.cycle_type() == [2 for i in range(n//2)]): 
 193  raise ValueError("The permutation p (= %s) is not a " 
 194  "fixed point free involution" % p) 
 195  objects = Set(range(1, n+1)) 
 196  data = p.to_cycles() 
196  197  # Third case: p is already a perfect matching, we return p directly 
197   elif isinstance(p,PerfectMatching): 
 198  elif isinstance(p, PerfectMatching): 
198  199  return p 
199  200  else: 
200   raise ValueError, "cannot convert p (= %s) to a PerfectMatching"%p 
 201  raise ValueError("cannot convert p (= %s) to a PerfectMatching" % p) 
201  202  # Finally, we create the parent and the element using the element 
202  203  # class of the parent. Note: as this function is private, when we 
203  204  # create an object via parent.element_class(...), __init__ is directly 
… 
… 
class PerfectMatching(ElementWrapper): 
210  211  
211  212  EXAMPLES:: 
212  213  
213   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
 214  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]);m 
214  215  [('a', 'e'), ('b', 'c'), ('d', 'f')] 
215   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]);n 
 216  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]);n 
216  217  [(1, 3), (2, 8), (4, 7), (5, 6)] 
217  218  """ 
218   return '%s'%self.value 
 219  return '%s' % self.value 
219  220  
220  221  def _latex_(self): 
221  222  r""" 
… 
… 
class PerfectMatching(ElementWrapper): 
243  244  
244  245  EXAMPLES:: 
245  246  
246   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]) 
 247  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]) 
247  248  sage: m.__hash__() #random 
248  249  1053935254331348997 
249  250  sage: hash(m) #indirect doctest #random 
250  251  
251   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]) 
 252  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]) 
252  253  sage: hash(n) #indirect doctest #random 
253  254  8097274995140737937 
254  255  """ 
255  256  return hash(tuple(self.value)) 
256  257  
257   def __eq__(self,other): 
 258  def __eq__(self, other): 
258  259  r""" 
259  260  Compares two perfect matchings 
260  261  
261  262  EXAMPLES:: 
262  263  
263   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]) 
264   sage: n=PerfectMatching([('c','b'),('d','f'),('e','a')]) 
265   sage: n==m 
 264  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]) 
 265  sage: n = PerfectMatching([('c','b'),('d','f'),('e','a')]) 
 266  sage: n == m 
266  267  True 
267   sage: n==PerfectMatching([('a','b'),('d','f'),('e','c')]) 
 268  sage: n == PerfectMatching([('a','b'),('d','f'),('e','c')]) 
268  269  False 
269  270  
270  271  """ 
… 
… 
class PerfectMatching(ElementWrapper): 
273  274  return False 
274  275  except AttributeError: 
275  276  return False 
276   return Set(map(Set,self.value))==Set(map(Set,other.value)) 
 277  return Set(map(Set, self.value)) == Set(map(Set, other.value)) 
277  278  
278  279  def size(self): 
279  280  r""" 
… 
… 
class PerfectMatching(ElementWrapper): 
283  284  
284  285  EXAMPLES:: 
285  286  
286   sage: m=PerfectMatching([(3, 1), (2, 4), (2, 7)]); m.size() 
 287  sage: m = PerfectMatching([(3, 1), (2, 4), (2, 7)]); m.size() 
287  288  6 
288  289  """ 
289  290  return 2*len(self.value) 
… 
… 
class PerfectMatching(ElementWrapper): 
294  295  
295  296  EXAMPLES:: 
296  297  
297   sage: m=PerfectMatching([(3, 1), (2, 4), (2, 7)]); m.partner(4) 
 298  sage: m = PerfectMatching([(3, 1), (2, 4), (2, 7)]); m.partner(4) 
298  299  2 
299   sage: n=PerfectMatching([('c','b'),('d','f'),('e','a')]) 
 300  sage: n = PerfectMatching([('c','b'),('d','f'),('e','a')]) 
300  301  sage: n.partner('c') 
301  302  'b' 
302  303  """ 
303  304  for i in range(self.size()): 
304   if self.value[i][0]==x: 
 305  if self.value[i][0] == x: 
305  306  return self.value[i][1] 
306   if self.value[i][1]==x: 
 307  if self.value[i][1] == x: 
307  308  return self.value[i][0] 
308   raise ValueError,"%s in not an element of the %s"%(x,self) 
 309  raise ValueError("%s in not an element of the %s" % (x, self)) 
309  310  
310  311  def conjugate_by_permutation(self, p): 
311  312  r""" 
… 
… 
class PerfectMatching(ElementWrapper): 
314  315  
315  316  EXAMPLE:: 
316  317  
317   sage: m=PerfectMatching([(1,4),(2,6),(3,5)]) 
 318  sage: m = PerfectMatching([(1,4),(2,6),(3,5)]) 
318  319  sage: m.conjugate_by_permutation(Permutation([4,1,5,6,3,2])) 
319  320  [(4, 6), (1, 2), (5, 3)] 
320  321  
… 
… 
class PerfectMatching(ElementWrapper): 
323  324  sage: PerfectMatching([]).conjugate_by_permutation(Permutation([])) 
324  325  [] 
325  326  """ 
326   return self.parent()(map(lambda t:tuple(map(p,t)),self.value)) 
 327  return self.parent()(map(lambda t: tuple(map(p, t)), self.value)) 
327  328  
328   def loops_iterator(self,other=None): 
 329  def loops_iterator(self, other=None): 
329  330  r""" 
330  331  INPUT: 
331  332  
… 
… 
class PerfectMatching(ElementWrapper): 
342  343  
343  344  EXAMPLES:: 
344  345  
345   sage: o=PerfectMatching([(1, 7), (2, 4), (3, 8), (5, 6)]) 
346   sage: p=PerfectMatching([(1, 6), (2, 7), (3, 4), (5, 8)]) 
347   sage: it=o.loops_iterator(p) 
 346  sage: o = PerfectMatching([(1, 7), (2, 4), (3, 8), (5, 6)]) 
 347  sage: p = PerfectMatching([(1, 6), (2, 7), (3, 4), (5, 8)]) 
 348  sage: it = o.loops_iterator(p) 
348  349  sage: it.next() 
349  350  [1, 7, 2, 4, 3, 8, 5, 6] 
350  351  sage: it.next() 
… 
… 
class PerfectMatching(ElementWrapper): 
353  354  StopIteration 
354  355  """ 
355  356  if other is None: 
356   other=self.parent().an_element() 
357   elif self.parent() <> other.parent(): 
358   s="%s is not a matching of the ground set of %s"%(other,self) 
359   raise ValueError,s 
360   remain=flatten(self.value) 
361   while len(remain)>0: 
362   a=remain.pop(0) 
363   b=self.partner(a) 
 357  other = self.parent().an_element() 
 358  elif self.parent() != other.parent(): 
 359  s = "%s is not a matching of the ground set of %s" % (other, self) 
 360  raise ValueError(s) 
 361  remain = flatten(self.value) 
 362  while len(remain) > 0: 
 363  a = remain.pop(0) 
 364  b = self.partner(a) 
364  365  remain.remove(b) 
365   loop=[a,b] 
366   c=other.partner(b) 
367   while c<>a: 
368   b=self.partner(c) 
 366  loop = [a, b] 
 367  c = other.partner(b) 
 368  while c != a: 
 369  b = self.partner(c) 
369  370  remain.remove(c) 
370  371  loop.append(c) 
371  372  remain.remove(b) 
372  373  loop.append(b) 
373   c=other.partner(b) 
 374  c = other.partner(b) 
374  375  yield loop 
375  376  
376   def loops(self,other=None): 
 377  def loops(self, other=None): 
377  378  r""" 
378  379  INPUT: 
379  380  
… 
… 
class PerfectMatching(ElementWrapper): 
390  391  
391  392  EXAMPLES:: 
392  393  
393   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]) 
394   sage: n=PerfectMatching([('a','b'),('d','f'),('e','c')]) 
 394  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]) 
 395  sage: n = PerfectMatching([('a','b'),('d','f'),('e','c')]) 
395  396  sage: m.loops(n) 
396  397  [['a', 'e', 'c', 'b'], ['d', 'f']] 
397   sage: o=PerfectMatching([(1, 7), (2, 4), (3, 8), (5, 6)]) 
398   sage: p=PerfectMatching([(1, 6), (2, 7), (3, 4), (5, 8)]) 
 398  
 399  sage: o = PerfectMatching([(1, 7), (2, 4), (3, 8), (5, 6)]) 
 400  sage: p = PerfectMatching([(1, 6), (2, 7), (3, 4), (5, 8)]) 
399  401  sage: o.loops(p) 
400  402  [[1, 7, 2, 4, 3, 8, 5, 6]] 
401  403  """ 
… 
… 
class PerfectMatching(ElementWrapper): 
418  420  
419  421  EXAMPLES:: 
420  422  
421   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]) 
422   sage: n=PerfectMatching([('a','b'),('d','f'),('e','c')]) 
 423  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]) 
 424  sage: n = PerfectMatching([('a','b'),('d','f'),('e','c')]) 
423  425  sage: m.loop_type(n) 
424  426  [2, 1] 
425  427  
426  428  TESTS:: 
427  429  
428   sage: m=PerfectMatching([]); m.loop_type() 
 430  sage: m = PerfectMatching([]); m.loop_type() 
429  431  [] 
430  432  """ 
431   return Partition(reversed(sorted([len(l)//2 
432   for l in self.loops_iterator(other)]))) 
 433  return Partition(reversed( 
 434  sorted([len(l)//2 for l in self.loops_iterator(other)]))) 
433  435  
434   def number_of_loops(self,other=None): 
 436  def number_of_loops(self, other=None): 
435  437  r""" 
436  438  INPUT: 
437  439  
… 
… 
class PerfectMatching(ElementWrapper): 
447  449  
448  450  EXAMPLES:: 
449  451  
450   sage: m=PerfectMatching([('a','e'),('b','c'),('d','f')]) 
451   sage: n=PerfectMatching([('a','b'),('d','f'),('e','c')]) 
 452  sage: m = PerfectMatching([('a','e'),('b','c'),('d','f')]) 
 453  sage: n = PerfectMatching([('a','b'),('d','f'),('e','c')]) 
452  454  sage: m.number_of_loops(n) 
453  455  2 
454  456  """ 
… 
… 
class PerfectMatching(ElementWrapper): 
462  464  r""" 
463  465  INPUT: 
464  466  
465   A perfect matching on an *totally ordered* ground set. 
 467  A perfect matching on a *totally ordered* ground set. 
466  468  
467  469  OUTPUT: 
468  470  
… 
… 
class PerfectMatching(ElementWrapper): 
474  476  
475  477  EXAMPLES:: 
476  478  
477   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 479  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
478  480  [(1, 3), (2, 8), (4, 7), (5, 6)] 
479  481  sage: it = n.crossings_iterator(); 
480  482  sage: it.next() 
… 
… 
class PerfectMatching(ElementWrapper): 
484  486  ... 
485  487  StopIteration 
486  488  """ 
487   x=self.value[:] 
488   if len(x)==0: 
 489  x = self.value[:] 
 490  if len(x) == 0: 
489  491  return 
490   (i,j)=x.pop(0) 
491   for (a,b) in x: 
 492  (i, j) = x.pop(0) 
 493  for (a, b) in x: 
492  494  # if (i<a<j<b) or (i<b<j<a) or (j<a<i<b) or (j<b<i<a) or ( 
493  495  # a<i<b<j) or (a<j<b<i) or (b<i<a<j) or (b<j<a<i): 
494   labij = sorted([a,b,i,j]) 
 496  labij = sorted([a, b, i, j]) 
495  497  posij = sorted([labij.index(i), labij.index(j)]) 
496   if posij == [0,2] or posij == [1,3]: 
497   yield ((i,j),(a,b)) 
 498  if posij == [0, 2] or posij == [1, 3]: 
 499  yield ((i, j), (a, b)) 
498  500  for cr in PerfectMatchings(flatten(x))(x).crossings_iterator(): 
499  501  yield cr 
500  502  
… 
… 
class PerfectMatching(ElementWrapper): 
502  504  r""" 
503  505  INPUT: 
504  506  
505   A perfect matching on an *totally ordered* ground set. 
 507  A perfect matching on a *totally ordered* ground set. 
506  508  
507  509  OUTPUT: 
508  510  
… 
… 
class PerfectMatching(ElementWrapper): 
514  516  
515  517  EXAMPLES:: 
516  518  
517   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 519  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
518  520  [(1, 3), (2, 8), (4, 7), (5, 6)] 
519  521  sage: n.crossings() 
520  522  [((1, 3), (2, 8))] 
521  523  
522  524  TESTS:: 
523  525  
524   sage: m=PerfectMatching([]); m.crossings() 
 526  sage: m = PerfectMatching([]); m.crossings() 
525  527  [] 
526  528  """ 
527  529  return list(self.crossings_iterator()) 
… 
… 
class PerfectMatching(ElementWrapper): 
530  532  r""" 
531  533  INPUT: 
532  534  
533   A perfect matching on an *totally ordered* ground set. 
 535  A perfect matching on a *totally ordered* ground set. 
534  536  
535  537  OUTPUT: 
536  538  
… 
… 
class PerfectMatching(ElementWrapper): 
541  543  
542  544  EXAMPLES:: 
543  545  
544   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 546  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
545  547  [(1, 3), (2, 8), (4, 7), (5, 6)] 
546  548  sage: n.number_of_crossings() 
547  549  1 
… 
… 
class PerfectMatching(ElementWrapper): 
556  558  r""" 
557  559  INPUT: 
558  560  
559   A perfect matching on an *totally ordered* ground set. 
 561  A perfect matching on a *totally ordered* ground set. 
560  562  
561  563  OUTPUT: 
562  564  
… 
… 
class PerfectMatching(ElementWrapper): 
567  569  
568  570  EXAMPLES:: 
569  571  
570   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 572  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
571  573  [(1, 3), (2, 8), (4, 7), (5, 6)] 
572  574  sage: n.is_non_crossing() 
573  575  False 
… 
… 
class PerfectMatching(ElementWrapper): 
586  588  r""" 
587  589  INPUT: 
588  590  
589   A perfect matching on an *totally ordered* ground set. 
 591  A perfect matching on a *totally ordered* ground set. 
590  592  
591  593  OUTPUT: 
592  594  
… 
… 
class PerfectMatching(ElementWrapper): 
598  600  
599  601  EXAMPLES:: 
600  602  
601   sage: n=PerfectMatching([(1, 6), (2, 7), (3, 5), (4, 8)]) 
 603  sage: n = PerfectMatching([(1, 6), (2, 7), (3, 5), (4, 8)]) 
602  604  sage: it = n.nestings_iterator(); 
603  605  sage: it.next() 
604  606  ((1, 6), (3, 5)) 
… 
… 
class PerfectMatching(ElementWrapper): 
609  611  ... 
610  612  StopIteration 
611  613  """ 
612   x=self.value[:] 
613   if len(x)==0: 
 614  x = self.value[:] 
 615  if len(x) == 0: 
614  616  return 
615   (i,j)=x.pop(0) 
616   for (a,b) in x: 
 617  (i, j) = x.pop(0) 
 618  for (a, b) in x: 
617  619  # if (i<a<j<b) or (i<b<j<a) or (j<a<i<b) or (j<b<i<a) or ( 
618  620  # a<i<b<j) or (a<j<b<i) or (b<i<a<j) or (b<j<a<i): 
619   labij = sorted([a,b,i,j]) 
 621  labij = sorted([a, b, i, j]) 
620  622  posij = sorted([labij.index(i), labij.index(j)]) 
621   if posij == [0,3] or posij == [1,2]: 
622   yield ((i,j),(a,b)) 
 623  if posij == [0, 3] or posij == [1, 2]: 
 624  yield ((i, j), (a, b)) 
623  625  for nest in PerfectMatchings(flatten(x))(x).nestings_iterator(): 
624  626  yield nest 
625  627  
… 
… 
class PerfectMatching(ElementWrapper): 
627  629  r""" 
628  630  INPUT: 
629  631  
630   A perfect matching on an *totally ordered* ground set. 
 632  A perfect matching on a *totally ordered* ground set. 
631  633  
632  634  OUTPUT: 
633  635  
… 
… 
class PerfectMatching(ElementWrapper): 
639  641  
640  642  EXAMPLES:: 
641  643  
642   sage: m=PerfectMatching([(1, 6), (2, 7), (3, 5), (4, 8)]) 
 644  sage: m = PerfectMatching([(1, 6), (2, 7), (3, 5), (4, 8)]) 
643  645  sage: m.nestings() 
644  646  [((1, 6), (3, 5)), ((2, 7), (3, 5))] 
645   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 647  
 648  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
646  649  [(1, 3), (2, 8), (4, 7), (5, 6)] 
647  650  sage: n.nestings() 
648  651  [((2, 8), (4, 7)), ((2, 8), (5, 6)), ((4, 7), (5, 6))] 
649  652  
650  653  TESTS:: 
651  654  
652   sage: m=PerfectMatching([]); m.nestings() 
 655  sage: m = PerfectMatching([]); m.nestings() 
653  656  [] 
654  657  """ 
655  658  return list(self.nestings_iterator()) 
… 
… 
class PerfectMatching(ElementWrapper): 
658  661  r""" 
659  662  INPUT: 
660  663  
661   A perfect matching on an *totally ordered* ground set. 
 664  A perfect matching on a *totally ordered* ground set. 
662  665  
663  666  OUTPUT: 
664  667  
… 
… 
class PerfectMatching(ElementWrapper): 
669  672  
670  673  EXAMPLES:: 
671  674  
672   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 675  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
673  676  [(1, 3), (2, 8), (4, 7), (5, 6)] 
674  677  sage: n.number_of_nestings() 
675  678  3 
… 
… 
class PerfectMatching(ElementWrapper): 
684  687  r""" 
685  688  INPUT: 
686  689  
687   A perfect matching on an *totally ordered* ground set. 
 690  A perfect matching on a *totally ordered* ground set. 
688  691  
689  692  OUTPUT: 
690  693  
… 
… 
class PerfectMatching(ElementWrapper): 
695  698  
696  699  EXAMPLES:: 
697  700  
698   sage: n=PerfectMatching([3,8,1,7,6,5,4,2]); n 
 701  sage: n = PerfectMatching([3,8,1,7,6,5,4,2]); n 
699  702  [(1, 3), (2, 8), (4, 7), (5, 6)] 
700  703  sage: n.is_non_nesting() 
701  704  False 
… 
… 
class PerfectMatching(ElementWrapper): 
710  713  else: 
711  714  return False 
712  715  
713   def Weingarten_function(self,d,other=None): 
 716  def Weingarten_function(self, d, other=None): 
714  717  r""" 
715  718  Returns the Weingarten function of two pairings. 
716  719  
717   This function is the value of some integrals over the orhtogonal 
 720  This function is the value of some integrals over the orthogonal 
718  721  groups `O_N`. With the convention of [CM]_, the method returns 
719  722  `Wg^{O(d)}(other,self)`. 
720  723  
… 
… 
class PerfectMatching(ElementWrapper): 
722  725  
723  726  sage: var('N') 
724  727  N 
725   sage: m=PerfectMatching([(1,3),(2,4)]) 
726   sage: n=PerfectMatching([(1,2),(3,4)]) 
 728  sage: m = PerfectMatching([(1,3),(2,4)]) 
 729  sage: n = PerfectMatching([(1,2),(3,4)]) 
727  730  sage: factor(m.Weingarten_function(N,n)) 
728  731  1/((N  1)*(N + 2)*N) 
729  732  """ 
730  733  if other is None: 
731  734  other = self.parent().an_element() 
732   W=self.parent().Weingarten_matrix(d) 
 735  W = self.parent().Weingarten_matrix(d) 
733  736  return W[other.rank()][self.rank()] 
734  737  
735  738  def to_graph(self): 
… 
… 
class PerfectMatching(ElementWrapper): 
751  754  """ 
752  755  from sage.graphs.graph import Graph 
753  756  G = Graph() 
754   for a,b in self.value: 
755   G.add_edge((a,b)) 
 757  for a, b in self.value: 
 758  G.add_edge((a, b)) 
756  759  return G 
757  760  
758  761  @combinatorial_map(name='to permutation') 
… 
… 
class PerfectMatching(ElementWrapper): 
776  779  from sage.combinat.permutation import Permutation 
777  780  return Permutation(self.__dict__['value']) 
778  781  
779   class PerfectMatchings(UniqueRepresentation,Parent): 
 782  
 783  class PerfectMatchings(UniqueRepresentation, Parent): 
780  784  r""" 
781  785  Class of perfect matchings of a ground set. At the creation, the set 
782  786  can be given as any iterable object. If the argument is an integer `n`, it 
783  787  will be transformed into `[1 .. n]`:: 
784  788  
785   sage: M=PerfectMatchings(6);M 
 789  sage: M = PerfectMatchings(6);M 
786  790  Set of perfect matchings of {1, 2, 3, 4, 5, 6} 
787  791  sage: PerfectMatchings([1, 3, 1, 2]) 
788  792  Set of perfect matchings of {1, 2, 3, 1} 
… 
… 
class PerfectMatchings(UniqueRepresentat 
794  798  [[(1, 2), (3, 4)], [(1, 3), (2, 4)], [(1, 4), (2, 3)]] 
795  799  sage: PerfectMatchings(8).cardinality() 
796  800  105 
797   sage: M=PerfectMatchings(('a', 'e', 'b', 'f', 'c', 'd')) 
 801  sage: M = PerfectMatchings(('a', 'e', 'b', 'f', 'c', 'd')) 
798  802  sage: M.an_element() 
799  803  [('a', 'b'), ('f', 'e'), ('c', 'd')] 
800  804  sage: all([PerfectMatchings(i).an_element() in PerfectMatchings(i) 
… 
… 
class PerfectMatchings(UniqueRepresentat 
824  828  {'a', 'c', 'b', 'e'} 
825  829  """ 
826  830  # if the argument is a python int n, we replace it by the list [1 .. n] 
827   if isinstance(objects,int): 
828   objects=range(1,objects+1) 
 831  if isinstance(objects, int): 
 832  objects = range(1, objects+1) 
829  833  # same thing if the argument is a sage integer. 
830   elif isinstance(objects,Integer): 
831   objects=range(1,objects+1) 
 834  elif isinstance(objects, Integer): 
 835  objects = range(1, objects+1) 
832  836  # Finally, if it is iterable, we return the corresponding set. 
833  837  # Note that it is important to return a hashable object here (in 
834  838  # particular, NOT A LIST), see comment below. 
835   if not hasattr(objects,'__iter__'): 
836   raise ValueError, "do not know how to construct a set of matchings from %s (it must be iterable)" 
 839  if not hasattr(objects, '__iter__'): 
 840  raise ValueError("do not know how to construct a set of matchings from %s (it must be iterable)") 
837  841  return Set(objects) 
838  842  
839  843  @staticmethod 
… 
… 
class PerfectMatchings(UniqueRepresentat 
844  848  
845  849  EXAMPLES:: 
846  850  
847   sage: M=PerfectMatchings(6);M 
 851  sage: M = PerfectMatchings(6);M 
848  852  Set of perfect matchings of {1, 2, 3, 4, 5, 6} 
849  853  sage: PerfectMatchings([1, 3, 1, 2]) 
850  854  Set of perfect matchings of {1, 2, 3, 1} 
… 
… 
class PerfectMatchings(UniqueRepresentat 
853  857  it does not create a new object, but returns the already existing 
854  858  one:: 
855  859  
856   sage: N=PerfectMatchings((2, 3, 5, 4, 1, 6)) 
 860  sage: N = PerfectMatchings((2, 3, 5, 4, 1, 6)) 
857  861  sage: N is M 
858  862  True 
859  863  """ 
… 
… 
class PerfectMatchings(UniqueRepresentat 
862  866  # second argument, i.e. the output of _parse_input, must be hashable) 
863  867  #  look for a place in memory and call the __init__ function 
864  868  return super(PerfectMatchings, cls).__classcall__( 
865   cls, cls._parse_input(objects)) 
 869  cls, cls._parse_input(objects)) 
866  870  
867   def __init__(self,objects): 
 871  def __init__(self, objects): 
868  872  r""" 
869  873  See :meth:`__classcall__` 
870  874  
871  875  TEST:: 
872  876  
873   sage: M=PerfectMatchings(6) 
 877  sage: M = PerfectMatchings(6) 
874  878  sage: TestSuite(M).run() 
875  879  """ 
876   self._objects=objects 
877   Parent.__init__(self, category = FiniteEnumeratedSets()) 
 880  self._objects = objects 
 881  Parent.__init__(self, category=FiniteEnumeratedSets()) 
878  882  
879  883  def _repr_(self): 
880  884  r""" 
… 
… 
class PerfectMatchings(UniqueRepresentat 
885  889  sage: PerfectMatchings([1, 3, 1, 2]) 
886  890  Set of perfect matchings of {1, 2, 3, 1} 
887  891  """ 
888   return "Set of perfect matchings of %s"%self._objects 
 892  return "Set of perfect matchings of %s" % self._objects 
889  893  
890  894  def __iter__(self): 
891  895  r""" 
… 
… 
class PerfectMatchings(UniqueRepresentat 
901  905  elif len(self._objects) == 1: 
902  906  pass 
903  907  else: 
904   l=list(self._objects) 
905   a=l.pop(0) 
 908  l = list(self._objects) 
 909  a = l.pop(0) 
906  910  for i in range(len(l)): 
907   obj_rest=l[:] 
908   b=obj_rest.pop(i) 
 911  obj_rest = l[:] 
 912  b = obj_rest.pop(i) 
909  913  for p in PerfectMatchings(obj_rest): 
910  914  yield self([(a, b)]+p.value) 
911  915  
912   def __contains__(self,x): 
 916  def __contains__(self, x): 
913  917  r""" 
914  918  Tests if ``x`` is an element of ``self``. 
915  919  
916  920  EXAMPLES:: 
917  921  
918   sage: m=PerfectMatching([(1,2),(4,3)]) 
 922  sage: m = PerfectMatching([(1,2),(4,3)]) 
919  923  sage: m in PerfectMatchings(4) 
920  924  True 
921  925  sage: m in PerfectMatchings((0, 1, 2, 3)) 
… 
… 
class PerfectMatchings(UniqueRepresentat 
935  939  ... ('a', 'b', 'c', 'd')) 
936  940  False 
937  941  """ 
938   if not isinstance(x,PerfectMatching): 
 942  if not isinstance(x, PerfectMatching): 
939  943  try: 
940   x=PerfectMatching(x) 
 944  x = PerfectMatching(x) 
941  945  except ValueError: 
942  946  return False 
943   if x.parent() is not self: 
944   return False 
945   return True 
 947  return x.parent() is self 
946  948  
947  949  def cardinality(self): 
948  950  r""" 
949   Returns the cardinality of the set of perfect matching ``self``, 
950   that is `1*3*5*...*(2n1)`, where `2n` is the size of the ground set. 
 951  Returns the cardinality of the set of perfect matching ``self`` 
 952  
 953  This is `1*3*5*...*(2n1)`, where `2n` is the size of the ground set. 
951  954  
952  955  EXAMPLES:: 
953  956  
954  957  sage: PerfectMatchings(8).cardinality() 
955  958  105 
956  959  """ 
957   n=len(self._objects) 
958   if n%2==1: 
 960  n = len(self._objects) 
 961  if n % 2 == 1: 
959  962  return 0 
960  963  else: 
961   return Integer(prod(i for i in range(n) if i%2==1)) 
 964  return Integer(prod(i for i in range(n) if i % 2 == 1)) 
962  965  
963  966  def random_element(self): 
964  967  r""" 
… 
… 
class PerfectMatchings(UniqueRepresentat 
966  969  
967  970  EXAMPLES:: 
968  971  
969   sage: M=PerfectMatchings(('a', 'e', 'b', 'f', 'c', 'd')) 
 972  sage: M = PerfectMatchings(('a', 'e', 'b', 'f', 'c', 'd')) 
970  973  sage: M.an_element() 
971  974  [('a', 'b'), ('f', 'e'), ('c', 'd')] 
972  975  sage: all([PerfectMatchings(2*i).an_element() in PerfectMatchings(2*i) 
… 
… 
class PerfectMatchings(UniqueRepresentat 
978  981  sage: p = PerfectMatchings(13).random_element() 
979  982  Traceback (most recent call last): 
980  983  ... 
981   ValueError: There is no perfect matching on an odd number of elements 
 984  ValueError: there is no perfect matching on an odd number of elements 
982  985  
983  986  """ 
984   n=len(self._objects) 
 987  n = len(self._objects) 
985  988  
986   if n%2==1: 
987   raise ValueError("There is no perfect matching on an odd number of elements") 
 989  if n % 2 == 1: 
 990  raise ValueError("there is no perfect matching on an odd number of elements") 
988  991  
989  992  k = n//2 
990  993  
991  994  from sage.combinat.permutation import Permutations 
992  995  p = Permutations(n).random_element() 
993  996  
994   return self([(self._objects[p[2*i]1],self._objects[p[2*i+1]1]) for i in range(k)]) 
 997  return self([(self._objects[p[2*i]1], self._objects[p[2*i+1]1]) for i in range(k)]) 
995  998  
996  999  an_element = random_element 
997  1000  
998  1001  @cached_method 
999   def Weingarten_matrix(self,N): 
 1002  def Weingarten_matrix(self, N): 
1000  1003  r""" 
1001  1004  Returns the Weingarten matrix corresponding to the set of 
1002   PerfectMatchings ``self``. It is a useful theoretical tool to compute 
1003   polynomial integral over the orthogonal group `O_N` (see [CM]_). 
 1005  PerfectMatchings ``self``. 
 1006  
 1007  It is a useful theoretical tool to compute polynomial integral 
 1008  over the orthogonal group `O_N` (see [CM]_). 
1004  1009  
1005  1010  EXAMPLES:: 
1006  1011  
1007   sage: M=PerfectMatchings(4).Weingarten_matrix(var('N')) 
 1012  sage: M = PerfectMatchings(4).Weingarten_matrix(var('N')) 
1008  1013  sage: N*(N1)*(N+2)*M.apply_map(factor) 
1009  1014  [N + 1 1 1] 
1010  1015  [ 1 N + 1 1] 
1011  1016  [ 1 1 N + 1] 
1012  1017  """ 
1013   G=Matrix([ [N**(p1.number_of_loops(p2)) for p1 in self] 
1014   for p2 in self]) 
 1018  G = Matrix([[N**(p1.number_of_loops(p2)) for p1 in self] 
 1019  for p2 in self]) 
1015  1020  return G**(1) 
1016  1021  
1017   Element=PerfectMatching 
 1022  Element = PerfectMatching 