LCOV - code coverage report
Current view: top level - lps/include/mcrl2/lps - multi_action.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 98 98 100.0 %
Date: 2024-04-26 03:18:02 Functions: 36 40 90.0 %
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/lps/multi_action.h
      10             : /// \brief Multi-action class.
      11             : 
      12             : #ifndef MCRL2_LPS_MULTI_ACTION_H
      13             : #define MCRL2_LPS_MULTI_ACTION_H
      14             : 
      15             : #include "mcrl2/core/print.h"
      16             : #include "mcrl2/process/process_expression.h"
      17             : 
      18             : namespace mcrl2
      19             : {
      20             : 
      21             : namespace lps
      22             : {
      23             : 
      24             : // prototype declaration
      25             : bool is_multi_action(const atermpp::aterm_appl& x);
      26             : 
      27             : //--- start generated class multi_action ---//
      28             : /// \\brief A timed multi-action
      29             : class multi_action: public atermpp::aterm_appl
      30             : {
      31             :   public:
      32             : 
      33             : 
      34             :     /// Move semantics
      35       87026 :     multi_action(const multi_action&) noexcept = default;
      36       73464 :     multi_action(multi_action&&) noexcept = default;
      37        9139 :     multi_action& operator=(const multi_action&) noexcept = default;
      38        1692 :     multi_action& operator=(multi_action&&) noexcept = default;
      39             : 
      40      139702 :     const process::action_list& actions() const
      41             :     {
      42      139702 :       return atermpp::down_cast<process::action_list>((*this)[0]);
      43             :     }
      44             : 
      45      389189 :     const data::data_expression& time() const
      46             :     {
      47      389189 :       return atermpp::down_cast<data::data_expression>((*this)[1]);
      48             :     }
      49             : //--- start user section multi_action ---//
      50             :     /// \brief Constructor
      51       47394 :     explicit multi_action(const process::action_list& actions = process::action_list(), 
      52             :                           data::data_expression time = data::undefined_real())
      53       47394 :       : atermpp::aterm_appl(core::detail::function_symbol_TimedMultAct(), actions, time)
      54             :     {
      55       47394 :       assert(data::sort_real::is_real(time.sort()));
      56       47394 :     }
      57             : 
      58             :     /// \brief Constructor.
      59             :     /// \param term A term
      60           4 :     explicit multi_action(const atermpp::aterm& term)
      61           4 :       : atermpp::aterm_appl(term)
      62             :     {
      63           4 :       assert(core::detail::check_term_TimedMultAct(*this));
      64           4 :     }
      65             : 
      66             :     /// \brief Constructor
      67         419 :     explicit multi_action(const process::action& l)
      68         838 :       : multi_action(process::action_list({ l }),data::undefined_real())
      69         419 :     {}
      70             : 
      71             :     /// \brief Returns true if time is available.
      72             :     /// \return True if time is available.
      73      170482 :     bool has_time() const
      74             :     {
      75      170482 :       return time() != data::undefined_real();
      76             :     }
      77             : 
      78             :     /// \brief Joins the actions of both multi actions.
      79             :     /// \pre The time of both multi actions must be equal.
      80           2 :     multi_action operator+(const multi_action& other) const
      81             :     {
      82           2 :       assert(time() == other.time());
      83           4 :       return multi_action(actions() + other.actions(), time());
      84             :     }
      85             : 
      86             :     /// \brief Returns the multiaction in which the list of actions is sorted. 
      87             :     /// \return A multi-action with a sorted list.
      88        2346 :     multi_action sort_actions() const
      89             :     {
      90        2346 :       if (actions().size()<=1)  // There is almost always only one action. 
      91             :       {
      92        2334 :         return *this;
      93             :       }
      94          24 :       return multi_action(atermpp::sort_list(actions()),time());
      95             :     }
      96             : 
      97             :    //--- end user section multi_action ---//
      98             : };
      99             : 
     100             : /// \\brief Make_multi_action constructs a new term into a given address.
     101             : /// \\ \param t The reference into which the new multi_action is constructed. 
     102             : template <class... ARGUMENTS>
     103        4973 : inline void make_multi_action(atermpp::aterm_appl& t, const ARGUMENTS&... args)
     104             : {
     105        4973 :   atermpp::make_term_appl(t, core::detail::function_symbol_TimedMultAct(), args...);
     106        4973 : }
     107             : 
     108             : /// \\brief list of multi_actions
     109             : typedef atermpp::term_list<multi_action> multi_action_list;
     110             : 
     111             : /// \\brief vector of multi_actions
     112             : typedef std::vector<multi_action>    multi_action_vector;
     113             : 
     114             : /// \\brief Test for a multi_action expression
     115             : /// \\param x A term
     116             : /// \\return True if \\a x is a multi_action expression
     117             : inline
     118         860 : bool is_multi_action(const atermpp::aterm_appl& x)
     119             : {
     120         860 :   return x.function() == core::detail::function_symbols::TimedMultAct;
     121             : }
     122             : 
     123             : // prototype declaration
     124             : std::string pp(const multi_action& x);
     125             : 
     126             : /// \\brief Outputs the object to a stream
     127             : /// \\param out An output stream
     128             : /// \\param x Object x
     129             : /// \\return The output stream
     130             : inline
     131           6 : std::ostream& operator<<(std::ostream& out, const multi_action& x)
     132             : {
     133           6 :   return out << lps::pp(x);
     134             : }
     135             : 
     136             : /// \\brief swap overload
     137             : inline void swap(multi_action& t1, multi_action& t2)
     138             : {
     139             :   t1.swap(t2);
     140             : }
     141             : //--- end generated class multi_action ---//
     142             : 
     143             : 
     144             : // template function overloads
     145             : lps::multi_action normalize_sorts(const multi_action& x, const data::sort_specification& sortspec);
     146             : lps::multi_action translate_user_notation(const lps::multi_action& x);
     147             : std::set<data::variable> find_all_variables(const lps::multi_action& x);
     148             : std::set<data::variable> find_free_variables(const lps::multi_action& x);
     149             : 
     150             : /// \cond INTERNAL_DOCS
     151             : namespace detail
     152             : {
     153             : 
     154             : /// \brief Visits all permutations of the arrays, and calls f for each instance.
     155             : /// \pre The range [first, last) contains sorted arrays.
     156             : /// \param first Start of a sequence of arrays
     157             : /// \param last End of a sequence of arrays
     158             : /// \param f A function
     159             : template <typename Iter, typename Function>
     160        1250 : void forall_permutations(Iter first, Iter last, Function f)
     161             : {
     162        1250 :   if (first == last)
     163             :   {
     164         684 :     f();
     165         684 :     return;
     166             :   }
     167         566 :   Iter next = first;
     168         566 :   ++next;
     169         566 :   forall_permutations(next, last, f);
     170         572 :   while (std::next_permutation(first->first, first->second))
     171             :   {
     172           6 :     forall_permutations(next, last, f);
     173             :   }
     174             : }
     175             : 
     176             : /// \brief Returns true if the actions in a and b have the same names, and the same sorts.
     177             : /// \pre a and b are sorted w.r.t. to the names of the actions.
     178             : /// \param a A sequence of actions
     179             : /// \param b A sequence of actions
     180             : /// \return True if the actions in a and b have the same names, and the same sorts.
     181        3021 : inline bool equal_action_signatures(const std::vector<process::action>& a, const std::vector<process::action>& b)
     182             : {
     183        3021 :   if (a.size() != b.size())
     184             :   {
     185         223 :     return false;
     186             :   }
     187        2798 :   std::vector<process::action>::const_iterator i, j;
     188        3371 :   for (i = a.begin(), j = b.begin(); i != a.end(); ++i, ++j)
     189             :   {
     190        2693 :     if (i->label() != j->label())
     191             :     {
     192        2120 :       return false;
     193             :     }
     194             :   }
     195         678 :   return true;
     196             : }
     197             : 
     198             : /// \brief Compares action labels
     199             : struct compare_action_labels
     200             : {
     201             :   /// \brief Function call operator
     202             :   /// \param a An action
     203             :   /// \param b An action
     204             :   /// \return The function result
     205         566 :   bool operator()(const process::action& a, const process::action& b) const
     206             :   {
     207         566 :     return a.label() < b.label();
     208             :   }
     209             : };
     210             : 
     211             : /// \brief Compares action labels and arguments
     212             : struct compare_action_label_arguments
     213             : {
     214             :   /// \brief Function call operator
     215             :   /// \param a An action
     216             :   /// \param b An action
     217             :   /// \return The function result
     218          36 :   bool operator()(const process::action& a, const process::action& b) const
     219             :   {
     220          36 :     if (a.label() != b.label())
     221             :     {
     222           4 :       return a.label() < b.label();
     223             :     }
     224          32 :     return a < b;
     225             :   }
     226             : };
     227             : 
     228             : /// \brief Used for building an expression for the comparison of data parameters.
     229             : struct equal_data_parameters_builder
     230             : {
     231             :   const std::vector<process::action>& a;
     232             :   const std::vector<process::action>& b;
     233             :   std::set<data::data_expression>& result;
     234             : 
     235         678 :   equal_data_parameters_builder(const std::vector<process::action>& a_,
     236             :                                 const std::vector<process::action>& b_,
     237             :                                 std::set<data::data_expression>& result_
     238             :                                )
     239         678 :     : a(a_),
     240         678 :       b(b_),
     241         678 :       result(result_)
     242         678 :   {}
     243             : 
     244             :   /// \brief Adds the expression 'a == b' to result.
     245         684 :   void operator()()
     246             :   {
     247         684 :     std::vector<data::data_expression> v;
     248         684 :     std::vector<process::action>::const_iterator i, j;
     249        1270 :     for (i = a.begin(), j = b.begin(); i != a.end(); ++i, ++j)
     250             :     {
     251         586 :       data::data_expression_list d1 = i->arguments();
     252         586 :       data::data_expression_list d2 = j->arguments();
     253         586 :       assert(d1.size() == d2.size());
     254         586 :       data::data_expression_list::iterator i1 = d1.begin(), i2 = d2.begin();
     255         909 :       for (     ; i1 != d1.end(); ++i1, ++i2)
     256             :       {
     257         323 :         v.push_back(data::lazy::equal_to(*i1, *i2));
     258             :       }
     259         586 :     }
     260         684 :     data::data_expression expr = data::lazy::join_and(v.begin(), v.end());
     261         684 :     result.insert(expr);
     262         684 :   }
     263             : };
     264             : 
     265             : /// \brief Used for building an expression for the comparison of data parameters.
     266             : struct not_equal_multi_actions_builder
     267             : {
     268             :   const std::vector<process::action>& a;
     269             :   const std::vector<process::action>& b;
     270             :   std::vector<data::data_expression>& result;
     271             : 
     272             :   not_equal_multi_actions_builder(const std::vector<process::action>& a_,
     273             :                                   const std::vector<process::action>& b_,
     274             :                                   std::vector<data::data_expression>& result_
     275             :                                  )
     276             :     : a(a_),
     277             :       b(b_),
     278             :       result(result_)
     279             :   {}
     280             : 
     281             :   /// \brief Adds the expression 'a == b' to result.
     282             :   void operator()()
     283             :   {
     284             :     using namespace data::lazy;
     285             : 
     286             :     std::vector<data::data_expression> v;
     287             :     std::vector<process::action>::const_iterator i, j;
     288             :     for (i = a.begin(), j = b.begin(); i != a.end(); ++i, ++j)
     289             :     {
     290             :       data::data_expression_list d1 = i->arguments();
     291             :       data::data_expression_list d2 = j->arguments();
     292             :       assert(d1.size() == d2.size());
     293             :       data::data_expression_list::iterator i1=d1.begin(), i2=d2.begin();
     294             :       for (   ; i1 != d1.end(); ++i1, ++i2)
     295             :       {
     296             :         v.push_back(data::not_equal_to(*i1, *i2));
     297             :       }
     298             :     }
     299             :     result.push_back(data::lazy::join_or(v.begin(), v.end()));
     300             :   }
     301             : };
     302             : 
     303             : } // namespace detail
     304             : /// \endcond
     305             : 
     306             : /// \brief Returns a data expression that expresses under which conditions the
     307             : /// multi actions a and b are equal. The multi actions may contain free variables.
     308             : /// \param a A sequence of actions
     309             : /// \param b A sequence of actions
     310             : /// \return Necessary conditions for the equality of a and b
     311        3021 : inline data::data_expression equal_multi_actions(const multi_action& a, const multi_action& b)
     312             : {
     313             : #ifdef MCRL2_EQUAL_MULTI_ACTIONS_DEBUG
     314             :   mCRL2log(debug) << "\n<equal multi actions>" << std::endl;
     315             :   mCRL2log(debug) << "a = " << process::pp(a.actions()) << std::endl;
     316             :   mCRL2log(debug) << "b = " << process::pp(b.actions()) << std::endl;
     317             : #endif
     318             :   using namespace data::lazy;
     319             : 
     320             :   // make copies of a and b and sort them
     321        3021 :   std::vector<process::action> va(a.actions().begin(), a.actions().end()); // protection not needed
     322        3021 :   std::vector<process::action> vb(b.actions().begin(), b.actions().end()); // protection not needed
     323        3021 :   std::sort(va.begin(), va.end(), detail::compare_action_label_arguments());
     324        3021 :   std::sort(vb.begin(), vb.end(), detail::compare_action_label_arguments());
     325             : 
     326        3021 :   if (!detail::equal_action_signatures(va, vb))
     327             :   {
     328             : #ifdef MCRL2_EQUAL_MULTI_ACTIONS_DEBUG
     329             :     mCRL2log(debug) << "different action signatures detected!" << std::endl;
     330             :     mCRL2log(debug) << "a = " << process::action_list(va.begin(), va.end()) << std::endl;
     331             :     mCRL2log(debug) << "b = " << process::action_list(vb.begin(), vb.end()) << std::endl;
     332             : #endif
     333        2343 :     return data::sort_bool::false_();
     334             :   }
     335             : 
     336             :   // compute the intervals of a with equal names
     337             :   typedef std::vector<process::action>::iterator action_iterator;
     338         678 :   std::vector<std::pair<action_iterator, action_iterator> > intervals;
     339         678 :   action_iterator first = va.begin();
     340        1243 :   while (first != va.end())
     341             :   {
     342         565 :     action_iterator next = std::upper_bound(first, va.end(), *first, detail::compare_action_labels());
     343         565 :     intervals.push_back(std::make_pair(first, next));
     344         565 :     first = next;
     345             :   }
     346             : 
     347         678 :   std::set<data::data_expression> z;
     348         678 :   detail::equal_data_parameters_builder f(va, vb, z);
     349         678 :   detail::forall_permutations(intervals.begin(), intervals.end(), f);
     350         678 :   data::data_expression result = data::lazy::join_or(z.begin(), z.end());
     351         678 :   return result;
     352        3021 : }
     353             : 
     354             : /// \brief Returns a pbes expression that expresses under which conditions the
     355             : /// multi actions a and b are not equal. The multi actions may contain free variables.
     356             : /// \param a A sequence of actions
     357             : /// \param b A sequence of actions
     358             : /// \return Necessary conditions for the inequality of a and b
     359             : inline data::data_expression not_equal_multi_actions(const multi_action& a, const multi_action& b)
     360             : {
     361             :   using namespace data::lazy;
     362             : 
     363             :   // make copies of a and b and sort them
     364             :   std::vector<process::action> va(a.actions().begin(), a.actions().end());
     365             :   std::vector<process::action> vb(b.actions().begin(), b.actions().end());
     366             :   std::sort(va.begin(), va.end(), detail::compare_action_label_arguments());
     367             :   std::sort(vb.begin(), vb.end(), detail::compare_action_label_arguments());
     368             : 
     369             :   if (!detail::equal_action_signatures(va, vb))
     370             :   {
     371             :     return data::sort_bool::true_();
     372             :   }
     373             : 
     374             :   // compute the intervals of a with equal names
     375             :   typedef std::vector<process::action>::iterator action_iterator;
     376             :   std::vector<std::pair<action_iterator, action_iterator> > intervals;
     377             :   action_iterator first = va.begin();
     378             :   while (first != va.end())
     379             :   {
     380             :     action_iterator next = std::upper_bound(first, va.end(), *first, detail::compare_action_labels());
     381             :     intervals.push_back(std::make_pair(first, next));
     382             :     first = next;
     383             :   }
     384             :   std::vector<data::data_expression> z;
     385             :   detail::not_equal_multi_actions_builder f(va, vb, z);
     386             :   detail::forall_permutations(intervals.begin(), intervals.end(), f);
     387             :   data::data_expression result = data::lazy::join_and(z.begin(), z.end());
     388             :   return result;
     389             : }
     390             : 
     391             : } // namespace lps
     392             : 
     393             : } // namespace mcrl2
     394             : 
     395             : namespace std
     396             : {
     397             : /// \brief specialization of the standard std::hash function for an action_label_string.
     398             : template<>
     399             : struct hash< mcrl2::lps::multi_action >
     400             : {
     401        7545 :   std::size_t operator()(const mcrl2::lps::multi_action& ma) const
     402             :   {
     403             :     std::hash<atermpp::aterm> hasher;
     404        7545 :     return hasher(ma.actions()) ^ (hasher(ma.time())<<1);
     405             :   }
     406             : };
     407             : 
     408             : } // namespace std
     409             : 
     410             : #endif // MCRL2_LPS_MULTI_ACTION_H

Generated by: LCOV version 1.14