Skip to content

Commit

Permalink
DualMatroid: Add is_valid and relabel methods
Browse files Browse the repository at this point in the history
  • Loading branch information
gmou3 committed May 16, 2024
1 parent ffbbea9 commit b993b9f
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 82 deletions.
3 changes: 1 addition & 2 deletions src/sage/matroids/database_matroids.py
Original file line number Diff line number Diff line change
Expand Up @@ -1489,7 +1489,7 @@ def K5dual(groundset='abcdefghij'):
EXAMPLES::
sage: M = matroids.catalog.K5dual(); M
M*(K5): Matroid of rank 6 on 10 elements with 15 circuits
M*(K5): Dual of 'Graphic matroid of rank 4 on 10 elements'
sage: M.is_3connected()
True
sage: G1 = M.automorphism_group()
Expand All @@ -1502,7 +1502,6 @@ def K5dual(groundset='abcdefghij'):
[Oxl2011]_, p. 656.
"""
M = CompleteGraphic(5).dual()
M = Matroid(circuits=list(M.circuits()))
M = _rename_and_relabel(M, "M*(K5)", groundset)
return M

Expand Down
197 changes: 117 additions & 80 deletions src/sage/matroids/dual_matroid.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Theory
======
Let `M` be a matroid with ground set `E`. If `B` is the set of bases of `M`,
Let `M` be a matroid with groundset `E`. If `B` is the set of bases of `M`,
then the set `\{E - b : b \in B\}` is the set of bases of another matroid, the
dual of `M`.
Expand All @@ -24,25 +24,21 @@
The class ``DualMatroid`` wraps around a matroid instance to represent its
dual. Only useful for classes that don't have an explicit construction of the
dual (such as :class:`RankMatroid <sage.matroids.rank_matroid.RankMatroid>`
and
dual (such as :class:`RankMatroid <sage.matroids.rank_matroid.RankMatroid>` and
:class:`CircuitClosuresMatroid <sage.matroids.circuit_closures_matroid.CircuitClosuresMatroid>`).
It is also used as default implementation of the method
It is also used as the default implementation of the method
:meth:`M.dual() <sage.matroids.matroid.Matroid.dual>`.
For direct access to the ``DualMatroid`` constructor, run::
sage: from sage.matroids.advanced import *
See also :mod:`sage.matroids.advanced`.
AUTHORS:
- Rudi Pendavingh, Michael Welsh, Stefan van Zwam (2013-04-01): initial version
Methods
=======
"""

# ****************************************************************************
# Copyright (C) 2013 Rudi Pendavingh <[email protected]>
# Copyright (C) 2013 Michael Welsh <[email protected]>
Expand All @@ -57,19 +53,18 @@

from .matroid import Matroid


class DualMatroid(Matroid):
r"""
Dual of a matroid.
For some matroid representations it can be computationally expensive to
derive an explicit representation of the dual. This class wraps around any
matroid to provide an abstract dual. It also serves as default
implementation.
matroid to provide an abstract dual. It also serves as the default
implementation of the dual.
INPUT:
- ``matroid`` - a matroid.
- ``matroid`` -- matroid
EXAMPLES::
Expand Down Expand Up @@ -103,9 +98,17 @@ def __init__(self, matroid):
{'a', 'b', 'g', 'h'}, {'c', 'd', 'e', 'f'},
{'e', 'f', 'g', 'h'}},
4: {{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}}}'
TESTS::
sage: from sage.matroids.dual_matroid import DualMatroid
sage: DualMatroid([])
Traceback (most recent call last):
...
TypeError: no matroid provided to take the dual of
"""
if not isinstance(matroid, Matroid):
raise TypeError("no matroid provided to take dual of.")
raise TypeError("no matroid provided to take the dual of")
self._matroid = matroid

