Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/combinat/composition.py
8815 views
1
r"""
2
Integer compositions
3
4
A composition `c` of a nonnegative integer `n` is a list of positive integers
5
(the *parts* of the composition) with total sum `n`.
6
7
This module provides tools for manipulating compositions and enumerated
8
sets of compositions.
9
10
EXAMPLES::
11
12
sage: Composition([5, 3, 1, 3])
13
[5, 3, 1, 3]
14
sage: list(Compositions(4))
15
[[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
16
17
18
AUTHORS:
19
20
- Mike Hansen, Nicolas M. Thiery
21
- MuPAD-Combinat developers (algorithms and design inspiration)
22
- Travis Scrimshaw (2013-02-03): Removed ``CombinatorialClass``
23
"""
24
#*****************************************************************************
25
# Copyright (C) 2007 Mike Hansen <[email protected]>
26
# 2009 Nicolas M. Thiery <nthiery at users.sf.net>
27
#
28
# Distributed under the terms of the GNU General Public License (GPL)
29
# http://www.gnu.org/licenses/
30
#*****************************************************************************
31
32
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
33
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
34
from sage.structure.unique_representation import UniqueRepresentation
35
from sage.structure.parent import Parent
36
from sage.structure.element import Element
37
from sage.misc.classcall_metaclass import ClasscallMetaclass
38
from sage.misc.superseded import deprecated_function_alias
39
from sage.rings.all import ZZ
40
from combinat import CombinatorialObject
41
from cartesian_product import CartesianProduct
42
from integer_list import IntegerListsLex
43
import __builtin__
44
from sage.rings.integer import Integer
45
from sage.combinat.combinatorial_map import combinatorial_map
46
47
48
class Composition(CombinatorialObject, Element):
49
r"""
50
Integer compositions
51
52
A composition of a nonnegative integer `n` is a list
53
`(i_1, \ldots, i_k)` of positive integers with total sum `n`.
54
55
EXAMPLES:
56
57
The simplest way to create a composition is by specifying its
58
entries as a list, tuple (or other iterable)::
59
60
sage: Composition([3,1,2])
61
[3, 1, 2]
62
sage: Composition((3,1,2))
63
[3, 1, 2]
64
sage: Composition(i for i in range(2,5))
65
[2, 3, 4]
66
67
You can also create a composition from its code. The *code* of
68
a composition `(i_1, i_2, \ldots, i_k)` of `n` is a list of length `n`
69
that consists of a `1` followed by `i_1-1` zeros, then a `1` followed
70
by `i_2-1` zeros, and so on.
71
72
::
73
74
sage: Composition([4,1,2,3,5]).to_code()
75
[1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
76
sage: Composition(code=_)
77
[4, 1, 2, 3, 5]
78
sage: Composition([3,1,2,3,5]).to_code()
79
[1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
80
sage: Composition(code=_)
81
[3, 1, 2, 3, 5]
82
83
You can also create the composition of `n` corresponding to a subset of
84
`\{1, 2, \ldots, n-1\}` under the bijection that maps the composition
85
`(i_1, i_2, \ldots, i_k)` of `n` to the subset
86
`\{i_1, i_1 + i_2, i_1 + i_2 + i_3, \ldots, i_1 + \cdots + i_{k-1}\}`
87
(see :meth:`to_subset`)::
88
89
sage: Composition(from_subset=({1, 2, 4}, 5))
90
[1, 1, 2, 1]
91
sage: Composition([1, 1, 2, 1]).to_subset()
92
{1, 2, 4}
93
94
The following notation equivalently specifies the composition from the
95
set `\{i_1 - 1, i_1 + i_2 - 1, i_1 + i_2 + i_3 - 1, \dots, i_1 + \cdots
96
+ i_{k-1} - 1, n-1\}` or `\{i_1 - 1, i_1 + i_2 - 1, i_1 + i_2 + i_3
97
- 1, \dots, i_1 + \cdots + i_{k-1} - 1\}` and `n`. This provides
98
compatibility with Python's `0`-indexing.
99
100
::
101
102
sage: Composition(descents=[1,0,4,8,11])
103
[1, 1, 3, 4, 3]
104
sage: Composition(descents=[0,1,3,4])
105
[1, 1, 2, 1]
106
sage: Composition(descents=([0,1,3],5))
107
[1, 1, 2, 1]
108
sage: Composition(descents=({0,1,3},5))
109
[1, 1, 2, 1]
110
"""
111
__metaclass__ = ClasscallMetaclass
112
113
@staticmethod
114
def __classcall_private__(cls, co=None, descents=None, code=None, from_subset=None):
115
"""
116
This constructs a list from optional arguments and delegates the
117
construction of a :class:`Composition` to the ``element_class()`` call
118
of the appropriate parent.
119
120
EXAMPLES::
121
122
sage: Composition([3,2,1])
123
[3, 2, 1]
124
sage: Composition(from_subset=({1, 2, 4}, 5))
125
[1, 1, 2, 1]
126
sage: Composition(descents=[1,0,4,8,11])
127
[1, 1, 3, 4, 3]
128
sage: Composition([4,1,2,3,5]).to_code()
129
[1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
130
sage: Composition(code=_)
131
[4, 1, 2, 3, 5]
132
"""
133
if descents is not None:
134
if isinstance(descents, tuple):
135
return Compositions().from_descents(descents[0], nps=descents[1])
136
else:
137
return Compositions().from_descents(descents)
138
elif code is not None:
139
return Compositions().from_code(code)
140
elif from_subset is not None:
141
return Compositions().from_subset(*from_subset)
142
elif isinstance(co, Composition):
143
return co
144
else:
145
return Compositions()(list(co))
146
147
def __init__(self, parent, lst):
148
"""
149
Initialize ``self``.
150
151
EXAMPLES::
152
153
sage: C = Composition([3,1,2])
154
sage: TestSuite(C).run()
155
"""
156
CombinatorialObject.__init__(self, lst)
157
Element.__init__(self, parent)
158
159
def _ascii_art_(self):
160
"""
161
TESTS::
162
163
sage: ascii_art(Compositions(4).list())
164
[ * ]
165
[ * ** * * ]
166
[ * * ** *** * ** * ]
167
[ *, * , * , * , **, ** , ***, **** ]
168
sage: Partitions.global_options(diagram_str='#', convention="French")
169
sage: ascii_art(Compositions(4).list())
170
[ # ]
171
[ # # # ## ]
172
[ # # ## # # ## ### ]
173
[ #, ##, #, ###, #, ##, #, #### ]
174
"""
175
from sage.misc.ascii_art import ascii_art
176
return ascii_art(self.to_skew_partition())
177
178
def __setstate__(self, state):
179
r"""
180
In order to maintain backwards compatibility and be able to unpickle a
181
old pickle from ``Composition_class`` we have to override the default
182
``__setstate__``.
183
184
EXAMPLES::
185
186
sage: loads("x\x9ck`J.NLO\xd5K\xce\xcfM\xca\xccK,\x011\n\xf2\x8b3K2\xf3\xf3\xb8\x9c\x11\xec\xf8\xe4\x9c\xc4\xe2b\xaeBF\xcd\xc6B\xa6\xdaBf\x8dP\xd6\xf8\x8c\xc4\xe2\x8cB\x16? +'\xb3\xb8\xa4\x905\xb6\x90M\x03bZQf^z\xb1^f^Ijzj\x11Wnbvj<\x8cS\xc8\x1e\xcah\xd8\x1aT\xc8\x91\x01d\x18\x01\x19\x9c\x19P\x11\xae\xd4\xd2$=\x00eW0g")
187
[1, 2, 1]
188
sage: loads(dumps( Composition([1,2,1]) )) # indirect doctest
189
[1, 2, 1]
190
"""
191
if isinstance(state, dict): # for old pickles from Composition_class
192
self._set_parent(Compositions())
193
self.__dict__ = state
194
else:
195
self._set_parent(state[0])
196
self.__dict__ = state[1]
197
198
@combinatorial_map(order=2, name='conjugate')
199
def conjugate(self):
200
r"""
201
Return the conjugate of the composition ``self``.
202
203
The conjugate of a composition `I` is defined as the
204
complement (see :meth:`complement`) of the reverse composition
205
(see :meth:`reversed`) of `I`.
206
207
An equivalent definition of the conjugate goes by saying that
208
the ribbon shape of the conjugate of a composition `I` is the
209
conjugate of the ribbon shape of `I`. (The ribbon shape of a
210
composition is returned by :meth:`to_skew_partition`.)
211
212
This implementation uses the algorithm from mupad-combinat.
213
214
EXAMPLES::
215
216
sage: Composition([1, 1, 3, 1, 2, 1, 3]).conjugate()
217
[1, 1, 3, 3, 1, 3]
218
219
The ribbon shape of the conjugate of `I` is the conjugate of
220
the ribbon shape of `I`::
221
222
sage: all( I.conjugate().to_skew_partition()
223
....: == I.to_skew_partition().conjugate()
224
....: for I in Compositions(4) )
225
True
226
227
TESTS::
228
229
sage: parent(list(Compositions(1))[0].conjugate())
230
Compositions of 1
231
sage: parent(list(Compositions(0))[0].conjugate())
232
Compositions of 0
233
"""
234
comp = self
235
if comp == []:
236
return self
237
n = len(comp)
238
coofcp = [sum(comp[:j])-j+1 for j in range(1,n+1)]
239
240
cocjg = []
241
for i in range(n-1):
242
cocjg += [i+1 for _ in range(0, (coofcp[n-i-1]-coofcp[n-i-2]))]
243
cocjg += [n for j in range(coofcp[0])]
244
245
return self.parent()([cocjg[0]] + [cocjg[i]-cocjg[i-1]+1 for i in range(1,len(cocjg))])
246
247
@combinatorial_map(order=2, name='reversed')
248
def reversed(self):
249
r"""
250
Return the reverse composition of ``self``.
251
252
The reverse composition of a composition `(i_1, i_2, \ldots, i_k)`
253
is defined as the composition `(i_k, i_{k-1}, \ldots, i_1)`.
254
255
EXAMPLES::
256
257
sage: Composition([1, 1, 3, 1, 2, 1, 3]).reversed()
258
[3, 1, 2, 1, 3, 1, 1]
259
"""
260
return self.parent()(reversed(self))
261
262
@combinatorial_map(order=2, name='complement')
263
def complement(self):
264
r"""
265
Return the complement of the composition ``self``.
266
267
The complement of a composition `I` is defined as follows:
268
269
If `I` is the empty composition, then the complement is the empty
270
composition as well. Otherwise, let `S` be the descent set of `I`
271
(that is, the subset
272
`\{ i_1, i_1 + i_2, \ldots, i_1 + i_2 + \cdots + i_{k-1} \}`
273
of `\{ 1, 2, \ldots, |I|-1 \}`, where `I` is written as
274
`(i_1, i_2, \ldots, i_k)`). Then, the complement of `I` is
275
defined as the composition of size `|I|` whose descent set is
276
`\{ 1, 2, \ldots, |I|-1 \} \setminus S`.
277
278
The complement of a composition `I` also is the reverse
279
composition (:meth:`reversed`) of the conjugate
280
(:meth:`conjugate`) of `I`.
281
282
EXAMPLES::
283
284
sage: Composition([1, 1, 3, 1, 2, 1, 3]).conjugate()
285
[1, 1, 3, 3, 1, 3]
286
sage: Composition([1, 1, 3, 1, 2, 1, 3]).complement()
287
[3, 1, 3, 3, 1, 1]
288
"""
289
return self.conjugate().reversed()
290
291
def __add__(self, other):
292
"""
293
Return the concatenation of two compositions.
294
295
EXAMPLES::
296
297
sage: Composition([1, 1, 3]) + Composition([4, 1, 2])
298
[1, 1, 3, 4, 1, 2]
299
300
TESTS::
301
302
sage: Composition([]) + Composition([]) == Composition([])
303
True
304
"""
305
return Compositions()(list(self)+list(other))
306
307
def size(self):
308
"""
309
Return the size of ``self``, that is the sum of its parts.
310
311
EXAMPLES::
312
313
sage: Composition([7,1,3]).size()
314
11
315
"""
316
return sum(self)
317
318
@staticmethod
319
def sum(compositions):
320
"""
321
Return the concatenation of the given compositions.
322
323
INPUT:
324
325
- ``compositions`` -- a list (or iterable) of compositions
326
327
EXAMPLES::
328
329
sage: Composition.sum([Composition([1, 1, 3]), Composition([4, 1, 2]), Composition([3,1])])
330
[1, 1, 3, 4, 1, 2, 3, 1]
331
332
Any iterable can be provided as input::
333
334
sage: Composition.sum([Composition([i,i]) for i in [4,1,3]])
335
[4, 4, 1, 1, 3, 3]
336
337
Empty inputs are handled gracefully::
338
339
sage: Composition.sum([]) == Composition([])
340
True
341
"""
342
return sum(compositions, Compositions()([]))
343
344
def near_concatenation(self, other):
345
r"""
346
Return the near-concatenation of two nonempty compositions
347
``self`` and ``other``.
348
349
The near-concatenation `I \odot J` of two nonempty compositions
350
`I` and `J` is defined as the composition
351
`(i_1, i_2, \ldots , i_{n-1}, i_n + j_1, j_2, j_3, \ldots , j_m)`,
352
where `(i_1, i_2, \ldots , i_n) = I` and
353
`(j_1, j_2, \ldots , j_m) = J`.
354
355
This method returns ``None`` if one of the two input
356
compositions is empty.
357
358
EXAMPLES::
359
360
sage: Composition([1, 1, 3]).near_concatenation(Composition([4, 1, 2]))
361
[1, 1, 7, 1, 2]
362
sage: Composition([6]).near_concatenation(Composition([1, 5]))
363
[7, 5]
364
sage: Composition([1, 5]).near_concatenation(Composition([6]))
365
[1, 11]
366
367
TESTS::
368
369
sage: Composition([]).near_concatenation(Composition([]))
370
<BLANKLINE>
371
sage: Composition([]).near_concatenation(Composition([2, 1]))
372
<BLANKLINE>
373
sage: Composition([3, 2]).near_concatenation(Composition([]))
374
<BLANKLINE>
375
"""
376
if len(self) == 0 or len(other) == 0:
377
return None
378
return Compositions()(list(self)[:-1] + [self[-1] + other[0]] + list(other)[1:])
379
380
def ribbon_decomposition(self, other, check=True):
381
r"""
382
Return a pair describing the ribbon decomposition of a composition
383
``self`` with respect to a composition ``other`` of the same size.
384
385
If `I` and `J` are two compositions of the same nonzero size, then
386
the ribbon decomposition of `I` with respect to `J` is defined as
387
follows: Write `I` and `J` as `I = (i_1, i_2, \ldots , i_n)` and
388
`J = (j_1, j_2, \ldots , j_m)`. Then, the equality
389
`I = I_1 \bullet I_2 \bullet \ldots \bullet I_m` holds for a
390
unique `m`-tuple `(I_1, I_2, \ldots , I_m)` of compositions such
391
that each `I_k` has size `j_k` and for a unique choice of `m-1`
392
signs `\bullet` each of which is either the concatenation sign
393
`\cdot` or the near-concatenation sign `\odot` (see
394
:meth:`__add__` and :meth:`near_concatenation` for the definitions
395
of these two signs). This `m`-tuple and this choice of signs
396
together are said to form the ribbon decomposition of `I` with
397
respect to `J`. If `I` and `J` are empty, then the same definition
398
applies, except that there are `0` rather than `m-1` signs.
399
400
See Section 4.8 of [NCSF1]_.
401
402
INPUT:
403
404
- ``other`` -- composition of same size as ``self``
405
406
- ``check`` -- (default: ``True``) a Boolean determining whether
407
to check the input compositions for having the same size
408
409
OUTPUT:
410
411
- a pair ``(u, v)``, where ``u`` is a tuple of compositions
412
(corresponding to the `m`-tuple `(I_1, I_2, \ldots , I_m)` in
413
the above definition), and ``v`` is a tuple of `0`s and `1`s
414
(encoding the choice of signs `\bullet` in the above definition,
415
with a `0` standing for `\cdot` and a `1` standing for `\odot`).
416
417
EXAMPLES::
418
419
sage: Composition([3, 1, 1, 3, 1]).ribbon_decomposition([4, 3, 2])
420
(([3, 1], [1, 2], [1, 1]), (0, 1))
421
sage: Composition([9, 6]).ribbon_decomposition([1, 3, 6, 3, 2])
422
(([1], [3], [5, 1], [3], [2]), (1, 1, 1, 1))
423
sage: Composition([9, 6]).ribbon_decomposition([1, 3, 5, 1, 3, 2])
424
(([1], [3], [5], [1], [3], [2]), (1, 1, 0, 1, 1))
425
sage: Composition([1, 1, 1, 1, 1]).ribbon_decomposition([3, 2])
426
(([1, 1, 1], [1, 1]), (0,))
427
sage: Composition([4, 2]).ribbon_decomposition([6])
428
(([4, 2],), ())
429
sage: Composition([]).ribbon_decomposition([])
430
((), ())
431
432
Let us check that the defining property
433
`I = I_1 \bullet I_2 \bullet \ldots \bullet I_m` is satisfied::
434
435
sage: def compose_back(u, v):
436
....: comp = u[0]
437
....: r = len(v)
438
....: if len(u) != r + 1:
439
....: raise ValueError("something is wrong")
440
....: for i in range(r):
441
....: if v[i] == 0:
442
....: comp += u[i + 1]
443
....: else:
444
....: comp = comp.near_concatenation(u[i + 1])
445
....: return comp
446
sage: all( all( all( compose_back(*(I.ribbon_decomposition(J))) == I
447
....: for J in Compositions(n) )
448
....: for I in Compositions(n) )
449
....: for n in range(1, 5) )
450
True
451
452
TESTS::
453
454
sage: Composition([3, 1, 1, 3, 1]).ribbon_decomposition([4, 3, 1])
455
Traceback (most recent call last):
456
...
457
ValueError: [3, 1, 1, 3, 1] is not the same size as [4, 3, 1]
458
459
AUTHORS:
460
461
- Darij Grinberg (2013-08-29)
462
"""
463
# Speaking in terms of the definition in the docstring, we have
464
# I = self and J = other.
465
466
if check and (sum(self) != sum(other)):
467
raise ValueError("{} is not the same size as {}".format(self, other))
468
469
factors = []
470
signs = []
471
472
I_iter = iter(self)
473
i = 0
474
for j in other:
475
current_factor = []
476
current_factor_size = 0
477
while True:
478
if i == 0:
479
try:
480
i = I_iter.next()
481
except StopIteration:
482
factors.append(Compositions()(current_factor))
483
return (tuple(factors), tuple(signs))
484
if current_factor_size + i <= j:
485
current_factor.append(i)
486
current_factor_size += i
487
i = 0
488
else:
489
if j == current_factor_size:
490
signs.append(0)
491
else:
492
current_factor.append(j - current_factor_size)
493
i -= j - current_factor_size
494
signs.append(1)
495
factors.append(Compositions()(current_factor))
496
break
497
498
return (tuple(factors), tuple(signs))
499
500
def join(self, other, check=True):
501
r"""
502
Return the join of ``self`` with a composition ``other`` of the
503
same size.
504
505
The join of two compositions `I` and `J` of size `n` is the
506
coarsest composition of `n` which refines each of `I` and `J`. It
507
can be described as the composition whose descent set is the
508
union of the descent sets of `I` and `J`. It is also the
509
concatenation of `I_1, I_2, \cdots , I_m`, where
510
`I = I_1 \bullet I_2 \bullet \ldots \bullet I_m` is the ribbon
511
decomposition of `I` with respect to `J` (see
512
:meth:`ribbon_decomposition`).
513
514
INPUT:
515
516
- ``other`` -- composition of same size as ``self``
517
518
- ``check`` -- (default: ``True``) a Boolean determining whether
519
to check the input compositions for having the same size
520
521
OUTPUT:
522
523
- the join of the compositions ``self`` and ``other``
524
525
EXAMPLES::
526
527
sage: Composition([3, 1, 1, 3, 1]).join([4, 3, 2])
528
[3, 1, 1, 2, 1, 1]
529
sage: Composition([9, 6]).join([1, 3, 6, 3, 2])
530
[1, 3, 5, 1, 3, 2]
531
sage: Composition([9, 6]).join([1, 3, 5, 1, 3, 2])
532
[1, 3, 5, 1, 3, 2]
533
sage: Composition([1, 1, 1, 1, 1]).join([3, 2])
534
[1, 1, 1, 1, 1]
535
sage: Composition([4, 2]).join([3, 3])
536
[3, 1, 2]
537
sage: Composition([]).join([])
538
[]
539
540
Let us verify on small examples that the join
541
of `I` and `J` refines both of `I` and `J`::
542
543
sage: all( all( I.join(J).is_finer(I) and
544
....: I.join(J).is_finer(J)
545
....: for J in Compositions(4) )
546
....: for I in Compositions(4) )
547
True
548
549
and is the coarsest composition to do so::
550
551
sage: all( all( all( K.is_finer(I.join(J))
552
....: for K in I.finer()
553
....: if K.is_finer(J) )
554
....: for J in Compositions(3) )
555
....: for I in Compositions(3) )
556
True
557
558
Let us check that the join of `I` and `J` is indeed the
559
conctenation of `I_1, I_2, \cdots , I_m`, where
560
`I = I_1 \bullet I_2 \bullet \ldots \bullet I_m` is the ribbon
561
decomposition of `I` with respect to `J`::
562
563
sage: all( all( Composition.sum(I.ribbon_decomposition(J)[0])
564
....: == I.join(J) for J in Compositions(4) )
565
....: for I in Compositions(4) )
566
True
567
568
Also, the descent set of the join of `I` and `J` is the
569
union of the descent sets of `I` and `J`::
570
571
sage: all( all( I.to_subset().union(J.to_subset())
572
....: == I.join(J).to_subset()
573
....: for J in Compositions(4) )
574
....: for I in Compositions(4) )
575
True
576
577
TESTS::
578
579
sage: Composition([3, 1, 1, 3, 1]).join([4, 3, 1])
580
Traceback (most recent call last):
581
...
582
ValueError: [3, 1, 1, 3, 1] is not the same size as [4, 3, 1]
583
584
.. SEEALSO::
585
586
:meth:`meet`, :meth:`ribbon_decomposition`
587
588
AUTHORS:
589
590
- Darij Grinberg (2013-09-05)
591
"""
592
# The following code is a slimmed down version of the
593
# ribbon_decomposition method. It is a lot faster than
594
# using to_subset() and from_subset, and also a lot
595
# faster than ribbon_decomposition.
596
597
# Speaking in terms of the definition in the docstring, we have
598
# I = self and J = other.
599
600
if check and (sum(self) != sum(other)):
601
raise ValueError("{} is not the same size as {}".format(self, other))
602
603
factors = []
604
605
I_iter = iter(self)
606
i = 0
607
for j in other:
608
current_factor_size = 0
609
while True:
610
if i == 0:
611
try:
612
i = I_iter.next()
613
except StopIteration:
614
return Compositions()(factors)
615
if current_factor_size + i <= j:
616
factors.append(i)
617
current_factor_size += i
618
i = 0
619
else:
620
if not j == current_factor_size:
621
factors.append(j - current_factor_size)
622
i -= j - current_factor_size
623
break
624
625
return Compositions()(factors)
626
627
sup = join
628
629
def meet(self, other, check=True):
630
r"""
631
Return the meet of ``self`` with a composition ``other`` of the
632
same size.
633
634
The meet of two compositions `I` and `J` of size `n` is the
635
finest composition of `n` which is coarser than each of `I` and
636
`J`. It can be described as the composition whose descent set is
637
the intersection of the descent sets of `I` and `J`.
638
639
INPUT:
640
641
- ``other`` -- composition of same size as ``self``
642
643
- ``check`` -- (default: ``True``) a Boolean determining whether
644
to check the input compositions for having the same size
645
646
OUTPUT:
647
648
- the meet of the compositions ``self`` and ``other``
649
650
EXAMPLES::
651
652
sage: Composition([3, 1, 1, 3, 1]).meet([4, 3, 2])
653
[4, 5]
654
sage: Composition([9, 6]).meet([1, 3, 6, 3, 2])
655
[15]
656
sage: Composition([9, 6]).meet([1, 3, 5, 1, 3, 2])
657
[9, 6]
658
sage: Composition([1, 1, 1, 1, 1]).meet([3, 2])
659
[3, 2]
660
sage: Composition([4, 2]).meet([3, 3])
661
[6]
662
sage: Composition([]).meet([])
663
[]
664
sage: Composition([1]).meet([1])
665
[1]
666
667
Let us verify on small examples that the meet
668
of `I` and `J` is coarser than both of `I` and `J`::
669
670
sage: all( all( I.is_finer(I.meet(J)) and
671
....: J.is_finer(I.meet(J))
672
....: for J in Compositions(4) )
673
....: for I in Compositions(4) )
674
True
675
676
and is the finest composition to do so::
677
678
sage: all( all( all( I.meet(J).is_finer(K)
679
....: for K in I.fatter()
680
....: if J.is_finer(K) )
681
....: for J in Compositions(3) )
682
....: for I in Compositions(3) )
683
True
684
685
The descent set of the meet of `I` and `J` is the
686
intersection of the descent sets of `I` and `J`::
687
688
sage: def test_meet(n):
689
....: return all( all( I.to_subset().intersection(J.to_subset())
690
....: == I.meet(J).to_subset()
691
....: for J in Compositions(n) )
692
....: for I in Compositions(n) )
693
sage: all( test_meet(n) for n in range(1, 5) )
694
True
695
sage: all( test_meet(n) for n in range(5, 9) ) # long time
696
True
697
698
TESTS::
699
700
sage: Composition([3, 1, 1, 3, 1]).meet([4, 3, 1])
701
Traceback (most recent call last):
702
...
703
ValueError: [3, 1, 1, 3, 1] is not the same size as [4, 3, 1]
704
705
.. SEEALSO::
706
707
:meth:`join`
708
709
AUTHORS:
710
711
- Darij Grinberg (2013-09-05)
712
"""
713
# The following code is much faster than using to_subset()
714
# and from_subset.
715
716
# Speaking in terms of the definition in the docstring, we have
717
# I = self and J = other.
718
719
if check and (sum(self) != sum(other)):
720
raise ValueError("{} is not the same size as {}".format(self, other))
721
722
factors = []
723
current_part = 0
724
725
I_iter = iter(self)
726
i = 0
727
for j in other:
728
current_factor_size = 0
729
while True:
730
if i == 0:
731
try:
732
i = I_iter.next()
733
except StopIteration:
734
factors.append(current_part)
735
return Compositions()(factors)
736
if current_factor_size + i <= j:
737
current_part += i
738
current_factor_size += i
739
i = 0
740
else:
741
if j == current_factor_size:
742
factors.append(current_part)
743
current_part = 0
744
else:
745
i -= j - current_factor_size
746
current_part += j - current_factor_size
747
break
748
749
return Compositions()(factors)
750
751
inf = meet
752
753
def finer(self):
754
"""
755
Return the set of compositions which are finer than ``self``.
756
757
EXAMPLES::
758
759
sage: C = Composition([3,2]).finer()
760
sage: C.cardinality()
761
8
762
sage: list(C)
763
[[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]]
764
"""
765
return CartesianProduct(*[Compositions(i) for i in self]).map(Composition.sum)
766
767
def is_finer(self, co2):
768
"""
769
Return ``True`` if the composition ``self`` is finer than the
770
composition ``co2``; otherwise, return ``False``.
771
772
EXAMPLES::
773
774
sage: Composition([4,1,2]).is_finer([3,1,3])
775
False
776
sage: Composition([3,1,3]).is_finer([4,1,2])
777
False
778
sage: Composition([1,2,2,1,1,2]).is_finer([5,1,3])
779
True
780
sage: Composition([2,2,2]).is_finer([4,2])
781
True
782
"""
783
co1 = self
784
if sum(co1) != sum(co2):
785
raise ValueError("compositions self (= %s) and co2 (= %s) must be of the same size"%(self, co2))
786
787
sum1 = 0
788
sum2 = 0
789
i1 = 0
790
for j2 in co2:
791
sum2 += j2
792
while sum1 < sum2:
793
sum1 += co1[i1]
794
i1 += 1
795
if sum1 > sum2:
796
return False
797
798
return True
799
800
def fatten(self, grouping):
801
r"""
802
Return the composition fatter than ``self``, obtained by grouping
803
together consecutive parts according to ``grouping``.
804
805
INPUT:
806
807
- ``grouping`` -- a composition whose sum is the length of ``self``
808
809
EXAMPLES:
810
811
Let us start with the composition::
812
813
sage: c = Composition([4,5,2,7,1])
814
815
With ``grouping`` equal to `(1, \ldots, 1)`, `c` is left unchanged::
816
817
sage: c.fatten(Composition([1,1,1,1,1]))
818
[4, 5, 2, 7, 1]
819
820
With ``grouping`` equal to `(\ell)` where `\ell` is the length of
821
`c`, this yields the coarsest composition above `c`::
822
823
sage: c.fatten(Composition([5]))
824
[19]
825
826
Other values for ``grouping`` yield (all the) other compositions
827
coarser than `c`::
828
829
sage: c.fatten(Composition([2,1,2]))
830
[9, 2, 8]
831
sage: c.fatten(Composition([3,1,1]))
832
[11, 7, 1]
833
834
TESTS::
835
836
sage: Composition([]).fatten(Composition([]))
837
[]
838
sage: c.fatten(Composition([3,1,1])).__class__ == c.__class__
839
True
840
"""
841
result = [None] * len(grouping)
842
j = 0
843
for i in range(len(grouping)):
844
result[i] = sum(self[j:j+grouping[i]])
845
j += grouping[i]
846
return Compositions()(result)
847
848
def fatter(self):
849
"""
850
Return the set of compositions which are fatter than ``self``.
851
852
Complexity for generation: `O(|c|)` memory, `O(|r|)` time where `|c|`
853
is the size of ``self`` and `r` is the result.
854
855
EXAMPLES::
856
857
sage: C = Composition([4,5,2]).fatter()
858
sage: C.cardinality()
859
4
860
sage: list(C)
861
[[4, 5, 2], [4, 7], [9, 2], [11]]
862
863
Some extreme cases::
864
865
sage: list(Composition([5]).fatter())
866
[[5]]
867
sage: list(Composition([]).fatter())
868
[[]]
869
sage: list(Composition([1,1,1,1]).fatter()) == list(Compositions(4))
870
True
871
"""
872
return Compositions(len(self)).map(self.fatten)
873
874
def refinement_splitting(self, J):
875
r"""
876
Return the refinement splitting of ``self`` according to ``J``.
877
878
INPUT:
879
880
- ``J`` -- A composition such that ``self`` is finer than ``J``
881
882
OUTPUT:
883
884
- the unique list of compositions `(I^{(p)})_{p=1, \ldots , m}`,
885
obtained by splitting `I`, such that
886
`|I^{(p)}| = J_p` for all `p = 1, \ldots, m`.
887
888
.. SEEALSO::
889
890
:meth:`refinement_splitting_lengths`
891
892
EXAMPLES::
893
894
sage: Composition([1,2,2,1,1,2]).refinement_splitting([5,1,3])
895
[[1, 2, 2], [1], [1, 2]]
896
sage: Composition([]).refinement_splitting([])
897
[]
898
sage: Composition([3]).refinement_splitting([2])
899
Traceback (most recent call last):
900
...
901
ValueError: compositions self (= [3]) and J (= [2]) must be of the same size
902
sage: Composition([2,1]).refinement_splitting([1,2])
903
Traceback (most recent call last):
904
...
905
ValueError: composition J (= [2, 1]) does not refine self (= [1, 2])
906
"""
907
I = self
908
if sum(I) != sum(J):
909
#Error: compositions are not of the same size
910
raise ValueError("compositions self (= %s) and J (= %s) must be of the same size"%(I, J))
911
sum1 = 0
912
sum2 = 0
913
i1 = -1
914
decomp = []
915
for j2 in J:
916
new_comp = []
917
sum2 += j2
918
while sum1 < sum2:
919
i1 += 1
920
new_comp.append(I[i1])
921
sum1 += new_comp[-1]
922
if sum1 > sum2:
923
raise ValueError("composition J (= %s) does not refine self (= %s)"%(I, J))
924
decomp.append(Compositions()(new_comp))
925
return decomp
926
927
def refinement_splitting_lengths(self, J):
928
"""
929
Return the lengths of the compositions in the refinement splitting of
930
``self`` according to ``J``.
931
932
.. SEEALSO::
933
934
:meth:`refinement_splitting` for the definition of refinement splitting
935
936
EXAMPLES::
937
938
sage: Composition([1,2,2,1,1,2]).refinement_splitting_lengths([5,1,3])
939
[3, 1, 2]
940
sage: Composition([]).refinement_splitting_lengths([])
941
[]
942
sage: Composition([3]).refinement_splitting_lengths([2])
943
Traceback (most recent call last):
944
...
945
ValueError: compositions self (= [3]) and J (= [2]) must be of the same size
946
sage: Composition([2,1]).refinement_splitting_lengths([1,2])
947
Traceback (most recent call last):
948
...
949
ValueError: composition J (= [2, 1]) does not refine self (= [1, 2])
950
"""
951
return Compositions()(map(len,self.refinement_splitting(J)))
952
953
refinement = deprecated_function_alias(13243, refinement_splitting_lengths)
954
955
def major_index(self):
956
"""
957
Return the major index of ``self``. The major index is
958
defined as the sum of the descents.
959
960
EXAMPLES::
961
962
sage: Composition([1, 1, 3, 1, 2, 1, 3]).major_index()
963
31
964
"""
965
co = self
966
lv = len(co)
967
if lv == 1:
968
return 0
969
else:
970
return sum([(lv-(i+1))*co[i] for i in range(lv)])
971
972
def to_code(self):
973
r"""
974
Return the code of the composition ``self``. The code of a composition
975
`I` is a list of length `\mathrm{size}(I)` of 1s and 0s such that
976
there is a 1 wherever a new part starts. (Exceptional case: When the
977
composition is empty, the code is ``[0]``.)
978
979
EXAMPLES::
980
981
sage: Composition([4,1,2,3,5]).to_code()
982
[1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
983
"""
984
if self == []:
985
return [0]
986
987
code = []
988
for i in range(len(self)):
989
code += [1] + [0]*(self[i]-1)
990
991
return code
992
993
def partial_sums(self, final=True):
994
r"""
995
The partial sums of the sequence defined by the entries of the
996
composition.
997
998
If `I = (i_1, \ldots, i_m)` is a composition, then the partial sums of
999
the entries of the composition are
1000
`[i_1, i_1 + i_2, \ldots, i_1 + i_2 + \cdots + i_m]`.
1001
1002
INPUT:
1003
1004
- ``final`` -- (default: ``True``) whether or not to include the final
1005
partial sum, which is always the size of the composition.
1006
1007
.. SEEALSO::
1008
1009
:meth:`to_subset`
1010
1011
EXAMPLES::
1012
1013
sage: Composition([1,1,3,1,2,1,3]).partial_sums()
1014
[1, 2, 5, 6, 8, 9, 12]
1015
1016
With ``final = False``, the last partial sum is not included::
1017
1018
sage: Composition([1,1,3,1,2,1,3]).partial_sums(final=False)
1019
[1, 2, 5, 6, 8, 9]
1020
"""
1021
s = 0
1022
partial_sums = []
1023
for i in self:
1024
s += i
1025
partial_sums.append(s)
1026
if final is False:
1027
partial_sums.pop()
1028
return partial_sums
1029
1030
def to_subset(self, final=False):
1031
r"""
1032
The subset corresponding to ``self`` under the bijection (see below)
1033
between compositions of `n` and subsets of `\{1, 2, \ldots, n-1\}`.
1034
1035
The bijection maps a composition `(i_1, \ldots, i_k)` of `n` to
1036
`\{i_1, i_1 + i_2, i_1 + i_2 + i_3, \ldots, i_1 + \cdots + i_{k-1}\}`.
1037
1038
INPUT:
1039
1040
- ``final`` -- (default: ``False``) whether or not to include the final
1041
partial sum, which is always the size of the composition.
1042
1043
.. SEEALSO::
1044
1045
:meth:`partial_sums`
1046
1047
EXAMPLES::
1048
1049
sage: Composition([1,1,3,1,2,1,3]).to_subset()
1050
{1, 2, 5, 6, 8, 9}
1051
sage: for I in Compositions(3): print I.to_subset()
1052
{1, 2}
1053
{1}
1054
{2}
1055
{}
1056
1057
With ``final=True``, the sum of all the elements of the composition is
1058
included in the subset::
1059
1060
sage: Composition([1,1,3,1,2,1,3]).to_subset(final=True)
1061
{1, 2, 5, 6, 8, 9, 12}
1062
1063
TESTS:
1064
1065
We verify that ``to_subset`` is indeed a bijection for compositions of
1066
size `n = 8`::
1067
1068
sage: n = 8
1069
sage: all(Composition(from_subset=(S, n)).to_subset() == S \
1070
... for S in Subsets(n-1))
1071
True
1072
sage: all(Composition(from_subset=(I.to_subset(), n)) == I \
1073
... for I in Compositions(n))
1074
True
1075
"""
1076
from sage.sets.set import Set
1077
return Set(self.partial_sums(final=final))
1078
1079
def descents(self, final_descent=False):
1080
r"""
1081
This gives one fewer than the partial sums of the composition.
1082
1083
This is here to maintain some sort of backward compatibility, even
1084
through the original implementation was broken (it gave the wrong
1085
answer). The same information can be found in :meth:`partial_sums`.
1086
1087
.. SEEALSO::
1088
1089
:meth:`partial_sums`
1090
1091
INPUT:
1092
1093
- ``final_descent`` -- (Default: ``False``) a boolean integer
1094
1095
OUTPUT:
1096
1097
- the list of partial sums of ``self`` with each part
1098
decremented by `1`. This includes the sum of all entries when
1099
``final_descent`` is ``True``.
1100
1101
EXAMPLES::
1102
1103
sage: c = Composition([2,1,3,2])
1104
sage: c.descents()
1105
[1, 2, 5]
1106
sage: c.descents(final_descent=True)
1107
[1, 2, 5, 7]
1108
"""
1109
return [i - 1 for i in self.partial_sums(final=final_descent)]
1110
1111
def peaks(self):
1112
"""
1113
Return a list of the peaks of the composition ``self``. The
1114
peaks of a composition are the descents which do not
1115
immediately follow another descent.
1116
1117
EXAMPLES::
1118
1119
sage: Composition([1, 1, 3, 1, 2, 1, 3]).peaks()
1120
[4, 7]
1121
"""
1122
descents = dict((d-1,True) for d in self.to_subset(final=True))
1123
return [i+1 for i in range(len(self))
1124
if i not in descents and i+1 in descents]
1125
1126
@combinatorial_map(name='to partition')
1127
def to_partition(self):
1128
"""
1129
Return the partition obtained by sorting ``self`` into decreasing
1130
order.
1131
1132
EXAMPLES::
1133
1134
sage: Composition([2,1,3]).to_partition()
1135
[3, 2, 1]
1136
sage: Composition([4,2,2]).to_partition()
1137
[4, 2, 2]
1138
sage: Composition([]).to_partition()
1139
[]
1140
"""
1141
from sage.combinat.partition import Partition
1142
return Partition(sorted(self, reverse=True))
1143
1144
def to_skew_partition(self, overlap=1):
1145
"""
1146
Return the skew partition obtained from ``self``. This is a
1147
skew partition whose rows have the entries of ``self`` as their
1148
length, taken in reverse order (so the first entry of ``self``
1149
is the length of the lowermost row, etc.). The parameter
1150
``overlap`` indicates the number of cells on each row that are
1151
directly below cells of the previous row. When it is set to `1`
1152
(its default value), the result is the ribbon shape of ``self``.
1153
1154
EXAMPLES::
1155
1156
sage: Composition([3,4,1]).to_skew_partition()
1157
[6, 6, 3] / [5, 2]
1158
sage: Composition([3,4,1]).to_skew_partition(overlap=0)
1159
[8, 7, 3] / [7, 3]
1160
sage: Composition([]).to_skew_partition()
1161
[] / []
1162
sage: Composition([1,2]).to_skew_partition()
1163
[2, 1] / []
1164
sage: Composition([2,1]).to_skew_partition()
1165
[2, 2] / [1]
1166
"""
1167
from sage.combinat.skew_partition import SkewPartition
1168
outer = []
1169
inner = []
1170
sum_outer = -1*overlap
1171
1172
for k in self[:-1]:
1173
outer.append(k + sum_outer + overlap)
1174
sum_outer += k - overlap
1175
inner.append(sum_outer + overlap)
1176
1177
if self != []:
1178
outer.append(self[-1] + sum_outer + overlap)
1179
else:
1180
return SkewPartition([[],[]])
1181
1182
return SkewPartition(
1183
[ filter(lambda x: x != 0, [l for l in reversed(outer)]),
1184
filter(lambda x: x != 0, [l for l in reversed(inner)])])
1185
1186
1187
def shuffle_product(self, other, overlap=False):
1188
r"""
1189
The (overlapping) shuffles of ``self`` and ``other``.
1190
1191
Suppose `I = (i_1, \ldots, i_k)` and `J = (j_1, \ldots, j_l)` are two
1192
compositions. A *shuffle* of `I` and `J` is a composition of length
1193
`k + l` that contains both `I` and `J` as subsequences.
1194
1195
More generally, an *overlapping shuffle* of `I` and `J` is obtained by
1196
distributing the elements of `I` and `J` (preserving the relative
1197
ordering of these elements) among the positions of an empty list; an
1198
element of `I` and an element of `J` are permitted to share the same
1199
position, in which case they are replaced by their sum. In particular,
1200
a shuffle of `I` and `J` is an overlapping shuffle of `I` and `J`.
1201
1202
INPUT:
1203
1204
- ``other`` -- composition
1205
1206
- ``overlap`` -- boolean (default: ``False``); if ``True``, the
1207
overlapping shuffle product is returned.
1208
1209
OUTPUT:
1210
1211
An enumerated set (allowing for mutliplicities)
1212
1213
EXAMPLES:
1214
1215
The shuffle product of `[2,2]` and `[1,1,3]`::
1216
1217
sage: alph = Composition([2,2])
1218
sage: beta = Composition([1,1,3])
1219
sage: S = alph.shuffle_product(beta); S
1220
Shuffle product of [2, 2] and [1, 1, 3]
1221
sage: S.list()
1222
[[2, 2, 1, 1, 3], [2, 1, 2, 1, 3], [2, 1, 1, 2, 3], [2, 1, 1, 3, 2], [1, 2, 2, 1, 3], [1, 2, 1, 2, 3], [1, 2, 1, 3, 2], [1, 1, 2, 2, 3], [1, 1, 2, 3, 2], [1, 1, 3, 2, 2]]
1223
1224
The *overlapping* shuffle product of `[2,2]` and `[1,1,3]`::
1225
1226
sage: alph = Composition([2,2])
1227
sage: beta = Composition([1,1,3])
1228
sage: O = alph.shuffle_product(beta, overlap=True); O
1229
Overlapping shuffle product of [2, 2] and [1, 1, 3]
1230
sage: O.list()
1231
[[2, 2, 1, 1, 3], [2, 1, 2, 1, 3], [2, 1, 1, 2, 3], [2, 1, 1, 3, 2], [1, 2, 2, 1, 3], [1, 2, 1, 2, 3], [1, 2, 1, 3, 2], [1, 1, 2, 2, 3], [1, 1, 2, 3, 2], [1, 1, 3, 2, 2], [3, 2, 1, 3], [2, 3, 1, 3], [3, 1, 2, 3], [2, 1, 3, 3], [3, 1, 3, 2], [2, 1, 1, 5], [1, 3, 2, 3], [1, 2, 3, 3], [1, 3, 3, 2], [1, 2, 1, 5], [1, 1, 5, 2], [1, 1, 2, 5], [3, 3, 3], [3, 1, 5], [1, 3, 5]]
1232
1233
Note that the shuffle product of two compositions can include the same
1234
composition more than once since a composition can be a shuffle of two
1235
compositions in several ways. For example::
1236
1237
sage: S = Composition([1]).shuffle_product([1]); S
1238
Shuffle product of [1] and [1]
1239
sage: S.list()
1240
[[1, 1], [1, 1]]
1241
sage: O = Composition([1]).shuffle_product([1], overlap=True); O
1242
Overlapping shuffle product of [1] and [1]
1243
sage: O.list()
1244
[[1, 1], [1, 1], [2]]
1245
1246
TESTS::
1247
1248
sage: Composition([]).shuffle_product([]).list()
1249
[[]]
1250
"""
1251
if overlap:
1252
from sage.combinat.words.shuffle_product import ShuffleProduct_overlapping
1253
return ShuffleProduct_overlapping(self, other)
1254
else:
1255
from sage.combinat.words.shuffle_product import ShuffleProduct_w1w2
1256
return ShuffleProduct_w1w2(self, other)
1257
1258
def wll_gt(self, co2):
1259
"""
1260
Return ``True`` if the composition ``self`` is greater than the
1261
composition ``co2`` with respect to the wll-ordering; otherwise,
1262
return ``False``.
1263
1264
The wll-ordering is a total order on the set of all compositions
1265
defined as follows: A composition `I` is greater than a
1266
composition `J` if and only if one of the following conditions
1267
holds:
1268
1269
- The size of `I` is greater than the size of `J`.
1270
1271
- The size of `I` equals the size of `J`, but the length of `I`
1272
is greater than the length of `J`.
1273
1274
- The size of `I` equals the size of `J`, and the length of `I`
1275
equals the length of `J`, but `I` is lexicographically
1276
greater than `J`.
1277
1278
("wll-ordering" is short for "weight, length, lexicographic
1279
ordering".)
1280
1281
EXAMPLES::
1282
1283
sage: Composition([4,1,2]).wll_gt([3,1,3])
1284
True
1285
sage: Composition([7]).wll_gt([4,1,2])
1286
False
1287
sage: Composition([8]).wll_gt([4,1,2])
1288
True
1289
sage: Composition([3,2,2,2]).wll_gt([5,2])
1290
True
1291
sage: Composition([]).wll_gt([3])
1292
False
1293
sage: Composition([2,1]).wll_gt([2,1])
1294
False
1295
sage: Composition([2,2,2]).wll_gt([4,2])
1296
True
1297
sage: Composition([4,2]).wll_gt([2,2,2])
1298
False
1299
sage: Composition([1,1,2]).wll_gt([2,2])
1300
True
1301
sage: Composition([2,2]).wll_gt([1,3])
1302
True
1303
sage: Composition([2,1,2]).wll_gt([])
1304
True
1305
"""
1306
co1 = self
1307
if sum(co1) > sum(co2):
1308
return True
1309
elif sum(co1) < sum(co2):
1310
return False
1311
if len(co1) > len(co2):
1312
return True
1313
if len(co1) < len(co2):
1314
return False
1315
for i in range(len(co1)):
1316
if co1[i] > co2[i]:
1317
return True
1318
elif co1[i] < co2[i]:
1319
return False
1320
return False
1321
1322
##############################################################
1323
1324
class Compositions(Parent, UniqueRepresentation):
1325
r"""
1326
Set of integer compositions.
1327
1328
A composition `c` of a nonnegative integer `n` is a list of
1329
positive integers with total sum `n`.
1330
1331
.. SEEALSO::
1332
1333
- :class:`Composition`
1334
- :class:`Partitions`
1335
- :class:`IntegerVectors`
1336
1337
EXAMPLES:
1338
1339
There are 8 compositions of 4::
1340
1341
sage: Compositions(4).cardinality()
1342
8
1343
1344
Here is the list of them::
1345
1346
sage: Compositions(4).list()
1347
[[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
1348
1349
You can use the ``.first()`` method to get the 'first' composition of
1350
a number::
1351
1352
sage: Compositions(4).first()
1353
[1, 1, 1, 1]
1354
1355
You can also calculate the 'next' composition given the current
1356
one::
1357
1358
sage: Compositions(4).next([1,1,2])
1359
[1, 2, 1]
1360
1361
If `n` is not specified, this returns the combinatorial class of
1362
all (non-negative) integer compositions::
1363
1364
sage: Compositions()
1365
Compositions of non-negative integers
1366
sage: [] in Compositions()
1367
True
1368
sage: [2,3,1] in Compositions()
1369
True
1370
sage: [-2,3,1] in Compositions()
1371
False
1372
1373
If `n` is specified, it returns the class of compositions of `n`::
1374
1375
sage: Compositions(3)
1376
Compositions of 3
1377
sage: list(Compositions(3))
1378
[[1, 1, 1], [1, 2], [2, 1], [3]]
1379
sage: Compositions(3).cardinality()
1380
4
1381
1382
The following examples show how to test whether or not an object
1383
is a composition::
1384
1385
sage: [3,4] in Compositions()
1386
True
1387
sage: [3,4] in Compositions(7)
1388
True
1389
sage: [3,4] in Compositions(5)
1390
False
1391
1392
Similarly, one can check whether or not an object is a composition
1393
which satisfies further constraints::
1394
1395
sage: [4,2] in Compositions(6, inner=[2,2])
1396
True
1397
sage: [4,2] in Compositions(6, inner=[2,3])
1398
False
1399
sage: [4,1] in Compositions(5, inner=[2,1], max_slope = 0)
1400
True
1401
1402
Note that the given constraints should be compatible::
1403
1404
sage: [4,2] in Compositions(6, inner=[2,2], min_part=3)
1405
True
1406
1407
The options ``length``, ``min_length``, and ``max_length`` can be used
1408
to set length constraints on the compositions. For example, the
1409
compositions of 4 of length equal to, at least, and at most 2 are
1410
given by::
1411
1412
sage: Compositions(4, length=2).list()
1413
[[3, 1], [2, 2], [1, 3]]
1414
sage: Compositions(4, min_length=2).list()
1415
[[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1416
sage: Compositions(4, max_length=2).list()
1417
[[4], [3, 1], [2, 2], [1, 3]]
1418
1419
Setting both ``min_length`` and ``max_length`` to the same value is
1420
equivalent to setting ``length`` to this value::
1421
1422
sage: Compositions(4, min_length=2, max_length=2).list()
1423
[[3, 1], [2, 2], [1, 3]]
1424
1425
The options ``inner`` and ``outer`` can be used to set part-by-part
1426
containment constraints. The list of compositions of 4 bounded
1427
above by ``[3,1,2]`` is given by::
1428
1429
sage: list(Compositions(4, outer=[3,1,2]))
1430
[[3, 1], [2, 1, 1], [1, 1, 2]]
1431
1432
``outer`` sets ``max_length`` to the length of its argument. Moreover, the
1433
parts of ``outer`` may be infinite to clear the constraint on specific
1434
parts. This is the list of compositions of 4 of length at most 3
1435
such that the first and third parts are at most 1::
1436
1437
sage: Compositions(4, outer=[1,oo,1]).list()
1438
[[1, 3], [1, 2, 1]]
1439
1440
This is the list of compositions of 4 bounded below by ``[1,1,1]``::
1441
1442
sage: Compositions(4, inner=[1,1,1]).list()
1443
[[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1444
1445
The options ``min_slope`` and ``max_slope`` can be used to set constraints
1446
on the slope, that is the difference ``p[i+1]-p[i]`` of two
1447
consecutive parts. The following is the list of weakly increasing
1448
compositions of 4::
1449
1450
sage: Compositions(4, min_slope=0).list()
1451
[[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]]
1452
1453
Here are the weakly decreasing ones::
1454
1455
sage: Compositions(4, max_slope=0).list()
1456
[[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]]
1457
1458
The following is the list of compositions of 4 such that two
1459
consecutive parts differ by at most one::
1460
1461
sage: Compositions(4, min_slope=-1, max_slope=1).list()
1462
[[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1463
1464
The constraints can be combined together in all reasonable ways.
1465
This is the list of compositions of 5 of length between 2 and 4
1466
such that the difference between consecutive parts is between -2
1467
and 1::
1468
1469
sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
1470
[[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]]
1471
1472
We can do the same thing with an outer constraint::
1473
1474
sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
1475
[[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]]
1476
1477
However, providing incoherent constraints may yield strange
1478
results. It is up to the user to ensure that the inner and outer
1479
compositions themselves satisfy the parts and slope constraints.
1480
1481
Note that if you specify ``min_part=0``, then the objects produced may
1482
have parts equal to zero. This violates the internal assumptions
1483
that the composition class makes. Use at your own risk, or
1484
preferably consider using ``IntegerVectors`` instead::
1485
1486
sage: Compositions(2, length=3, min_part=0).list()
1487
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!
1488
[[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
1489
1490
sage: list(IntegerVectors(2, 3))
1491
[[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]]
1492
1493
The generation algorithm is constant amortized time, and handled
1494
by the generic tool :class:`IntegerListsLex`.
1495
1496
TESTS::
1497
1498
sage: C = Compositions(4, length=2)
1499
sage: C == loads(dumps(C))
1500
True
1501
1502
sage: Compositions(6, min_part=2, length=3)
1503
Compositions of the integer 6 satisfying constraints length=3, min_part=2
1504
1505
sage: [2, 1] in Compositions(3, length=2)
1506
True
1507
sage: [2,1,2] in Compositions(5, min_part=1)
1508
True
1509
sage: [2,1,2] in Compositions(5, min_part=2)
1510
False
1511
1512
sage: Compositions(4, length=2).cardinality()
1513
3
1514
sage: Compositions(4, min_length=2).cardinality()
1515
7
1516
sage: Compositions(4, max_length=2).cardinality()
1517
4
1518
sage: Compositions(4, max_part=2).cardinality()
1519
5
1520
sage: Compositions(4, min_part=2).cardinality()
1521
2
1522
sage: Compositions(4, outer=[3,1,2]).cardinality()
1523
3
1524
1525
sage: Compositions(4, length=2).list()
1526
[[3, 1], [2, 2], [1, 3]]
1527
sage: Compositions(4, min_length=2).list()
1528
[[3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1529
sage: Compositions(4, max_length=2).list()
1530
[[4], [3, 1], [2, 2], [1, 3]]
1531
sage: Compositions(4, max_part=2).list()
1532
[[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1533
sage: Compositions(4, min_part=2).list()
1534
[[4], [2, 2]]
1535
sage: Compositions(4, outer=[3,1,2]).list()
1536
[[3, 1], [2, 1, 1], [1, 1, 2]]
1537
sage: Compositions(3, outer = Composition([3,2])).list()
1538
[[3], [2, 1], [1, 2]]
1539
sage: Compositions(4, outer=[1,oo,1]).list()
1540
[[1, 3], [1, 2, 1]]
1541
sage: Compositions(4, inner=[1,1,1]).list()
1542
[[2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1543
sage: Compositions(4, inner=Composition([1,2])).list()
1544
[[2, 2], [1, 3], [1, 2, 1]]
1545
sage: Compositions(4, min_slope=0).list()
1546
[[4], [2, 2], [1, 3], [1, 1, 2], [1, 1, 1, 1]]
1547
sage: Compositions(4, min_slope=-1, max_slope=1).list()
1548
[[4], [2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1549
sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4).list()
1550
[[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]]
1551
sage: Compositions(5, max_slope=1, min_slope=-2, min_length=2, max_length=4, outer=[2,5,2]).list()
1552
[[2, 3], [2, 2, 1], [2, 1, 2], [1, 2, 2]]
1553
"""
1554
@staticmethod
1555
def __classcall_private__(self, n=None, **kwargs):
1556
"""
1557
Return the correct parent based upon the input.
1558
1559
EXAMPLES::
1560
1561
sage: C = Compositions(3)
1562
sage: C2 = Compositions(int(3))
1563
sage: C is C2
1564
True
1565
"""
1566
if n is None:
1567
if len(kwargs) != 0:
1568
raise ValueError("Incorrect number of arguments")
1569
return Compositions_all()
1570
else:
1571
if len(kwargs) == 0:
1572
if isinstance(n, (int,Integer)):
1573
return Compositions_n(n)
1574
else:
1575
raise ValueError("n must be an integer")
1576
else:
1577
# FIXME: should inherit from IntegerListLex, and implement repr, or _name as a lazy attribute
1578
kwargs['name'] = "Compositions of the integer %s satisfying constraints %s"%(n, ", ".join( ["%s=%s"%(key, kwargs[key]) for key in sorted(kwargs.keys())] ))
1579
kwargs['element_class'] = Composition
1580
if 'min_part' not in kwargs:
1581
kwargs['min_part'] = 1
1582
elif kwargs['min_part'] == 0:
1583
from warnings import warn
1584
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)
1585
1586
if 'outer' in kwargs:
1587
kwargs['ceiling'] = list(kwargs['outer'])
1588
if 'max_length' in kwargs:
1589
kwargs['max_length'] = min(len(kwargs['outer']), kwargs['max_length'])
1590
else:
1591
kwargs['max_length'] = len(kwargs['outer'])
1592
del kwargs['outer']
1593
1594
if 'inner' in kwargs:
1595
inner = list(kwargs['inner'])
1596
kwargs['floor'] = inner
1597
del kwargs['inner']
1598
# Should this be handled by integer lists lex?
1599
if 'min_length' in kwargs:
1600
kwargs['min_length'] = max(len(inner), kwargs['min_length'])
1601
else:
1602
kwargs['min_length'] = len(inner)
1603
return IntegerListsLex(n, **kwargs)
1604
1605
def __init__(self, is_infinite=False):
1606
"""
1607
Initialize ``self``.
1608
1609
EXAMPLES::
1610
1611
sage: C = Compositions()
1612
sage: TestSuite(C).run()
1613
"""
1614
if is_infinite:
1615
Parent.__init__(self, category=InfiniteEnumeratedSets())
1616
else:
1617
Parent.__init__(self, category=FiniteEnumeratedSets())
1618
1619
Element = Composition
1620
1621
def _element_constructor_(self, lst):
1622
"""
1623
Construct an element with ``self`` as parent.
1624
1625
EXAMPLES::
1626
1627
sage: P = Compositions()
1628
sage: P([3,3,1]) # indirect doctest
1629
[3, 3, 1]
1630
"""
1631
if isinstance(lst, Composition):
1632
lst = list(lst)
1633
elt = self.element_class(self, lst)
1634
if elt not in self:
1635
raise ValueError("%s not in %s"%(elt, self))
1636
return elt
1637
1638
def __contains__(self, x):
1639
"""
1640
TESTS::
1641
1642
sage: [2,1,3] in Compositions()
1643
True
1644
sage: [] in Compositions()
1645
True
1646
sage: [-2,-1] in Compositions()
1647
False
1648
sage: [0,0] in Compositions()
1649
True
1650
"""
1651
if isinstance(x, Composition):
1652
return True
1653
elif isinstance(x, __builtin__.list):
1654
for i in range(len(x)):
1655
if (not isinstance(x[i], (int, Integer))) and x[i] not in ZZ:
1656
return False
1657
if x[i] < 0:
1658
return False
1659
return True
1660
else:
1661
return False
1662
1663
def from_descents(self, descents, nps=None):
1664
"""
1665
Return a composition from the list of descents.
1666
1667
INPUT:
1668
1669
- ``descents`` -- an iterable
1670
1671
- ``nps`` -- (default: ``None``) an integer or ``None``
1672
1673
OUTPUT:
1674
1675
- The composition of ``nps`` whose descents are listed in
1676
``descents``, assuming that ``nps`` is not ``None`` (otherwise,
1677
the last element of ``descents`` is removed from ``descents``, and
1678
``nps`` is set to be this last element plus 1).
1679
1680
EXAMPLES::
1681
1682
sage: [x-1 for x in Composition([1, 1, 3, 4, 3]).to_subset()]
1683
[0, 1, 4, 8]
1684
sage: Compositions().from_descents([1,0,4,8],12)
1685
[1, 1, 3, 4, 3]
1686
sage: Compositions().from_descents([1,0,4,8,11])
1687
[1, 1, 3, 4, 3]
1688
"""
1689
d = [x+1 for x in sorted(descents)]
1690
if nps is None:
1691
nps = d.pop()
1692
return self.from_subset(d, nps)
1693
1694
def from_subset(self, S, n):
1695
r"""
1696
The composition of `n` corresponding to the subset ``S`` of
1697
`\{1, 2, \ldots, n-1\}` under the bijection that maps the composition
1698
`(i_1, i_2, \ldots, i_k)` of `n` to the subset
1699
`\{i_1, i_1 + i_2, i_1 + i_2 + i_3, \ldots, i_1 + \cdots + i_{k-1}\}`
1700
(see :meth:`Composition.to_subset`).
1701
1702
INPUT:
1703
1704
- ``S`` -- an iterable, a subset of `\{1, 2, \ldots, n-1\}`
1705
1706
- ``n`` -- an integer
1707
1708
EXAMPLES::
1709
1710
sage: Compositions().from_subset([2,1,5,9], 12)
1711
[1, 1, 3, 4, 3]
1712
sage: Compositions().from_subset({2,1,5,9}, 12)
1713
[1, 1, 3, 4, 3]
1714
1715
sage: Compositions().from_subset([], 12)
1716
[12]
1717
sage: Compositions().from_subset([], 0)
1718
[]
1719
1720
TESTS::
1721
1722
sage: Compositions().from_subset([2,1,5,9],9)
1723
Traceback (most recent call last):
1724
...
1725
ValueError: S (=[1, 2, 5, 9]) is not a subset of {1, ..., 8}
1726
"""
1727
d = sorted(S)
1728
1729
if d == []:
1730
if n == 0:
1731
return self.element_class(self, [])
1732
else:
1733
return self.element_class(self, [n])
1734
1735
if n <= d[-1]:
1736
raise ValueError, "S (=%s) is not a subset of {1, ..., %s}" % (d,n-1)
1737
else:
1738
d.append(n)
1739
1740
co = [d[0]]
1741
for i in range(len(d)-1):
1742
co.append(d[i+1]-d[i])
1743
1744
return self.element_class(self, co)
1745
1746
def from_code(self, code):
1747
r"""
1748
Return the composition from its code. The code of a composition
1749
`I` is a list of length `\mathrm{size}(I)` consisting of 1s and
1750
0s such that there is a 1 wherever a new part starts.
1751
(Exceptional case: When the composition is empty, the code is
1752
``[0]``.)
1753
1754
EXAMPLES::
1755
1756
sage: Composition([4,1,2,3,5]).to_code()
1757
[1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
1758
sage: Compositions().from_code(_)
1759
[4, 1, 2, 3, 5]
1760
sage: Composition([3,1,2,3,5]).to_code()
1761
[1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
1762
sage: Compositions().from_code(_)
1763
[3, 1, 2, 3, 5]
1764
"""
1765
if code == [0]:
1766
return []
1767
1768
L = filter(lambda x: code[x]==1, range(len(code))) #the positions of the letter 1
1769
return self.element_class(self, [L[i]-L[i-1] for i in range(1, len(L))] + [len(code)-L[-1]])
1770
1771
# Allows to unpickle old constrained Compositions_constraints objects.
1772
class Compositions_constraints(IntegerListsLex):
1773
def __setstate__(self, data):
1774
"""
1775
TESTS::
1776
1777
# This is the unpickling sequence for Compositions(4, max_part=2) in sage <= 4.1.1
1778
sage: pg_Compositions_constraints = unpickle_global('sage.combinat.composition', 'Compositions_constraints')
1779
sage: si = unpickle_newobj(pg_Compositions_constraints, ())
1780
sage: pg_make_integer = unpickle_global('sage.rings.integer', 'make_integer')
1781
sage: unpickle_build(si, {'constraints':{'max_part':pg_make_integer('2')}, 'n':pg_make_integer('4')})
1782
sage: si
1783
Integer lists of sum 4 satisfying certain constraints
1784
sage: si.list()
1785
[[2, 2], [2, 1, 1], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]]
1786
"""
1787
n = data['n']
1788
self.__class__ = IntegerListsLex
1789
constraints = {'min_part' : 1,
1790
'element_class' : Composition}
1791
constraints.update(data['constraints'])
1792
self.__init__(n, **constraints)
1793
1794
class Compositions_all(Compositions):
1795
"""
1796
Class of all compositions.
1797
"""
1798
def __init__(self):
1799
"""
1800
Initialize ``self``.
1801
1802
TESTS::
1803
1804
sage: C = Compositions()
1805
sage: TestSuite(C).run()
1806
"""
1807
Compositions.__init__(self, True)
1808
1809
def _repr_(self):
1810
"""
1811
Return a string representation of ``self``.
1812
1813
TESTS::
1814
1815
sage: repr(Compositions())
1816
'Compositions of non-negative integers'
1817
"""
1818
return "Compositions of non-negative integers"
1819
1820
def subset(self, size=None):
1821
"""
1822
Return the set of compositions of the given size.
1823
1824
EXAMPLES::
1825
1826
sage: C = Compositions()
1827
sage: C.subset(4)
1828
Compositions of 4
1829
sage: C.subset(size=3)
1830
Compositions of 3
1831
"""
1832
if size is None:
1833
return self
1834
return Compositions(size)
1835
1836
def __iter__(self):
1837
"""
1838
Iterate over all compositions.
1839
1840
TESTS::
1841
1842
sage: C = Compositions()
1843
sage: it = C.__iter__()
1844
sage: [it.next() for i in range(10)]
1845
[[], [1], [1, 1], [2], [1, 1, 1], [1, 2], [2, 1], [3], [1, 1, 1, 1], [1, 1, 2]]
1846
"""
1847
n = 0
1848
while True:
1849
for c in Compositions(n):
1850
yield self.element_class(self, list(c))
1851
n += 1
1852
1853
class Compositions_n(Compositions):
1854
"""
1855
Class of compositions of a fixed `n`.
1856
"""
1857
@staticmethod
1858
def __classcall_private__(cls, n):
1859
"""
1860
Standardize input to ensure a unique representation.
1861
1862
EXAMPLES::
1863
1864
sage: C = Compositions(5)
1865
sage: C2 = Compositions(int(5))
1866
sage: C3 = Compositions(ZZ(5))
1867
sage: C is C2
1868
True
1869
sage: C is C3
1870
True
1871
"""
1872
return super(Compositions_n, cls).__classcall__(cls, Integer(n))
1873
1874
def __init__(self, n):
1875
"""
1876
TESTS::
1877
1878
sage: C = Compositions(3)
1879
sage: C == loads(dumps(C))
1880
True
1881
sage: TestSuite(C).run()
1882
"""
1883
self.n = n
1884
Compositions.__init__(self, False)
1885
1886
def _repr_(self):
1887
"""
1888
Return a string representation of ``self``.
1889
1890
TESTS::
1891
1892
sage: repr(Compositions(3))
1893
'Compositions of 3'
1894
"""
1895
return "Compositions of %s"%self.n
1896
1897
def __contains__(self, x):
1898
"""
1899
TESTS::
1900
1901
sage: [2,1,3] in Compositions(6)
1902
True
1903
sage: [2,1,2] in Compositions(6)
1904
False
1905
sage: [] in Compositions(0)
1906
True
1907
sage: [0] in Compositions(0)
1908
True
1909
"""
1910
return x in Compositions() and sum(x) == self.n
1911
1912
def cardinality(self):
1913
"""
1914
Return the number of compositions of `n`.
1915
1916
TESTS::
1917
1918
sage: Compositions(3).cardinality()
1919
4
1920
sage: Compositions(0).cardinality()
1921
1
1922
"""
1923
if self.n >= 1:
1924
return 2**(self.n-1)
1925
elif self.n == 0:
1926
return 1
1927
else:
1928
return 0
1929
1930
def __iter__(self):
1931
"""
1932
Iterate over the compositions of `n`.
1933
1934
TESTS::
1935
1936
sage: Compositions(4).list()
1937
[[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]]
1938
sage: Compositions(0).list()
1939
[[]]
1940
"""
1941
if self.n == 0:
1942
yield self.element_class(self, [])
1943
return
1944
1945
for i in range(1,self.n+1):
1946
for c in Compositions_n(self.n-i):
1947
yield self.element_class(self, [i]+list(c))
1948
1949
def from_descents(descents, nps=None):
1950
r"""
1951
This has been deprecated in :trac:`14063`. Use
1952
:meth:`Compositions.from_descents()` instead.
1953
1954
EXAMPLES::
1955
1956
sage: [x-1 for x in Composition([1, 1, 3, 4, 3]).to_subset()]
1957
[0, 1, 4, 8]
1958
sage: sage.combinat.composition.from_descents([1,0,4,8],12)
1959
doctest:1: DeprecationWarning: from_descents is deprecated. Use Compositions().from_descents instead.
1960
See http://trac.sagemath.org/14063 for details.
1961
[1, 1, 3, 4, 3]
1962
"""
1963
from sage.misc.superseded import deprecation
1964
deprecation(14063, 'from_descents is deprecated. Use Compositions().from_descents instead.')
1965
return Compositions().from_descents(descents, nps)
1966
1967
def composition_from_subset(S, n):
1968
r"""
1969
This has been deprecated in :trac:`14063`. Use
1970
:meth:`Compositions.from_subset()` instead.
1971
1972
EXAMPLES::
1973
1974
sage: from sage.combinat.composition import composition_from_subset
1975
sage: composition_from_subset([2,1,5,9], 12)
1976
doctest:1: DeprecationWarning: composition_from_subset is deprecated. Use Compositions().from_subset instead.
1977
See http://trac.sagemath.org/14063 for details.
1978
[1, 1, 3, 4, 3]
1979
"""
1980
from sage.misc.superseded import deprecation
1981
deprecation(14063, 'composition_from_subset is deprecated. Use Compositions().from_subset instead.')
1982
return Compositions().from_subset(S, n)
1983
1984
def from_code(code):
1985
r"""
1986
This has been deprecated in :trac:`14063`. Use
1987
:meth:`Compositions.from_code()` instead.
1988
1989
EXAMPLES::
1990
1991
sage: import sage.combinat.composition as composition
1992
sage: Composition([4,1,2,3,5]).to_code()
1993
[1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0]
1994
sage: composition.from_code(_)
1995
doctest:1: DeprecationWarning: from_code is deprecated. Use Compositions().from_code instead.
1996
See http://trac.sagemath.org/14063 for details.
1997
[4, 1, 2, 3, 5]
1998
"""
1999
from sage.misc.superseded import deprecation
2000
deprecation(14063, 'from_code is deprecated. Use Compositions().from_code instead.')
2001
return Compositions().from_code(code)
2002
2003
from sage.structure.sage_object import register_unpickle_override
2004
register_unpickle_override('sage.combinat.composition', 'Composition_class', Composition)
2005
2006
2007