LCOV - code coverage report
Current view: top level - pbes/include/mcrl2/pbes - small_progress_measures.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 129 164 78.7 %
Date: 2024-05-01 03:37:31 Functions: 15 20 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Wieger Wesselink
       2             : // Copyright: see the accompanying file COPYING or copy at
       3             : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
       4             : //
       5             : // Distributed under the Boost Software License, Version 1.0.
       6             : // (See accompanying file LICENSE_1_0.txt or copy at
       7             : // http://www.boost.org/LICENSE_1_0.txt)
       8             : //
       9             : /// \file mcrl2/pbes/small_progress_measures.h
      10             : /// \brief add your file description here.
      11             : 
      12             : #ifndef MCRL2_BES_SMALL_PROGRESS_MEASURES_H
      13             : #define MCRL2_BES_SMALL_PROGRESS_MEASURES_H
      14             : 
      15             : // TODO: Make it possible to undefine this flag
      16             : #define MCRL2_SMALL_PROGRESS_MEASURES_DEBUG
      17             : 
      18             : #include <iomanip>
      19             : #include "mcrl2/core/detail/print_utility.h"
      20             : #include "mcrl2/pbes/find.h"
      21             : #include "mcrl2/pbes/normal_forms.h"
      22             : #include "mcrl2/pbes/print.h"
      23             : 
      24             : namespace mcrl2
      25             : {
      26             : 
      27             : namespace pbes_system
      28             : {
      29             : 
      30             : template <typename T>
      31          19 : bool is_odd(T t)
      32             : {
      33          19 :   return t % 2 != 0;
      34             : }
      35             : 
      36             : template <typename T>
      37           9 : bool is_even(T t)
      38             : {
      39           9 :   return t % 2 == 0;
      40             : }
      41             : 
      42             : template <typename InputIterator1, typename InputIterator2>
      43           4 : int lexicographical_compare_3way(InputIterator1 first1, InputIterator1 last1,
      44             :                                  InputIterator2 first2, InputIterator2 last2)
      45             : {
      46           9 :   while (first1 != last1 && first2 != last2)
      47             :   {
      48           8 :     if (*first1 < *first2)
      49             :     {
      50           2 :       return -1;
      51             :     }
      52           6 :     if (*first2 < *first1)
      53             :     {
      54           1 :       return 1;
      55             :     }
      56           5 :     ++first1;
      57           5 :     ++first2;
      58             :   }
      59           1 :   if (first2 == last2)
      60             :   {
      61           1 :     return !(first1 == last1);
      62             :   }
      63             :   else
      64             :   {
      65           0 :     return -1;
      66             :   }
      67             : }
      68             : 
      69             : inline
      70           7 : bool is_disjunctive(const pbes_expression& x)
      71             : {
      72           7 :   return is_or(x);
      73             : }
      74             : 
      75             : inline
      76           3 : int maximum_rank(const pbes& b)
      77             : {
      78           3 :   int result = 0;
      79           3 :   fixpoint_symbol last_symbol;
      80          10 :   for (auto i = b.equations().begin(); i != b.equations().end(); ++i)
      81             :   {
      82           7 :     if (i == b.equations().begin())
      83             :     {
      84           3 :       result = i->symbol().is_nu() ? 0 : 1;
      85             :     }
      86           4 :     else if (i->symbol() != last_symbol)
      87             :     {
      88           4 :       result++;
      89             :     }
      90           7 :     last_symbol = i->symbol();
      91             :   }
      92           3 :   return result;
      93           3 : }
      94             : 
      95             : struct progress_measure
      96             : {
      97          14 :   explicit progress_measure(std::size_t d)
      98          14 :     : v(d, 0)
      99          14 :   {}
     100             : 
     101             :   // N.B. The special value top is represented by alpha[0] == -1
     102             :   std::vector<int> v;
     103             : 
     104          20 :   bool is_top() const
     105             :   {
     106          20 :     return v[0] == -1;
     107             :   }
     108             : };
     109             : 
     110             : inline
     111           0 : std::ostream& operator<<(std::ostream& out, const progress_measure& pm)
     112             : {
     113           0 :   if (pm.is_top())
     114             :   {
     115           0 :     out << "top";
     116             :   }
     117             :   else
     118             :   {
     119           0 :     out << core::detail::print_list(pm.v);
     120             :   }
     121           0 :   return out;
     122             : }
     123             : 
     124             : // increment position m of vector alpha
     125             : inline
     126          15 : void inc(std::vector<int>& alpha, int m, const std::vector<int>& beta)
     127             : {
     128          15 :   if (alpha[0] == -1)
     129             :   {
     130           2 :     return;
     131             :   }
     132          13 :   else if (m == -1)
     133             :   {
     134           2 :     alpha[0] = -1;
     135           2 :     return;
     136             :   }
     137          11 :   else if (alpha[m] == beta[m])
     138             :   {
     139           4 :     alpha[m] = 0;
     140           4 :     inc(alpha, m - 1, beta);
     141             :   }
     142             :   else
     143             :   {
     144           7 :     alpha[m]++;
     145             :   }
     146             : }
     147             : 
     148             : /// \brief Vertex of the progress measures graph
     149             : struct progress_measures_vertex
     150             : {
     151          14 :   explicit progress_measures_vertex(bool even_ = false, int rank_ = 0, unsigned int d = 1)
     152          28 :     : even(even_),
     153          14 :       rank(rank_),
     154          14 :       alpha(d)
     155          14 :   {}
     156             : 
     157             :   std::vector<progress_measures_vertex*> successors;
     158             :   bool even;
     159             :   int rank;
     160             :   progress_measure alpha;
     161             : 
     162             : #ifdef MCRL2_SMALL_PROGRESS_MEASURES_DEBUG
     163             :   std::string name;
     164             : #endif
     165             : };
     166             : 
     167             : // compare the positions with index in [0, ... ,m]
     168             : struct compare_progress_measures_vertex
     169             : {
     170             :   unsigned int m;
     171             : 
     172          19 :   explicit compare_progress_measures_vertex(unsigned int m_)
     173          19 :     : m(m_)
     174          19 :   {}
     175             : 
     176           9 :   bool operator()(const progress_measures_vertex* x, const progress_measures_vertex* y) const
     177             :   {
     178           9 :     if (x->alpha.is_top())
     179             :     {
     180           1 :       return false;
     181             :     }
     182           8 :     else if (y->alpha.is_top())
     183             :     {
     184           4 :       return true;
     185             :     }
     186           4 :     int n = lexicographical_compare_3way(x->alpha.v.begin(), x->alpha.v.begin() + m + 1, y->alpha.v.begin(), y->alpha.v.begin() + m + 1);
     187             :     //if (n == 0)
     188             :     //{
     189             :     //  return is_even(x->rank) && is_odd(y->rank);
     190             :     //}
     191           4 :     return n < 0;
     192             :   }
     193             : };
     194             : 
     195             : inline
     196           0 : std::ostream& operator<<(std::ostream& out, const progress_measures_vertex& v)
     197             : {
     198           0 :   out << " alpha = " << v.alpha;
     199           0 :   out << " successors = {";
     200           0 :   for (auto i = v.successors.begin(); i != v.successors.end(); ++i)
     201             :   {
     202           0 :     if (i != v.successors.begin())
     203             :     {
     204           0 :       out << ", ";
     205             :     }
     206           0 :     out << std::string((*i)->name);
     207             :   }
     208           0 :   out << "}";
     209           0 :   out << " rank = " << v.rank;
     210           0 :   out << " disjunctive = " << std::boolalpha << v.even;
     211           0 :   return out;
     212             : }
     213             : 
     214             : /// \brief Algorithm class for the small progress measures algorithm
     215             : class small_progress_measures_algorithm
     216             : {
     217             :   protected:
     218             :     typedef progress_measures_vertex vertex;
     219             :     typedef std::map<propositional_variable_instantiation, vertex> vertex_map;
     220             : 
     221           3 :     void initialize_vertices()
     222             :     {
     223             :       // first build the vertex map without successor information
     224           3 :       m_d = maximum_rank(m_bes) + 1;
     225           3 :       unsigned int block_size = 0;
     226           3 :       int last_rank = 0;
     227           3 :       fixpoint_symbol last_symbol = fixpoint_symbol::nu();
     228          10 :       for (const pbes_equation& eqn: m_bes.equations())
     229             :       {
     230           7 :         if (eqn.symbol() != last_symbol)
     231             :         {
     232           6 :           if (is_even(m_beta.size()))
     233             :           {
     234           4 :             m_beta.push_back(0);
     235             :           }
     236             :           else
     237             :           {
     238           2 :             m_beta.push_back(block_size);
     239             :           }
     240           6 :           block_size = 0;
     241           6 :           last_rank++;
     242           6 :           last_symbol = eqn.symbol();
     243             :         }
     244           7 :         block_size++;
     245           7 :         m_vertices[propositional_variable_instantiation(eqn.variable().name())] = vertex(is_disjunctive(eqn.formula()), last_rank, m_d);
     246             :       }
     247           3 :       if (is_even(m_beta.size()))
     248             :       {
     249           1 :         m_beta.push_back(0);
     250             :       }
     251             :       else
     252             :       {
     253           2 :         m_beta.push_back(block_size);
     254             :       }
     255             : 
     256             :       // add successor information
     257          10 :       for (const pbes_equation& eqn: m_bes.equations())
     258             :       {
     259           7 :         std::set<propositional_variable_instantiation> succ = pbes_system::find_propositional_variable_instantiations(eqn.formula());
     260           7 :         auto k = m_vertices.find(propositional_variable_instantiation(eqn.variable().name()));
     261           7 :         std::vector<vertex*>& k_successors = k->second.successors;
     262          17 :         for (const propositional_variable_instantiation& v: succ)
     263             :         {
     264          10 :           k_successors.push_back(&m_vertices[v]);
     265             :         }
     266             : 
     267             : #ifdef MCRL2_SMALL_PROGRESS_MEASURES_DEBUG
     268           7 :         k->second.name = std::string(eqn.variable().name());
     269             : #endif
     270           7 :       }
     271           3 :     }
     272             : 
     273           0 :     std::string print_vertices() const
     274             :     {
     275           0 :       std::ostringstream out;
     276           0 :       for (const pbes_equation& eqn: m_bes.equations())
     277             :       {
     278           0 :         const vertex& v = m_vertices.find(propositional_variable_instantiation(eqn.variable().name()))->second;
     279           0 :         out << v.name << " " << v << std::endl;
     280             :       }
     281           0 :       return out.str();
     282           0 :     }
     283             : 
     284           0 :     std::string print_vertex(const vertex& v) const
     285             :     {
     286           0 :       std::ostringstream out;
     287           0 :       out << v.name << " (alpha = " << v.alpha << ", rank = " << v.rank << ")";
     288           0 :       return out.str();
     289           0 :     }
     290             : 
     291             :     /// \brief Logs the neighbors of a vertex
     292           0 :     std::string print_neighbors(const progress_measures_vertex& v) const
     293             :     {
     294           0 :       std::ostringstream out;
     295           0 :       for (progress_measures_vertex* successor: v.successors)
     296             :       {
     297           0 :         out << "\n      " << print_vertex(*successor);
     298             :       }
     299           0 :       return out.str();
     300           0 :     }
     301             : 
     302             :     vertex_map m_vertices;
     303             :     int m_d = 0;
     304             :     const pbes& m_bes;
     305             :     std::vector<int> m_beta;
     306             : 
     307             :   public:
     308           3 :     explicit small_progress_measures_algorithm(const pbes& b)
     309           3 :       : m_bes(b)
     310           3 :     {}
     311             : 
     312           3 :     bool run(const propositional_variable_instantiation& first_variable)
     313             :     {
     314           3 :       mCRL2log(log::verbose) << "Applying small progress measures.\n";
     315           3 :       mCRL2log(log::debug)  << "BES " << pbes_system::pp(m_bes) << "\n\n";
     316           3 :       initialize_vertices();
     317           3 :       mCRL2log(log::debug) << "--- vertices ---\n" << print_vertices();
     318           3 :       mCRL2log(log::debug) << "\nbeta = " << core::detail::print_list(m_beta) << "\n";
     319             :       for (;;) // forever
     320             :       {
     321           8 :         bool changed = false;
     322          27 :         for (auto &i: m_vertices)
     323             :         {
     324          19 :           vertex& v = i.second;
     325          19 :           mCRL2log(log::debug) << "\nchoose vertex " << print_vertex(v);
     326          19 :           int m = v.rank;
     327          19 :           std::vector<progress_measures_vertex*>::const_iterator j;
     328          19 :           mCRL2log(log::debug) << "\n    neighbors:" << print_neighbors(v);
     329          19 :           if (v.even)
     330             :           {
     331           6 :             j = std::min_element(v.successors.begin(), v.successors.end(), compare_progress_measures_vertex(m));
     332           6 :             mCRL2log(log::debug) << "\n    minimum neighbor " << print_vertex(**j);
     333             :           }
     334             :           else
     335             :           {
     336          13 :             j = std::max_element(v.successors.begin(), v.successors.end(), compare_progress_measures_vertex(m));
     337          13 :             mCRL2log(log::debug) << "\n    maximum neighbor " << print_vertex(**j);
     338             :           }
     339          19 :           std::vector<int> alpha(m_d, 0);
     340          19 :           const progress_measures_vertex& w = **j;
     341          19 :           std::copy(w.alpha.v.begin(),  w.alpha.v.begin() + m + 1, alpha.begin());
     342          19 :           if (is_odd(m))
     343             :           {
     344          11 :             mCRL2log(log::debug) << "\n    inc(" << core::detail::print_list(alpha) << ", " << std::to_string(m) << ") = ";
     345          11 :             inc(alpha, m, m_beta);
     346          11 :             mCRL2log(log::debug) << (alpha[0] < 0 ? "top" : core::detail::print_list(alpha));
     347             :           }
     348             : 
     349          19 :           if (!std::equal(alpha.begin(), alpha.end(), v.alpha.v.begin()))
     350             :           {
     351           8 :             changed = true;
     352           8 :             v.alpha.v = alpha;
     353           8 :             mCRL2log(log::debug) << "\nupdate vertex " << print_vertex(v);
     354             :           }
     355          19 :         }
     356           8 :         if (!changed)
     357             :         {
     358           3 :           break;
     359             :         }
     360           5 :       }
     361           3 :       mCRL2log(log::debug) << "\n--- vertices ---\n" << print_vertices();
     362           3 :       return !m_vertices[first_variable].alpha.is_top();
     363             :     }
     364             : };
     365             : 
     366             : inline
     367           3 : bool small_progress_measures(pbes& b)
     368             : {
     369           3 :   propositional_variable_instantiation first(b.equations().front().variable().name());
     370           3 :   assert(b.equations().front().variable().parameters().empty());
     371           3 :   make_standard_form(b, true);
     372           3 :   small_progress_measures_algorithm algorithm(b);
     373           6 :   return algorithm.run(first);
     374           3 : }
     375             : 
     376             : } // namespace pbes_system
     377             : 
     378             : } // namespace mcrl2
     379             : 
     380             : #endif // MCRL2_BES_SMALL_PROGRESS_MEASURES_H

Generated by: LCOV version 1.14