Skip to content

Commit

Permalink
gh-38027: Work on FlatsMatroid
Browse files Browse the repository at this point in the history
    
Add class-optimized `_closure` and `_is_closed` methods.

Add input handling of a list of flats, and of a lattice of flats. Note
that previously one could only define a `FlatsMatroid` from a dictionary
of flats (indexed by their rank). The definition from a raw list
requires more time upon definition as it computes and stores the lattice
of flats from the input list. On the positive side, given this lattice,
some methods become blazingly fast (e.g., `is_valid`,
`whitney_numbers`).

The lattice of flats is now cached upon computation.

### 📝 Checklist

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [ ] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.
    
URL: #38027
Reported by: gmou3
Reviewer(s): gmou3, Travis Scrimshaw
  • Loading branch information
Release Manager committed May 23, 2024
2 parents 886fb1d + 9bf7105 commit 6d02e7b
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 66 deletions.
1 change: 1 addition & 0 deletions src/sage/matroids/advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- :class:`MinorMatroid <sage.matroids.minor_matroid.MinorMatroid>`
- :class:`DualMatroid <sage.matroids.dual_matroid.DualMatroid>`
- :class:`RankMatroid <sage.matroids.rank_matroid.RankMatroid>`
- :class:`CircuitsMatroid <sage.matroids.circuits_matroid.CircuitsMatroid>`
- :class:`CircuitClosuresMatroid <sage.matroids.circuit_closures_matroid.CircuitClosuresMatroid>`
- :class:`BasisMatroid <sage.matroids.basis_matroid.BasisMatroid>`
- :class:`FlatsMatroid <sage.matroids.flats_matroid.FlatsMatroid>`
Expand Down
49 changes: 42 additions & 7 deletions src/sage/matroids/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@


from itertools import combinations
from sage.combinat.posets.lattices import FiniteLatticePoset
from sage.matrix.constructor import Matrix
from sage.structure.element import is_Matrix
from sage.rings.integer_ring import ZZ
Expand Down Expand Up @@ -181,7 +182,7 @@ def Matroid(groundset=None, data=None, **kwds):
- ``circuits`` -- The list of circuits of the matroid.
- ``nonspanning_circuits`` -- The list of nonspanning circuits of the
matroid.
- ``flats`` -- The dictionary of flats indexed by their rank.
- ``flats`` -- The dictionary, list, or lattice of flats of the matroid.
- ``graph`` -- A graph, whose edges form the elements of the matroid.
- ``matrix`` -- A matrix representation of the matroid.
- ``reduced_matrix`` -- A reduced representation of the matroid: if
Expand Down Expand Up @@ -326,25 +327,53 @@ def Matroid(groundset=None, data=None, **kwds):
Strange things can happen if the input does not satisfy the circuit
axioms, and these can be caught by the
:meth:`is_valid() <sage.matroids.matroid.Matroid.is_valid>` method. So
always check whether your input makes sense!
:meth:`is_valid() <sage.matroids.circuits_matroid.CircuitsMatroid.is_valid>`
method. So please check that your input makes sense!
::
sage: M = Matroid('abcd', circuits=['ab', 'acd'])
sage: M.is_valid()
False
#. Dictionary of flats:
#. Flats:
::
Given a dictionary of flats indexed by their rank, we get a
:class:`FlatsMatroid <sage.matroids.flats_matroid.FlatsMatroid>`::
sage: M = Matroid(flats={0: [''], 1: ['a', 'b'], 2: ['ab']})
sage: M.is_isomorphic(matroids.Uniform(2, 2)) and M.is_valid()
True
sage: type(M)
<class 'sage.matroids.flats_matroid.FlatsMatroid'>
If instead we simply provide a list of flats, then the class computes
and stores the lattice of flats upon definition. This can be
time-consuming, but after it's done we benefit from some faster methods
(e.g., :meth:`is_valid() <sage.matroids.flats_matroid.FlatsMatroid.is_valid>`)::
sage: M = Matroid(flats=['', 'a', 'b', 'ab'])
sage: for i in range(M.rank() + 1): # print flats by rank
....: print(f'{i}: {sorted([sorted(F) for F in M.flats(i)], key=str)}')
0: [[]]
1: [['a'], ['b']]
2: [['a', 'b']]
sage: M.is_valid()
True
sage: type(M)
<class 'sage.matroids.flats_matroid.FlatsMatroid'>
Finally, we can also directly provide a lattice of flats::
sage: from sage.combinat.posets.lattices import LatticePoset
sage: flats = [frozenset(F) for F in powerset('ab')]
sage: L_M = LatticePoset((flats, lambda x, y: x < y))
sage: M = Matroid(L_M)
sage: M.is_isomorphic(matroids.Uniform(2, 2)) and M.is_valid()
True
sage: type(M)
<class 'sage.matroids.flats_matroid.FlatsMatroid'>
#. Graph:
Sage has great support for graphs, see :mod:`sage.graphs.graph`.
Expand Down Expand Up @@ -787,6 +816,8 @@ def Matroid(groundset=None, data=None, **kwds):
key = 'matroid'
elif isinstance(data, str):
key = 'revlex'
elif isinstance(data, dict) or isinstance(data, FiniteLatticePoset):
key = 'flats'
elif data is None:
raise TypeError("no input data given for Matroid()")
else:
Expand Down Expand Up @@ -860,8 +891,12 @@ def Matroid(groundset=None, data=None, **kwds):
# Determine groundset
if groundset is None:
groundset = set()
for i in data:
for F in data[i]:
if isinstance(data, dict):
for i in data:
for F in data[i]:
groundset.update(F)
else: # iterable of flats (including lattice)
for F in data:
groundset.update(F)
M = FlatsMatroid(groundset=groundset, flats=data)

Expand Down
11 changes: 7 additions & 4 deletions src/sage/matroids/flats_matroid.pxd
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
from sage.matroids.matroid cimport Matroid
from .matroid cimport Matroid

cdef class FlatsMatroid(Matroid):
cdef frozenset _groundset # _E
cdef int _matroid_rank # _R
cdef frozenset _groundset
cdef int _matroid_rank
cdef dict _F # flats
cdef object _L # lattice of flats
cpdef groundset(self)
cpdef _rank(self, X)
cpdef full_rank(self)
cpdef _is_independent(self, F)
cpdef _closure(self, X)
cpdef _is_closed(self, X)

# enumeration
cpdef flats(self, k)
cpdef whitney_numbers(self)
cpdef whitney_numbers2(self)

# isomorphism and relabeling
Expand Down
Loading

0 comments on commit 6d02e7b

Please sign in to comment.