From 1e6f2a11c4a1c34f7b230dce9bea05571b67cba4 Mon Sep 17 00:00:00 2001 From: Joris van Rantwijk Date: Fri, 22 Nov 2024 20:12:25 +0100 Subject: [PATCH] Simplify expand_t_blossom() --- cpp/mwmatching.h | 107 ++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 71 deletions(-) diff --git a/cpp/mwmatching.h b/cpp/mwmatching.h index 3d777f8..84455a9 100644 --- a/cpp/mwmatching.h +++ b/cpp/mwmatching.h @@ -1414,7 +1414,7 @@ public: assert(sub_blossom->vertex_dual_offset == 0); sub_blossom->vertex_dual_offset = vertex_dual_offset; - // Add unlabeled blossom to the delta2 queue. + // Add unlabeled sub-blossom to the delta2 queue. delta2_enable_blossom(sub_blossom); } @@ -1423,65 +1423,53 @@ public: // that ran through this blossom by linking some of the sub-blossoms // into the tree. - // Find the sub-blossom that was attached to the parent node - // in the alternating tree. + // Find the sub-blossom through which the expanding blossom was + // attached to the alternating tree. BlossomT* entry = top_level_blossom(blossom->tree_edge.second); - // Assign label T to that blossom and link to the alternating tree. - assign_blossom_label_t(entry); - entry->tree_edge = blossom->tree_edge; - entry->tree_root = blossom->tree_root; - // Find the position of this sub-blossom within the expanding blossom. auto subblossom_loc = blossom->find_subblossom(entry); VertexId entry_pos = subblossom_loc.first; auto entry_it = subblossom_loc.second; - // Walk around the blossom from "entry" to the base + // Get the edge that attaches this blossom to the alternating tree. + VertexId x, y; + std::tie(x, y) = blossom->tree_edge; + + // Walk around the expanding blossom from "entry" to its base // in an even number of steps. + auto sub_begin = blossom->subblossoms.begin(); + auto sub_end = blossom->subblossoms.end(); auto sub_it = entry_it; - if (entry_pos % 2 == 0) { + while ((sub_it != sub_begin) && (sub_it != sub_end)) { - // Walk backward to the base. - auto sub_begin = blossom->subblossoms.begin(); - while (sub_it != sub_begin) { - // Assign label S to the next node on the path. + // Assign label T to the current sub-blossom on the path. + // This also assigns label S to the next sub-blossom. + extend_tree_s_to_t(x, y); + + if (entry_pos % 2 == 0) { + // Walk two steps backward to the base. --sub_it; - extend_tree_t_to_s(sub_it->edge.first); - - // Assign label T to the next node on the path. assert(sub_it != sub_begin); --sub_it; - BlossomT* sub_blossom = sub_it->blossom; - assign_blossom_label_t(sub_blossom); - sub_blossom->tree_edge = flip_vertex_pair(sub_it->edge); - sub_blossom->tree_root = blossom->tree_root; - } - - } else { - - // Walk forward to the base. - auto sub_end = blossom->subblossoms.end(); - while (sub_it != sub_end) { - // Assign label S to the next node on the path. - extend_tree_t_to_s(sub_it->edge.second); + // Get the edge from S-sub-blossom to next sub-blossom. + std::tie(y, x) = sub_it->edge; + } else { + // Walk two steps forward to the base. ++sub_it; - - // Assign label T to the next node on the path. - // We may wrap past the end of the subblossom list. assert(sub_it != sub_end); - VertexPair& tree_edge = sub_it->edge; + // Get the edge from S-sub-blossom to next sub-blossom. + std::tie(x, y) = sub_it->edge; ++sub_it; - - BlossomT *sub_blossom = (sub_it == sub_end) ? - blossom->subblossoms.front().blossom : - sub_it->blossom; - assign_blossom_label_t(sub_blossom); - sub_blossom->tree_edge = tree_edge; - sub_blossom->tree_root = blossom->tree_root; } } + // Finally, assign label T to the base sub-blossom. + BlossomT* base = blossom->subblossoms.front().blossom; + assign_blossom_label_t(base); + base->tree_edge = std::make_pair(x, y); + base->tree_root = blossom->tree_root; + // Delete the expanded blossom. nontrivial_blossom.erase(blossom->this_blossom_iterator); } @@ -1655,34 +1643,6 @@ public: /* ********** Alternating tree: ********** */ - /** - * Assign label S to the unlabeled blossom that contains vertex "x". - * - * The newly labeled S-blossom is added to the alternating tree - * via its matched edge. All vertices in the newly labeled S-blossom - * are added to the scan queue. - * - * @pre "x" is an unlabeled vertex. - * @pre "x" is matched to a T-vertex via a tight edge. - */ - void extend_tree_t_to_s(VertexId x) - { - // Assign label S to the blossom that contains vertex "x". - BlossomT* bx = top_level_blossom(x); - assign_blossom_label_s(bx); - - // Vertex "x" is matched to T-vertex "y". - VertexId y = vertex_mate[x]; - assert(y != NO_VERTEX); - - BlossomT* by = top_level_blossom(y); - assert(by->label == LABEL_T); - - // Attach the blossom to the alternating tree via vertex "y". - bx->tree_edge = std::make_pair(y, x); - bx->tree_root = by->tree_root; - } - /** * Assign label T to the unlabeled blossom that contains vertex "y". * @@ -1708,9 +1668,14 @@ public: by->tree_root = bx->tree_root; // Assign label S to the blossom that is mated to the T-blossom. - VertexId z = vertex_mate[by->base_vertex]; + VertexId y2 = by->base_vertex; + VertexId z = vertex_mate[y2]; assert(z != NO_VERTEX); - extend_tree_t_to_s(z); + + BlossomT* bz = top_level_blossom(z); + assign_blossom_label_s(bz); + bz->tree_edge = std::make_pair(y2, z); + bz->tree_root = by->tree_root; } /**