mirror of
https://github.com/Z3Prover/z3
synced 2025-06-16 19:06:17 +00:00
Use templates on spanning trees
This commit is contained in:
parent
55e91c099f
commit
bc9bfe7f97
5 changed files with 64 additions and 45 deletions
|
@ -32,7 +32,7 @@ Notes:
|
||||||
|
|
||||||
#include"inf_rational.h"
|
#include"inf_rational.h"
|
||||||
#include"diff_logic.h"
|
#include"diff_logic.h"
|
||||||
#include"spanning_tree.h"
|
#include"spanning_tree_def.h"
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ namespace smt {
|
||||||
typedef typename Ext::fin_numeral fin_numeral;
|
typedef typename Ext::fin_numeral fin_numeral;
|
||||||
|
|
||||||
graph m_graph;
|
graph m_graph;
|
||||||
thread_spanning_tree tree;
|
thread_spanning_tree<Ext> tree;
|
||||||
|
|
||||||
// Denote supply/demand b_i on node i
|
// Denote supply/demand b_i on node i
|
||||||
vector<fin_numeral> m_balances;
|
vector<fin_numeral> m_balances;
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace smt {
|
||||||
m_balances.resize(num_nodes);
|
m_balances.resize(num_nodes);
|
||||||
m_potentials.resize(num_nodes);
|
m_potentials.resize(num_nodes);
|
||||||
|
|
||||||
tree = thread_spanning_tree();
|
tree = thread_spanning_tree<Ext>();
|
||||||
m_step = 0;
|
m_step = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,7 +303,6 @@ namespace smt {
|
||||||
return edge_in_tree(get_edge_id(src, dst));
|
return edge_in_tree(get_edge_id(src, dst));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool network_flow<Ext>::check_well_formed() {
|
bool network_flow<Ext>::check_well_formed() {
|
||||||
SASSERT(tree.check_well_formed());
|
SASSERT(tree.check_well_formed());
|
||||||
|
|
|
@ -19,13 +19,20 @@ Notes:
|
||||||
#ifndef _SPANNING_TREE_H_
|
#ifndef _SPANNING_TREE_H_
|
||||||
#define _SPANNING_TREE_H_
|
#define _SPANNING_TREE_H_
|
||||||
|
|
||||||
|
#include "diff_logic.h"
|
||||||
#include "spanning_tree_base.h"
|
#include "spanning_tree_base.h"
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
class thread_spanning_tree : virtual public spanning_tree_base {
|
class thread_spanning_tree : public spanning_tree_base, private Ext {
|
||||||
private:
|
private:
|
||||||
|
typedef dl_var node;
|
||||||
|
typedef dl_edge<Ext> edge;
|
||||||
|
typedef dl_graph<Ext> graph;
|
||||||
|
typedef typename Ext::numeral numeral;
|
||||||
|
typedef typename Ext::fin_numeral fin_numeral;
|
||||||
|
|
||||||
// Store the parent of a node i in the spanning tree
|
// Store the parent of a node i in the spanning tree
|
||||||
svector<node> m_pred;
|
svector<node> m_pred;
|
||||||
// Store the number of edge on the path from node i to the root
|
// Store the number of edge on the path from node i to the root
|
||||||
|
@ -47,8 +54,8 @@ namespace smt {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void initialize(svector<bool> const & upwards, int num_nodes);
|
void initialize(svector<bool> const & upwards, int num_nodes);
|
||||||
void get_descendants(node start, svector<node>& descendants);
|
void get_descendants(node start, svector<node> & descendants);
|
||||||
void get_ancestors(node start, svector<node>& ancestors);
|
void get_ancestors(node start, svector<node> & ancestors);
|
||||||
node get_common_ancestor(node u, node v);
|
node get_common_ancestor(node u, node v);
|
||||||
void update(node p, node q, node u, node v);
|
void update(node p, node q, node u, node v);
|
||||||
bool check_well_formed();
|
bool check_well_formed();
|
||||||
|
|
|
@ -24,8 +24,6 @@ Notes:
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
typedef int node;
|
|
||||||
|
|
||||||
template<typename TV>
|
template<typename TV>
|
||||||
inline std::string pp_vector(std::string const & label, TV v, bool has_header = false) {
|
inline std::string pp_vector(std::string const & label, TV v, bool has_header = false) {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
|
@ -45,26 +43,28 @@ namespace smt {
|
||||||
}
|
}
|
||||||
|
|
||||||
class spanning_tree_base {
|
class spanning_tree_base {
|
||||||
public:
|
private:
|
||||||
spanning_tree_base() {};
|
typedef int node;
|
||||||
virtual ~spanning_tree_base() {};
|
|
||||||
|
public:
|
||||||
|
virtual void initialize(svector<bool> const & upwards, int num_nodes) {};
|
||||||
|
|
||||||
virtual void initialize(svector<bool> const & upwards, int num_nodes) = 0;
|
|
||||||
/**
|
/**
|
||||||
\brief Get all descendants of a node including itself
|
\brief Get all descendants of a node including itself
|
||||||
*/
|
*/
|
||||||
virtual void get_descendants(node start, svector<node>& descendants) = 0;
|
virtual void get_descendants(node start, svector<node> & descendants) {};
|
||||||
/**
|
/**
|
||||||
\brief Get all ancestors of a node including itself
|
\brief Get all ancestors of a node including itself
|
||||||
*/
|
*/
|
||||||
virtual void get_ancestors(node start, svector<node>& ancestors) = 0;
|
virtual void get_ancestors(node start, svector<node> & ancestors) {};
|
||||||
virtual node get_common_ancestor(node u, node v) = 0;
|
|
||||||
virtual void update(node p, node q, node u, node v) = 0;
|
virtual node get_common_ancestor(node u, node v) {UNREACHABLE(); return -1;};
|
||||||
virtual bool check_well_formed() = 0;
|
virtual void update(node p, node q, node u, node v) {};
|
||||||
|
virtual bool check_well_formed() {UNREACHABLE(); return false;};
|
||||||
|
|
||||||
// TODO: remove these two unnatural functions
|
// TODO: remove these two unnatural functions
|
||||||
virtual bool get_arc_direction(node start) const = 0;
|
virtual bool get_arc_direction(node start) const {UNREACHABLE(); return false;};
|
||||||
virtual node get_parent(node start) = 0;
|
virtual node get_parent(node start) {UNREACHABLE(); return -1;};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ Copyright (c) 2013 Microsoft Corporation
|
||||||
|
|
||||||
Module Name:
|
Module Name:
|
||||||
|
|
||||||
spanning_tree.cpp
|
spanning_tree_def.h
|
||||||
|
|
||||||
Abstract:
|
Abstract:
|
||||||
|
|
||||||
|
@ -15,16 +15,13 @@ Author:
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include <sstream>
|
|
||||||
|
#ifndef _SPANNING_TREE_DEF_H_
|
||||||
|
#define _SPANNING_TREE_DEF_H_
|
||||||
|
|
||||||
#include "spanning_tree.h"
|
#include "spanning_tree.h"
|
||||||
#include "debug.h"
|
|
||||||
#include "vector.h"
|
|
||||||
#include "uint_set.h"
|
|
||||||
#include "trace.h"
|
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
swap v and q in tree.
|
swap v and q in tree.
|
||||||
- fixup m_thread
|
- fixup m_thread
|
||||||
|
@ -41,7 +38,8 @@ namespace smt {
|
||||||
New thread: prev -> q -*-> final(q) -> v -*-> alpha -> beta -*-> final(v) -> next
|
New thread: prev -> q -*-> final(q) -> v -*-> alpha -> beta -*-> final(v) -> next
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void thread_spanning_tree::swap_order(node q, node v) {
|
template<typename Ext>
|
||||||
|
void thread_spanning_tree<Ext>::swap_order(node q, node v) {
|
||||||
SASSERT(q != v);
|
SASSERT(q != v);
|
||||||
SASSERT(m_pred[q] == v);
|
SASSERT(m_pred[q] == v);
|
||||||
SASSERT(is_preorder_traversal(v, get_final(v)));
|
SASSERT(is_preorder_traversal(v, get_final(v)));
|
||||||
|
@ -68,7 +66,8 @@ namespace smt {
|
||||||
/**
|
/**
|
||||||
\brief find node that points to 'n' in m_thread
|
\brief find node that points to 'n' in m_thread
|
||||||
*/
|
*/
|
||||||
node thread_spanning_tree::find_rev_thread(node n) const {
|
template<typename Ext>
|
||||||
|
typename thread_spanning_tree<Ext>::node thread_spanning_tree<Ext>::find_rev_thread(node n) const {
|
||||||
node ancestor = m_pred[n];
|
node ancestor = m_pred[n];
|
||||||
SASSERT(ancestor != -1);
|
SASSERT(ancestor != -1);
|
||||||
while (m_thread[ancestor] != n) {
|
while (m_thread[ancestor] != n) {
|
||||||
|
@ -77,7 +76,8 @@ namespace smt {
|
||||||
return ancestor;
|
return ancestor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_spanning_tree::fix_depth(node start, node end) {
|
template<typename Ext>
|
||||||
|
void thread_spanning_tree<Ext>::fix_depth(node start, node end) {
|
||||||
SASSERT(m_pred[start] != -1);
|
SASSERT(m_pred[start] != -1);
|
||||||
m_depth[start] = m_depth[m_pred[start]]+1;
|
m_depth[start] = m_depth[m_pred[start]]+1;
|
||||||
while (start != end) {
|
while (start != end) {
|
||||||
|
@ -86,7 +86,8 @@ namespace smt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node thread_spanning_tree::get_final(int start) {
|
template<typename Ext>
|
||||||
|
typename thread_spanning_tree<Ext>::node thread_spanning_tree<Ext>::get_final(int start) {
|
||||||
int n = start;
|
int n = start;
|
||||||
while (m_depth[m_thread[n]] > m_depth[start]) {
|
while (m_depth[m_thread[n]] > m_depth[start]) {
|
||||||
n = m_thread[n];
|
n = m_thread[n];
|
||||||
|
@ -94,7 +95,8 @@ namespace smt {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thread_spanning_tree::is_preorder_traversal(node start, node end) {
|
template<typename Ext>
|
||||||
|
bool thread_spanning_tree<Ext>::is_preorder_traversal(node start, node end) {
|
||||||
// get children of start
|
// get children of start
|
||||||
uint_set children;
|
uint_set children;
|
||||||
children.insert(start);
|
children.insert(start);
|
||||||
|
@ -118,7 +120,8 @@ namespace smt {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thread_spanning_tree::is_ancestor_of(node ancestor, node child) {
|
template<typename Ext>
|
||||||
|
bool thread_spanning_tree<Ext>::is_ancestor_of(node ancestor, node child) {
|
||||||
for (node n = child; n != -1; n = m_pred[n]) {
|
for (node n = child; n != -1; n = m_pred[n]) {
|
||||||
if (n == ancestor) {
|
if (n == ancestor) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -154,7 +157,8 @@ namespace smt {
|
||||||
roots[y] = x;
|
roots[y] = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_spanning_tree::initialize(svector<bool> const & upwards, int num_nodes) {
|
template<typename Ext>
|
||||||
|
void thread_spanning_tree<Ext>::initialize(svector<bool> const & upwards, int num_nodes) {
|
||||||
m_pred.resize(num_nodes + 1);
|
m_pred.resize(num_nodes + 1);
|
||||||
m_depth.resize(num_nodes + 1);
|
m_depth.resize(num_nodes + 1);
|
||||||
m_thread.resize(num_nodes + 1);
|
m_thread.resize(num_nodes + 1);
|
||||||
|
@ -179,7 +183,8 @@ namespace smt {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
node thread_spanning_tree::get_common_ancestor(node u, node v) {
|
template<typename Ext>
|
||||||
|
typename thread_spanning_tree<Ext>::node thread_spanning_tree<Ext>::get_common_ancestor(node u, node v) {
|
||||||
while (u != v) {
|
while (u != v) {
|
||||||
if (m_depth[u] > m_depth[v])
|
if (m_depth[u] > m_depth[v])
|
||||||
u = m_pred[u];
|
u = m_pred[u];
|
||||||
|
@ -189,7 +194,8 @@ namespace smt {
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_spanning_tree::get_descendants(node start, svector<node>& descendants) {
|
template<typename Ext>
|
||||||
|
void thread_spanning_tree<Ext>::get_descendants(node start, svector<node>& descendants) {
|
||||||
descendants.reset();
|
descendants.reset();
|
||||||
node u = start;
|
node u = start;
|
||||||
while (m_depth[m_thread[u]] > m_depth[start]) {
|
while (m_depth[m_thread[u]] > m_depth[start]) {
|
||||||
|
@ -198,7 +204,8 @@ namespace smt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_spanning_tree::get_ancestors(node start, svector<node>& ancestors) {
|
template<typename Ext>
|
||||||
|
void thread_spanning_tree<Ext>::get_ancestors(node start, svector<node>& ancestors) {
|
||||||
ancestors.reset();
|
ancestors.reset();
|
||||||
while (m_pred[start] != -1) {
|
while (m_pred[start] != -1) {
|
||||||
ancestors.push_back(start);
|
ancestors.push_back(start);
|
||||||
|
@ -222,7 +229,8 @@ namespace smt {
|
||||||
\ \ /
|
\ \ /
|
||||||
q q
|
q q
|
||||||
*/
|
*/
|
||||||
void thread_spanning_tree::update(node p, node q, node u, node v) {
|
template<typename Ext>
|
||||||
|
void thread_spanning_tree<Ext>::update(node p, node q, node u, node v) {
|
||||||
bool q_upwards = false;
|
bool q_upwards = false;
|
||||||
|
|
||||||
// v is parent of u so T_u does not contain root node
|
// v is parent of u so T_u does not contain root node
|
||||||
|
@ -299,7 +307,8 @@ namespace smt {
|
||||||
m_upwards direction of edge from i to m_pred[i] m_graph
|
m_upwards direction of edge from i to m_pred[i] m_graph
|
||||||
|
|
||||||
*/
|
*/
|
||||||
bool thread_spanning_tree::check_well_formed() {
|
template<typename Ext>
|
||||||
|
bool thread_spanning_tree<Ext>::check_well_formed() {
|
||||||
node root = m_pred.size()-1;
|
node root = m_pred.size()-1;
|
||||||
|
|
||||||
// Check that m_thread traverses each node.
|
// Check that m_thread traverses each node.
|
||||||
|
@ -346,11 +355,15 @@ namespace smt {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool thread_spanning_tree::get_arc_direction(node start) const {
|
template<typename Ext>
|
||||||
|
bool thread_spanning_tree<Ext>::get_arc_direction(node start) const {
|
||||||
return m_upwards[start];
|
return m_upwards[start];
|
||||||
}
|
}
|
||||||
|
|
||||||
node thread_spanning_tree::get_parent(node start) {
|
template<typename Ext>
|
||||||
|
typename thread_spanning_tree<Ext>::node thread_spanning_tree<Ext>::get_parent(node start) {
|
||||||
return m_pred[start];
|
return m_pred[start];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue