mirror of
https://github.com/Z3Prover/z3
synced 2025-06-14 01:46:15 +00:00
add smt lookahead
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
dd4b8b9ff8
commit
d2dcb39c11
11 changed files with 187 additions and 17 deletions
|
@ -32,6 +32,7 @@ z3_add_component(smt
|
||||||
smt_justification.cpp
|
smt_justification.cpp
|
||||||
smt_kernel.cpp
|
smt_kernel.cpp
|
||||||
smt_literal.cpp
|
smt_literal.cpp
|
||||||
|
smt_lookahead.cpp
|
||||||
smt_model_checker.cpp
|
smt_model_checker.cpp
|
||||||
smt_model_finder.cpp
|
smt_model_finder.cpp
|
||||||
smt_model_generator.cpp
|
smt_model_generator.cpp
|
||||||
|
|
|
@ -1784,15 +1784,6 @@ namespace smt {
|
||||||
m_bvar_inc *= INV_ACTIVITY_LIMIT;
|
m_bvar_inc *= INV_ACTIVITY_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* context::next_decision() {
|
|
||||||
bool_var var;
|
|
||||||
lbool phase;
|
|
||||||
m_case_split_queue->next_case_split(var, phase);
|
|
||||||
if (var == null_bool_var) return m_manager.mk_true();
|
|
||||||
m_case_split_queue->unassign_var_eh(var);
|
|
||||||
return bool_var2expr(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Execute next case split, return false if there are no
|
\brief Execute next case split, return false if there are no
|
||||||
more case splits to be performed.
|
more case splits to be performed.
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace smt {
|
||||||
|
|
||||||
class context {
|
class context {
|
||||||
friend class model_generator;
|
friend class model_generator;
|
||||||
|
friend class lookahead;
|
||||||
public:
|
public:
|
||||||
statistics m_stats;
|
statistics m_stats;
|
||||||
|
|
||||||
|
@ -1074,8 +1075,6 @@ namespace smt {
|
||||||
|
|
||||||
enode * get_enode_eq_to(func_decl * f, unsigned num_args, enode * const * args);
|
enode * get_enode_eq_to(func_decl * f, unsigned num_args, enode * const * args);
|
||||||
|
|
||||||
expr* next_decision();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool decide();
|
bool decide();
|
||||||
|
|
||||||
|
|
|
@ -900,6 +900,7 @@ namespace smt {
|
||||||
expr * n = m_b_internalized_stack.back();
|
expr * n = m_b_internalized_stack.back();
|
||||||
unsigned n_id = n->get_id();
|
unsigned n_id = n->get_id();
|
||||||
bool_var v = get_bool_var_of_id(n_id);
|
bool_var v = get_bool_var_of_id(n_id);
|
||||||
|
m_bool_var2expr[v] = nullptr;
|
||||||
TRACE("undo_mk_bool_var", tout << "undo_bool: " << v << "\n" << mk_pp(n, m_manager) << "\n" << "m_bdata.size: " << m_bdata.size()
|
TRACE("undo_mk_bool_var", tout << "undo_bool: " << v << "\n" << mk_pp(n, m_manager) << "\n" << "m_bdata.size: " << m_bdata.size()
|
||||||
<< " m_assignment.size: " << m_assignment.size() << "\n";);
|
<< " m_assignment.size: " << m_assignment.size() << "\n";);
|
||||||
TRACE("mk_var_bug", tout << "undo_mk_bool: " << v << "\n";);
|
TRACE("mk_var_bug", tout << "undo_mk_bool: " << v << "\n";);
|
||||||
|
|
|
@ -18,6 +18,7 @@ Revision History:
|
||||||
--*/
|
--*/
|
||||||
#include "smt/smt_kernel.h"
|
#include "smt/smt_kernel.h"
|
||||||
#include "smt/smt_context.h"
|
#include "smt/smt_context.h"
|
||||||
|
#include "smt/smt_lookahead.h"
|
||||||
#include "ast/ast_smt2_pp.h"
|
#include "ast/ast_smt2_pp.h"
|
||||||
#include "smt/params/smt_params_helper.hpp"
|
#include "smt/params/smt_params_helper.hpp"
|
||||||
|
|
||||||
|
@ -202,8 +203,9 @@ namespace smt {
|
||||||
m_kernel.get_guessed_literals(result);
|
m_kernel.get_guessed_literals(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* next_decision() {
|
expr_ref next_cube() {
|
||||||
return m_kernel.next_decision();
|
lookahead lh(m_kernel);
|
||||||
|
return lh.choose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_statistics(::statistics & st) const {
|
void collect_statistics(::statistics & st) const {
|
||||||
|
@ -379,8 +381,8 @@ namespace smt {
|
||||||
m_imp->get_guessed_literals(result);
|
m_imp->get_guessed_literals(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* kernel::next_decision() {
|
expr_ref kernel::next_cube() {
|
||||||
return m_imp->next_decision();
|
return m_imp->next_cube();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& kernel::display(std::ostream & out) const {
|
std::ostream& kernel::display(std::ostream & out) const {
|
||||||
|
|
|
@ -217,7 +217,7 @@ namespace smt {
|
||||||
/**
|
/**
|
||||||
\brief return the next case split literal.
|
\brief return the next case split literal.
|
||||||
*/
|
*/
|
||||||
expr* next_decision();
|
expr_ref next_cube();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief retrieve depth of variables from decision stack.
|
\brief retrieve depth of variables from decision stack.
|
||||||
|
|
134
src/smt/smt_lookahead.cpp
Normal file
134
src/smt/smt_lookahead.cpp
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2006 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
smt_lookahead.cpp
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Lookahead cuber for SMT
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
nbjorner 2019-05-27.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "ast/ast_smt2_pp.h"
|
||||||
|
#include "smt/smt_lookahead.h"
|
||||||
|
#include "smt/smt_context.h"
|
||||||
|
|
||||||
|
namespace smt {
|
||||||
|
|
||||||
|
lookahead::lookahead(context& ctx):
|
||||||
|
ctx(ctx), m(ctx.get_manager()) {}
|
||||||
|
|
||||||
|
double lookahead::get_score() {
|
||||||
|
double score = 0;
|
||||||
|
for (clause* cp : ctx.m_aux_clauses) {
|
||||||
|
unsigned nf = 0, nu = 0;
|
||||||
|
bool is_taut = false;
|
||||||
|
for (literal lit : *cp) {
|
||||||
|
switch (ctx.get_assignment(lit)) {
|
||||||
|
case l_false:
|
||||||
|
if (ctx.get_assign_level(lit) > 0) {
|
||||||
|
++nf;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case l_true:
|
||||||
|
is_taut = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
++nu;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!is_taut && nf > 0) {
|
||||||
|
score += pow(0.5, nu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct lookahead::compare {
|
||||||
|
context& ctx;
|
||||||
|
compare(context& ctx): ctx(ctx) {}
|
||||||
|
|
||||||
|
bool operator()(bool_var v1, bool_var v2) const {
|
||||||
|
return ctx.get_activity(v1) > ctx.get_activity(v2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
expr_ref lookahead::choose() {
|
||||||
|
ctx.pop_to_base_lvl();
|
||||||
|
unsigned sz = ctx.m_bool_var2expr.size();
|
||||||
|
bool_var best_v = null_bool_var;
|
||||||
|
double best_score = -1;
|
||||||
|
svector<bool_var> vars;
|
||||||
|
for (bool_var v = 0; v < static_cast<bool_var>(sz); ++v) {
|
||||||
|
expr* b = ctx.bool_var2expr(v);
|
||||||
|
if (b && ctx.get_assignment(v) == l_undef) {
|
||||||
|
vars.push_back(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compare comp(ctx);
|
||||||
|
std::sort(vars.begin(), vars.end(), comp);
|
||||||
|
|
||||||
|
unsigned nf = 0, nc = 0, ns = 0, bound = 2000;
|
||||||
|
for (bool_var v : vars) {
|
||||||
|
if (!ctx.bool_var2expr(v)) continue;
|
||||||
|
literal lit(v, false);
|
||||||
|
ctx.push_scope();
|
||||||
|
ctx.assign(lit, b_justification::mk_axiom(), true);
|
||||||
|
ctx.propagate();
|
||||||
|
bool inconsistent = ctx.inconsistent();
|
||||||
|
double score1 = get_score();
|
||||||
|
ctx.pop_scope(1);
|
||||||
|
if (inconsistent) {
|
||||||
|
ctx.assign(~lit, b_justification::mk_axiom(), false);
|
||||||
|
ctx.propagate();
|
||||||
|
++nf;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.push_scope();
|
||||||
|
ctx.assign(~lit, b_justification::mk_axiom(), true);
|
||||||
|
ctx.propagate();
|
||||||
|
inconsistent = ctx.inconsistent();
|
||||||
|
double score2 = get_score();
|
||||||
|
ctx.pop_scope(1);
|
||||||
|
if (inconsistent) {
|
||||||
|
ctx.assign(lit, b_justification::mk_axiom(), false);
|
||||||
|
ctx.propagate();
|
||||||
|
++nf;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double score = score1 + score2 + 1024*score1*score2;
|
||||||
|
if (score > best_score) {
|
||||||
|
best_score = score;
|
||||||
|
best_v = v;
|
||||||
|
bound += ns;
|
||||||
|
ns = 0;
|
||||||
|
}
|
||||||
|
++nc;
|
||||||
|
++ns;
|
||||||
|
if (ns > bound) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr_ref result(m);
|
||||||
|
if (ctx.inconsistent()) {
|
||||||
|
result = m.mk_false();
|
||||||
|
}
|
||||||
|
else if (best_v != null_bool_var) {
|
||||||
|
result = ctx.bool_var2expr(best_v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = m.mk_true();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
40
src/smt/smt_lookahead.h
Normal file
40
src/smt/smt_lookahead.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2006 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
smt_lookahead.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Lookahead solver for SMT
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
nbjorner 2019-05-27.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ast/ast.h"
|
||||||
|
|
||||||
|
namespace smt {
|
||||||
|
class context;
|
||||||
|
|
||||||
|
class lookahead {
|
||||||
|
context& ctx;
|
||||||
|
ast_manager& m;
|
||||||
|
|
||||||
|
struct compare;
|
||||||
|
|
||||||
|
double get_score();
|
||||||
|
|
||||||
|
public:
|
||||||
|
lookahead(context& ctx);
|
||||||
|
|
||||||
|
expr_ref choose();
|
||||||
|
};
|
||||||
|
}
|
|
@ -42,7 +42,7 @@ namespace smt {
|
||||||
expr_ref cube() {
|
expr_ref cube() {
|
||||||
switch (m_round) {
|
switch (m_round) {
|
||||||
case 0:
|
case 0:
|
||||||
m_result = m_solver.m_context.next_decision();
|
m_result = m_solver.m_context.next_cube();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
m_result = m_solver.get_manager().mk_not(m_result);
|
m_result = m_solver.get_manager().mk_not(m_result);
|
||||||
|
|
|
@ -10,6 +10,7 @@ def_module_params('parallel',
|
||||||
('conquer.delay', UINT, 10, 'delay of cubes until applying conquer'),
|
('conquer.delay', UINT, 10, 'delay of cubes until applying conquer'),
|
||||||
('conquer.backtrack_frequency', UINT, 10, 'frequency to apply core minimization during conquer'),
|
('conquer.backtrack_frequency', UINT, 10, 'frequency to apply core minimization during conquer'),
|
||||||
('simplify.exp', DOUBLE, 1, 'restart and inprocess max is multiplied by simplify.exp ^ depth'),
|
('simplify.exp', DOUBLE, 1, 'restart and inprocess max is multiplied by simplify.exp ^ depth'),
|
||||||
|
('simplify.max_conflicts', UINT, UINT_MAX, 'maximal number of conflicts during simplifcation phase'),
|
||||||
('simplify.restart.max', UINT, 5000, 'maximal number of restarts during simplification phase'),
|
('simplify.restart.max', UINT, 5000, 'maximal number of restarts during simplification phase'),
|
||||||
('simplify.inprocess.max', UINT, 2, 'maximal number of inprocessing steps during simplification'),
|
('simplify.inprocess.max', UINT, 2, 'maximal number of inprocessing steps during simplification'),
|
||||||
))
|
))
|
||||||
|
|
|
@ -297,6 +297,7 @@ class parallel_tactic : public tactic {
|
||||||
p.set_uint("restart.max", pp.simplify_restart_max() * mult);
|
p.set_uint("restart.max", pp.simplify_restart_max() * mult);
|
||||||
p.set_bool("lookahead_simplify", true);
|
p.set_bool("lookahead_simplify", true);
|
||||||
p.set_bool("retain_blocked_clauses", retain_blocked);
|
p.set_bool("retain_blocked_clauses", retain_blocked);
|
||||||
|
p.set_uint("max_conflicts", pp.simplify_max_conflicts());
|
||||||
if (m_depth > 1) p.set_uint("bce_delay", 0);
|
if (m_depth > 1) p.set_uint("bce_delay", 0);
|
||||||
get_solver().updt_params(p);
|
get_solver().updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue