~tapaal-ltl/verifypn/fire-count-heuristic

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
}