15#ifndef MCRL2_PBES_TOOLS_PBESFIXPOINTSOLVE_H
16#define MCRL2_PBES_TOOLS_PBESFIXPOINTSOLVE_H
18#include "mcrl2/data/detail/prover/bdd_prover.h"
19#include "mcrl2/data/merge_data_specifications.h"
21#include "mcrl2/pbes/algorithms.h"
22#include "mcrl2/pbes/detail/iteration_builders.h"
23#include "mcrl2/pbes/io.h"
24#include "mcrl2/pbes/pbes_expression.h"
25#include "mcrl2/pbes/rewrite.h"
26#include "mcrl2/pbes/rewriter.h"
27#include "mcrl2/pbes/rewriters/pbes2data_rewriter.h"
28#include "mcrl2/smt/solver.h"
29#include "mcrl2/utilities/logger.h"
39 data::rewrite_strategy rewrite_strategy =
data::rewrite_strategy::jitty;
48 detail::substitute_propositional_variables_builder<pbes_system::pbes_expression_builder>& substituter)
50 substituter.set_equation(by);
51 substituter.set_name(into.variable().name());
53 substituter.apply(p, into.formula());
58 detail::replace_other_propositional_variables_with_functions_builder<pbes_system::pbes_expression_builder>&
62 replace_substituter.set_forward(
true);
63 replace_substituter.set_name(equation.variable().name());
64 replace_substituter.apply(expr, equation.formula());
68 replace_substituter.set_forward(
false);
69 replace_substituter.apply(expr, equation.formula());
82 detail::substitute_propositional_variables_builder<pbes_system::pbes_expression_builder>& substituter,
83 detail::replace_other_propositional_variables_with_functions_builder<pbes_system::pbes_expression_builder>&
87 std::set<data::variable>& global_variables)
89 mCRL2log(log::log_level_t::debug) <<
"INV: " << equation.symbol() <<
"\n";
96 std::set<propositional_variable_instantiation> set = find_propositional_variable_instantiations(equation.formula());
99 mCRL2log(log::log_level_t::debug) <<
"INV: " << equation.variable().name() <<
" does not contain any pvi." <<
"\n";
103 if (std::any_of(set.begin(),
105 [=](
const propositional_variable_instantiation& v) {
return v.name() != equation.variable().name(); }))
108 mCRL2log(log::log_level_t::debug) <<
"INV: " << equation.variable().name() <<
" contains other pvi." <<
"\n";
117 substituter.set_equation(eq);
118 substituter.set_name(equation.variable().name());
120 substituter.apply(cc, equation.formula());
121 cc = pbes_rewrite(cc, pbes_rewriter);
123 bool global_invariant =
false;
125 detail::substitute_propositional_variables_for_bools_builder<pbes_system::pbes_expression_builder> bool_substituter(
129 mCRL2log(log::log_level_t::verbose) <<
"INV: PVI set size " << set.size() <<
"\n";
131 for (
const propositional_variable_instantiation& pvi: set)
135 mCRL2log(log::log_level_t::verbose) <<
"INV: PVI " << i <<
"begin added now. \n";
139 data::mutable_indexed_substitution sigma;
140 data::data_expression_list pars = pvi.parameters();
141 for (
const data::variable& v : equation.variable().parameters())
143 data::data_expression par = pars.front();
145 if (par.sort() != v.sort())
148 mCRL2log(log::log_level_t::verbose) <<
"INV: No param match for " << v.name() <<
"\n";
149 return InvResult::INV_FALSE;
153 pbes_expression cc_i = pbes_rewrite(cc, pbes_rewriter, sigma);
156 bool_substituter.set_pvi(pvi);
157 bool_substituter.set_replacement(false_());
159 bool_substituter.apply(c_i, equation.formula());
160 c_i = pbes_rewrite(c_i, pbes_rewriter);
162 pbes_equation cc_i_eq;
163 cc_i_eq.formula() = cc_i;
164 data::data_expression cc_i_data = pbestodata(cc_i_eq, replace_substituter);
165 pbes_equation c_i_eq;
166 c_i_eq.formula() = c_i;
167 data::data_expression c_i_data = pbestodata(c_i_eq, replace_substituter);
169 f_bdd_prover.set_formula(c_i_data);
170 data::detail::Answer c_i_is_contradiction = f_bdd_prover.is_contradiction();
171 if (c_i_is_contradiction == data::detail::Answer::answer_yes)
173 mCRL2log(log::log_level_t::verbose) <<
"Core constraint is not simple (contains pvi)." << std::endl;
174 return InvResult::INV_FALSE;
178 data::data_expression bdd_expr = data::imp(c_i_data, cc_i_data);
180 for (
const data::variable& v : global_variables)
182 bdd_expr = make_exists_(data::variable_list({v}), bdd_expr);
185 f_bdd_prover.set_formula(bdd_expr);
186 mCRL2log(log::log_level_t::verbose) <<
"INV?: " << std::endl;
188 data::detail::Answer v_is_tautology = f_bdd_prover.is_tautology();
189 data::detail::Answer v_is_contradiction = f_bdd_prover.is_contradiction();
190 if (v_is_contradiction == data::detail::Answer::answer_yes)
192 mCRL2log(log::log_level_t::verbose) <<
"Contradiction for inv checker." << std::endl;
193 equation.formula() = false_();
194 return InvResult::EQ_FALSE;
196 else if (v_is_tautology == data::detail::Answer::answer_no || v_is_tautology == data::detail::Answer::answer_undefined)
198 mCRL2log(log::log_level_t::verbose) <<
"Found some transition that is not an invariant" << std::endl;
199 return InvResult::INV_FALSE;
201 else if (v_is_tautology == data::detail::Answer::answer_yes)
203 mCRL2log(log::log_level_t::verbose) <<
"This transition is true" << std::endl;
204 global_invariant =
true;
208 mCRL2log(log::log_level_t::error) <<
"No contradiction and no tautology" << std::endl;
209 throw mcrl2::runtime_error(
"TODO");
213 mCRL2log(log::log_level_t::info) <<
"Is global invariant? " << global_invariant << std::endl;
214 if (global_invariant)
223 detail::substitute_propositional_variables_builder<pbes_system::pbes_expression_builder>& substituter,
224 detail::replace_other_propositional_variables_with_functions_builder<pbes_system::pbes_expression_builder>&
231 std::optional<smt::smt_solver> solv;
232 std::optional<mcrl2::data::detail::BDD_Prover> f_bdd_prover;
235 solv.emplace(data_spec);
239 f_bdd_prover.emplace(data_spec, data::used_data_equation_selector(data_spec));
256 mCRL2log(log::log_level_t::info) << eq.variable().name() <<
": " << i << std::endl;
259 substituter.set_equation(eq);
260 substituter.set_name(equation.variable().name());
262 substituter.apply(p, equation.formula());
263 p = pbes_rewrite(p, pbes_rewriter);
267 p_eq.formula() = pbes_rewrite(p, pbes_rewriter);
269 replace_substituter.reset_variable_list();
285 data::variable_list var_list = p_eq.variable().parameters();
286 for (
const auto& x : as_set(replace_substituter.get_variable_list()))
288 var_list.push_front(x);
290 mCRL2log(log::log_level_t::verbose) << eq.variable().name() <<
": SMT check for " << i <<
" started." << std::endl;
291 smt::answer result = solv->solve(var_list, data::not_(formula), std::chrono::seconds(0));
294 case smt::answer::UNSAT:
295 mCRL2log(log::log_level_t::info) << eq.variable().name() <<
": iteration " << i <<
" is equal to " << i + 1 << std::endl;
298 case smt::answer::SAT:
300 case smt::answer::UNKNOWN:
306 f_bdd_prover->set_formula(formula);
307 mCRL2log(log::log_level_t::verbose) << eq.variable().name() <<
": EQ-BDD check for " << i <<
" started." << std::endl;
311 mCRL2log(log::log_level_t::info) << eq.variable().name() <<
": iteration " << i <<
" is equal to " << i + 1 << std::endl;
322 substitute(init_eq, eq, substituter);
327 mCRL2log(log::log_level_t::verbose) << eq.variable().name() <<
": SMT init check for " << i <<
" started." << std::endl;
329 smt::answer result = solv->solve({}, smt_data, std::chrono::seconds(0));
332 case smt::answer::UNSAT:
333 mCRL2log(log::log_level_t::info) << eq.variable().name() <<
": iteration " << i <<
" is equal to " << i + 1 << std::endl;
336 case smt::answer::SAT:
338 case smt::answer::UNKNOWN:
344 f_bdd_prover->set_formula(init_data);
345 mCRL2log(log::log_level_t::verbose) << eq.variable().name() <<
": EQ-BDD init check for " << i <<
" started." << std::endl;
349 mCRL2log(log::log_level_t::verbose) << eq.variable().name() <<
": EQ-BDD tauto? "
350 << (v_is_tautology == data::detail::Answer::answer_yes) << std::endl;
351 mCRL2log(log::log_level_t::verbose) << eq.variable().name() <<
": EQ-BDD contra? "
352 << (v_is_contradiction == data::detail::Answer::answer_yes) << std::endl;
356 mCRL2log(log::log_level_t::info) << eq.variable().name() <<
": iteration " << i <<
" is equal to " << i + 1 << std::endl;
377 data::
rewriter data_rewriter(p.data(), options.rewrite_strategy);
379 detail::substitute_propositional_variables_builder<pbes_system::pbes_expression_builder> substituter(pbes_rewriter);
381 detail::replace_other_propositional_variables_with_functions_builder<pbes_system::pbes_expression_builder>
382 replace_substituter(pbes_rewriter);
384 for (std::vector<pbes_equation>::reverse_iterator i = p.equations().rbegin(); i != p.equations().rend(); i++)
386 mCRL2log(log::log_level_t::verbose) <<
"Investigating the equation for " << i->variable().name() <<
"\n";
387 if (options.check_global_invariant)
389 InvResult global_inv = global_invariant_check(*i,
394 p.global_variables());
395 if (global_inv == InvResult::INV_FALSE)
397 perform_iteration(*i, substituter, replace_substituter, p.data(), options, p.initial_state(), pbes_rewriter);
402 perform_iteration(*i, substituter, replace_substituter, p.data(), options, p.initial_state(), pbes_rewriter);
405 for (std::vector<pbes_equation>::reverse_iterator j = i + 1; j != p.equations().rend(); j++)
407 substitute(*j, *i, substituter);
data_expression & operator=(data_expression &&) noexcept=default
Rewriter that operates on data expressions.
Component for selecting a subset of equations that are actually used in an encompassing specification...
used_data_equation_selector(const data_specification &)
select all equations
bool is_nu() const
Returns true if the symbol is nu.
bool is_mu() const
Returns true if the symbol is mu.
fixpoint_symbol & operator=(const fixpoint_symbol &) noexcept=default
fixpoint_symbol & symbol()
Returns the fixpoint symbol of the equation.
propositional_variable & variable()
Returns the pbes variable of the equation.
pbes_expression & formula()
Returns the predicate formula on the right hand side of the equation.
pbes_expression & operator=(const pbes_expression &) noexcept=default
parameterized boolean equation system
\brief A propositional variable instantiation
const core::identifier_string & name() const
const core::identifier_string & name() const
propositional_variable & operator=(const propositional_variable &) noexcept=default
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
Answer
A prover that uses EQ-BDDs.
data_expression not_(const data_expression &x)
data_expression imp(const data_expression &x, const data_expression &y)
const pbes_expression & true_()
data::data_expression pbestodata(pbes_equation &equation, detail::replace_other_propositional_variables_with_functions_builder< pbes_system::pbes_expression_builder > &replace_substituter)
void perform_iteration(pbes_equation &equation, detail::substitute_propositional_variables_builder< pbes_system::pbes_expression_builder > &substituter, detail::replace_other_propositional_variables_with_functions_builder< pbes_system::pbes_expression_builder > &replace_substituter, data::data_specification data_spec, pbesfixpointsolve_options options, propositional_variable_instantiation initial_state, simplify_data_rewriter< data::rewriter > pbes_rewriter)
InvResult global_invariant_check(pbes_equation &equation, detail::substitute_propositional_variables_builder< pbes_system::pbes_expression_builder > &substituter, detail::replace_other_propositional_variables_with_functions_builder< pbes_system::pbes_expression_builder > &replace_substituter, data::data_specification data_spec, simplify_data_rewriter< data::rewriter > pbes_rewriter, std::set< data::variable > &global_variables)
const pbes_expression & false_()
void substitute(pbes_equation &into, const pbes_equation &by, substitute_propositional_variables_builder< pbes_system::pbes_expression_builder > &substituter)
bool check_global_invariant
void run(pbes &p, pbesfixpointsolve_options options)
A rewriter that simplifies boolean expressions in a term, and rewrites data expressions using DataRew...