Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support morphisms in Matroid constructor #37940

Merged
merged 4 commits into from
May 12, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 60 additions & 4 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 @@ -734,6 +778,10 @@ def Matroid(groundset=None, data=None, **kwds):
key = 'graph'
elif is_Matrix(data):
key = 'matrix'
elif isinstance(data, sage.modules.with_basis.morphism.ModuleMorphism) or (
Copy link
Contributor

@mkoeppe mkoeppe May 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of using isinstance with this class, I think it's better to use isinstance(data, Morphism) and data.category_for().is_subcategory(Modules(data.base_ring()).WithBasis())

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what's best but the above doesn't seem to work.

isinstance(data, tuple) and
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I find "tuple" input very convincing.
Does it have a clear benefit over just passing the groundset via the groundset parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I did this is so that the following works:

sage: M = matroids.catalog.Fano()
sage: A = M.representation(order=True, labels=True)
sage: Matroid(A)
...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, ok

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to do something similar for matrices though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made it so that this also works and retains the groundset labels:

sage: M = matroids.catalog.Fano()
sage: A = M.representation(labels=True)
sage: Matroid(A)
...

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 +904,17 @@ 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 key == 'morphism' or key == 'reduced_morphism':
if isinstance(data, tuple):
A = data[0]
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
Loading