LCOV - code coverage report
Current view: top level - pbes/include/mcrl2/pbes - pbesinst_algorithm.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 73 83 88.0 %
Date: 2024-04-26 03:18:02 Functions: 8 9 88.9 %
Legend: Lines: hit not hit

          Line data    Source code
       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/pbesinst_algorithm.h
      10             : /// \brief Algorithm for instantiating a PBES.
      11             : 
      12             : #ifndef MCRL2_PBES_PBESINST_ALGORITHM_H
      13             : #define MCRL2_PBES_PBESINST_ALGORITHM_H
      14             : 
      15             : #include "mcrl2/pbes/detail/bes_equation_limit.h"
      16             : #include "mcrl2/pbes/detail/instantiate_global_variables.h"
      17             : #include "mcrl2/pbes/rewriters/enumerate_quantifiers_rewriter.h"
      18             : #include "mcrl2/pbes/rewriters/one_point_rule_rewriter.h"
      19             : #include "mcrl2/pbes/rewriters/simplify_quantifiers_rewriter.h"
      20             : 
      21             : namespace mcrl2
      22             : {
      23             : 
      24             : namespace pbes_system
      25             : {
      26             : 
      27             : /// \brief Creates a substitution function for the pbesinst rewriter.
      28             : /// \param v A sequence of data variables
      29             : /// \param e A sequence of data expressions
      30             : /// \param sigma The substitution that maps the i-th element of \p v to the i-th element of \p e
      31             : inline
      32          98 : void make_pbesinst_substitution(const data::variable_list& v, const data::data_expression_list& e, data::rewriter::substitution_type& sigma)
      33             : {
      34          98 :   assert(v.size() == e.size());
      35          98 :   data::variable_list::iterator i = v.begin();
      36          98 :   data::data_expression_list::iterator j = e.begin();
      37         950 :   for (; i != v.end(); ++i, ++j)
      38             :   {
      39         852 :     sigma[*i] = *j;
      40             :   }
      41          98 : }
      42             : 
      43             : inline
      44         424 : bool pbesinst_is_constant(const pbes_expression& x)
      45             : {
      46         424 :   return pbes_system::find_free_variables(x).empty();
      47             : }
      48             : 
      49             : /// \brief Creates a unique name for a propositional variable instantiation. The
      50             : /// propositional variable instantiation must be closed.
      51             : /// Originally implemented by Alexander van Dam.
      52             : /// \return A name that uniquely corresponds to the propositional variable.
      53             : struct pbesinst_rename_long
      54             : {
      55         212 :   core::identifier_string operator()(const propositional_variable_instantiation& Ye) const
      56             :   {
      57         212 :     assert(pbesinst_is_constant(Ye));
      58         212 :     std::string name = Ye.name();
      59        2116 :     for (const data::data_expression& exp: Ye.parameters())
      60             :     {
      61        1904 :       if (is_function_symbol(exp) && exp.sort() != data::sort_pos::pos() && exp.sort() != data::sort_nat::nat())
      62             :       {
      63             :         // This case is dealt with separately, as it occurs often.
      64             :         // The use of pp as in the next case is correct for this case also, but very time consuming.
      65             :         // The exception to this rule is constants @c1 of sort Pos, @c0 of sort Nat.
      66        1212 :         name += "@";
      67        1212 :         name += atermpp::down_cast<data::function_symbol>(exp).name();
      68             :       }
      69         692 :       else if (is_function_symbol(exp) || is_application(exp) || is_abstraction(exp))
      70             :       {
      71         692 :         name += "@";
      72         692 :         name += data::pp(exp);
      73             :       }
      74             :       else
      75             :       {
      76           0 :         throw mcrl2::runtime_error(std::string("pbesinst_rename_long: could not rename the variable ") + pbes_system::pp(Ye) + " " + data::pp(exp));
      77             :       }
      78             :     }
      79         424 :     return name;
      80         212 :   }
      81             : };
      82             : 
      83             : /// \brief Creates a unique name for a propositional variable instantiation. The
      84             : /// propositional variable instantiation must be closed.
      85             : /// Originally implemented by Alexander van Dam.
      86             : /// \return A name that uniquely corresponds to the propositional variable.
      87             : struct pbesinst_rename
      88             : {
      89         212 :   propositional_variable_instantiation operator()(const propositional_variable_instantiation& Ye) const
      90             :   {
      91         212 :     if (!pbesinst_is_constant(Ye))
      92             :     {
      93           0 :       return Ye;
      94             :     }
      95         424 :     return propositional_variable_instantiation(pbesinst_rename_long()(Ye), data::data_expression_list());
      96             :   }
      97             : };
      98             : 
      99             : /// \brief Algorithm class for the pbesinst instantiation algorithm.
     100             : class pbesinst_algorithm
     101             : {
     102             :   protected:
     103             :     /// \brief Data rewriter.
     104             :     data::rewriter datar;
     105             : 
     106             :     /// \brief The rewriter.
     107             :     enumerate_quantifiers_rewriter R;
     108             : 
     109             :     /// \brief The number of generated equations.
     110             :     std::size_t m_equation_count;
     111             : 
     112             :     /// \brief Propositional variable instantiations that need to be handled.
     113             :     std::set<propositional_variable_instantiation> todo;
     114             : 
     115             :     /// \brief Propositional variable instantiations that have been handled.
     116             :     std::set<propositional_variable_instantiation> done;
     117             : 
     118             :     /// \brief Data structure for storing the result. E[i] corresponds to the equations
     119             :     /// generated from the i-th PBES equation.
     120             :     std::vector<std::vector<pbes_equation> > E;
     121             : 
     122             :     /// \brief The initial value.
     123             :     propositional_variable_instantiation init;
     124             : 
     125             :     /// \brief A lookup map for PBES equations.
     126             :     std::map<core::identifier_string, int> equation_index;
     127             : 
     128             :     /// \brief Print the equations to standard out.
     129             :     bool m_print_equations;
     130             : 
     131             :     /// \brief Prints a log message for every 1000-th equation
     132           0 :     std::string print_equation_count(std::size_t size) const
     133             :     {
     134           0 :       if (size > 0 && size % 1000 == 0)
     135             :       {
     136           0 :         std::ostringstream out;
     137           0 :         out << "Generated " << size << " BES equations" << std::endl;
     138           0 :         return out.str();
     139           0 :       }
     140           0 :       return "";
     141             :     }
     142             : 
     143             :     // renames propositional variables in x
     144          90 :     pbes_expression rho(const pbes_expression& x) const
     145             :     {
     146         180 :       return replace_propositional_variables(x, pbesinst_rename());
     147             :     }
     148             : 
     149             :   public:
     150             : 
     151             :     /// \brief Constructor.
     152             :     /// \param data_spec A data specification.
     153             :     /// \param rewrite_strategy A strategy for the data rewriter.
     154             :     /// \param print_equations If true, the generated equations are printed.
     155           8 :     explicit pbesinst_algorithm(data::data_specification const& data_spec,
     156             :                        data::rewriter::strategy rewrite_strategy = data::jitty,
     157             :                        bool print_equations = false
     158             :                       )
     159           8 :       :
     160           8 :         datar(data_spec, rewrite_strategy),
     161           8 :         R(datar, data_spec),
     162           8 :         m_equation_count(0),
     163           8 :         m_print_equations(print_equations)
     164           8 :     {}
     165             : 
     166             :     /// \brief Runs the algorithm. The result is obtained by calling the function \p get_result.
     167             :     /// \param p A PBES.
     168           8 :     void run(pbes& p)
     169             :     {
     170             :       using utilities::detail::pick_element;
     171             :       using utilities::detail::contains;
     172             : 
     173           8 :       pbes_system::detail::instantiate_global_variables(p);
     174             : 
     175             :       // simplify all right hand sides of p
     176             :       //
     177             :       // NOTE: This is not just an optimization. There are certain PBES
     178             :       // equations for which applying enumerate_quantifiers_rewriter directly
     179             :       // won't terminate, like:
     180             :       //
     181             :       // forall m: Nat . exists k: Nat . val(m == k)
     182             :       pbes_system::one_point_rule_rewriter one_point_rule_rewriter;
     183           8 :       pbes_system::simplify_quantifiers_data_rewriter<mcrl2::data::rewriter> simplify_rewriter(datar);
     184          21 :       for (pbes_equation& eqn: p.equations())
     185             :       {
     186          13 :         eqn.formula() = one_point_rule_rewriter(simplify_rewriter(eqn.formula()));
     187             :       }
     188             : 
     189             :       // initialize equation_index and E
     190           8 :       int eqn_index = 0;
     191           8 :       auto const& equations = p.equations();
     192          21 :       for (const pbes_equation& eqn : equations)
     193             :       {
     194          13 :         equation_index[eqn.variable().name()] = eqn_index++;
     195          13 :         E.emplace_back();
     196             :       }
     197           8 :       init = atermpp::down_cast<propositional_variable_instantiation>(R(p.initial_state()));
     198           8 :       todo.insert(init);
     199          98 :       while (!todo.empty())
     200             :       {
     201          90 :         auto const& X_e = pick_element(todo);
     202          90 :         done.insert(X_e);
     203          90 :         int index = equation_index[X_e.name()];
     204          90 :         const pbes_equation& eqn = p.equations()[index];
     205          90 :         data::rewriter::substitution_type sigma;
     206          90 :         make_pbesinst_substitution(eqn.variable().parameters(), X_e.parameters(), sigma);
     207          90 :         auto const& phi = eqn.formula();
     208          90 :         pbes_expression psi_e = R(phi, sigma);
     209          90 :         R.clear_identifier_generator();
     210         203 :         for (const propositional_variable_instantiation& v: find_propositional_variable_instantiations(psi_e))
     211             :         {
     212         113 :           if (!contains(done, v))
     213             :           {
     214          87 :             todo.insert(v);
     215             :           }
     216          90 :         }
     217         180 :         pbes_equation new_eqn(eqn.symbol(), propositional_variable(pbesinst_rename()(X_e).name(), data::variable_list()), rho(psi_e));
     218          90 :         if (m_print_equations)
     219             :         {
     220          74 :           mCRL2log(log::info) << eqn.symbol() << " " << X_e << " = " << psi_e << std::endl;
     221             :         }
     222          90 :         E[index].push_back(new_eqn);
     223          90 :         mCRL2log(log::verbose) << print_equation_count(++m_equation_count);
     224          90 :         detail::check_bes_equation_limit(m_equation_count);
     225          90 :       }
     226           8 :     }
     227             : 
     228             :     /// \brief Returns the computed bes in pbes format
     229             :     /// \return The computed bes in pbes format
     230           8 :     pbes get_result()
     231             :     {
     232           8 :       pbes result;
     233          21 :       for (const std::vector<pbes_equation>& equations: E)
     234             :       {
     235          13 :         result.equations().insert(result.equations().end(), equations.begin(), equations.end());
     236             :       }
     237           8 :       result.initial_state() = pbesinst_rename()(init);
     238           8 :       return result;
     239           0 :     }
     240             : 
     241             :     /// \brief Returns the flag for printing the generated bes equations
     242             :     /// \return The flag for printing the generated bes equations
     243             :     bool& print_equations()
     244             :     {
     245             :       return m_print_equations;
     246             :     }
     247             : 
     248             :     enumerate_quantifiers_rewriter& rewriter()
     249             :     {
     250             :       return R;
     251             :     }
     252             : };
     253             : 
     254             : } // namespace pbes_system
     255             : 
     256             : } // namespace mcrl2
     257             : 
     258             : #endif // MCRL2_PBES_PBESINST_ALGORITHM_H

Generated by: LCOV version 1.14