double BestFirstReachabilitySearch::lookaheadDistance(const PetriNet& net, const Structures::State* state, const PQL::Condition* query, int depth){ double min = -1; State* ns = (State*)alloca(StateAllocator<>::stateSize(net)); StateAllocator<>::initializeState(ns, net); for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ if(net.fire(t, state, ns) && !_states->contains(ns)){ PQL::DistanceContext context(net, _distanceStrategy, ns->marking(), ns->intValuation(), ns->boolValuation(), _dm); double d = query->distance(context); if(d < min || min == -1) min = d; if(depth - 1 > 0) d = lookaheadDistance(net, ns, query, depth-1); if(d < min || min == -1) min = d; } } return min; }
ReachabilityResult MonoDFS::reachable(const PetriNet &net, const MarkVal *m0, const VarVal *v0, const BoolVal *b0, PQL::Condition *query){ //Do we initially satisfy query? if(query->evaluate(PQL::EvaluationContext(m0, v0, b0))) return ReachabilityResult(ReachabilityResult::Satisfied, "A state satisfying the query was found"); //Create StateSet MonotonicityContext context(&net,query); context.analyze(); DFSStateSet states(net,&context, ModeNormal); StateAllocator<1000000> allocator(net); State* s0 = allocator.createState(); memcpy(s0->marking(), m0, sizeof(MarkVal)*net.numberOfPlaces()); memcpy(s0->intValuation(), v0, sizeof(VarVal)*net.numberOfIntVariables()); memcpy(s0->boolValuation(), b0, sizeof(BoolVal)*net.numberOfBoolVariables()); states.add(s0, 0); unsigned int max = 0; int count = 0; BigInt exploredStates = 0; BigInt expandedStates = 0; BigInt transitionFired = 0; State* ns = allocator.createState(); while(states.waitingSize()){ if(count++ & 1<<18){ if(states.waitingSize() > max) max = states.waitingSize(); count = 0; //report progress reportProgress((double)(max-states.waitingSize())/(double)max); //check abort if(abortRequested()) return ReachabilityResult(ReachabilityResult::Unknown, "Search was aborted."); } //Take first step of the stack Step tstep = states.getNextStep(); State* s = tstep.state; ns->setParent(s); bool foundSomething = false; for(unsigned int t = tstep.t; t < net.numberOfTransitions(); t++){ if(net.fire(t, s->marking(), s->intValuation(),s->boolValuation(), ns->marking(), ns->intValuation(), ns->boolValuation())){ transitionFired++; if(states.add(ns,t)){ ns->setTransition(t); if(query->evaluate(PQL::EvaluationContext(ns->marking(), ns->intValuation(), ns->boolValuation()))) return ReachabilityResult(ReachabilityResult::Satisfied, "A state satisfying the query was found", expandedStates, exploredStates, transitionFired, states.getCountRemove(), ns->pathLength(), ns->trace()); exploredStates++; foundSomething = true; ns = allocator.createState(); break; } } } if(!foundSomething){ states.popWating(); expandedStates++; } } //states.writeStatistics(); return ReachabilityResult(ReachabilityResult::NotSatisfied, "No state satisfying the query exists.", expandedStates, exploredStates, transitionFired, states.getCountRemove()); }
ReachabilityResult BestFirstReachabilitySearch::reachable(const PetriNet &net, const MarkVal *m0, const VarVal *v0, const BoolVal *ba, PQL::Condition *query){ StateAllocator<> allocator(net); State* s0 = allocator.createState(); memcpy(s0->marking(), m0, sizeof(MarkVal) * net.numberOfPlaces()); memcpy(s0->intValuation(), v0, sizeof(VarVal) * net.numberOfIntVariables()); memcpy(s0->boolValuation(), ba, sizeof(BoolVal) * net.numberOfBoolVariables()); if(query->evaluate(*s0)) return ReachabilityResult(ReachabilityResult::Satisfied, "Satisfied initially", 0, 0); //Initialize subclasses initialize(query, net); StateSet states(net); _states = &states; states.add(s0); //PriorityQueue<State*> queue; EnhancedPriorityQueue<State*> queue; queue.push(0, s0); //Allocate new state State* ns = allocator.createState(); State* ns2 = allocator.createState(); State* ns3 = allocator.createState(); int count = 0; BigInt expandedStates = 0; BigInt exploredStates = 0; BigInt transitionFired = 0; size_t max = 1; while(!queue.empty()){ if(count++ & 1<<17){ count = 0; if(queue.size() > max) max = queue.size(); this->reportProgress((double)(max - queue.size()) / ((double)(max))); if(this->abortRequested()) return ReachabilityResult(ReachabilityResult::Unknown, "Query aborted!"); } //Take something out of the queue State* s = queue.pop(depthFirst); expandedStates++; // Attempt to fire each transition for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ if(net.fire(t, s->marking(), s->intValuation(), s->boolValuation(), ns->marking(), ns->intValuation(), ns->boolValuation())){ //If it's new transitionFired++; if(states.add(ns)){ exploredStates++; //Set parent and transition for the state ns->setParent(s); ns->setTransition(t); //Test query if(query->evaluate(*ns)){ //ns->dumpTrace(net); return ReachabilityResult(ReachabilityResult::Satisfied, "Query was satified!", expandedStates, exploredStates, transitionFired,0 , ns->pathLength(), ns->trace()); } // Insert in queue, with given priority double bestp = priority(ns, query, net); queue.push(bestp, ns); if(fireUntillNoBetter && net.fire(t, ns, ns2)){ if(query->evaluate(*ns2)){ ns2->setTransition(t); ns2->setParent(ns); return ReachabilityResult(ReachabilityResult::Satisfied, "Query was satified!", expandedStates, exploredStates, transitionFired,0, ns2->pathLength(), ns2->trace()); } double p = priority(ns2, query, net); if(p <= bestp){ bestp = p; while(net.fire(t, ns2, ns3) && (p = priority(ns3, query, net)) <= bestp){ ns3->setTransition(t); ns3->setParent(ns2); bestp = p; State* tmp = ns2; //SWAP ns2 and ns3 ns2 = ns3; ns3 = tmp; exploredStates++; if(query->evaluate(*ns2)){ return ReachabilityResult(ReachabilityResult::Satisfied, "Query was satisfied!", expandedStates, exploredStates, transitionFired, 0, ns2->pathLength(), ns2->trace()); } } if(states.add(ns2)){ queue.push(priority(ns2, query, net), ns2); ns2 = allocator.createState(); } } } //Allocate new stake, as states take ownership ns = allocator.createState(); } } } } return ReachabilityResult(ReachabilityResult::NotSatisfied, "Query cannot be satisfied!", expandedStates, exploredStates, transitionFired,0); }
ReachabilityResult HeuristicDFS::reachable(const PetriNet& net, const MarkVal* m0, const VarVal* v0, const BoolVal *ba, PQL::Condition* query){ //Do we initially satisfy query? if(query->evaluate(PQL::EvaluationContext(m0, v0, ba))) return ReachabilityResult(ReachabilityResult::Satisfied, "A state satisfying the query was found"); StateSet states(net); StateAllocator<> allocator(net); std::list<State*> stack; State* s0 = allocator.createState(); memcpy(s0->marking(), m0, sizeof(MarkVal)*net.numberOfPlaces()); memcpy(s0->intValuation(), v0, sizeof(VarVal)*net.numberOfIntVariables()); memcpy(s0->boolValuation(), ba, sizeof(BoolVal)*net.numberOfBoolVariables()); stack.push_back(s0); states.add(s0); Structures::DistanceMatrix distanceMatrix(net); State* ns = allocator.createState(); unsigned int max = 0; int count = 0; BigInt expandedStates = 0; BigInt exploredStates = 0; BigInt transitionFired = 0; while(!stack.empty()){ // Progress reporting and abort checking if(count++ & 1<<16){ if(stack.size() > max) max = stack.size(); count = 0; // Report progress reportProgress((double)(max - stack.size())/(double)max); // Check abort if(abortRequested()) return ReachabilityResult(ReachabilityResult::Unknown, "Search was aborted."); } State* s = stack.back(); stack.pop_back(); State* succ[net.numberOfTransitions()]; double distances[net.numberOfTransitions()]; memset(succ, 0, net.numberOfTransitions()*sizeof(State*)); for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ if(net.fire(t, s, ns)){ transitionFired++; if(states.add(ns)){ exploredStates++; ns->setParent(s); ns->setTransition(t); if(query->evaluate(*ns)) return ReachabilityResult(ReachabilityResult::Satisfied, "A state satisfying the query was found", expandedStates, exploredStates, transitionFired, 0, ns->pathLength(), ns->trace()); PQL::DistanceContext context(net, _distanceStrategy, ns->marking(), ns->intValuation(), ns->boolValuation(), &distanceMatrix); succ[t] = ns; distances[t] = query->distance(context); ns = allocator.createState(); } } } // Pretty bobble sort of the successors while(true){ bool foundSomething = false; unsigned int min = 0; for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ if(succ[t] && (!foundSomething || distances[t] < distances[min])){ min = t; foundSomething = true; } } if(foundSomething){ stack.push_back(succ[min]); succ[min] = NULL; }else break; } expandedStates++; } return ReachabilityResult(ReachabilityResult::NotSatisfied, "No state satisfying the query exists.", expandedStates, exploredStates, transitionFired, 0); }
ReachabilityResult MonoBFS::reachable(const PetriNet &net, const MarkVal *m0, const VarVal *v0, const BoolVal *ba, PQL::Condition *query){ //Do we initially satisfy query? if(query->evaluate(PQL::EvaluationContext(m0, v0,ba))) return ReachabilityResult(ReachabilityResult::Satisfied, "A state satisfying the query was found"); //Create StateSet MonotonicityContext context(&net, query); context.analyze(); BFSOrderableStateSet states(net,&context); StateAllocator<1000000> allocator(net); State* s0 = allocator.createState(); memcpy(s0->marking(), m0, sizeof(MarkVal)*net.numberOfPlaces()); memcpy(s0->intValuation(), v0, sizeof(VarVal)*net.numberOfIntVariables()); memcpy(s0->boolValuation(), ba, sizeof(BoolVal)*net.numberOfBoolVariables()); states.add(s0); unsigned int max = 0; int count = 0; BigInt expandedStates = 0; BigInt exploredStates = 0; BigInt transitionFired = 0; State* ns = allocator.createState(); State* s = states.getNextState(); while(s){ // Progress reporting and abort checking if(count++ & 1<<15){ if(states.waitingSize() > max) max = states.waitingSize(); count = 0; // Report progress reportProgress((double)(max - states.waitingSize())/(double)max); // Check abort if(abortRequested()) return ReachabilityResult(ReachabilityResult::Unknown, "Search was aborted."); } for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ if(net.fire(t, s, ns)){ transitionFired++; if(states.add(ns)){ exploredStates++; ns->setParent(s); ns->setTransition(t); if(query->evaluate(PQL::EvaluationContext(ns->marking(), ns->intValuation(), ns->boolValuation()))){ //ns->dumpTrace(net); return ReachabilityResult(ReachabilityResult::Satisfied, "A state satisfying the query was found", expandedStates, exploredStates, transitionFired, states.getCountRemove(), ns->pathLength(), ns->trace()); } ns = allocator.createState(); } } } s = states.getNextState(); expandedStates++; } return ReachabilityResult(ReachabilityResult::NotSatisfied, "No state satisfying the query exists.", expandedStates, exploredStates, transitionFired, states.getCountRemove()); }
ReachabilityResult IndexedBestFS::reachable(const PetriNet &net, const MarkVal *m0, const VarVal *v0, const BoolVal *ba, PQL::Condition *query){ StateAllocator<> allocator(net); State* s0 = allocator.createState(); memcpy(s0->marking(), m0, sizeof(MarkVal) * net.numberOfPlaces()); memcpy(s0->intValuation(), v0, sizeof(VarVal) * net.numberOfIntVariables()); memcpy(s0->boolValuation(), ba, sizeof(BoolVal) * net.numberOfBoolVariables()); if(query->evaluate(*s0)) return ReachabilityResult(ReachabilityResult::Satisfied, "Satisfied initially", 0, 0); //Initialize subclasses MonotonicityContext context(&net, query); context.analyze(); //Initialise StateSet IndexedBestFSStateSet states(net, &context, _distanceStrategy, query, _varianceFirst); states.add(s0); //Allocate new state State* ns = allocator.createState(); int count = 0; BigInt expandedStates = 0; BigInt exploredStates = 0; BigInt transitionFired = 0; size_t max = 1; State* s = states.getNextState(); while(s){ if(count++ & 1<<16){ count = 0; if(states.waitingSize() > max) max = states.waitingSize(); this->reportProgress((double)(max - states.waitingSize()) / ((double)(max))); if(this->abortRequested()) return ReachabilityResult(ReachabilityResult::Unknown, "Query aborted!"); } // Attempt to fire each transition for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ if(net.fire(t, s, ns)){ //If it's new transitionFired++; if(states.add(ns)){ exploredStates++; //Set parent and transition for the state ns->setParent(s); ns->setTransition(t); //Test query if(query->evaluate(*ns)){ //ns->dumpTrace(net); return ReachabilityResult(ReachabilityResult::Satisfied, "Query was satified!", expandedStates, exploredStates, transitionFired, states.getCountRemove(), ns->pathLength(), ns->trace()); } //Allocate new state, as states take ownership ns = allocator.createState(); } } } //Take something out of the queue expandedStates++; s = states.getNextState(); } return ReachabilityResult(ReachabilityResult::NotSatisfied, "Query cannot be satisfied!", expandedStates, exploredStates, transitionFired, states.getCountRemove()); }
ReachabilityResult MagicSearch::reachable(const PetriNet &net, const MarkVal *m0, const VarVal *v0, PQL::Condition *query){ SmartStateAllocator<MEMORY_BOUND> allocator(net); SmartStateSet states(net); EnhancedPriorityQueue<Step> queue; _dm = new Structures::DistanceMatrix(net); { //Compute constraints ConstraintAnalysisContext context(net); query->findConstraints(context); if(context.canAnalyze) contraints = context.retval; } //Create s0 SmartState* s0 = allocator.createStoredState(); memcpy(s0->marking(), m0, sizeof(MarkVal) * net.numberOfPlaces()); memcpy(s0->valuation(), v0, sizeof(VarVal) * net.numberOfVariables()); states.add(s0, s0->marking(), s0->valuation()); Step step0; step0.depth = 0; step0.lastApprox = INT_MAX; step0.lastStored = 0; step0.state = s0; queue.push(0, step0); //Temporary marking and valuation to work with MarkVal tmpM[net.numberOfPlaces()]; VarVal tmpV[net.numberOfVariables()]; SmartState* ns = allocator.createStoredState(); SmartState* ls = allocator.createState(); //Statistics int lastReport = 0; BigInt expanded = 0, explored = 0; size_t max = 1; //Main loop while(!queue.empty()){ // Report progress if needed if(lastReport++ & 1<<17){ lastReport = 0; if(queue.size() > max) max = queue.size(); this->reportProgress((double)(max - queue.size()) / ((double)(max))); if(this->abortRequested()) return ReachabilityResult(ReachabilityResult::Unknown, "Query aborted!"); } //Pop stuff of the queue Step step = queue.pop(depthFirst); expanded++; //Cound expanded states // Get current state const MarkVal* m; const VarVal* v; if(step.state->stored()){ m = step.state->marking(); v = step.state->valuation(); }else{ step.state->getState(net, tmpM, tmpV); m = tmpM; v = tmpV; } //Attempt to exclude by over-approx if(step.lastApprox >= approxScale(step.depth)){ if(canExcludeByOverApprox(net, m, v)) continue; step.lastApprox = 0; } for(unsigned int t = 0; t < net.numberOfTransitions(); t++){ //Fire the transition if(net.fire(t, m, v, ns->marking(), ns->valuation())){ //Determine whether or not to store the entire state bool storeCurrentState = step.lastStored >= storeScale(allocator.percentMemoryUsed());// storeScale(allocator.percentMemoryUsed()); SmartState* storeState; if(storeCurrentState) storeState = ns; else storeState = ls; storeState->setParent(step.state); storeState->setTransition(t); //Add it to the state set if(states.add(storeState, ns->marking(), ns->valuation())){ explored++; //Count explored states //Test the query if(query->evaluate(EvaluationContext(ns->marking(), ns->valuation()))){ printf("\nmemory usage: %f\n",allocator.percentMemoryUsed()); return ReachabilityResult(ReachabilityResult::Satisfied, "Query was satified!", expanded, explored, storeState->pathLength(), storeState->trace()); } //Make the next step Step nextstep; nextstep.depth = step.depth + 1; nextstep.lastApprox = step.lastApprox + 1; if(storeState == ns) nextstep.lastStored = 0; else nextstep.lastStored = step.lastStored + 1; nextstep.state = storeState; //Push step on the queue double p = priority(ns->marking(), ns->valuation(), query, net); queue.push(p, nextstep); //Allocate new memory, depending on what was stored if(storeState == ns) ns = allocator.createStoredState(); else ls = allocator.createState(); } } } } return ReachabilityResult(ReachabilityResult::NotSatisfied, "Query cannot be satisfied!", expanded, explored); }