LCOV - code coverage report
Current view: top level - lts/include/mcrl2/lts - stochastic_lts_builder.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 117 130 90.0 %
Date: 2024-04-26 03:18:02 Functions: 21 26 80.8 %
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/lts/stochastic_stochastic_lts_builder.h
      10             : /// \brief add your file description here.
      11             : 
      12             : #ifndef MCRL2_LTS_STOCHASTIC_LTS_BUILDER_H
      13             : #define MCRL2_LTS_STOCHASTIC_LTS_BUILDER_H
      14             : 
      15             : #include "mcrl2/lts/lts_builder.h"
      16             : 
      17             : namespace mcrl2 {
      18             : 
      19             : namespace lts {
      20             : 
      21             : struct stochastic_lts_builder
      22             : {
      23             :   typedef atermpp::indexed_set<lps::state, mcrl2::utilities::detail::GlobalThreadSafe> indexed_set_for_states_type;
      24             :   // All LTS classes use integers to represent actions in transitions. A mapping from actions to integers
      25             :   // is needed to avoid duplicates.
      26             :   utilities::unordered_map_large<lps::multi_action, std::size_t> m_actions;
      27             : 
      28          18 :   stochastic_lts_builder()
      29          18 :   {
      30          36 :     lps::multi_action tau(process::action_list(), data::undefined_real());
      31          18 :     m_actions.emplace(std::make_pair(tau, m_actions.size()));
      32          18 :   }
      33             : 
      34         190 :   std::size_t add_action(const lps::multi_action& a)
      35             :   {
      36         190 :     auto i = m_actions.find(a);
      37         190 :     if (i == m_actions.end())
      38             :     {
      39          66 :       i = m_actions.emplace(std::make_pair(a, m_actions.size())).first;
      40             :     }
      41         190 :     return i->second;
      42             :   }
      43             : 
      44             :   // Set the initial (stochastic) state of the LTS
      45             :   virtual void set_initial_state(const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities) = 0;
      46             : 
      47             :   // Add a transition to the LTS
      48             :   virtual void add_transition(std::size_t from, const lps::multi_action& a, const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities, const std::size_t number_of_threads = 1) = 0;
      49             : 
      50             :   // Add actions and states to the LTS
      51             :   virtual void finalize(const indexed_set_for_states_type& state_map, bool timed) = 0;
      52             : 
      53             :   // Save the LTS to a file
      54             :   virtual void save(const std::string& filename) = 0;
      55             : 
      56          18 :   virtual ~stochastic_lts_builder() = default;
      57             : };
      58             : 
      59             : class stochastic_lts_none_builder: public stochastic_lts_builder
      60             : {
      61             :   public:
      62           0 :     void set_initial_state(const std::list<std::size_t>& /* to */, const std::vector<data::data_expression>& /* probabilities */) override
      63           0 :     {}
      64             : 
      65           0 :     void add_transition(std::size_t /* from */, const lps::multi_action& /* a */, const std::list<std::size_t>& /* targets */, const std::vector<data::data_expression>& /* probabilities */, const std::size_t /* number_of_threads */) override
      66           0 :     {}
      67             : 
      68           0 :     void finalize(const indexed_set_for_states_type& /* state_map */, bool /* timed */) override
      69           0 :     {}
      70             : 
      71           0 :     void save(const std::string& /* filename */) override
      72           0 :     {}
      73             : };
      74             : 
      75             : class stochastic_lts_aut_builder: public stochastic_lts_builder
      76             : {
      77             :   protected:
      78             :     struct stochastic_state
      79             :     {
      80             :       std::list<std::size_t> targets;
      81             :       std::vector<data::data_expression> probabilities;
      82             : 
      83             :       stochastic_state() = default;
      84             : 
      85          92 :       stochastic_state(std::list<std::size_t>  targets_, std::vector<data::data_expression>  probabilities_)
      86          92 :         : targets(std::move(targets_)), probabilities(std::move(probabilities_))
      87          92 :       {}
      88             : 
      89          92 :       void save_to_aut(std::ostream& out) const
      90             :       {
      91          92 :         auto j = targets.begin();
      92          92 :         out << *j++;
      93          92 :         if (targets.size() > 1)
      94             :         {
      95         168 :           for (auto i = probabilities.begin(); j != targets.end(); ++i, ++j)
      96             :           {
      97          84 :             out << " " << lps::print_probability(*i) << " " << *j;
      98             :           }
      99             :         }
     100          92 :       }
     101             :     };
     102             : 
     103             :     struct transition
     104             :     {
     105             :       std::size_t from;
     106             :       std::size_t label;
     107             :       std::size_t to;
     108             : 
     109          82 :       transition(std::size_t from_, std::size_t label_, std::size_t to_)
     110          82 :         : from(from_), label(label_), to(to_)
     111          82 :       {}
     112             : 
     113             :       bool operator<(const transition& other) const
     114             :       {
     115             :         return std::tie(from, label, to) < std::tie(other.from, other.label, other.to);
     116             :       }
     117             :     };
     118             : 
     119             :     std::vector<stochastic_state> m_stochastic_states;
     120             :     std::vector<transition> m_transitions;
     121             :     std::size_t m_number_of_states = 0;
     122             :     std::mutex m_exclusive_transition_access;
     123             : 
     124             :   public:
     125          10 :     stochastic_lts_aut_builder() = default;
     126             : 
     127             :     // Set the initial (stochastic) state of the LTS
     128          10 :     void set_initial_state(const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities) override
     129             :     {
     130          10 :       m_stochastic_states.emplace_back(targets, probabilities);
     131          10 :     }
     132             : 
     133             :     // Add a transition to the LTS
     134          82 :     void add_transition(std::size_t from, const lps::multi_action& a, const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities, const std::size_t number_of_threads) override
     135             :     {
     136          82 :       if (mcrl2::utilities::detail::GlobalThreadSafe && number_of_threads>1) m_exclusive_transition_access.lock();
     137          82 :       std::size_t to = m_stochastic_states.size();
     138          82 :       std::size_t label = add_action(a);
     139          82 :       m_stochastic_states.emplace_back(targets, probabilities);
     140          82 :       m_transitions.emplace_back(from, label, to);
     141          82 :       if (mcrl2::utilities::detail::GlobalThreadSafe && number_of_threads>1) m_exclusive_transition_access.unlock();
     142          82 :     }
     143             : 
     144             :     // Add actions and states to the LTS
     145          10 :     void finalize(const indexed_set_for_states_type& state_map, bool /* timed */) override
     146             :     {
     147          10 :       m_number_of_states = state_map.size();
     148          10 :     }
     149             : 
     150          10 :     void save(std::ostream& out) const
     151             :     {
     152          10 :       std::vector<lps::multi_action> actions{ m_actions.size() };
     153          50 :       for (const auto& p: m_actions)
     154             :       {
     155          40 :         actions[p.second] = p.first;
     156             :       }
     157             : 
     158          10 :       out << "des (";
     159          10 :       m_stochastic_states[0].save_to_aut(out);
     160          10 :       out << "," << m_transitions.size() << "," << m_number_of_states << ")" << "\n";
     161             : 
     162          92 :       for (const transition& t: m_transitions)
     163             :       {
     164          82 :         out << "(" << t.from << ",\"" << lps::pp(actions[t.label]) << "\",";
     165          82 :         m_stochastic_states[t.to].save_to_aut(out);
     166          82 :         out << ")" << "\n";
     167             :       }
     168          10 :     }
     169             : 
     170             :     // Save the LTS to a file
     171          10 :     void save(const std::string& filename) override
     172             :     {
     173          10 :       if (filename.empty())
     174             :       {
     175           0 :         save(std::cout);
     176             :       }
     177             :       else
     178             :       {
     179          10 :         std::ofstream out(filename.c_str());
     180          10 :         if (!out.is_open())
     181             :         {
     182           0 :           throw mcrl2::runtime_error("cannot create .aut file '" + filename + ".");
     183             :         }
     184          10 :         save(out);
     185          10 :         out.close();
     186          10 :       }
     187          10 :     }
     188             : };
     189             : 
     190             : class stochastic_lts_lts_builder: public stochastic_lts_builder
     191             : {
     192             :   protected:
     193             :     probabilistic_lts_lts_t m_lts;
     194             :     bool m_discard_state_labels = false;
     195             :     probabilistic_state<std::size_t, lps::probabilistic_data_expression> m_initial_state;
     196             :     std::mutex m_exclusive_transition_access;
     197             : 
     198             :   public:
     199           8 :     stochastic_lts_lts_builder(
     200             :       const data::data_specification& dataspec,
     201             :       const process::action_label_list& action_labels,
     202             :       const data::variable_list& process_parameters,
     203             :       bool discard_state_labels = false
     204             :     )
     205           8 :       : m_discard_state_labels(discard_state_labels)
     206             :     {
     207           8 :       m_lts.set_data(dataspec);
     208           8 :       m_lts.set_process_parameters(process_parameters);
     209           8 :       m_lts.set_action_label_declarations(action_labels);
     210           8 :     }
     211             : 
     212             :     static probabilistic_state<std::size_t, lps::probabilistic_data_expression> 
     213         116 :              make_probabilistic_state(const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities)
     214             :     {
     215         116 :       probabilistic_state<std::size_t, lps::probabilistic_data_expression> result;
     216         116 :       assert(targets.size()>0);
     217         116 :       if (targets.size()==1)
     218             :       {
     219           4 :         result.set(targets.front());
     220             :       }
     221             :       else 
     222             :       {
     223         112 :         std::list<std::size_t>::const_iterator ti = targets.begin();
     224         112 :         std::vector<data::data_expression>::const_iterator pi = probabilities.begin();
     225         336 :         for (; ti != targets.end(); ++pi, ++ti)
     226             :         {
     227         224 :           result.add(*ti, lps::probabilistic_data_expression(*pi));
     228             :         }
     229             :       }
     230         116 :       return result;
     231           0 :     }
     232             : 
     233             :     // Set the initial (stochastic) state of the LTS
     234           8 :     void set_initial_state(const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities) override
     235             :     {
     236           8 :       m_initial_state = make_probabilistic_state(targets, probabilities);
     237           8 :     }
     238             : 
     239             :     // Add a transition to the LTS
     240         108 :     void add_transition(std::size_t from, const lps::multi_action& a, const std::list<std::size_t>& targets, const std::vector<data::data_expression>& probabilities, const std::size_t number_of_threads) override
     241             :     {
     242         108 :       if (mcrl2::utilities::detail::GlobalThreadSafe && number_of_threads>1) m_exclusive_transition_access.lock();
     243         108 :       auto s1 = make_probabilistic_state(targets, probabilities);
     244         108 :       std::size_t label = add_action(a);
     245         108 :       std::size_t to = m_lts.add_probabilistic_state(s1);
     246         108 :       m_lts.add_transition(transition(from, label, to));
     247         108 :       if (mcrl2::utilities::detail::GlobalThreadSafe && number_of_threads>1) m_exclusive_transition_access.unlock();
     248             : 
     249         108 :     }
     250             : 
     251             :     // Add actions and states to the LTS
     252           8 :     void finalize(const indexed_set_for_states_type& state_map, bool timed) override
     253             :     {
     254             :       // add actions
     255           8 :       m_lts.set_num_action_labels(m_actions.size());
     256          52 :       for (const auto& p: m_actions)
     257             :       {
     258          44 :         m_lts.set_action_label(p.second, action_label_lts(lps::multi_action(p.first.actions(), p.first.time())));
     259             :       }
     260             : 
     261             :       // add state labels
     262           8 :       if (!m_discard_state_labels)
     263             :       {
     264           8 :         std::size_t n = state_map.size();
     265           8 :         std::vector<state_label_lts> state_labels(n);
     266         120 :         for (std::size_t i = 0; i < n; i++)
     267             :         {
     268         112 :           if (timed)
     269             :           {
     270           0 :             state_labels[i] = state_label_lts(remove_time_stamp(state_map[i]));
     271             :           }
     272             :           else
     273             :           {
     274         112 :             state_labels[i] = state_label_lts(state_map[i]);
     275             :           }
     276             :         }
     277           8 :         m_lts.state_labels() = std::move(state_labels);
     278           8 :       }
     279             : 
     280           8 :       m_lts.set_num_states(state_map.size(), true);
     281           8 :       m_lts.set_initial_probabilistic_state(m_initial_state); // This can't be done at the start :-(
     282           8 :     }
     283             : 
     284             :     // Save the LTS to a file
     285           4 :     void save(const std::string& filename) override
     286             :     {
     287           4 :       m_lts.save(filename);
     288           4 :     }
     289             : };
     290             : 
     291             : class stochastic_lts_fsm_builder: public stochastic_lts_lts_builder
     292             : {
     293             :   public:
     294             :     typedef stochastic_lts_lts_builder super;
     295           4 :     stochastic_lts_fsm_builder(const data::data_specification& dataspec, const process::action_label_list& action_labels, const data::variable_list& process_parameters)
     296           4 :       : super(dataspec, action_labels, process_parameters)
     297           4 :     { }
     298             : 
     299           4 :     void save(const std::string& filename) override
     300             :     {
     301           4 :       probabilistic_lts_fsm_t fsm;
     302           4 :       detail::lts_convert(m_lts, fsm);
     303           4 :       fsm.save(filename);
     304           4 :     }
     305             : };
     306             : 
     307             : inline
     308          18 : std::unique_ptr<stochastic_lts_builder> create_stochastic_lts_builder(const lps::stochastic_specification& lpsspec, const lps::explorer_options& options, lts_type output_format)
     309             : {
     310          18 :   switch (output_format)
     311             :   {
     312          10 :     case lts_aut: return std::make_unique<stochastic_lts_aut_builder>();
     313           4 :     case lts_lts: return std::make_unique<stochastic_lts_lts_builder>(lpsspec.data(), lpsspec.action_labels(), lpsspec.process().process_parameters(), options.discard_lts_state_labels);
     314           4 :     case lts_fsm: return std::make_unique<stochastic_lts_fsm_builder>(lpsspec.data(), lpsspec.action_labels(), lpsspec.process().process_parameters());
     315           0 :     default: return std::make_unique<stochastic_lts_none_builder>();
     316             :   }
     317             : }
     318             : 
     319             : } // namespace lts
     320             : 
     321             : } // namespace mcrl2
     322             : 
     323             : #endif // MCRL2_LTS_STOCHASTIC_LTS_BUILDER_H

Generated by: LCOV version 1.14