19 | | You can use the .first() method to get the 'first' composition of a |
20 | | number. |
21 | | |
22 | | :: |
23 | | |
24 | | sage: Compositions(4).first() |
25 | | [1, 1, 1, 1] |
26 | | |
27 | | You can also calculate the 'next' composition given the current |
28 | | one. |
29 | | |
30 | | :: |
31 | | |
32 | | sage: Compositions(4).next([1,1,2]) |
33 | | [1, 2, 1] |
34 | | |
35 | | The following examples shows how to test whether or not an object |
36 | | is a composition. |
37 | | |
38 | | :: |
39 | | |
40 | | sage: [3,4] in Compositions() |
41 | | True |
42 | | sage: [3,4] in Compositions(7) |
43 | | True |
44 | | sage: [3,4] in Compositions(5) |
45 | | False |
46 | | |
47 | | Similarly, one can check whether or not an object is a composition |
48 | | which satisfies further constraints. |
49 | | |
50 | | :: |
51 | | |
52 | | sage: [4,2] in Compositions(6, inner=[2,2], min_part=2) |
53 | | True |
54 | | sage: [4,2] in Compositions(6, inner=[2,2], min_part=2) |
55 | | True |
56 | | sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) |
57 | | False |
58 | | |
59 | | Note that the given constraints should compatible. |
60 | | |
61 | | :: |
62 | | |
63 | | sage: [4,1] in Compositions(5, inner=[2,1], min_part=1) |
64 | | True |
65 | | |
66 | | The options length, min_length, and max_length can be used to set |
67 | | length constraints on the compositions. For example, the |
68 | | compositions of 4 of length equal to, at least, and at most 2 are |
69 | | given by:: |
70 | | |
71 | | sage: Compositions(4, length=2).list() |
72 | | [[1, 3], [2, 2], [3, 1]] |
73 | | sage: Compositions(4, min_length=2).list() |
74 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1]] |
75 | | sage: Compositions(4, max_length=2).list() |
76 | | [[1, 3], [2, 2], [3, 1], [4]] |
77 | | |
78 | | Setting both min_length and max_length to the same value is |
79 | | equivalent to setting length to this value. |
80 | | |
81 | | :: |
82 | | |
83 | | sage: Compositions(4, min_length=2, max_length=2).list() |
84 | | [[1, 3], [2, 2], [3, 1]] |
85 | | |
86 | | The options inner and outer can be used to set part-by-part |
87 | | containment constraints. The list of compositions of 4 bounded above |
88 | | by [3,1,2] is given by:: |
89 | | |
90 | | sage: Compositions(4, outer=[3,1,2]).list() |
91 | | [[1, 1, 2], [2, 1, 1], [3, 1]] |
92 | | |
93 | | Outer sets max_length to the length of its argument. Moreover, the |
94 | | parts of outer may be infinite to clear the constraint on specific |
95 | | parts. This is the list of compositions of 4 of length at most 3 |
96 | | such that the first and third parts are at most 1:: |
97 | | |
98 | | sage: Compositions(4, outer=[1,oo,1]).list() |
99 | | [[1, 2, 1], [1, 3]] |
100 | | |
101 | | This is the list of compositions of 4 bounded below by [1,1,1]. |
102 | | |
103 | | :: |
104 | | |
105 | | sage: Compositions(4, inner=[1,1,1]).list() |
106 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1]] |
107 | | |
108 | | The options min_slope and max_slope can be used to set |
109 | | constraints on the slope, that is the difference p[i+1]-p[i] of two |
110 | | consecutive parts. The following is the list of weakly increasing |
111 | | compositions of 4. |
112 | | |
113 | | :: |
114 | | |
115 | | sage: Compositions(4, min_slope=0).list() |
116 | | [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]] |
117 | | |
118 | | The following is the list of compositions of 4 such that two |
119 | | consecutive parts differ by at most one unit:: |
120 | | |
121 | | sage: Compositions(4, min_slope=-1, max_slope=1).list() |
122 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2], [4]] |
123 | | |
124 | | The constraints can be combinat together in all reasonable ways. |
125 | | This is the list of compositions of 5 of length between 2 and 4 |
126 | | such that the difference between consecutive parts is between -2 and |
127 | | 1. |
128 | | |
129 | | :: |
130 | | |
131 | | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list() |
132 | | [[1, 1, 1, 2], |
133 | | [1, 1, 2, 1], |
134 | | [1, 2, 1, 1], |
135 | | [1, 2, 2], |
136 | | [2, 1, 1, 1], |
137 | | [2, 1, 2], |
138 | | [2, 2, 1], |
139 | | [2, 3], |
140 | | [3, 1, 1], |
141 | | [3, 2]] |
142 | | |
143 | | We can do the same thing with an outer constraint:: |
144 | | |
145 | | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() |
146 | | [[1, 2, 2], [2, 1, 2], [2, 2, 1], [2, 3]] |
147 | | |
148 | | However, providing incoherent constraints may yield strange |
149 | | results. It is up to the user to ensure that the inner and outer |
150 | | compositions themselves satisfy the parts and slope constraints. |
| 140 | |
| 141 | def __add__(self, other): |
| 142 | """ |
| 143 | Returns the concatenation of two compositions. |
| 144 | |
| 145 | EXAMPLES:: |
| 146 | |
| 147 | sage: Composition([1, 1, 3]) + Composition([4, 1, 2]) |
| 148 | [1, 1, 3, 4, 1, 2] |
| 149 | |
| 150 | TESTS:: |
| 151 | |
| 152 | sage: Composition([]) + Composition([]) == Composition([]) |
| 153 | True |
| 154 | """ |
| 155 | return Composition(list(self)+list(other)) |
| 156 | |
| 157 | def size(self): |
| 158 | """ |
| 159 | Returns the size of the composition, that is the sum of its parts. |
| 160 | |
| 161 | EXAMPLES:: |
| 162 | |
| 163 | sage: Composition([7,1,3]).size() |
| 164 | 11 |
| 165 | """ |
| 166 | return sum(self) |
| 167 | |
| 168 | @staticmethod |
| 169 | def sum(compositions): |
| 170 | """ |
| 171 | INPUT: |
| 172 | |
| 173 | - ``compositions``: a list (or iterable) of compositions |
| 174 | |
| 175 | Returns the concatenation of the given compositions |
| 176 | |
| 177 | EXAMPLES:: |
| 178 | |
| 179 | sage: sage.combinat.composition.Composition_class.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])]) |
| 180 | [1, 1, 3, 4, 1, 2, 3, 1] |
| 181 | |
| 182 | Any iterable can be provided as input:: |
| 183 | |
| 184 | sage: sage.combinat.composition.Composition_class.sum([Composition([i,i]) for i in [4,1,3]]) |
| 185 | [4, 4, 1, 1, 3, 3] |
| 186 | |
| 187 | Empty inputs are handled gracefuly:: |
| 188 | |
| 189 | sage: sage.combinat.composition.Composition_class.sum([]) == Composition([]) |
| 190 | True |
| 191 | """ |
| 192 | return sum(compositions, Composition([])) |
| 193 | |
| 194 | def finer(self): |
| 195 | """ |
| 196 | Returns the set of compositions which are finer than self |
| 197 | |
| 198 | EXAMPLES:: |
| 199 | |
| 200 | sage: C = Composition([3,2]).finer() |
| 201 | sage: C.cardinality() |
| 202 | 8 |
| 203 | sage: list(C) |
| 204 | [[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 2, 1, 1], [1, 2, 2], [2, 1, 1, 1], [2, 1, 2], [3, 1, 1], [3, 2]] |
| 205 | """ |
| 206 | return CartesianProduct(*[Compositions(i) for i in self]).map(Composition_class.sum) |
| 207 | |
| 243 | def fatten(self, grouping): |
| 244 | """ |
| 245 | INPUT: |
| 246 | |
| 247 | - ``grouping`` - a composition whose sum is the length of self |
| 248 | |
| 249 | Returns the composition fatter than self, obtained by grouping |
| 250 | together consecutive parts according to grouping. |
| 251 | |
| 252 | EXAMPLES: |
| 253 | |
| 254 | Let us start with the composition:: |
| 255 | |
| 256 | sage: c = Composition([4,5,2,7,1]) |
| 257 | |
| 258 | With `grouping = (1,\dots,1)`, `c` is left unchanged:: |
| 259 | |
| 260 | sage: c.fatten(Composition([1,1,1,1,1])) |
| 261 | [4, 5, 2, 7, 1] |
| 262 | |
| 263 | With `grouping = (5)`, this yields the coarser composition above `c`:: |
| 264 | |
| 265 | sage: c.fatten(Composition([5])) |
| 266 | [19] |
| 267 | |
| 268 | Other values for `grouping` yield (all the) other compositions coarser |
| 269 | to `c`:: |
| 270 | |
| 271 | sage: c.fatten(Composition([2,1,2])) |
| 272 | [9, 2, 8] |
| 273 | sage: c.fatten(Composition([3,1,1])) |
| 274 | [11, 7, 1] |
| 275 | |
| 276 | TESTS:: |
| 277 | |
| 278 | sage: Composition([]).fatten(Composition([])) |
| 279 | [] |
| 280 | sage: c.fatten(Composition([3,1,1])).__class__ == c.__class__ |
| 281 | True |
| 282 | """ |
| 283 | result = [None] * len(grouping) |
| 284 | j = 0 |
| 285 | for i in range(len(grouping)): |
| 286 | result[i] = sum(self[j:j+grouping[i]]) |
| 287 | j += grouping[i] |
| 288 | return Composition_class(result) |
| 289 | |
| 290 | def fatter(self): |
| 291 | """ |
| 292 | Returns the set of compositions which are fatter than self |
| 293 | |
| 294 | Complexity for generation: O(size(c)) memory, O(size(result)) time |
| 295 | |
| 296 | EXAMPLES:: |
| 297 | |
| 298 | sage: C = Composition([4,5,2]).fatter() |
| 299 | sage: C.cardinality() |
| 300 | 4 |
| 301 | sage: list(C) |
| 302 | [[4, 5, 2], [4, 7], [9, 2], [11]] |
| 303 | |
| 304 | Some extreme cases:: |
| 305 | |
| 306 | sage: list(Composition([5]).fatter()) |
| 307 | [[5]] |
| 308 | sage: list(Composition([]).fatter()) |
| 309 | [[]] |
| 310 | sage: list(Composition([1,1,1,1]).fatter()) == list(Compositions(4)) |
| 311 | True |
| 312 | """ |
| 313 | |
| 314 | return Compositions(len(self)).map(self.fatten) |
| 315 | |
450 | | """ |
451 | | Returns the combinatorial class of compositions. |
452 | | |
453 | | EXAMPLES: If n is not specified, it returns the combinatorial |
454 | | class of all (non-negative) integer compositions. |
455 | | |
456 | | :: |
| 459 | r""" |
| 460 | Sets of integer Compositions |
| 461 | |
| 462 | A composition `c` of a nonnegative integer `n` is a list of |
| 463 | positive integers with total sum `n`. |
| 464 | |
| 465 | See also: `Composition`, `Partitions`, `IntegerVectors` |
| 466 | |
| 467 | EXAMPLES: |
| 468 | |
| 469 | There are 8 compositions of 4:: |
| 470 | |
| 471 | sage: Compositions(4).cardinality() |
| 472 | 8 |
| 473 | |
| 474 | Here is the list of them:: |
| 475 | |
| 476 | sage: list(Compositions(4)) |
| 477 | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] |
| 478 | |
| 479 | You can use the .first() method to get the 'first' composition of |
| 480 | a number:: |
| 481 | |
| 482 | sage: Compositions(4).first() |
| 483 | [1, 1, 1, 1] |
| 484 | |
| 485 | You can also calculate the 'next' composition given the current |
| 486 | one:: |
| 487 | |
| 488 | sage: Compositions(4).next([1,1,2]) |
| 489 | [1, 2, 1] |
| 490 | |
| 491 | |
| 492 | |
| 493 | If `n` is not specified, this returns the combinatorial class of |
| 494 | all (non-negative) integer compositions:: |
| 513 | |
| 514 | The following examples shows how to test whether or not an object |
| 515 | is a composition:: |
| 516 | |
| 517 | sage: [3,4] in Compositions() |
| 518 | True |
| 519 | sage: [3,4] in Compositions(7) |
| 520 | True |
| 521 | sage: [3,4] in Compositions(5) |
| 522 | False |
| 523 | |
| 524 | Similarly, one can check whether or not an object is a composition |
| 525 | which satisfies further constraints:: |
| 526 | |
| 527 | sage: [4,2] in Compositions(6, inner=[2,2]) |
| 528 | True |
| 529 | sage: [4,2] in Compositions(6, inner=[2,3]) |
| 530 | False |
| 531 | sage: [4,1] in Compositions(5, inner=[2,1], max_slope = 0) |
| 532 | True |
| 533 | |
| 534 | Note that the given constraints should be compatible:: |
| 535 | |
| 536 | sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) # |
| 537 | True |
| 538 | |
| 539 | The options length, min_length, and max_length can be used to set |
| 540 | length constraints on the compositions. For example, the |
| 541 | compositions of 4 of length equal to, at least, and at most 2 are |
| 542 | given by:: |
| 543 | |
| 544 | sage: Compositions(4, length=2).list() |
| 545 | [[3, 1], [2, 2], [1, 3]] |
| 546 | sage: Compositions(4, min_length=2).list() |
| 547 | [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 548 | sage: Compositions(4, max_length=2).list() |
| 549 | [[4], [3, 1], [2, 2], [1, 3]] |
| 550 | |
| 551 | Setting both min_length and max_length to the same value is |
| 552 | equivalent to setting length to this value:: |
| 553 | |
| 554 | sage: Compositions(4, min_length=2, max_length=2).list() |
| 555 | [[3, 1], [2, 2], [1, 3]] |
| 556 | |
| 557 | The options inner and outer can be used to set part-by-part |
| 558 | containment constraints. The list of compositions of 4 bounded |
| 559 | above by [3,1,2] is given by:: |
| 560 | |
| 561 | sage: list(Compositions(4, outer=[3,1,2])) |
| 562 | [[3, 1], [2, 1, 1], [1, 1, 2]] |
| 563 | |
| 564 | Outer sets max_length to the length of its argument. Moreover, the |
| 565 | parts of outer may be infinite to clear the constraint on specific |
| 566 | parts. This is the list of compositions of 4 of length at most 3 |
| 567 | such that the first and third parts are at most 1:: |
| 568 | |
| 569 | sage: list(Compositions(4, outer=[1,oo,1])) |
| 570 | [[1, 3], [1, 2, 1]] |
| 571 | |
| 572 | This is the list of compositions of 4 bounded below by [1,1,1]:: |
| 573 | |
| 574 | sage: list(Compositions(4, inner=[1,1,1])) |
| 575 | [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 576 | |
| 577 | The options min_slope and max_slope can be used to set constraints |
| 578 | on the slope, that is the difference `p[i+1]-p[i]` of two |
| 579 | consecutive parts. The following is the list of weakly increasing |
| 580 | compositions of 4:: |
| 581 | |
| 582 | sage: Compositions(4, min_slope=0).list() |
| 583 | [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]] |
478 | | In addition, the following constraints can be put on the |
479 | | compositions: length, min_part, max_part, min_length, |
480 | | max_length, min_slope, max_slope, inner, and outer. For |
481 | | example, |
| 585 | Here are the weakly decreasing ones:: |
| 586 | |
| 587 | sage: Compositions(4, max_slope=0).list() |
| 588 | [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] |
| 589 | |
| 590 | |
| 591 | The following is the list of compositions of 4 such that two |
| 592 | consecutive parts differ by at most one:: |
| 593 | |
| 594 | sage: Compositions(4, min_slope=-1, max_slope=1).list() |
| 595 | [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 596 | |
| 597 | The constraints can be combined together in all reasonable ways. |
| 598 | This is the list of compositions of 5 of length between 2 and 4 |
| 599 | such that the difference between consecutive parts is between -2 |
| 600 | and 1:: |
| 601 | |
| 602 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list() |
| 603 | [[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [2, 1, 1, 1], [1, 2, 2], [1, 2, 1, 1], [1, 1, 2, 1], [1, 1, 1, 2]] |
| 604 | |
| 605 | We can do the same thing with an outer constraint:: |
| 606 | |
| 607 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() |
| 608 | [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]] |
| 609 | |
| 610 | However, providing incoherent constraints may yield strange |
| 611 | results. It is up to the user to ensure that the inner and outer |
| 612 | compositions themselves satisfy the parts and slope constraints. |
| 613 | |
| 614 | Note that if you specify min_part=0, then the objects produced may |
| 615 | have parts equal to zero. This violates the internal assumptions |
| 616 | that the Composition class makes. Use at your own risk, or |
| 617 | preferably consider using `IntegerVectors` instead:: |
| 618 | |
| 619 | sage: list(Compositions(2, length=3, min_part=0)) |
| 620 | doctest:... RuntimeWarning: Currently, setting min_part=0 produces Composition objects which violate internal assumptions. Calling methods on these objects may produce errors or WRONG results! |
| 621 | [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] |
| 622 | |
| 623 | sage: list(IntegerVectors(2, 3)) |
| 624 | [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] |
| 625 | |
| 626 | The generation algorithm is constant amortized time, and handled |
| 627 | by the generic tool `IntegerListsLex`. |
| 628 | |
| 629 | TESTS:: |
485 | | sage: Compositions(3, length=2).list() |
486 | | [[1, 2], [2, 1]] |
487 | | sage: Compositions(4, max_slope=0).list() |
488 | | [[1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]] |
| 638 | |
| 639 | sage: [2, 1] in Compositions(3, length=2) |
| 640 | True |
| 641 | sage: [2,1,2] in Compositions(5, min_part=1) |
| 642 | True |
| 643 | sage: [2,1,2] in Compositions(5, min_part=2) |
| 644 | False |
| 645 | |
| 646 | sage: Compositions(4, length=2).cardinality() |
| 647 | 3 |
| 648 | sage: Compositions(4, min_length=2).cardinality() |
| 649 | 7 |
| 650 | sage: Compositions(4, max_length=2).cardinality() |
| 651 | 4 |
| 652 | sage: Compositions(4, max_part=2).cardinality() |
| 653 | 5 |
| 654 | sage: Compositions(4, min_part=2).cardinality() |
| 655 | 2 |
| 656 | sage: Compositions(4, outer=[3,1,2]).cardinality() |
| 657 | 3 |
| 658 | |
| 659 | sage: Compositions(4, length=2).list() |
| 660 | [[3, 1], [2, 2], [1, 3]] |
| 661 | sage: Compositions(4, min_length=2).list() |
| 662 | [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 663 | sage: Compositions(4, max_length=2).list() |
| 664 | [[4], [3, 1], [2, 2], [1, 3]] |
| 665 | sage: Compositions(4, max_part=2).list() |
| 666 | [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 667 | sage: Compositions(4, min_part=2).list() |
| 668 | [[4], [2, 2]] |
| 669 | sage: Compositions(4, outer=[3,1,2]).list() |
| 670 | [[3, 1], [2, 1, 1], [1, 1, 2]] |
| 671 | sage: Compositions(4, outer=[1,oo,1]).list() |
| 672 | [[1, 3], [1, 2, 1]] |
| 673 | sage: Compositions(4, inner=[1,1,1]).list() |
| 674 | [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 675 | sage: Compositions(4, min_slope=0).list() |
| 676 | [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]] |
| 677 | sage: Compositions(4, min_slope=-1, max_slope=1).list() |
| 678 | [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 679 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list() |
| 680 | [[3, 2], [3, 1, 1], [2, 3], [2, 2, 1], [2, 1, 2], [2, 1, 1, 1], [1, 2, 2], [1, 2, 1, 1], [1, 1, 2, 1], [1, 1, 1, 2]] |
| 681 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() |
| 682 | [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]] |
496 | | return Compositions_n(n) |
| 694 | # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute |
| 695 | kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] )) |
| 696 | kwargs['element_constructor'] = Composition_class |
| 697 | if 'min_part' not in kwargs: |
| 698 | kwargs['min_part'] = 1 |
| 699 | elif kwargs['min_part'] == 0: |
| 700 | from warnings import warn |
| 701 | warn("Currently, setting min_part=0 produces Composition objects which violate internal assumptions. Calling methods on these objects may produce errors or WRONG results!", RuntimeWarning) |
| 702 | |
| 703 | if 'outer' in kwargs: |
| 704 | kwargs['ceiling'] = kwargs['outer'] |
| 705 | if 'max_length' in kwargs: |
| 706 | kwargs['max_length'] = min( len(kwargs['outer']), kwargs['max_length']) |
| 707 | else: |
| 708 | kwargs['max_length'] = len(kwargs['outer']) |
| 709 | del kwargs['outer'] |
| 710 | |
| 711 | if 'inner' in kwargs: |
| 712 | inner = kwargs['inner'] |
| 713 | kwargs['floor'] = inner |
| 714 | del kwargs['inner'] |
| 715 | # Should this be handled by integer lists lex? |
| 716 | if 'min_length' in kwargs: |
| 717 | kwargs['min_length'] = max( len(inner), kwargs['min_length']) |
| 718 | else: |
| 719 | kwargs['min_length'] = len(inner) |
| 720 | return IntegerListsLex(n, **kwargs) |
| 721 | |
| 722 | |
| 723 | # Allows to unpickle old constrained Compositions_constraints objects. |
| 724 | class Compositions_constraints(IntegerListsLex): |
| 725 | def __setstate__(self, data): |
| 726 | """ |
| 727 | TESTS:: |
| 728 | |
| 729 | # This is the unpickling sequence for Compositions(4, max_part=2) in sage <= 4.1.1 |
| 730 | sage: pg_Compositions_constraints = unpickle_global('sage.combinat.composition', 'Compositions_constraints') |
| 731 | sage: si = unpickle_newobj(pg_Compositions_constraints, ()) |
| 732 | sage: pg_make_integer = unpickle_global('sage.rings.integer', 'make_integer') |
| 733 | sage: unpickle_build(si, {'constraints':{'max_part':pg_make_integer('2')}, 'n':pg_make_integer('4')}) |
| 734 | sage: si |
| 735 | Integer lists of sum 4 satisfying certain constraints |
| 736 | sage: si.list() |
| 737 | [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 738 | """ |
| 739 | n = data['n'] |
| 740 | self.__class__ = IntegerListsLex |
| 741 | constraints = { |
| 742 | 'min_part' : 1, |
| 743 | 'element_constructor' : Composition_class} |
| 744 | constraints.update(data['constraints']) |
| 745 | self.__init__(n, **constraints) |
643 | | def __repr__(self): |
644 | | """ |
645 | | TESTS:: |
646 | | |
647 | | sage: repr(Compositions(6, min_part=2, length=3)) |
648 | | 'Compositions of 6 with constraints length=3, min_part=2' |
649 | | """ |
650 | | return "Compositions of %s with constraints %s"%(self.n, ", ".join( ["%s=%s"%(key, self.constraints[key]) for key in sorted(self.constraints.keys())] )) |
651 | | |
652 | | def __contains__(self, x): |
653 | | """ |
654 | | TESTS:: |
655 | | |
656 | | sage: [2, 1] in Compositions(3, length=2) |
657 | | True |
658 | | sage: [2,1,2] in Compositions(5, min_part=1) |
659 | | True |
660 | | sage: [2,1,2] in Compositions(5, min_part=2) |
661 | | False |
662 | | """ |
663 | | return x in Compositions() and sum(x) == self.n and misc.check_integer_list_constraints(x, singleton=True, **self.constraints) |
664 | | |
665 | | |
666 | | def cardinality(self): |
667 | | """ |
668 | | EXAMPLES:: |
669 | | |
670 | | sage: Compositions(4, length=2).cardinality() |
671 | | 3 |
672 | | sage: Compositions(4, min_length=2).cardinality() |
673 | | 7 |
674 | | sage: Compositions(4, max_length=2).cardinality() |
675 | | 4 |
676 | | sage: Compositions(4, max_part=2).cardinality() |
677 | | 5 |
678 | | sage: Compositions(4, min_part=2).cardinality() |
679 | | 2 |
680 | | sage: Compositions(4, outer=[3,1,2]).cardinality() |
681 | | 3 |
682 | | """ |
683 | | if len(self.constraints) == 1 and 'length' in self.constraints: |
684 | | if self.n >= 1: |
685 | | return binomial(self.n-1, self.constraints['length'] - 1) |
686 | | elif self.n == 0: |
687 | | if self.constraints['length'] == 0: |
688 | | return 1 |
689 | | else: |
690 | | return 0 |
691 | | else: |
692 | | return 0 |
693 | | return len(self.list()) |
694 | | |
695 | | |
696 | | |
697 | | def list(self): |
698 | | """ |
699 | | Returns a list of all the compositions of n. |
700 | | |
701 | | EXAMPLES:: |
702 | | |
703 | | sage: Compositions(4, length=2).list() |
704 | | [[1, 3], [2, 2], [3, 1]] |
705 | | sage: Compositions(4, min_length=2).list() |
706 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1]] |
707 | | sage: Compositions(4, max_length=2).list() |
708 | | [[1, 3], [2, 2], [3, 1], [4]] |
709 | | sage: Compositions(4, max_part=2).list() |
710 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2]] |
711 | | sage: Compositions(4, min_part=2).list() |
712 | | [[2, 2], [4]] |
713 | | sage: Compositions(4, outer=[3,1,2]).list() |
714 | | [[1, 1, 2], [2, 1, 1], [3, 1]] |
715 | | sage: Compositions(4, outer=[1,'inf',1]).list() |
716 | | [[1, 2, 1], [1, 3]] |
717 | | sage: Compositions(4, inner=[1,1,1]).list() |
718 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1]] |
719 | | sage: Compositions(4, min_slope=0).list() |
720 | | [[1, 1, 1, 1], [1, 1, 2], [1, 3], [2, 2], [4]] |
721 | | sage: Compositions(4, min_slope=-1, max_slope=1).list() |
722 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2], [4]] |
723 | | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list() |
724 | | [[1, 1, 1, 2], |
725 | | [1, 1, 2, 1], |
726 | | [1, 2, 1, 1], |
727 | | [1, 2, 2], |
728 | | [2, 1, 1, 1], |
729 | | [2, 1, 2], |
730 | | [2, 2, 1], |
731 | | [2, 3], |
732 | | [3, 1, 1], |
733 | | [3, 2]] |
734 | | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() |
735 | | [[1, 2, 2], [2, 1, 2], [2, 2, 1], [2, 3]] |
736 | | """ |
737 | | n = self.n |
738 | | |
739 | | if n == 0: |
740 | | return [Composition_class([])] |
741 | | |
742 | | result = [] |
743 | | for i in range(1,n+1): |
744 | | result += map(lambda x: [i]+x[:], Compositions_constraints(n-i).list()) |
745 | | |
746 | | if self.constraints: |
747 | | result = misc.check_integer_list_constraints(result, **self.constraints) |
748 | | |
749 | | result = [Composition_class(r) for r in result] |
750 | | |
751 | | return result |
752 | | |
753 | | |
754 | | |
| 880 | # Those belong to the Compositino class |