mirror of
https://github.com/Z3Prover/z3
synced 2025-05-03 13:55:47 +00:00
merge LRA
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
085d31dca2
commit
911b24784a
120 changed files with 23069 additions and 15 deletions
193
src/util/lp/binary_heap_priority_queue.hpp
Normal file
193
src/util/lp/binary_heap_priority_queue.hpp
Normal file
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
Copyright (c) 2017 Microsoft Corporation
|
||||
Author: Lev Nachmanson
|
||||
*/
|
||||
#include "util/vector.h"
|
||||
#include "util/lp/binary_heap_priority_queue.h"
|
||||
namespace lean {
|
||||
// is is the child place in heap
|
||||
template <typename T> void binary_heap_priority_queue<T>::swap_with_parent(unsigned i) {
|
||||
unsigned parent = m_heap[i >> 1];
|
||||
put_at(i >> 1, m_heap[i]);
|
||||
put_at(i, parent);
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::put_at(unsigned i, unsigned h) {
|
||||
m_heap[i] = h;
|
||||
m_heap_inverse[h] = i;
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::decrease_priority(unsigned o, T newPriority) {
|
||||
m_priorities[o] = newPriority;
|
||||
int i = m_heap_inverse[o];
|
||||
while (i > 1) {
|
||||
if (m_priorities[m_heap[i]] < m_priorities[m_heap[i >> 1]])
|
||||
swap_with_parent(i);
|
||||
else
|
||||
break;
|
||||
i >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LEAN_DEBUG
|
||||
template <typename T> bool binary_heap_priority_queue<T>::is_consistent() const {
|
||||
for (int i = 0; i < m_heap_inverse.size(); i++) {
|
||||
int i_index = m_heap_inverse[i];
|
||||
lean_assert(i_index <= static_cast<int>(m_heap_size));
|
||||
lean_assert(i_index == -1 || m_heap[i_index] == i);
|
||||
}
|
||||
for (unsigned i = 1; i < m_heap_size; i++) {
|
||||
unsigned ch = i << 1;
|
||||
for (int k = 0; k < 2; k++) {
|
||||
if (ch > m_heap_size) break;
|
||||
if (!(m_priorities[m_heap[i]] <= m_priorities[m_heap[ch]])){
|
||||
return false;
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
template <typename T> void binary_heap_priority_queue<T>::remove(unsigned o) {
|
||||
T priority_of_o = m_priorities[o];
|
||||
int o_in_heap = m_heap_inverse[o];
|
||||
if (o_in_heap == -1) {
|
||||
return; // nothing to do
|
||||
}
|
||||
lean_assert(static_cast<unsigned>(o_in_heap) <= m_heap_size);
|
||||
if (static_cast<unsigned>(o_in_heap) < m_heap_size) {
|
||||
put_at(o_in_heap, m_heap[m_heap_size--]);
|
||||
if (m_priorities[m_heap[o_in_heap]] > priority_of_o) {
|
||||
fix_heap_under(o_in_heap);
|
||||
} else { // we need to propogate the m_heap[o_in_heap] up
|
||||
unsigned i = o_in_heap;
|
||||
while (i > 1) {
|
||||
unsigned ip = i >> 1;
|
||||
if (m_priorities[m_heap[i]] < m_priorities[m_heap[ip]])
|
||||
swap_with_parent(i);
|
||||
else
|
||||
break;
|
||||
i = ip;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lean_assert(static_cast<unsigned>(o_in_heap) == m_heap_size);
|
||||
m_heap_size--;
|
||||
}
|
||||
m_heap_inverse[o] = -1;
|
||||
// lean_assert(is_consistent());
|
||||
}
|
||||
// n is the initial queue capacity.
|
||||
// The capacity will be enlarged two times automatically if needed
|
||||
template <typename T> binary_heap_priority_queue<T>::binary_heap_priority_queue(unsigned n) :
|
||||
m_priorities(n),
|
||||
m_heap(n + 1), // because the indexing for A starts from 1
|
||||
m_heap_inverse(n, -1)
|
||||
{ }
|
||||
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::resize(unsigned n) {
|
||||
m_priorities.resize(n);
|
||||
m_heap.resize(n + 1);
|
||||
m_heap_inverse.resize(n, -1);
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::put_to_heap(unsigned i, unsigned o) {
|
||||
m_heap[i] = o;
|
||||
m_heap_inverse[o] = i;
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::enqueue_new(unsigned o, const T& priority) {
|
||||
m_heap_size++;
|
||||
int i = m_heap_size;
|
||||
lean_assert(o < m_priorities.size());
|
||||
m_priorities[o] = priority;
|
||||
put_at(i, o);
|
||||
while (i > 1 && m_priorities[m_heap[i >> 1]] > priority) {
|
||||
swap_with_parent(i);
|
||||
i >>= 1;
|
||||
}
|
||||
}
|
||||
// This method can work with an element that is already in the queue.
|
||||
// In this case the priority will be changed and the queue adjusted.
|
||||
template <typename T> void binary_heap_priority_queue<T>::enqueue(unsigned o, const T & priority) {
|
||||
if (o >= m_priorities.size()) {
|
||||
resize(o << 1); // make the size twice larger
|
||||
}
|
||||
if (m_heap_inverse[o] == -1)
|
||||
enqueue_new(o, priority);
|
||||
else
|
||||
change_priority_for_existing(o, priority);
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::change_priority_for_existing(unsigned o, const T & priority) {
|
||||
if (m_priorities[o] > priority) {
|
||||
decrease_priority(o, priority);
|
||||
} else {
|
||||
m_priorities[o] = priority;
|
||||
fix_heap_under(m_heap_inverse[o]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// return the first element of the queue and removes it from the queue
|
||||
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue_and_get_priority(T & priority) {
|
||||
lean_assert(m_heap_size != 0);
|
||||
int ret = m_heap[1];
|
||||
priority = m_priorities[ret];
|
||||
put_the_last_at_the_top_and_fix_the_heap();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::fix_heap_under(unsigned i) {
|
||||
while (true) {
|
||||
unsigned smallest = i;
|
||||
unsigned l = i << 1;
|
||||
if (l <= m_heap_size && m_priorities[m_heap[l]] < m_priorities[m_heap[i]])
|
||||
smallest = l;
|
||||
unsigned r = l + 1;
|
||||
if (r <= m_heap_size && m_priorities[m_heap[r]] < m_priorities[m_heap[smallest]])
|
||||
smallest = r;
|
||||
if (smallest != i)
|
||||
swap_with_parent(smallest);
|
||||
else
|
||||
break;
|
||||
i = smallest;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> void binary_heap_priority_queue<T>::put_the_last_at_the_top_and_fix_the_heap() {
|
||||
if (m_heap_size > 1) {
|
||||
put_at(1, m_heap[m_heap_size--]);
|
||||
fix_heap_under(1);
|
||||
} else {
|
||||
m_heap_size--;
|
||||
}
|
||||
}
|
||||
/// return the first element of the queue and removes it from the queue
|
||||
template <typename T> unsigned binary_heap_priority_queue<T>::dequeue() {
|
||||
lean_assert(m_heap_size > 0);
|
||||
int ret = m_heap[1];
|
||||
put_the_last_at_the_top_and_fix_the_heap();
|
||||
m_heap_inverse[ret] = -1;
|
||||
return ret;
|
||||
}
|
||||
#ifdef LEAN_DEBUG
|
||||
template <typename T> void binary_heap_priority_queue<T>::print(std::ostream & out) {
|
||||
vector<int> index;
|
||||
vector<T> prs;
|
||||
while (size()) {
|
||||
T prior;
|
||||
int j = dequeue_and_get_priority(prior);
|
||||
index.push_back(j);
|
||||
prs.push_back(prior);
|
||||
out << "(" << j << ", " << prior << ")";
|
||||
}
|
||||
out << std::endl;
|
||||
// restore the queue
|
||||
for (int i = 0; i < index.size(); i++)
|
||||
enqueue(index[i], prs[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue