Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/matroids/rank_matroid.py
8817 views
1
r"""
2
Rank function matroids
3
4
The easiest way to define arbitrary matroids in Sage might be through the
5
class ``RankMatroid``. All that is required is a groundset and a function that
6
computes the rank for each given subset.
7
8
Of course, since the rank function is used as black box, matroids so defined
9
cannot take advantage of any extra structure your class might have, and rely
10
on default implementations. Besides this, matroids in this class can't be
11
saved.
12
13
Constructions
14
=============
15
Any function can be used, but no checks are performed, so be careful.
16
17
EXAMPLES::
18
19
sage: def f(X):
20
....: return min(len(X), 3)
21
....:
22
sage: M = Matroid(groundset=range(6), rank_function=f)
23
sage: M.is_valid()
24
True
25
sage: M.is_isomorphic(matroids.Uniform(3, 6))
26
True
27
28
sage: def g(X):
29
....: if len(X) >= 3:
30
....: return 1
31
....: else:
32
....: return 0
33
....:
34
sage: N = Matroid(groundset='abc', rank_function=g)
35
sage: N.is_valid()
36
False
37
38
See :class:`below <sage.matroids.rank_matroid.RankMatroid>` for more. It is
39
recommended to use the :func:`Matroid() <sage.matroids.constructor.Matroid>`
40
function for easy construction of a ``RankMatroid``. For direct access to the
41
``RankMatroid`` constructor, run::
42
43
sage: from sage.matroids.advanced import *
44
45
AUTHORS:
46
47
- Rudi Pendavingh, Stefan van Zwam (2013-04-01): initial version
48
49
Methods
50
=======
51
"""
52
#*****************************************************************************
53
# Copyright (C) 2013 Rudi Pendavingh <[email protected]>
54
# Copyright (C) 2013 Stefan van Zwam <[email protected]>
55
#
56
#
57
# Distributed under the terms of the GNU General Public License (GPL)
58
# as published by the Free Software Foundation; either version 2 of
59
# the License, or (at your option) any later version.
60
# http://www.gnu.org/licenses/
61
#*****************************************************************************
62
from matroid import Matroid
63
64
65
class RankMatroid(Matroid):
66
"""
67
Matroid specified by its rank function.
68
69
INPUT:
70
71
- ``groundset`` -- the groundset of a matroid.
72
- ``rank_function`` -- a function mapping subsets of ``groundset`` to
73
nonnegative integers.
74
75
OUTPUT:
76
77
A matroid on ``groundset`` whose rank function equals ``rank_function``
78
79
EXAMPLES::
80
81
sage: from sage.matroids.advanced import *
82
sage: def f(X):
83
....: return min(len(X), 3)
84
....:
85
sage: M = RankMatroid(groundset=range(6), rank_function=f)
86
sage: M.is_valid()
87
True
88
sage: M.is_isomorphic(matroids.Uniform(3, 6))
89
True
90
91
"""
92
def __init__(self, groundset, rank_function):
93
"""
94
Initialize the rank matroid.
95
96
EXAMPLES::
97
98
sage: from sage.matroids.advanced import *
99
sage: M = RankMatroid(range(6),
100
....: rank_function=matroids.Uniform(3, 6).rank)
101
sage: M
102
Matroid of rank 3 on 6 elements
103
104
"""
105
self._groundset = frozenset(groundset)
106
self._rank_function = rank_function
107
108
def groundset(self):
109
r"""
110
Return the groundset of ``self``.
111
112
EXAMPLES::
113
114
sage: from sage.matroids.advanced import *
115
sage: M = RankMatroid(range(6),
116
....: rank_function=matroids.Uniform(3, 6).rank)
117
sage: sorted(M.groundset())
118
[0, 1, 2, 3, 4, 5]
119
120
"""
121
return self._groundset
122
123
def _rank(self, X):
124
r"""
125
Return the rank of set `X`.
126
127
Internal function without any sanity checks. May assume that ``X``
128
has Python's ``frozenset`` interface and is a subset of
129
self.groundset().
130
131
EXAMPLES::
132
133
sage: from sage.matroids.advanced import *
134
sage: M = RankMatroid(range(6),
135
....: rank_function=matroids.Uniform(3, 6).rank)
136
sage: M._rank([0, 2, 4, 5])
137
3
138
"""
139
return self._rank_function(X)
140
141
# Comparison:
142
143
def __hash__(self):
144
r"""
145
Return a string invariant of the matroid.
146
147
This function is called when matroids are added to a set. It is very
148
desirable to override it so it can distinguish matroids on the same
149
groundset, which is a very typical use case!
150
151
.. WARNING::
152
153
This method is linked to __richcmp__ (in Cython) and __cmp__ or
154
__eq__/__ne__ (in Python). If you override one, you should (and in
155
Cython: MUST) override the other!
156
157
EXAMPLES::
158
159
sage: from sage.matroids.advanced import *
160
sage: M = Matroid(groundset=range(10),
161
....: rank_function=lambda X: min(len(X), 4))
162
sage: N = Matroid(groundset=range(10),
163
....: rank_function=lambda X: min(len(X), 4))
164
sage: O = Matroid(groundset=range(10),
165
....: rank_function=lambda X: min(len(X), 3))
166
sage: hash(M) == hash(N)
167
True
168
sage: hash(M) == hash(O)
169
False
170
"""
171
return hash((self.groundset(), self.full_rank()))
172
173
def __eq__(self, other):
174
"""
175
Compare two matroids.
176
177
INPUT:
178
179
- ``other`` -- A matroid.
180
181
OUTPUT:
182
183
``True`` if ``self`` and ``other have the same groundset and the same
184
rank function; ``False`` otherwise.
185
186
.. NOTE::
187
188
Note that rank functions ``f`` and ``g`` are normally deemed equal
189
only if ``f is g``. It would be too time-consuming to check all
190
their values.
191
192
EXAMPLES::
193
194
sage: from sage.matroids.advanced import *
195
sage: def f(X):
196
....: return min(len(X), 3)
197
....:
198
sage: def g(X):
199
....: return min(len(X), 3)
200
....:
201
sage: M1 = RankMatroid(groundset=range(6), rank_function=f)
202
sage: M2 = RankMatroid(groundset=range(6), rank_function=g)
203
sage: M3 = RankMatroid(groundset=range(7), rank_function=f)
204
sage: M4 = RankMatroid(groundset=range(6), rank_function=f)
205
sage: M1 == M2 # indirect doctest
206
False
207
sage: M1 == M3
208
False
209
sage: M1 == M4
210
True
211
"""
212
if not isinstance(other, RankMatroid):
213
return False
214
return (self.groundset() == other.groundset()) and (self._rank_function == other._rank_function)
215
216
def __ne__(self, other):
217
"""
218
Compare two matroids.
219
220
INPUT:
221
222
- ``other`` -- A matroid.
223
224
OUTPUT:
225
226
``False`` if ``self`` and ``other have the same groundset and the
227
same rank function; ``True`` otherwise.
228
229
.. NOTE::
230
231
Rank functions ``f`` and ``g`` are normally deemed equal only if
232
``f is g``. It would be too time-consuming to check all their
233
values.
234
235
EXAMPLES::
236
237
sage: from sage.matroids.advanced import *
238
sage: def f(X):
239
....: return min(len(X), 3)
240
....:
241
sage: def g(X):
242
....: return min(len(X), 3)
243
....:
244
sage: M1 = RankMatroid(groundset=range(6), rank_function=f)
245
sage: M2 = RankMatroid(groundset=range(6), rank_function=g)
246
sage: M3 = RankMatroid(groundset=range(7), rank_function=f)
247
sage: M4 = RankMatroid(groundset=range(6), rank_function=f)
248
sage: M1 != M2 # indirect doctest
249
True
250
sage: M1 != M3
251
True
252
sage: M1 != M4
253
False
254
"""
255
return not self.__eq__(other)
256
257
# Copying, loading, saving:
258
259
def __copy__(self):
260
"""
261
Create a shallow copy.
262
263
EXAMPLES::
264
265
sage: from sage.matroids.advanced import *
266
sage: M = Matroid(groundset=range(10),
267
....: rank_function=lambda X: min(len(X), 4))
268
sage: N = copy(M) # indirect doctest
269
sage: M == N
270
True
271
sage: M.groundset() is N.groundset()
272
True
273
"""
274
from copy import copy
275
N = RankMatroid(groundset=[], rank_function=None)
276
N._groundset = self._groundset
277
N._rank_function = self._rank_function
278
if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default copy
279
N.rename(getattr(self, '__custom_name'))
280
return N
281
282
def __deepcopy__(self, memo={}):
283
"""
284
Create a deep copy.
285
286
.. NOTE::
287
288
Since matroids are immutable, a shallow copy normally suffices.
289
290
EXAMPLES::
291
292
sage: M = Matroid(groundset=range(10),
293
....: rank_function=lambda X: min(len(X), 4))
294
sage: N = deepcopy(M) # indirect doctest
295
sage: M == N
296
True
297
sage: M.groundset() is N.groundset()
298
False
299
"""
300
from copy import deepcopy
301
# Since matroids are immutable, N cannot reference itself in correct code, so no need to worry about the recursion.
302
N = RankMatroid(groundset=deepcopy(self._groundset), rank_function=deepcopy(self._rank_function))
303
if getattr(self, '__custom_name') is not None: # because of name wrangling, this is not caught by the default deepcopy
304
N.rename(deepcopy(getattr(self, '__custom_name'), memo))
305
return N
306
307
def __reduce__(self):
308
"""
309
Save the matroid for later reloading.
310
311
.. NOTE::
312
313
Unfortunately, functions cannot be pickled reliably, so this class
314
doesn't have load/save support
315
316
EXAMPLES::
317
318
sage: M = Matroid(groundset=range(10),
319
....: rank_function=lambda X: min(len(X), 4))
320
sage: M == loads(dumps(M)) # indirect doctest
321
Traceback (most recent call last):
322
...
323
TypeError: unfortunately, functions cannot be saved reliably, so
324
this class doesn't have load/save support. Convert to another
325
class, such as BasisMatroid, instead.
326
327
"""
328
raise TypeError("unfortunately, functions cannot be saved reliably, so this class doesn't have load/save support. Convert to another class, such as BasisMatroid, instead.")
329
330