1
/* PeTe - Petri Engine exTremE
2
* Copyright (C) 2011 Jonas Finnemann Jensen <jopsen@gmail.com>,
3
* Thomas Søndersø Nielsen <primogens@gmail.com>,
4
* Lars Kærlund Østergaard <larsko@gmail.com>,
6
* This program is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#include "UltimateSearch.h"
21
#include "../Structures/EnhancedPriorityQueue.h"
22
#include "../Structures/StateSet.h"
23
#include "../Structures/LimitedStateAllocator.h"
24
#include "../PQL/Contexts.h"
25
#include "../Structures/DistanceMatrix.h"
29
using namespace PetriEngine::Structures;
30
using namespace PetriEngine::PQL;
32
/** Define memory bound for ultimate search strategy */
33
#define ULTIMATE_MEMORY_BOUND 1024*1024*1024
35
namespace PetriEngine{
36
namespace Reachability{
38
ReachabilityResult UltimateSearch::reachable(const PetriNet &net,
41
PQL::Condition *query){
42
// Test if it initally satisfied
44
if(query->evaluate(EvaluationContext(m0, v0)))
45
return ReachabilityResult(ReachabilityResult::Satisfied, "Satisifed initially", 0, 0, 0);
48
// Attempt to exclude by over-approx
50
ConstraintAnalysisContext context(net);
51
query->findConstraints(context);
52
if(context.canAnalyze){
53
bool isImpossible = true;
54
for(size_t i = 0; i < context.retval.size(); i++){
55
isImpossible &= context.retval[i]->isImpossible(net, m0, v0);
56
if(!isImpossible) break;
59
return ReachabilityResult(ReachabilityResult::NotSatisfied,
60
"Excluded by over-approximation",
65
// Create allocator, stateset and queue
66
LimitedStateAllocator<> allocator(net, _memorylimit);
68
EnhancedPriorityQueue<State*> queue;
74
s0.setMarking(const_cast<MarkVal*>(m0));
75
s0.setValuation(const_cast<VarVal*>(v0));
82
BigInt expanded = 0, explored = 0;
86
State* ns = allocator.createState();
88
DistanceContext::DistanceStrategy flags = (DistanceContext::DistanceStrategy)(DistanceContext::AndSum | DistanceContext::OrExtreme);
91
while(!queue.empty()){
95
if(queue.size() > max)
97
this->reportProgress((double)(max - queue.size()) / ((double)(max)));
98
if(this->abortRequested())
99
return ReachabilityResult(ReachabilityResult::Unknown,
104
State* s = queue.pop(depthFirst);
107
// Try firing each transition
108
for(unsigned int t = 0; t < net.numberOfTransitions(); t++){
109
if(net.fire(t, s, ns, 1, _kbound) && states.add(ns)){
113
ns->setTransition(t);
116
if(query->evaluate(*ns)){
117
return ReachabilityResult(ReachabilityResult::Satisfied,
118
"Query was satisfied",
119
expanded, explored, ns->pathLength(), ns->trace());
122
// Push new state on the queue
123
DistanceContext context(net,
128
queue.push(query->distance(context), ns);
130
// Allocate new state, abort if not possible
131
ns = allocator.createState();
133
return ReachabilityResult(ReachabilityResult::Unknown,
134
"Memory bound exceeded",
140
return ReachabilityResult(ReachabilityResult::NotSatisfied,
141
"Query cannot be satisfied",