Skip to content

Commit

Permalink
gh-37940: Support morphisms in Matroid constructor
Browse files Browse the repository at this point in the history
    
This follows the merging of #37692 and it enables the (re-)feeding of a
linear matroid's morphism representation into the `Matroid` constructor.

Example:
```
sage: M = matroids.catalog.Fano()
sage: A = M.representation(order=True); A
Generic morphism:
  From: Free module generated by {'a', 'b', 'c', 'd', 'e', 'f', 'g'}
over Finite Field of size 2
  To:   Free module generated by {0, 1, 2} over Finite Field of size 2
sage: Matroid(A)
Binary matroid of rank 3 on 7 elements, type (3, 0)
```
    
URL: #37940
Reported by: gmou3
Reviewer(s): gmou3, Matthias Köppe, Travis Scrimshaw
  • Loading branch information
Release Manager committed May 12, 2024
2 parents 5d12c34 + 13e499a commit 3fdc4d2
Showing 1 changed file with 67 additions and 5 deletions.
72 changes: 67 additions & 5 deletions src/sage/matroids/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ def Matroid(groundset=None, data=None, **kwds):
``reduced_matrix = A``
then the matroid is represented by `[I\ \ A]` where `I` is an
appropriately sized identity matrix.
- ``morphism`` -- A morphism representation of the matroid.
- ``reduced_morphism`` -- A reduced morphism representation of the matroid.
- ``rank_function`` -- A function that computes the rank of each subset.
Can only be provided together with a groundset.
- ``circuit_closures`` -- Either a list of tuples ``(k, C)`` with ``C``
Expand Down Expand Up @@ -533,6 +535,48 @@ def Matroid(groundset=None, data=None, **kwds):
sage: M.base_ring()
Integer Ring
A morphism representation of a :class:`LinearMatroid` can also be used as
input::
sage: M = matroids.catalog.Fano()
sage: A = M.representation(order=True); A
Generic morphism:
From: Free module generated by {'a', 'b', 'c', 'd', 'e', 'f', 'g'} over
Finite Field of size 2
To: Free module generated by {0, 1, 2} over Finite Field of size 2
sage: A._unicode_art_matrix()
a b c d e f g
0⎛1 0 0 0 1 1 1⎞
1⎜0 1 0 1 0 1 1⎟
2⎝0 0 1 1 1 0 1⎠
sage: N = Matroid(A); N
Binary matroid of rank 3 on 7 elements, type (3, 0)
sage: N.groundset()
frozenset({'a', 'b', 'c', 'd', 'e', 'f', 'g'})
sage: M == N
True
The keywords ``morphism`` and ``reduced_morphism`` are also available::
sage: M = matroids.catalog.RelaxedNonFano("abcdefg")
sage: A = M.representation(order=True, reduced=True); A
Generic morphism:
From: Free module generated by {'d', 'e', 'f', 'g'} over
Finite Field in w of size 2^2
To: Free module generated by {'a', 'b', 'c'} over
Finite Field in w of size 2^2
sage: A._unicode_art_matrix()
d e f g
a⎛1 1 0 1⎞
b⎜1 0 1 1⎟
c⎝0 1 w 1⎠
sage: N = Matroid(reduced_morphism=A); N
Quaternary matroid of rank 3 on 7 elements
sage: N.groundset()
frozenset({'a', 'b', 'c', 'd', 'e', 'f', 'g'})
sage: M == N
True
#. Rank function:
Any function mapping subsets to integers can be used as input::
Expand Down Expand Up @@ -713,8 +757,8 @@ def Matroid(groundset=None, data=None, **kwds):
if data is None:
for k in ['bases', 'independent_sets', 'circuits',
'nonspanning_circuits', 'flats', 'graph', 'matrix',
'reduced_matrix', 'rank_function', 'revlex',
'circuit_closures', 'matroid']:
'reduced_matrix', 'morphism', 'reduced_morphism',
'rank_function', 'revlex', 'circuit_closures', 'matroid']:
if k in kwds:
data = kwds.pop(k)
key = k
Expand All @@ -732,8 +776,13 @@ def Matroid(groundset=None, data=None, **kwds):
Graph = ()
if isinstance(data, Graph):
key = 'graph'
elif is_Matrix(data):
elif is_Matrix(data) or (
isinstance(data, tuple) and is_Matrix(data[0])):
key = 'matrix'
elif isinstance(data, sage.modules.with_basis.morphism.ModuleMorphism) or (
isinstance(data, tuple) and
isinstance(data[0], sage.modules.with_basis.morphism.ModuleMorphism)):
key = 'morphism'
elif isinstance(data, sage.matroids.matroid.Matroid):
key = 'matroid'
elif isinstance(data, str):
Expand Down Expand Up @@ -856,9 +905,22 @@ def Matroid(groundset=None, data=None, **kwds):
M = GraphicMatroid(G, groundset=groundset)

# Matrices:
elif key in ['matrix', 'reduced_matrix']:
elif key in ['matrix', 'reduced_matrix', 'morphism', 'reduced_morphism']:
A = data
is_reduced = (key == 'reduced_matrix')
is_reduced = (key == 'reduced_matrix' or key == 'reduced_morphism')
if isinstance(data, tuple):
A = data[0]
if key == 'matrix' or key == 'reduced_matrix':
if groundset is None:
groundset = data[1]
if is_reduced:
groundset += data[2]
if key == 'morphism' or key == 'reduced_morphism':
if groundset is None:
groundset = list(A.domain().basis().keys())
if is_reduced:
groundset = list(A.codomain().basis().keys()) + groundset
A = A.matrix()

# Fix the representation
if not is_Matrix(A):
Expand Down

0 comments on commit 3fdc4d2

Please sign in to comment.