mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 17:15:31 +00:00
update topological sort to use arrays instead of hash tables, expose Context over Z3Object for programmability
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
0e6c64510a
commit
51ed13f96a
17 changed files with 103 additions and 96 deletions
|
@ -24,39 +24,51 @@ Revision History:
|
|||
#include "util/obj_hashtable.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/memory_manager.h"
|
||||
#include "util/tptr.h"
|
||||
|
||||
|
||||
template<typename T>
|
||||
class top_sort {
|
||||
typedef obj_hashtable<T> T_set;
|
||||
obj_map<T, unsigned> m_partition_id;
|
||||
obj_map<T, unsigned> m_dfs_num;
|
||||
unsigned_vector m_partition_id;
|
||||
unsigned_vector m_dfs_num;
|
||||
ptr_vector<T> m_top_sorted;
|
||||
ptr_vector<T> m_stack_S;
|
||||
ptr_vector<T> m_stack_P;
|
||||
unsigned m_next_preorder;
|
||||
obj_map<T, T_set*> m_deps;
|
||||
ptr_vector<T_set> m_deps;
|
||||
ptr_vector<T> m_dep_keys;
|
||||
|
||||
static T_set* add_tag(T_set* t) { return TAG(T_set*, t, 1); }
|
||||
static T_set* del_tag(T_set* t) { return UNTAG(T_set*, t); }
|
||||
T_set* get_dep(T* t) const { return del_tag(m_deps.get(t->get_small_id())); }
|
||||
|
||||
|
||||
bool contains_partition(T* f) const {
|
||||
return m_partition_id.get(f->get_small_id()) != UINT_MAX;
|
||||
}
|
||||
|
||||
|
||||
void traverse(T* f) {
|
||||
unsigned p_id = 0;
|
||||
if (m_dfs_num.find(f, p_id)) {
|
||||
if (!m_partition_id.contains(f)) {
|
||||
while (!m_stack_P.empty() && m_partition_id.contains(m_stack_P.back()) && m_partition_id[m_stack_P.back()] > p_id) {
|
||||
unsigned p_id = m_dfs_num.get(f->get_small_id(), UINT_MAX);
|
||||
if (p_id != UINT_MAX) {
|
||||
if (!contains_partition(f)) {
|
||||
while (!m_stack_P.empty() && contains_partition(m_stack_P.back()) && partition_id(m_stack_P.back()) > p_id) {
|
||||
m_stack_P.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!m_deps.contains(f)) {
|
||||
else if (!contains_dep(f))
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m_dfs_num.insert(f, m_next_preorder++);
|
||||
m_dfs_num.setx(f->get_small_id(), m_next_preorder, UINT_MAX);
|
||||
++m_next_preorder;
|
||||
m_stack_S.push_back(f);
|
||||
m_stack_P.push_back(f);
|
||||
if (m_deps[f]) {
|
||||
for (T* g : *m_deps[f]) {
|
||||
T_set* ts = get_dep(f);
|
||||
if (ts) {
|
||||
for (T* g : *ts)
|
||||
traverse(g);
|
||||
}
|
||||
}
|
||||
if (f == m_stack_P.back()) {
|
||||
p_id = m_top_sorted.size();
|
||||
|
@ -65,7 +77,7 @@ class top_sort {
|
|||
s_f = m_stack_S.back();
|
||||
m_stack_S.pop_back();
|
||||
m_top_sorted.push_back(s_f);
|
||||
m_partition_id.insert(s_f, p_id);
|
||||
m_partition_id.setx(s_f->get_small_id(), p_id, UINT_MAX);
|
||||
}
|
||||
while (s_f != f);
|
||||
m_stack_P.pop_back();
|
||||
|
@ -76,28 +88,29 @@ class top_sort {
|
|||
public:
|
||||
|
||||
virtual ~top_sort() {
|
||||
for (auto & kv : m_deps) dealloc(kv.m_value);
|
||||
for (auto * t : m_dep_keys)
|
||||
dealloc(get_dep(t));
|
||||
}
|
||||
|
||||
void topological_sort() {
|
||||
m_next_preorder = 0;
|
||||
m_partition_id.reset();
|
||||
m_top_sorted.reset();
|
||||
for (auto & kv : m_deps) {
|
||||
traverse(kv.m_key);
|
||||
}
|
||||
for (auto * t : m_dep_keys)
|
||||
traverse(t);
|
||||
SASSERT(m_stack_S.empty());
|
||||
SASSERT(m_stack_P.empty());
|
||||
m_dfs_num.reset();
|
||||
}
|
||||
|
||||
void insert(T* t, T_set* s) {
|
||||
m_deps.insert(t, s);
|
||||
void insert(T* t, T_set* s) {
|
||||
m_deps.setx(t->get_small_id(), add_tag(s), nullptr);
|
||||
m_dep_keys.push_back(t);
|
||||
}
|
||||
|
||||
void add(T* t, T* s) {
|
||||
T_set* tb = nullptr;
|
||||
if (!m_deps.find(t, tb) || !tb) {
|
||||
T_set* tb = get_dep(t);
|
||||
if (!tb) {
|
||||
tb = alloc(T_set);
|
||||
insert(t, tb);
|
||||
}
|
||||
|
@ -106,18 +119,18 @@ public:
|
|||
|
||||
ptr_vector<T> const& top_sorted() const { return m_top_sorted; }
|
||||
|
||||
obj_map<T, unsigned> const& partition_ids() const { return m_partition_id; }
|
||||
unsigned partition_id(T* t) const { return m_partition_id[t->get_small_id()]; }
|
||||
|
||||
unsigned partition_id(T* t) const { return m_partition_id[t]; }
|
||||
bool find(T* t, unsigned& p) const { p = m_partition_id.get(t->get_small_id(), UINT_MAX); return p != UINT_MAX; }
|
||||
|
||||
bool contains_dep(T* t) const { return m_deps.get(t->get_small_id(), nullptr) != nullptr; }
|
||||
|
||||
bool is_singleton_partition(T* f) const {
|
||||
unsigned pid = m_partition_id[f];
|
||||
unsigned pid = m_partition_id(f);
|
||||
return f == m_top_sorted[pid] &&
|
||||
(pid == 0 || m_partition_id[m_top_sorted[pid-1]] != pid) &&
|
||||
(pid + 1 == m_top_sorted.size() || m_partition_id[m_top_sorted[pid+1]] != pid);
|
||||
(pid == 0 || partition_id(m_top_sorted[pid-1]) != pid) &&
|
||||
(pid + 1 == m_top_sorted.size() || partition_id(m_top_sorted[pid+1]) != pid);
|
||||
}
|
||||
|
||||
obj_map<T, T_set*> const& deps() const { return m_deps; }
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue