3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-09-01 07:40:41 +00:00

Refactor assignment and search state

This commit is contained in:
Jakob Rath 2022-11-21 17:25:15 +01:00
parent 022c06f75d
commit 6e72a97727
22 changed files with 326 additions and 211 deletions

View file

@ -8,20 +8,15 @@ Module Name:
Author:
Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6
Jakob Rath 2021-04-06
--*/
#pragma once
#include "math/polysat/boolean.h"
#include "math/polysat/types.h"
#include "math/polysat/assignment.h"
namespace polysat {
typedef std::pair<pvar, rational> assignment_item_t;
typedef vector<assignment_item_t> assignment_t;
class solver;
enum class search_item_k
{
assignment,
@ -46,7 +41,7 @@ namespace polysat {
bool is_resolved() const { return m_resolved; }
search_item_k kind() const { return m_kind; }
pvar var() const { SASSERT(is_assignment()); return m_var; }
sat::literal lit() const { SASSERT(is_boolean()); return m_lit; }
sat::literal lit() const { SASSERT(is_boolean()); return m_lit; }
void set_resolved() { m_resolved = true; }
};
@ -54,27 +49,28 @@ namespace polysat {
solver& s;
vector<search_item> m_items;
assignment_t m_assignment; // First-order part of the search state
mutable scoped_ptr_vector<pdd> m_subst;
vector<pdd> m_subst_trail;
assignment m_assignment;
bool value(pvar v, rational& r) const;
public:
search_state(solver& s): s(s) {}
search_state(solver& s): s(s), m_assignment(s) {}
unsigned size() const { return m_items.size(); }
search_item const& back() const { return m_items.back(); }
search_item const& operator[](unsigned i) const { return m_items[i]; }
assignment_t const& assignment() const { return m_assignment; }
pdd& assignment(unsigned sz) const;
substitution const& subst(unsigned sz) const { return m_assignment.subst(sz); }
// TODO: implement the following method if we actually need the assignments without resolved items already during conflict resolution
// (no separate trail needed, just a second m_subst and an index into the trail, I think)
// (update on set_resolved? might be one iteration too early, looking at the old solver::resolve_conflict loop)
substitution const& unresolved_assignment(unsigned sz) const;
void push_assignment(pvar p, rational const& r);
void push_boolean(sat::literal lit);
void pop();
void pop_assignment();
void set_resolved(unsigned i) { m_items[i].set_resolved(); }
using const_iterator = decltype(m_items)::const_iterator;
@ -106,74 +102,4 @@ namespace polysat {
inline std::ostream& operator<<(std::ostream& out, search_item_pp const& p) { return p.verbose ? p.s.display_verbose(p.i, out) : p.s.display(p.i, out); }
// Go backwards over the search_state.
// If new entries are added during processing an item, they will be queued for processing next after the current item.
class search_iterator {
search_state* m_search;
unsigned current;
unsigned first; // highest index + 1
struct idx_range {
unsigned current;
unsigned first; // highest index + 1
};
vector<idx_range> m_index_stack;
void init() {
first = m_search->size();
current = first; // we start one before the beginning
}
void try_push_block() {
if (first != m_search->size()) {
m_index_stack.push_back({current, first});
init();
}
}
void pop_block() {
current = m_index_stack.back().current;
// We don't restore 'first', otherwise 'next()' will immediately push a new block again.
// Instead, the current block is merged with the popped one.
m_index_stack.pop_back();
}
unsigned last() {
return m_index_stack.empty() ? 0 : m_index_stack.back().first;
}
public:
search_iterator(search_state& search):
m_search(&search) {
init();
}
void set_resolved() {
m_search->set_resolved(current);
}
search_item const& operator*() {
return (*m_search)[current];
}
bool next() {
#if 1 // If you want to resolve over constraints that have been added during conflict resolution, enable this.
try_push_block();
#endif
if (current > last()) {
--current;
return true;
}
else {
SASSERT(current == last());
if (m_index_stack.empty())
return false;
pop_block();
return next();
}
}
};
}