Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/matroids/set_system.pyx
8817 views
1
"""
2
Set systems
3
4
Many matroid methods return a collection of subsets. In this module a class
5
:class:`SetSystem <sage.matroids.set_system.SetSystem>` is defined to do
6
just this. The class is intended for internal use, so all you can do as a user
7
is iterate over its members.
8
9
The class is equipped with partition refinement methods to help with matroid
10
isomorphism testing.
11
12
AUTHORS:
13
14
- Rudi Pendavingh, Stefan van Zwam (2013-04-01): initial version
15
16
Methods
17
=======
18
"""
19
#*****************************************************************************
20
# Copyright (C) 2013 Rudi Pendavingh <[email protected]>
21
# Copyright (C) 2013 Stefan van Zwam <[email protected]>
22
#
23
# Distributed under the terms of the GNU General Public License (GPL)
24
# as published by the Free Software Foundation; either version 2 of
25
# the License, or (at your option) any later version.
26
# http://www.gnu.org/licenses/
27
#*****************************************************************************
28
29
include 'sage/ext/stdsage.pxi'
30
include 'sage/misc/bitset.pxi'
31
32
# SetSystem
33
34
cdef class SetSystem:
35
"""
36
A ``SetSystem`` is an enumerator of a collection of subsets of a given
37
fixed and finite ground set. It offers the possibility to enumerate its
38
contents. One is most likely to encounter these as output from some
39
Matroid methods::
40
41
sage: M = matroids.named_matroids.Fano()
42
sage: M.circuits()
43
Iterator over a system of subsets
44
45
To access the sets in this structure, simply iterate over them. The
46
simplest way must be::
47
48
sage: from sage.matroids.set_system import SetSystem
49
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
50
sage: T = list(S)
51
52
Or immediately use it to iterate::
53
54
sage: from sage.matroids.set_system import SetSystem
55
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
56
sage: [min(X) for X in S]
57
[1, 3, 1]
58
59
Note that this class is intended for runtime, so no loads/dumps mechanism
60
was implemented.
61
62
.. WARNING::
63
64
The only guaranteed behavior of this class is that it is iterable. It
65
is expected that M.circuits(), M.bases(), and so on will in the near
66
future return actual iterators. All other methods (which are already
67
hidden by default) are only for internal use by the Sage matroid code.
68
"""
69
def __cinit__(self, groundset, subsets=None, capacity=1):
70
"""
71
Init internal data structures.
72
73
EXAMPLES::
74
75
sage: from sage.matroids.set_system import SetSystem
76
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
77
sage: S
78
Iterator over a system of subsets
79
"""
80
cdef long i
81
if not isinstance(groundset, tuple):
82
self._groundset = tuple(groundset)
83
else:
84
self._groundset = groundset
85
self._idx = {}
86
for i in xrange(len(groundset)):
87
self._idx[groundset[i]] = i
88
89
self._groundset_size = len(groundset)
90
self._bitset_size = max(self._groundset_size, 1)
91
self._capacity = capacity
92
self._subsets = <bitset_t*> sage_malloc(self._capacity * sizeof(bitset_t))
93
bitset_init(self._temp, self._bitset_size)
94
self._len = 0
95
96
def __init__(self, groundset, subsets=None, capacity=1):
97
"""
98
Create a SetSystem.
99
100
INPUT:
101
102
- ``groundset`` -- a list or tuple of finitely many elements.
103
- ``subsets`` -- (default: ``None``) an enumerator for a set of
104
subsets of ``groundset``.
105
- ``capacity`` -- (default: ``1``) Initial maximal capacity of the set
106
system.
107
108
EXAMPLES::
109
110
sage: from sage.matroids.set_system import SetSystem
111
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
112
sage: S
113
Iterator over a system of subsets
114
sage: sorted(S[1])
115
[3, 4]
116
sage: for s in S: print sorted(s)
117
[1, 2]
118
[3, 4]
119
[1, 2, 4]
120
121
"""
122
if subsets is not None:
123
for e in subsets:
124
self.append(e)
125
126
def __dealloc__(self):
127
cdef long i
128
for i in xrange(self._len):
129
bitset_free(self._subsets[i])
130
sage_free(self._subsets)
131
bitset_free(self._temp)
132
133
def __len__(self):
134
"""
135
Return the number of subsets in this SetSystem.
136
137
EXAMPLES::
138
139
sage: from sage.matroids.set_system import SetSystem
140
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
141
sage: S
142
Iterator over a system of subsets
143
sage: len(S)
144
3
145
"""
146
return self._len
147
148
def __iter__(self):
149
"""
150
Return an iterator for the subsets in this SetSystem.
151
152
EXAMPLES::
153
154
sage: from sage.matroids.set_system import SetSystem
155
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
156
sage: for s in S: print sorted(s)
157
[1, 2]
158
[3, 4]
159
[1, 2, 4]
160
"""
161
return SetSystemIterator(self)
162
163
def __getitem__(self, k):
164
"""
165
Return the `k`-th subset in this SetSystem.
166
167
INPUT:
168
169
- ``k`` -- an integer. The index of the subset in the system.
170
171
OUTPUT:
172
173
The subset at index `k`.
174
175
EXAMPLES::
176
177
sage: from sage.matroids.set_system import SetSystem
178
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
179
sage: sorted(S[0])
180
[1, 2]
181
sage: sorted(S[1])
182
[3, 4]
183
sage: sorted(S[2])
184
[1, 2, 4]
185
"""
186
if k < len(self):
187
return self.subset(k)
188
else:
189
raise ValueError("out of range")
190
191
def __repr__(self):
192
"""
193
Return a string representation of ``self``.
194
195
EXAMPLES::
196
197
sage: from sage.matroids.set_system import SetSystem
198
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
199
sage: repr(S) # indirect doctest
200
'Iterator over a system of subsets'
201
202
"""
203
return "Iterator over a system of subsets"
204
205
cdef copy(self):
206
cdef SetSystem S
207
S = SetSystem(self._groundset, capacity=len(self))
208
for i in xrange(len(self)):
209
S._append(self._subsets[i])
210
return S
211
212
cdef _relabel(self, l):
213
"""
214
Relabel each element `e` of the ground set as `l(e)`, where `l` is a
215
given injective map.
216
217
INPUT:
218
219
- ``l`` -- a python object such that `l[e]` is the new label of e.
220
221
OUTPUT:
222
223
``None``.
224
225
"""
226
cdef long i
227
E = []
228
for i in range(self._groundset_size):
229
if self._groundset[i] in l:
230
E.append(l[self._E[i]])
231
else:
232
E.append(self._E[i])
233
self._groundset = E
234
self._idx = {}
235
for i in xrange(self._groundset_size):
236
self._idx[self._groundset[i]] = i
237
238
cpdef _complements(self):
239
"""
240
Return a SetSystem containing the complements of each element in the
241
groundset.
242
243
EXAMPLES::
244
245
sage: from sage.matroids.set_system import SetSystem
246
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
247
sage: T = S._complements()
248
sage: for t in T: print sorted(t)
249
[3, 4]
250
[1, 2]
251
[3]
252
253
"""
254
cdef SetSystem S
255
if self._groundset_size == 0:
256
return self
257
S = SetSystem(self._groundset, capacity=len(self))
258
for i in xrange(len(self)):
259
bitset_complement(self._temp, self._subsets[i])
260
S._append(self._temp)
261
return S
262
263
cdef inline resize(self, k=None):
264
"""
265
Change the capacity of the SetSystem.
266
"""
267
if k is None:
268
k = self._len
269
for i in xrange(k, self._len):
270
bitset_free(self._subsets[i])
271
self._len = min(self._len, k)
272
k2 = max(k, 1)
273
self._subsets = <bitset_t*> sage_realloc(self._subsets, k2 * sizeof(bitset_t))
274
self._capacity = k2
275
276
cdef inline _append(self, bitset_t X):
277
"""
278
Append subset in internal, bitset format
279
"""
280
if self._capacity == self._len:
281
self.resize(self._capacity * 2)
282
bitset_init(self._subsets[self._len], self._bitset_size)
283
bitset_copy(self._subsets[self._len], X)
284
self._len += 1
285
286
cdef inline append(self, X):
287
"""
288
Append subset.
289
"""
290
if self._capacity == self._len:
291
self.resize(self._capacity * 2)
292
bitset_init(self._subsets[self._len], self._bitset_size)
293
bitset_clear(self._subsets[self._len])
294
for x in X:
295
bitset_add(self._subsets[self._len], self._idx[x])
296
self._len += 1
297
298
cdef inline _subset(self, long k):
299
"""
300
Return the k-th subset, in index format.
301
"""
302
return bitset_list(self._subsets[k])
303
304
cdef subset(self, k):
305
"""
306
Return the k-th subset.
307
"""
308
cdef long i
309
F = set()
310
i = bitset_first(self._subsets[k])
311
while i >= 0:
312
F.add(self._groundset[i])
313
i = bitset_next(self._subsets[k], i + 1)
314
return frozenset(F)
315
316
cpdef _get_groundset(self):
317
"""
318
Return the ground set of this SetSystem.
319
320
EXAMPLES::
321
322
sage: from sage.matroids.set_system import SetSystem
323
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
324
sage: sorted(S._get_groundset())
325
[1, 2, 3, 4]
326
"""
327
return frozenset(self._groundset)
328
329
# isomorphism
330
331
cdef list _incidence_count(self, E):
332
"""
333
For the sub-collection indexed by ``E``, count how often each element
334
occurs.
335
"""
336
cdef long i, e
337
cdef list cnt
338
cnt = [0 for v in xrange(self._groundset_size)]
339
for e in E:
340
i = bitset_first(self._subsets[e])
341
while i >= 0:
342
cnt[i] += 1
343
i = bitset_next(self._subsets[e], i + 1)
344
return cnt
345
346
cdef SetSystem _groundset_partition(self, SetSystem P, list cnt):
347
"""
348
Helper method for partition methods below.
349
"""
350
cdef dict C
351
cdef long i, j, v, t0, t
352
cdef bint split
353
354
C = {}
355
for i in xrange(len(P)):
356
v = bitset_first(P._subsets[i])
357
if v < 0:
358
continue
359
t0 = cnt[v]
360
v = bitset_next(P._subsets[i], v + 1)
361
split = False
362
while v >= 0:
363
t = cnt[v]
364
if t != t0:
365
split = True
366
if t < t0:
367
t0 = t
368
v = bitset_next(P._subsets[i], v + 1)
369
if split:
370
C.clear()
371
v = bitset_first(P._subsets[i])
372
while v >= 0:
373
t = cnt[v]
374
if t != t0:
375
if t in C:
376
C[t].add(v)
377
else:
378
C[t] = set([v])
379
v = bitset_next(P._subsets[i], v + 1)
380
for t in sorted(C):
381
bitset_clear(self._temp)
382
for v in C[t]:
383
bitset_add(self._temp, v)
384
bitset_discard(P._subsets[i], v)
385
P._append(self._temp)
386
387
cdef long subset_characteristic(self, SetSystem P, long e):
388
"""
389
Helper method for partition methods below.
390
"""
391
cdef long c
392
c = 0
393
for p in xrange(len(P)):
394
c <<= bitset_len(P._subsets[p])
395
bitset_intersection(self._temp, P._subsets[p], self._subsets[e])
396
c += bitset_len(self._temp)
397
return c
398
399
cdef subsets_partition(self, SetSystem P=None, E=None):
400
"""
401
Helper method for partition methods below.
402
"""
403
S = {}
404
if P is None:
405
P = self.groundset_partition()
406
if E is None:
407
E = xrange(self._len)
408
if len(E) == 0:
409
return [E]
410
411
ED = [(self.subset_characteristic(P, e), e) for e in E]
412
ED.sort()
413
414
EP = []
415
ep = []
416
d = ED[0][0]
417
eh = [d]
418
for ed in ED:
419
if ed[0] != d:
420
EP.append(ep)
421
ep = [ed[1]]
422
d = ed[0]
423
else:
424
ep.append(ed[1])
425
eh.append(ed[0])
426
EP.append(ep)
427
return EP, hash(tuple(eh))
428
429
cdef _distinguish(self, v):
430
"""
431
Helper method for partition methods below.
432
"""
433
cdef SetSystem S
434
S = SetSystem(self._groundset, capacity=len(self) + 1)
435
bitset_clear(self._temp)
436
bitset_add(self._temp, v)
437
for i in xrange(len(self)):
438
bitset_difference(S._temp, self._subsets[i], self._temp)
439
S._append(S._temp)
440
S._append(self._temp)
441
return S
442
443
# partition functions
444
cdef initial_partition(self, SetSystem P=None, E=None):
445
"""
446
Helper method for partition methods below.
447
"""
448
if E is None:
449
E = xrange(self._len)
450
if P is None:
451
P = SetSystem(self._groundset, [self._groundset], capacity=self._groundset_size)
452
cnt = self._incidence_count(E)
453
self._groundset_partition(P, cnt)
454
return P
455
456
cpdef _equitable_partition(self, SetSystem P=None, EP=None):
457
"""
458
Return an equitable ordered partition of the ground set of the
459
hypergraph whose edges are the subsets in this SetSystem.
460
461
Given any ordered partition `P = (p_1, ..., p_k)` of the ground set of
462
a hypergraph, any edge `e` of the hypergraph has a characteristic
463
intersection number sequence `i(e)=(|p_1\cap e|, ... , |p_k\cap e|))`.
464
There is an ordered partition `EP` of the edges that groups the edges
465
according to this intersection number sequence. Given this an ordered
466
partition of the edges, we may similarly refine `P` to a new ordered
467
partition `P'`, by considering the incidence numbers of ground set
468
elements with each partition element of `EP`.
469
470
The ordered partition `P` is equitable when `P' = P`.
471
472
INPUT:
473
474
- ``P``, an equitable ordered partition of the ground set, stored as
475
a SetSystem.
476
- ``EP``, the corresponding equitable partition of the edges, stored
477
as a list of lists of indices of subsets of this SetSystem.
478
479
OUTPUT:
480
481
- ``P``, an equitable ordered partition of the ground set, stored as a
482
SetSystem.
483
- ``EP``, the corresponding equitable partition of the edges, stored
484
as a list of lists of indices of subsets of this SetSystem.
485
- ``h``, an integer invariant of the SetSystem.
486
487
EXAMPLES::
488
489
sage: from sage.matroids.set_system import SetSystem
490
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
491
sage: for p in S._equitable_partition()[0]: print sorted(p)
492
[3]
493
[4]
494
[1, 2]
495
sage: T = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 3, 4]])
496
sage: for p in T._equitable_partition()[0]: print sorted(p)
497
[2]
498
[1]
499
[3, 4]
500
501
.. NOTE::
502
503
We do not maintain any well-defined order when refining a
504
partition. We do maintain that the resulting order of the
505
partition elements is an invariant of the isomorphism class of the
506
hypergraph.
507
"""
508
cdef long h, l
509
cdef list EP2, H
510
511
if P is None:
512
P = self.initial_partition()
513
else:
514
P = P.copy()
515
if EP is None:
516
EP = self.subsets_partition(P)[0]
517
518
h = len(EP)
519
pl = 0
520
while len(P) > pl:
521
H = [h]
522
pl = len(P)
523
EP2 = []
524
for ep in EP:
525
SP, h = self.subsets_partition(P, ep)
526
H.append(h)
527
for p in SP:
528
cnt = self._incidence_count(p)
529
self._groundset_partition(P, cnt)
530
if len(p) > 1:
531
EP2.append(p)
532
EP = EP2
533
h = hash(tuple(H))
534
535
return P, EP, h
536
537
cpdef _heuristic_partition(self, SetSystem P=None, EP=None):
538
"""
539
Return an heuristic ordered partition into singletons of the ground
540
set of the hypergraph whose edges are the subsets in this SetSystem.
541
542
This partition obtained as follows: make an equitable
543
partition ``P``, and while ``P`` has a partition element ``p`` with
544
more than one element, select an arbitrary ``e`` from the first such
545
``p`` and split ``p`` into ``p-e``. Then replace ``P`` with
546
the equitabele refinement of this partition.
547
548
INPUT:
549
550
- ``P`` -- (default: ``None``) an ordered partition of the ground set.
551
- ``EP`` -- (default: ``None``) the corresponding partition of the
552
edges, stored as a list of lists of indices of subsets of this
553
SetSystem.
554
555
OUTPUT:
556
557
- ``P`` -- an ordered partition of the ground set into singletons,
558
stored as a SetSystem.
559
- ``EP`` -- the corresponding partition of the edges, stored as a list
560
of lists of indices of subsets of this SetSystem.
561
- ``h`` -- an integer invariant of the SetSystem.
562
563
EXAMPLES::
564
565
sage: from sage.matroids.set_system import SetSystem
566
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
567
sage: for p in S._heuristic_partition()[0]: print sorted(p)
568
[3]
569
[4]
570
[2]
571
[1]
572
sage: T = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 3, 4]])
573
sage: for p in T._heuristic_partition()[0]: print sorted(p)
574
[2]
575
[1]
576
[4]
577
[3]
578
"""
579
P, EP, h = self._equitable_partition(P, EP)
580
for i in xrange(len(P)):
581
if bitset_len(P._subsets[i]) > 1:
582
return self._heuristic_partition(P._distinguish(bitset_first(P._subsets[i])), EP)
583
return P, EP, h
584
585
cpdef _isomorphism(self, SetSystem other, SetSystem SP=None, SetSystem OP=None):
586
"""
587
Return a groundset isomorphism between this SetSystem and an other.
588
589
INPUT:
590
591
- ``other`` -- a SetSystem
592
- ``SP`` (optional) -- a SetSystem storing an ordered partition of the
593
ground set of ``self``
594
- ``OP`` (optional) -- a SetSystem storing an ordered partition of the
595
ground set of ``other``
596
597
OUTPUT:
598
599
``morphism`` -- a dictionary containing an isomorphism respecting the
600
given ordered partitions, or ``None`` if no such isomorphism exists.
601
602
EXAMPLES::
603
604
sage: from sage.matroids.set_system import SetSystem
605
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
606
sage: T = SetSystem(['a', 'b', 'c', 'd'], [['a', 'b'], ['c', 'd'],
607
....: ['a', 'c', 'd']])
608
sage: S._isomorphism(T)
609
{1: 'c', 2: 'd', 3: 'b', 4: 'a'}
610
"""
611
cdef long l, p
612
if SP is None or OP is None:
613
SP, SEP, sh = self._equitable_partition()
614
OP, OEP, oh = other._equitable_partition()
615
if sh != oh:
616
return None
617
if len(SP) != len(OP):
618
return None
619
p = SP._groundset_size + 1
620
for i in xrange(len(SP)):
621
l = bitset_len(SP._subsets[i])
622
if l != bitset_len(OP._subsets[i]):
623
return None
624
if l != 1 and l < p:
625
p = l
626
for i in xrange(len(SP)):
627
if bitset_len(SP._subsets[i]) == p:
628
SP2, SEP, sh = self._equitable_partition(SP._distinguish(bitset_first(SP._subsets[i])))
629
v = bitset_first(OP._subsets[i])
630
while v >= 0:
631
OP2, OEP, oh = other._equitable_partition(OP._distinguish(v))
632
if sh == oh:
633
m = self._isomorphism(other, SP2, OP2)
634
if m is not None:
635
return m
636
v = bitset_next(OP._subsets[i], v + 1)
637
return None
638
if sorted([self.subset_characteristic(SP, i) for i in xrange(len(self))]) != sorted([other.subset_characteristic(OP, i) for i in xrange(len(other))]):
639
return None
640
return dict([(self._groundset[bitset_first(SP._subsets[i])], other._groundset[bitset_first(OP._subsets[i])]) for i in xrange(len(SP))])
641
642
cpdef _equivalence(self, is_equiv, SetSystem other, SetSystem SP=None, SetSystem OP=None):
643
"""
644
Return a groundset isomorphism that is an equivalence between this
645
SetSystem and an other.
646
647
INPUT:
648
649
- ``is_equiv`` -- a function that determines if a given groundset
650
isomorphism is a valid equivalence
651
- ``other`` -- a SetSystem
652
- ``SP`` (optional) -- a SetSystem storing an ordered partition of the
653
groundset of ``self``
654
- ``OP`` (optional) -- a SetSystem storing an ordered partition of the
655
groundset of ``other``
656
657
OUTPUT:
658
659
``morphism``, a dictionary containing an isomorphism respecting the
660
given ordered partitions, so that ``is_equiv(self, other, morphism)``
661
is ``True``; or ``None`` if no such equivalence exists.
662
663
EXAMPLES::
664
665
sage: from sage.matroids.set_system import SetSystem
666
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
667
sage: T = SetSystem(['a', 'b', 'c', 'd'], [['a', 'b'], ['c', 'd'],
668
....: ['a', 'c', 'd']])
669
sage: S._equivalence(lambda self, other, morph:True, T)
670
{1: 'c', 2: 'd', 3: 'b', 4: 'a'}
671
672
Check that Trac #15189 is fixed::
673
674
sage: M = Matroid(ring=GF(5), reduced_matrix=[[1,0,3],[0,1,1],[1,1,0]])
675
sage: N = Matroid(ring=GF(5), reduced_matrix=[[1,0,1],[0,1,1],[1,1,0]])
676
sage: M.is_field_isomorphic(N)
677
False
678
sage: any(M.is_field_isomorphism(N, p) for p in Permutations(range(6)))
679
False
680
"""
681
if SP is None or OP is None:
682
SP, SEP, sh = self._equitable_partition()
683
OP, OEP, oh = other._equitable_partition()
684
if sh != oh:
685
return None
686
if len(SP) != len(OP):
687
return None
688
for i in xrange(len(SP)):
689
if bitset_len(SP._subsets[i]) != bitset_len(OP._subsets[i]):
690
return None
691
for i in xrange(len(SP)):
692
if bitset_len(SP._subsets[i]) > 1:
693
SP2, SEP, sh = self._equitable_partition(SP._distinguish(bitset_first(SP._subsets[i])))
694
v = bitset_first(OP._subsets[i])
695
while v >= 0:
696
OP2, OEP, oh = other._equitable_partition(OP._distinguish(v))
697
if sh == oh:
698
m = self._equivalence(is_equiv, other, SP2, OP2)
699
if m is not None:
700
return m
701
v = bitset_next(OP._subsets[i], v + 1)
702
return None
703
morph = dict([(self._groundset[bitset_first(SP._subsets[i])], other._groundset[bitset_first(OP._subsets[i])]) for i in xrange(len(SP))])
704
if is_equiv(self, other, morph):
705
return morph
706
707
708
cdef class SetSystemIterator:
709
def __init__(self, H):
710
"""
711
Create an iterator for a SetSystem.
712
713
Called internally when iterating over the contents of a SetSystem.
714
715
EXAMPLES::
716
717
sage: from sage.matroids.set_system import SetSystem
718
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
719
sage: type(S.__iter__())
720
<type 'sage.matroids.set_system.SetSystemIterator'>
721
"""
722
self._H = H
723
self._pointer = -1
724
self._len = len(H)
725
726
def __next__(self):
727
"""
728
Return the next subset of a SetSystem.
729
730
EXAMPLES::
731
732
sage: from sage.matroids.set_system import SetSystem
733
sage: S = SetSystem([1, 2, 3, 4], [[1, 2], [3, 4], [1, 2, 4]])
734
sage: I = S.__iter__()
735
sage: sorted(I.__next__())
736
[1, 2]
737
sage: sorted(I.__next__())
738
[3, 4]
739
sage: sorted(I.__next__())
740
[1, 2, 4]
741
"""
742
self._pointer += 1
743
if self._pointer == self._len:
744
self._pointer = -1
745
raise StopIteration
746
else:
747
return self._H.subset(self._pointer)
748
749