Skip to content

Commit

Permalink
Merge pull request #47 from xuluze/cmr
Browse files Browse the repository at this point in the history
Add algorithm keyword to is_graphic and is_regular in matroid
  • Loading branch information
mkoeppe authored Sep 2, 2024
2 parents 319ab4d + 571a7ed commit 6690fef
Show file tree
Hide file tree
Showing 13 changed files with 1,261 additions and 393 deletions.
5 changes: 2 additions & 3 deletions build/pkgs/cmr/checksums.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
tarball=cmr-0+VERSION.tar.gz
sha1=1fb6c029456eaa030205e06ee2eb526ac7c2553e
md5=95e7c27c74a66e55e74791c2fbc46988
cksum=622510774
sha1=94cbb90279f2387a0ae870fa9d51110f6eb289f7
sha256=cb7db56a86002beacef74de7cfa00617428a0b3ba6247663d7db6305eca45ab0
upstream_url=https://github.com/discopt/cmr/archive/VERSION.tar.gz
2 changes: 1 addition & 1 deletion build/pkgs/cmr/package-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
63f3e1fbaf52174e25fb95770af439260a4b5631
66b5141ea955c5c43b8d82cf105554b627cd5424
5 changes: 5 additions & 0 deletions src/doc/en/reference/references/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,11 @@ REFERENCES:
vol. 308, no. 1, July 1988.
http://www.ams.org/journals/tran/1988-308-01/S0002-9947-1988-0946427-X/S0002-9947-1988-0946427-X.pdf
.. [BW1988b] Robert E. Bixby, Donald K. Wagner.
*An Almost Linear-Time Algorithm for Graph Realization*.
Mathematics of Operations Research, 1988.
:doi:`10.1287/moor.13.1.99`
.. [BW1993] Thomas Becker and Volker Weispfenning. *Groebner Bases - A
Computational Approach To Commutative Algebra*. Springer,
New York, 1993.
Expand Down
259 changes: 143 additions & 116 deletions src/sage/libs/cmr/cmr.pxd

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/sage/matrix/matrix_cmr_sparse.pxd
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# sage_setup: distribution = sagemath-cmr
from sage.libs.cmr.cmr cimport CMR_CHRMAT, CMR_REGULAR_PARAMS, CMR_GRAPH, CMR_GRAPH_EDGE, bool
from sage.libs.cmr.cmr cimport CMR_CHRMAT, CMR_SEYMOUR_PARAMS, CMR_GRAPH, CMR_GRAPH_EDGE, bool

from .matrix_sparse cimport Matrix_sparse

Expand All @@ -22,7 +22,7 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse):
@staticmethod
cdef _from_cmr(CMR_CHRMAT *mat, bint immutable=?, base_ring=?)

cdef _set_cmr_regular_parameters(CMR_REGULAR_PARAMS *params, dict kwds)
cdef _set_cmr_seymour_parameters(CMR_SEYMOUR_PARAMS *params, dict kwds)

cdef _sage_edge(CMR_GRAPH *graph, CMR_GRAPH_EDGE e)
cdef _sage_edges(CMR_GRAPH *graph, CMR_GRAPH_EDGE *edges, int n, keys)
Expand Down
769 changes: 697 additions & 72 deletions src/sage/matrix/matrix_cmr_sparse.pyx

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions src/sage/matrix/seymour_decomposition.pxd
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# sage_setup: distribution = sagemath-cmr
from sage.libs.cmr.cmr cimport CMR_MATROID_DEC, CMR_ELEMENT
from sage.libs.cmr.cmr cimport CMR_SEYMOUR_NODE, CMR_ELEMENT
from sage.structure.sage_object cimport SageObject


cdef class DecompositionNode(SageObject):
cdef object _base_ring
cdef object _matrix
cdef CMR_MATROID_DEC *_dec
cdef CMR_SEYMOUR_NODE *_dec
cdef object _row_keys
cdef object _column_keys
cdef object _child_nodes
cdef object _minors

