LCOV - code coverage report
Current view: top level - lts/include/mcrl2/lts/detail - liblts_plts_merge.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 38 47 80.9 %
Date: 2024-05-01 03:37:31 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Hector Joao Rivera Verduzco
       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             : // This file contains the merge algorithm that merges two plts's.
      11             : // Merges an LTS L with this LTS (say K) and stores the resulting LTS
      12             : // (say M) in this LTS datastructure, effectively replacing K.
      13             : // Conceptually, we just take the union of the sets of states and the
      14             : // sets of transitions of K and L:
      15             : //   States_M      = States_K + States_L
      16             : //   Transitions_M = Transitions_K + Transitions_L
      17             : // where + denotes set union.
      18             : // However, this assumes that States_K and States_L are disjoint,
      19             : // which is generally not the case. More specifically we have:
      20             : //   States_K = { 0, ..., N_K - 1 }   and
      21             : //   States_L = { 0, ..., N_L - 1 }
      22             : // for some N_K, N_L > 0.
      23             : // Therefore, state i of L will be numbered |N_K| + i in the resulting
      24             : // LTS M and state i of K will be numbered i in M. This yields:
      25             : //   States_M = { 0, ..., N_K + N_L - 1 }.
      26             : 
      27             : 
      28             : #ifndef MCRL2_LTS_LIBLTS_PLTS_MERGE_H
      29             : #define MCRL2_LTS_LIBLTS_PLTS_MERGE_H
      30             : 
      31             : #include "mcrl2/lts/lts_aut.h"
      32             : #include "mcrl2/lts/lts_fsm.h"
      33             : #include "mcrl2/lts/lts_lts.h"
      34             : 
      35             : namespace mcrl2
      36             : {
      37             : namespace lts
      38             : {
      39             : namespace detail
      40             : {
      41             : 
      42             : template <class LTS_TYPE>
      43           6 : void plts_merge(LTS_TYPE& l1, const LTS_TYPE& l2)
      44             : {
      45           6 :   const std::size_t old_nstates=l1.num_states();
      46           6 :   const std::size_t old_n_prob_states = l1.num_probabilistic_states();
      47           6 :   l1.set_num_states(l1.num_states() + l2.num_states());
      48             : 
      49             :   // The resulting LTS will have state information only if BOTH LTSs
      50             :   // currently have state information.
      51           6 :   if (l1.has_state_info() && l2.has_state_info())
      52             :   {
      53           0 :     for (std::size_t i=0; i<l2.num_states(); ++i)
      54             :     {
      55           0 :       l1.add_state(l2.state_label(i));
      56             :     }
      57             :   }
      58             :   else
      59             :   {
      60             :     // remove state information from this LTS, if any
      61           6 :     l1.clear_state_labels();
      62             :   }
      63             : 
      64             :   // Before we can set the label data in a new transitions
      65             :   // array, we first have to collect the labels of both LTSs in a
      66             :   // map, of which the second element indicates the new index of each action label.
      67             : 
      68             :   typedef typename LTS_TYPE::action_label_t type1;
      69             :   typedef typename LTS_TYPE::labels_size_type type2;
      70             :   typedef typename std::pair< typename std::map < type1,type2 >::const_iterator, bool > insert_type;
      71           6 :   std::map < type1,type2 > labs;
      72             : 
      73             :   // Put the labels of the LTS l1 in a map.
      74          24 :   for (std::size_t i = 0; i < l1.num_action_labels(); ++i)
      75             :   {
      76          18 :     labs.insert(std::pair <typename LTS_TYPE::action_label_t,typename LTS_TYPE::labels_size_type>
      77             :                 (l1.action_label(i),i));
      78             :   }
      79             :   // Add the labels for the LTS l2, and put them there with a new index if it was
      80             :   // not added yet.
      81             :   // Furthermore, update the hidden_action_map. 
      82             :   // If label a1 is mapped on a2 in l2, then this must be the same
      83             :   // in l1. It may be that label a1 did not exist yet in which case it needs
      84             :   // to be added too.
      85             : 
      86             : 
      87          24 :   for (std::size_t i=0; i<l2.num_action_labels(); ++i)
      88             :   {
      89             :     typename LTS_TYPE::labels_size_type new_index;
      90          18 :     const insert_type it= labs.insert(std::pair < type1,type2 >
      91          18 :                                (l2.action_label(i),l1.num_action_labels()));
      92          18 :     if (it.second) 
      93             :     {
      94             :       // New element has been inserted.
      95           0 :       new_index=l1.add_action(l2.action_label(i));
      96           0 :       if (l2.is_tau(l2.apply_hidden_label_map(i)))
      97             :       {
      98           0 :         l1.hidden_label_set().insert(new_index);
      99             :       }
     100             :     }
     101             :     else 
     102             :     {
     103          18 :       new_index=it.first->second; // Old index to which i is mapped.
     104             :       // If label i occurred in l1 and were not both mapped to the hidden label, raise an exception.
     105          18 :       if (l1.is_tau(l1.apply_hidden_label_map(new_index)) != l2.is_tau(l2.apply_hidden_label_map(i)))
     106             :       {
     107           0 :         throw mcrl2::runtime_error("The action " + pp(l2.action_label(i)) + " has incompatible hidden actions " +
     108             :                                        pp(l1.action_label(l1.apply_hidden_label_map(new_index))) + " and " +
     109             :                                        pp(l2.action_label(l2.apply_hidden_label_map(i))) + ".");
     110             :       }
     111             : 
     112             :     }
     113          18 :     assert(new_index==it.first->second);
     114             :   }
     115             : 
     116             :   // Update the label numbers of all transitions of the LTS l1 to reflect
     117             :   // the new indices as given by labs.
     118           6 :   std::vector<transition> &trans1=l1.get_transitions();
     119          34 :   for (transition& t : trans1)
     120             :   {
     121          28 :     t.set_label(labs[l1.action_label(t.label())]);
     122             :   }
     123             : 
     124             :   // Now add the transition labels of LTS l2
     125             :   // Now add the source and target states of the transitions of LTS l2.
     126             :   // The labels will be added below, depending on whether there is label
     127             :   // information in both LTSs.
     128           6 :   const std::vector<transition> &trans2=l2.get_transitions();
     129          36 :   for (const transition transition_to_add : trans2)
     130             :   {
     131          30 :     l1.add_transition(transition(transition_to_add.from()+old_nstates,
     132          60 :                                  labs[l2.action_label(transition_to_add.label())],
     133          30 :                                  transition_to_add.to()+old_n_prob_states));
     134             :   }
     135             :   
     136             :   // Now update the state number for each probability pairs of all
     137             :   // probabilistic states
     138           6 :   const std::size_t n_prob_states_l2 = l2.num_probabilistic_states();
     139          18 :   for (std::size_t i = 0; i < n_prob_states_l2; ++i)
     140             :   {
     141          12 :     typename LTS_TYPE::probabilistic_state_t new_prob_state;
     142          12 :     const typename LTS_TYPE::probabilistic_state_t& old_prob_state = l2.probabilistic_state(i);
     143             : 
     144          12 :     if (old_prob_state.size()>1)
     145             :     {
     146          36 :       for (const typename LTS_TYPE::probabilistic_state_t::state_probability_pair& sp_pair : old_prob_state)
     147             :       {
     148          24 :         new_prob_state.add(sp_pair.state()+ old_nstates, sp_pair.probability());
     149             :       }
     150             : 
     151             :     }
     152             :     else
     153             :     {
     154           0 :       new_prob_state.set(old_prob_state.get()+old_nstates);
     155             :     }
     156          12 :     l1.add_probabilistic_state(new_prob_state);
     157             :   }
     158             : 
     159             :   // Add the initial probabilistic state of both plts at the end of the merged plts.
     160             :   // First add the initia probabilistic state of l1
     161           6 :   l1.add_probabilistic_state(l1.initial_probabilistic_state());
     162             : 
     163             :   // Then add the initia probabilistic state of l2
     164           6 :   typename LTS_TYPE::probabilistic_state_t new_initial_prob_state_l2;
     165           6 :   if (l2.initial_probabilistic_state().size()<=1)
     166             :   {
     167           6 :     new_initial_prob_state_l2.set(l2.initial_probabilistic_state().get() + old_nstates);
     168             :   }
     169             :   else // If the initial state is a distribution with more than one state.
     170             :   {
     171           0 :     for (const typename LTS_TYPE::probabilistic_state_t::state_probability_pair& sp_pair : l2.initial_probabilistic_state())
     172             :     {
     173           0 :       new_initial_prob_state_l2.add(sp_pair.state() + old_nstates, sp_pair.probability());
     174             :     }
     175             :   }
     176           6 :   l1.add_probabilistic_state(new_initial_prob_state_l2);
     177           6 : }
     178             : } // namespace detail
     179             : } // namespace lts
     180             : } // namespace mcrl2
     181             : 
     182             : 
     183             : #endif  // MCRL2_LTS_LIBLTS_PLTS_MERGE_H

Generated by: LCOV version 1.14