mirror of
https://github.com/Z3Prover/z3
synced 2025-06-19 04:13:38 +00:00
adding support for non-extensional arrays in duality
This commit is contained in:
parent
83a774ac79
commit
180f55bbda
7 changed files with 196 additions and 46 deletions
|
@ -31,6 +31,8 @@ using namespace stl_ext;
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
|
class implicant_solver;
|
||||||
|
|
||||||
/* Generic operations on Z3 formulas */
|
/* Generic operations on Z3 formulas */
|
||||||
|
|
||||||
struct Z3User {
|
struct Z3User {
|
||||||
|
@ -104,6 +106,9 @@ namespace Duality {
|
||||||
|
|
||||||
FuncDecl RenumberPred(const FuncDecl &f, int n);
|
FuncDecl RenumberPred(const FuncDecl &f, int n);
|
||||||
|
|
||||||
|
Term ExtractStores(hash_map<ast, Term> &memo, const Term &t, std::vector<expr> &cnstrs, hash_map<ast,expr> &renaming);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void SummarizeRec(hash_set<ast> &memo, std::vector<expr> &lits, int &ops, const Term &t);
|
void SummarizeRec(hash_set<ast> &memo, std::vector<expr> &lits, int &ops, const Term &t);
|
||||||
|
@ -602,6 +607,8 @@ protected:
|
||||||
void FixCurrentState(Edge *root);
|
void FixCurrentState(Edge *root);
|
||||||
|
|
||||||
void FixCurrentStateFull(Edge *edge, const expr &extra);
|
void FixCurrentStateFull(Edge *edge, const expr &extra);
|
||||||
|
|
||||||
|
void FixCurrentStateFull(Edge *edge, const std::vector<expr> &assumps, const hash_map<ast,expr> &renaming);
|
||||||
|
|
||||||
/** Declare a constant in the background theory. */
|
/** Declare a constant in the background theory. */
|
||||||
|
|
||||||
|
@ -944,10 +951,12 @@ protected:
|
||||||
Term UnderapproxFormula(const Term &f, hash_set<ast> &dont_cares);
|
Term UnderapproxFormula(const Term &f, hash_set<ast> &dont_cares);
|
||||||
|
|
||||||
void ImplicantFullRed(hash_map<ast,int> &memo, const Term &f, std::vector<Term> &lits,
|
void ImplicantFullRed(hash_map<ast,int> &memo, const Term &f, std::vector<Term> &lits,
|
||||||
hash_set<ast> &done, hash_set<ast> &dont_cares);
|
hash_set<ast> &done, hash_set<ast> &dont_cares, bool extensional = true);
|
||||||
|
|
||||||
Term UnderapproxFullFormula(const Term &f, hash_set<ast> &dont_cares);
|
public:
|
||||||
|
Term UnderapproxFullFormula(const Term &f, bool extensional = true);
|
||||||
|
|
||||||
|
protected:
|
||||||
Term ToRuleRec(Edge *e, hash_map<ast,Term> &memo, const Term &t, std::vector<expr> &quants);
|
Term ToRuleRec(Edge *e, hash_map<ast,Term> &memo, const Term &t, std::vector<expr> &quants);
|
||||||
|
|
||||||
hash_map<ast,Term> resolve_ite_memo;
|
hash_map<ast,Term> resolve_ite_memo;
|
||||||
|
@ -988,6 +997,8 @@ protected:
|
||||||
|
|
||||||
void AddEdgeToSolver(Edge *edge);
|
void AddEdgeToSolver(Edge *edge);
|
||||||
|
|
||||||
|
void AddEdgeToSolver(implicant_solver &aux_solver, Edge *edge);
|
||||||
|
|
||||||
void AddToProofCore(hash_set<ast> &core);
|
void AddToProofCore(hash_set<ast> &core);
|
||||||
|
|
||||||
void GetGroundLitsUnderQuants(hash_set<ast> *memo, const Term &f, std::vector<Term> &res, int under);
|
void GetGroundLitsUnderQuants(hash_set<ast> *memo, const Term &f, std::vector<Term> &res, int under);
|
||||||
|
|
|
@ -410,6 +410,33 @@ namespace Duality {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Z3User::Term Z3User::ExtractStores(hash_map<ast, Term> &memo, const Term &t, std::vector<expr> &cnstrs, hash_map<ast,expr> &renaming)
|
||||||
|
{
|
||||||
|
std::pair<ast,Term> foo(t,expr(ctx));
|
||||||
|
std::pair<hash_map<ast,Term>::iterator, bool> bar = memo.insert(foo);
|
||||||
|
Term &res = bar.first->second;
|
||||||
|
if(!bar.second) return res;
|
||||||
|
if (t.is_app()) {
|
||||||
|
func_decl f = t.decl();
|
||||||
|
std::vector<Term> args;
|
||||||
|
int nargs = t.num_args();
|
||||||
|
for(int i = 0; i < nargs; i++)
|
||||||
|
args.push_back(ExtractStores(memo, t.arg(i),cnstrs,renaming));
|
||||||
|
res = f(args.size(),&args[0]);
|
||||||
|
if(f.get_decl_kind() == Store){
|
||||||
|
func_decl fresh = ctx.fresh_func_decl("@arr", res.get_sort());
|
||||||
|
expr y = fresh();
|
||||||
|
expr equ = ctx.make(Equal,y,res);
|
||||||
|
cnstrs.push_back(equ);
|
||||||
|
renaming[y] = res;
|
||||||
|
res = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else res = t;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Z3User::IsLiteral(const expr &lit, expr &atom, expr &val){
|
bool Z3User::IsLiteral(const expr &lit, expr &atom, expr &val){
|
||||||
if(!(lit.is_quantifier() && IsClosedFormula(lit))){
|
if(!(lit.is_quantifier() && IsClosedFormula(lit))){
|
||||||
if(!lit.is_app())
|
if(!lit.is_app())
|
||||||
|
@ -1851,7 +1878,7 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPFP::ImplicantFullRed(hash_map<ast,int> &memo, const Term &f, std::vector<Term> &lits,
|
void RPFP::ImplicantFullRed(hash_map<ast,int> &memo, const Term &f, std::vector<Term> &lits,
|
||||||
hash_set<ast> &done, hash_set<ast> &dont_cares){
|
hash_set<ast> &done, hash_set<ast> &dont_cares, bool extensional){
|
||||||
if(done.find(f) != done.end())
|
if(done.find(f) != done.end())
|
||||||
return; /* already processed */
|
return; /* already processed */
|
||||||
if(f.is_app()){
|
if(f.is_app()){
|
||||||
|
@ -1859,7 +1886,7 @@ namespace Duality {
|
||||||
decl_kind k = f.decl().get_decl_kind();
|
decl_kind k = f.decl().get_decl_kind();
|
||||||
if(k == Implies || k == Iff || k == And || k == Or || k == Not){
|
if(k == Implies || k == Iff || k == And || k == Or || k == Not){
|
||||||
for(int i = 0; i < nargs; i++)
|
for(int i = 0; i < nargs; i++)
|
||||||
ImplicantFullRed(memo,f.arg(i),lits,done,dont_cares);
|
ImplicantFullRed(memo,f.arg(i),lits,done,dont_cares, extensional);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1867,6 +1894,15 @@ namespace Duality {
|
||||||
if(dont_cares.find(f) == dont_cares.end()){
|
if(dont_cares.find(f) == dont_cares.end()){
|
||||||
int b = SubtermTruth(memo,f);
|
int b = SubtermTruth(memo,f);
|
||||||
if(b != 0 && b != 1) goto done;
|
if(b != 0 && b != 1) goto done;
|
||||||
|
if(f.is_app() && f.decl().get_decl_kind() == Equal && f.arg(0).is_array()){
|
||||||
|
if(b == 1 && !extensional){
|
||||||
|
expr x = dualModel.eval(f.arg(0)); expr y = dualModel.eval(f.arg(1));
|
||||||
|
if(!eq(x,y))
|
||||||
|
b = 0;
|
||||||
|
}
|
||||||
|
if(b == 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
expr bv = (b==1) ? f : !f;
|
expr bv = (b==1) ? f : !f;
|
||||||
lits.push_back(bv);
|
lits.push_back(bv);
|
||||||
}
|
}
|
||||||
|
@ -1988,12 +2024,16 @@ namespace Duality {
|
||||||
return conjoin(lits);
|
return conjoin(lits);
|
||||||
}
|
}
|
||||||
|
|
||||||
RPFP::Term RPFP::UnderapproxFullFormula(const Term &f, hash_set<ast> &dont_cares){
|
RPFP::Term RPFP::UnderapproxFullFormula(const Term &f, bool extensional){
|
||||||
|
hash_set<ast> dont_cares;
|
||||||
|
resolve_ite_memo.clear();
|
||||||
|
timer_start("UnderapproxFormula");
|
||||||
/* first compute truth values of subterms */
|
/* first compute truth values of subterms */
|
||||||
hash_map<ast,int> memo;
|
hash_map<ast,int> memo;
|
||||||
hash_set<ast> done;
|
hash_set<ast> done;
|
||||||
std::vector<Term> lits;
|
std::vector<Term> lits;
|
||||||
ImplicantFullRed(memo,f,lits,done,dont_cares);
|
ImplicantFullRed(memo,f,lits,done,dont_cares, extensional);
|
||||||
|
timer_stop("UnderapproxFormula");
|
||||||
/* return conjunction of literals */
|
/* return conjunction of literals */
|
||||||
return conjoin(lits);
|
return conjoin(lits);
|
||||||
}
|
}
|
||||||
|
@ -2538,22 +2578,6 @@ namespace Duality {
|
||||||
ConstrainEdgeLocalized(edge,eu);
|
ConstrainEdgeLocalized(edge,eu);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RPFP::FixCurrentStateFull(Edge *edge, const expr &extra){
|
|
||||||
hash_set<ast> dont_cares;
|
|
||||||
resolve_ite_memo.clear();
|
|
||||||
timer_start("UnderapproxFormula");
|
|
||||||
Term dual = edge->dual.null() ? ctx.bool_val(true) : edge->dual;
|
|
||||||
for(unsigned i = 0; i < edge->constraints.size(); i++)
|
|
||||||
dual = dual && edge->constraints[i];
|
|
||||||
// dual = dual && extra;
|
|
||||||
Term eu = UnderapproxFullFormula(dual,dont_cares);
|
|
||||||
timer_stop("UnderapproxFormula");
|
|
||||||
ConstrainEdgeLocalized(edge,eu);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void RPFP::GetGroundLitsUnderQuants(hash_set<ast> *memo, const Term &f, std::vector<Term> &res, int under){
|
void RPFP::GetGroundLitsUnderQuants(hash_set<ast> *memo, const Term &f, std::vector<Term> &res, int under){
|
||||||
if(memo[under].find(f) != memo[under].end())
|
if(memo[under].find(f) != memo[under].end())
|
||||||
return;
|
return;
|
||||||
|
@ -2836,7 +2860,91 @@ namespace Duality {
|
||||||
return ctx.make(And,lits);
|
return ctx.make(And,lits);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set up edge constraint in aux solver
|
|
||||||
|
/* This is a wrapper for a solver that is intended to compute
|
||||||
|
implicants from models. It works around a problem in Z3 with
|
||||||
|
models in the non-extensional array theory. It does this by
|
||||||
|
naming all of the store terms in a formula. That is, (store ...)
|
||||||
|
is replaced by "name" with an added constraint name = (store
|
||||||
|
...). This allows us to determine from the model whether an array
|
||||||
|
equality is true or false (it is false if the two sides are
|
||||||
|
mapped to different function symbols, even if they have the same
|
||||||
|
contents).
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct implicant_solver {
|
||||||
|
RPFP *owner;
|
||||||
|
solver &aux_solver;
|
||||||
|
std::vector<expr> assumps, namings;
|
||||||
|
std::vector<int> assump_stack, naming_stack;
|
||||||
|
hash_map<ast,expr> renaming, renaming_memo;
|
||||||
|
|
||||||
|
void add(const expr &e){
|
||||||
|
expr t = e;
|
||||||
|
if(!aux_solver.extensional_array_theory()){
|
||||||
|
unsigned i = namings.size();
|
||||||
|
t = owner->ExtractStores(renaming_memo,t,namings,renaming);
|
||||||
|
for(; i < namings.size(); i++)
|
||||||
|
aux_solver.add(namings[i]);
|
||||||
|
}
|
||||||
|
assumps.push_back(t);
|
||||||
|
aux_solver.add(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push() {
|
||||||
|
assump_stack.push_back(assumps.size());
|
||||||
|
naming_stack.push_back(namings.size());
|
||||||
|
aux_solver.push();
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we pop the solver, we have to re-add any namings that were lost
|
||||||
|
|
||||||
|
void pop(int n) {
|
||||||
|
aux_solver.pop(n);
|
||||||
|
int new_assumps = assump_stack[assump_stack.size()-n];
|
||||||
|
int new_namings = naming_stack[naming_stack.size()-n];
|
||||||
|
for(unsigned i = new_namings; i < namings.size(); i++)
|
||||||
|
aux_solver.add(namings[i]);
|
||||||
|
assumps.resize(new_assumps);
|
||||||
|
namings.resize(new_namings);
|
||||||
|
assump_stack.resize(assump_stack.size()-1);
|
||||||
|
naming_stack.resize(naming_stack.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_result check() {
|
||||||
|
return aux_solver.check();
|
||||||
|
}
|
||||||
|
|
||||||
|
model get_model() {
|
||||||
|
return aux_solver.get_model();
|
||||||
|
}
|
||||||
|
|
||||||
|
expr get_implicant() {
|
||||||
|
owner->dualModel = aux_solver.get_model();
|
||||||
|
expr dual = owner->ctx.make(And,assumps);
|
||||||
|
bool ext = aux_solver.extensional_array_theory();
|
||||||
|
expr eu = owner->UnderapproxFullFormula(dual,ext);
|
||||||
|
// if we renamed store terms, we have to undo
|
||||||
|
if(!ext)
|
||||||
|
eu = owner->SubstRec(renaming,eu);
|
||||||
|
return eu;
|
||||||
|
}
|
||||||
|
|
||||||
|
implicant_solver(RPFP *_owner, solver &_aux_solver)
|
||||||
|
: owner(_owner), aux_solver(_aux_solver)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// set up edge constraint in aux solver
|
||||||
|
void RPFP::AddEdgeToSolver(implicant_solver &aux_solver, Edge *edge){
|
||||||
|
if(!edge->dual.null())
|
||||||
|
aux_solver.add(edge->dual);
|
||||||
|
for(unsigned i = 0; i < edge->constraints.size(); i++){
|
||||||
|
expr tl = edge->constraints[i];
|
||||||
|
aux_solver.add(tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RPFP::AddEdgeToSolver(Edge *edge){
|
void RPFP::AddEdgeToSolver(Edge *edge){
|
||||||
if(!edge->dual.null())
|
if(!edge->dual.null())
|
||||||
aux_solver.add(edge->dual);
|
aux_solver.add(edge->dual);
|
||||||
|
@ -2853,28 +2961,29 @@ namespace Duality {
|
||||||
const std::vector<expr> &theory = ls->get_axioms();
|
const std::vector<expr> &theory = ls->get_axioms();
|
||||||
for(unsigned i = 0; i < theory.size(); i++)
|
for(unsigned i = 0; i < theory.size(); i++)
|
||||||
axioms_needed.insert(theory[i]);
|
axioms_needed.insert(theory[i]);
|
||||||
aux_solver.push();
|
implicant_solver is(this,aux_solver);
|
||||||
AddEdgeToSolver(node->Outgoing);
|
is.push();
|
||||||
|
AddEdgeToSolver(is,node->Outgoing);
|
||||||
node->Annotation.SetEmpty();
|
node->Annotation.SetEmpty();
|
||||||
hash_set<ast> *core = new hash_set<ast>;
|
hash_set<ast> *core = new hash_set<ast>;
|
||||||
core->insert(node->Outgoing->dual);
|
core->insert(node->Outgoing->dual);
|
||||||
while(1){
|
while(1){
|
||||||
aux_solver.push();
|
is.push();
|
||||||
expr annot = !GetAnnotation(node);
|
expr annot = !GetAnnotation(node);
|
||||||
aux_solver.add(annot);
|
is.add(annot);
|
||||||
if(aux_solver.check() == unsat){
|
if(is.check() == unsat){
|
||||||
aux_solver.pop(1);
|
is.pop(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dualModel = aux_solver.get_model();
|
is.pop(1);
|
||||||
aux_solver.pop(1);
|
|
||||||
Push();
|
Push();
|
||||||
FixCurrentStateFull(node->Outgoing,annot);
|
ConstrainEdgeLocalized(node->Outgoing,is.get_implicant());
|
||||||
ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node));
|
ConstrainEdgeLocalized(node->Outgoing,!GetAnnotation(node)); //TODO: need this?
|
||||||
check_result foo = Check(root);
|
check_result foo = Check(root);
|
||||||
if(foo != unsat)
|
if(foo != unsat){
|
||||||
|
slvr().print("should_be_unsat.smt2");
|
||||||
throw "should be unsat";
|
throw "should be unsat";
|
||||||
|
}
|
||||||
std::vector<expr> assumps, axioms_to_add;
|
std::vector<expr> assumps, axioms_to_add;
|
||||||
slvr().get_proof().get_assumptions(assumps);
|
slvr().get_proof().get_assumptions(assumps);
|
||||||
for(unsigned i = 0; i < assumps.size(); i++){
|
for(unsigned i = 0; i < assumps.size(); i++){
|
||||||
|
@ -2890,7 +2999,7 @@ namespace Duality {
|
||||||
|
|
||||||
{
|
{
|
||||||
expr itp = GetAnnotation(node);
|
expr itp = GetAnnotation(node);
|
||||||
dualModel = aux_solver.get_model();
|
dualModel = is.get_model(); // TODO: what does this mean?
|
||||||
std::vector<expr> case_lits;
|
std::vector<expr> case_lits;
|
||||||
itp = StrengthenFormulaByCaseSplitting(itp, case_lits);
|
itp = StrengthenFormulaByCaseSplitting(itp, case_lits);
|
||||||
SetAnnotation(node,itp);
|
SetAnnotation(node,itp);
|
||||||
|
@ -2898,14 +3007,14 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned i = 0; i < axioms_to_add.size(); i++)
|
for(unsigned i = 0; i < axioms_to_add.size(); i++)
|
||||||
aux_solver.add(axioms_to_add[i]);
|
is.add(axioms_to_add[i]);
|
||||||
|
|
||||||
if(node->Annotation.IsEmpty()){
|
if(node->Annotation.IsEmpty()){
|
||||||
if(!axioms_added){
|
if(!axioms_added){
|
||||||
// add the axioms in the off chance they are useful
|
// add the axioms in the off chance they are useful
|
||||||
const std::vector<expr> &theory = ls->get_axioms();
|
const std::vector<expr> &theory = ls->get_axioms();
|
||||||
for(unsigned i = 0; i < theory.size(); i++)
|
for(unsigned i = 0; i < theory.size(); i++)
|
||||||
aux_solver.add(theory[i]);
|
is.add(theory[i]);
|
||||||
axioms_added = true;
|
axioms_added = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2923,7 +3032,7 @@ namespace Duality {
|
||||||
if(proof_core)
|
if(proof_core)
|
||||||
delete proof_core; // shouldn't happen
|
delete proof_core; // shouldn't happen
|
||||||
proof_core = core;
|
proof_core = core;
|
||||||
aux_solver.pop(1);
|
is.pop(1);
|
||||||
timer_stop("InterpolateByCases");
|
timer_stop("InterpolateByCases");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,7 @@ namespace Duality {
|
||||||
Report = false;
|
Report = false;
|
||||||
StratifiedInlining = false;
|
StratifiedInlining = false;
|
||||||
RecursionBound = -1;
|
RecursionBound = -1;
|
||||||
|
BatchExpand = false;
|
||||||
{
|
{
|
||||||
scoped_no_proof no_proofs_please(ctx.m());
|
scoped_no_proof no_proofs_please(ctx.m());
|
||||||
#ifdef USE_RPFP_CLONE
|
#ifdef USE_RPFP_CLONE
|
||||||
|
@ -365,6 +366,7 @@ namespace Duality {
|
||||||
bool Report; // spew on stdout
|
bool Report; // spew on stdout
|
||||||
bool StratifiedInlining; // Do stratified inlining as preprocessing step
|
bool StratifiedInlining; // Do stratified inlining as preprocessing step
|
||||||
int RecursionBound; // Recursion bound for bounded verification
|
int RecursionBound; // Recursion bound for bounded verification
|
||||||
|
bool BatchExpand;
|
||||||
|
|
||||||
bool SetBoolOption(bool &opt, const std::string &value){
|
bool SetBoolOption(bool &opt, const std::string &value){
|
||||||
if(value == "0") {
|
if(value == "0") {
|
||||||
|
@ -403,6 +405,9 @@ namespace Duality {
|
||||||
if(option == "stratified_inlining"){
|
if(option == "stratified_inlining"){
|
||||||
return SetBoolOption(StratifiedInlining,value);
|
return SetBoolOption(StratifiedInlining,value);
|
||||||
}
|
}
|
||||||
|
if(option == "batch_expand"){
|
||||||
|
return SetBoolOption(BatchExpand,value);
|
||||||
|
}
|
||||||
if(option == "recursion_bound"){
|
if(option == "recursion_bound"){
|
||||||
return SetIntOption(RecursionBound,value);
|
return SetIntOption(RecursionBound,value);
|
||||||
}
|
}
|
||||||
|
@ -2016,7 +2021,7 @@ namespace Duality {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
was_sat = true;
|
was_sat = true;
|
||||||
tree->Push();
|
tree->Push();
|
||||||
std::vector<Node *> &expansions = stack.back().expansions;
|
std::vector<Node *> &expansions = stack.back().expansions;
|
||||||
#ifndef NO_DECISIONS
|
#ifndef NO_DECISIONS
|
||||||
for(unsigned i = 0; i < expansions.size(); i++){
|
for(unsigned i = 0; i < expansions.size(); i++){
|
||||||
|
@ -2027,11 +2032,16 @@ namespace Duality {
|
||||||
if(tree->slvr().check() == unsat)
|
if(tree->slvr().check() == unsat)
|
||||||
throw "help!";
|
throw "help!";
|
||||||
#endif
|
#endif
|
||||||
stack.push_back(stack_entry());
|
int expand_max = 1;
|
||||||
stack.back().level = tree->slvr().get_scope_level();
|
if(0&&duality->BatchExpand){
|
||||||
if(ExpandSomeNodes(false,1)){
|
int thing = stack.size() * 0.1;
|
||||||
continue;
|
expand_max = std::max(1,thing);
|
||||||
|
if(expand_max > 1)
|
||||||
|
std::cout << "foo!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ExpandSomeNodes(false,expand_max))
|
||||||
|
continue;
|
||||||
while(stack.size() > 1){
|
while(stack.size() > 1){
|
||||||
tree->Pop(1);
|
tree->Pop(1);
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
|
@ -2090,6 +2100,8 @@ namespace Duality {
|
||||||
std::list<Node *> updated_nodes;
|
std::list<Node *> updated_nodes;
|
||||||
|
|
||||||
virtual void ExpandNode(RPFP::Node *p){
|
virtual void ExpandNode(RPFP::Node *p){
|
||||||
|
stack.push_back(stack_entry());
|
||||||
|
stack.back().level = tree->slvr().get_scope_level();
|
||||||
stack.back().expansions.push_back(p);
|
stack.back().expansions.push_back(p);
|
||||||
DerivationTree::ExpandNode(p);
|
DerivationTree::ExpandNode(p);
|
||||||
std::vector<Node *> &new_nodes = p->Outgoing->Children;
|
std::vector<Node *> &new_nodes = p->Outgoing->Children;
|
||||||
|
|
|
@ -37,7 +37,7 @@ Revision History:
|
||||||
|
|
||||||
namespace Duality {
|
namespace Duality {
|
||||||
|
|
||||||
solver::solver(Duality::context& c, bool extensional, bool models) : object(c), the_model(c) {
|
solver::solver(Duality::context& c, bool _extensional, bool models) : object(c), the_model(c) {
|
||||||
params_ref p;
|
params_ref p;
|
||||||
p.set_bool("proof", true); // this is currently useless
|
p.set_bool("proof", true); // this is currently useless
|
||||||
if(models)
|
if(models)
|
||||||
|
@ -47,7 +47,8 @@ namespace Duality {
|
||||||
p.set_bool("mbqi",mbqi); // just to test
|
p.set_bool("mbqi",mbqi); // just to test
|
||||||
p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants
|
p.set_str("mbqi.id","itp"); // use mbqi for quantifiers in interpolants
|
||||||
p.set_uint("mbqi.max_iterations",1); // use mbqi for quantifiers in interpolants
|
p.set_uint("mbqi.max_iterations",1); // use mbqi for quantifiers in interpolants
|
||||||
if(true || extensional)
|
extensional = mbqi && (true || _extensional);
|
||||||
|
if(extensional)
|
||||||
p.set_bool("array.extensional",true);
|
p.set_bool("array.extensional",true);
|
||||||
scoped_ptr<solver_factory> sf = mk_smt_solver_factory();
|
scoped_ptr<solver_factory> sf = mk_smt_solver_factory();
|
||||||
m_solver = (*sf)(m(), p, true, true, true, ::symbol::null);
|
m_solver = (*sf)(m(), p, true, true, true, ::symbol::null);
|
||||||
|
@ -657,6 +658,18 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
||||||
pp.display_smt2(std::cout, m_solver->get_assertion(n-1));
|
pp.display_smt2(std::cout, m_solver->get_assertion(n-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void solver::print(const char *filename) {
|
||||||
|
std::ofstream f(filename);
|
||||||
|
unsigned n = m_solver->get_num_assertions();
|
||||||
|
if(!n)
|
||||||
|
return;
|
||||||
|
ast_smt_pp pp(m());
|
||||||
|
for (unsigned i = 0; i < n-1; ++i)
|
||||||
|
pp.add_assumption(m_solver->get_assertion(i));
|
||||||
|
pp.display_smt2(f, m_solver->get_assertion(n-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void solver::show_assertion_ids() {
|
void solver::show_assertion_ids() {
|
||||||
#if 0
|
#if 0
|
||||||
unsigned n = m_solver->get_num_assertions();
|
unsigned n = m_solver->get_num_assertions();
|
||||||
|
|
|
@ -819,6 +819,7 @@ namespace Duality {
|
||||||
model the_model;
|
model the_model;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
proof_gen_mode m_mode;
|
proof_gen_mode m_mode;
|
||||||
|
bool extensional;
|
||||||
public:
|
public:
|
||||||
solver(context & c, bool extensional = false, bool models = true);
|
solver(context & c, bool extensional = false, bool models = true);
|
||||||
solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;}
|
solver(context & c, ::solver *s):object(c),the_model(c) { m_solver = s; canceled = false;}
|
||||||
|
@ -922,6 +923,7 @@ namespace Duality {
|
||||||
unsigned get_scope_level(){ scoped_proof_mode spm(m(),m_mode); return m_solver->get_scope_level();}
|
unsigned get_scope_level(){ scoped_proof_mode spm(m(),m_mode); return m_solver->get_scope_level();}
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
|
void print(const char *filename);
|
||||||
void show_assertion_ids();
|
void show_assertion_ids();
|
||||||
|
|
||||||
proof get_proof(){
|
proof get_proof(){
|
||||||
|
@ -929,6 +931,7 @@ namespace Duality {
|
||||||
return proof(ctx(),m_solver->get_proof());
|
return proof(ctx(),m_solver->get_proof());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool extensional_array_theory() {return extensional;}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -75,6 +75,7 @@ def_module_params('fixedpoint',
|
||||||
('recursion_bound', UINT, UINT_MAX, 'DUALITY: Recursion bound for stratified inlining'),
|
('recursion_bound', UINT, UINT_MAX, 'DUALITY: Recursion bound for stratified inlining'),
|
||||||
('profile', BOOL, False, 'DUALITY: profile run time'),
|
('profile', BOOL, False, 'DUALITY: profile run time'),
|
||||||
('mbqi', BOOL, True, 'DUALITY: use model-based quantifier instantion'),
|
('mbqi', BOOL, True, 'DUALITY: use model-based quantifier instantion'),
|
||||||
|
('batch_expand', BOOL, False, 'DUALITY: use batch expansion'),
|
||||||
('dump_aig', SYMBOL, '', 'Dump clauses in AIG text format (AAG) to the given file name'),
|
('dump_aig', SYMBOL, '', 'Dump clauses in AIG text format (AAG) to the given file name'),
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,7 @@ lbool dl_interface::query(::expr * query) {
|
||||||
rs->SetOption("feasible_edges",m_ctx.get_params().feasible_edges() ? "1" : "0");
|
rs->SetOption("feasible_edges",m_ctx.get_params().feasible_edges() ? "1" : "0");
|
||||||
rs->SetOption("use_underapprox",m_ctx.get_params().use_underapprox() ? "1" : "0");
|
rs->SetOption("use_underapprox",m_ctx.get_params().use_underapprox() ? "1" : "0");
|
||||||
rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0");
|
rs->SetOption("stratified_inlining",m_ctx.get_params().stratified_inlining() ? "1" : "0");
|
||||||
|
rs->SetOption("batch_expand",m_ctx.get_params().batch_expand() ? "1" : "0");
|
||||||
unsigned rb = m_ctx.get_params().recursion_bound();
|
unsigned rb = m_ctx.get_params().recursion_bound();
|
||||||
if(rb != UINT_MAX){
|
if(rb != UINT_MAX){
|
||||||
std::ostringstream os; os << rb;
|
std::ostringstream os; os << rb;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue