4 | | A composition c of a nonnegative integer n is a list of positive |
5 | | integers with total sum n. |
6 | | |
7 | | EXAMPLES: There are 8 compositions of 4. |
8 | | |
9 | | :: |
10 | | |
11 | | sage: Compositions(4).cardinality() |
12 | | 8 |
13 | | |
14 | | Here is the list of them:: |
15 | | |
16 | | sage: Compositions(4).list() |
17 | | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] |
18 | | |
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. |
151 | | |
152 | | AUTHORS: |
153 | | |
154 | | - Mike Hansen |
155 | | |
156 | | - MuPAD-Combinat developers (for algorithms and design inspiration) |
| 4 | A compositions `c` of a nonnegative integer `n` is a list of positive integers |
| 5 | (the *parts* of the compositions) with total sum `n`. |
| 131 | |
| 132 | def __add__(self, other): |
| 133 | """ |
| 134 | Returns the concatenation of two compositions. |
| 135 | |
| 136 | EXAMPLES:: |
| 137 | |
| 138 | sage: Composition([1, 1, 3]) + Composition([4, 1, 2]) |
| 139 | [1, 1, 3, 4, 1, 2] |
| 140 | |
| 141 | TESTS:: |
| 142 | |
| 143 | sage: Composition([]) + Composition([]) == Composition([]) |
| 144 | True |
| 145 | """ |
| 146 | return Composition(list(self)+list(other)) |
| 147 | |
| 148 | def size(self): |
| 149 | """ |
| 150 | Returns the size of the composition, that is the sum of its parts. |
| 151 | |
| 152 | EXAMPLES:: |
| 153 | |
| 154 | sage: Composition([7,1,3]).size() |
| 155 | 11 |
| 156 | """ |
| 157 | return sum(self) |
| 158 | |
| 159 | @staticmethod |
| 160 | def sum(compositions): |
| 161 | """ |
| 162 | INPUT: |
| 163 | |
| 164 | - ``compositions``: a list (or iterable) of compositions |
| 165 | |
| 166 | Returns the concatenation of the given compositions |
| 167 | |
| 168 | EXAMPLES:: |
| 169 | |
| 170 | sage: sage.combinat.composition.Composition_class.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])]) |
| 171 | [1, 1, 3, 4, 1, 2, 3, 1] |
| 172 | |
| 173 | Any iterable can be provided as input:: |
| 174 | |
| 175 | sage: sage.combinat.composition.Composition_class.sum([Composition([i,i]) for i in [4,1,3]]) |
| 176 | [4, 4, 1, 1, 3, 3] |
| 177 | |
| 178 | Empty inputs are handled gracefuly:: |
| 179 | |
| 180 | sage: sage.combinat.composition.Composition_class.sum([]) == Composition([]) |
| 181 | True |
| 182 | """ |
| 183 | return sum(compositions, Composition([])) |
| 184 | |
| 185 | def finer(self): |
| 186 | """ |
| 187 | Returns the set of compositions which are finer than self |
| 188 | |
| 189 | EXAMPLES:: |
| 190 | |
| 191 | sage: C = Composition([3,2]).finer() |
| 192 | sage: C.cardinality() |
| 193 | 8 |
| 194 | sage: list(C) |
| 195 | [[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]] |
| 196 | """ |
| 197 | return CartesianProduct(*[Compositions(i) for i in self]).map(Composition_class.sum) |
| 198 | |
| 234 | def fatten(self, grouping): |
| 235 | """ |
| 236 | INPUT: |
| 237 | |
| 238 | - ``grouping`` - a composition whose sum is the length of self |
| 239 | |
| 240 | Returns the composition fatter than self, obtained by grouping |
| 241 | together consecutive parts according to grouping. |
| 242 | |
| 243 | EXAMPLES: |
| 244 | |
| 245 | Let us start with the composition:: |
| 246 | |
| 247 | sage: c = Composition([4,5,2,7,1]) |
| 248 | |
| 249 | With `grouping = (1,\dots,1)`, `c` is left unchanged:: |
| 250 | |
| 251 | sage: c.fatten(Composition([1,1,1,1,1])) |
| 252 | [4, 5, 2, 7, 1] |
| 253 | |
| 254 | With `grouping = (5)`, this yields the coarser composition above `c`:: |
| 255 | |
| 256 | sage: c.fatten(Composition([5])) |
| 257 | [19] |
| 258 | |
| 259 | Other values for `grouping` yield (all the) other compositions coarser |
| 260 | to `c`:: |
| 261 | |
| 262 | sage: c.fatten(Composition([2,1,2])) |
| 263 | [9, 2, 8] |
| 264 | sage: c.fatten(Composition([3,1,1])) |
| 265 | [11, 7, 1] |
| 266 | |
| 267 | TESTS:: |
| 268 | |
| 269 | sage: Composition([]).fatten(Composition([])) |
| 270 | [] |
| 271 | sage: c.fatten(Composition([3,1,1])).__class__ == c.__class__ |
| 272 | True |
| 273 | """ |
| 274 | result = [None] * len(grouping) |
| 275 | j = 0 |
| 276 | for i in range(len(grouping)): |
| 277 | result[i] = sum(self[j:j+grouping[i]]) |
| 278 | j += grouping[i] |
| 279 | return Composition_class(result) |
| 280 | |
| 281 | def fatter(self): |
| 282 | """ |
| 283 | Returns the set of compositions which are fatter than self |
| 284 | |
| 285 | Complexity for generation: O(size(c)) memory, O(size(result)) time |
| 286 | |
| 287 | EXAMPLES:: |
| 288 | |
| 289 | sage: C = Composition([4,5,2]).fatter() |
| 290 | sage: C.cardinality() |
| 291 | 4 |
| 292 | sage: list(C) |
| 293 | [[4, 5, 2], [4, 7], [9, 2], [11]] |
| 294 | |
| 295 | Some extreme cases:: |
| 296 | |
| 297 | sage: list(Composition([5]).fatter()) |
| 298 | [[5]] |
| 299 | sage: list(Composition([]).fatter()) |
| 300 | [[]] |
| 301 | sage: list(Composition([1,1,1,1]).fatter()) == list(Compositions(4)) |
| 302 | True |
| 303 | """ |
| 304 | |
| 305 | return Compositions(len(self)).map(self.fatten) |
| 306 | |
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 | | :: |
| 450 | r""" |
| 451 | Sets of integer Compositions |
| 452 | |
| 453 | A composition `c` of a nonnegative integer `n` is a list of |
| 454 | positive integers with total sum `n`. |
| 455 | |
| 456 | See also: `Composition`, `Partitions`, `IntegerVectors` |
| 457 | |
| 458 | EXAMPLES: |
| 459 | |
| 460 | There are 8 compositions of 4:: |
| 461 | |
| 462 | sage: Compositions(4).cardinality() |
| 463 | 8 |
| 464 | |
| 465 | Here is the list of them:: |
| 466 | |
| 467 | sage: list(Compositions(4)) |
| 468 | [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] |
| 469 | |
| 470 | You can use the .first() method to get the 'first' composition of |
| 471 | a number:: |
| 472 | |
| 473 | sage: Compositions(4).first() |
| 474 | [1, 1, 1, 1] |
| 475 | |
| 476 | You can also calculate the 'next' composition given the current |
| 477 | one:: |
| 478 | |
| 479 | sage: Compositions(4).next([1,1,2]) |
| 480 | [1, 2, 1] |
| 481 | |
| 482 | |
| 483 | |
| 484 | If `n` is not specified, this returns the combinatorial class of |
| 485 | all (non-negative) integer compositions:: |
| 504 | |
| 505 | The following examples shows how to test whether or not an object |
| 506 | is a composition:: |
| 507 | |
| 508 | sage: [3,4] in Compositions() |
| 509 | True |
| 510 | sage: [3,4] in Compositions(7) |
| 511 | True |
| 512 | sage: [3,4] in Compositions(5) |
| 513 | False |
| 514 | |
| 515 | Similarly, one can check whether or not an object is a composition |
| 516 | which satisfies further constraints:: |
| 517 | |
| 518 | sage: [4,2] in Compositions(6, inner=[2,2]) |
| 519 | True |
| 520 | sage: [4,2] in Compositions(6, inner=[2,3]) |
| 521 | False |
| 522 | sage: [4,1] in Compositions(5, inner=[2,1], max_slope = 0) |
| 523 | True |
| 524 | |
| 525 | Note that the given constraints should be compatible:: |
| 526 | |
| 527 | sage: [4,2] in Compositions(6, inner=[2,2], min_part=3) # |
| 528 | True |
| 529 | |
| 530 | The options length, min_length, and max_length can be used to set |
| 531 | length constraints on the compositions. For example, the |
| 532 | compositions of 4 of length equal to, at least, and at most 2 are |
| 533 | given by:: |
| 534 | |
| 535 | sage: Compositions(4, length=2).list() |
| 536 | [[3, 1], [2, 2], [1, 3]] |
| 537 | sage: Compositions(4, min_length=2).list() |
| 538 | [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 539 | sage: Compositions(4, max_length=2).list() |
| 540 | [[4], [3, 1], [2, 2], [1, 3]] |
| 541 | |
| 542 | Setting both min_length and max_length to the same value is |
| 543 | equivalent to setting length to this value:: |
| 544 | |
| 545 | sage: Compositions(4, min_length=2, max_length=2).list() |
| 546 | [[3, 1], [2, 2], [1, 3]] |
| 547 | |
| 548 | The options inner and outer can be used to set part-by-part |
| 549 | containment constraints. The list of compositions of 4 bounded |
| 550 | above by [3,1,2] is given by:: |
| 551 | |
| 552 | sage: list(Compositions(4, outer=[3,1,2])) |
| 553 | [[3, 1], [2, 1, 1], [1, 1, 2]] |
| 554 | |
| 555 | Outer sets max_length to the length of its argument. Moreover, the |
| 556 | parts of outer may be infinite to clear the constraint on specific |
| 557 | parts. This is the list of compositions of 4 of length at most 3 |
| 558 | such that the first and third parts are at most 1:: |
| 559 | |
| 560 | sage: list(Compositions(4, outer=[1,oo,1])) |
| 561 | [[1, 3], [1, 2, 1]] |
| 562 | |
| 563 | This is the list of compositions of 4 bounded below by [1,1,1]:: |
| 564 | |
| 565 | sage: list(Compositions(4, inner=[1,1,1])) |
| 566 | [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 567 | |
| 568 | The options min_slope and max_slope can be used to set constraints |
| 569 | on the slope, that is the difference `p[i+1]-p[i]` of two |
| 570 | consecutive parts. The following is the list of weakly increasing |
| 571 | compositions of 4:: |
| 572 | |
| 573 | sage: Compositions(4, min_slope=0).list() |
| 574 | [[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, |
| 576 | Here are the weakly decreasing ones:: |
| 577 | |
| 578 | sage: Compositions(4, max_slope=0).list() |
| 579 | [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] |
| 580 | |
| 581 | |
| 582 | The following is the list of compositions of 4 such that two |
| 583 | consecutive parts differ by at most one:: |
| 584 | |
| 585 | sage: Compositions(4, min_slope=-1, max_slope=1).list() |
| 586 | [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 587 | |
| 588 | The constraints can be combined together in all reasonable ways. |
| 589 | This is the list of compositions of 5 of length between 2 and 4 |
| 590 | such that the difference between consecutive parts is between -2 |
| 591 | and 1:: |
| 592 | |
| 593 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list() |
| 594 | [[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]] |
| 595 | |
| 596 | We can do the same thing with an outer constraint:: |
| 597 | |
| 598 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() |
| 599 | [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]] |
| 600 | |
| 601 | However, providing incoherent constraints may yield strange |
| 602 | results. It is up to the user to ensure that the inner and outer |
| 603 | compositions themselves satisfy the parts and slope constraints. |
| 604 | |
| 605 | Note that if you specify min_part=0, then the objects produced may |
| 606 | have parts equal to zero. This violates the internal assumptions |
| 607 | that the Composition class makes. Use at your own risk, or |
| 608 | preferably consider using `IntegerVectors` instead:: |
| 609 | |
| 610 | sage: list(Compositions(2, length=3, min_part=0)) |
| 611 | 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! |
| 612 | [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] |
| 613 | |
| 614 | sage: list(IntegerVectors(2, 3)) |
| 615 | [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] |
| 616 | |
| 617 | The generation algorithm is constant amortized time, and handled |
| 618 | by the generic tool `IntegerListsLex`. |
| 619 | |
| 620 | AUTHORS: |
| 621 | |
| 622 | - Mike Hansen, Nicolas M. Thiery |
| 623 | |
| 624 | - MuPAD-Combinat developers (for algorithms and design inspiration) |
| 625 | |
| 626 | 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]] |
| 635 | |
| 636 | sage: [2, 1] in Compositions(3, length=2) |
| 637 | True |
| 638 | sage: [2,1,2] in Compositions(5, min_part=1) |
| 639 | True |
| 640 | sage: [2,1,2] in Compositions(5, min_part=2) |
| 641 | False |
| 642 | |
| 643 | sage: Compositions(4, length=2).cardinality() |
| 644 | 3 |
| 645 | sage: Compositions(4, min_length=2).cardinality() |
| 646 | 7 |
| 647 | sage: Compositions(4, max_length=2).cardinality() |
| 648 | 4 |
| 649 | sage: Compositions(4, max_part=2).cardinality() |
| 650 | 5 |
| 651 | sage: Compositions(4, min_part=2).cardinality() |
| 652 | 2 |
| 653 | sage: Compositions(4, outer=[3,1,2]).cardinality() |
| 654 | 3 |
| 655 | |
| 656 | sage: Compositions(4, length=2).list() |
| 657 | [[3, 1], [2, 2], [1, 3]] |
| 658 | sage: Compositions(4, min_length=2).list() |
| 659 | [[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 660 | sage: Compositions(4, max_length=2).list() |
| 661 | [[4], [3, 1], [2, 2], [1, 3]] |
| 662 | sage: Compositions(4, max_part=2).list() |
| 663 | [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 664 | sage: Compositions(4, min_part=2).list() |
| 665 | [[4], [2, 2]] |
| 666 | sage: Compositions(4, outer=[3,1,2]).list() |
| 667 | [[3, 1], [2, 1, 1], [1, 1, 2]] |
| 668 | sage: Compositions(4, outer=[1,oo,1]).list() |
| 669 | [[1, 3], [1, 2, 1]] |
| 670 | sage: Compositions(4, inner=[1,1,1]).list() |
| 671 | [[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 672 | sage: Compositions(4, min_slope=0).list() |
| 673 | [[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]] |
| 674 | sage: Compositions(4, min_slope=-1, max_slope=1).list() |
| 675 | [[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 676 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list() |
| 677 | [[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]] |
| 678 | sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list() |
| 679 | [[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]] |
496 | | return Compositions_n(n) |
| 691 | # FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute |
| 692 | kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] )) |
| 693 | kwargs['element_constructor'] = Composition_class |
| 694 | if 'min_part' not in kwargs: |
| 695 | kwargs['min_part'] = 1 |
| 696 | elif kwargs['min_part'] == 0: |
| 697 | from warnings import warn |
| 698 | 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) |
| 699 | |
| 700 | if 'outer' in kwargs: |
| 701 | kwargs['ceiling'] = kwargs['outer'] |
| 702 | if 'max_length' in kwargs: |
| 703 | kwargs['max_length'] = min( len(kwargs['outer']), kwargs['max_length']) |
| 704 | else: |
| 705 | kwargs['max_length'] = len(kwargs['outer']) |
| 706 | del kwargs['outer'] |
| 707 | |
| 708 | if 'inner' in kwargs: |
| 709 | inner = kwargs['inner'] |
| 710 | kwargs['floor'] = inner |
| 711 | del kwargs['inner'] |
| 712 | # Should this be handled by integer lists lex? |
| 713 | if 'min_length' in kwargs: |
| 714 | kwargs['min_length'] = max( len(inner), kwargs['min_length']) |
| 715 | else: |
| 716 | kwargs['min_length'] = len(inner) |
| 717 | return IntegerListsLex(n, **kwargs) |
| 718 | |
| 719 | |
| 720 | # Allows to unpickle old constrained Compositions_constraints objects. |
| 721 | class Compositions_constraints(IntegerListsLex): |
| 722 | def __setstate__(self, data): |
| 723 | """ |
| 724 | TESTS:: |
| 725 | |
| 726 | # dumps(Compositions(4, max_part=2)) |
| 727 | sage: pickle = 'x\x9ck`J.NLO\xd5K\xce\xcfM\xca\xccK,\x011\n\xf2\x8b3K2\xf3\xf3\xb8\x9c\x11\xec\xe2\xf8d QR\x94\x98\x99WR\xccU\xc8\xa8\xd9X\xc8T[\xc8\xac\x11\xca\x8d$^\xc8R[\xc8\x1a\xca\x91\x9bX\x11_\x90XTR\xc8\x061\xbb(3/\xbdX\x0f\xa8 5=\xb5\x88+71;5\x1e\xc6)d\x0fe4j\r*\xe4(\x0ee\xcc\xcb\x00rL\x80\x1c\xce\xd2$=\x00\xbd\xea5\xb2' |
| 728 | sage: sp = loads(pickle); sp |
| 729 | Integer lists of sum 4 satisfying certain constraints |
| 730 | sage: sp.list() |
| 731 | [[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] |
| 732 | """ |
| 733 | n = data['n'] |
| 734 | self.__class__ = IntegerListsLex |
| 735 | constraints = { |
| 736 | 'min_part' : 1, |
| 737 | 'element_constructor' : Composition_class} |
| 738 | constraints.update(data['constraints']) |
| 739 | 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 | | |
| 874 | # Those belong to the Compositino class |