From a06ff64534815cbf702a3847a19443612d307b80 Mon Sep 17 00:00:00 2001 From: Jaron Kent-Dobias Date: Fri, 30 Sep 2022 10:55:55 +0200 Subject: Changed rbmp to use blossom algorithm. --- blossom5-v2.05.src/PMexpand.cpp | 304 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 blossom5-v2.05.src/PMexpand.cpp (limited to 'blossom5-v2.05.src/PMexpand.cpp') diff --git a/blossom5-v2.05.src/PMexpand.cpp b/blossom5-v2.05.src/PMexpand.cpp new file mode 100644 index 0000000..79ba684 --- /dev/null +++ b/blossom5-v2.05.src/PMexpand.cpp @@ -0,0 +1,304 @@ +#include +#include +#include +#include "PMimplementation.h" + + + + +inline void PerfectMatching::ProcessSelfloop(Node* b, Edge* a) +{ + int dir; + Node* j; + Node* prev[2]; + for (dir=0; dir<2; dir++) + { + j = a->head[dir]; + GET_PENULTIMATE_BLOSSOM(j); + prev[dir] = j; + } + if (prev[0] != prev[1]) + { + ADD_EDGE(prev[0], a, 1); + ADD_EDGE(prev[1], a, 0); + a->slack -= 2*prev[0]->blossom_eps; + } + else + { + a->next[0] = prev[0]->blossom_selfloops; + prev[0]->blossom_selfloops = a; + } + +} + + + +void PerfectMatching::Expand(Node* b) +{ + assert(b->is_blossom); + assert(b->is_outer); + assert(b->flag == 1); + + double start_time = get_time(); + + Node* i; + Node* j; + Node* k; + Edge* a; + EdgeIterator I; + int dir; + ExpandTmpItem* tmp_item; + Tree* t = b->tree; + REAL eps = t->eps; + Edge* a_augment = NULL; + + GET_TREE_PARENT(b, i); + a = ARC_TO_EDGE_PTR(b->tree_parent); + dir = ARC_TO_EDGE_DIR(b->tree_parent); + + j = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM(j); + MOVE_EDGE(b, j, a, dir); + + a = ARC_TO_EDGE_PTR(b->match); + dir = ARC_TO_EDGE_DIR(b->match); + k = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM(k); + MOVE_EDGE(b, k, a, dir); + + i = ARC_HEAD(k->blossom_sibling); + while ( 1 ) + { + tmp_item = expand_tmp_list->New(); + tmp_item->i = i; tmp_item->blossom_parent = i->blossom_parent; tmp_item->blossom_grandparent = i->blossom_grandparent; + i->flag = 2; + + // blossom_selfloops + i->is_outer = 1; + while ((a=i->blossom_selfloops)) + { + i->blossom_selfloops = a->next[0]; + ProcessSelfloop(i, a); + } + i->is_outer = 0; + + if (i == k) break; + i->match = i->blossom_sibling; + j = ARC_HEAD(i->match); + tmp_item = expand_tmp_list->New(); + tmp_item->i = j; tmp_item->blossom_parent = j->blossom_parent; tmp_item->blossom_grandparent = j->blossom_grandparent; + j->flag = 2; + + // blossom_selfloops + j->is_outer = 1; + while ((a=j->blossom_selfloops)) + { + j->blossom_selfloops = a->next[0]; + ProcessSelfloop(j, a); + } + j->is_outer = 0; + + j->match = ARC_REV(i->match); + i = ARC_HEAD(j->blossom_sibling); + } + k->match = b->match; + i = ARC_TAIL(b->tree_parent); + Arc* aa = i->blossom_sibling; + i->flag = 1; i->tree = b->tree; i->y += b->tree->eps; + i->tree_parent = b->tree_parent; + if (i != k) + { + Node** i_ptr; + if (i->match == aa) + { + i = ARC_HEAD(i->match); + i_ptr = &j; + while ( 1 ) + { + aa = i->blossom_sibling; + i->flag = 0; i->tree = b->tree; i->y -= t->eps; + *i_ptr = i; + i_ptr = &i->first_tree_child; + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + i = ARC_HEAD(aa); + i->flag = 1; i->tree = b->tree; i->y += t->eps; + i->tree_parent = ARC_REV(aa); + if (i == k) break; + i = ARC_HEAD(i->match); + } + *i_ptr = ARC_HEAD(k->match); + } + else + { + i = k; + j = ARC_HEAD(k->match); + do + { + i->tree_parent = i->blossom_sibling; + i->flag = 1; i->tree = b->tree; i->y += b->tree->eps; + i = ARC_HEAD(i->tree_parent); + i->flag = 0; i->tree = b->tree; i->y -= b->tree->eps; + i->first_tree_child = j; + j = i; + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + i = ARC_HEAD(i->match); + } while ( i->flag != 1 ); + } + i = ARC_HEAD(k->match); + + j->tree_sibling_prev = i->tree_sibling_prev; + j->tree_sibling_next = i->tree_sibling_next; + if (i->tree_sibling_prev->tree_sibling_next) i->tree_sibling_prev->tree_sibling_next = j; + else ARC_HEAD(b->tree_parent)->first_tree_child = j; + if (i->tree_sibling_next) i->tree_sibling_next->tree_sibling_prev = j; + else ARC_HEAD(b->tree_parent)->first_tree_child->tree_sibling_prev = j; + + i->tree_sibling_prev = i; + i->tree_sibling_next = NULL; + } + + // go through inner arcs + i = k; + while ( 1 ) + { + // "-" node + if (i->is_blossom) + { + a = ARC_TO_EDGE_PTR(i->match); + REAL tmp = a->slack; a->slack = i->y; i->y = tmp; + t->pq_blossoms.Add(a); + } + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (j->flag != 0) a->slack -= eps; + } + i->is_processed = 1; + if (i->tree_parent == b->tree_parent) break; + i = ARC_HEAD(i->tree_parent); + // "+" node + FOR_ALL_EDGES(i, a, dir, I) + { + j = a->head[dir]; + if (j->flag == 2) + { + a->slack += eps; + t->pq0.Add(a); + } + else if (j->flag == 0 && i < j) + { + a->slack += 2*eps; + t->pq00.Add(a); + } + } + i->is_processed = 1; + i = ARC_HEAD(i->match); + } + + // go through boundary arcs + for (tmp_item=expand_tmp_list->ScanFirst(); tmp_item; tmp_item=expand_tmp_list->ScanNext()) + { + i = tmp_item->i; + j = tmp_item->blossom_parent; tmp_item->blossom_parent = i->blossom_parent; i->blossom_parent = j; + j = tmp_item->blossom_grandparent; tmp_item->blossom_grandparent = i->blossom_grandparent; i->blossom_grandparent = j; + } + for (dir=0; dir<2; dir++) + { + if (!b->first[dir]) continue; + b->first[dir]->prev[dir]->next[dir] = NULL; + + Edge* a_next; + for (a=b->first[dir]; a; a=a_next) + { + a_next = a->next[dir]; + i = a->head0[1-dir]; + GET_PENULTIMATE_BLOSSOM2(i); + ADD_EDGE(i, a, dir); + GET_OUTER_HEAD(a, dir, j); + + if (i->flag == 1) continue; + + if (j->flag == 0 && j->tree != t) j->tree->pq_current->pq01[1-j->tree->dir_current].Remove(a, pq_buf); + + if (i->flag == 2) + { + a->slack += eps; + if (j->flag == 0) j->tree->pq0.Add(a); + } + else + { + a->slack += 2*eps; + if (j->flag == 2) t->pq0.Add(a); + else if (j->flag == 0) + { + if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + if (a->slack <= j->tree->eps + eps) a_augment = a; + } + j->tree->pq_current->pq00.Add(a); + } + else if (j->tree != t) + { + if (!j->tree->pq_current) AddTreeEdge(t, j->tree); + j->tree->pq_current->pq01[j->tree->dir_current].Add(a); + } + + } + } + } + for (tmp_item=expand_tmp_list->ScanFirst(); tmp_item; tmp_item=expand_tmp_list->ScanNext()) + { + i = tmp_item->i; + i->blossom_parent = tmp_item->blossom_parent; + i->blossom_grandparent = tmp_item->blossom_grandparent; + i->is_outer = 1; + } + expand_tmp_list->Reset(); + + b->is_removed = 1; + b->tree_sibling_next = removed_first; + removed_first = b; + removed_num ++; + if (4*removed_num > node_num) FreeRemoved(); + + blossom_num --; + stat.expand_count ++; + + stat.expand_time += get_time() - start_time; + + if (a_augment) Augment(a_augment); +} + +void PerfectMatching::FreeRemoved() +{ + Node* i0; + Node* i; + for (i0=nodes; i0is_outer && !i->is_marked; i=i->blossom_parent) + { + i->is_marked = 1; + if (i->blossom_grandparent->is_removed) i->blossom_grandparent = i->blossom_parent; + } + } + for (i0=nodes; i0is_outer && i->is_marked; i=i->blossom_parent) + { + i->is_marked = 0; + } + } + + while ((i=removed_first)) + { + removed_first = i->tree_sibling_next; + blossoms->Delete(i); + removed_num --; + } + + assert(removed_num == 0); +} + -- cgit v1.2.3-70-g09d2