def groundset(self):
Expand All @@ -114,9 +117,7 @@ def groundset(self):
The groundset is the set of elements that comprise the matroid.
OUTPUT:
A set.
OUTPUT: set
EXAMPLES::
Expand All @@ -135,11 +136,9 @@ def _rank(self, X):
INPUT:
- ``X`` -- an object with Python's ``frozenset`` interface.
OUTPUT:
- ``X`` -- an object with Python's ``frozenset`` interface
The rank of ``X`` in the matroid.
OUTPUT: integer
EXAMPLES::
Expand All @@ -155,12 +154,10 @@ def _corank(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface
containing a subset of ``self.groundset()``.
- ``X`` -- an object with Python's ``frozenset`` interface
containing a subset of ``self.groundset()``
OUTPUT:
The corank of ``X``.
OUTPUT: integer
EXAMPLES::
Expand All @@ -176,12 +173,10 @@ def _max_independent(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``.
OUTPUT:
- ``X`` -- an object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``
A maximal independent subset of ``X``.
OUTPUT: a maximal independent subset of ``X``
EXAMPLES::
Expand All @@ -202,13 +197,11 @@ def _circuit(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``.
OUTPUT:
- ``X`` -- an object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``
A circuit contained in ``X``, if it exists. Otherwise an error is
raised.
OUTPUT: a circuit contained in ``X``, if it exists; otherwise, an error is
raised
EXAMPLES::
Expand All @@ -230,12 +223,10 @@ def _closure(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``.
OUTPUT:
- ``X`` -- an object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``
The smallest closed set containing ``X``.
OUTPUT: the smallest closed set containing ``X``
EXAMPLES::
Expand All @@ -251,12 +242,10 @@ def _max_coindependent(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``.
OUTPUT:
- ``X`` -- an object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``
A maximal coindependent subset of ``X``.
OUTPUT: a maximal coindependent subset of ``X``
EXAMPLES::
Expand All @@ -277,12 +266,10 @@ def _coclosure(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``.
- ``X`` -- an object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``
OUTPUT:
The smallest coclosed set containing ``X``.
OUTPUT: the smallest coclosed set containing ``X``
EXAMPLES::
Expand All @@ -298,13 +285,11 @@ def _cocircuit(self, X):
INPUT:
- ``X`` -- An object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``.
OUTPUT:
- ``X`` -- an object with Python's ``frozenset`` interface containing
a subset of ``self.groundset()``
A cocircuit contained in ``X``, if it exists. Otherwise an error is
raised.
OUTPUT: a cocircuit contained in ``X``, if it exists; otherwise, an error is
raised
EXAMPLES::
Expand All @@ -324,23 +309,21 @@ def _minor(self, contractions=None, deletions=None):
INPUT:
- ``contractions`` -- An object with Python's ``frozenset`` interface
containing a subset of ``self.groundset()``.
- ``deletions`` -- An object with Python's ``frozenset`` interface
containing a subset of ``self.groundset()``.
- ``contractions`` -- an object with Python's ``frozenset`` interface
containing a subset of ``self.groundset()``
- ``deletions`` -- an object with Python's ``frozenset`` interface
containing a subset of ``self.groundset()``
OUTPUT:
A ``DualMatroid`` instance representing
OUTPUT: a :class:`DualMatroid` representing
`(``self._matroid`` / ``deletions`` \ ``contractions``)^*`
.. NOTE::
This method does NOT do any checks. Besides the assumptions above,
we assume the following:
- ``contractions`` is independent
- ``deletions`` is coindependent
- ``contractions`` is independent;
- ``deletions`` is coindependent;
- ``contractions`` and ``deletions`` are disjoint.
EXAMPLES::
Expand All @@ -364,16 +347,13 @@ def dual(self):
r"""
Return the dual of the matroid.
Let `M` be a matroid with ground set `E`. If `B` is the set of bases
Let `M` be a matroid with groundset `E`. If `B` is the set of bases
of `M`, then the set `\{E - b : b \in B\}` is the set of bases of
another matroid, the *dual* of `M`. Note that the dual of the dual of
`M` equals `M`, so if this is the
:class:`DualMatroid` instance
`M` equals `M`, so if this is the :class:`DualMatroid` instance
wrapping `M` then the returned matroid is `M`.
OUTPUT:
The dual matroid.
OUTPUT: the dual matroid
EXAMPLES::
Expand Down Expand Up @@ -439,11 +419,9 @@ def __eq__(self, other):
INPUT:
- ``other`` -- A matroid.
- ``other`` -- matroid
OUTPUT:
Boolean.
OUTPUT: boolean
EXAMPLES::
Expand Down Expand Up @@ -471,11 +449,9 @@ def __ne__(self, other):
INPUT:
- ``other`` -- A matroid.
OUTPUT:
- ``other`` -- matroid
Boolean.
OUTPUT: boolean
EXAMPLES::
Expand Down Expand Up @@ -526,3 +502,64 @@ def __reduce__(self):
data = (self._matroid, self.get_custom_name())
version = 0
return sage.matroids.unpickling.unpickle_dual_matroid, (version, data)

def relabel(self, mapping):
r"""
Return an isomorphic matroid with relabeled groundset.
The output is obtained by relabeling each element ``e`` by
``mapping[e]``, where ``mapping`` is a given injective map. If
``e not in mapping`` then the identity map is assumed.
INPUT:
- ``mapping`` -- a python object such that `mapping[e]` is the new
label of `e`
OUTPUT: matroid
EXAMPLES::
sage: M = matroids.catalog.K5dual(range(10))
sage: type(M)
<class 'sage.matroids.dual_matroid.DualMatroid'>
sage: sorted(M.groundset())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
sage: N = M.dual().relabel({0:10})
sage: sorted(N.groundset())
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sage: N.is_isomorphic(matroids.catalog.K5())
True
TESTS::
sage: M = matroids.catalog.K5dual(range(10))
sage: f = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e',
....: 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j'}
sage: N = M.relabel(f)
sage: for S in powerset(M.groundset()):
....: assert M.rank(S) == N.rank([f[x] for x in S])
"""
M = self._matroid.relabel(mapping).dual()
return M

def is_valid(self):
"""
Test if ``self`` obeys the matroid axioms.
For a :class:`DualMatroid`, we check its dual.
OUTPUT: boolean
EXAMPLES::
sage: M = matroids.catalog.K5dual()
sage: type(M)
<class 'sage.matroids.dual_matroid.DualMatroid'>
sage: M.is_valid()
True
sage: M = Matroid([[0, 1], [2, 3]])
sage: M.dual().is_valid()
False
"""
return self._matroid.is_valid()

0 comments on commit b993b9f

Please sign in to comment.