mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 03:45:51 +00:00
working on duality
This commit is contained in:
parent
a93f8b04e5
commit
a3462ba6aa
11 changed files with 415 additions and 121 deletions
|
@ -142,6 +142,7 @@ namespace Duality {
|
|||
context *ctx; /** Z3 context for formulas */
|
||||
solver *slvr; /** Z3 solver */
|
||||
bool need_goals; /** Can the solver use the goal tree to optimize interpolants? */
|
||||
solver aux_solver; /** For temporary use -- don't leave assertions here. */
|
||||
|
||||
/** Tree interpolation. This method assumes the formulas in TermTree
|
||||
"assumptions" are currently asserted in the solver. The return
|
||||
|
@ -178,6 +179,8 @@ namespace Duality {
|
|||
/** Cancel, throw Canceled object if possible. */
|
||||
virtual void cancel(){ }
|
||||
|
||||
LogicSolver(context &c) : aux_solver(c){}
|
||||
|
||||
virtual ~LogicSolver(){}
|
||||
};
|
||||
|
||||
|
@ -215,7 +218,7 @@ namespace Duality {
|
|||
}
|
||||
#endif
|
||||
|
||||
iZ3LogicSolver(context &c){
|
||||
iZ3LogicSolver(context &c) : LogicSolver(c) {
|
||||
ctx = ictx = &c;
|
||||
slvr = islvr = new interpolating_solver(*ictx);
|
||||
need_goals = false;
|
||||
|
@ -287,9 +290,9 @@ namespace Duality {
|
|||
literals dualLabels;
|
||||
std::list<stack_entry> stack;
|
||||
std::vector<Term> axioms; // only saved here for printing purposes
|
||||
solver aux_solver;
|
||||
|
||||
|
||||
solver &aux_solver;
|
||||
hash_set<ast> *proof_core;
|
||||
|
||||
public:
|
||||
|
||||
/** Construct an RPFP graph with a given interpolating prover context. It is allowed to
|
||||
|
@ -299,13 +302,14 @@ namespace Duality {
|
|||
inherit the axioms.
|
||||
*/
|
||||
|
||||
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx), *(_ls->slvr)), dualModel(*(_ls->ctx)), aux_solver(*(_ls->ctx))
|
||||
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx), *(_ls->slvr)), dualModel(*(_ls->ctx)), aux_solver(_ls->aux_solver)
|
||||
{
|
||||
ls = _ls;
|
||||
nodeCount = 0;
|
||||
edgeCount = 0;
|
||||
stack.push_back(stack_entry());
|
||||
HornClauses = false;
|
||||
proof_core = 0;
|
||||
}
|
||||
|
||||
~RPFP();
|
||||
|
@ -606,9 +610,13 @@ namespace Duality {
|
|||
|
||||
lbool Solve(Node *root, int persist);
|
||||
|
||||
/** Same as Solve, but annotates only a single node. */
|
||||
|
||||
lbool SolveSingleNode(Node *root, Node *node);
|
||||
|
||||
/** Get the constraint tree (but don't solve it) */
|
||||
|
||||
TermTree *GetConstraintTree(Node *root);
|
||||
TermTree *GetConstraintTree(Node *root, Node *skip_descendant = 0);
|
||||
|
||||
/** Dispose of the dual model (counterexample) if there is one. */
|
||||
|
||||
|
@ -678,6 +686,12 @@ namespace Duality {
|
|||
/** Pop a scope (see Push). Note, you cannot pop axioms. */
|
||||
|
||||
void Pop(int num_scopes);
|
||||
|
||||
/** Return true if the given edge is used in the proof of unsat.
|
||||
Can be called only after Solve or Check returns an unsat result. */
|
||||
|
||||
bool EdgeUsedInProof(Edge *edge);
|
||||
|
||||
|
||||
/** Convert a collection of clauses to Nodes and Edges in the RPFP.
|
||||
|
||||
|
@ -762,8 +776,19 @@ namespace Duality {
|
|||
|
||||
// int GetLabelsRec(hash_map<ast,int> *memo, const Term &f, std::vector<symbol> &labels, bool labpos);
|
||||
|
||||
/** Compute and save the proof core for future calls to
|
||||
EdgeUsedInProof. You only need to call this if you will pop
|
||||
the solver before calling EdgeUsedInProof.
|
||||
*/
|
||||
void ComputeProofCore();
|
||||
|
||||
private:
|
||||
|
||||
void ClearProofCore(){
|
||||
if(proof_core)
|
||||
delete proof_core;
|
||||
proof_core = 0;
|
||||
}
|
||||
|
||||
Term SuffixVariable(const Term &t, int n);
|
||||
|
||||
|
@ -779,10 +804,14 @@ namespace Duality {
|
|||
|
||||
Term ReducedDualEdge(Edge *e);
|
||||
|
||||
TermTree *ToTermTree(Node *root);
|
||||
TermTree *ToTermTree(Node *root, Node *skip_descendant = 0);
|
||||
|
||||
TermTree *ToGoalTree(Node *root);
|
||||
|
||||
void CollapseTermTreeRec(TermTree *root, TermTree *node);
|
||||
|
||||
TermTree *CollapseTermTree(TermTree *node);
|
||||
|
||||
void DecodeTree(Node *root, TermTree *interp, int persist);
|
||||
|
||||
Term GetUpperBound(Node *n);
|
||||
|
|
|
@ -185,6 +185,7 @@ namespace Duality {
|
|||
return clone_quantifier(t,new_body);
|
||||
}
|
||||
|
||||
|
||||
RPFP::Term RPFP::LocalizeRec(Edge *e, hash_map<ast,Term> &memo, const Term &t)
|
||||
{
|
||||
std::pair<ast,Term> foo(t,expr(ctx));
|
||||
|
@ -274,13 +275,15 @@ namespace Duality {
|
|||
return implies(b, Localize(e, e->F.Formula));
|
||||
}
|
||||
|
||||
TermTree *RPFP::ToTermTree(Node *root)
|
||||
TermTree *RPFP::ToTermTree(Node *root, Node *skip_descendant)
|
||||
{
|
||||
if(skip_descendant && root == skip_descendant)
|
||||
return new TermTree(ctx.bool_val(true));
|
||||
Edge *e = root->Outgoing;
|
||||
if(!e) return new TermTree(ctx.bool_val(true), std::vector<TermTree *>());
|
||||
std::vector<TermTree *> children(e->Children.size());
|
||||
for(unsigned i = 0; i < children.size(); i++)
|
||||
children[i] = ToTermTree(e->Children[i]);
|
||||
children[i] = ToTermTree(e->Children[i],skip_descendant);
|
||||
// Term top = ReducedDualEdge(e);
|
||||
Term top = e->dual.null() ? ctx.bool_val(true) : e->dual;
|
||||
TermTree *res = new TermTree(top, children);
|
||||
|
@ -623,6 +626,7 @@ namespace Duality {
|
|||
TermTree *goals = NULL;
|
||||
if(ls->need_goals)
|
||||
goals = GetGoalTree(root);
|
||||
ClearProofCore();
|
||||
|
||||
// if (dualModel != null) dualModel.Dispose();
|
||||
// if (dualLabels != null) dualLabels.Dispose();
|
||||
|
@ -644,11 +648,54 @@ namespace Duality {
|
|||
return res;
|
||||
}
|
||||
|
||||
void RPFP::CollapseTermTreeRec(TermTree *root, TermTree *node){
|
||||
root->addTerm(node->getTerm());
|
||||
std::vector<Term> &cnsts = node->getTerms();
|
||||
for(unsigned i = 0; i < cnsts.size(); i++)
|
||||
root->addTerm(cnsts[i]);
|
||||
std::vector<TermTree *> &chs = node->getChildren();
|
||||
for(unsigned i = 0; i < chs.size(); i++){
|
||||
CollapseTermTreeRec(root,chs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TermTree *RPFP::CollapseTermTree(TermTree *node){
|
||||
std::vector<TermTree *> &chs = node->getChildren();
|
||||
for(unsigned i = 0; i < chs.size(); i++)
|
||||
CollapseTermTreeRec(node,chs[i]);
|
||||
for(unsigned i = 0; i < chs.size(); i++)
|
||||
delete chs[i];
|
||||
chs.clear();
|
||||
return node;
|
||||
}
|
||||
|
||||
lbool RPFP::SolveSingleNode(Node *root, Node *node)
|
||||
{
|
||||
timer_start("Solve");
|
||||
TermTree *tree = CollapseTermTree(GetConstraintTree(root,node));
|
||||
tree->getChildren().push_back(CollapseTermTree(ToTermTree(node)));
|
||||
TermTree *interpolant = NULL;
|
||||
ClearProofCore();
|
||||
|
||||
timer_start("interpolate_tree");
|
||||
lbool res = ls->interpolate_tree(tree, interpolant, dualModel,0,true);
|
||||
timer_stop("interpolate_tree");
|
||||
if (res == l_false)
|
||||
{
|
||||
DecodeTree(node, interpolant->getChildren()[0], 0);
|
||||
delete interpolant;
|
||||
}
|
||||
|
||||
delete tree;
|
||||
timer_stop("Solve");
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Get the constraint tree (but don't solve it) */
|
||||
|
||||
TermTree *RPFP::GetConstraintTree(Node *root)
|
||||
TermTree *RPFP::GetConstraintTree(Node *root, Node *skip_descendant)
|
||||
{
|
||||
return AddUpperBound(root, ToTermTree(root));
|
||||
return AddUpperBound(root, ToTermTree(root,skip_descendant));
|
||||
}
|
||||
|
||||
/** Dispose of the dual model (counterexample) if there is one. */
|
||||
|
@ -677,6 +724,7 @@ namespace Duality {
|
|||
|
||||
check_result RPFP::Check(Node *root, std::vector<Node *> underapproxes, std::vector<Node *> *underapprox_core )
|
||||
{
|
||||
ClearProofCore();
|
||||
// if (dualModel != null) dualModel.Dispose();
|
||||
check_result res;
|
||||
if(!underapproxes.size())
|
||||
|
@ -713,6 +761,7 @@ namespace Duality {
|
|||
|
||||
check_result RPFP::CheckUpdateModel(Node *root, std::vector<expr> assumps){
|
||||
// check_result temp1 = slvr.check(); // no idea why I need to do this
|
||||
ClearProofCore();
|
||||
check_result res = slvr.check_keep_model(assumps.size(),&assumps[0]);
|
||||
dualModel = slvr.get_model();
|
||||
return res;
|
||||
|
@ -1760,9 +1809,9 @@ namespace Duality {
|
|||
expr conj = ctx.make(And,conjuncts);
|
||||
s.add(conj);
|
||||
check_result res = s.check();
|
||||
s.pop(1);
|
||||
if(res != unsat)
|
||||
throw "should be unsat";
|
||||
s.pop(1);
|
||||
|
||||
for(unsigned i = 0; i < conjuncts.size(); ){
|
||||
std::swap(conjuncts[i],conjuncts.back());
|
||||
|
@ -2276,8 +2325,28 @@ namespace Duality {
|
|||
|
||||
}
|
||||
|
||||
void RPFP::ComputeProofCore(){
|
||||
if(!proof_core){
|
||||
std::vector<expr> assumps;
|
||||
slvr.get_proof().get_assumptions(assumps);
|
||||
proof_core = new hash_set<ast>;
|
||||
for(unsigned i = 0; i < assumps.size(); i++)
|
||||
proof_core->insert(assumps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool RPFP::EdgeUsedInProof(Edge *edge){
|
||||
ComputeProofCore();
|
||||
if(!edge->dual.null() && proof_core->find(edge->dual) != proof_core->end())
|
||||
return true;
|
||||
for(unsigned i = 0; i < edge->constraints.size(); i++)
|
||||
if(proof_core->find(edge->constraints[i]) != proof_core->end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
RPFP::~RPFP(){
|
||||
ClearProofCore();
|
||||
for(unsigned i = 0; i < nodes.size(); i++)
|
||||
delete nodes[i];
|
||||
for(unsigned i = 0; i < edges.size(); i++)
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace Duality {
|
|||
best.insert(*it);
|
||||
}
|
||||
#else
|
||||
virtual void ChooseExpand(const std::set<RPFP::Node *> &choices, std::set<RPFP::Node *> &best, bool high_priority=false){
|
||||
virtual void ChooseExpand(const std::set<RPFP::Node *> &choices, std::set<RPFP::Node *> &best, bool high_priority=false, bool best_only=false){
|
||||
if(high_priority) return;
|
||||
int best_score = INT_MAX;
|
||||
int worst_score = 0;
|
||||
|
@ -194,13 +194,13 @@ namespace Duality {
|
|||
best_score = std::min(best_score,score);
|
||||
worst_score = std::max(worst_score,score);
|
||||
}
|
||||
int cutoff = best_score + (worst_score-best_score)/2;
|
||||
int cutoff = best_only ? best_score : (best_score + (worst_score-best_score)/2);
|
||||
for(std::set<Node *>::iterator it = choices.begin(), en = choices.end(); it != en; ++it)
|
||||
if(scores[(*it)->map].updates <= cutoff)
|
||||
best.insert(*it);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** Called when done expanding a tree */
|
||||
virtual void Done() {}
|
||||
};
|
||||
|
@ -1607,12 +1607,12 @@ namespace Duality {
|
|||
heuristic->ChooseExpand(choices, best);
|
||||
}
|
||||
#else
|
||||
void ExpansionChoicesFull(std::set<Node *> &best, bool high_priority){
|
||||
void ExpansionChoicesFull(std::set<Node *> &best, bool high_priority, bool best_only = false){
|
||||
std::set<Node *> choices;
|
||||
for(std::list<RPFP::Node *>::iterator it = leaves.begin(), en = leaves.end(); it != en; ++it)
|
||||
if (high_priority || !tree->Empty(*it)) // if used in the counter-model
|
||||
choices.insert(*it);
|
||||
heuristic->ChooseExpand(choices, best, high_priority);
|
||||
heuristic->ChooseExpand(choices, best, high_priority, best_only);
|
||||
}
|
||||
|
||||
void ExpansionChoicesRec(std::vector <Node *> &unused_set, std::vector <Node *> &used_set,
|
||||
|
@ -1650,9 +1650,9 @@ namespace Duality {
|
|||
|
||||
std::set<Node *> old_choices;
|
||||
|
||||
void ExpansionChoices(std::set<Node *> &best, bool high_priority){
|
||||
void ExpansionChoices(std::set<Node *> &best, bool high_priority, bool best_only = false){
|
||||
if(!underapprox || constrained || high_priority){
|
||||
ExpansionChoicesFull(best, high_priority);
|
||||
ExpansionChoicesFull(best, high_priority,best_only);
|
||||
return;
|
||||
}
|
||||
std::vector <Node *> unused_set, used_set;
|
||||
|
@ -1684,7 +1684,7 @@ namespace Duality {
|
|||
timer_start("ExpandSomeNodes");
|
||||
timer_start("ExpansionChoices");
|
||||
std::set<Node *> choices;
|
||||
ExpansionChoices(choices,high_priority);
|
||||
ExpansionChoices(choices,high_priority,max != INT_MAX);
|
||||
timer_stop("ExpansionChoices");
|
||||
std::list<RPFP::Node *> leaves_copy = leaves; // copy so can modify orig
|
||||
leaves.clear();
|
||||
|
@ -1740,38 +1740,54 @@ namespace Duality {
|
|||
if(slvr_level != stack.back().level)
|
||||
throw "stacks out of sync!";
|
||||
|
||||
res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop
|
||||
// res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop
|
||||
check_result foo = tree->Check(top);
|
||||
res = foo == unsat ? l_false : l_true;
|
||||
|
||||
if (res == l_false) {
|
||||
if (stack.empty()) // should never happen
|
||||
return false;
|
||||
|
||||
std::vector<Node *> &expansions = stack.back().expansions;
|
||||
int update_count = 0;
|
||||
for(unsigned i = 0; i < expansions.size(); i++){
|
||||
tree->Generalize(expansions[i]);
|
||||
if(RecordUpdate(expansions[i]))
|
||||
update_count++;
|
||||
}
|
||||
if(update_count == 0)
|
||||
std::cout << "backtracked without learning\n";
|
||||
tree->Pop(1);
|
||||
hash_set<Node *> leaves_to_remove;
|
||||
for(unsigned i = 0; i < expansions.size(); i++){
|
||||
Node *node = expansions[i];
|
||||
// if(node != top)
|
||||
// tree->ConstrainParent(node->Incoming[0],node);
|
||||
std::vector<Node *> &cs = node->Outgoing->Children;
|
||||
for(unsigned i = 0; i < cs.size(); i++){
|
||||
leaves_to_remove.insert(cs[i]);
|
||||
UnmapNode(cs[i]);
|
||||
if(std::find(updated_nodes.begin(),updated_nodes.end(),cs[i]) != updated_nodes.end())
|
||||
throw "help!";
|
||||
{
|
||||
std::vector<Node *> &expansions = stack.back().expansions;
|
||||
int update_count = 0;
|
||||
for(unsigned i = 0; i < expansions.size(); i++){
|
||||
Node *node = expansions[i];
|
||||
tree->SolveSingleNode(top,node);
|
||||
tree->Generalize(node);
|
||||
if(RecordUpdate(node))
|
||||
update_count++;
|
||||
}
|
||||
RemoveExpansion(node);
|
||||
if(update_count == 0)
|
||||
std::cout << "backtracked without learning\n";
|
||||
}
|
||||
RemoveLeaves(leaves_to_remove);
|
||||
stack.pop_back();
|
||||
tree->ComputeProofCore(); // need to compute the proof core before popping solver
|
||||
while(1) {
|
||||
std::vector<Node *> &expansions = stack.back().expansions;
|
||||
bool prev_level_used = LevelUsedInProof(stack.size()-2); // need to compute this before pop
|
||||
tree->Pop(1);
|
||||
hash_set<Node *> leaves_to_remove;
|
||||
for(unsigned i = 0; i < expansions.size(); i++){
|
||||
Node *node = expansions[i];
|
||||
// if(node != top)
|
||||
// tree->ConstrainParent(node->Incoming[0],node);
|
||||
std::vector<Node *> &cs = node->Outgoing->Children;
|
||||
for(unsigned i = 0; i < cs.size(); i++){
|
||||
leaves_to_remove.insert(cs[i]);
|
||||
UnmapNode(cs[i]);
|
||||
if(std::find(updated_nodes.begin(),updated_nodes.end(),cs[i]) != updated_nodes.end())
|
||||
throw "help!";
|
||||
}
|
||||
RemoveExpansion(node);
|
||||
}
|
||||
RemoveLeaves(leaves_to_remove);
|
||||
stack.pop_back();
|
||||
if(prev_level_used || stack.size() == 1) break;
|
||||
RemoveUpdateNodesAtCurrentLevel(); // this level is about to be deleted -- remove its children from update list
|
||||
std::vector<Node *> &unused_ex = stack.back().expansions;
|
||||
for(unsigned i = 0; i < unused_ex.size(); i++)
|
||||
heuristic->Update(unused_ex[i]->map); // make it less likely to expand this node in future
|
||||
}
|
||||
HandleUpdatedNodes();
|
||||
if(stack.size() == 1)
|
||||
return false;
|
||||
|
@ -1782,8 +1798,10 @@ namespace Duality {
|
|||
for(unsigned i = 0; i < expansions.size(); i++){
|
||||
tree->FixCurrentState(expansions[i]->Outgoing);
|
||||
}
|
||||
#if 0
|
||||
if(tree->slvr.check() == unsat)
|
||||
throw "help!";
|
||||
#endif
|
||||
stack.push_back(stack_entry());
|
||||
stack.back().level = tree->slvr.get_scope_level();
|
||||
if(ExpandSomeNodes(false,1)){
|
||||
|
@ -1798,6 +1816,27 @@ namespace Duality {
|
|||
}
|
||||
}
|
||||
|
||||
bool LevelUsedInProof(unsigned level){
|
||||
std::vector<Node *> &expansions = stack[level].expansions;
|
||||
for(unsigned i = 0; i < expansions.size(); i++)
|
||||
if(tree->EdgeUsedInProof(expansions[i]->Outgoing))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void RemoveUpdateNodesAtCurrentLevel() {
|
||||
for(std::list<Node *>::iterator it = updated_nodes.begin(), en = updated_nodes.end(); it != en;){
|
||||
Node *node = *it;
|
||||
if(AtCurrentStackLevel(node->Incoming[0]->Parent)){
|
||||
std::list<Node *>::iterator victim = it;
|
||||
++it;
|
||||
updated_nodes.erase(victim);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveLeaves(hash_set<Node *> &leaves_to_remove){
|
||||
std::list<RPFP::Node *> leaves_copy;
|
||||
leaves_copy.swap(leaves);
|
||||
|
@ -2270,7 +2309,7 @@ namespace Duality {
|
|||
return name;
|
||||
}
|
||||
|
||||
virtual void ChooseExpand(const std::set<RPFP::Node *> &choices, std::set<RPFP::Node *> &best, bool high_priority){
|
||||
virtual void ChooseExpand(const std::set<RPFP::Node *> &choices, std::set<RPFP::Node *> &best, bool high_priority, bool best_only){
|
||||
if(!high_priority || !old_cex.tree){
|
||||
Heuristic::ChooseExpand(choices,best,false);
|
||||
return;
|
||||
|
|
|
@ -481,9 +481,9 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
for(unsigned i = 0; i < theory.size(); i++)
|
||||
_theory[i] = theory[i];
|
||||
|
||||
push();
|
||||
|
||||
if(!incremental){
|
||||
push();
|
||||
for(unsigned i = 0; i < linear_assumptions.size(); i++)
|
||||
for(unsigned j = 0; j < linear_assumptions[i].size(); j++)
|
||||
add(linear_assumptions[i][j]);
|
||||
|
@ -522,7 +522,8 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
}
|
||||
#endif
|
||||
|
||||
pop();
|
||||
if(!incremental)
|
||||
pop();
|
||||
|
||||
return (res == unsat) ? l_false : ((res == sat) ? l_true : l_undef);
|
||||
|
||||
|
@ -554,6 +555,29 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
return "";
|
||||
}
|
||||
|
||||
|
||||
static void get_assumptions_rec(stl_ext::hash_set<ast> &memo, const proof &pf, std::vector<expr> &assumps){
|
||||
if(memo.find(pf) != memo.end())return;
|
||||
memo.insert(pf);
|
||||
pfrule dk = pf.rule();
|
||||
if(dk == PR_ASSERTED){
|
||||
expr con = pf.conc();
|
||||
assumps.push_back(con);
|
||||
}
|
||||
else {
|
||||
unsigned nprems = pf.num_prems();
|
||||
for(unsigned i = 0; i < nprems; i++){
|
||||
proof arg = pf.prem(i);
|
||||
get_assumptions_rec(memo,arg,assumps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void proof::get_assumptions(std::vector<expr> &assumps){
|
||||
stl_ext::hash_set<ast> memo;
|
||||
get_assumptions_rec(memo,*this,assumps);
|
||||
}
|
||||
|
||||
|
||||
void ast::show() const{
|
||||
std::cout << mk_pp(raw(), m()) << std::endl;
|
||||
|
@ -564,6 +588,15 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void solver::show() {
|
||||
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(std::cout, m_solver->get_assertion(n-1));
|
||||
}
|
||||
|
||||
void include_ast_show(ast &a){
|
||||
a.show();
|
||||
|
|
|
@ -393,6 +393,7 @@ namespace Duality {
|
|||
sort array_range() const;
|
||||
};
|
||||
|
||||
|
||||
class func_decl : public ast {
|
||||
public:
|
||||
func_decl() : ast() {}
|
||||
|
@ -593,6 +594,36 @@ namespace Duality {
|
|||
};
|
||||
|
||||
|
||||
typedef ::decl_kind pfrule;
|
||||
|
||||
class proof : public ast {
|
||||
public:
|
||||
proof(context & c):ast(c) {}
|
||||
proof(context & c, ::proof *s):ast(c, s) {}
|
||||
proof(proof const & s):ast(s) {}
|
||||
operator ::proof*() const { return to_app(raw()); }
|
||||
proof & operator=(proof const & s) { return static_cast<proof&>(ast::operator=(s)); }
|
||||
|
||||
pfrule rule() const {
|
||||
::func_decl *d = to_app(raw())->get_decl();
|
||||
return d->get_decl_kind();
|
||||
}
|
||||
|
||||
unsigned num_prems() const {
|
||||
return to_app(raw())->get_num_args() - 1;
|
||||
}
|
||||
|
||||
expr conc() const {
|
||||
return ctx().cook(to_app(raw())->get_arg(num_prems()));
|
||||
}
|
||||
|
||||
proof prem(unsigned i) const {
|
||||
return proof(ctx(),to_app(to_app(raw())->get_arg(i)));
|
||||
}
|
||||
|
||||
void get_assumptions(std::vector<expr> &assumps);
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
#if Z3_MAJOR_VERSION > 4 || Z3_MAJOR_VERSION == 4 && Z3_MINOR_VERSION >= 3
|
||||
|
@ -870,6 +901,12 @@ namespace Duality {
|
|||
|
||||
unsigned get_scope_level(){return m_solver->get_scope_level();}
|
||||
|
||||
void show();
|
||||
|
||||
proof get_proof(){
|
||||
return proof(ctx(),m_solver->get_proof());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue