mCRL2
Loading...
Searching...
No Matches
invariant_checker.h
Go to the documentation of this file.
1// Author(s): Luc Engelen
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//
11
12// Interface to class Invariant_Checker
13
14#ifndef MCRL2_LPS_INVARIANT_CHECKER_H
15#define MCRL2_LPS_INVARIANT_CHECKER_H
16
20
63
64namespace mcrl2
65{
66namespace lps
67{
68namespace detail
69{
70
71template <typename Specification>
73{
74 typedef typename Specification::process_type process_type;
75 typedef typename process_type::action_summand_type action_summand_type;
76 typedef std::vector<action_summand_type> action_summand_vector_type;
77
78 private:
79 const Specification& f_spec;
86 std::string f_dot_file_name;
88 void save_dot_file(std::size_t a_summand_number);
89 bool check_init(const data::data_expression& a_invariant);
90 bool check_summand(const data::data_expression& a_invariant, const action_summand_type& a_summand, const std::size_t a_summand_number);
91 bool check_summands(const data::data_expression& a_invariant);
92 public:
93
98 const Specification& a_lps,
99 data::rewriter::strategy a_rewrite_strategy = data::jitty,
100 int a_time_limit = 0,
101 bool a_path_eliminator = false,
103 bool a_apply_induction = false,
104 bool a_counter_example = false,
105 bool a_all_violations = false,
106 const std::string& a_dot_file_name = std::string()
107 );
108
110 bool check_invariant(const data::data_expression& a_invariant);
111};
112
113// Class Invariant_Checker ------------------------------------------------------------------------
114// Class Invariant_Checker - Functions declared private -----------------------------------------
115
116template <typename Specification>
118{
119 if (f_counter_example)
120 {
121 data::data_expression v_counter_example(f_bdd_prover.get_counter_example());
122 assert(v_counter_example.defined());
123 mCRL2log(log::info) << " Counter example: " << data::pp(v_counter_example) << "\n";
124 }
125}
126
127// --------------------------------------------------------------------------------------------
128
129template <typename Specification>
130void Invariant_Checker<Specification>::save_dot_file(std::size_t a_summand_number)
131{
132 if (!f_dot_file_name.empty())
133 {
134 std::string v_file_name=f_dot_file_name;
135
136 if (a_summand_number == (std::size_t)-1) // Dangerous
137 {
138 v_file_name += "-init.dot";
139 }
140 else
141 {
142 v_file_name += "-" + std::to_string(a_summand_number) + ".dot";
143 }
144 f_bdd2dot.output_bdd(f_bdd_prover.get_bdd(), v_file_name);
145 }
146}
147
148// --------------------------------------------------------------------------------------------
149
150template <typename Specification>
152{
153 data::mutable_map_substitution<> v_substitutions;
154 const data::variable_list& d = f_spec.process().process_parameters();
155 const data::data_expression_list& e = f_init.expressions();
156 auto di = d.begin();
157 auto ei = e.begin();
158 for (; di != d.end(); ++di, ++ei)
159 {
160 v_substitutions[*di] = *ei;
161 }
162
163 data::data_expression b_invariant = data::replace_variables_capture_avoiding(a_invariant, v_substitutions);
164 f_bdd_prover.set_formula(b_invariant);
165 if (f_bdd_prover.is_tautology() == data::detail::answer_yes)
166 {
167 return true;
168 }
169 else
170 {
171 if (f_bdd_prover.is_contradiction() != data::detail::answer_yes)
172 {
173 print_counter_example();
174 save_dot_file((std::size_t)(-1));
175 }
176 return false;
177 }
178}
179
180// --------------------------------------------------------------------------------------------
181
182template <typename Specification>
184 const data::data_expression& a_invariant,
185 const action_summand_type& a_summand,
186 const std::size_t a_summand_number)
187{
188 using namespace data::sort_bool;
189 const data::data_expression& v_condition = a_summand.condition();
190
191 data::mutable_map_substitution<> v_substitutions;
192
193 for (const data::assignment& a: a_summand.assignments())
194 {
195 v_substitutions[a.lhs()] = a.rhs();
196 }
197
198 const data::data_expression v_subst_invariant = data::replace_variables_capture_avoiding(a_invariant, v_substitutions);
199
200 const data::data_expression v_formula = implies(and_(a_invariant, v_condition), v_subst_invariant);
201 f_bdd_prover.set_formula(v_formula);
202 if (f_bdd_prover.is_tautology() == data::detail::answer_yes)
203 {
204 mCRL2log(log::verbose) << "The invariant holds for summand " << a_summand_number << "." << std::endl;
205 return true;
206 }
207 else
208 {
209 mCRL2log(log::info) << "The invariant does not hold for summand " << a_summand_number << std::endl;
210 if (f_bdd_prover.is_contradiction() != data::detail::answer_yes)
211 {
212 print_counter_example();
213 save_dot_file(a_summand_number);
214 }
215 return false;
216 }
217}
218
219// --------------------------------------------------------------------------------------------
220
221template <typename Specification>
223{
224 bool v_result = true;
225 std::size_t v_summand_number = 1;
226
227 for (auto i = f_summands.begin(); i != f_summands.end() && (f_all_violations || v_result); ++i)
228 {
229 v_result = check_summand(a_invariant, *i, v_summand_number) && v_result;
230 v_summand_number++;
231 }
232 return v_result;
233}
234
235// Class Invariant_Checker<Specification> - Functions declared public --------------------------------------------
236
237template <typename Specification>
239 const Specification& a_lps,
240 data::rewriter::strategy a_rewrite_strategy, int a_time_limit, bool a_path_eliminator, data::detail::smt_solver_type a_solver_type,
241 bool a_apply_induction, bool a_counter_example, bool a_all_violations, std::string const& a_dot_file_name
242):
243 f_spec(a_lps),
244 f_bdd_prover(a_lps.data(), data::used_data_equation_selector(a_lps.data()), a_rewrite_strategy, a_time_limit, a_path_eliminator, a_solver_type, a_apply_induction)
245{
246 f_init = a_lps.initial_process();
247 f_summands = a_lps.process().action_summands();
248 f_counter_example = a_counter_example;
249 f_all_violations = a_all_violations;
250 f_dot_file_name = a_dot_file_name;
251}
252
253// --------------------------------------------------------------------------------------------
254
255template <typename Specification>
257{
258 bool v_result = true;
259
260 if (check_init(a_invariant))
261 {
262 mCRL2log(log::verbose) << "The invariant holds for the initial state." << std::endl;
263 }
264 else
265 {
266 mCRL2log(log::info) << "The invariant does not hold for the initial state." << std::endl;
267 v_result = false;
268 }
269 if ((f_all_violations || v_result))
270 {
271 if (check_summands(a_invariant))
272 {
273 mCRL2log(log::verbose) << "The invariant holds for all summands." << std::endl;
274 }
275 else
276 {
277 mCRL2log(log::info) << "The invariant does not hold for all summands." << std::endl;
278 v_result = false;
279 }
280 }
281 if (v_result)
282 {
283 mCRL2log(log::info) << "The invariant holds for this LPS." << std::endl;
284 }
285 else
286 {
287 mCRL2log(log::info) << "The invariant does not hold for this LPS." << std::endl;
288 }
289
290 return v_result;
291}
292
293} // namespace detail
294} // namespace lps
295} // namespace mcrl2
296
297#endif
const_iterator end() const
Returns a const_iterator pointing to the end of the term_list.
Definition aterm_list.h:282
const_iterator begin() const
Returns a const_iterator pointing to the beginning of the term_list.
Definition aterm_list.h:275
bool defined() const
Returns true if this term is not equal to the term assigned by the default constructor of aterms,...
Definition aterm_core.h:143
\brief Assignment of a data expression to a variable
Definition assignment.h:91
rewrite_strategy strategy
The rewrite strategies of the rewriter.
Definition rewriter.h:44
The class BDD2Dot offers the ability to write binary decision diagrams to dot files....
Definition bdd2dot.h:30
void output_bdd(const data_expression &a_bdd, const std::string &a_file_name)
Writes the BDD it receives as input to a file.
Definition bdd2dot.h:94
void set_formula(const data_expression &formula)
Sets Prover::f_formula to formula. precondition: the argument passed as parameter formula is an expre...
Definition bdd_prover.h:628
data_expression get_counter_example()
Returns all the guards on a path in the BDD that leads to a leaf labelled "false",...
Definition bdd_prover.h:587
Answer is_contradiction()
Indicates whether or not the formula Prover::f_formula is a contradiction.
Definition bdd_prover.h:545
data_expression get_bdd()
Returns the BDD BDD_Prover::f_bdd.
Definition bdd_prover.h:552
Answer is_tautology()
Indicates whether or not the formula Prover::f_formula is a tautology.
Definition bdd_prover.h:538
Generic substitution function. The substitution is stored as a mapping of variables to expressions....
Component for selecting a subset of equations that are actually used in an encompassing specification...
Definition selection.h:37
void save_dot_file(std::size_t a_summand_number)
process_type::action_summand_type action_summand_type
bool check_summand(const data::data_expression &a_invariant, const action_summand_type &a_summand, const std::size_t a_summand_number)
action_summand_vector_type f_summands
bool check_summands(const data::data_expression &a_invariant)
bool check_init(const data::data_expression &a_invariant)
Specification::process_type process_type
Invariant_Checker(const Specification &a_lps, data::rewriter::strategy a_rewrite_strategy=data::jitty, int a_time_limit=0, bool a_path_eliminator=false, data::detail::smt_solver_type a_solver_type=data::detail::solver_type_cvc, bool a_apply_induction=false, bool a_counter_example=false, bool a_all_violations=false, const std::string &a_dot_file_name=std::string())
std::vector< action_summand_type > action_summand_vector_type
bool check_invariant(const data::data_expression &a_invariant)
precondition: the argument passed as parameter a_invariant is a valid expression in internal mCRL2 fo...
data::data_expression_list expressions() const
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Definition logger.h:391
smt_solver_type
The enumeration type smt_solver_type enumerates all available SMT solvers.
Definition solver_type.h:27
data_expression and_(const data_expression &x, const data_expression &y)
std::string pp(const abstraction &x)
Definition data.cpp:39
void replace_variables_capture_avoiding(T &x, Substitution &sigma, data::set_identifier_generator &id_generator, typename std::enable_if<!std::is_base_of< atermpp::aterm, T >::value >::type *=nullptr)
@ verbose
Definition logger.h:37
A class that takes a linear process specification and checks all tau-summands of that LPS for conflue...
Definition indexed_set.h:72