~tapaal-ltl/verifypn/rule-D-fix

« back to all changes in this revision

Viewing changes to PetriEngine/Reachability/RandomDFS.cpp

  • Committer: Jonas Finnemann Jensen
  • Date: 2011-09-15 13:30:00 UTC
  • Revision ID: jopsen@gmail.com-20110915133000-wnywm1odf82emiuw
Import of sources from github

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>,
 
5
 * 
 
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.
 
10
 * 
 
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.
 
15
 * 
 
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/>.
 
18
 */
 
19
#include "RandomDFS.h"
 
20
#include "../PQL/PQL.h"
 
21
#include "../PQL/Contexts.h"
 
22
#include "../Structures/StateSet.h"
 
23
#include "../Structures/LimitedStateAllocator.h"
 
24
 
 
25
#include <list>
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
#include <stdio.h>
 
29
#include <time.h>
 
30
 
 
31
using namespace PetriEngine::PQL;
 
32
using namespace PetriEngine::Structures;
 
33
 
 
34
namespace PetriEngine{ namespace Reachability {
 
35
 
 
36
ReachabilityResult RandomDFS::reachable(const PetriNet &net,
 
37
                                                                                const MarkVal *m0,
 
38
                                                                                const VarVal *v0,
 
39
                                                                                PQL::Condition *query){
 
40
        //Do we initially satisfy query?
 
41
        if(query && query->evaluate(PQL::EvaluationContext(m0, v0)))
 
42
                return ReachabilityResult(ReachabilityResult::Satisfied,
 
43
                                                                  "A state satisfying the query was found");
 
44
 
 
45
        StateSet states(net);
 
46
        LimitedStateAllocator<> allocator(net, _memorylimit);
 
47
        std::list<State*> stack;
 
48
        srand(time(0)); // Chosen by fair dice roll
 
49
 
 
50
        State* s0 = allocator.createState();
 
51
        if(!s0)
 
52
                return ReachabilityResult(ReachabilityResult::Unknown,
 
53
                                                                   "Memory bound exceeded");
 
54
        memcpy(s0->marking(), m0, sizeof(MarkVal)*net.numberOfPlaces());
 
55
        memcpy(s0->valuation(), v0, sizeof(VarVal)*net.numberOfVariables());
 
56
 
 
57
        stack.push_back(s0);
 
58
        states.add(s0);
 
59
        State* ns = allocator.createState();
 
60
        if(!ns)
 
61
                return ReachabilityResult(ReachabilityResult::Unknown,
 
62
                                                                   "Memory bound exceeded");
 
63
 
 
64
        int countdown = rand() % 800000;
 
65
        unsigned int max = 0;
 
66
        int count = 0;
 
67
        BigInt exploredStates = 0;
 
68
        BigInt expandedStates = 0;
 
69
        State* s = s0;
 
70
        while(!stack.empty()){
 
71
                // Progress reporting and abort checking
 
72
                if(count++ & 1<<17){
 
73
                        if(stack.size() > max)
 
74
                                max = stack.size();
 
75
                        count = 0;
 
76
                        // Report progress
 
77
                        reportProgress((double)(max - stack.size())/(double)max);
 
78
                        // Check abort
 
79
                        if(abortRequested())
 
80
                                return ReachabilityResult(ReachabilityResult::Unknown,
 
81
                                                                                "Search was aborted.");
 
82
                }
 
83
 
 
84
                s = stack.back();
 
85
                stack.pop_back();
 
86
 
 
87
                //Hack for when query is null and we're look to print a random state
 
88
                if(!query && countdown-- <= 0){
 
89
                        //TODO: Remove this hack or copy the code for random state generation, if we need that feature...
 
90
                        printf("%s == %i ", net.placeNames()[0].c_str(), s->marking()[0]);
 
91
                        for(int p = 1; p < net.numberOfPlaces(); p++)
 
92
                                printf(" and %s == %i ", net.placeNames()[p].c_str(), s->marking()[p]);
 
93
                        for(int x = 0; x < net.numberOfVariables(); x++)
 
94
                                printf(" and %s == %i ", net.variableNames()[x].c_str(), s->valuation()[x]);
 
95
                        return ReachabilityResult();
 
96
                }
 
97
 
 
98
                State* succ[net.numberOfTransitions()];
 
99
                memset(succ, 0, net.numberOfTransitions()*sizeof(State*));
 
100
                for(unsigned int t = 0; t < net.numberOfTransitions(); t++){
 
101
                        if(net.fire(t, s, ns, 1, _kbound)){
 
102
                                if(states.add(ns)){
 
103
                                        exploredStates++;
 
104
                                        ns->setParent(s);
 
105
                                        ns->setTransition(t);
 
106
                                        if(query && query->evaluate(*ns))
 
107
                                                return ReachabilityResult(ReachabilityResult::Satisfied,
 
108
                                                                                                "A state satisfying the query was found", expandedStates, exploredStates, ns->pathLength(), ns->trace());
 
109
                                        succ[t] = ns;
 
110
                                        ns = allocator.createState();
 
111
                                        if(!ns)
 
112
                                                return ReachabilityResult(ReachabilityResult::Unknown,
 
113
                                                                                                   "Memory bound exceeded",
 
114
                                                                                                   expandedStates, exploredStates);
 
115
                                }
 
116
                        }
 
117
                }
 
118
                // Randomly sorts states into the stack
 
119
                expandedStates++;
 
120
                int random;
 
121
                int t;
 
122
                do {
 
123
                        random = rand() % net.numberOfTransitions();
 
124
                        t = random;
 
125
                        do{
 
126
                                if(succ[t]){
 
127
                                        stack.push_back(succ[t]);
 
128
                                        succ[t] = NULL;
 
129
                                        t++;
 
130
                                        break;
 
131
                                }
 
132
                                t = (t+1) % net.numberOfTransitions();
 
133
                        } while(t != random);
 
134
                } while(t != random);
 
135
        }
 
136
 
 
137
        //Hack for when query is null and we're look to print a random state
 
138
        if(!query){
 
139
                printf("%s == %i ", net.placeNames()[0].c_str(), s->marking()[0]);
 
140
                        for(int p = 1; p < net.numberOfPlaces(); p++)
 
141
                                printf(" and %s == %i ", net.placeNames()[p].c_str(), s->marking()[p]);
 
142
                        for(int x = 0; x < net.numberOfVariables(); x++)
 
143
                                printf(" and %s == %i ", net.variableNames()[x].c_str(), s->valuation()[x]);
 
144
        }
 
145
 
 
146
 
 
147
        return ReachabilityResult(ReachabilityResult::NotSatisfied,
 
148
                                                "No state satisfying the query exists.", expandedStates, exploredStates);
 
149
}
 
150
 
 
151
}} // Namespaces