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/PQ.h | 396 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 blossom5-v2.05.src/PQ.h (limited to 'blossom5-v2.05.src/PQ.h') diff --git a/blossom5-v2.05.src/PQ.h b/blossom5-v2.05.src/PQ.h new file mode 100644 index 0000000..8fb37b7 --- /dev/null +++ b/blossom5-v2.05.src/PQ.h @@ -0,0 +1,396 @@ +/* + PQ.h - implements pairing heaps priority queue (with multipass 'delete min') + + Copyright 2008 Vladimir Kolmogorov (vnk@ist.ac.at) + + This software can be used for research purposes only. Commercial use is prohibited. + Public redistribution of the code or its derivatives is prohibited. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HFKSJHFKJHARBABDAKFAF +#define HFKSJHFKJHARBABDAKFAF + +// exactly one flag must be defined +//#define PQ_MULTIPASS +#define PQ_INTERLEAVED_MULTIPASS + +#include + +template class PriorityQueue +{ +public: + struct Item + { + REAL slack; + + Item* parentPQ; + union + { + struct + { + Item* leftPQ; + Item* rightPQ; + }; + REAL y_saved; // used in repairs + }; + }; + static void* AllocateBuf(); + static void DeallocateBuf(void* buf); + + static void ResetItem(Item* i); + static bool isReset(Item* i); + + ////////////////////////////////////////////////////////// + + void Reset(); + void Add(Item* i); +#define Remove(i, buf) _Remove(i) + void _Remove(Item* i); + void Decrease(Item* i_old, Item* i_new, void* buf); + Item* GetMin(); + + ////////////////////////////////////////////////////////// + + void Update(REAL delta); + void Merge(PriorityQueue& dest); + + // traversing items in the order they are stored (irrespective of slack). + // The caller must go through all items, no other member functions can be called during the scan. + Item* GetAndResetFirst(); + Item* GetAndResetNext(); + + Item* GetFirst(); + Item* GetNext(Item* i); + + ////////////////////////////////////////////////////////// + +private: + struct Buf + { + }; + Item* rootPQ; + void RemoveRoot(); +}; + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +template inline void* PriorityQueue::AllocateBuf() +{ + return NULL; +} + +template inline void PriorityQueue::DeallocateBuf(void* _buf) +{ +} + +template inline void PriorityQueue::ResetItem(Item* i) +{ + i->parentPQ = NULL; +} + +template inline bool PriorityQueue::isReset(Item* i) +{ + return (i->parentPQ == NULL); +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +template inline void PriorityQueue::Reset() +{ + rootPQ = NULL; +} + +/* +template inline void PriorityQueue::RemoveRoot() +{ + Item* r = rootPQ; + PriorityQueue pq; + pq.rootPQ = rootPQ; + rootPQ = NULL; + Item* i; + for (i=pq.GetAndResetFirst(); i; i=pq.GetAndResetNext()) + { + if (i != r) Add(i); + } + r->parentPQ = NULL; +} +*/ + +// sets i = merge(i, j). Ignores parentPQ and rightPQ for i and j. +#define MERGE_PQ(i, j)\ + {\ + if (i->slack <= j->slack)\ + {\ + j->rightPQ = i->leftPQ;\ + if (j->rightPQ) j->rightPQ->parentPQ = j;\ + j->parentPQ = i;\ + i->leftPQ = j;\ + }\ + else\ + {\ + i->rightPQ = j->leftPQ;\ + if (i->rightPQ) i->rightPQ->parentPQ = i;\ + i->parentPQ = j;\ + j->leftPQ = i;\ + i = j;\ + }\ + } + +template inline void PriorityQueue::RemoveRoot() +{ + Item* i = rootPQ->leftPQ; + rootPQ->parentPQ = NULL; + if (i) + { +#ifdef PQ_MULTIPASS + while ( i->rightPQ ) + { + Item** prev_ptr = &rootPQ; + while ( 1 ) + { + if (i->rightPQ) + { + Item* j = i->rightPQ; + Item* next = j->rightPQ; + MERGE_PQ(i, j); + *prev_ptr = i; + if (!next) { i->rightPQ = NULL; break; } + prev_ptr = &i->rightPQ; + i = next; + } + else + { + *prev_ptr = i; + i->rightPQ = NULL; + break; + } + } + i = rootPQ; + } +#endif + +#ifdef PQ_INTERLEAVED_MULTIPASS + while ( i->rightPQ ) + { + Item* prev = NULL; + while ( i ) + { + Item* next; + if (i->rightPQ) + { + Item* j = i->rightPQ; + next = j->rightPQ; + MERGE_PQ(i, j); + } + else next = NULL; + i->rightPQ = prev; + prev = i; + i = next; + } + i = prev; + } +#endif + i->parentPQ = i; + } + rootPQ = i; +} + +template inline void PriorityQueue::Add(Item* i) +{ + if (!rootPQ) + { + rootPQ = i; + i->parentPQ = i; + i->leftPQ = i->rightPQ = NULL; + } + else if (i->slack <= rootPQ->slack) + { + rootPQ->parentPQ = i; + i->leftPQ = rootPQ; + i->rightPQ = NULL; + rootPQ = i; + i->parentPQ = i; + } + else + { + i->leftPQ = NULL; + i->rightPQ = rootPQ->leftPQ; + if (i->rightPQ) i->rightPQ->parentPQ = i; + rootPQ->leftPQ = i; + i->parentPQ = rootPQ; + } +} + + +template inline void PriorityQueue::_Remove(Item* i) +{ + Item* p = i->parentPQ; + if (p == i) RemoveRoot(); + else + { + if (i->rightPQ) i->rightPQ->parentPQ = p; + if (p->leftPQ == i) p->leftPQ = i->rightPQ; + else p->rightPQ = i->rightPQ; + if (i->leftPQ) + { + i->parentPQ = i; + i->rightPQ = NULL; + PriorityQueue pq; + pq.rootPQ = i; + pq.RemoveRoot(); + pq.Merge(*this); + } + else i->parentPQ = NULL; + } +} + +template inline void PriorityQueue::Decrease(Item* i_old, Item* i_new, void* _buf) +{ + if (i_old->parentPQ == i_old) + { + if (i_old != i_new) + { + rootPQ = i_new; + i_new->parentPQ = i_new; + i_new->leftPQ = i_old->leftPQ; + i_new->rightPQ = NULL; + if (i_new->leftPQ) i_new->leftPQ->parentPQ = i_new; + i_old->parentPQ = NULL; + } + } + else + { + Remove(i_old, _buf); + Add(i_new); + } +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetMin() +{ + return rootPQ; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + + + +template inline void PriorityQueue::Merge(PriorityQueue& dest) +{ + if (!rootPQ) return; + if (!dest.rootPQ) dest.rootPQ = rootPQ; + else + { + if (rootPQ->slack < dest.rootPQ->slack) + { + Item* j = rootPQ; rootPQ = dest.rootPQ; dest.rootPQ = j; + } + rootPQ->rightPQ = dest.rootPQ->leftPQ; + if (rootPQ->rightPQ) rootPQ->rightPQ->parentPQ = rootPQ; + rootPQ->parentPQ = dest.rootPQ; + dest.rootPQ->leftPQ = rootPQ; + } + rootPQ = NULL; +} + + + +template inline void PriorityQueue::Update(REAL delta) +{ + if (!rootPQ) return; + + Item* i = rootPQ; + while (i->leftPQ) i = i->leftPQ; + + while ( 1 ) + { + i->slack += delta; + + if (i->rightPQ) + { + i = i->rightPQ; + while (i->leftPQ) i = i->leftPQ; + } + else + { + while ( 1 ) + { + Item* j = i; + i = i->parentPQ; + if (i == j) return; + if (i->leftPQ == j) break; + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +template inline typename PriorityQueue::Item* PriorityQueue::GetAndResetFirst() +{ + if (!rootPQ) return NULL; + return GetAndResetNext(); +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetAndResetNext() +{ + if (!rootPQ) return NULL; + Item* result = rootPQ; + result->parentPQ = NULL; + Item* i = rootPQ->leftPQ; + if (!i) rootPQ = result->rightPQ; + else + { + rootPQ = i; + while (i->rightPQ) i = i->rightPQ; + i->rightPQ = result->rightPQ; + } + return result; +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetFirst() +{ + if (!rootPQ) return NULL; + Item* i = rootPQ; + while (i->leftPQ) i = i->leftPQ; + return i; +} + +template inline typename PriorityQueue::Item* PriorityQueue::GetNext(Item* i) +{ + if (i->rightPQ) + { + i = i->rightPQ; + while (i->leftPQ) i = i->leftPQ; + return i; + } + while ( 1 ) + { + Item* j = i; + i = i->parentPQ; + if (i == j) return NULL; + if (i->leftPQ == j) return i; + } +} + +#endif -- cgit v1.2.3-70-g09d2