LCOV - code coverage report
Current view: top level - pbes/include/mcrl2/pbes/detail - ppg_traverser.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 87 118 73.7 %
Date: 2024-04-21 03:44:01 Functions: 12 14 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Gijs Kant
       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/ppg_traverser.h
      10             : /// \brief Traverser class for Parameterised Parity Games (PPG), PBES expressions of the form:
      11             : /// PPG :== /\_{i: I} f_i && /\_{j: J} forall v: D_j . ( g_j => X_j(e_j) )
      12             : ///       | \/_{i: I} f_i || \/_{j: J} exists v: D_j . ( g_j && X_j(e_j) ).
      13             : #ifndef MCRL2_PBES_DETAIL_PPG_TRAVERSER_H
      14             : #define MCRL2_PBES_DETAIL_PPG_TRAVERSER_H
      15             : 
      16             : #include "mcrl2/pbes/pbes_functions.h"
      17             : 
      18             : namespace mcrl2 {
      19             : 
      20             : namespace pbes_system {
      21             : 
      22             : namespace detail {
      23             : 
      24             : /// \cond INTERNAL_DOCS
      25             : /// \brief Visitor for checking if a pbes object is a PPG.
      26             : struct ppg_traverser: public pbes_expression_traverser<ppg_traverser>
      27             : {
      28             :   typedef pbes_expression_traverser<ppg_traverser> super;
      29             :   using super::enter;
      30             :   using super::leave;
      31             :   using super::apply;
      32             : 
      33             :   enum expression_mode {
      34             :     CONJUNCTIVE, UNIVERSAL,
      35             :     DISJUNCTIVE, EXISTENTIAL,
      36             :     UNDETERMINED
      37             :   };
      38             : 
      39             :   std::string print_mode(expression_mode mode)
      40             :   {
      41             :     switch(mode)
      42             :     {
      43             :     case CONJUNCTIVE:
      44             :       return "Conjunctive";
      45             :       break;
      46             :     case UNIVERSAL:
      47             :       return "Universal";
      48             :       break;
      49             :     case DISJUNCTIVE:
      50             :       return "Disjunctive";
      51             :       break;
      52             :     case EXISTENTIAL:
      53             :       return "Existential";
      54             :       break;
      55             :     case UNDETERMINED:
      56             :       return "Undetermined";
      57             :       break;
      58             :     default:
      59             :       throw(std::runtime_error("Unknown mode!"));
      60             :     }
      61             :   }
      62             : 
      63             :   bool result;
      64             :   std::stack<expression_mode> mode_stack;
      65             : 
      66          14 :   ppg_traverser()
      67          14 :     : result(true)
      68          14 :   {}
      69             : 
      70           0 :   void enter(const not_& x)
      71             :   {
      72           0 :     result = result && is_simple_expression(x);
      73           0 :   }
      74             : 
      75           0 :   void enter(const imp& x)
      76             :   {
      77           0 :     result = result && is_simple_expression(x);
      78           0 :   }
      79             : 
      80          36 :   void enter(const pbes_system::forall& x)
      81             :   {
      82          36 :     expression_mode mode = mode_stack.top();
      83          36 :     bool simple_body = is_simple_expression(x.body());
      84          36 :     if (!simple_body)
      85             :     {
      86             :       //std::clog << "Note: 'forall' in mode " << print_mode(mode) << std::endl;
      87          36 :       switch(mode)
      88             :       {
      89          28 :       case UNDETERMINED:
      90             :       case CONJUNCTIVE:
      91          28 :         mode = UNIVERSAL;
      92          36 :       case UNIVERSAL:
      93          36 :         break;
      94           0 :       case DISJUNCTIVE:
      95             :       case EXISTENTIAL:
      96           0 :         result = false;
      97           0 :         break;
      98           0 :       default:
      99           0 :         break;
     100             :       }
     101             :     }
     102          36 :     mode_stack.push(mode);
     103          36 :   }
     104             : 
     105          36 :   void leave(const pbes_system::forall& /*x*/)
     106             :   {
     107          36 :     mode_stack.pop();
     108          36 :   }
     109             : 
     110           4 :   void enter(const pbes_system::exists& x)
     111             :   {
     112           4 :     expression_mode mode = mode_stack.top();
     113           4 :     bool simple_body = is_simple_expression(x.body());
     114           4 :     if (!simple_body)
     115             :     {
     116             :       //std::clog << "Note: 'exists' in mode " << print_mode(mode) << std::endl;
     117           4 :       switch(mode)
     118             :       {
     119           2 :       case UNDETERMINED:
     120             :       case DISJUNCTIVE:
     121           2 :         mode = EXISTENTIAL;
     122           2 :       case EXISTENTIAL:
     123           2 :         break;
     124           2 :       case CONJUNCTIVE:
     125             :       case UNIVERSAL:
     126             :         //std::clog << "Invalid: 'exists' in mode " << print_mode(mode) << std::endl;
     127           2 :         result = false;
     128           2 :         break;
     129           0 :       default:
     130           0 :         break;
     131             :       }
     132             :     }
     133           4 :     mode_stack.push(mode);
     134           4 :   }
     135             : 
     136           4 :   void leave(const pbes_system::exists& /*x*/)
     137             :   {
     138           4 :     mode_stack.pop();
     139           4 :   }
     140             : 
     141          64 :   void enter(const pbes_system::and_& x)
     142             :   {
     143          64 :     expression_mode mode = mode_stack.top();
     144          64 :     bool is_simple = is_simple_expression(x);
     145          64 :     if (!is_simple)
     146             :     {
     147             :       //std::clog << "Note: 'and' in mode " << print_mode(mode) << std::endl;
     148          64 :       switch(mode)
     149             :       {
     150          22 :       case UNDETERMINED:
     151          22 :         mode = CONJUNCTIVE;
     152             :         //std::clog << "Note: to mode " << print_mode(mode) << std::endl;
     153          61 :       case CONJUNCTIVE:
     154          61 :         break;
     155           0 :       case UNIVERSAL:
     156             :         //std::clog << "and: " << core::pp(x) << std::endl;
     157             :         //std::clog << "Invalid: 'and' in mode " << print_mode(mode) << std::endl;
     158           0 :         result = false;
     159           0 :         break;
     160           3 :       case EXISTENTIAL:
     161             :       case DISJUNCTIVE:
     162             :       {
     163           3 :         std::size_t count = 0;
     164           3 :         std::vector<pbes_expression> conjuncts = split_conjuncts(x);
     165          10 :         for(const pbes_expression& conjunct : conjuncts)
     166             :         {
     167           7 :           if (!is_simple_expression(conjunct))
     168             :           {
     169             :             //std::clog << "and: " << core::pp(*it) << std::endl;
     170           3 :             count++;
     171           3 :             if (count > 1 || !is_propositional_variable_instantiation(conjunct))
     172             :             {
     173             :               //std::clog << "Invalid: 'and' in mode " << print_mode(mode) << std::endl;
     174           0 :               result = false;
     175           0 :               break;
     176             :             }
     177             :           }
     178             :         }
     179           3 :         break;
     180           3 :       }
     181           0 :       default:
     182           0 :         break;
     183             :       }
     184             :     }
     185          64 :     mode_stack.push(mode);
     186          64 :   }
     187             : 
     188          64 :   void leave(const pbes_system::and_& /*x*/)
     189             :   {
     190          64 :     mode_stack.pop();
     191          64 :   }
     192             : 
     193         100 :   void enter(const pbes_system::or_& x)
     194             :   {
     195         100 :     expression_mode mode = mode_stack.top();
     196         100 :     bool is_simple = is_simple_expression(x);
     197         100 :     if (!is_simple)
     198             :     {
     199             :       //std::clog << "Note: 'or' in mode " << print_mode(mode) << std::endl;
     200          96 :       switch(mode)
     201             :       {
     202           0 :       case UNDETERMINED:
     203           0 :         mode = DISJUNCTIVE;
     204           0 :       case DISJUNCTIVE:
     205           0 :         break;
     206           0 :       case EXISTENTIAL:
     207             :         //std::clog << "Invalid: 'or' in mode " << print_mode(mode) << std::endl;
     208           0 :         result = false;
     209           0 :         break;
     210          96 :       case UNIVERSAL:
     211             :       case CONJUNCTIVE:
     212             :       {
     213          96 :         std::size_t count = 0;
     214          96 :         std::vector<pbes_expression>  disjuncts = split_disjuncts(x);
     215         312 :         for(const pbes_expression& disjunct : disjuncts)
     216             :         {
     217         216 :           if (!is_simple_expression(disjunct))
     218             :           {
     219          96 :             count++;
     220          96 :             if (count > 1 || !is_propositional_variable_instantiation(disjunct))
     221             :             {
     222             :               ///std::clog << "Invalid: 'or' in mode " << print_mode(mode) << std::endl;
     223           0 :               result = false;
     224           0 :               break;
     225             :             }
     226             :           }
     227             :         }
     228          96 :         break;
     229          96 :       }
     230           0 :       default:
     231           0 :         break;
     232             :       }
     233             :     }
     234         100 :     mode_stack.push(mode);
     235         100 :   }
     236             : 
     237         100 :   void leave(const pbes_system::or_& /*x*/)
     238             :   {
     239         100 :     mode_stack.pop();
     240         100 :   }
     241             : 
     242          32 :   void enter(const pbes_equation& /*x*/)
     243             :   {
     244             :     //std::clog << "Equation " << x.variable().name() << std::endl;
     245          32 :     mode_stack.push(UNDETERMINED);
     246          32 :   }
     247             : 
     248          32 :   void leave(const pbes_equation& /*x*/)
     249             :   {
     250          32 :     mode_stack.pop();
     251          32 :   }
     252             : 
     253             : };
     254             : /// \endcond
     255             : 
     256             : /// \brief Determines if an expression is a PPG expression.
     257             : /// \param x a PBES object
     258             : /// \return true if x is a PPG expression.
     259             : template <typename T>
     260          14 : bool is_ppg(const T& x)
     261             : {
     262          14 :   ppg_traverser f;
     263          14 :   f.apply(x);
     264          14 :   return f.result;
     265          14 : }
     266             : 
     267             : } // namespace detail
     268             : 
     269             : } // namespace pbes_system
     270             : 
     271             : } // namespace mcrl2
     272             : 
     273             : #endif // MCRL2_PBES_DETAIL_PPG_TRAVERSER_H

Generated by: LCOV version 1.14