LCOV - code coverage report
Current view: top level - lts/include/mcrl2/lts - lts_utilities.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 73 81 90.1 %
Date: 2024-04-17 03:40:49 Functions: 13 14 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Jan Friso Groote
       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             : 
      10             : /** \file
      11             :  *
      12             :  * \brief This file contains some utility functions to manipulate lts's
      13             :  * \details The function in this file typically allow to present the
      14             :  *          transitions of a state space differently.
      15             :  * \author Jan Friso Groote
      16             :  */
      17             : 
      18             : #ifndef MCRL2_LTS_LTS_UTILITIES_H
      19             : #define MCRL2_LTS_LTS_UTILITIES_H
      20             : 
      21             : #include "mcrl2/lts/lts_lts.h"
      22             : 
      23             : namespace mcrl2
      24             : {
      25             : 
      26             : namespace lts
      27             : {
      28             : 
      29             : /** \brief Sorts the transitions using a sort style.
      30             :  * \param[in/out] transitions A vector of transitions to be sorted. 
      31             :  * \param[in] hidden_label_set A set that tells which actions are to be interpreted as being hidden.
      32             :  *            Sorting takes place after mapping hidden actions to zero.
      33             :  * \param[in] ts The sort style to use.
      34             :  */
      35             : 
      36         293 : inline void sort_transitions(std::vector<transition>& transitions, 
      37             :                       const std::set<transition::size_type>& hidden_label_set,
      38             :                       transition_sort_style ts = src_lbl_tgt)
      39             : {
      40         293 :   switch (ts)
      41             :   {
      42         132 :     case lbl_tgt_src:
      43             :     {
      44         132 :       const detail::compare_transitions_lts compare(hidden_label_set);
      45         132 :       sort(transitions.begin(),transitions.end(),compare);
      46         132 :       break;
      47             :     }
      48         161 :     case src_lbl_tgt:
      49             :     default:
      50             :     {
      51         161 :       const detail::compare_transitions_slt compare(hidden_label_set);
      52         161 :       sort(transitions.begin(),transitions.end(),compare);
      53         161 :       break;
      54             :     }
      55             :   }
      56         293 : }
      57             : 
      58             : /** \brief Sorts the transitions using a sort style.
      59             :  * \param[in/out] transitions A vector of transitions to be sorted. 
      60             :  * \param[in] ts The sort style to use.
      61             :  */
      62             : 
      63           1 : inline void sort_transitions(std::vector<transition>& transitions, transition_sort_style ts = src_lbl_tgt)
      64             : {
      65           1 :   sort_transitions(transitions, std::set<transition::size_type>(), ts);
      66           1 : }
      67             : 
      68             : 
      69             : namespace detail
      70             : {
      71             : 
      72             : // An indexed sorted vector below contains the outgoing or incoming transitions per state,
      73             : // grouped per state. The input consists of a vector of transitions. The incoming/outcoming
      74             : // tau transitions are grouped by state in the m_states_with_outgoing_or_incoming_transition. 
      75             : // It is as long as the lts aut has transitions. The vector m_indices is as long as the number
      76             : // of states plus 1. For each state it contains the place in the other vector where its tau transitions
      77             : // start. So, the tau transitions reside at position indices[s] to indices[s+1]. These indices
      78             : // can be acquired using the functions lowerbound and upperbound. 
      79             : // This data structure is chosen due to its minimal memory and time footprint. 
      80             : template <class CONTENT>
      81             : class indexed_sorted_vector_for_transitions
      82             : {
      83             :   protected:
      84             :     typedef std::size_t state_type;
      85             :     typedef std::size_t label_type;
      86             :     typedef std::pair<label_type,state_type> label_state_pair;
      87             : 
      88             :     std::vector < CONTENT > m_states_with_outgoing_or_incoming_transition;
      89             :     std::vector <size_t> m_indices;
      90             : 
      91             :   public:
      92             : 
      93         200 :     indexed_sorted_vector_for_transitions(const std::vector < transition >& transitions , state_type num_states, bool outgoing)
      94         200 :      : m_indices(num_states+1,0)
      95             :     {
      96             :       // First count the number of outgoing transitions per state and put it in indices.
      97        2281 :       for(const transition& t: transitions)
      98             :       {
      99        2081 :         m_indices[outgoing?t.from():t.to()]++;
     100             :       }
     101             : 
     102             :       // Calculate the m_indices where the states with outgoing/incoming tau transition must be placed.
     103             :       // Put the starting index for state i at position i-1. When placing the transitions these indices
     104             :       // are decremented properly. 
     105             :       
     106         200 :       size_t sum=0;
     107        1857 :       for(state_type& i: m_indices)  // The vector is changed. This must be a reference. 
     108             :       {
     109        1657 :         sum=sum+i;
     110        1657 :         i=sum;
     111             :       }
     112             : 
     113             :       // Now declare enough space for all transitions and store them in reverse order, while
     114             :       // at the same time decrementing the indices in m_indices. 
     115         200 :       m_states_with_outgoing_or_incoming_transition.resize(sum);
     116        2281 :       for(const transition& t: transitions)
     117             :       {
     118        2081 :         if (outgoing)
     119             :         {
     120        1424 :           assert(t.from()<m_indices.size());
     121        1424 :           assert(m_indices[t.from()]>0);
     122        1424 :           m_indices[t.from()]--;
     123        1424 :           assert(m_indices[t.from()] < m_states_with_outgoing_or_incoming_transition.size());
     124        1424 :           m_states_with_outgoing_or_incoming_transition[m_indices[t.from()]]=label_state_pair(t.label(), t.to());
     125             :         }
     126             :         else
     127             :         {
     128         657 :           assert(t.to()<m_indices.size());
     129         657 :           assert(m_indices[t.to()]>0);
     130         657 :           m_indices[t.to()]--;
     131         657 :           assert(m_indices[t.to()] < m_states_with_outgoing_or_incoming_transition.size());
     132         657 :           m_states_with_outgoing_or_incoming_transition[m_indices[t.to()]]=label_state_pair(t.label(), t.from());
     133             :         }
     134             :       }
     135         200 :       assert(m_indices.at(num_states)==m_states_with_outgoing_or_incoming_transition.size());
     136         200 :     }
     137             : 
     138             :     // Get the indexed transitions. 
     139        7911 :     const std::vector<CONTENT>& get_transitions() const
     140             :     {
     141        7911 :       return m_states_with_outgoing_or_incoming_transition;
     142             :     }
     143             :   
     144             :     // Get the lowest index of incoming/outging transitions stored in m_states_with_outgoing_or_incoming_transition.
     145        4816 :     size_t lowerbound(const state_type s) const
     146             :     {
     147        4816 :       assert(s+1<m_indices.size());
     148        4816 :       return m_indices[s];
     149             :     }
     150             : 
     151             :     // Get 1 beyond the higest index of incoming/outging transitions stored in m_states_with_outgoing_or_incoming_transition.
     152       12626 :     size_t upperbound(const state_type s) const
     153             :     {
     154       12626 :       assert(s+1<m_indices.size());
     155       12626 :       return m_indices[s+1];
     156             :     }
     157             : 
     158             :     // Drastically clear the vectors by resetting its memory usage to minimal. 
     159             :     void clear()   
     160             :     {
     161             :       std::vector <state_type>().swap(m_states_with_outgoing_or_incoming_transition);
     162             :       std::vector <size_t>().swap(m_indices);
     163             :       
     164             :     }
     165             : };
     166             : 
     167             : } // end namespace detail 
     168             : 
     169             : //
     170             : /// \brief Type for exploring transitions per state.
     171             : typedef std::pair<transition::size_type, transition::size_type> outgoing_pair_t;
     172             : 
     173             : typedef detail::indexed_sorted_vector_for_transitions < outgoing_pair_t > outgoing_transitions_per_state_t;
     174             : 
     175             : /// \brief Label of a pair of a label and target state. 
     176        7777 : inline std::size_t label(const outgoing_pair_t& p)
     177             : {
     178        7777 :   return p.first;
     179             : }
     180             : 
     181             : /// \brief Target state of a label state pair. 
     182        9122 : inline std::size_t to(const outgoing_pair_t& p)
     183             : {
     184        9122 :   return p.second;
     185             : }
     186             : 
     187             : /// \brief Type for exploring transitions per state and action.
     188             : // It can be considered to replace this function with an unordered_multimap.
     189             : // This may increase memory requirements, but would allow for constant versus logarithmic access times
     190             : // of elements. 
     191             : typedef std::multimap<std::pair<transition::size_type, transition::size_type>, transition::size_type>
     192             :                      outgoing_transitions_per_state_action_t;
     193             : 
     194             : /// \brief From state of an iterator exploring transitions per outgoing state and action.
     195             : inline std::size_t from(const outgoing_transitions_per_state_action_t::const_iterator& i)
     196             : {
     197             :   return i->first.first;
     198             : }
     199             : 
     200             : /// \brief Label of an iterator exploring transitions per outgoing state and action.
     201             : inline std::size_t label(const outgoing_transitions_per_state_action_t::const_iterator& i)
     202             : {
     203             :   return i->first.second;
     204             : }
     205             : 
     206             : /// \brief To state of an iterator exploring transitions per outgoing state and action.
     207        5556 : inline std::size_t to(const outgoing_transitions_per_state_action_t::const_iterator& i)
     208             : {
     209        5556 :   return i->second;
     210             : }
     211             : 
     212             : /// \brief Provide the transitions as a multimap accessible per from state and label.
     213             : inline outgoing_transitions_per_state_action_t transitions_per_outgoing_state_action_pair(const std::vector<transition>& trans)
     214             : {
     215             :   outgoing_transitions_per_state_action_t result;
     216             :   for (const transition& t: trans)
     217             :   {
     218             :     result.insert(std::pair<std::pair<transition::size_type, transition::size_type>, transition::size_type>(
     219             :                     std::pair<transition::size_type, transition::size_type>(t.from(), t.label()), t.to()));
     220             :   }
     221             :   return result;
     222             : }
     223             : 
     224             : /// \brief Provide the transitions as a multimap accessible per from state and label.
     225           0 : inline outgoing_transitions_per_state_action_t transitions_per_outgoing_state_action_pair(
     226             :                  const std::vector<transition>& trans, 
     227             :                  const std::set<transition::size_type>& hide_label_set)
     228             : {
     229           0 :   outgoing_transitions_per_state_action_t result;
     230           0 :   for (const transition& t: trans)
     231             :   {
     232           0 :     result.insert(std::pair<std::pair<transition::size_type, transition::size_type>, transition::size_type>(
     233           0 :                     std::pair<transition::size_type, transition::size_type>(t.from(), detail::apply_hidden_labels(t.label(),hide_label_set)), t.to()));
     234             :   }
     235           0 :   return result;
     236           0 : } 
     237             : 
     238             : /// \brief Provide the transitions as a multimap accessible per from state and label, ordered backwardly.
     239             : inline outgoing_transitions_per_state_action_t transitions_per_outgoing_state_action_pair_reversed(const std::vector<transition>& trans)
     240             : {
     241             :   outgoing_transitions_per_state_action_t result;
     242             :   for (const transition& t: trans)
     243             :   {
     244             :     result.insert(std::pair<std::pair<transition::size_type, transition::size_type>, transition::size_type>(
     245             :                     std::pair<transition::size_type, transition::size_type>(t.to(), t.label()), t.from()));
     246             :   }
     247             :   return result;
     248             : }
     249             : 
     250             : /// \brief Provide the transitions as a multimap accessible per from state and label, ordered backwardly.
     251          54 : inline outgoing_transitions_per_state_action_t transitions_per_outgoing_state_action_pair_reversed(
     252             :                 const std::vector<transition>& trans,
     253             :                 const std::set<transition::size_type>& hide_label_set)
     254             : {
     255          54 :   outgoing_transitions_per_state_action_t result;
     256         619 :   for (const transition& t: trans)
     257             :   {
     258         565 :     result.insert(std::pair<std::pair<transition::size_type, transition::size_type>, transition::size_type>(
     259        1130 :                     std::pair<transition::size_type, transition::size_type>(t.to(), detail::apply_hidden_labels(t.label(),hide_label_set)), t.from()));
     260             :   }
     261          54 :   return result;
     262           0 : } 
     263             : 
     264             : namespace detail
     265             : {
     266             : // Yields a label with an obscure name referring to divergence.
     267             : 
     268             : template < class LABEL_TYPE >
     269             : // LABEL_TYPE make_divergence_label(const std::string& s, const LABEL_TYPE& l)
     270          16 : LABEL_TYPE make_divergence_label(const std::string& s)
     271             : {
     272          16 :   return LABEL_TYPE(s);
     273             : }
     274             : 
     275             : template <>
     276             : inline mcrl2::lts::action_label_lts make_divergence_label<mcrl2::lts::action_label_lts>(const std::string& s)
     277             : {
     278             :   return action_label_lts(lps::multi_action(process::action(process::action_label(core::identifier_string(s),
     279             :                                                                                   data::sort_expression_list()),
     280             :                                                             data::data_expression_list())));
     281             : }
     282             : 
     283             : // Make a new divergent_transition_label and replace each self loop with it.
     284             : // Return the number of the divergent transition label.
     285             : template < class LTS_TYPE >
     286          16 : std::size_t mark_explicit_divergence_transitions(LTS_TYPE& l)
     287             : {
     288             :   // Below we create an odd action label, representing divergence.
     289          32 :   const typename LTS_TYPE::action_label_t lab=make_divergence_label<typename LTS_TYPE::action_label_t>("!@*&divergence&*@!"); 
     290          16 :   std::size_t divergent_transition_label=l.add_action(lab);
     291          16 :   assert(divergent_transition_label+1==l.num_action_labels());
     292         107 :   for(transition& t: l.get_transitions())
     293             :   {
     294          91 :     if (l.is_tau(l.apply_hidden_label_map(t.label())) && t.to()==t.from())
     295             :     {
     296           8 :       t = transition(t.to(),divergent_transition_label,t.to());
     297             :     }
     298             :   }
     299          16 :   return divergent_transition_label;
     300          16 : }
     301             : 
     302             : // Replace each transition in a state that is an outgoing divergent_transition with a tau_loop in that state.
     303             : template < class LTS_TYPE >
     304          16 : void unmark_explicit_divergence_transitions(LTS_TYPE& l, const std::size_t divergent_transition_label)
     305             : {
     306         103 :   for(transition& t: l.get_transitions())
     307             :   {
     308          87 :     if (t.label()==divergent_transition_label)
     309             :     { 
     310           8 :       t = transition(t.from(),l.tau_label_index(),t.from());
     311             :     }
     312             :   }
     313          16 : }
     314             : 
     315             : } // namespace detail
     316             : 
     317             : }
     318             : }
     319             : 
     320             : #endif // MCRL2_LTS_LTS_UTILITIES_H

Generated by: LCOV version 1.14