mirror of
https://github.com/Z3Prover/z3
synced 2025-04-29 11:55:51 +00:00
working on duality and quantified arithmetic in interpolation
This commit is contained in:
parent
8320144af0
commit
a93f8b04e5
10 changed files with 829 additions and 60 deletions
|
@ -277,6 +277,7 @@ namespace Duality {
|
|||
public:
|
||||
std::list<Edge *> edges;
|
||||
std::list<Node *> nodes;
|
||||
std::list<Edge *> constraints;
|
||||
};
|
||||
|
||||
|
||||
|
@ -286,6 +287,8 @@ namespace Duality {
|
|||
literals dualLabels;
|
||||
std::list<stack_entry> stack;
|
||||
std::vector<Term> axioms; // only saved here for printing purposes
|
||||
solver aux_solver;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
@ -296,7 +299,7 @@ namespace Duality {
|
|||
inherit the axioms.
|
||||
*/
|
||||
|
||||
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx), *(_ls->slvr)), dualModel(*(_ls->ctx))
|
||||
RPFP(LogicSolver *_ls) : Z3User(*(_ls->ctx), *(_ls->slvr)), dualModel(*(_ls->ctx)), aux_solver(*(_ls->ctx))
|
||||
{
|
||||
ls = _ls;
|
||||
nodeCount = 0;
|
||||
|
@ -351,10 +354,10 @@ namespace Duality {
|
|||
bool SubsetEq(const Transformer &other){
|
||||
Term t = owner->SubstParams(other.IndParams,IndParams,other.Formula);
|
||||
expr test = Formula && !t;
|
||||
owner->slvr.push();
|
||||
owner->slvr.add(test);
|
||||
check_result res = owner->slvr.check();
|
||||
owner->slvr.pop(1);
|
||||
owner->aux_solver.push();
|
||||
owner->aux_solver.add(test);
|
||||
check_result res = owner->aux_solver.check();
|
||||
owner->aux_solver.pop(1);
|
||||
return res == unsat;
|
||||
}
|
||||
|
||||
|
@ -444,6 +447,19 @@ namespace Duality {
|
|||
return n;
|
||||
}
|
||||
|
||||
/** Delete a node. You can only do this if not connected to any edges.*/
|
||||
void DeleteNode(Node *node){
|
||||
if(node->Outgoing || !node->Incoming.empty())
|
||||
throw "cannot delete RPFP node";
|
||||
for(std::vector<Node *>::iterator it = nodes.end(), en = nodes.begin(); it != en;){
|
||||
if(*(--it) == node){
|
||||
nodes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete node;
|
||||
}
|
||||
|
||||
/** This class represents a hyper-edge in the RPFP graph */
|
||||
|
||||
class Edge
|
||||
|
@ -460,6 +476,7 @@ namespace Duality {
|
|||
hash_map<ast,Term> varMap;
|
||||
Edge *map;
|
||||
Term labeled;
|
||||
std::vector<Term> constraints;
|
||||
|
||||
Edge(Node *_Parent, const Transformer &_F, const std::vector<Node *> &_Children, RPFP *_owner, int _number)
|
||||
: F(_F), Parent(_Parent), Children(_Children), dual(expr(_owner->ctx)) {
|
||||
|
@ -480,6 +497,29 @@ namespace Duality {
|
|||
return e;
|
||||
}
|
||||
|
||||
|
||||
/** Delete a hyper-edge and unlink it from any nodes. */
|
||||
void DeleteEdge(Edge *edge){
|
||||
if(edge->Parent)
|
||||
edge->Parent->Outgoing = 0;
|
||||
for(unsigned int i = 0; i < edge->Children.size(); i++){
|
||||
std::vector<Edge *> &ic = edge->Children[i]->Incoming;
|
||||
for(std::vector<Edge *>::iterator it = ic.begin(), en = ic.end(); it != en; ++it){
|
||||
if(*it == edge){
|
||||
ic.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(std::vector<Edge *>::iterator it = edges.end(), en = edges.begin(); it != en;){
|
||||
if(*(--it) == edge){
|
||||
edges.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete edge;
|
||||
}
|
||||
|
||||
/** Create an edge that lower-bounds its parent. */
|
||||
Edge *CreateLowerBoundEdge(Node *_Parent)
|
||||
{
|
||||
|
@ -494,13 +534,25 @@ namespace Duality {
|
|||
|
||||
void AssertEdge(Edge *e, int persist = 0, bool with_children = false, bool underapprox = false);
|
||||
|
||||
|
||||
/* Constrain an edge by the annotation of one of its children. */
|
||||
|
||||
void ConstrainParent(Edge *parent, Node *child);
|
||||
|
||||
/** For incremental solving, asserts the negation of the upper bound associated
|
||||
* with a node.
|
||||
* */
|
||||
|
||||
void AssertNode(Node *n);
|
||||
|
||||
/** Assert a constraint on an edge in the SMT context.
|
||||
*/
|
||||
void ConstrainEdge(Edge *e, const Term &t);
|
||||
|
||||
/** Fix the truth values of atomic propositions in the given
|
||||
edge to their values in the current assignment. */
|
||||
void FixCurrentState(Edge *root);
|
||||
|
||||
|
||||
/** Declare a constant in the background theory. */
|
||||
|
||||
void DeclareConstant(const FuncDecl &f);
|
||||
|
@ -592,6 +644,9 @@ namespace Duality {
|
|||
|
||||
Term ComputeUnderapprox(Node *root, int persist);
|
||||
|
||||
/** Try to strengthen the annotation of a node by removing disjuncts. */
|
||||
void Generalize(Node *node);
|
||||
|
||||
/** Push a scope. Assertions made after Push can be undone by Pop. */
|
||||
|
||||
void Push();
|
||||
|
@ -803,7 +858,15 @@ namespace Duality {
|
|||
|
||||
Term SubstBound(hash_map<int,Term> &subst, const Term &t);
|
||||
|
||||
void ConstrainEdgeLocalized(Edge *e, const Term &t);
|
||||
|
||||
void GreedyReduce(solver &s, std::vector<expr> &conjuncts);
|
||||
|
||||
void NegateLits(std::vector<expr> &lits);
|
||||
|
||||
expr SimplifyOr(std::vector<expr> &lits);
|
||||
|
||||
void SetAnnotation(Node *root, const expr &t);
|
||||
};
|
||||
|
||||
/** RPFP solver base class. */
|
||||
|
|
|
@ -283,7 +283,10 @@ namespace Duality {
|
|||
children[i] = ToTermTree(e->Children[i]);
|
||||
// Term top = ReducedDualEdge(e);
|
||||
Term top = e->dual.null() ? ctx.bool_val(true) : e->dual;
|
||||
return new TermTree(top, children);
|
||||
TermTree *res = new TermTree(top, children);
|
||||
for(unsigned i = 0; i < e->constraints.size(); i++)
|
||||
res->addTerm(e->constraints[i]);
|
||||
return res;
|
||||
}
|
||||
|
||||
TermTree *RPFP::GetGoalTree(Node *root){
|
||||
|
@ -375,6 +378,19 @@ namespace Duality {
|
|||
x = x && y;
|
||||
}
|
||||
|
||||
void RPFP::SetAnnotation(Node *root, const expr &t){
|
||||
hash_map<ast, Term> memo;
|
||||
Term b;
|
||||
std::vector<Term> v;
|
||||
RedVars(root, b, v);
|
||||
memo[b] = ctx.bool_val(true);
|
||||
for (unsigned i = 0; i < v.size(); i++)
|
||||
memo[v[i]] = root->Annotation.IndParams[i];
|
||||
Term annot = SubstRec(memo, t);
|
||||
// Strengthen(ref root.Annotation.Formula, annot);
|
||||
root->Annotation.Formula = annot;
|
||||
}
|
||||
|
||||
void RPFP::DecodeTree(Node *root, TermTree *interp, int persist)
|
||||
{
|
||||
std::vector<TermTree *> &ic = interp->getChildren();
|
||||
|
@ -384,16 +400,7 @@ namespace Duality {
|
|||
for (unsigned i = 0; i < nc.size(); i++)
|
||||
DecodeTree(nc[i], ic[i], persist);
|
||||
}
|
||||
hash_map<ast, Term> memo;
|
||||
Term b;
|
||||
std::vector<Term> v;
|
||||
RedVars(root, b, v);
|
||||
memo[b] = ctx.bool_val(true);
|
||||
for (unsigned i = 0; i < v.size(); i++)
|
||||
memo[v[i]] = root->Annotation.IndParams[i];
|
||||
Term annot = SubstRec(memo, interp->getTerm());
|
||||
// Strengthen(ref root.Annotation.Formula, annot);
|
||||
root->Annotation.Formula = annot;
|
||||
SetAnnotation(root,interp->getTerm());
|
||||
#if 0
|
||||
if(persist != 0)
|
||||
Z3_persist_ast(ctx,root->Annotation.Formula,persist);
|
||||
|
@ -511,6 +518,10 @@ namespace Duality {
|
|||
timer_stop("solver add");
|
||||
}
|
||||
|
||||
void RPFP::ConstrainParent(Edge *parent, Node *child){
|
||||
ConstrainEdgeLocalized(parent,GetAnnotation(child));
|
||||
}
|
||||
|
||||
|
||||
/** For incremental solving, asserts the negation of the upper bound associated
|
||||
* with a node.
|
||||
|
@ -526,6 +537,24 @@ namespace Duality {
|
|||
}
|
||||
}
|
||||
|
||||
/** Assert a constraint on an edge in the SMT context.
|
||||
*/
|
||||
|
||||
void RPFP::ConstrainEdge(Edge *e, const Term &t)
|
||||
{
|
||||
Term tl = Localize(e, t);
|
||||
ConstrainEdgeLocalized(e,tl);
|
||||
}
|
||||
|
||||
void RPFP::ConstrainEdgeLocalized(Edge *e, const Term &tl)
|
||||
{
|
||||
e->constraints.push_back(tl);
|
||||
stack.back().constraints.push_back(e);
|
||||
slvr.add(tl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Declare a constant in the background theory. */
|
||||
|
||||
void RPFP::DeclareConstant(const FuncDecl &f){
|
||||
|
@ -1064,7 +1093,7 @@ namespace Duality {
|
|||
}
|
||||
}
|
||||
/* Unreachable! */
|
||||
throw "error in RPFP::ImplicantRed";
|
||||
std::cerr << "error in RPFP::ImplicantRed";
|
||||
goto done;
|
||||
}
|
||||
else if(k == Not) {
|
||||
|
@ -1671,6 +1700,17 @@ namespace Duality {
|
|||
return eu;
|
||||
}
|
||||
|
||||
void RPFP::FixCurrentState(Edge *edge){
|
||||
hash_set<ast> dont_cares;
|
||||
resolve_ite_memo.clear();
|
||||
timer_start("UnderapproxFormula");
|
||||
Term dual = edge->dual.null() ? ctx.bool_val(true) : edge->dual;
|
||||
Term eu = UnderapproxFormula(dual,dont_cares);
|
||||
timer_stop("UnderapproxFormula");
|
||||
ConstrainEdgeLocalized(edge,eu);
|
||||
}
|
||||
|
||||
|
||||
|
||||
RPFP::Term RPFP::ModelValueAsConstraint(const Term &t){
|
||||
if(t.is_array()){
|
||||
|
@ -1714,6 +1754,69 @@ namespace Duality {
|
|||
res = CreateRelation(p->Annotation.IndParams,funder);
|
||||
}
|
||||
|
||||
void RPFP::GreedyReduce(solver &s, std::vector<expr> &conjuncts){
|
||||
// verify
|
||||
s.push();
|
||||
expr conj = ctx.make(And,conjuncts);
|
||||
s.add(conj);
|
||||
check_result res = s.check();
|
||||
s.pop(1);
|
||||
if(res != unsat)
|
||||
throw "should be unsat";
|
||||
|
||||
for(unsigned i = 0; i < conjuncts.size(); ){
|
||||
std::swap(conjuncts[i],conjuncts.back());
|
||||
expr save = conjuncts.back();
|
||||
conjuncts.pop_back();
|
||||
s.push();
|
||||
expr conj = ctx.make(And,conjuncts);
|
||||
s.add(conj);
|
||||
check_result res = s.check();
|
||||
s.pop(1);
|
||||
if(res != unsat){
|
||||
conjuncts.push_back(save);
|
||||
std::swap(conjuncts[i],conjuncts.back());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RPFP::NegateLits(std::vector<expr> &lits){
|
||||
for(unsigned i = 0; i < lits.size(); i++){
|
||||
expr &f = lits[i];
|
||||
if(f.is_app() && f.decl().get_decl_kind() == Not)
|
||||
f = f.arg(0);
|
||||
else
|
||||
f = !f;
|
||||
}
|
||||
}
|
||||
|
||||
expr RPFP::SimplifyOr(std::vector<expr> &lits){
|
||||
if(lits.size() == 0)
|
||||
return ctx.bool_val(false);
|
||||
if(lits.size() == 1)
|
||||
return lits[0];
|
||||
return ctx.make(Or,lits);
|
||||
}
|
||||
|
||||
void RPFP::Generalize(Node *node){
|
||||
std::vector<expr> conjuncts;
|
||||
expr fmla = GetAnnotation(node);
|
||||
CollectConjuncts(fmla,conjuncts,false);
|
||||
// try to remove conjuncts one at a tme
|
||||
aux_solver.push();
|
||||
Edge *edge = node->Outgoing;
|
||||
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);
|
||||
}
|
||||
GreedyReduce(aux_solver,conjuncts);
|
||||
aux_solver.pop(1);
|
||||
NegateLits(conjuncts);
|
||||
SetAnnotation(node,SimplifyOr(conjuncts));
|
||||
}
|
||||
|
||||
/** Push a scope. Assertions made after Push can be undone by Pop. */
|
||||
|
||||
|
@ -1735,6 +1838,8 @@ namespace Duality {
|
|||
(*it)->dual = expr(ctx,NULL);
|
||||
for(std::list<Node *>::iterator it = back.nodes.begin(), en = back.nodes.end(); it != en; ++it)
|
||||
(*it)->dual = expr(ctx,NULL);
|
||||
for(std::list<Edge *>::iterator it = back.constraints.begin(), en = back.constraints.end(); it != en; ++it)
|
||||
(*it)->constraints.pop_back();
|
||||
stack.pop_back();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1270,18 +1270,24 @@ namespace Duality {
|
|||
}
|
||||
}
|
||||
|
||||
bool UpdateNodeToNode(Node *node, Node *top){
|
||||
if(!node->Annotation.SubsetEq(top->Annotation)){
|
||||
reporter->Update(node,top->Annotation);
|
||||
indset->Update(node,top->Annotation);
|
||||
updated_nodes.insert(node->map);
|
||||
node->Annotation.IntersectWith(top->Annotation);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Update the unwinding solution, using an interpolant for the
|
||||
derivation tree. */
|
||||
void UpdateWithInterpolant(Node *node, RPFP *tree, Node *top){
|
||||
if(top->Outgoing)
|
||||
for(unsigned i = 0; i < top->Outgoing->Children.size(); i++)
|
||||
UpdateWithInterpolant(node->Outgoing->Children[i],tree,top->Outgoing->Children[i]);
|
||||
if(!node->Annotation.SubsetEq(top->Annotation)){
|
||||
reporter->Update(node,top->Annotation);
|
||||
indset->Update(node,top->Annotation);
|
||||
updated_nodes.insert(node->map);
|
||||
node->Annotation.IntersectWith(top->Annotation);
|
||||
}
|
||||
UpdateNodeToNode(node, top);
|
||||
heuristic->Update(node);
|
||||
}
|
||||
|
||||
|
@ -1305,7 +1311,8 @@ namespace Duality {
|
|||
if(node->Bound.IsFull()) return true;
|
||||
reporter->Bound(node);
|
||||
int start_decs = rpfp->CumulativeDecisions();
|
||||
DerivationTree dt(this,unwinding,reporter,heuristic,FullExpand);
|
||||
DerivationTree *dtp = new DerivationTreeSlow(this,unwinding,reporter,heuristic,FullExpand);
|
||||
DerivationTree &dt = *dtp;
|
||||
bool res = dt.Derive(unwinding,node,UseUnderapprox);
|
||||
int end_decs = rpfp->CumulativeDecisions();
|
||||
// std::cout << "decisions: " << (end_decs - start_decs) << std::endl;
|
||||
|
@ -1321,6 +1328,7 @@ namespace Duality {
|
|||
UpdateWithInterpolant(node,dt.tree,dt.top);
|
||||
delete dt.tree;
|
||||
}
|
||||
delete dtp;
|
||||
return !res;
|
||||
}
|
||||
|
||||
|
@ -1491,7 +1499,7 @@ namespace Duality {
|
|||
return res != unsat;
|
||||
}
|
||||
|
||||
bool Build(){
|
||||
virtual bool Build(){
|
||||
#ifdef EFFORT_BOUNDED_STRAT
|
||||
start_decs = tree->CumulativeDecisions();
|
||||
#endif
|
||||
|
@ -1545,7 +1553,7 @@ namespace Duality {
|
|||
}
|
||||
}
|
||||
|
||||
void ExpandNode(RPFP::Node *p){
|
||||
virtual void ExpandNode(RPFP::Node *p){
|
||||
// tree->RemoveEdge(p->Outgoing);
|
||||
Edge *edge = duality->GetNodeOutgoing(p->map,last_decs);
|
||||
std::vector<RPFP::Node *> &cs = edge->Children;
|
||||
|
@ -1573,6 +1581,7 @@ namespace Duality {
|
|||
}
|
||||
#else
|
||||
#if 0
|
||||
|
||||
void ExpansionChoices(std::set<Node *> &best){
|
||||
std::vector <Node *> unused_set, used_set;
|
||||
std::set<Node *> choices;
|
||||
|
@ -1668,7 +1677,7 @@ namespace Duality {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
bool ExpandSomeNodes(bool high_priority = false){
|
||||
bool ExpandSomeNodes(bool high_priority = false, int max = INT_MAX){
|
||||
#ifdef EFFORT_BOUNDED_STRAT
|
||||
last_decs = tree->CumulativeDecisions() - start_decs;
|
||||
#endif
|
||||
|
@ -1679,17 +1688,194 @@ namespace Duality {
|
|||
timer_stop("ExpansionChoices");
|
||||
std::list<RPFP::Node *> leaves_copy = leaves; // copy so can modify orig
|
||||
leaves.clear();
|
||||
int count = 0;
|
||||
for(std::list<RPFP::Node *>::iterator it = leaves_copy.begin(), en = leaves_copy.end(); it != en; ++it){
|
||||
if(choices.find(*it) != choices.end())
|
||||
if(choices.find(*it) != choices.end() && count < max){
|
||||
count++;
|
||||
ExpandNode(*it);
|
||||
}
|
||||
else leaves.push_back(*it);
|
||||
}
|
||||
timer_stop("ExpandSomeNodes");
|
||||
return !choices.empty();
|
||||
}
|
||||
|
||||
void RemoveExpansion(RPFP::Node *p){
|
||||
Edge *edge = p->Outgoing;
|
||||
Node *parent = edge->Parent;
|
||||
std::vector<RPFP::Node *> cs = edge->Children;
|
||||
tree->DeleteEdge(edge);
|
||||
for(unsigned i = 0; i < cs.size(); i++)
|
||||
tree->DeleteNode(cs[i]);
|
||||
leaves.push_back(parent);
|
||||
}
|
||||
};
|
||||
|
||||
class DerivationTreeSlow : public DerivationTree {
|
||||
public:
|
||||
|
||||
struct stack_entry {
|
||||
unsigned level; // SMT solver stack level
|
||||
std::vector<Node *> expansions;
|
||||
};
|
||||
|
||||
std::vector<stack_entry> stack;
|
||||
|
||||
hash_map<Node *, expr> updates;
|
||||
|
||||
DerivationTreeSlow(Duality *_duality, RPFP *rpfp, Reporter *_reporter, Heuristic *_heuristic, bool _full_expand)
|
||||
: DerivationTree(_duality, rpfp, _reporter, _heuristic, _full_expand) {
|
||||
stack.push_back(stack_entry());
|
||||
}
|
||||
|
||||
virtual bool Build(){
|
||||
|
||||
stack.back().level = tree->slvr.get_scope_level();
|
||||
|
||||
while (true)
|
||||
{
|
||||
lbool res;
|
||||
|
||||
unsigned slvr_level = tree->slvr.get_scope_level();
|
||||
if(slvr_level != stack.back().level)
|
||||
throw "stacks out of sync!";
|
||||
|
||||
res = tree->Solve(top, 1); // incremental solve, keep interpolants for one pop
|
||||
|
||||
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!";
|
||||
}
|
||||
RemoveExpansion(node);
|
||||
}
|
||||
RemoveLeaves(leaves_to_remove);
|
||||
stack.pop_back();
|
||||
HandleUpdatedNodes();
|
||||
if(stack.size() == 1)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
tree->Push();
|
||||
std::vector<Node *> &expansions = stack.back().expansions;
|
||||
for(unsigned i = 0; i < expansions.size(); i++){
|
||||
tree->FixCurrentState(expansions[i]->Outgoing);
|
||||
}
|
||||
if(tree->slvr.check() == unsat)
|
||||
throw "help!";
|
||||
stack.push_back(stack_entry());
|
||||
stack.back().level = tree->slvr.get_scope_level();
|
||||
if(ExpandSomeNodes(false,1)){
|
||||
continue;
|
||||
}
|
||||
while(stack.size() > 1){
|
||||
tree->Pop(1);
|
||||
stack.pop_back();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveLeaves(hash_set<Node *> &leaves_to_remove){
|
||||
std::list<RPFP::Node *> leaves_copy;
|
||||
leaves_copy.swap(leaves);
|
||||
for(std::list<RPFP::Node *>::iterator it = leaves_copy.begin(), en = leaves_copy.end(); it != en; ++it){
|
||||
if(leaves_to_remove.find(*it) == leaves_to_remove.end())
|
||||
leaves.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
hash_map<Node *, std::vector<Node *> > node_map;
|
||||
std::list<Node *> updated_nodes;
|
||||
|
||||
virtual void ExpandNode(RPFP::Node *p){
|
||||
stack.back().expansions.push_back(p);
|
||||
DerivationTree::ExpandNode(p);
|
||||
std::vector<Node *> &new_nodes = p->Outgoing->Children;
|
||||
for(unsigned i = 0; i < new_nodes.size(); i++){
|
||||
Node *n = new_nodes[i];
|
||||
node_map[n->map].push_back(n);
|
||||
}
|
||||
}
|
||||
|
||||
bool RecordUpdate(Node *node){
|
||||
bool res = duality->UpdateNodeToNode(node->map,node);
|
||||
if(res){
|
||||
std::vector<Node *> to_update = node_map[node->map];
|
||||
for(unsigned i = 0; i < to_update.size(); i++){
|
||||
Node *node2 = to_update[i];
|
||||
// maintain invariant that no nodes on updated list are created at current stack level
|
||||
if(node2 == node || !(node->Incoming.size() > 0 && AtCurrentStackLevel(node2->Incoming[0]->Parent))){
|
||||
updated_nodes.push_back(node2);
|
||||
if(node2 != node)
|
||||
node2->Annotation = node->Annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void HandleUpdatedNodes(){
|
||||
for(std::list<Node *>::iterator it = updated_nodes.begin(), en = updated_nodes.end(); it != en;){
|
||||
Node *node = *it;
|
||||
node->Annotation = node->map->Annotation;
|
||||
if(node->Incoming.size() > 0)
|
||||
tree->ConstrainParent(node->Incoming[0],node);
|
||||
if(AtCurrentStackLevel(node->Incoming[0]->Parent)){
|
||||
std::list<Node *>::iterator victim = it;
|
||||
++it;
|
||||
updated_nodes.erase(victim);
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
bool AtCurrentStackLevel(Node *node){
|
||||
std::vector<Node *> vec = stack.back().expansions;
|
||||
for(unsigned i = 0; i < vec.size(); i++)
|
||||
if(vec[i] == node)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void UnmapNode(Node *node){
|
||||
std::vector<Node *> &vec = node_map[node->map];
|
||||
for(unsigned i = 0; i < vec.size(); i++){
|
||||
if(vec[i] == node){
|
||||
std::swap(vec[i],vec.back());
|
||||
vec.pop_back();
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw "can't unmap node";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Covering {
|
||||
|
||||
struct cover_info {
|
||||
|
|
|
@ -425,15 +425,18 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
|
||||
static int linearize_assumptions(int num,
|
||||
TermTree *assumptions,
|
||||
std::vector<expr> &linear_assumptions,
|
||||
std::vector<std::vector <expr> > &linear_assumptions,
|
||||
std::vector<int> &parents){
|
||||
for(unsigned i = 0; i < assumptions->getChildren().size(); i++)
|
||||
num = linearize_assumptions(num, assumptions->getChildren()[i], linear_assumptions, parents);
|
||||
linear_assumptions[num] = assumptions->getTerm();
|
||||
// linear_assumptions[num].push_back(assumptions->getTerm());
|
||||
for(unsigned i = 0; i < assumptions->getChildren().size(); i++)
|
||||
parents[assumptions->getChildren()[i]->getNumber()] = num;
|
||||
parents[num] = SHRT_MAX; // in case we have no parent
|
||||
linear_assumptions[num] = assumptions->getTerm();
|
||||
linear_assumptions[num].push_back(assumptions->getTerm());
|
||||
std::vector<expr> &ts = assumptions->getTerms();
|
||||
for(unsigned i = 0; i < ts.size(); i++)
|
||||
linear_assumptions[num].push_back(ts[i]);
|
||||
return num + 1;
|
||||
}
|
||||
|
||||
|
@ -462,14 +465,15 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
|
||||
{
|
||||
int size = assumptions->number(0);
|
||||
std::vector<expr> linear_assumptions(size);
|
||||
std::vector<std::vector<expr> > linear_assumptions(size);
|
||||
std::vector<int> parents(size);
|
||||
linearize_assumptions(0,assumptions,linear_assumptions,parents);
|
||||
|
||||
ptr_vector< ::ast> _interpolants(size-1);
|
||||
ptr_vector< ::ast>_assumptions(size);
|
||||
vector<ptr_vector< ::ast> >_assumptions(size);
|
||||
for(int i = 0; i < size; i++)
|
||||
_assumptions[i] = linear_assumptions[i];
|
||||
for(unsigned j = 0; j < linear_assumptions[i].size(); j++)
|
||||
_assumptions[i].push_back(linear_assumptions[i][j]);
|
||||
::vector<int> _parents; _parents.resize(parents.size());
|
||||
for(unsigned i = 0; i < parents.size(); i++)
|
||||
_parents[i] = parents[i];
|
||||
|
@ -481,7 +485,8 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
|
|||
|
||||
if(!incremental){
|
||||
for(unsigned i = 0; i < linear_assumptions.size(); i++)
|
||||
add(linear_assumptions[i]);
|
||||
for(unsigned j = 0; j < linear_assumptions[i].size(); j++)
|
||||
add(linear_assumptions[i][j]);
|
||||
}
|
||||
|
||||
check_result res = check();
|
||||
|
|
|
@ -867,6 +867,9 @@ namespace Duality {
|
|||
if(m_solver)
|
||||
m_solver->cancel();
|
||||
}
|
||||
|
||||
unsigned get_scope_level(){return m_solver->get_scope_level();}
|
||||
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
@ -1199,6 +1202,8 @@ namespace Duality {
|
|||
|
||||
inline expr getTerm(){return term;}
|
||||
|
||||
inline std::vector<expr> &getTerms(){return terms;}
|
||||
|
||||
inline std::vector<TermTree *> &getChildren(){
|
||||
return children;
|
||||
}
|
||||
|
@ -1215,6 +1220,8 @@ namespace Duality {
|
|||
}
|
||||
|
||||
inline void setTerm(expr t){term = t;}
|
||||
|
||||
inline void addTerm(expr t){terms.push_back(t);}
|
||||
|
||||
inline void setChildren(const std::vector<TermTree *> & _children){
|
||||
children = _children;
|
||||
|
@ -1231,6 +1238,7 @@ namespace Duality {
|
|||
|
||||
private:
|
||||
expr term;
|
||||
std::vector<expr> terms;
|
||||
std::vector<TermTree *> children;
|
||||
int num;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue