LCOV - code coverage report
Current view: top level - lps/include/mcrl2/lps - disjointness_checker.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 46 56 82.1 %
Date: 2024-04-19 03:43:27 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Author(s): Luc Engelen
       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 include/disjointness_checker.h
      10             : /// \brief Add your file description here.
      11             : 
      12             : // Interface to class Disjointness_Checker
      13             : // file: disjointness_checker.h
      14             : 
      15             : #ifndef MCRL2_LPS_DISJOINTNESS_CHECKER_H
      16             : #define MCRL2_LPS_DISJOINTNESS_CHECKER_H
      17             : 
      18             : #include "mcrl2/lps/linear_process.h"
      19             : 
      20             : /// \brief Class that can determine if two summands are syntactically disjoint.
      21             : /// Two summands are syntactically disjoint if the following conditions hold:
      22             : /// - The set of variables used by one summand is disjoint from the set of variables changed by the other summand and
      23             : ///   vice versa.
      24             : /// - The set of variables changed by one summand is disjoint from the set of variables changed by the other summand.
      25             : ///
      26             : /// An instance of the class Disjointness_Checker is created using the constructor
      27             : /// Disjointness_Checker::Disjointness_Checker. The parameter a_process_equations is used to pass the summands to be
      28             : /// checked for disjointness. The function Disjointness_Checker::disjoint indicates whether the two summands with numbers
      29             : /// n_1 and n_2 are syntactically disjoint.
      30             : 
      31             : namespace mcrl2
      32             : {
      33             : namespace lps
      34             : {
      35             : namespace detail
      36             : {
      37             : 
      38             : class Disjointness_Checker
      39             : {
      40             :   private:
      41             :     /// \brief The number of summands of the LPS passed as argument of the constructor.
      42             :     std::size_t f_number_of_summands;
      43             : 
      44             :     /// \brief A two dimensional array, indicating which parameters a summand uses, for each of the summands.
      45             :     std::vector<std::set<data::variable> > f_used_parameters_per_summand;
      46             : 
      47             :     /// \brief A two dimensional array, indicating which parameters a summand changes, for each of the summands.
      48             :     std::vector<std::set<data::variable> > f_changed_parameters_per_summand;
      49             : 
      50             :     /// \brief Updates the array Disjointness_Checker::f_used_parameters_per_summand, given the expression a_expression.
      51             :     void process_data_expression(std::size_t n, const data::data_expression& x);
      52             : 
      53             :     /// \brief Updates the array Disjointness_Checker::f_used_parameters_per_summand, given the multiaction a.
      54             :     void process_multi_action(std::size_t n, const multi_action& a);
      55             : 
      56             :     /// \brief Updates the arrays Disjointness_Checker::f_changed_parameters_per_summand and
      57             :     /// \brief Disjointness_Checker::f_used_parameters_per_summand, given the summand s.
      58             :     void process_summand(std::size_t n, const action_summand& s);
      59             : 
      60             :   public:
      61             :     /// \brief Constructor that initializes the sets Disjointness_Checker::f_used_parameters_per_summand and
      62             :     /// \brief Disjointness_Checker::f_changed_parameters_per_summand, and the indexed set
      63             :     /// \brief Disjointness_Checker::f_parameter_set.
      64             :     /// precondition: the argument passed as parameter a_process_equations is a specification of process equations in mCRL2
      65             :     /// format
      66             :     /// precondition: the arguments passed as parameters n_1 and n_2 correspond to summands in
      67             :     /// the proces equations passed as parameter a_process_equations. They lie in the interval from and including 1 upto and
      68             :     /// including the highest summand number
      69             :     template <typename LinearProcess>
      70             :     Disjointness_Checker(const LinearProcess& a_process_equation);
      71             : 
      72             :     /// \brief Indicates whether or not the summands with number n_1 and n_2 are disjoint.
      73             :     bool disjoint(std::size_t n1, std::size_t n2);
      74             : };
      75             : 
      76             : inline
      77         271 : void Disjointness_Checker::process_data_expression(std::size_t n, const data::data_expression& x)
      78             : {
      79             :   // This should probably once be replaced by a visitor.
      80         271 :   if (data::is_variable(x))
      81             :   {
      82          43 :     f_used_parameters_per_summand[n].insert(data::variable(x));
      83             :   }
      84         228 :   else if (data::is_where_clause(x))
      85             :   {
      86           0 :     const data::where_clause& t = atermpp::down_cast<data::where_clause>(x);
      87           0 :     process_data_expression(n, t.body());
      88           0 :     const data::assignment_list& assignments = t.assignments();
      89           0 :     for (const auto & assignment : assignments)
      90             :     {
      91           0 :       process_data_expression(n, assignment.rhs());
      92             :     }
      93             :   }
      94         228 :   else if (data::is_function_symbol(x))
      95             :   {
      96             :     // do nothing
      97             :   }
      98          71 :   else if (data::is_application(x))
      99             :   {
     100          71 :     const data::application& t = atermpp::down_cast<data::application>(x);
     101          71 :     process_data_expression(n, t.head());
     102         205 :     for (auto i = t.begin(); i != t.end(); ++i)
     103             :     {
     104         134 :       process_data_expression(n,*i);
     105             :     }
     106             :   }
     107           0 :   else if (data::is_abstraction(x))
     108             :   {
     109           0 :     const data::abstraction& t = atermpp::down_cast<data::abstraction>(x);
     110           0 :     process_data_expression(n, t.body());
     111             :   }
     112             :   else
     113             :   {
     114           0 :     throw mcrl2::runtime_error("disjointness checker encountered unknown term " + data::pp(x));
     115             :   }
     116         271 : }
     117             : 
     118             : inline
     119          20 : void Disjointness_Checker::process_multi_action(std::size_t n, const multi_action& a)
     120             : {
     121          20 :   if (a.has_time())
     122             :   {
     123           0 :     process_data_expression(n, a.time());
     124             :   }
     125             : 
     126          20 :   const process::action_list& v_actions = a.actions();
     127          31 :   for (const auto & v_action : v_actions)
     128             :   {
     129          11 :     const data::data_expression_list v_expressions=v_action.arguments();
     130             : 
     131          15 :     for (const auto & v_expression : v_expressions)
     132             :     {
     133           4 :       process_data_expression(n, v_expression);
     134             :     }
     135          11 :   }
     136          20 : }
     137             : 
     138             : inline
     139          20 : void Disjointness_Checker::process_summand(std::size_t n, const action_summand& s)
     140             : {
     141             :   // variables used in condition
     142          20 :   process_data_expression(n, s.condition());
     143             : 
     144             :   // variables used in multiaction
     145          20 :   process_multi_action(n, s.multi_action());
     146             : 
     147             :   // variables used and changed in assignments
     148          20 :   const data::assignment_list& v_assignments = s.assignments();
     149          62 :   for (const auto & v_assignment : v_assignments)
     150             :   {
     151             :     // variables changed in the assignment
     152          42 :     f_changed_parameters_per_summand[n].insert(v_assignment.lhs());
     153             : 
     154             :     // variables used in assignment
     155          42 :     process_data_expression(n, v_assignment.rhs());
     156             :   }
     157          20 : }
     158             : 
     159             : template <typename LinearProcess>
     160           5 : Disjointness_Checker::Disjointness_Checker(const LinearProcess& a_process_equation)
     161             : {
     162           5 :   const auto& v_summands = a_process_equation.action_summands();
     163           5 :   std::size_t v_summand_number = 1;
     164             : 
     165           5 :   f_number_of_summands = v_summands.size();
     166           5 :   f_used_parameters_per_summand =
     167          10 :     std::vector<std::set<data::variable> >(f_number_of_summands + 1, std::set<data::variable>());
     168           5 :   f_changed_parameters_per_summand =
     169          10 :     std::vector<std::set<data::variable> >(f_number_of_summands + 1, std::set<data::variable>());
     170             : 
     171          25 :   for (const auto & v_summand : v_summands)
     172             :   {
     173          20 :     process_summand(v_summand_number, v_summand);
     174          20 :     v_summand_number++;
     175             :   }
     176           5 : }
     177             : 
     178             : inline
     179          44 : bool Disjointness_Checker::disjoint(std::size_t n1, std::size_t n2)
     180             : {
     181             :   using utilities::detail::has_empty_intersection;
     182          44 :   assert(n1 <= f_number_of_summands && n2 <= f_number_of_summands);
     183          44 :   bool v_used_1_changed_2 = has_empty_intersection(f_used_parameters_per_summand[n1], f_changed_parameters_per_summand[n2]);
     184          44 :   bool v_used_2_changed_1 = has_empty_intersection(f_used_parameters_per_summand[n2], f_changed_parameters_per_summand[n1]);
     185          44 :   bool v_changed_1_changed_2 = has_empty_intersection(f_changed_parameters_per_summand[n1], f_changed_parameters_per_summand[n2]);
     186          44 :   return v_used_1_changed_2 && v_used_2_changed_1 && v_changed_1_changed_2;
     187             : }
     188             : 
     189             : } // namespace detail
     190             : } // namespace lps
     191             : } // namespace mcrl2
     192             : 
     193             : #endif

Generated by: LCOV version 1.14