3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-20 04:43:39 +00:00

Merge branch 'opt' of https://git01.codeplex.com/z3 into opt

This commit is contained in:
Nikolaj Bjorner 2013-11-01 17:26:48 -07:00
commit b35ed169b1

View file

@ -42,7 +42,6 @@ namespace smt {
return oss.str(); return oss.str();
} }
template<typename Ext> template<typename Ext>
network_flow<Ext>::network_flow(graph & g, vector<fin_numeral> const & balances) : network_flow<Ext>::network_flow(graph & g, vector<fin_numeral> const & balances) :
m_balances(balances) { m_balances(balances) {
@ -98,6 +97,7 @@ namespace smt {
m_balances[root] = -sum_supply; m_balances[root] = -sum_supply;
m_flows.resize(num_nodes + num_edges); m_flows.resize(num_nodes + num_edges);
m_flows.fill(numeral::zero());
m_states.resize(num_nodes + num_edges); m_states.resize(num_nodes + num_edges);
m_states.fill(LOWER); m_states.fill(LOWER);
@ -269,15 +269,11 @@ namespace smt {
node v = m_graph.get_target(m_leaving_edge); node v = m_graph.get_target(m_leaving_edge);
// 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
if (m_pred[u] == v) { if (m_pred[u] == v) {
node temp = u; std::swap(u, v);
u = v;
v = temp;
} }
if ((m_states[m_entering_edge] == UPPER) == m_in_edge_dir) { if ((m_states[m_entering_edge] == UPPER) == m_in_edge_dir) {
// q should be in T_v so swap p and q // q should be in T_v so swap p and q
node temp = p; std::swap(p, q);
p = q;
q = temp;
} }
TRACE("network_flow", { TRACE("network_flow", {
@ -329,7 +325,14 @@ namespace smt {
gamma = m_thread[m_final[v]]; gamma = m_thread[m_final[v]];
// Check that f(u) is not in T_v // Check that f(u) is not in T_v
node delta = m_final[u] != m_final[v] ? m_final[u] : phi; bool found_final_u = false;
for (node n = v; n == m_final[v]; n = m_thread[n]) {
if (n == m_final[u]) {
found_final_u = true;
break;
}
}
node delta = found_final_u ? phi : m_final[u];
n = u; n = u;
last = m_pred[gamma]; last = m_pred[gamma];
while (n != last && n != -1) { while (n != last && n != -1) {
@ -380,13 +383,13 @@ namespace smt {
for (unsigned i = 0; i < m_thread.size(); ++i) { for (unsigned i = 0; i < m_thread.size(); ++i) {
m_rev_thread[m_thread[i]] = i; m_rev_thread[m_thread[i]] = i;
} }
SASSERT(check_well_formed());
TRACE("network_flow", { TRACE("network_flow", {
tout << pp_vector("Predecessors", m_pred, true) << pp_vector("Threads", m_thread); tout << pp_vector("Predecessors", m_pred, true) << pp_vector("Threads", m_thread);
tout << pp_vector("Reverse Threads", m_rev_thread) << pp_vector("Last Successors", m_final); tout << pp_vector("Reverse Threads", m_rev_thread) << pp_vector("Last Successors", m_final);
tout << pp_vector("Depths", m_depth) << pp_vector("Upwards", m_upwards); tout << pp_vector("Depths", m_depth) << pp_vector("Upwards", m_upwards);
}); });
SASSERT(check_well_formed());
} }
template<typename Ext> template<typename Ext>
@ -470,7 +473,10 @@ namespace smt {
while (roots[x] >= 0) { while (roots[x] >= 0) {
x = roots[x]; x = roots[x];
} }
SASSERT(roots[x] < 0);
if (old_x != x) {
roots[old_x] = x; roots[old_x] = x;
}
return x; return x;
} }
@ -485,44 +491,64 @@ namespace smt {
std::swap(x, y); std::swap(x, y);
} }
SASSERT(roots[x] <= roots[y]); SASSERT(roots[x] <= roots[y]);
roots[y] = x;
roots[x] += roots[y]; roots[x] += roots[y];
roots[y] = x;
}
static int get_final(int root, svector<int> const & thread, svector<int> const & depth) {
int n = root;
while (depth[thread[n]] > depth[root]) {
n = thread[n];
}
return n;
} }
template<typename Ext> template<typename Ext>
bool network_flow<Ext>::check_well_formed() { bool network_flow<Ext>::check_well_formed() {
// m_thread is depth-first stack
// m_pred is predecessor link
// m_depth depth counting from a root note.
// m_graph
#if 0
node root = m_pred.size()-1; node root = m_pred.size()-1;
// m_upwards show correct direction
for (unsigned i = 0; i < m_upwards.size(); ++i) { for (unsigned i = 0; i < m_upwards.size(); ++i) {
if (m_upwards[i]) {
node p = m_pred[i]; node p = m_pred[i];
edge_id e = get_edge_id(i, p); edge_id id;
// we are either the root or the predecessor points up. SASSERT(m_upwards[i] == m_graph.get_edge_id(i, p, id));
SASSERT(p == root || m_upwards[p]);
} }
// m_depth[x] denotes distance from x to the root node
for (node x = m_thread[root]; x != root; x = m_thread[x]) {
SASSERT(m_depth[x] == m_depth[m_pred[x]] + 1);
}
// m_final of a node denotes the last node with a bigger depth
for (unsigned i = 0; i < m_final.size(); ++i) {
SASSERT(m_final[i] == get_final(i, m_thread, m_depth));
} }
// m_thread forms a spanning tree over [0..root] // m_thread forms a spanning tree over [0..root]
// union-find structure: // Union-find structure
svector<int> roots(root+1, -1); svector<int> roots(m_pred.size(), -1);
for (unsigned i = 0; i < m_thread.size(); ++i) { for (node x = m_thread[root]; x != root; x = m_thread[x]) {
if (m_states[i] == BASIS) { node y = m_pred[x];
node x = m_thread[i]; // We are now going to check the edge between x and y
node y = i;
// we are now going to check the edge between x and y:
SASSERT(find(roots, x) != find(roots, y)); SASSERT(find(roots, x) != find(roots, y));
merge(roots, x, y); merge(roots, x, y);
} }
else {
// ? LOWER, UPPER std::cout << "roots" << std::endl;
for (unsigned i = 0; i < roots.size(); ++i) {
std::cout << i << " |-> " << roots[i] << std::endl;
} }
// All nodes belong to the same spanning tree
for (unsigned i = 0; i < roots.size(); ++i) {
SASSERT(i == 0 ? roots[i] + roots.size() == 0 : roots[i] == 0);
}
// m_flows are zero on non-basic edges
for (unsigned i = 0; i < m_flows.size(); ++i) {
SASSERT(m_states[i] == BASIS || m_flows[i].is_zero());
} }
#endif
return true; return true;
} }