cdef _set_dec(self, CMR_MATROID_DEC *dec)
cdef _set_dec(self, CMR_SEYMOUR_NODE *dec)
cdef _set_root_dec(self)
cdef _set_row_keys(self, row_keys)
cdef _set_column_keys(self, column_keys)
Expand Down Expand Up @@ -42,7 +43,7 @@ cdef class SymbolicNode(DecompositionNode):
cdef object _symbol


cdef create_DecompositionNode(CMR_MATROID_DEC *dec,
cdef create_DecompositionNode(CMR_SEYMOUR_NODE *dec,
matrix=?,
row_keys=?, column_keys=?,
base_ring=?)
326 changes: 180 additions & 146 deletions src/sage/matrix/seymour_decomposition.pyx

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/sage/matroids/graphic_matroid.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ cdef class GraphicMatroid(Matroid):
"""
return True

def is_graphic(self):
def is_graphic(self, **kwds):
r"""
Return if ``self`` is graphic.
Expand All @@ -1125,7 +1125,7 @@ cdef class GraphicMatroid(Matroid):
"""
return True

def is_regular(self):
def is_regular(self, **kwds):
r"""
Return if ``self`` is regular.
Expand Down
6 changes: 4 additions & 2 deletions src/sage/matroids/linear_matroid.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ cdef class BinaryMatroid(LinearMatroid):
cpdef _fast_isom_test(self, other)
cpdef relabel(self, mapping)

cpdef is_graphic(self)
cpdef is_graphic(self, algorithm=*)
cpdef _is_graphic_GG(self)
cpdef _is_graphic_cmr(self)
cpdef is_valid(self)


Expand Down Expand Up @@ -172,5 +174,5 @@ cdef class RegularMatroid(LinearMatroid):
cpdef has_line_minor(self, k, hyperlines=*, certificate=*)
cpdef _linear_extension_chains(self, F, fundamentals=*)

cpdef is_graphic(self)
cpdef is_graphic(self, algorithm=*)
cpdef is_valid(self)
147 changes: 127 additions & 20 deletions src/sage/matroids/linear_matroid.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3817,8 +3817,61 @@ cdef class BinaryMatroid(LinearMatroid):
keep_initial_representation=False)

# graphicness test
cpdef is_graphic(self):
cpdef is_graphic(self, algorithm=None):
r"""
Test if the binary matroid is graphic.
A matroid is *graphic* if there exists a graph whose edge set equals
the groundset of the matroid, such that a subset of elements of the
matroid is independent if and only if the corresponding subgraph is
acyclic.
INPUT:
- ``algorithm`` -- (default: ``None``); specify which algorithm
to check graphicness:
- ``None`` -- an algorithm based on [GG2012]_.
- ``"cmr"`` -- an algorithm based on [BW1988b]_.
the optional package "cmr" is required.
OUTPUT:
Boolean.
.. SEEALSO::
:meth:`M.is_graphic() <sage.matroids.linear_matroid.
RegularMatroid.is_graphic>`
:meth:`M.is_graphic() <sage.matroids.graphic_matroid.
GraphicMatroid.is_graphic>`
EXAMPLES::
sage: R10 = matroids.catalog.R10()
sage: M = Matroid(ring=GF(2), reduced_matrix=R10.representation(
....: reduced=True, labels=False))
sage: M.is_graphic(algorithm="cmr") # optional - cmr
False
sage: K5 = Matroid(graphs.CompleteGraph(5)) # needs sage.graphs
sage: K5.is_graphic(algorithm="cmr") # optional - cmr # needs sage.graphs
True
sage: K5 = Matroid(graphs.CompleteGraph(5), regular=True) # needs sage.graphs
sage: M = Matroid(ring=GF(2), reduced_matrix=K5.representation( # needs sage.graphs sage.rings.finite_rings
....: reduced=True, labels=False))
sage: M.is_graphic(algorithm="cmr") # optional - cmr # needs sage.graphs sage.rings.finite_rings
True
sage: M.dual().is_graphic(algorithm="cmr") # optional - cmr # needs sage.graphs
False
"""
if algorithm is None:
return self._is_graphic_GG()
if algorithm == "cmr":
return self._is_graphic_cmr()
raise ValueError("Not a valid algorithm.")

