mirror of
https://github.com/Z3Prover/z3
synced 2025-06-16 10:56:16 +00:00
Fix bugs on candidate list pivot rule
This commit is contained in:
parent
0d6ffe6b31
commit
66eda866ca
2 changed files with 57 additions and 43 deletions
|
@ -156,24 +156,29 @@ namespace smt {
|
||||||
private:
|
private:
|
||||||
edge_id m_next_edge;
|
edge_id m_next_edge;
|
||||||
svector<edge_id> m_candidates;
|
svector<edge_id> m_candidates;
|
||||||
unsigned num_candidates;
|
unsigned m_num_candidates;
|
||||||
|
unsigned m_minor_step;
|
||||||
|
unsigned m_current_length;
|
||||||
static const unsigned NUM_CANDIDATES = 10;
|
static const unsigned NUM_CANDIDATES = 10;
|
||||||
|
static const unsigned MINOR_STEP_LIMIT = 5;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
candidate_list_pivot(graph & g, vector<numeral> & potentials,
|
candidate_list_pivot(graph & g, vector<numeral> & potentials,
|
||||||
svector<edge_state> & states, edge_id & enter_id) :
|
svector<edge_state> & states, edge_id & enter_id) :
|
||||||
pivot_rule_impl(g, potentials, states, enter_id),
|
pivot_rule_impl(g, potentials, states, enter_id),
|
||||||
m_next_edge(0),
|
m_next_edge(0),
|
||||||
num_candidates(NUM_CANDIDATES),
|
m_minor_step(0),
|
||||||
m_candidates(num_candidates) {
|
m_current_length(0),
|
||||||
|
m_num_candidates(NUM_CANDIDATES),
|
||||||
|
m_candidates(m_num_candidates) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool choose_entering_edge() {
|
bool choose_entering_edge() {
|
||||||
if (m_candidates.empty()) {
|
if (m_current_length == 0 || m_minor_step == MINOR_STEP_LIMIT) {
|
||||||
// Build the candidate list
|
// Build the candidate list
|
||||||
unsigned num_edges = m_graph.get_num_edges();
|
unsigned num_edges = m_graph.get_num_edges();
|
||||||
numeral max = numeral::zero();
|
numeral max = numeral::zero();
|
||||||
unsigned count = 0;
|
m_current_length = 0;
|
||||||
for (unsigned i = m_next_edge; i < m_next_edge + num_edges; ++i) {
|
for (unsigned i = m_next_edge; i < m_next_edge + num_edges; ++i) {
|
||||||
edge_id id = (i >= num_edges) ? i - num_edges : i;
|
edge_id id = (i >= num_edges) ? i - num_edges : i;
|
||||||
node src = m_graph.get_source(id);
|
node src = m_graph.get_source(id);
|
||||||
|
@ -181,16 +186,18 @@ namespace smt {
|
||||||
if (m_states[id] != BASIS) {
|
if (m_states[id] != BASIS) {
|
||||||
numeral cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id);
|
numeral cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id);
|
||||||
if (cost.is_pos()) {
|
if (cost.is_pos()) {
|
||||||
m_candidates[count++] = id;
|
m_candidates[m_current_length] = id;
|
||||||
|
++m_current_length;
|
||||||
if (cost > max) {
|
if (cost > max) {
|
||||||
max = cost;
|
max = cost;
|
||||||
m_enter_id = id;
|
m_enter_id = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (count >= num_candidates) break;
|
if (m_current_length >= m_num_candidates) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_next_edge = m_enter_id;
|
m_next_edge = m_enter_id;
|
||||||
|
m_minor_step = 1;
|
||||||
if (max.is_pos()) {
|
if (max.is_pos()) {
|
||||||
TRACE("network_flow", {
|
TRACE("network_flow", {
|
||||||
tout << "Found entering edge " << m_enter_id << " between node ";
|
tout << "Found entering edge " << m_enter_id << " between node ";
|
||||||
|
@ -202,36 +209,37 @@ namespace smt {
|
||||||
TRACE("network_flow", tout << "Found no entering edge...\n";);
|
TRACE("network_flow", tout << "Found no entering edge...\n";);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
numeral max = numeral::zero();
|
++m_minor_step;
|
||||||
unsigned last = m_candidates.size();
|
numeral max = numeral::zero();
|
||||||
for (unsigned i = 0; i < last; ++i) {
|
for (unsigned i = 0; i < m_current_length; ++i) {
|
||||||
edge_id id = m_candidates[i];
|
edge_id id = m_candidates[i];
|
||||||
node src = m_graph.get_source(id);
|
node src = m_graph.get_source(id);
|
||||||
node tgt = m_graph.get_target(id);
|
node tgt = m_graph.get_target(id);
|
||||||
if (m_states[id] != BASIS) {
|
if (m_states[id] != BASIS) {
|
||||||
numeral cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id);
|
numeral cost = m_potentials[src] - m_potentials[tgt] - m_graph.get_weight(id);
|
||||||
if (cost > max) {
|
if (cost > max) {
|
||||||
max = cost;
|
max = cost;
|
||||||
m_enter_id = id;
|
m_enter_id = id;
|
||||||
}
|
}
|
||||||
// Remove stale candidates
|
// Remove stale candidates
|
||||||
if (!cost.is_pos()) {
|
if (!cost.is_pos()) {
|
||||||
m_candidates[i] = m_candidates[--last];
|
--m_current_length;
|
||||||
}
|
m_candidates[i] = m_candidates[m_current_length];
|
||||||
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max.is_pos()) {
|
|
||||||
TRACE("network_flow", {
|
|
||||||
tout << "Found entering edge " << m_enter_id << " between node ";
|
|
||||||
tout << m_graph.get_source(m_enter_id) << " and node " << m_graph.get_target(m_enter_id);
|
|
||||||
tout << " with reduced cost = " << max << "...\n";
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
TRACE("network_flow", tout << "Found no entering edge...\n";);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (max.is_pos()) {
|
||||||
|
TRACE("network_flow", {
|
||||||
|
tout << "Found entering edge " << m_enter_id << " between node ";
|
||||||
|
tout << m_graph.get_source(m_enter_id) << " and node " << m_graph.get_target(m_enter_id);
|
||||||
|
tout << " with reduced cost = " << max << "...\n";
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
TRACE("network_flow", tout << "Found no entering edge...\n";);
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -333,23 +333,29 @@ namespace smt {
|
||||||
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)));
|
||||||
node prev = find_rev_thread(v);
|
node prev = find_rev_thread(v);
|
||||||
node final_q = get_final(q);
|
node f_q = get_final(q);
|
||||||
node final_v = get_final(v);
|
node f_v = get_final(v);
|
||||||
node next = m_thread[final_v];
|
node next = m_thread[f_v];
|
||||||
node alpha = find_rev_thread(q);
|
node alpha = find_rev_thread(q);
|
||||||
|
|
||||||
if (final_q == final_v) {
|
if (f_q == f_v) {
|
||||||
m_thread[final_q] = v;
|
SASSERT(f_q != v && alpha != next);
|
||||||
|
m_thread[f_q] = v;
|
||||||
m_thread[alpha] = next;
|
m_thread[alpha] = next;
|
||||||
|
f_q = alpha;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node beta = m_thread[final_q];
|
node beta = m_thread[f_q];
|
||||||
m_thread[final_q] = v;
|
SASSERT(f_q != v && alpha != beta);
|
||||||
|
m_thread[f_q] = v;
|
||||||
m_thread[alpha] = beta;
|
m_thread[alpha] = beta;
|
||||||
|
f_q = f_v;
|
||||||
}
|
}
|
||||||
|
SASSERT(prev != q);
|
||||||
m_thread[prev] = q;
|
m_thread[prev] = q;
|
||||||
m_pred[v] = q;
|
m_pred[v] = q;
|
||||||
SASSERT(is_preorder_traversal(q, get_final(q)));
|
// Notes: f_q has to be used since m_depth hasn't been updated yet.
|
||||||
|
SASSERT(is_preorder_traversal(q, f_q));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue