252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
1 |
/* Copyright (C) 2020 Nikolaj J. Ulrik <nikolaj@njulrik.dk>,
|
2 |
* Simon M. Virenfeldt <simon@simwir.dk>
|
|
3 |
*
|
|
4 |
* This program is free software: you can redistribute it and/or modify
|
|
5 |
* it under the terms of the GNU General Public License as published by
|
|
6 |
* the Free Software Foundation, either version 3 of the License, or
|
|
7 |
* (at your option) any later version.
|
|
8 |
*
|
|
9 |
* This program is distributed in the hope that it will be useful,
|
|
10 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12 |
* GNU General Public License for more details.
|
|
13 |
*
|
|
14 |
* You should have received a copy of the GNU General Public License
|
|
15 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16 |
*/
|
|
17 |
||
18 |
#include "LTL/LTL.h" |
|
19 |
#include "LTL/LTLMain.h" |
|
20 |
#include "PetriEngine/PQL/PQL.h" |
|
21 |
#include "PetriEngine/PQL/Expressions.h" |
|
256.2.1
by Nikolaj Jensen Ulrik
WIP Resuming stubborn tarjan model checker |
22 |
#include "LTL/Algorithm/ResumingStubbornTarjan.h" |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
23 |
|
24 |
#include "LTL/SuccessorGeneration/Spoolers.h" |
|
25 |
#include "LTL/SuccessorGeneration/Heuristics.h" |
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
26 |
|
27 |
#include <utility> |
|
28 |
||
29 |
using namespace PetriEngine::PQL; |
|
30 |
||
257
by Simon Virenfeldt
Add debug explored states print |
31 |
#define DEBUG_EXPLORED_STATES
|
32 |
||
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
33 |
namespace LTL { |
34 |
struct Result { |
|
35 |
bool satisfied = false; |
|
36 |
bool is_weak = true; |
|
37 |
Algorithm algorithm = Algorithm::Tarjan; |
|
257
by Simon Virenfeldt
Add debug explored states print |
38 |
#ifdef DEBUG_EXPLORED_STATES
|
39 |
size_t explored_states = 0; |
|
40 |
#endif
|
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
41 |
};
|
42 |
||
43 |
/**
|
|
44 |
* Converts a formula on the form A f, E f or f into just f, assuming f is an LTL formula.
|
|
45 |
* In the case E f, not f is returned, and in this case the model checking result should be negated
|
|
46 |
* (indicated by bool in return value)
|
|
47 |
* @param formula - a formula on the form A f, E f or f
|
|
48 |
* @return @code(ltl_formula, should_negate) - ltl_formula is the formula f if it is a valid LTL formula, nullptr otherwise.
|
|
49 |
* should_negate indicates whether the returned formula is negated (in the case the parameter was E f)
|
|
50 |
*/
|
|
256.1.1
by Nikolaj Jensen Ulrik
WIP automaton stubborn set |
51 |
std::pair<Condition_ptr, bool> to_ltl(const Condition_ptr &formula) |
52 |
{
|
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
53 |
LTL::LTLValidator validator; |
54 |
bool should_negate = false; |
|
55 |
Condition_ptr converted; |
|
56 |
if (auto _formula = dynamic_cast<ECondition *>(formula.get())) { |
|
57 |
converted = std::make_shared<NotCondition>((*_formula)[0]); |
|
58 |
should_negate = true; |
|
59 |
} else if (auto _formula = dynamic_cast<ACondition *>(formula.get())) { |
|
60 |
converted = (*_formula)[0]; |
|
61 |
} else { |
|
62 |
converted = formula; |
|
63 |
}
|
|
64 |
converted->visit(validator); |
|
65 |
if (validator.bad()) { |
|
66 |
converted = nullptr; |
|
67 |
}
|
|
68 |
return std::make_pair(converted, should_negate); |
|
69 |
}
|
|
70 |
||
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
71 |
template<typename Checker> |
72 |
Result _verify(const PetriNet *net, |
|
73 |
Condition_ptr &negatedQuery, |
|
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
74 |
std::unique_ptr<Checker> checker, |
256.1.13
by Simon Virenfeldt
Merge lp:~tapaal-ltl/verifypn/ltl-model-checker@257 |
75 |
const options_t &options) |
256.1.1
by Nikolaj Jensen Ulrik
WIP automaton stubborn set |
76 |
{
|
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
77 |
Result result; |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
78 |
|
79 |
/*
|
|
80 |
std::unique_ptr<Checker> modelChecker;
|
|
81 |
if constexpr (std::is_same_v<Checker, TarjanModelChecker<SpoolingSuccessorGenerator, true>> ||
|
|
82 |
std::is_same_v<Checker, TarjanModelChecker<SpoolingSuccessorGenerator, false>>) {
|
|
83 |
||
84 |
} else {
|
|
85 |
modelChecker = std::make_unique<Checker>(*net, negatedQuery, options.trace, options.ltluseweak);
|
|
86 |
}
|
|
87 |
*/
|
|
88 |
||
89 |
result.satisfied = checker->isSatisfied(); |
|
90 |
result.is_weak = checker->isweak(); |
|
257
by Simon Virenfeldt
Add debug explored states print |
91 |
#ifdef DEBUG_EXPLORED_STATES
|
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
92 |
result.explored_states = checker->get_explored(); |
257
by Simon Virenfeldt
Add debug explored states print |
93 |
#endif
|
256.1.13
by Simon Virenfeldt
Merge lp:~tapaal-ltl/verifypn/ltl-model-checker@257 |
94 |
if (options.printstatistics) { |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
95 |
checker->printStats(std::cout); |
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
96 |
}
|
97 |
return result; |
|
98 |
}
|
|
99 |
||
100 |
ReturnValue LTLMain(const PetriNet *net, |
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
101 |
const Condition_ptr &query, |
102 |
const std::string &queryName, |
|
256.1.1
by Nikolaj Jensen Ulrik
WIP automaton stubborn set |
103 |
const options_t &options) |
104 |
{
|
|
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
105 |
auto res = to_ltl(query); |
106 |
Condition_ptr negated_formula = res.first; |
|
107 |
bool negate_answer = res.second; |
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
108 |
|
109 |
if (options.stubbornreduction && options.ltlalgorithm != Algorithm::Tarjan) { |
|
110 |
std::cerr << "Error: Stubborn reductions only supported for Tarjan's algorithm" << std::endl; |
|
111 |
return ErrorCode; |
|
112 |
}
|
|
113 |
||
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
114 |
Structures::BuchiAutomaton automaton = makeBuchiAutomaton(negated_formula); |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
115 |
bool hasinhib = net->has_inhibitor(); |
116 |
||
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
117 |
Result result; |
118 |
switch (options.ltlalgorithm) { |
|
119 |
case Algorithm::NDFS: |
|
256.3.2
by Nikolaj Jensen Ulrik
Merge ltl-model-checker + WIP work on resuming tarjan, near correct? |
120 |
if (options.trace != TraceLevel::None) { |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
121 |
result = _verify(net, negated_formula, |
122 |
std::make_unique<NestedDepthFirstSearch<PetriEngine::Structures::TracableStateSet>>( |
|
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
123 |
*net, negated_formula, automaton, options.trace, options.ltluseweak), options); |
256.1.9
by Simon Virenfeldt
Fix compile errors from merge |
124 |
} else { |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
125 |
result = _verify(net, negated_formula, |
126 |
std::make_unique<NestedDepthFirstSearch<PetriEngine::Structures::StateSet>>( |
|
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
127 |
*net, negated_formula, automaton, options.trace, options.ltluseweak), options); |
256.3.2
by Nikolaj Jensen Ulrik
Merge ltl-model-checker + WIP work on resuming tarjan, near correct? |
128 |
}
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
129 |
break; |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
130 |
case Algorithm::RandomNDFS: { |
131 |
SpoolingSuccessorGenerator gen{*net, negated_formula}; |
|
132 |
gen.setSpooler(std::make_unique<EnabledSpooler>(net, gen)); |
|
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
133 |
gen.setHeuristic(std::make_unique<RandomHeuristic>()); |
134 |
||
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
135 |
result = _verify(net, negated_formula, |
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
136 |
std::make_unique<RandomNDFS>(*net, negated_formula, automaton, std::move(gen), options.trace, |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
137 |
options.ltluseweak), |
138 |
options); |
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
139 |
break; |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
140 |
}
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
141 |
case Algorithm::Tarjan: |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
142 |
if (options.strategy != PetriEngine::Reachability::DEFAULT || |
143 |
(!hasinhib && options.stubbornreduction && !negated_formula->containsNext())) { |
|
144 |
// Use spooling successor generator in case of different search strategy or stubborn set method.
|
|
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
145 |
SpoolingSuccessorGenerator gen{*net, negated_formula}; |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
146 |
if (!hasinhib && options.stubbornreduction && !negated_formula->containsNext()) { |
147 |
std::cout << "Running stubborn version!" << std::endl; |
|
148 |
||
149 |
gen.setSpooler(std::make_unique<InterestingLTLStubbornSet>(*net, negated_formula)); |
|
150 |
}
|
|
269
by Nikolaj Jensen Ulrik
Ensure spooler gets set |
151 |
else { |
152 |
gen.setSpooler(std::make_unique<EnabledSpooler>(net, gen)); |
|
153 |
}
|
|
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
154 |
if (options.strategy == PetriEngine::Reachability::RDFS) { |
155 |
gen.setHeuristic(std::make_unique<RandomHeuristic>()); |
|
156 |
} else if (options.strategy == PetriEngine::Reachability::HEUR) { |
|
271
by Simon Virenfeldt
Implemented fire count heuristic |
157 |
//gen.setHeuristic(std::make_unique<AutomatonHeuristic>(net, automaton));
|
158 |
gen.setHeuristic(std::make_unique<FireCountHeuristic>(net)); |
|
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
159 |
}
|
160 |
||
161 |
if (options.trace != TraceLevel::None) { |
|
162 |
result = _verify(net, negated_formula, |
|
163 |
std::make_unique<TarjanModelChecker<SpoolingSuccessorGenerator, true>>( |
|
164 |
*net, |
|
165 |
negated_formula, |
|
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
166 |
automaton, |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
167 |
std::move(gen), |
168 |
options.trace, |
|
169 |
options.ltluseweak), |
|
170 |
options); |
|
171 |
} else { |
|
172 |
result = _verify(net, negated_formula, |
|
173 |
std::make_unique<TarjanModelChecker<SpoolingSuccessorGenerator, false>>( |
|
174 |
*net, |
|
175 |
negated_formula, |
|
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
176 |
automaton, |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
177 |
std::move(gen), |
178 |
options.trace, |
|
179 |
options.ltluseweak), |
|
180 |
options); |
|
181 |
}
|
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
182 |
} else { |
267
by Nikolaj Jensen Ulrik
LTL engine now allows combination of stubborn sets and heuristics |
183 |
// no spooling needed, thus use resuming successor generation
|
256.3.2
by Nikolaj Jensen Ulrik
Merge ltl-model-checker + WIP work on resuming tarjan, near correct? |
184 |
if (options.trace != TraceLevel::None) { |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
185 |
result = _verify(net, negated_formula, |
186 |
std::make_unique<TarjanModelChecker<ResumingSuccessorGenerator, true>>( |
|
187 |
*net, |
|
188 |
negated_formula, |
|
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
189 |
automaton, |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
190 |
ResumingSuccessorGenerator{*net}, |
191 |
options.trace, |
|
192 |
options.ltluseweak), |
|
193 |
options); |
|
256.1.7
by Nikolaj Jensen Ulrik
misc changes |
194 |
} else { |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
195 |
result = _verify(net, negated_formula, |
196 |
std::make_unique<TarjanModelChecker<ResumingSuccessorGenerator, false>>( |
|
197 |
*net, |
|
198 |
negated_formula, |
|
270
by Nikolaj Jensen Ulrik
WIP Büchi guided search |
199 |
automaton, |
266
by Nikolaj Jensen Ulrik
Functioning spooling successor generator |
200 |
ResumingSuccessorGenerator{*net}, |
201 |
options.trace, |
|
202 |
options.ltluseweak), |
|
203 |
options); |
|
256.1.1
by Nikolaj Jensen Ulrik
WIP automaton stubborn set |
204 |
}
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
205 |
}
|
206 |
break; |
|
207 |
case Algorithm::None: |
|
208 |
assert(false); |
|
209 |
std::cerr << "Error: cannot LTL verify with algorithm None"; |
|
210 |
}
|
|
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
211 |
std::cout << "FORMULA " << queryName |
212 |
<< (result.satisfied ^ negate_answer ? " TRUE" : " FALSE") << " TECHNIQUES EXPLICIT " |
|
213 |
<< LTL::to_string(options.ltlalgorithm) |
|
214 |
<< (result.is_weak ? " WEAK_SKIP" : "") |
|
215 |
<< ((options.stubbornreduction && !negated_formula->containsNext()) ? " STUBBORN" : "") |
|
216 |
<< std::endl; |
|
257
by Simon Virenfeldt
Add debug explored states print |
217 |
#ifdef DEBUG_EXPLORED_STATES
|
218 |
std::cout << "FORMULA " << queryName << " STATS EXPLORED " << result.explored_states << std::endl; |
|
219 |
#endif
|
|
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
220 |
/*(queries[qid]->isReachability(0) ? " REACHABILITY" : "") <<*/
|
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
221 |
|
253
by Nikolaj Jensen Ulrik
Broken LTL stubborn set implementation |
222 |
return SuccessCode; |
252
by Nikolaj Jensen Ulrik
Refactor LTLMain, add template parameter to ModelChecker, fix bugs in stubborn set refactor |
223 |
}
|
256.1.4
by Nikolaj Jensen Ulrik
Some refactoring to support multiple stubborn set methods |
224 |
}
|