cpdef _is_graphic_GG(self):
r"""
Test if the binary matroid is graphic.
A matroid is *graphic* if there exists a graph whose edge set equals
Expand All @@ -3835,14 +3888,14 @@ cdef class BinaryMatroid(LinearMatroid):
sage: R10 = matroids.catalog.R10()
sage: M = Matroid(ring=GF(2), reduced_matrix=R10.representation(
....: reduced=True, labels=False))
sage: M.is_graphic()
sage: M._is_graphic_GG()
False
sage: K5 = Matroid(graphs.CompleteGraph(5), regular=True) # needs sage.graphs
sage: M = Matroid(ring=GF(2), reduced_matrix=K5.representation( # needs sage.graphs sage.rings.finite_rings
....: reduced=True, labels=False))
sage: M.is_graphic() # needs sage.graphs sage.rings.finite_rings
sage: M._is_graphic_GG() # needs sage.graphs sage.rings.finite_rings
True
sage: M.dual().is_graphic() # needs sage.graphs
sage: M.dual()._is_graphic_GG() # needs sage.graphs
False
ALGORITHM:
Expand Down Expand Up @@ -3888,6 +3941,51 @@ cdef class BinaryMatroid(LinearMatroid):
# now self is graphic iff there is a binary vector x so that M*x = 0 and x_0 = 1, so:
return BinaryMatroid(m).corank(frozenset([0])) > 0

cpdef _is_graphic_cmr(self):
r"""
Test if the binary matroid is graphic.
A matroid is *graphic* if there exists a graph whose edge set equals
the groundset of the matroid, such that a subset of elements of the
matroid is independent if and only if the corresponding subgraph is
acyclic.
OUTPUT:
Boolean.
.. SEEALSO::
:meth:`M._is_binary_linear_matroid_graphic() <sage.matrix.matrix_cmr_sparse.
Matrix_cmr_chr_sparse._is_binary_linear_matroid_graphic>`
:meth:`M.is_network_matrix() <sage.matrix.matrix_cmr_sparse.
Matrix_cmr_chr_sparse.is_network_matrix>`
EXAMPLES::
sage: R10 = matroids.catalog.R10()
sage: M = Matroid(ring=GF(2), reduced_matrix=R10.representation(
....: reduced=True, labels=False))
sage: M._is_graphic_cmr() # optional - cmr
False
sage: K5 = Matroid(graphs.CompleteGraph(5), regular=True) # needs sage.graphs
sage: M = Matroid(ring=GF(2), reduced_matrix=K5.representation( # needs sage.graphs sage.rings.finite_rings
....: reduced=True, labels=False))
sage: M._is_graphic_cmr() # optional - cmr # needs sage.graphs sage.rings.finite_rings
True
sage: M.dual()._is_graphic_cmr() # optional - cmr # needs sage.graphs
False
ALGORITHM:
The implemented recognition algorithm is based on [BW1988b]_, [An Almost Linear-Time Algorithm for Graph Realization](https://doi.org/10.1287/moor.13.1.99) by Robert E. Bixby and Donald K. Wagner (Mathematics of Operations Research, 1988).
For a matrix `M \in \{0,1\}^{m \times n}` with `k` nonzeros it runs in `\mathcal{O}( k \cdot \alpha(k, m) )` time, where `\alpha(\cdot)` denotes the inverse Ackerman function.
"""
from sage.matrix.matrix_cmr_sparse import Matrix_cmr_chr_sparse
A = self.representation()
A_cmr = Matrix_cmr_chr_sparse(A.parent(), A)
return A_cmr._is_binary_linear_matroid_graphic()

cpdef is_valid(self):
r"""
Test if the data obey the matroid axioms.
Expand Down Expand Up @@ -5247,7 +5345,7 @@ cdef class QuaternaryMatroid(LinearMatroid):
EXAMPLES::
sage: M = matroids.catalog.Q10() # needs sage.rings.finite_rings
sage: M = matroids.catalog.Q10() # needs sage.rings.finite_rings
sage: M._basic_representation() # needs sage.rings.finite_rings
5 x 10 QuaternaryMatrix
[100001x00y]
Expand Down Expand Up @@ -5397,7 +5495,7 @@ cdef class QuaternaryMatroid(LinearMatroid):
EXAMPLES::
sage: M = matroids.catalog.Q10() # needs sage.rings.finite_rings
sage: M = matroids.catalog.Q10() # needs sage.rings.finite_rings
sage: M._invariant() # needs sage.rings.finite_rings
(0, 0, 5, 5, 20, 10, 25)
"""
Expand All @@ -5424,7 +5522,7 @@ cdef class QuaternaryMatroid(LinearMatroid):
EXAMPLES::
sage: M = matroids.catalog.Q10() # needs sage.rings.finite_rings
sage: M = matroids.catalog.Q10() # needs sage.rings.finite_rings
sage: M.bicycle_dimension() # needs sage.rings.finite_rings
0
"""
Expand Down Expand Up @@ -6301,7 +6399,7 @@ cdef class RegularMatroid(LinearMatroid):
fundamentals = set([1])
return LinearMatroid._linear_extension_chains(self, F, fundamentals)

cpdef is_graphic(self):
cpdef is_graphic(self, algorithm=None):
"""
Test if the regular matroid is graphic.
Expand All @@ -6310,29 +6408,38 @@ cdef class RegularMatroid(LinearMatroid):
matroid is independent if and only if the corresponding subgraph is
acyclic.
INPUT:
- ``algorithm`` -- (default: ``None``); specify which algorithm
to check graphicness:
- ``None`` -- an algorithm based on [GG2012]_.
- ``"cmr"`` -- an algorithm based on [BW1988b]_.
the optional package "cmr" is required.
OUTPUT:
Boolean.
.. SEEALSO::
:meth:`M.is_graphic() <sage.matroids.linear_matroid.
BinaryMatroid.is_graphic>`
:meth:`M.is_graphic() <sage.matroids.graphic_matroid.
GraphicMatroid.is_graphic>`
EXAMPLES::
sage: M = matroids.catalog.R10()
sage: M.is_graphic()
sage: M.is_graphic(algorithm="cmr") # optional - cmr
False
sage: M = Matroid(graphs.CompleteGraph(5), regular=True) # needs sage.graphs
sage: M.is_graphic() # needs sage.graphs sage.rings.finite_rings
sage: M.is_graphic(algorithm="cmr") # optional - cmr # needs sage.graphs sage.rings.finite_rings
True
sage: M.dual().is_graphic() # needs sage.graphs
sage: M.dual().is_graphic(algorithm="cmr") # optional - cmr # needs sage.graphs
False
ALGORITHM:
In a recent paper, Geelen and Gerards [GG2012]_ reduced the problem to
testing if a system of linear equations has a solution. While not the
fastest method, and not necessarily constructive (in the presence of
2-separations especially), it is easy to implement.
"""
return BinaryMatroid(reduced_matrix=self._reduced_representation()).is_graphic()
return BinaryMatroid(reduced_matrix=self._reduced_representation()).is_graphic(algorithm=algorithm)

cpdef is_valid(self):
r"""
Expand Down Expand Up @@ -6365,7 +6472,7 @@ cdef class RegularMatroid(LinearMatroid):

# representation

def is_regular(self):
def is_regular(self, **kwds):
r"""
Return if ``self`` is regular.
Expand Down
4 changes: 2 additions & 2 deletions src/sage/matroids/matroid.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ cdef class Matroid(SageObject):
cpdef _local_ternary_matroid(self, basis=*)
cpdef ternary_matroid(self, randomized_tests=*, verify=*)
cpdef is_ternary(self, randomized_tests=*)
cpdef is_regular(self)
cpdef is_graphic(self)
cpdef is_regular(self, algorithm=*)
cpdef is_graphic(self, algorithm=*)

# matroid k-closed
cpdef is_k_closed(self, int k)
Expand Down
Loading

0 comments on commit 6690fef

Please sign in to comment.