3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-03-17 02:30:01 +00:00
z3/src/tactic/portfolio/solver_subsumption_tactic.cpp
Copilot 2436943794
Standardize for-loop increments to prefix form (++i) (#8199)
* Initial plan

* Convert postfix to prefix increment in for loops

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Fix member variable increment conversion bug

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* Update API generator to produce prefix increments

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
2026-01-14 19:55:31 -08:00

182 lines
5.1 KiB
C++

/*++
Copyright (c) 2011 Microsoft Corporation
Module Name:
solver_subsumption_tactic.cpp
Author:
Nikolaj Bjorner (nbjorner) 2021-7-23
--*/
#include "ast/ast_util.h"
#include "tactic/tactical.h"
#include "tactic/portfolio/solver_subsumption_tactic.h"
#include "solver/solver.h"
class solver_subsumption_tactic : public tactic {
ast_manager& m;
params_ref m_params;
solver_ref m_solver;
void push() {
m_solver->push();
}
void pop() {
m_solver->pop(1);
}
void assert_expr(expr* f) {
m_solver->assert_expr(f);
}
bool subsumed(expr* f) {
expr_ref_vector fmls(m);
fmls.push_back(m.mk_not(f));
lbool is_sat = m_solver->check_sat(fmls);
return (is_sat == l_false);
}
/**
* Check subsumption (a \/ b \/ c)
*
* If
* F |= (a \/ ~b \/ c)
* Then replace (a \/ b \/ c) by (a \/ c)
*
* If
* F |= (a \/ b \/ c)
* Then replace (a \/ b \/ c) by true
*
*/
bool simplify(expr_ref& f) {
expr_ref_vector fmls(m), ors(m), nors(m), prefix(m);
expr_ref nf(m.mk_not(f), m);
fmls.push_back(nf);
lbool is_sat = m_solver->check_sat(fmls);
if (is_sat == l_false) {
f = m.mk_true();
return true;
}
if (!m.is_or(f))
return false;
ors.append(to_app(f)->get_num_args(), to_app(f)->get_args());
for (expr* arg : ors)
nors.push_back(mk_not(m, arg));
for (unsigned i = 0; i < ors.size(); ++i) {
expr* arg = ors.get(i);
expr_ref save(nors.get(i), m);
nors[i] = arg;
is_sat = m_solver->check_sat(nors);
nors[i] = save;
if (is_sat == l_false)
nors[i] = m.mk_true();
else
prefix.push_back(arg);
}
if (ors.size() != prefix.size()) {
ors.reset();
ors.append(prefix.size(), prefix.data());
f = mk_or(ors);
return true;
}
return false;
}
void simplify(vector<std::pair<unsigned, expr_ref>>& fmls, unsigned_vector& change) {
if (fmls.size() == 0)
return;
if (fmls.size() == 1) {
if (subsumed(fmls[0].second)) {
change.push_back(fmls[0].first);
fmls[0].second = m.mk_true();
}
else if (simplify(fmls[0].second))
change.push_back(fmls[0].first);
return;
}
unsigned mid = fmls.size() / 2;
vector<std::pair<unsigned, expr_ref>> pre(mid, fmls.data());
vector<std::pair<unsigned, expr_ref>> post(fmls.size() - mid, fmls.data() + mid);
push();
for (auto const& [p, f] : post)
assert_expr(f);
simplify(pre, change);
pop();
push();
for (auto const& [p, f] : pre)
assert_expr(f);
simplify(post, change);
pop();
if (!change.empty()) {
fmls.reset();
fmls.append(pre);
fmls.append(post);
}
}
public:
solver_subsumption_tactic(ast_manager& m, params_ref const& p) :
m(m),
m_params(p) {
}
tactic* translate(ast_manager& other_m) override {
return alloc(solver_subsumption_tactic, other_m, m_params);
}
char const* name() const override { return "solver_subsumption"; }
void updt_params(params_ref const& p) override {
m_params.append(p);
unsigned max_conflicts = m_params.get_uint("max_conflicts", 2);
m_params.set_uint("sat.max_conflicts", max_conflicts);
m_params.set_uint("smt.max_conflicts", max_conflicts);
}
void collect_param_descrs(param_descrs& r) override {
r.insert("max_conflicts", CPK_UINT, "(default: 2) maximal number of conflicts allowed per solver call.");
}
void operator()(goal_ref const& g, goal_ref_buffer& result) override {
TRACE(tactic, tout << "params: " << m_params << "\n"; g->display(tout););
tactic_report report("subsumption", *g);
vector<std::pair<unsigned, expr_ref>> fmls;
unsigned_vector change;
unsigned sz = g->size();
if (sz == 1) {
result.push_back(g.get());
return;
}
for (unsigned i = 0; i < sz; ++i)
fmls.push_back(std::make_pair(i, expr_ref(g->form(i), m)));
if (!m_solver) {
scoped_ptr<solver_factory> f = mk_smt_strategic_solver_factory();
m_solver = (*f)(m, m_params, false, false, true, symbol::null);
}
simplify(fmls, change);
if (change.empty()) {
result.push_back(g.get());
return;
}
g->inc_depth();
for (unsigned idx : change)
g->update(idx, fmls[idx].second);
g->elim_true();
result.push_back(g.get());
}
void cleanup() override {}
};
tactic* mk_solver_subsumption_tactic(ast_manager& m, params_ref const& p) {
return alloc(solver_subsumption_tactic, m, p);
}