mCRL2
Loading...
Searching...
No Matches
pbessolve.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink; Threads are added by Jan Friso Groote
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
12
13#ifndef MCRL2_PBES_TOOLS_PBESSOLVE_H
14#define MCRL2_PBES_TOOLS_PBESSOLVE_H
15
20#include "mcrl2/lps/io.h"
24
25using namespace mcrl2;
26using namespace mcrl2::pbes_system;
27using namespace mcrl2::utilities::tools;
32
33// TODO: put this code in the utilities library?
34inline std::string file_extension(const std::string& filename)
35{
36 auto pos = filename.find_last_of('.');
37 if (pos == std::string::npos)
38 {
39 return "";
40 }
41 return filename.substr(pos + 1);
42}
43
45 : public parallel_tool<rewriter_tool<pbes_input_tool<input_tool>>>
46{
47 protected:
49
51 std::string lpsfile;
52 std::string ltsfile;
53 std::string evidence_file;
54
55 void add_options(utilities::interface_description& desc) override
56 {
58 desc.add_hidden_option("check-strategy",
59 "do a sanity check on the computed strategy", 'c');
60 desc.add_option("search-strategy",
61 utilities::make_enum_argument<search_strategy>("NAME")
62 .add_value_desc(breadth_first,
63 "Leads to smaller counter examples",
64 true)
65 .add_value_desc(depth_first, ""),
66 "Use search strategy NAME:", 'z');
67 desc.add_option("file", utilities::make_file_argument("NAME"),
68 "The file containing the LPS or LTS that was used to "
69 "generate the PBES using lps2pbes -c. If this "
70 "option is set, a counter example or witness for the "
71 "encoded property will be generated. The "
72 "extension of the file should be .lps in case of an LPS "
73 "file, in all other cases it is assumed to "
74 "be an LTS.",
75 'f');
76 desc.add_option("prune-todo-list", "Prune the todo list periodically.");
77 desc.add_hidden_option("no-remove-unused-rewrite-rules",
78 "do not remove unused rewrite rules. ", 'u');
79 desc.add_option("evidence-file", utilities::make_file_argument("NAME"),
80 "The file to which the evidence is written. If not set, a "
81 "default name will be chosen.");
82 desc.add_option(
83 "solve-strategy",
84 utilities::make_enum_argument<int>("NAME")
85 .add_value_desc(0, "No on-the-fly solving is applied", true)
86 .add_value_desc(1, "Propagate solved equations using an attractor.")
87 .add_value_desc(2, "Detect winning loops.")
88 .add_value_desc(3, "Solve subgames using a fatal attractor.")
89 .add_value_desc(4, "Solve subgames using the solver."),
90 "Use solve strategy NAME. Strategies 1-4 periodically apply on-the-fly "
91 "solving, which may lead to early termination.",
92 's');
93 desc.add_hidden_option(
94 "long-strategy",
95 utilities::make_enum_argument<int>("STRATEGY")
96 .add_value_desc(0, "Do not apply any optimizations.")
97 .add_value_desc(1, "Remove self loops.")
98 .add_value_desc(2, "Propagate solved equations using substitution.")
99 .add_value_desc(3, "Propagate solved equations using an attractor.")
100 .add_value_desc(4, "Detect winning loops using a fatal attractor.")
101 .add_value_desc(
102 5, "Solve subgames using a fatal attractor (local version).")
103 .add_value_desc(
104 6, "Solve subgames using a fatal attractor (original version).")
105 .add_value_desc(7, "Solve subgames using the solver.")
106 .add_value_desc(8, "Detect winning loops (original version)."
107 " N.B. This optimization does not work "
108 "correctly in combination with counter examples."
109 " It may also cause stack overflow."),
110 "use strategy STRATEGY (N.B. This is a developer option that overrides "
111 "--strategy)",
112 'l');
113 desc.add_hidden_option(
114 "no-replace-constants-by-variables",
115 "Do not move constant expressions to a substitution.");
116 desc.add_hidden_option("aggressive",
117 "Apply optimizations 4 and 5 at every iteration.");
118 desc.add_hidden_option("prune-todo-alternative",
119 "Use a variation of todo list pruning.");
120 }
121
122 void parse_options(const utilities::command_line_parser& parser) override
123 {
124 super::parse_options(parser);
125
126 options.check_strategy = parser.has_option("check-strategy");
128 !parser.has_option("no-replace-constants-by-variables");
130 !parser.has_option("no-remove-unused-rewrite-rules");
131 options.aggressive = parser.has_option("aggressive");
132 options.prune_todo_list = parser.has_option("prune-todo-list");
134 parser.has_option("prune-todo-alternative");
136 parser.option_argument_as<mcrl2::pbes_system::search_strategy>(
137 "search-strategy");
138 options.rewrite_strategy = rewrite_strategy();
140
141
142 if (parser.has_option("file"))
143 {
144 std::string filename = parser.option_argument("file");
145 if (file_extension(filename) == "lps")
146 {
147 lpsfile = filename;
148 }
149 else
150 {
151 ltsfile = filename;
152 }
153 }
154
155 if (parser.has_option("evidence-file"))
156 {
157 if (!parser.has_option("file"))
158 {
160 "Option --evidence-file cannot be used without option --file");
161 }
162 evidence_file = parser.option_argument("evidence-file");
163 }
164
165 if (parser.has_option("long-strategy"))
166 {
167 options.optimization = parser.option_argument_as<int>("long-strategy");
168 }
169 else
170 {
171 options.optimization = parser.option_argument_as<int>("solve-strategy");
172 if (options.optimization == 0)
173 {
175 }
176 else if (options.optimization == 1)
177 {
179 }
180 else if (options.optimization == 2)
181 {
183 }
184 else if (options.optimization == 3)
185 {
187 }
188 else if (options.optimization == 4)
189 {
191 }
192 }
193
195 {
196 throw mcrl2::runtime_error("Invalid strategy " +
197 std::to_string(options.optimization));
198 }
200 {
201 mCRL2log(log::warning) << "Option --prune-todo-list has no effect for "
202 "strategies less than 2."
203 << std::endl;
204 }
206 {
207 throw mcrl2::runtime_error("Strategy " + std::to_string(options.optimization) + " can only be used in single thread mode.");
208 }
209 }
210
211 std::set<utilities::file_format> available_input_formats() const override
212 {
213 return {pbes_system::pbes_format_internal()};
214 }
215
216 public:
217 pbessolve_tool(const std::string& toolname)
218 : super(toolname, "Wieger Wesselink",
219 "Generate a BES from a PBES and solve it. ",
220 "Solves (P)BES from INFILE. "
221 "If INFILE is not present, stdin is used. "
222 "The PBES is first instantiated into a parity game, "
223 "which is then solved using Zielonka's algorithm. "
224 "It supports the generation of a witness or counter "
225 "example for the property encoded by the PBES.")
226 {
227 }
228
229 template <typename PbesInstAlgorithm>
230 void run_algorithm(PbesInstAlgorithm& algorithm, pbes_system::pbes& pbesspec,
233 {
234 mCRL2log(log::verbose) << "Generating parity game..." << std::endl;
235 timer().start("instantiation");
236 algorithm.run();
237 timer().finish("instantiation");
238
239 mCRL2log(log::verbose) << "Number of vertices in the structure graph: "
240 << G.all_vertices().size() << std::endl;
241
242 if ((!lpsfile.empty() || !ltsfile.empty()) &&
244 {
246 << "Warning: the PBES has no counter example information. Did you "
247 "use the"
248 " --counter-example option when generating the PBES?"
249 << std::endl;
250 }
251
252 if (!lpsfile.empty())
253 {
254 lps::specification lpsspec;
255 lps::load_lps(lpsspec, lpsfile);
256 lps::detail::replace_global_variables(lpsspec, sigma);
257
258 bool result;
259 lps::specification evidence;
260 timer().start("solving");
261 std::tie(result, evidence) = solve_structure_graph_with_counter_example(
262 G, lpsspec, pbesspec, algorithm.equation_index());
263 timer().finish("solving");
264 std::cout << (result ? "true" : "false") << std::endl;
265 if (evidence_file.empty())
266 {
267 evidence_file = input_filename() + ".evidence.lps";
268 }
269 lps::save_lps(evidence, evidence_file);
271 << "Saved " << (result ? "witness" : "counter example") << " in "
272 << evidence_file << std::endl;
273 }
274 else if (!ltsfile.empty())
275 {
276 lts::lts_lts_t ltsspec;
277 ltsspec.load(ltsfile);
278 lts::lts_lts_t evidence;
279 timer().start("solving");
280 bool result = solve_structure_graph_with_counter_example(G, ltsspec);
281 timer().finish("solving");
282 std::cout << (result ? "true" : "false") << std::endl;
283 if (evidence_file.empty())
284 {
285 evidence_file = input_filename() + ".evidence.lts";
286 }
287 ltsspec.save(evidence_file);
289 << "Saved " << (result ? "witness" : "counter example") << " in "
290 << evidence_file << std::endl;
291 }
292 else
293 {
294 timer().start("solving");
296 timer().finish("solving");
297 std::cout << (result ? "true" : "false") << std::endl;
298 }
299 }
300
301 bool run() override
302 {
303 pbes_system::pbes pbesspec =
304 pbes_system::detail::load_pbes(input_filename());
307
308 if (!lpsfile.empty())
309 {
310 // Make sure that the global variables of the LPS and the PBES get the
311 // same values
312 sigma = pbes_system::detail::instantiate_global_variables(pbesspec);
313 pbes_system::detail::replace_global_variables(pbesspec, sigma);
314 }
315
317 if (options.optimization <= 1)
318 {
319 pbesinst_structure_graph_algorithm algorithm(options, pbesspec, G);
320 run_algorithm<pbesinst_structure_graph_algorithm>(algorithm, pbesspec, G,
321 sigma);
322 }
323 else
324 {
325 pbesinst_structure_graph_algorithm2 algorithm(options, pbesspec, G);
326 run_algorithm<pbesinst_structure_graph_algorithm2>(algorithm, pbesspec, G,
327 sigma);
328 }
329 return true;
330 }
331};
332
333#endif // MCRL2_PBES_TOOLS_PBESSOLVE_H
std::size_t size() const
Definition vector.h:329
Generic substitution function. The substitution is stored as a mapping of variables to expressions....
Base class for tools that use a rewriter.
Linear process specification.
This class contains labelled transition systems in .lts format.
Definition lts_lts.h:378
void save(const std::string &filename) const
Save the labelled transition system to file.
void load(const std::string &filename)
Load the labelled transition system from file.
parameterized boolean equation system
Definition pbes.h:58
Adds an optimization to pbesinst_structure_graph.
Variant of pbesinst that will compute a structure graph for a PBES. The result will be put in the str...
const vertex_vector & all_vertices() const
Base class for filter tools that take a pbes as input.
Standard exception class for reporting runtime errors.
Definition exception.h:27
Base class for tools that take a file as input.
Definition input_tool.h:28
Base class for tools that are using multiple threads.
void add_options(utilities::interface_description &desc)
Add the –threads option to an interface description.
void parse_options(const utilities::command_line_parser &parser)
Parse non-standard options.
std::size_t number_of_threads() const
Returns the number of threads in this tool.
std::set< utilities::file_format > available_input_formats() const override
Definition pbessolve.h:211
std::string ltsfile
Definition pbessolve.h:52
void add_options(utilities::interface_description &desc) override
Definition pbessolve.h:55
pbessolve_tool(const std::string &toolname)
Definition pbessolve.h:217
std::string lpsfile
Definition pbessolve.h:51
std::string evidence_file
Definition pbessolve.h:53
pbessolve_options options
Definition pbessolve.h:50
void run_algorithm(PbesInstAlgorithm &algorithm, pbes_system::pbes &pbesspec, structure_graph &G, const data::mutable_map_substitution<> &sigma)
Definition pbessolve.h:230
bool run() override
Definition pbessolve.h:301
parallel_tool< rewriter_tool< pbes_input_tool< input_tool > > > super
Definition pbessolve.h:48
void parse_options(const utilities::command_line_parser &parser) override
Definition pbessolve.h:122
Base class for tools that take a file as input, and write the results to a file.
static RewriterCompilingJitty::substitution_type & sigma(RewriterCompilingJitty *this_rewriter)
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
add your file description here.
IO routines for linear process specifications.
@ warning
Definition logger.h:34
@ verbose
Definition logger.h:37
void normalize(pbes &x)
The function normalize brings (embedded) pbes expressions into positive normal form,...
The main namespace for the PBES library.
Definition absinthe.h:28
bool solve_structure_graph(structure_graph &G, bool check_strategy=false)
search_strategy
Search strategy when generating a BES from a PBES.
bool has_counter_example_information(const pbes &pbesspec)
Guesses if a pbes has counter example information.
std::pair< bool, lps::specification > solve_structure_graph_with_counter_example(structure_graph &G, const lps::specification &lpsspec, const pbes &p, const pbes_equation_index &p_index)
The namespace for command line tool classes.
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72
Class that transforms a tool into a parallel tool with a –threads flag.
Base class for tools that produce a (P)BES as output.
add your file description here.
Base class for tools that use a data rewriter.
std::string file_extension(const std::string &filename)
Definition pbessolve.h:34