10#ifndef MCRL2_PBES_PARELM_H
11#define MCRL2_PBES_PARELM_H
13#include "mcrl2/pbes/algorithms.h"
14#include "mcrl2/pbes/detail/find_free_variables.h"
15#include "mcrl2/utilities/detail/iota.h"
16#include "mcrl2/utilities/reachable_nodes.h"
17#include "mcrl2/pbes/detail/pbes_remove_counterexample_info.h"
31 for (
const data::variable& v: variables)
77 for (
const data::variable& v: x.variables())
79 bound_variables.insert(v);
85 for (
const data::variable& v: x.variables())
87 bound_variables.erase(v);
93 for (
const data::variable& v: x.variables())
95 bound_variables.insert(v);
101 for (
const data::variable& v: x.variables())
103 bound_variables.erase(v);
113 for (
const data::data_expression& e: x.parameters())
115 for (
const data::variable& var: data::find_free_variables(e))
117 if (contains(bound_variables, var))
121 int Xindex = detail::variable_index(Xparams, var);
127 boost::add_edge(propvar_offsets.at(Y) + Yindex, propvar_offsets.at(X) + Xindex, G);
136 Xparams = eqn.variable().parameters();
147 bool search_propositional_variables =
false;
148 return detail::find_free_variables(t, bound_variables, search_propositional_variables);
159 std::size_t offset = 0;
160 for (
const pbes_equation& eqn: p.equations())
162 std::size_t size = eqn.variable().parameters().size();
163 if (offset + size > index)
165 return eqn.variable().name();
167 offset += eqn.variable().parameters().size();
169 return core::identifier_string(
"<not found>");
175 for (
const pbes_equation& eqn: p.equations())
187 data::variable_list global_variables(p.global_variables().begin(), p.global_variables().end());
188 std::vector<data::variable> predicate_variables;
191 std::size_t offset = 0;
192 std::map<core::identifier_string, std::size_t> propvar_offsets;
193 for (pbes_equation& eqn: p.equations())
195 propvar_offsets[eqn.variable().name()] = offset;
196 offset += eqn.variable().parameters().size();
197 predicate_variables.insert(predicate_variables.end(), eqn.variable().parameters().begin(), eqn.variable().parameters().end());
199 std::size_t N = offset;
202 std::set<std::size_t> significant_variables;
204 for (pbes_equation& eqn: p.equations())
207 if (ignore_cex && detail::is_counter_example_equation(eqn))
209 for (
const data::variable& w: eqn.variable().parameters())
211 int k = detail::variable_index(eqn.variable().parameters(), w);
214 throw mcrl2::runtime_error(
"<variable error>" + data::pp(w));
216 significant_variables.insert(offset + k);
221 for (
const data::variable& w: unbound_variables(eqn.formula(), global_variables))
223 int k = detail::variable_index(eqn.variable().parameters(), w);
226 throw mcrl2::runtime_error(
"<variable error>" + data::pp(w));
228 significant_variables.insert(offset + k);
231 offset += eqn.variable().parameters().size();
235 compute_dependency_graph(p, propvar_offsets, G);
238 std::vector<std::size_t> r = utilities::reachable_nodes(G, significant_variables.begin(), significant_variables.end());
239 std::sort(r.begin(), r.end());
240 std::vector<std::size_t> q(N);
241 utilities::detail::iota(q.begin(), q.end(), 0);
242 std::vector<std::size_t> s;
243 std::set_difference(q.begin(), q.end(), r.begin(), r.end(), std::back_inserter(s));
246 std::map<core::identifier_string, std::vector<std::size_t> > removals;
247 std::size_t index = 0;
248 auto sfirst = s.begin();
249 for (pbes_equation& eqn: p.equations())
251 std::size_t maxindex = index + eqn.variable().parameters().size();
252 auto slast = std::find_if(sfirst, s.end(), [&](std::size_t i) {
return i >= maxindex; });
255 std::vector<std::size_t> w(sfirst, slast);
256 std::transform(w.begin(), w.end(), w.begin(), [&](std::size_t i) {
return i - index; });
257 removals[eqn.variable().name()] = w;
263 if (mCRL2logEnabled(log::debug))
265 print_dependencies(p, predicate_variables, significant_variables, G);
269 if (mCRL2logEnabled(log::verbose))
271 print_removed_parameters(predicate_variables, propvar_offsets, removals);
275 pbes_system::algorithms::remove_parameters(p, removals);
279 const std::map<core::identifier_string, std::size_t>& propvar_offsets,
282 mCRL2log(log::verbose) <<
"\nremoving the following parameters:" << std::endl;
283 for (
auto& removal: removals)
285 core::identifier_string X1 = removal.first;
286 for (std::size_t j: removal.second)
288 data::variable v1 = predicate_variables[j + propvar_offsets.at(X1)];
289 mCRL2log(log::verbose) <<
"(" + core::pp(X1) +
", " + data::pp(v1) +
")\n";
294 static void print_dependencies(
const pbes& p,
const std::vector<data::variable>& predicate_variables,
const std::set<std::size_t>& significant_variables,
const graph& G)
296 mCRL2log(log::debug) <<
"\ninfluential parameters:" << std::endl;
297 for (std::size_t i: significant_variables)
299 core::identifier_string X1 = find_predicate_variable(p, i);
301 mCRL2log(log::debug) <<
"(" + core::pp(X1) +
", " + data::pp(v1) +
")\n";
303 mCRL2log(log::debug) <<
"\ndependencies:" << std::endl;
304 using edge_iterator = boost::graph_traits<graph>::edge_iterator;
305 std::pair<edge_iterator, edge_iterator> e = edges(G);
306 edge_iterator first = e.first;
307 edge_iterator last = e.second;
308 for (; first != last; ++first)
310 edge_descriptor f = *first;
311 std::size_t i1 = boost::source(f, G);
312 core::identifier_string X1 = find_predicate_variable(p, i1);
313 data::variable v1 = predicate_variables[i1];
314 std::size_t i2 = boost::target(f, G);
315 core::identifier_string X2 = find_predicate_variable(p, i2);
316 data::variable v2 = predicate_variables[i2];
317 std::string left =
"(" + core::pp(X1) +
", " + data::pp(v1) +
")";
318 std::string right =
"(" + core::pp(X2) +
", " + data::pp(v2) +
")";
319 mCRL2log(log::debug) << left <<
" -> " << right << std::endl;
330 if (has_counter_example)
332 mCRL2log(log::warning) <<
"Warning: the PBES has counter example information, which may not be preserved by parameter elimination." << std::endl;
aterm_string & operator=(const aterm_string &t) noexcept=default
\brief The existential quantification operator for pbes expressions
\brief The universal quantification operator for pbes expressions
const propositional_variable & variable() const
Returns the pbes variable of the equation.
Algorithm class for the parelm algorithm.
static std::set< data::variable > unbound_variables(const pbes_expression &t, const data::variable_list &bound_variables)
Finds unbound variables in a pbes expression.
static void print_dependencies(const pbes &p, const std::vector< data::variable > &predicate_variables, const std::set< std::size_t > &significant_variables, const graph &G)
static core::identifier_string find_predicate_variable(const pbes &p, std::size_t index)
Finds the predicate variable to which the data parameter with the given index belongs....
static void compute_dependency_graph(const pbes &p, const std::map< core::identifier_string, std::size_t > &propvar_offsets, graph &G)
void run(pbes &p, bool ignore_cex=false)
Runs the parelm algorithm. The pbes is modified by the algorithm.
void print_removed_parameters(const std::vector< data::variable > &predicate_variables, const std::map< core::identifier_string, std::size_t > &propvar_offsets, const std::map< core::identifier_string, std::vector< std::size_t > > &removals) const
parameterized boolean equation system
\brief A propositional variable instantiation
const core::identifier_string & name() const
const core::identifier_string & name() const
#define mCRL2log(LEVEL)
mCRL2log(LEVEL) provides the stream used to log.
int variable_index(const data::variable_list &variables, const data::variable &d)
Finds the index of a variable in a sequence.
bool has_counter_example_information(const pbes &pbesspec)
Guesses if a pbes has counter example information.
void parelm(pbes &p, bool ignore_cex)
Apply the parelm algorithm.
void leave(const forall &x)
void apply(const pbes_equation &eqn)
core::identifier_string X
void enter(const exists &x)
void apply(const propositional_variable_instantiation &x)
void leave(const exists &x)
void enter(const forall &x)
parelm_dependency_traverser(graph &G_, const std::map< core::identifier_string, std::size_t > &propvar_offsets_)
const std::map< core::identifier_string, std::size_t > & propvar_offsets
std::multiset< data::variable > bound_variables
data::variable_list Xparams