LCOV - code coverage report
Current view: top level - pbes/include/mcrl2/pbes/detail - stategraph_local_algorithm.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 369 598 61.7 %
Date: 2024-04-21 03:44:01 Functions: 30 41 73.2 %
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/detail/stategraph_local_algorithm.h
      10             : /// \brief add your file description here.
      11             : 
      12             : #ifndef MCRL2_PBES_DETAIL_STATEGRAPH_LOCAL_ALGORITHM_H
      13             : #define MCRL2_PBES_DETAIL_STATEGRAPH_LOCAL_ALGORITHM_H
      14             : 
      15             : #include "mcrl2/pbes/algorithms.h"
      16             : #include "mcrl2/pbes/detail/stategraph_algorithm.h"
      17             : 
      18             : namespace mcrl2 {
      19             : 
      20             : namespace pbes_system {
      21             : 
      22             : namespace detail {
      23             : 
      24             : struct default_rules_predicate
      25             : {
      26             :   const local_control_flow_graph& V;
      27             : 
      28          11 :   default_rules_predicate(const local_control_flow_graph& V_)
      29          11 :     : V(V_)
      30          11 :   {}
      31             : 
      32          15 :   bool operator()(const core::identifier_string& X, std::size_t i) const
      33             :   {
      34          15 :     return V.has_label(X, i);
      35             :   }
      36             : };
      37             : 
      38             : class belongs_relation
      39             : {
      40             :   protected:
      41             :     typedef std::map<core::identifier_string, std::set<data::variable> > belongs_map;
      42             : 
      43             :     belongs_map m_belongs_map;
      44             : 
      45             :   public:
      46          18 :     const std::set<data::variable>& operator[](const core::identifier_string& X) const
      47             :     {
      48          18 :       auto i = m_belongs_map.find(X);
      49          18 :       if (i == m_belongs_map.end())
      50             :       {
      51           0 :         throw mcrl2::runtime_error("unknown key encountered in belongs_relation::operator[]");
      52             :       }
      53          18 :       return i->second;
      54             :     }
      55             : 
      56             :     belongs_map::iterator begin()
      57             :     {
      58             :       return m_belongs_map.begin();
      59             :     }
      60             : 
      61           6 :     belongs_map::const_iterator begin() const
      62             :     {
      63           6 :       return m_belongs_map.begin();
      64             :     }
      65             : 
      66             :     belongs_map::iterator end()
      67             :     {
      68             :       return m_belongs_map.end();
      69             :     }
      70             : 
      71          19 :     belongs_map::const_iterator end() const
      72             :     {
      73          19 :       return m_belongs_map.end();
      74             :     }
      75             : 
      76             :     belongs_map::iterator find(const core::identifier_string& X)
      77             :     {
      78             :       return m_belongs_map.find(X);
      79             :     }
      80             : 
      81          13 :     belongs_map::const_iterator find(const core::identifier_string& X) const
      82             :     {
      83          13 :       return m_belongs_map.find(X);
      84             :     }
      85             : 
      86          13 :     std::set<data::variable>& operator[](const core::identifier_string& X)
      87             :     {
      88          13 :       return m_belongs_map[X];
      89             :     }
      90             : 
      91             :     std::size_t size() const
      92             :     {
      93             :       return m_belongs_map.size();
      94             :     }
      95             : 
      96             :     std::string print() const
      97             :     {
      98             :       std::ostringstream out;
      99             :       out << "{";
     100             :       for (auto i = m_belongs_map.begin(); i != m_belongs_map.end(); ++i)
     101             :       {
     102             :         if (i != m_belongs_map.begin())
     103             :         {
     104             :           out << ", ";
     105             :         }
     106             :         out << i->first << " -> " << core::detail::print_set(i->second);
     107             :       }
     108             :       out << "}";
     109             :       return out.str();
     110             :     }
     111             : };
     112             : 
     113             : /// \brief Algorithm class for the local variant of the stategraph algorithm
     114             : class stategraph_local_algorithm: public stategraph_algorithm
     115             : {
     116             :   public:
     117             :     typedef stategraph_algorithm super;
     118             : 
     119             :   protected:
     120             :     // m_belongs[k] corresponds with m_control_flow_graphs[k]
     121             :     std::vector<belongs_relation> m_belongs;
     122             : 
     123             :     // if true, marking updates will be cached in the nodes of the local CFGs
     124             :     bool m_cache_marking_updates;
     125             : 
     126             :     std::size_t m_marking_rewrite_count;
     127             : 
     128             :     std::size_t m_marking_rewrite_cached_count;
     129             : 
     130             :     std::vector<core::identifier_string> binding_variable_names() const
     131             :     {
     132             :       std::vector<core::identifier_string> result;
     133             :       auto const& equations = m_pbes.equations();
     134             :       for (const stategraph_equation& equation: equations)
     135             :       {
     136             :         result.push_back(equation.variable().name());
     137             :       }
     138             :       return result;
     139             :     }
     140             : 
     141             :     struct vertex_pair
     142             :     {
     143             :       const local_control_flow_graph_vertex* u;
     144             :       const local_control_flow_graph_vertex* v;
     145             :       std::size_t k; // index of the graph
     146             : 
     147           0 :       vertex_pair(const local_control_flow_graph_vertex* u_, const local_control_flow_graph_vertex* v_, std::size_t k_)
     148           0 :         : u(u_), v(v_), k(k_)
     149           0 :       {}
     150             : 
     151           0 :       bool operator<(const vertex_pair& other) const
     152             :       {
     153           0 :         return u < other.u || (u == other.u && v < other.v);
     154             :       }
     155             :     };
     156             : 
     157             :     struct equation_label_pair
     158             :     {
     159             :       const core::identifier_string X;
     160             :       std::size_t i; // label
     161             : 
     162           0 :       equation_label_pair(const core::identifier_string& X_, std::size_t i_)
     163           0 :         : X(X_), i(i_)
     164           0 :       {}
     165             : 
     166           0 :       bool operator<(const equation_label_pair& other) const
     167             :       {
     168           0 :         return X < other.X || (X == other.X && i < other.i);
     169             :       }
     170             :     };
     171             : 
     172             :     // maps (X, i) to the set of all edges with label i and source vertex with name X
     173             :     std::map<core::identifier_string, std::map<std::size_t, std::set<vertex_pair> > > m_edge_index;
     174             : 
     175           0 :     void compute_edge_index()
     176             :     {
     177           0 :       for (std::size_t k = 0; k < m_local_control_flow_graphs.size(); k++)
     178             :       {
     179           0 :         auto const& Gk = m_local_control_flow_graphs[k];
     180           0 :         auto const& vertices = Gk.vertices;
     181           0 :         for (const auto& u: vertices)
     182             :         {
     183           0 :           auto const& X = u.name();
     184           0 :           auto const& outgoing_edges = u.outgoing_edges();
     185           0 :           for(const auto& e: outgoing_edges)
     186             :           {
     187           0 :             auto const& v = *(e.first);
     188           0 :             auto const& I = e.second;
     189           0 :             for (std::size_t i: I)
     190             :             {
     191           0 :               m_edge_index[X][i].insert(vertex_pair(&u, &v, k));
     192             :             }
     193             :           }
     194             :         }
     195             :       }
     196           0 :     }
     197             : 
     198           0 :     std::string print_edge_index()
     199             :     {
     200           0 :       mCRL2log(log::debug) << "--- computed marking edge index ---" << std::endl;
     201           0 :       auto const& equations = m_pbes.equations();
     202           0 :       std::ostringstream out;
     203             : 
     204           0 :       for (const stategraph_equation& eq_X: equations)
     205             :       {
     206           0 :         auto const& X = eq_X.variable().name();
     207           0 :         auto& EX = m_edge_index[X];
     208           0 :         out << "index for equation " << X << std::endl;
     209           0 :         for (std::size_t i = 0; i < eq_X.predicate_variables().size(); i++)
     210             :         {
     211           0 :           auto& EXi = EX[i];
     212           0 :           for (const auto& ei: EXi)
     213             :           {
     214           0 :             out << " edge " << *ei.u << " --" << i << "--> " << *ei.v << std::endl;
     215             :           }
     216             :         }
     217             :       }
     218           0 :       return out.str();
     219           0 :     }
     220             : 
     221             :     // prints a belong set
     222           0 :     std::string print_belong_set(const stategraph_equation& eq, const std::set<std::size_t>& belongs) const
     223             :     {
     224           0 :       std::set<data::variable> v;
     225           0 :       for (std::size_t i: belongs)
     226             :       {
     227           0 :         v.insert(eq.parameters()[i]);
     228             :       }
     229           0 :       return core::detail::print_set(v);
     230           0 :     }
     231             : 
     232             :     // prints a subset of parameters of the equation corresponding to X
     233             :     // I is a set of indices of parameters of the equation corresponding to X
     234           0 :     std::string print_parameters(const core::identifier_string& X, const std::set<std::size_t>& I) const
     235             :     {
     236           0 :       auto const& eq_X = *find_equation(m_pbes, X);
     237           0 :       auto const& param = eq_X.parameters();
     238           0 :       std::ostringstream out;
     239           0 :       out << "{";
     240           0 :       for (auto i = I.begin(); i != I.end(); ++i)
     241             :       {
     242           0 :         if (i != I.begin())
     243             :         {
     244           0 :           out << ", ";
     245             :         }
     246           0 :         out << "(" << *i << ", " << param[*i] << ")";
     247             :       }
     248           0 :       out << "}";
     249           0 :       return out.str();
     250           0 :     }
     251             : 
     252             :     template <typename RulesPredicate>
     253           2 :     belongs_relation compute_belongs(const local_control_flow_graph& Vk, RulesPredicate rules)
     254             :     {
     255             :       using utilities::detail::contains;
     256             : 
     257           2 :       std::set<core::identifier_string> Nk; // Nk contains the names of the vertices in Vk
     258           6 :       for (const auto& v: Vk.vertices)
     259             :       {
     260           4 :         Nk.insert(v.name());
     261             :       }
     262             : 
     263           2 :       belongs_relation Bk;
     264           2 :       auto const& equations = m_pbes.equations();
     265          10 :       for (const stategraph_equation& eqn: equations)
     266             :       {
     267           4 :         auto const& X = eqn.variable().name();
     268           4 :         if (!contains(Nk, X))
     269             :         {
     270           0 :           continue;
     271             :         }
     272           4 :         Bk[X]; // force the creation of an empty set corresponding to X
     273           4 :         auto const& eq_X = *find_equation(m_pbes, X);
     274           4 :         auto const& dpX = eq_X.data_parameter_indices();
     275           4 :         std::set<std::size_t> belongs(dpX.begin(), dpX.end());
     276           4 :         mCRL2log(log::trace) << "  initial belong set for equation " << X << " = " << print_belong_set(eq_X, belongs) << std::endl;
     277             : 
     278           4 :         auto const& predvars = eq_X.predicate_variables();
     279          10 :         for (std::size_t i = 0; i < predvars.size(); i++)
     280             :         {
     281           6 :           auto const& Ye = predvars[i];
     282          12 :           for (auto j = belongs.begin(); j != belongs.end(); )
     283             :           {
     284           6 :             std::size_t m = *j;
     285           6 :             if ((contains(Ye.used(), m) || contains(Ye.changed(), m)) && !rules(X, i))
     286             :             {
     287           2 :               mCRL2log(log::trace) << " remove (X, i, m) = (" << X << ", " << i << ", " << m << ") variable=" << eq_X.parameters()[m] << " from belongs " << std::endl;
     288           2 :               mCRL2log(log::trace) << "  used = " << print_parameters(Ye.name(), Ye.used()) << " changed = " << print_parameters(Ye.name(), Ye.changed()) << std::endl;
     289           2 :               belongs.erase(j++);
     290             :             }
     291             :             else
     292             :             {
     293           4 :               ++j;
     294             :             }
     295             :           }
     296             :         }
     297           4 :         mCRL2log(log::trace) << "  final   belong set for equation " << X << " = " << print_belong_set(eq_X, belongs) << std::endl;
     298           6 :         for (std::size_t i: belongs)
     299             :         {
     300           2 :           Bk[X].insert(eq_X.parameters()[i]);
     301             :         }
     302             :       }
     303             : 
     304           4 :       return Bk;
     305           2 :     }
     306             : 
     307           1 :     void compute_belongs()
     308             :     {
     309           1 :       assert(m_local_control_flow_graphs.size() == m_connected_components_values.size());
     310           1 :       mCRL2log(log::debug) << "=== computing belongs relation ===" << std::endl;
     311           3 :       for (std::size_t k = 0; k < m_local_control_flow_graphs.size(); k++)
     312             :       {
     313           2 :         mCRL2log(log::debug) << "--- compute belongs for graph " << k << " ---" << std::endl;
     314           2 :         auto const& Vk = m_local_control_flow_graphs[k];
     315           2 :         belongs_relation Bk = compute_belongs(Vk, default_rules_predicate(Vk));
     316           2 :         m_belongs.push_back(Bk);
     317           2 :       }
     318           1 :     }
     319             : 
     320           2 :     std::string print_belongs(const belongs_relation& B) const
     321             :     {
     322           2 :       std::ostringstream out;
     323           6 :       for (const auto& b: B)
     324             :       {
     325           4 :         out << b.first << " -> " << core::detail::print_set(b.second) << std::endl;
     326             :       }
     327           4 :       return out.str();
     328           2 :     }
     329             : 
     330           1 :     void print_belongs() const
     331             :     {
     332           1 :       std::ostringstream out;
     333           1 :       out << "\n=== belongs relation ===\n";
     334           3 :       for (std::size_t k = 0; k < m_belongs.size(); k++)
     335             :       {
     336           2 :         out << "--- belongs relation for graph " << k << " ---" << std::endl;
     337           2 :         auto const& Bk = m_belongs[k];
     338           2 :         out << print_belongs(Bk);
     339             :       }
     340           1 :       mCRL2log(log::debug) << out.str() << std::endl;
     341           1 :     }
     342             : 
     343           6 :     std::set<data::variable> significant_variables(const local_control_flow_graph_vertex& u) const
     344             :     {
     345           6 :       const core::identifier_string& X = u.name();
     346           6 :       const pbes_equation& eq_X = *find_equation(m_pbes, X);
     347           6 :       pbes_expression phi = eq_X.formula();
     348           6 :       if (u.index() != data::undefined_index())
     349             :       {
     350           2 :         data::rewriter::substitution_type sigma;
     351           2 :         sigma[u.variable()] = u.value();
     352           2 :         pbes_system::simplify_data_rewriter<data::rewriter> pbesr(m_datar);
     353           2 :         phi = pbesr(phi, sigma);
     354           2 :       }
     355          12 :       return pbes_system::algorithms::significant_variables(phi);
     356           6 :     }
     357             : 
     358             :     // returns the index of variable d in the vector d_Y
     359           6 :     std::size_t find_parameter_index(const std::vector<data::variable>& d_Y, const data::variable& d) const
     360             :     {
     361           6 :       auto i = std::find(d_Y.begin(), d_Y.end(), d);
     362           6 :       if (i == d_Y.end())
     363             :       {
     364           0 :         throw mcrl2::runtime_error("find_parameter_index: variable not found!");
     365             :       }
     366           6 :       return i - d_Y.begin();
     367             :     }
     368             : 
     369           1 :     bool belongs_contains(const belongs_relation& B,
     370             :                           const core::identifier_string& X,
     371             :                           const data::variable& d
     372             :                          ) const
     373             :     {
     374           1 :       auto i = B.find(X);
     375           1 :       if (i == B.end())
     376             :       {
     377           0 :         return false;
     378             :       }
     379           1 :       return utilities::detail::contains(i->second, d);
     380             :     }
     381             : 
     382             :     // returns the intersection of V with { d | (X, d) in B }
     383          12 :     std::set<data::variable> belongs_intersection(const std::set<data::variable>& V,
     384             :                                                   const belongs_relation& B,
     385             :                                                   const core::identifier_string& X
     386             :                                                  )
     387             :     {
     388          12 :       auto i = B.find(X);
     389          12 :       if (i == B.end())
     390             :       {
     391           0 :         return std::set<data::variable>();
     392             :       }
     393          12 :       return utilities::detail::set_intersection(V, i->second);
     394             :     }
     395             : 
     396             :     template <typename Substitution>
     397           6 :     data::data_expression rewr(const data::data_expression& x, Substitution sigma)
     398             :     {
     399           6 :       return m_datar(x, sigma);
     400             :     }
     401             : 
     402           6 :     std::set<data::variable> marking_update(const local_control_flow_graph_vertex& u,
     403             :                                             std::size_t i,
     404             :                                             const data::variable& d,
     405             :                                             const data::data_expression_list& e,
     406             :                                             const stategraph_equation& eq_Y,
     407             :                                             const belongs_relation& B)
     408             :     {
     409           6 :       if (m_cache_marking_updates)
     410             :       {
     411             :         // check if the update is cached in u
     412           0 :         std::pair<std::size_t, data::variable> p(i, d);
     413           0 :         auto const& marking_update = u.marking_update();
     414           0 :         auto j = marking_update.find(p);
     415           0 :         if (j != marking_update.end())
     416             :         {
     417           0 :           m_marking_rewrite_count++;
     418           0 :           m_marking_rewrite_cached_count++;
     419           0 :           return j->second;
     420             :         }
     421           0 :       }
     422             : 
     423             :       // compute the value
     424           6 :       auto const& X = u.name();
     425           6 :       std::size_t l = find_parameter_index(eq_Y.parameters(), d);
     426           6 :       data::rewriter::substitution_type sigma;
     427           6 :       sigma[u.variable()] = u.value();
     428          12 :       auto W = FV(rewr(nth_element(e, l), sigma));
     429           6 :       std::set<data::variable> V = belongs_intersection(W, B, X);
     430           6 :       if (m_cache_marking_updates)
     431             :       {
     432           0 :         u.set_marking_update(i, d, V);
     433             :       }
     434           6 :       m_marking_rewrite_count++;
     435           6 :       return V;
     436           6 :     }
     437             : 
     438           1 :     void print_marking_statistics()
     439             :     {
     440           1 :       mCRL2log(log::verbose) << "--- marking statistics: " << m_marking_rewrite_count << " rewrite calls, from which " << m_marking_rewrite_cached_count << " were cached" << std::endl;
     441           1 :     }
     442             : 
     443             :     // updates u.marking
     444             :     // returns true if u.marking has changed
     445          12 :     bool update_marking_rule(const belongs_relation& B,
     446             :                              const local_control_flow_graph_vertex& u,
     447             :                              std::size_t i,
     448             :                              const local_control_flow_graph_vertex& v,
     449             :                              bool check_belongs // false corresponds with rule1, true corresponds with rule2
     450             :                             )
     451             :     {
     452          12 :       std::size_t size = u.marking().size();
     453          12 :       auto const& X = u.name();
     454          12 :       auto const& eq_X = *find_equation(m_pbes, X);
     455          12 :       auto const& Y = v.name();
     456          12 :       auto const& eq_Y = *find_equation(m_pbes, Y);
     457          12 :       auto const& Ye = eq_X.predicate_variables()[i];
     458          12 :       auto const& e = Ye.parameters();
     459          12 :       auto m = v.marking(); // N.B. a copy must be made, to handle the case u == v properly
     460          18 :       for (const data::variable& d: m)
     461             :       {
     462           6 :         if (check_belongs && belongs_contains(B, Y, d))
     463             :         {
     464           0 :           continue;
     465             :         }
     466           6 :         auto const update = marking_update(u, i, d, e, eq_Y, B);
     467           6 :         u.extend_marking(update);
     468           6 :       }
     469          24 :       return u.marking().size() != size;
     470          12 :     }
     471             : 
     472             :     // returns true if there is a vertex u in V and an edge (u, i, v) in V, such that u.name() == X
     473           4 :     bool has_incoming_edge(const local_control_flow_graph& /* V */, const local_control_flow_graph_vertex& v, const core::identifier_string& X, std::size_t i) const
     474             :     {
     475             :       using utilities::detail::contains;
     476             : 
     477           4 :       auto const& incoming_edges = v.incoming_edges();
     478           4 :       for(const auto& e: incoming_edges)
     479             :       {
     480           2 :         auto const& u = *e.first;
     481           2 :         auto const& I = e.second;
     482           2 :         if (u.name() == X && contains(I, i))
     483             :         {
     484           2 :           return true;
     485             :         }
     486             :       }
     487           2 :       return false;
     488             :     }
     489             : 
     490           1 :     void compute_control_flow_marking()
     491             :     {
     492           1 :       mCRL2log(log::debug) << "=== computing control flow marking ===" << std::endl;
     493             :       using utilities::detail::pick_element;
     494             : 
     495           1 :       start_timer("marking initialization");
     496           1 :       std::size_t J = m_local_control_flow_graphs.size();
     497           4 :       for (std::size_t j = 0; j < J; j++)
     498             :       {
     499           3 :         auto const& Vj = m_local_control_flow_graphs[j];
     500           3 :         auto const& Bj = m_belongs[j];
     501           9 :         for (const auto& u : Vj.vertices)
     502             :         {
     503           6 :           auto const& X = u.name();
     504           6 :           u.set_marking(belongs_intersection(significant_variables(u), Bj, X));
     505             :         }
     506           3 :         mCRL2log(log::debug) << "--- initial control flow marking for graph " << j << "\n" << Vj.print_marking();
     507             :       }
     508           1 :       finish_timer("marking initialization");
     509             : 
     510           1 :       start_timer("marking computation");
     511           1 :       bool stable = false;
     512           3 :       while (!stable)
     513             :       {
     514           2 :         bool stableint = false;
     515           4 :         while (!stableint)
     516             :         {
     517           2 :           stableint = true;
     518           8 :           for (std::size_t j = 0; j < J; j++)
     519             :           {
     520           6 :             auto const& Vj = m_local_control_flow_graphs[j];
     521           6 :             auto const& Bj = m_belongs[j];
     522           6 :             std::set<const local_control_flow_graph_vertex*> todo;
     523          18 :             for (const auto& v: Vj.vertices)
     524             :             {
     525          12 :               todo.insert(&v);
     526             :             }
     527          18 :             while (!todo.empty())
     528             :             {
     529          12 :               auto const& v = *pick_element(todo);
     530             : 
     531          12 :               mCRL2log(log::trace) << " extend marking rule1: v = " << v << " marking(v) = " << core::detail::print_set(v.marking()) << std::endl;
     532             : 
     533          12 :               auto const& incoming_edges = v.incoming_edges();
     534          22 :               for (const auto& e: incoming_edges)
     535             :               {
     536          10 :                 bool changed = false;
     537          10 :                 auto const& u = *e.first;
     538          10 :                 auto const& labels = e.second;
     539          20 :                 for (std::size_t i: labels)
     540             :                 {
     541             :                     // consider edge (u, i, v)
     542          10 :                     bool updated = update_marking_rule(Bj, u, i, v, false);
     543          10 :                     changed = changed || updated;
     544             :                 }
     545          10 :                 if (changed)
     546             :                 {
     547           0 :                   mCRL2log(log::trace) << "   marking(u)' = " << core::detail::print_set(u.marking()) << std::endl;
     548           0 :                   todo.insert(&u);
     549           0 :                   stableint = false;
     550             :                 }
     551             :               }
     552             :             }
     553           6 :           }
     554             :         }
     555             : 
     556           2 :         bool stableext = false;
     557           5 :         while (!stableext)
     558             :         {
     559           3 :           stableext = true;
     560          12 :           for (std::size_t j = 0; j < J; j++)
     561             :           {
     562           9 :             auto const& Vj = m_local_control_flow_graphs[j];
     563           9 :             auto const& Bj = m_belongs[j];
     564          27 :             for (const auto &u : Vj.vertices)
     565             :             {
     566          18 :               auto const& X = u.name();
     567          18 :               if (u.marking().size() == Bj[X].size())
     568             :               {
     569          17 :                 continue;
     570             :               }
     571           1 :               mCRL2log(log::trace) << " extend marking rule2: u = " << u << " marking(u) = " << core::detail::print_set(u.marking()) << std::endl;
     572             : 
     573           1 :               bool changed = false;
     574           1 :               auto const& eq_X = *find_equation(m_pbes, X); // slow
     575           1 :               auto const& predvars = eq_X.predicate_variables();
     576           1 :               auto const& outgoing_edges = u.outgoing_edges();
     577           3 :               for (const auto& e: outgoing_edges)
     578             :               {
     579           2 :                 auto const& labels = e.second;
     580           4 :                 for (std::size_t i: labels)
     581             :                 {
     582           2 :                   auto const& Ye = predvars[i];
     583           2 :                   auto const& Y = Ye.name();
     584           8 :                   for (std::size_t k = 0; k < J; k++)
     585             :                   {
     586           6 :                     if (j == k)
     587             :                     {
     588           2 :                       continue;
     589             :                     }
     590           4 :                     auto const& Vk = m_local_control_flow_graphs[k];
     591          12 :                     for (auto vk = Vk.vertices.begin(); vk != Vk.vertices.end(); ++vk)
     592             :                     {
     593           8 :                       auto const& v = *vk;
     594           8 :                       mCRL2log(log::trace) << "     v = " << v << " marking(v) = " << core::detail::print_set(v.marking()) << std::endl;
     595           8 :                       if (v.name() != Y)
     596             :                       {
     597           4 :                         continue;
     598             :                       }
     599           4 :                       if (has_incoming_edge(Vk, v, X, i))
     600             :                       {
     601           2 :                         bool updated = update_marking_rule(Bj, u, i, v, true);
     602           2 :                         changed = changed || updated;
     603             :                       }
     604             :                     }
     605             :                   }
     606             :                 }
     607             :               }
     608           1 :               if (changed)
     609             :               {
     610           1 :                 mCRL2log(log::trace) << "   marking(u)' = " << core::detail::print_set(u.marking()) << std::endl;
     611           1 :                 stableint = false;
     612           1 :                 stableext = false;
     613             :               }
     614             :             }
     615             :           }
     616             :         }
     617           2 :         stable = stableint;
     618             :       }
     619           1 :       finish_timer("marking computation");
     620           1 :     }
     621             : 
     622             :     // add (X, i) to todo for each incoming edge u = (X, n, dX[n] = z) --i--> v
     623           0 :     void add_equation_labels(std::set<equation_label_pair>& todo, const local_control_flow_graph_vertex& v)
     624             :     {
     625           0 :       auto const& incoming_edges = v.incoming_edges();
     626           0 :       for (const auto& e: incoming_edges)
     627             :       {
     628           0 :         auto const& u = *e.first;
     629           0 :         auto const& X = u.name();
     630           0 :         auto const& labels = e.second;
     631           0 :         for (std::size_t i: labels)
     632             :         {
     633           0 :           todo.insert(equation_label_pair(X, i));
     634             :         }
     635             :       }
     636           0 :     }
     637             : 
     638             :     // a more comprehensible version
     639           0 :     void compute_control_flow_marking_using_edge_index()
     640             :     {
     641           0 :       mCRL2log(log::debug) << "=== computing control flow marking ===" << std::endl;
     642             :       using utilities::detail::pick_element;
     643             : 
     644           0 :       start_timer("marking initialization");
     645           0 :       std::size_t J = m_local_control_flow_graphs.size();
     646           0 :       std::set<equation_label_pair> todo;
     647           0 :       for (std::size_t j = 0; j < J; j++)
     648             :       {
     649           0 :         auto const& Vj = m_local_control_flow_graphs[j];
     650           0 :         auto const& Bj = m_belongs[j];
     651           0 :         for (const auto& v: Vj.vertices)
     652             :         {
     653           0 :           auto const& Y = v.name();
     654           0 :           v.set_marking(belongs_intersection(significant_variables(v), Bj, Y));
     655             :           // Insert those pairs (X,i) for which some vertex u = (X,n,dX[n]=z) --i--> v and v.marking() != {}
     656           0 :           if (v.marking().empty())
     657             :           {
     658           0 :             continue;
     659             :           }
     660           0 :           auto const& incoming_edges = v.incoming_edges();
     661           0 :           for (const auto& e: incoming_edges)
     662             :           {
     663           0 :             auto const& u = *e.first;
     664           0 :             auto const& X = u.name();
     665           0 :             auto const& labels = e.second;
     666           0 :             for (std::size_t i: labels)
     667             :             {
     668           0 :               todo.insert(equation_label_pair(X, i));
     669             :             }
     670             :           }
     671             :        }
     672           0 :         mCRL2log(log::debug) << "--- initial control flow marking for graph " << j << "\n" << Vj.print_marking();
     673             :       }
     674           0 :       finish_timer("marking initialization");
     675             : 
     676           0 :       start_timer("marking computation");
     677           0 :       while (!todo.empty())
     678             :       {
     679           0 :         auto const& Xi = pick_element(todo);
     680           0 :         auto const& X = Xi.X;
     681           0 :         std::size_t i = Xi.i;
     682             : 
     683           0 :         mCRL2log(log::trace) << "    rule: considering equation " << X << std::endl;
     684           0 :         mCRL2log(log::trace) << "    rule2: considering PVI nr. " << i << std::endl;
     685             : 
     686           0 :         auto& EX = m_edge_index[X];
     687           0 :         auto& EXi = EX[i];
     688           0 :         for (auto ei = EXi.begin(); ei != EXi.end(); ++ei)
     689             :         {
     690           0 :           const local_control_flow_graph_vertex& u = *ei->u;
     691           0 :           mCRL2log(log::trace) << " extend marking rule2: u = " << u << " marking(u) = " << core::detail::print_set(u.marking()) << std::endl;
     692           0 :           std::size_t j = ei->k;
     693           0 :           auto const& Bj = m_belongs[j];
     694           0 :           for (const auto& ej: EXi)
     695             :           {
     696           0 :             const local_control_flow_graph_vertex& u1 = *ej.u;
     697           0 :             const local_control_flow_graph_vertex& v1 = *ej.v;
     698           0 :             std::size_t k = ej.k;
     699           0 :             auto const& Bk = m_belongs[k];
     700           0 :             bool updated = update_marking_rule(Bk, u1, i, v1, false);
     701           0 :             if (updated)
     702             :             {
     703           0 :               add_equation_labels(todo, u1);
     704             :             }
     705           0 :             if (j != k  )
     706             :             {
     707           0 :               updated = update_marking_rule(Bj, u, i, v1, true);
     708           0 :               if (updated)
     709             :               {
     710           0 :                 add_equation_labels(todo, u);
     711             :               }
     712             :             }
     713             :           }
     714             :         }
     715           0 :       }
     716           0 :       finish_timer("marking computation");
     717           0 :     }
     718             : 
     719             :     // an efficient version that uses an edge index
     720           0 :     void compute_control_flow_marking_efficient()
     721             :     {
     722           0 :       mCRL2log(log::debug) << "=== computing control flow marking ===" << std::endl;
     723             :       using utilities::detail::pick_element;
     724             : 
     725           0 :       start_timer("marking initialization");
     726           0 :       std::size_t J = m_local_control_flow_graphs.size();
     727           0 :       for (std::size_t j = 0; j < J; j++)
     728             :       {
     729           0 :         auto const& Vj = m_local_control_flow_graphs[j];
     730           0 :         auto const& Bj = m_belongs[j];
     731           0 :         for (const auto& u: Vj.vertices)
     732             :         {
     733           0 :           auto const& X = u.name();
     734           0 :           u.set_marking(belongs_intersection(significant_variables(u), Bj, X));
     735             :         }
     736           0 :         mCRL2log(log::debug) << "--- initial control flow marking for graph " << j << "\n" << Vj.print_marking();
     737             :       }
     738           0 :       finish_timer("marking initialization");
     739             : 
     740           0 :       start_timer("marking computation");
     741           0 :       bool stable = false;
     742           0 :       while (!stable)
     743             :       {
     744           0 :         bool stableint = false;
     745           0 :         while (!stableint)
     746             :         {
     747           0 :           stableint = true;
     748           0 :           for (std::size_t j = 0; j < J; j++)
     749             :           {
     750           0 :             auto const& Vj = m_local_control_flow_graphs[j];
     751           0 :             auto const& Bj = m_belongs[j];
     752           0 :             std::set<const local_control_flow_graph_vertex*> todo;
     753           0 :             for (const auto& v: Vj.vertices)
     754             :             {
     755           0 :               todo.insert(&v);
     756             :             }
     757           0 :             while (!todo.empty())
     758             :             {
     759           0 :               auto const& v = *pick_element(todo);
     760             : 
     761           0 :               mCRL2log(log::trace) << " extend marking rule1: v = " << v << " marking(v) = " << core::detail::print_set(v.marking()) << std::endl;
     762             : 
     763           0 :               auto const& incoming_edges = v.incoming_edges();
     764           0 :               for (const auto& e: incoming_edges)
     765             :               {
     766           0 :                 bool changed = false;
     767           0 :                 auto const& u = *e.first;
     768           0 :                 auto const& labels = e.second;
     769           0 :                 for (std::size_t i: labels)
     770             :                 {
     771             :                     // consider edge (u, i, v)
     772           0 :                     bool updated = update_marking_rule(Bj, u, i, v, false);
     773           0 :                     changed = changed || updated;
     774             :                 }
     775           0 :                 if (changed)
     776             :                 {
     777           0 :                   mCRL2log(log::trace) << "   marking(u)' = " << core::detail::print_set(u.marking()) << std::endl;
     778           0 :                   todo.insert(&u);
     779           0 :                   stableint = false;
     780             :                 }
     781             :               }
     782             :             }
     783           0 :           }
     784             :         }
     785             : 
     786             :         // stableext := false
     787             :         // while not stableext do
     788             :         //   stableext := true;
     789             :         //   for X in bnd(E) do
     790             :         //     for i <= npred(phi_X) do
     791             :         //       let E := { ( u, i, v) in E1 union ... union EJ | exists n,z: u = (X,n,dX[n]=z) };
     792             :         //       for (u,i,v) in E do
     793             :         //         let j be such that u in Vj;
     794             :         //         if (marking(u) = {d | (X,d) in Bj}) then continue;
     795             :         //         for (u',i,v') in E do
     796             :         //           let k be such that u' in Vk;
     797             :         //           if (j == k) then continue;
     798             :         //           m := marking(u);
     799             :         //           marking(u) := UpdateMarkingRule2(Bj,u,i,v')
     800             :         //           if not(marking(u) == m) then
     801             :         //             stableint := false;
     802             :         //             stableext := false;
     803             :         // stable := stableint /\ stableext;
     804           0 :         bool stableext = false;
     805           0 :         auto const& equations = m_pbes.equations();
     806           0 :         while (!stableext)
     807             :         {
     808           0 :           stableext = true;
     809           0 :           for (const auto& eq_X: equations)
     810             :           {
     811           0 :             auto const& X = eq_X.variable().name();
     812           0 :             auto& EX = m_edge_index[X];
     813           0 :             for (std::size_t i = 0; i < eq_X.predicate_variables().size(); i++)
     814             :             {
     815           0 :               auto& EXi = EX[i];
     816           0 :               for (auto ei = EXi.begin(); ei != EXi.end(); ++ei)
     817             :               {
     818           0 :                 const local_control_flow_graph_vertex& u = *ei->u;
     819             :                 // const local_control_flow_graph_vertex& v = *ei->v;
     820           0 :                 std::size_t j = ei->k;
     821           0 :                 auto const& Bj = m_belongs[j];
     822           0 :                 if (u.marking().size() == Bj[X].size())
     823             :                 {
     824           0 :                   continue;
     825             :                 }
     826           0 :                 for (const auto& ej: EXi)
     827             :                 {
     828             :                   // const local_control_flow_graph_vertex& u1 = *ej->u;
     829           0 :                   const local_control_flow_graph_vertex& v1 = *ej.v;
     830           0 :                   std::size_t k = ej.k;
     831           0 :                   if (j == k)
     832             :                   {
     833           0 :                     continue;
     834             :                   }
     835           0 :                   bool updated = update_marking_rule(Bj, u, i, v1, true);
     836           0 :                   if (updated)
     837             :                   {
     838           0 :                     stableint = false;
     839           0 :                     stableext = false;
     840             :                   }
     841             :                 }
     842             :               }
     843             :             }
     844             :           }
     845             :         }
     846           0 :         stable = stableint;
     847             :       }
     848           0 :       finish_timer("marking computation");
     849           0 :     }
     850             : 
     851           1 :     void print_control_flow_marking() const
     852             :     {
     853           1 :       std::size_t K = m_local_control_flow_graphs.size();
     854           4 :       for (std::size_t k = 0; k < K; k++)
     855             :       {
     856           3 :         const local_control_flow_graph& Gk = m_local_control_flow_graphs[k];
     857           3 :         mCRL2log(log::debug) <<  "--- computed control flow marking for graph " << k << "\n" << Gk.print_marking() << std::endl;
     858             :       }
     859           1 :     }
     860             : 
     861           4 :     void remove_belongs(std::set<data::variable>& B_X,
     862             :                         const core::identifier_string& X,
     863             :                         const belongs_relation& Bk,
     864             :                         std::size_t k)
     865             :     {
     866          12 :       for (const auto& i: Bk)
     867             :       {
     868           8 :         if (i.first != X)
     869             :         {
     870           4 :           continue;
     871             :         }
     872           4 :         auto const& V = i.second;
     873           6 :         for (const data::variable& v: V)
     874             :         {
     875           2 :           auto j = B_X.find(v);
     876           2 :           if (j != B_X.end())
     877             :           {
     878           2 :             mCRL2log(log::debug) <<  "removing belongs variable " << *j << " in B[" << X << "] , since it already appears in belongs relation " << k << std::endl;
     879           2 :             B_X.erase(*j);
     880             :           }
     881             :         }
     882             :       }
     883           4 :     }
     884             : 
     885           1 :     void compute_extra_local_control_flow_graph()
     886             :     {
     887           1 :       mCRL2log(log::trace) << "--- computing extra local control flow graph" << std::endl;
     888             : 
     889           1 :       local_control_flow_graph V;
     890           1 :       belongs_relation B;
     891             : 
     892           1 :       auto const& equations = m_pbes.equations();
     893           3 :       for (const auto& eq_X: equations)
     894             :       {
     895           2 :         auto const& X = eq_X.variable().name();
     896           2 :         auto const& u = V.insert_vertex(local_control_flow_graph_vertex(X, data::undefined_data_expression()));
     897             : 
     898           2 :         auto const& d_X = eq_X.parameters();
     899           2 :         auto& B_X = B[X];  // N.B. This forces the creation of an empty belong set B[X].
     900           2 :         auto const& I = eq_X.data_parameter_indices();
     901           4 :         for (std::size_t i : I)
     902             :         {
     903           2 :           B_X.insert(d_X[i]);
     904             :         }
     905           2 :         mCRL2log(log::trace) << "initial belongs relation B[" << X << "] = " << core::detail::print_set(B_X) << std::endl;
     906             : 
     907           6 :         for (std::size_t k = 0; k < m_belongs.size(); k++)
     908             :         {
     909           4 :           auto const& Bk = m_belongs[k];
     910           4 :           remove_belongs(B_X, X, Bk, k);
     911             :         }
     912             : 
     913           2 :         auto const& predvars = eq_X.predicate_variables();
     914           5 :         for (std::size_t i = 0; i < predvars.size(); i++)
     915             :         {
     916           3 :           auto const& Ye = predvars[i];
     917             : 
     918           3 :           bool add_edge = false;
     919             : 
     920             :           //if X != Y || exists k: d_X[k] \in B && (used(X, j, k) || changed(X, j, k)) then
     921             :           // implemented by checking for non-empty intersection
     922           3 :           if(X != Ye.name())
     923             :           {
     924           1 :             add_edge = true;
     925             :           }
     926             :           else
     927             :           {
     928           2 :             std::set<data::variable> used_or_changed;
     929           5 :             for (std::size_t j: Ye.changed())
     930             :             {
     931           3 :               used_or_changed.insert(d_X[j]);
     932             :             }
     933           5 :             for (std::size_t j: Ye.used())
     934             :             {
     935           3 :               used_or_changed.insert(d_X[j]);
     936             :             }
     937             : 
     938           2 :             std::set<data::variable>::const_iterator bi = B_X.begin();
     939           2 :             std::set<data::variable>::const_iterator ui = used_or_changed.begin();
     940           2 :             while (bi != B_X.end() && ui != used_or_changed.end())
     941             :             {
     942           0 :               if (*ui < *bi)
     943             :               {
     944           0 :                 ++ui;
     945             :               }
     946           0 :               else if (*bi < *ui)
     947             :               {
     948           0 :                 ++bi;
     949             :               }
     950             :               else
     951             :               {
     952           0 :                 add_edge = true;
     953           0 :                 break;
     954             :               }
     955             :             }
     956           2 :           }
     957             : 
     958           3 :           if(add_edge)
     959             :           {
     960           1 :             auto const& v = V.insert_vertex(local_control_flow_graph_vertex(Ye.name(), data::undefined_data_expression()));
     961           1 :             V.insert_edge(u, i, v);
     962             :           }
     963             :         }
     964             :       }
     965           1 :       m_local_control_flow_graphs.push_back(V);
     966           1 :       m_local_control_flow_graphs.back().compute_index();
     967           1 :       m_belongs.push_back(B);
     968           1 :       mCRL2log(log::debug) << "--- extra local control flow graph\n" << m_local_control_flow_graphs.back() << std::endl;
     969           1 :       mCRL2log(log::debug) << "--- belongs relation for extra graph\n" << print_belongs(B);
     970           1 :     }
     971             : 
     972           2 :     void compute_local_control_flow_graph(const std::set<local_control_flow_graph_vertex>& U, const std::map<core::identifier_string, std::size_t>& C)
     973             :     {
     974             :       using utilities::detail::pick_element;
     975             : 
     976           2 :       mCRL2log(log::debug) << "--- compute_local_control_flow_graph for vertices " << core::detail::print_set(U) << std::endl;
     977           2 :       local_control_flow_graph V;
     978           2 :       std::set<const local_control_flow_graph_vertex*> todo;
     979             : 
     980           5 :       for (const local_control_flow_graph_vertex& u: U)
     981             :       {
     982           3 :         auto k = V.insert(u);
     983           3 :         todo.insert(&(*k.first));
     984             :       }
     985             : 
     986           6 :       while (!todo.empty())
     987             :       {
     988             :         // u = (X, k, d = e)
     989           4 :         auto const& u = *pick_element(todo);
     990           4 :         auto const& X = u.name();
     991           4 :         const data::variable& d = u.variable();
     992           4 :         const data::data_expression& e = u.value();
     993           4 :         mCRL2log(log::trace) << "choose todo element (X, k, d=e) = " << u << std::endl;
     994           4 :         std::size_t k = u.index();
     995           4 :         auto const& eq_X = *find_equation(m_pbes, X);
     996           4 :         auto const& predvars = eq_X.predicate_variables();
     997             : 
     998          10 :         for (auto i = predvars.begin(); i != predvars.end(); ++i)
     999             :         {
    1000           6 :           std::size_t edge_label = i - predvars.begin();
    1001           6 :           auto const& Y = i->name();
    1002           6 :           auto q = C.find(Y);
    1003             : 
    1004           6 :           if (d == data::undefined_variable())
    1005             :           {
    1006             :             // case 1: (X, ?, ?=?) -> (Y, k', d'=e')
    1007           3 :             mCRL2log(log::trace) << "case 1" << std::endl;
    1008           3 :             if (q != C.end()) // (Y, k1) in C
    1009             :             {
    1010           1 :               std::size_t k1 = q->second;
    1011           1 :               auto e1 = i->target(k1);
    1012           1 :               if (e1 != data::undefined_data_expression())
    1013             :               {
    1014             :                 // target(X, i, k') = e'
    1015           1 :                 mCRL2log(log::trace) << "case 1: (X, e) -> (Y, d', e') ; target(X, i, k') = e' ; k' = " << print_index(k1) << std::endl;
    1016           1 :                 V.insert_edge(todo, m_pbes, u, Y, k1, e1, edge_label);
    1017             :               }
    1018           1 :             }
    1019             :             // case 2: (X, ?, ?=?) -> (Y, ?, ?=?)
    1020             :             else
    1021             :             {
    1022           2 :               if (X != Y)
    1023             :               {
    1024           0 :                 mCRL2log(log::trace) << "case 2: (X, ?) -> (Y, ?)" << std::endl;
    1025           0 :                 V.insert_edge(todo, m_pbes, u, Y, data::undefined_index(), data::undefined_data_expression(), edge_label);
    1026             :               }
    1027             :             }
    1028             :           }
    1029             :           else
    1030             :           {
    1031             :             // case 3: (X, d, e) -> (Y, d', e')
    1032           3 :             if (q != C.end()) // (Y, k') in C
    1033             :             {
    1034           2 :               std::size_t k1 = q->second;
    1035           2 :               if (is_mapped_to(i->source(), k, e))
    1036             :               {
    1037             :                 // source(X, i, k) = e && target(X, i, k') = e'
    1038           2 :                 auto e1 = i->target(k1);
    1039           2 :                 mCRL2log(log::trace) << "case 3a: (X, d, e) -> (Y, d', e') ; source(X, i, k) = e && target(X, i, k') = e' ; k' = " << print_index(k1) << std::endl;
    1040           2 :                 if (e1 != data::undefined_data_expression())
    1041             :                 {
    1042           2 :                   V.insert_edge(todo, m_pbes, u, Y, k1, e1, edge_label);
    1043             :                 }
    1044           2 :               }
    1045           0 :               else if (Y != X && is_undefined(i->source(), k))
    1046             :               {
    1047             :                 // Y != X && undefined(source(X, i, k)) && target(X, i, k') = e'
    1048           0 :                 auto e1 = i->target(k1);
    1049           0 :                 if (e1 != data::undefined_data_expression())
    1050             :                 {
    1051           0 :                   mCRL2log(log::trace) << "case 3b: (X, d, e) -> (Y, d', e') ; Y != X && undefined(source(X, i, k)) && target(X, i, k') = e' ; k' = " << print_index(k1) << std::endl;
    1052           0 :                   V.insert_edge(todo, m_pbes, u, Y, k1, e1, edge_label);
    1053             :                 }
    1054             : 
    1055             :                 // Y != X && undefined(source(X, i, k)) && copy(X, i, k) = k'
    1056           0 :                 if (i->copy(k) == k1)
    1057             :                 {
    1058           0 :                   mCRL2log(log::trace) << "case 3c: (X, d, e) -> (Y, d', e') ; Y != X && undefined(source(X, i, k)) && copy(X, i, k) = k' ; k' = " << print_index(k1) << std::endl;
    1059           0 :                   V.insert_edge(todo, m_pbes, u, Y, k1, e, edge_label);
    1060             :                 }
    1061           0 :               }
    1062             :             }
    1063             :             // case 4: (X, d, e) -> (Y, ?)
    1064             :             else
    1065             :             {
    1066           1 :               auto e1 = i->source(k);
    1067           1 :               if (e1 == e || e1 == data::undefined_data_expression())
    1068             :               {
    1069           1 :                 std::size_t k1 = data::undefined_index();
    1070           1 :                 mCRL2log(log::trace) << "case 4: (X, d, e) -> (Y, ?)" << std::endl;
    1071           1 :                 V.insert_edge(todo, m_pbes, u, Y, k1, data::undefined_data_expression(), edge_label);
    1072             :               }
    1073           1 :             }
    1074             :           }
    1075             :         }
    1076             :       }
    1077             :       // V.self_check();
    1078           2 :       m_local_control_flow_graphs.push_back(V);
    1079           2 :       m_local_control_flow_graphs.back().compute_index();
    1080           2 :     }
    1081             : 
    1082             :     void compute_local_control_flow_graph(const local_control_flow_graph_vertex& u, const std::map<core::identifier_string, std::size_t>& C)
    1083             :     {
    1084             :       std::set<local_control_flow_graph_vertex> U;
    1085             :       U.insert(u);
    1086             :       compute_local_control_flow_graph(U, C);
    1087             :     }
    1088             : 
    1089             :     // Computes a local control flow graph that corresponds to the given component in m_GCFP_graph.
    1090           2 :     void compute_local_control_flow_graph(const std::set<std::size_t>& component, const std::set<data::data_expression>& component_values)
    1091             :     {
    1092           2 :       mCRL2log(log::debug) << "Compute local control flow graphs for component " << print_connected_component(component) << std::endl;
    1093             : 
    1094             :       // preprocessing
    1095           2 :       std::map<core::identifier_string, std::size_t> C;
    1096           4 :       for (std::size_t p: component)
    1097             :       {
    1098           2 :         const GCFP_vertex& w = m_GCFP_graph.vertex(p);
    1099           2 :         C[w.name()] = w.index();
    1100             :       }
    1101             : 
    1102           2 :       std::set<local_control_flow_graph_vertex> U;
    1103           4 :       for (std::size_t p: component)
    1104             :       {
    1105           2 :         const GCFP_vertex& u = m_GCFP_graph.vertex(p);
    1106           4 :         for (const auto& value: component_values)
    1107             :         {
    1108           2 :           U.insert(local_control_flow_graph_vertex(u.name(), u.index(), u.variable(), value));
    1109             :         }
    1110             :       }
    1111             : 
    1112             :       // add a node (Xinit, ?, ?=?)
    1113           2 :       const core::identifier_string& Xinit = m_pbes.initial_state().name();
    1114           2 :       if (C.find(Xinit) == C.end())
    1115             :       {
    1116           1 :         U.insert(local_control_flow_graph_vertex(Xinit, data::undefined_index(), data::undefined_variable(), data::undefined_data_expression()));
    1117             :       }
    1118             : 
    1119           2 :       compute_local_control_flow_graph(U, C);
    1120           2 :     }
    1121             : 
    1122           1 :     void print_local_control_flow_graphs() const
    1123             :     {
    1124           3 :       for (auto i = m_local_control_flow_graphs.begin(); i != m_local_control_flow_graphs.end(); ++i)
    1125             :       {
    1126           2 :         mCRL2log(log::debug) << "--- computed local control flow graph " << (i - m_local_control_flow_graphs.begin()) << "\n" << *i << std::endl;
    1127             :       }
    1128           1 :     }
    1129             : 
    1130           1 :     void compute_local_control_flow_graphs()
    1131             :     {
    1132           3 :       for (std::size_t i = 0; i < m_connected_components.size(); i++)
    1133             :       {
    1134           2 :         compute_local_control_flow_graph(m_connected_components[i], m_connected_components_values[i]);
    1135             :       }
    1136           1 :     }
    1137             : 
    1138             :   public:
    1139           1 :     stategraph_local_algorithm(const pbes& p, const pbesstategraph_options& options)
    1140           1 :       : stategraph_algorithm(p, options),
    1141           1 :         m_cache_marking_updates(options.cache_marking_updates),
    1142           1 :         m_marking_rewrite_count(0),
    1143           1 :         m_marking_rewrite_cached_count(0)
    1144             : 
    1145           1 :     { }
    1146             : 
    1147             :     /// \brief Computes the control flow graph
    1148           1 :     void run() override
    1149             :     {
    1150           1 :       super::run();
    1151             : 
    1152           1 :       start_timer("compute_local_control_flow_graphs");
    1153           1 :       compute_local_control_flow_graphs();
    1154           1 :       finish_timer("compute_local_control_flow_graphs");
    1155           1 :       print_local_control_flow_graphs();
    1156             : 
    1157           1 :       start_timer("compute_belongs");
    1158           1 :       compute_belongs();
    1159           1 :       finish_timer("compute_belongs");
    1160           1 :       print_belongs();
    1161             : 
    1162           1 :       start_timer("compute_extra_local_control_flow_graph");
    1163           1 :       compute_extra_local_control_flow_graph();
    1164           1 :       finish_timer("compute_extra_local_control_flow_graph");
    1165             : 
    1166           1 :       start_timer("compute_control_flow_marking");
    1167           1 :       switch (m_options.marking_algorithm)
    1168             :       {
    1169           1 :         case 0: {
    1170           1 :           compute_control_flow_marking();
    1171           1 :           break;
    1172             :         }
    1173           0 :         case 1: {
    1174           0 :           compute_edge_index();
    1175           0 :           mCRL2log(log::trace) << print_edge_index() << std::endl;
    1176           0 :           compute_control_flow_marking_using_edge_index();
    1177           0 :           break;
    1178             :         }
    1179           0 :         case 2: {
    1180           0 :           compute_edge_index();
    1181           0 :           mCRL2log(log::trace) << print_edge_index() << std::endl;
    1182           0 :           compute_control_flow_marking_efficient();
    1183           0 :           break;
    1184             :         }
    1185           0 :         default: {
    1186           0 :           throw mcrl2::runtime_error("unknown value of marking_algorithm");
    1187             :         }
    1188             :       }
    1189           1 :       finish_timer("compute_control_flow_marking");
    1190           1 :       print_control_flow_marking();
    1191             : 
    1192           1 :       print_marking_statistics();
    1193           1 :     }
    1194             : 
    1195             : 
    1196             : 
    1197             :     const std::vector<belongs_relation>& belongs() const
    1198             :     {
    1199             :       return m_belongs;
    1200             :     }
    1201             : };
    1202             : 
    1203             : } // namespace detail
    1204             : 
    1205             : } // namespace pbes_system
    1206             : 
    1207             : } // namespace mcrl2
    1208             : 
    1209             : #endif // MCRL2_PBES_DETAIL_STATEGRAPH_LOCAL_ALGORITHM_H

Generated by: LCOV version 1.14