| 1 | r""" |
|---|
| 2 | Ribbon Tableaux |
|---|
| 3 | """ |
|---|
| 4 | #***************************************************************************** |
|---|
| 5 | # Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>, |
|---|
| 6 | # |
|---|
| 7 | # Distributed under the terms of the GNU General Public License (GPL) |
|---|
| 8 | # |
|---|
| 9 | # This code is distributed in the hope that it will be useful, |
|---|
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 12 | # General Public License for more details. |
|---|
| 13 | # |
|---|
| 14 | # The full text of the GPL is available at: |
|---|
| 15 | # |
|---|
| 16 | # http://www.gnu.org/licenses/ |
|---|
| 17 | #***************************************************************************** |
|---|
| 18 | |
|---|
| 19 | import sage.combinat.misc as misc |
|---|
| 20 | import sage.combinat.skew_tableau |
|---|
| 21 | import sage.combinat.word as word |
|---|
| 22 | import sage.combinat.permutation as permutation |
|---|
| 23 | import sage.combinat.partition as partition |
|---|
| 24 | import sage.combinat.skew_tableau |
|---|
| 25 | import sage.combinat.skew_partition |
|---|
| 26 | import sage.rings.integer |
|---|
| 27 | from combinat import CombinatorialClass, CombinatorialObject |
|---|
| 28 | |
|---|
| 29 | SkewTableau = sage.combinat.skew_tableau.SkewTableau |
|---|
| 30 | from_expr = sage.combinat.skew_tableau.from_expr |
|---|
| 31 | SkewPartition = sage.combinat.skew_partition.SkewPartition |
|---|
| 32 | Integer = sage.rings.integer.Integer |
|---|
| 33 | |
|---|
| 34 | def Ribbon(r): |
|---|
| 35 | """ |
|---|
| 36 | Returns a ribbon tableau object. |
|---|
| 37 | |
|---|
| 38 | EXAMPLES: |
|---|
| 39 | sage: Ribbon([[2,3],[1,4,5]]) |
|---|
| 40 | [[2, 3], [1, 4, 5]] |
|---|
| 41 | """ |
|---|
| 42 | return Ribbon_class(r) |
|---|
| 43 | |
|---|
| 44 | class Ribbon_class(CombinatorialObject): |
|---|
| 45 | def ribbon_shape(self): |
|---|
| 46 | """ |
|---|
| 47 | Returns the ribbon shape. The ribbon shape is given |
|---|
| 48 | just by the number of boxes in each row. |
|---|
| 49 | |
|---|
| 50 | EXAMPLES: |
|---|
| 51 | sage: Ribbon([[2,3],[1,4,5]]).ribbon_shape() |
|---|
| 52 | [2, 3] |
|---|
| 53 | """ |
|---|
| 54 | |
|---|
| 55 | return [len(row) for row in self] |
|---|
| 56 | |
|---|
| 57 | def height(self): |
|---|
| 58 | """ |
|---|
| 59 | Returns the height of the ribbon. |
|---|
| 60 | |
|---|
| 61 | EXAMPLES: |
|---|
| 62 | sage: Ribbon([[2,3],[1,4,5]]).height() |
|---|
| 63 | 2 |
|---|
| 64 | """ |
|---|
| 65 | return len(self) |
|---|
| 66 | |
|---|
| 67 | def spin(self): |
|---|
| 68 | """ |
|---|
| 69 | """ |
|---|
| 70 | return Integer(self.height()-1)/2 |
|---|
| 71 | |
|---|
| 72 | def width(self): |
|---|
| 73 | """ |
|---|
| 74 | Returns the width of the ribbon. |
|---|
| 75 | |
|---|
| 76 | EXAMPLES: |
|---|
| 77 | sage: Ribbon([[2,3],[1,4,5]]).width() |
|---|
| 78 | 4 |
|---|
| 79 | """ |
|---|
| 80 | return 1+sum([len(r)-1 for r in self]) |
|---|
| 81 | |
|---|
| 82 | def size(self): |
|---|
| 83 | """ |
|---|
| 84 | Returns the size ( number of boxes ) in the ribbon. |
|---|
| 85 | |
|---|
| 86 | EXAMPLES: |
|---|
| 87 | sage: Ribbon([[2,3],[1,4,5]]).size() |
|---|
| 88 | 5 |
|---|
| 89 | """ |
|---|
| 90 | return sum([len(r) for r in self]) |
|---|
| 91 | |
|---|
| 92 | def is_standard(self): |
|---|
| 93 | """ |
|---|
| 94 | Returns True is the ribbon is standard and False otherwise. |
|---|
| 95 | ribbon are standard if they are filled with the numbers |
|---|
| 96 | 1...size and they are increasing along both rows and columns. |
|---|
| 97 | |
|---|
| 98 | EXAMPLES: |
|---|
| 99 | sage: Ribbon([[2,3],[1,4,5]]).is_standard() |
|---|
| 100 | True |
|---|
| 101 | sage: Ribbon([[2,2],[1,4,5]]).is_standard() |
|---|
| 102 | False |
|---|
| 103 | sage: Ribbon([[4,5],[1,2,3]]).is_standard() |
|---|
| 104 | False |
|---|
| 105 | """ |
|---|
| 106 | |
|---|
| 107 | return self.to_skew_tableau().is_standard() |
|---|
| 108 | |
|---|
| 109 | def to_skew_tableau(self): |
|---|
| 110 | """ |
|---|
| 111 | Returns the skew tableau corresponding to the ribbon |
|---|
| 112 | tableau. |
|---|
| 113 | |
|---|
| 114 | EXAMPLES: |
|---|
| 115 | sage: Ribbon([[2,3],[1,4,5]]).to_skew_tableau() |
|---|
| 116 | [[None, None, 2, 3], [1, 4, 5]] |
|---|
| 117 | """ |
|---|
| 118 | st = [] |
|---|
| 119 | space_count = 0 |
|---|
| 120 | for row in reversed(self): |
|---|
| 121 | st.append( [None]*space_count + row ) |
|---|
| 122 | space_count += len(row) - 1 |
|---|
| 123 | st.reverse() |
|---|
| 124 | return sage.combinat.skew_tableau.SkewTableau(st) |
|---|
| 125 | |
|---|
| 126 | def to_permutation(self): |
|---|
| 127 | """ |
|---|
| 128 | Returns the permutation corresponding to the ribbon |
|---|
| 129 | tableau. |
|---|
| 130 | |
|---|
| 131 | EXAMPLES: |
|---|
| 132 | sage: r = Ribbon([[1], [2,3], [4, 5, 6]]) |
|---|
| 133 | sage: r.to_permutation() |
|---|
| 134 | [1, 2, 3, 4, 5, 6] |
|---|
| 135 | """ |
|---|
| 136 | return permutation.Permutation(self.to_word()) |
|---|
| 137 | |
|---|
| 138 | def shape(self): |
|---|
| 139 | """ |
|---|
| 140 | Returns the skew partition corresponding to the shape of the |
|---|
| 141 | ribbon. |
|---|
| 142 | |
|---|
| 143 | EXAMPLES: |
|---|
| 144 | sage: Ribbon([[2,3],[1,4,5]]).shape() |
|---|
| 145 | [[4, 3], [2]] |
|---|
| 146 | """ |
|---|
| 147 | return self.to_skew_tableau().shape() |
|---|
| 148 | |
|---|
| 149 | def to_word_by_row(self): |
|---|
| 150 | """ |
|---|
| 151 | Returns a word obtained from a row reading of the ribbon. |
|---|
| 152 | |
|---|
| 153 | EXAMPLES: |
|---|
| 154 | sage: Ribbon([[1],[2,3]]).to_word_by_row() |
|---|
| 155 | [1, 2, 3] |
|---|
| 156 | sage: Ribbon([[2, 4], [3], [1]]).to_word_by_row() |
|---|
| 157 | [2, 4, 3, 1] |
|---|
| 158 | """ |
|---|
| 159 | word = [] |
|---|
| 160 | for row in self: |
|---|
| 161 | word += row |
|---|
| 162 | |
|---|
| 163 | return word |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | def to_word_by_column(self): |
|---|
| 167 | """ |
|---|
| 168 | Returns the word obtained from a column reading of the ribbon |
|---|
| 169 | |
|---|
| 170 | EXAMPLES: |
|---|
| 171 | sage: Ribbon([[1],[2,3]]).to_word_by_column() |
|---|
| 172 | [2, 1, 3] |
|---|
| 173 | sage: Ribbon([[2, 4], [3], [1]]).to_word_by_column() |
|---|
| 174 | [2, 3, 1, 4] |
|---|
| 175 | |
|---|
| 176 | """ |
|---|
| 177 | return self.to_skew_tableau().to_word_by_column() |
|---|
| 178 | |
|---|
| 179 | def to_word(self): |
|---|
| 180 | """ |
|---|
| 181 | An alias for Ribbon.to_word_by_row(). |
|---|
| 182 | |
|---|
| 183 | EXAMPLES: |
|---|
| 184 | sage: Ribbon([[1],[2,3]]).to_word_by_row() |
|---|
| 185 | [1, 2, 3] |
|---|
| 186 | sage: Ribbon([[2, 4], [3], [1]]).to_word_by_row() |
|---|
| 187 | [2, 4, 3, 1] |
|---|
| 188 | """ |
|---|
| 189 | return self.to_word_by_row() |
|---|
| 190 | |
|---|
| 191 | def evaluation(self): |
|---|
| 192 | """ |
|---|
| 193 | Returns the evaluation of the word from ribbon. |
|---|
| 194 | |
|---|
| 195 | EXAMPLES: |
|---|
| 196 | sage: Ribbon([[1,2],[3,4]]).evaluation() |
|---|
| 197 | [1, 1, 1, 1] |
|---|
| 198 | """ |
|---|
| 199 | |
|---|
| 200 | return word.evaluation(self.to_word()) |
|---|
| 201 | |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | def from_shape_and_word(shape, word): |
|---|
| 205 | """ |
|---|
| 206 | Returns the ribbon corresponding to the given |
|---|
| 207 | ribbon shape and word. |
|---|
| 208 | |
|---|
| 209 | EXAMPLES: |
|---|
| 210 | sage: ribbon.from_shape_and_word([2,3],[1,2,3,4,5]) |
|---|
| 211 | [[1, 2], [3, 4, 5]] |
|---|
| 212 | """ |
|---|
| 213 | pos = 0 |
|---|
| 214 | r = [] |
|---|
| 215 | for l in shape: |
|---|
| 216 | r.append(word[pos:pos+l]) |
|---|
| 217 | pos += l |
|---|
| 218 | return Ribbon(r) |
|---|
| 219 | |
|---|
| 220 | def StandardRibbonTableaux(shape): |
|---|
| 221 | """ |
|---|
| 222 | Returns the combinatorial class of standard ribbon |
|---|
| 223 | tableaux of shape shape. |
|---|
| 224 | |
|---|
| 225 | EXAMPLES: |
|---|
| 226 | sage: StandardRibbonTableaux([2,2]) |
|---|
| 227 | Standard ribbon tableaux of shape [2, 2] |
|---|
| 228 | sage: StandardRibbonTableaux([2,2]).first() |
|---|
| 229 | [[1, 3], [2, 4]] |
|---|
| 230 | sage: StandardRibbonTableaux([2,2]).last() |
|---|
| 231 | [[3, 4], [1, 2]] |
|---|
| 232 | sage: StandardRibbonTableaux([2,2]).count() |
|---|
| 233 | 5 |
|---|
| 234 | sage: StandardRibbonTableaux([2,2]).list() |
|---|
| 235 | [[[1, 3], [2, 4]], |
|---|
| 236 | [[1, 4], [2, 3]], |
|---|
| 237 | [[2, 3], [1, 4]], |
|---|
| 238 | [[2, 4], [1, 3]], |
|---|
| 239 | [[3, 4], [1, 2]]] |
|---|
| 240 | |
|---|
| 241 | sage: StandardRibbonTableaux([2,2]).list() |
|---|
| 242 | [[[1, 3], [2, 4]], |
|---|
| 243 | [[1, 4], [2, 3]], |
|---|
| 244 | [[2, 3], [1, 4]], |
|---|
| 245 | [[2, 4], [1, 3]], |
|---|
| 246 | [[3, 4], [1, 2]]] |
|---|
| 247 | sage: StandardRibbonTableaux([3,2,2]).count() |
|---|
| 248 | 155 |
|---|
| 249 | |
|---|
| 250 | """ |
|---|
| 251 | return StandardRibbonTableaux_shape(shape) |
|---|
| 252 | |
|---|
| 253 | class StandardRibbonTableaux_shape(CombinatorialClass): |
|---|
| 254 | def __init__(self, shape): |
|---|
| 255 | """ |
|---|
| 256 | TESTS: |
|---|
| 257 | sage: S = StandardRibbonTableaux([2,2]) |
|---|
| 258 | sage: S == loads(dumps(S)) |
|---|
| 259 | True |
|---|
| 260 | """ |
|---|
| 261 | self.shape = shape |
|---|
| 262 | |
|---|
| 263 | def __repr__(self): |
|---|
| 264 | """ |
|---|
| 265 | TESTS: |
|---|
| 266 | sage: repr(StandardRibbonTableaux([2,2])) |
|---|
| 267 | 'Standard ribbon tableaux of shape [2, 2]' |
|---|
| 268 | """ |
|---|
| 269 | return "Standard ribbon tableaux of shape %s"%self.shape |
|---|
| 270 | |
|---|
| 271 | |
|---|
| 272 | def first(self): |
|---|
| 273 | """ |
|---|
| 274 | Returns the first standard ribbon of |
|---|
| 275 | ribbon shape shape. |
|---|
| 276 | |
|---|
| 277 | EXAMPLES: |
|---|
| 278 | sage: StandardRibbonTableaux([2,2]).first() |
|---|
| 279 | [[1, 3], [2, 4]] |
|---|
| 280 | |
|---|
| 281 | """ |
|---|
| 282 | return from_permutation(permutation.descents_composition_first(self.shape)) |
|---|
| 283 | |
|---|
| 284 | def last(self): |
|---|
| 285 | """ |
|---|
| 286 | Returns the first standard ribbon of |
|---|
| 287 | ribbon shape shape. |
|---|
| 288 | |
|---|
| 289 | EXAMPLES: |
|---|
| 290 | sage: StandardRibbonTableaux([2,2]).last() |
|---|
| 291 | [[3, 4], [1, 2]] |
|---|
| 292 | """ |
|---|
| 293 | return from_permutation(permutation.descents_composition_last(self.shape)) |
|---|
| 294 | |
|---|
| 295 | |
|---|
| 296 | def iterator(self): |
|---|
| 297 | """ |
|---|
| 298 | An iterator for the standard ribbon of ribbon |
|---|
| 299 | shape shape. |
|---|
| 300 | |
|---|
| 301 | EXAMPLES: |
|---|
| 302 | sage: [t for t in StandardRibbonTableaux([2,2])] |
|---|
| 303 | [[[1, 3], [2, 4]], |
|---|
| 304 | [[1, 4], [2, 3]], |
|---|
| 305 | [[2, 3], [1, 4]], |
|---|
| 306 | [[2, 4], [1, 3]], |
|---|
| 307 | [[3, 4], [1, 2]]] |
|---|
| 308 | """ |
|---|
| 309 | |
|---|
| 310 | for p in permutation.descents_composition_list(self.shape): |
|---|
| 311 | yield from_permutation(p) |
|---|
| 312 | |
|---|
| 313 | def from_permutation(p): |
|---|
| 314 | """ |
|---|
| 315 | Returns a standard ribbon of size len(p) from a Permutation p. |
|---|
| 316 | The lengths of each row are given by the distance between the descents |
|---|
| 317 | of the permutation p. |
|---|
| 318 | |
|---|
| 319 | EXAMPLES: |
|---|
| 320 | sage: [ribbon.from_permutation(p) for p in Permutations(3)] |
|---|
| 321 | [[[1, 2, 3]], |
|---|
| 322 | [[1, 3], [2]], |
|---|
| 323 | [[2], [1, 3]], |
|---|
| 324 | [[2, 3], [1]], |
|---|
| 325 | [[3], [1, 2]], |
|---|
| 326 | [[3], [2], [1]]] |
|---|
| 327 | |
|---|
| 328 | """ |
|---|
| 329 | if p == []: |
|---|
| 330 | return Ribbon([]) |
|---|
| 331 | |
|---|
| 332 | comp = p.descents() |
|---|
| 333 | |
|---|
| 334 | if comp == []: |
|---|
| 335 | return Ribbon([p[:]]) |
|---|
| 336 | |
|---|
| 337 | |
|---|
| 338 | #[p[j]$j=compo[i]+1..compo[i+1]] $i=1..nops(compo)-1, [p[j]$j=compo[nops(compo)]+1..nops(p)] |
|---|
| 339 | r = [] |
|---|
| 340 | r.append([p[j] for j in range(comp[0]+1)]) |
|---|
| 341 | for i in range(len(comp)-1): |
|---|
| 342 | r.append([ p[j] for j in range(comp[i]+1,comp[i+1]+1) ]) |
|---|
| 343 | r.append( [ p[j] for j in range(comp[-1]+1, len(p))] ) |
|---|
| 344 | |
|---|
| 345 | return Ribbon(r) |
|---|
| 346 | |
|---|
| 347 | |
|---|
| 348 | |
|---|
| 349 | ##################### |
|---|
| 350 | # Under Development # |
|---|
| 351 | ##################### |
|---|
| 352 | class RibbonTableaux_shapeweightlength(CombinatorialClass): |
|---|
| 353 | def __init__(self, shape, weight, length): |
|---|
| 354 | self.shape = shape |
|---|
| 355 | self.weight = weight |
|---|
| 356 | self.length = length |
|---|
| 357 | |
|---|
| 358 | def list(self): |
|---|
| 359 | pass |
|---|
| 360 | |
|---|
| 361 | |
|---|
| 362 | |
|---|
| 363 | def list(skp, weight, length): |
|---|
| 364 | if skp in partition.Partitions(): |
|---|
| 365 | skp = partition.Partition(skp) |
|---|
| 366 | skp = SkewPartition([skp, skp.rcore(length)]) |
|---|
| 367 | else: |
|---|
| 368 | skp = SkewPartition(skp) |
|---|
| 369 | |
|---|
| 370 | #skp_expr = skp.to_expr() |
|---|
| 371 | |
|---|
| 372 | if skp.size() != length*sum(weight): |
|---|
| 373 | raise ValueError |
|---|
| 374 | |
|---|
| 375 | return map(lambda x: from_expr( [skp[1], x[1]]), graph_implementation_rec(skp, weight, length, list_rec)) |
|---|
| 376 | |
|---|
| 377 | |
|---|
| 378 | |
|---|
| 379 | |
|---|
| 380 | |
|---|
| 381 | |
|---|
| 382 | |
|---|
| 383 | |
|---|
| 384 | |
|---|
| 385 | def insertion_tableau(skp, perm, evaluation, tableau, length): |
|---|
| 386 | """ |
|---|
| 387 | |
|---|
| 388 | INPUT: |
|---|
| 389 | skp -- skew partitions |
|---|
| 390 | perm, evaluation -- non-negative integers |
|---|
| 391 | tableau -- skew tableau |
|---|
| 392 | length -- integer |
|---|
| 393 | |
|---|
| 394 | """ |
|---|
| 395 | print "insertion_tableau(%s, %s, %s, %s, %s)"%(skp, perm, evaluation, tableau, length) |
|---|
| 396 | psave = skp[1] |
|---|
| 397 | partc = skp[1] + [0]*(len(skp[0])-len(skp[1])) |
|---|
| 398 | |
|---|
| 399 | tableau = tableau.to_expr()[1] |
|---|
| 400 | for k in range(len(tableau)): |
|---|
| 401 | tableau[-(k+1)] += [0]* ( skp[0][k] - partc[k] - len(tableau[-(k+1)])) |
|---|
| 402 | |
|---|
| 403 | ## We construct a tableau from the southwest corner to the northeast one |
|---|
| 404 | #[ op( revert([[0$(partition[1][k] - partc[k]) ] $k = nops(tableau)+1..nops(partition[1])])) , op(tableau) ]; |
|---|
| 405 | tableau = [[0]*(skp[0][k] - partc[k]) for k in reversed(range(len(tableau), len(skp[0])+1))] + tableau |
|---|
| 406 | |
|---|
| 407 | tableau = SkewTableau(expr=[skp[1], tableau]).conjugate() |
|---|
| 408 | tableau = tableau.to_expr()[1] |
|---|
| 409 | |
|---|
| 410 | skp = skp.conjugate().to_list() |
|---|
| 411 | skp[1].append( [0]*(len(skp[0])-len(skp[1])) ) |
|---|
| 412 | |
|---|
| 413 | if len(perm) > len(skp[0]): |
|---|
| 414 | return None |
|---|
| 415 | |
|---|
| 416 | for k in range(len(perm)): |
|---|
| 417 | if perm[ -(k+1) ] !=0: |
|---|
| 418 | #tableau ... = evaluation |
|---|
| 419 | tableau[len(tableau)-len(perm)+k-1][ spk[0][len(perm)-k] - skp[1][ len(perm)-k ] ] = evaluation |
|---|
| 420 | pass |
|---|
| 421 | |
|---|
| 422 | return SkewTableau(expr=[psave.conjugate(),tableau]).conjugate() |
|---|
| 423 | |
|---|
| 424 | |
|---|
| 425 | |
|---|
| 426 | |
|---|
| 427 | def list_rec(nexts, current, part, weight, length): |
|---|
| 428 | """ |
|---|
| 429 | |
|---|
| 430 | INPUT: |
|---|
| 431 | nexts, current, part -- skew partitions |
|---|
| 432 | weight -- non-negative integer list |
|---|
| 433 | length -- integer |
|---|
| 434 | """ |
|---|
| 435 | print "list_rec(%s, %s, %s, %s, %s)"%(nexts, current, part, weight, length) |
|---|
| 436 | if current == [] and nexts == [] and weight == []: |
|---|
| 437 | return [part[1],[]] |
|---|
| 438 | |
|---|
| 439 | ## Test if the current nodes is not an empty node |
|---|
| 440 | if current == []: |
|---|
| 441 | return [] |
|---|
| 442 | |
|---|
| 443 | |
|---|
| 444 | ## Test if the current nodes drive us to new solutions |
|---|
| 445 | if next != []: |
|---|
| 446 | res = [] |
|---|
| 447 | for i in range(len(current)): |
|---|
| 448 | for j in range(len(nexts[i])): |
|---|
| 449 | res.append( interstion_tableau(part, current[i][1], len(weight), nexts[i][j], length) ) |
|---|
| 450 | return res |
|---|
| 451 | else: |
|---|
| 452 | ## The current nodes are at the bottom of the tree |
|---|
| 453 | res = [] |
|---|
| 454 | for i in range(len(current)): |
|---|
| 455 | res.append( insertion_tableau(part, current[i][1], len(weight), [[],[]], length) ) |
|---|
| 456 | return res |
|---|
| 457 | |
|---|
| 458 | |
|---|
| 459 | ## ////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 460 | ## // Generic function for driving into the graph of partitions coding all ribbons |
|---|
| 461 | ## // tableaux of a given shape and weight |
|---|
| 462 | ## ////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 463 | |
|---|
| 464 | ## //This function construct the graph of the set of k-ribbon tableaux |
|---|
| 465 | ## //of a given skew shape and a given weight. |
|---|
| 466 | ## //The first argument is alaways a skew partition. |
|---|
| 467 | ## //In the case where the inner partition is empty there is no branch without solutions |
|---|
| 468 | ## //In the other cases there is in average a lot of branches without solutions |
|---|
| 469 | ## ///////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 470 | |
|---|
| 471 | |
|---|
| 472 | |
|---|
| 473 | def graph_implementation_rec(skp, weight, length, function): |
|---|
| 474 | print "graph_implementation_rec(%s, %s, %s, %s)"%(skp, weight, length, function) |
|---|
| 475 | |
|---|
| 476 | if sum(weight) == 0: |
|---|
| 477 | weight = [] |
|---|
| 478 | |
|---|
| 479 | partp = partition.Partition(skp[1]).conjugate() |
|---|
| 480 | |
|---|
| 481 | ## Some tests in order to know if the shape and the weight are compatible. |
|---|
| 482 | if weight != [] and weight[-1] <= len(partp): |
|---|
| 483 | perms = permutation.Permutations([0]*(len(partp)-weight[-1]) + [length]*(weight[-1])).list() |
|---|
| 484 | else: |
|---|
| 485 | return function([], [], part, weight, length) |
|---|
| 486 | |
|---|
| 487 | selection = [] |
|---|
| 488 | |
|---|
| 489 | for j in range(len(perms)): |
|---|
| 490 | retire = [(partp[i]+ len(partp) - (i+1) - perms[j][i]) for i in range(len(partp))] |
|---|
| 491 | retire.sort(reverse=True) |
|---|
| 492 | retire = [ retire[i] - len(partp) + (i+1) for i in range(len(retire))] |
|---|
| 493 | |
|---|
| 494 | if retire[-1] >= 0 and retire == [i for i in reversed(sorted(retire))]: |
|---|
| 495 | retire = partition.Partition(filter(lambda x: x != 0, retire)).conjugate() |
|---|
| 496 | |
|---|
| 497 | |
|---|
| 498 | # Cutting branches if the retired partition has a line strictly included into the inner one |
|---|
| 499 | append = True |
|---|
| 500 | padded_retire = retire + [0]*(len(skp[1])-len(retire)) |
|---|
| 501 | for k in range(len(skp[1])): |
|---|
| 502 | if padded_retire[k] - skp[1][k] < 0: |
|---|
| 503 | append = False |
|---|
| 504 | break |
|---|
| 505 | if append: |
|---|
| 506 | selection.append([retire, perms[j]]) |
|---|
| 507 | |
|---|
| 508 | |
|---|
| 509 | #selection contains the list of current nodes |
|---|
| 510 | |
|---|
| 511 | |
|---|
| 512 | if len(weight) == 1: |
|---|
| 513 | return function([], selection, part, weight, length) |
|---|
| 514 | else: |
|---|
| 515 | #The recursive calls permit us to construct the list of the sons |
|---|
| 516 | #of all current nodes in selection |
|---|
| 517 | a = [graph_implementation_rec([p[0], part[1]], [weight[i]]*(len(weight)-1), length, function) for p in selection] |
|---|
| 518 | return function(a, selection, skp, weight, length) |
|---|
| 519 | |
|---|
| 520 | |
|---|
| 521 | |
|---|
| 522 | |
|---|
| 523 | |
|---|
| 524 | |
|---|
| 525 | |
|---|
| 526 | |
|---|
| 527 | |
|---|
| 528 | |
|---|
| 529 | |
|---|
| 530 | |
|---|
| 531 | |
|---|