Skip to content

Commit 1251ff6

Browse files
author
Release Manager
committed
gh-37053: Add reverse Cuthill-McKee ordering for graphs Fixes #13583. We add the reverse Cuthill-McKee (RCM) ordering for graphs. We already had Cuthill-McKee and King. ```py sage: from sage.graphs.base.boost_graph import bandwidth_heuristics sage: bandwidth_heuristics(graphs.PathGraph(10)) (1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) sage: bandwidth_heuristics(graphs.GridGraph([3,3])) (3, [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (2, 1), (1, 2), (2, 2)]) sage: bandwidth_heuristics(graphs.GridGraph([3,3]), algorithm='reverse_cuthill_mckee') (3, [(2, 2), (1, 2), (2, 1), (0, 2), (1, 1), (2, 0), (0, 1), (1, 0), (0, 0)]) sage: bandwidth_heuristics(graphs.GridGraph([3,3]), algorithm='king') (3, [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (2, 1), (1, 2), (2, 2)]) ``` If needed, we can also expose methods `bandwidth` and `bandwidth_heuristics` in graphs. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #37053 Reported by: David Coudert Reviewer(s): Travis Scrimshaw
2 parents 1f1da59 + beb275a commit 1251ff6

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

src/sage/graphs/base/boost_graph.pyx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,8 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee') noexcept:
515515
Unfortunately, exactly computing the bandwidth is NP-hard (and an
516516
exponential algorithm is implemented in Sagemath in routine
517517
:func:`~sage.graphs.graph_decompositions.bandwidth.bandwidth`). Here, we
518-
implement two heuristics to find good orderings: Cuthill-McKee, and King.
518+
implement two heuristics to find good orderings: Cuthill-McKee, reverse
519+
Cuthill-McKee (also known as ``RCM``) and King.
519520
520521
This function works only in undirected graphs, and its running time is
521522
`O(md_{max}\log d_{max})` for the Cuthill-McKee ordering, and
@@ -527,7 +528,8 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee') noexcept:
527528
- ``g`` -- the input Sage graph
528529
529530
- ``algorithm`` -- string (default: ``'cuthill_mckee'``); the heuristic used
530-
to compute the ordering among ``'cuthill_mckee'`` and ``'king'``
531+
to compute the ordering among ``'cuthill_mckee'``,
532+
``'reverse_cuthill_mckee'`` and ``'king'``
531533
532534
OUTPUT:
533535
@@ -542,6 +544,8 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee') noexcept:
542544
(1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
543545
sage: bandwidth_heuristics(graphs.GridGraph([3,3]))
544546
(3, [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (2, 1), (1, 2), (2, 2)])
547+
sage: bandwidth_heuristics(graphs.GridGraph([3,3]), algorithm='reverse_cuthill_mckee')
548+
(3, [(2, 2), (1, 2), (2, 1), (0, 2), (1, 1), (2, 0), (0, 1), (1, 0), (0, 0)])
545549
sage: bandwidth_heuristics(graphs.GridGraph([3,3]), algorithm='king')
546550
(3, [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (2, 1), (1, 2), (2, 2)])
547551
@@ -581,11 +585,16 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee') noexcept:
581585
# Tests for errors and trivial cases
582586
if not isinstance(g, Graph):
583587
raise TypeError("the input must be a Sage Graph")
584-
if algorithm not in ['cuthill_mckee', 'king']:
588+
if algorithm not in ['cuthill_mckee', 'reverse_cuthill_mckee', 'king']:
585589
raise ValueError(f"unknown algorithm {algorithm!r}")
586590
if not g.num_edges():
587591
return (0, list(g))
588592

593+
cdef bint reverse = False
594+
if algorithm == 'reverse_cuthill_mckee':
595+
reverse = True
596+
algorithm = 'cuthill_mckee'
597+
589598
# These variables are automatically deleted when the function terminates.
590599
cdef BoostVecGraph g_boost
591600
cdef vector[v_index] result
@@ -601,8 +610,12 @@ cpdef bandwidth_heuristics(g, algorithm='cuthill_mckee') noexcept:
601610

602611
cdef int n = g.num_verts()
603612
cdef dict pos = {int_to_vertex[<int> result[i]]: i for i in range(n)}
604-
cdef int bandwidth = max([abs(pos[u] - pos[v]) for u, v in g.edge_iterator(labels=False)])
613+
cdef int bandwidth = max([abs(pos[u] - pos[v])
614+
for u, v in g.edge_iterator(labels=False)])
605615

616+
if reverse:
617+
return (bandwidth, [int_to_vertex[<int> result[i]]
618+
for i in range(n - 1, -1, -1)])
606619
return (bandwidth, [int_to_vertex[<int> result[i]] for i in range(n)])
607620

608621

0 commit comments

Comments
 (0)