mirror of
https://github.com/Z3Prover/z3
synced 2025-04-27 02:45:51 +00:00
adding recursion bounds to duality
This commit is contained in:
parent
672b8e1022
commit
13b61d894c
7 changed files with 60 additions and 23 deletions
|
@ -488,9 +488,10 @@ protected:
|
|||
std::vector<Edge *> Incoming;
|
||||
Term dual;
|
||||
Node *map;
|
||||
unsigned recursion_bound;
|
||||
|
||||
Node(const FuncDecl &_Name, const Transformer &_Annotation, const Transformer &_Bound, const Transformer &_Underapprox, const Term &_dual, RPFP *_owner, int _number)
|
||||
: Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0;}
|
||||
: Name(_Name), Annotation(_Annotation), Bound(_Bound), Underapprox(_Underapprox), dual(_dual) {owner = _owner; number = _number; Outgoing = 0; recursion_bound = UINT_MAX;}
|
||||
};
|
||||
|
||||
/** Create a node in the graph. The input is a term R(v_1...v_n)
|
||||
|
@ -829,7 +830,7 @@ protected:
|
|||
#ifdef _WINDOWS
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void FromClauses(const std::vector<Term> &clauses);
|
||||
void FromClauses(const std::vector<Term> &clauses, const std::vector<unsigned> *bounds = 0);
|
||||
|
||||
void FromFixpointContext(fixedpoint fp, std::vector<Term> &queries);
|
||||
|
||||
|
|
|
@ -3570,7 +3570,7 @@ namespace Duality {
|
|||
|
||||
#define USE_QE_LITE
|
||||
|
||||
void RPFP::FromClauses(const std::vector<Term> &unskolemized_clauses){
|
||||
void RPFP::FromClauses(const std::vector<Term> &unskolemized_clauses, const std::vector<unsigned> *bounds){
|
||||
hash_map<func_decl,Node *> pmap;
|
||||
func_decl fail_pred = ctx.fresh_func_decl("@Fail", ctx.bool_sort());
|
||||
|
||||
|
@ -3663,6 +3663,7 @@ namespace Duality {
|
|||
pmap[R] = node;
|
||||
if (is_query)
|
||||
node->Bound = CreateRelation(std::vector<Term>(), ctx.bool_val(false));
|
||||
node->recursion_bound = bounds ? 0 : UINT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3728,6 +3729,8 @@ namespace Duality {
|
|||
Transformer T = CreateTransformer(Relparams,Indparams,body);
|
||||
Edge *edge = CreateEdge(Parent,T,Children);
|
||||
edge->labeled = labeled;; // remember for label extraction
|
||||
if(bounds)
|
||||
Parent->recursion_bound = std::max(Parent->recursion_bound,(*bounds)[i]);
|
||||
// edges.push_back(edge);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ Revision History:
|
|||
#include <map>
|
||||
#include <list>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
// TODO: make these official options or get rid of them
|
||||
|
||||
|
@ -304,7 +305,7 @@ namespace Duality {
|
|||
|
||||
#ifdef BOUNDED
|
||||
struct Counter {
|
||||
int val;
|
||||
unsigned val;
|
||||
Counter(){val = 0;}
|
||||
};
|
||||
typedef std::map<Node *,Counter> NodeToCounter;
|
||||
|
@ -321,6 +322,10 @@ namespace Duality {
|
|||
heuristic = !cex.get_tree() ? (Heuristic *)(new LocalHeuristic(rpfp))
|
||||
: (Heuristic *)(new ReplayHeuristic(rpfp,cex));
|
||||
#endif
|
||||
// determine if we are recursion bounded
|
||||
for(unsigned i = 0; i < rpfp->nodes.size(); i++)
|
||||
if(rpfp->nodes[i]->recursion_bound < UINT_MAX)
|
||||
RecursionBound = 0;
|
||||
cex.clear(); // in case we didn't use it for heuristic
|
||||
if(unwinding) delete unwinding;
|
||||
unwinding = new RPFP(rpfp->ls);
|
||||
|
@ -461,7 +466,7 @@ namespace Duality {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/** Create an instance of a node in the unwinding. Set its
|
||||
annotation to true, and mark it unexpanded. */
|
||||
Node* CreateNodeInstance(Node *node, int number = 0){
|
||||
|
@ -780,10 +785,8 @@ namespace Duality {
|
|||
std::vector<Node *> &insts = insts_of_node[node];
|
||||
for(unsigned j = 0; j < insts.size(); j++)
|
||||
if(indset->Contains(insts[j]))
|
||||
if(NodePastRecursionBound(insts[j])){
|
||||
if(NodePastRecursionBound(insts[j],true))
|
||||
recursionBounded = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -801,12 +804,18 @@ namespace Duality {
|
|||
}
|
||||
|
||||
#ifdef BOUNDED
|
||||
bool NodePastRecursionBound(Node *node){
|
||||
bool NodePastRecursionBound(Node *node, bool report = false){
|
||||
if(RecursionBound < 0) return false;
|
||||
NodeToCounter &backs = back_edges[node];
|
||||
for(NodeToCounter::iterator it = backs.begin(), en = backs.end(); it != en; ++it){
|
||||
if(it->second.val > RecursionBound)
|
||||
if(it->second.val > it->first->recursion_bound){
|
||||
if(report){
|
||||
std::ostringstream os;
|
||||
os << "cut off " << it->first->Name.name() << " at depth " << it->second.val;
|
||||
reporter->Message(os.str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue