3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 00:55:31 +00:00

Propagator (#5845)

* user propagator without ids

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* user propagator without ids

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix signature

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* references #5818

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fix c++ build

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* switch to vs 2022

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* switch 2022

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* Update propagator example (I) (#5835)

* fix #5829

* na

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* switch to vs 2022

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* Adapted the example to the changes in the propagator

Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* context goes out of scope in stack allocation, so can't used scoped context when passing objects around

* parameter check

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* add rewriter

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* Fixed bug in user-propagator "created" (#5843)

Co-authored-by: Clemens Eisenhofer <56730610+CEisenhofer@users.noreply.github.com>
This commit is contained in:
Nikolaj Bjorner 2022-02-17 09:21:41 +02:00 committed by GitHub
parent 2e15e2aa4d
commit 2e00f2f32d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 261 additions and 328 deletions

View file

@ -50,15 +50,36 @@ struct model_hash_function {
}
};
namespace std {
template<>
struct hash<z3::expr> {
std::size_t operator()(const z3::expr &k) const {
return k.hash();
}
};
}
// Do not use Z3's == operator in the hash table
namespace std {
template<>
struct equal_to<z3::expr> {
bool operator()(const z3::expr &lhs, const z3::expr &rhs) const {
return z3::eq(lhs, rhs);
}
};
}
class user_propagator : public z3::user_propagator_base {
protected:
unsigned board;
std::unordered_map<unsigned, unsigned>& id_mapping;
std::unordered_map<z3::expr, unsigned>& id_mapping;
model currentModel;
std::unordered_set<model, model_hash_function> modelSet;
std::vector<unsigned> fixedValues;
std::vector<z3::expr> fixedValues;
std::stack<unsigned> fixedCnt;
int solutionId = 1;
@ -70,7 +91,10 @@ public:
}
void final() final {
this->conflict((unsigned) fixedValues.size(), fixedValues.data());
z3::expr_vector conflicting(fixedValues[0].ctx());
for (auto&& v : fixedValues)
conflicting.push_back(v);
this->conflict(conflicting);
if (modelSet.find(currentModel) != modelSet.end()) {
WriteLine("Got already computed model");
return;
@ -91,20 +115,20 @@ public:
return (unsigned)e.get_numeral_int();
}
void fixed(unsigned id, z3::expr const &e) override {
fixedValues.push_back(id);
unsigned value = bvToInt(e);
currentModel[id_mapping[id]] = value;
void fixed(z3::expr const &ast, z3::expr const &value) override {
fixedValues.push_back(ast);
unsigned valueBv = bvToInt(value);
currentModel[id_mapping[ast]] = valueBv;
}
user_propagator(z3::solver *s, std::unordered_map<unsigned, unsigned>& idMapping, unsigned board)
user_propagator(z3::solver *s, std::unordered_map<z3::expr, unsigned>& idMapping, unsigned board)
: user_propagator_base(s), board(board), id_mapping(idMapping), currentModel(board, (unsigned)-1) {
this->register_fixed();
this->register_final();
}
virtual ~user_propagator() = default;
~user_propagator() = default;
void push() override {
fixedCnt.push((unsigned) fixedValues.size());
@ -117,50 +141,58 @@ public:
for (auto j = fixedValues.size(); j > lastCnt; j--) {
currentModel[fixedValues[j - 1]] = (unsigned)-1;
}
fixedValues.resize(lastCnt);
fixedValues.erase(fixedValues.cbegin() + lastCnt, fixedValues.cend());
}
}
user_propagator_base *fresh(Z3_context) override { return this; }
user_propagator_base *fresh(Z3_context) override {
return this;
}
};
class user_propagator_with_theory : public user_propagator {
public:
void fixed(unsigned id, z3::expr const &e) override {
unsigned queenId = id_mapping[id];
unsigned queenPos = bvToInt(e);
void fixed(z3::expr const &ast, z3::expr const &value) override {
unsigned queenId = id_mapping[ast];
unsigned queenPos = bvToInt(value);
if (queenPos >= board) {
this->conflict(1, &id);
z3::expr_vector conflicting(ast.ctx());
conflicting.push_back(ast);
this->conflict(conflicting);
return;
}
for (unsigned fixed : fixedValues) {
for (z3::expr fixed : fixedValues) {
unsigned otherId = id_mapping[fixed];
unsigned otherPos = currentModel[fixed];
if (queenPos == otherPos) {
const unsigned conflicting[] = {id, fixed};
this->conflict(2, conflicting);
z3::expr_vector conflicting(ast.ctx());
conflicting.push_back(ast);
conflicting.push_back(fixed);
this->conflict(conflicting);
continue;
}
#ifdef QUEEN
int diffY = abs((int)queenId - (int)otherId);
int diffX = abs((int)queenPos - (int)otherPos);
if (diffX == diffY) {
const unsigned conflicting[] = {id, fixed};
this->conflict(2, conflicting);
z3::expr_vector conflicting(ast.ctx());
conflicting.push_back(ast);
conflicting.push_back(fixed);
this->conflict(conflicting);
}
#endif
}
fixedValues.push_back(id);
currentModel[id_mapping[id]] = queenPos;
fixedValues.push_back(ast);
currentModel[id_mapping[ast]] = queenPos;
}
user_propagator_with_theory(z3::solver *s, std::unordered_map<unsigned, unsigned>& idMapping, unsigned board)
user_propagator_with_theory(z3::solver *s, std::unordered_map<z3::expr, unsigned>& idMapping, unsigned board)
: user_propagator(s, idMapping, board) {}
};
@ -261,7 +293,7 @@ inline int test1(unsigned num) {
int test23(unsigned num, bool withTheory) {
z3::context context;
z3::solver solver(context, Z3_mk_simple_solver(context));
std::unordered_map<unsigned, unsigned> idMapping;
std::unordered_map<z3::expr, unsigned> idMapping;
user_propagator *propagator;
if (!withTheory) {
@ -274,8 +306,8 @@ int test23(unsigned num, bool withTheory) {
std::vector<z3::expr> queens = createQueens(context, num);
for (unsigned i = 0; i < queens.size(); i++) {
unsigned id = propagator->add(queens[i]);
idMapping[id] = i;
propagator->add(queens[i]);
idMapping[queens[i]] = i;
}
if (!withTheory) {