mCRL2
Loading...
Searching...
No Matches
normal_forms.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink
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//
9/// \file mcrl2/pbes/normal_forms.h
10/// \brief add your file description here.
11
12#ifndef MCRL2_PBES_NORMAL_FORMS_H
13#define MCRL2_PBES_NORMAL_FORMS_H
14
15#include "mcrl2/pbes/traverser.h"
16
17namespace mcrl2::pbes_system
18{
19
20namespace detail
21{
22
24{
28};
29
31
32/// \brief Traverser that implements the standard form normalization.
34{
35 public:
37
38 using super::apply;
39 using super::enter;
40 using super::leave;
41
42 /// \brief If true, the result will be in standard recursive normal form, otherwise in standard form.
44
45 /// \brief The fixpoint symbol of the current equation.
47
48 /// \brief The name of the variable of the current equation, with a trailing underscore added.
50
51 /// \brief Is set to true if the value true is encountered in the PBES.
52 bool m_has_true = false;
53
54 /// \brief Is set to true if the value false is encountered in the PBES.
55 bool m_has_false = false;
56
57 /// \brief For generating fresh variables.
58 utilities::number_postfix_generator m_generator;
59
60 /// \brief A stack containing sub-terms.
62
63 /// \brief A vector containing generated equations.
65
66 /// \brief A vector containing generated equations with new variables.
68
69 /// \brief Maps right hand sides of equations to their corresponding left hand side.
71
72 /// \brief The expression corresponding to true.
74
75 /// \brief The expression corresponding to false.
77
78 /// \brief Pops the stack and returns the popped element
80 {
81 standard_form_pair result = m_expression_stack.back();
82 m_expression_stack.pop_back();
83 return result;
84 }
85
86 /// \brief Pushes (first, second) on the stack.
87 void push(const pbes_expression& first, standard_form_type second)
88 {
89 m_expression_stack.emplace_back(first, second);
90 }
91
92 /// \brief Generates a fresh pbes variable.
93 propositional_variable fresh_variable(const std::string& hint)
94 {
95 core::identifier_string s = m_generator(hint);
96 return propositional_variable(s, data::variable_list());
97 }
98
99 /// \brief Generates an equation var=expr for the expression expr (if it does not exist).
100 /// \return The variable var.
102 {
103 std::map<pbes_expression, propositional_variable_instantiation>::iterator i = m_table.find(expr);
104 if (i != m_table.end())
105 {
106 return i->second;
107 }
108 propositional_variable var=fresh_variable(hint);
109 propositional_variable_instantiation varinst(var.name(), data::data_expression_list());;
110 m_table[expr] = varinst;
111 if (type == standard_form_and)
112 {
113 m_equations2.emplace_back(m_symbol, var, expr);
114 }
115 else
116 {
117 m_equations2.emplace_back(m_symbol, var, expr);
118 }
119 return varinst;
120 }
121
122 /// \brief Constructor.
123 /// \param recursive_form Determines whether or not the result will be in standard recursive normal form.
124 standard_form_traverser(bool recursive_form = false)
125 : m_recursive_form(recursive_form)
126 {
128 {
129 m_true = propositional_variable_instantiation(fresh_variable("True").name(), data::data_expression_list());
130 m_false = propositional_variable_instantiation(fresh_variable("False").name(), data::data_expression_list());
131 }
132 else
133 {
136 }
137 }
138
139 /// \brief Returns the top element of the expression stack, which is the result of the normalization.
141 {
142 return m_expression_stack.back().first;
143 }
144
145 /// \brief Returns the generated equations.
147 {
148 return m_equations;
149 }
150
151 /// \brief Enter a data_expression that must be either true or false.
152 /// \param x A term
153 void enter(const data::data_expression& x)
154 {
156 {
157 m_has_false = true;
159 }
160 else
161 {
163 m_has_true = true;
165 }
166 }
167
168 /// \brief Enter propositional_variable node.
169 /// \param x A pbes variable.
171 {
173 }
174
175 /// \brief Leave not node.
176 void leave(const not_& /* x */)
177 {
178 throw mcrl2::runtime_error("negation is not supported in standard recursive form algorithm");
179 }
180
181 /// \brief Leave and node
182 void leave(const and_& /* x */)
183 {
184 standard_form_pair right = pop();
185 standard_form_pair left = pop();
186 if (left.second == standard_form_or)
187 {
188 left.first = create_variable(left.first, standard_form_or, m_name);
189 }
190 if (right.second == standard_form_or)
191 {
192 right.first = create_variable(right.first, standard_form_or, m_name);
193 }
194 push(and_(left.first, right.first), standard_form_and);
195 }
196
197 /// \brief Leave or node
198 void leave(const or_& /* x */)
199 {
200 standard_form_pair right = pop();
201 standard_form_pair left = pop();
202 if (left.second == standard_form_and)
203 {
204 left.first = create_variable(left.first, standard_form_and, m_name);
205 }
206 if (right.second == standard_form_and)
207 {
208 right.first = create_variable(right.first, standard_form_and, m_name);
209 }
210 push(or_(left.first, right.first), standard_form_or);
211 }
212
213 /// \brief Leave imp node
214 void leave(const imp& /* x */)
215 {
216 throw mcrl2::runtime_error("implication is not supported in standard recursive form algorithm");
217 }
218
219 /// \brief Enter an equation
220 void enter(const pbes_equation& eq)
221 {
223 m_name = std::string(eq.variable().name()) + '_';
224 }
225
226 /// \brief Leave an equation
227 void leave(const pbes_equation& eq)
228 {
229 standard_form_pair p = pop();
230 m_equations.emplace_back(eq.symbol(), eq.variable(), p.first);
231 }
232
233 /// \brief Enter a pbes equation system.
234 void enter(const pbes& x)
235 {
236 assert(!x.equations().empty());
237 for (const pbes_equation& eqn: x.equations())
238 {
239 m_generator.add_identifier(std::string(eqn.variable().name()));
240 }
241 }
242
243 /// \brief Leave a pbes equation system.
244 void leave(const pbes&)
245 {
246 // set the fixpoint symbol for the added equations m_equations2, and move them to m_equations
247 assert(!m_equations.empty());
248 fixpoint_symbol sigma = m_equations.back().symbol();
249 for (pbes_equation& eqn: m_equations2)
250 {
251 eqn.symbol() = sigma;
252 }
253 std::copy(m_equations2.begin(), m_equations2.end(), std::back_inserter(m_equations));
254
255 // add equations for true and false if needed
257 {
258 if (m_has_true)
259 {
260 m_equations.emplace_back(fixpoint_symbol::nu(),
261 propositional_variable(atermpp::down_cast<propositional_variable_instantiation>(m_true).name()),
262 m_true);
263 }
264 if (m_has_false)
265 {
266 m_equations.emplace_back(fixpoint_symbol::mu(),
267 propositional_variable(atermpp::down_cast<propositional_variable_instantiation>(m_false).name()),
268 m_false);
269 }
270 }
271 }
272
273};
274
275} // namespace detail
276
277/// \brief Transforms a PBES into standard form.
278/// \param eqn A pbes equation system
279/// \param recursive_form Determines whether or not the result will be in standard recursive normal form
280inline
281void make_standard_form(pbes& eqn, bool recursive_form = false)
282{
283 detail::standard_form_traverser t(recursive_form);
284 t.apply(eqn);
285 assert(!is_propositional_variable(eqn.initial_state()) || eqn.equations().begin()->variable() == propositional_variable(eqn.initial_state()));
286 assert(!is_propositional_variable(eqn.initial_state()) || t.m_equations.begin()->variable() == propositional_variable(eqn.initial_state()));
287 eqn.equations() = t.m_equations;
288}
289
290} // namespace mcrl2::pbes_system
291
292#endif // MCRL2_PBES_NORMAL_FORMS_H
\brief The and operator for pbes expressions
Traverser that implements the standard form normalization.
void enter(const pbes &x)
Enter a pbes equation system.
std::vector< standard_form_pair > m_expression_stack
A stack containing sub-terms.
std::map< pbes_expression, propositional_variable_instantiation > m_table
Maps right hand sides of equations to their corresponding left hand side.
pbes_expression m_true
The expression corresponding to true.
propositional_variable fresh_variable(const std::string &hint)
Generates a fresh pbes variable.
standard_form_traverser(bool recursive_form=false)
Constructor.
void leave(const pbes &)
Leave a pbes equation system.
bool m_recursive_form
If true, the result will be in standard recursive normal form, otherwise in standard form.
void leave(const pbes_equation &eq)
Leave an equation.
void enter(const propositional_variable_instantiation &x)
Enter propositional_variable node.
std::string m_name
The name of the variable of the current equation, with a trailing underscore added.
std::vector< pbes_equation > m_equations2
A vector containing generated equations with new variables.
standard_form_pair pop()
Pops the stack and returns the popped element.
fixpoint_symbol m_symbol
The fixpoint symbol of the current equation.
bool m_has_false
Is set to true if the value false is encountered in the PBES.
pbes_expression m_false
The expression corresponding to false.
std::vector< pbes_equation > m_equations
A vector containing generated equations.
void enter(const data::data_expression &x)
Enter a data_expression that must be either true or false.
void enter(const pbes_equation &eq)
Enter an equation.
void push(const pbes_expression &first, standard_form_type second)
Pushes (first, second) on the stack.
const std::vector< pbes_equation > & equations() const
Returns the generated equations.
utilities::number_postfix_generator m_generator
For generating fresh variables.
bool m_has_true
Is set to true if the value true is encountered in the PBES.
pbes_expression result() const
Returns the top element of the expression stack, which is the result of the normalization.
propositional_variable_instantiation create_variable(const pbes_expression &expr, standard_form_type type, const std::string &hint)
Generates an equation var=expr for the expression expr (if it does not exist).
static fixpoint_symbol nu()
Returns the nu symbol.
fixpoint_symbol & operator=(fixpoint_symbol &&) noexcept=default
fixpoint_symbol & operator=(const fixpoint_symbol &) noexcept=default
\brief The implication operator for pbes expressions
\brief The not operator for pbes expressions
\brief The or operator for pbes expressions
const fixpoint_symbol & symbol() const
Returns the fixpoint symbol of the equation.
pbes_expression & operator=(const pbes_expression &) noexcept=default
parameterized boolean equation system
Definition pbes.h:54
const propositional_variable_instantiation & initial_state() const
Returns the initial state.
Definition pbes.h:188
propositional_variable_instantiation & initial_state()
Returns the initial state.
Definition pbes.h:195
\brief A propositional variable instantiation
propositional_variable_instantiation(const core::identifier_string &name, const data::data_expression_list &parameters)
Constructor.
\brief A propositional variable declaration
const core::identifier_string & name() const
propositional_variable(const core::identifier_string &name, const data::variable_list &parameters)
\brief Constructor Z12.
Namespace for system defined sort bool_.
Definition bool.h:29
bool is_false_function_symbol(const atermpp::aterm &e)
Recogniser for function false.
Definition bool.h:116
bool is_true_function_symbol(const atermpp::aterm &e)
Recogniser for function true.
Definition bool.h:84
bool is_propositional_variable(const atermpp::aterm &x)
const pbes_expression & true_()
std::string boolean_variables2pgsolver(Iter first, Iter last, const variable_map &variables)
Convert a sequence of Boolean variables to PGSolver format.
Definition pgsolver.cpp:27
bool is_or(const atermpp::aterm &x)
void bes2pgsolver(Iter first, Iter last, std::ostream &out, bool maxpg)
Save a sequence of BES equations in to a stream in PGSolver format.
Definition pgsolver.cpp:82
void save_bes_pgsolver(const pbes &bes, std::ostream &stream, bool maxpg)
Definition pgsolver.cpp:141
static std::string bes_expression2pgsolver(const pbes_expression &p, const variable_map &variables)
Convert a BES expression to PGSolver format.
Definition pgsolver.cpp:46
bool is_propositional_variable_instantiation(const atermpp::aterm &x)
bool is_and(const atermpp::aterm &x)
void make_standard_form(pbes &eqn, bool recursive_form=false)
Transforms a PBES into standard form.
const pbes_expression & false_()