LCOV - code coverage report
Current view: top level - pg/source - ParityGame_verify.cpp (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 0 44 0.0 %
Date: 2024-04-21 03:44:01 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2009-2013 University of Twente
       2             : // Copyright (c) 2009-2013 Michael Weber <michaelw@cs.utwente.nl>
       3             : // Copyright (c) 2009-2013 Maks Verver <maksverver@geocities.com>
       4             : // Copyright (c) 2009-2013 Eindhoven University of Technology
       5             : //
       6             : // Distributed under the Boost Software License, Version 1.0.
       7             : // (See accompanying file LICENSE_1_0.txt or copy at
       8             : // http://www.boost.org/LICENSE_1_0.txt)
       9             : 
      10             : #include "mcrl2/pg/ParityGame.h"
      11             : #include "mcrl2/pg/SCC.h"
      12             : 
      13             : /*! \file ParityGame_verify.cc
      14             : 
      15             :     Implementation of parity game solution verification algorithm.
      16             : */
      17             : 
      18             : 
      19             : /*! A functor that is used to verify the solution for a strongly-connected
      20             :     component of the game graph.
      21             : 
      22             :     This is a separate class because the SCC decomposition algorithm expects
      23             :     a functor which is called for every component found.
      24             : 
      25             :     \see ParityGame::verify
      26             : */
      27             : struct VerifySCC  // used by ParityGame::verify()
      28             : {
      29             :     const ParityGame    &game;
      30             :     const StaticGraph   &graph;
      31             :     const priority_t    prio;
      32             :     verti * const       error;
      33             : 
      34           0 :     int operator() (const verti *scc, std::size_t scc_size)
      35             :     {
      36             :         // Search vertices in this SCC for a vertex with priority `prio`:
      37           0 :         for (std::size_t i = 0; i < scc_size; ++i)
      38             :         {
      39           0 :             verti v = scc[i];
      40           0 :             if (game.priority(v) == prio)
      41             :             {
      42             :                 // Cycle detected if |SCC| > 1 or v has a self-edge:
      43           0 :                 if (scc_size > 1 || graph.has_succ(v, v))
      44             :                 {
      45           0 :                     if (error) *error = v;
      46           0 :                     return 1;
      47             :                 }
      48             :             }
      49             :         }
      50           0 :         return 0;
      51             :     }
      52             : };
      53             : 
      54           0 : bool ParityGame::verify(const Strategy &s, verti *error) const
      55             : {
      56           0 :     assert(s.size() == graph_.V());
      57             : 
      58             :     /* Make sure winning sets are consistently defined; i.e. only existent
      59             :        edges are used, and there are no transitions that cross winning sets. */
      60           0 :     for (verti v = 0; v < graph_.V(); ++v)
      61             :     {
      62           0 :         Player pl = winner(s, v);
      63             : 
      64           0 :         if (pl == player(v))  /* vertex won by owner */
      65             :         {
      66             :             /* Verify that:
      67             :                 1. the vertex owner has a strategy (necessarily passes)
      68             :                 2. the strategy uses an existing edge
      69             :                 3. the strategy doesn't move outside the owner's winning set */
      70           0 :             if ( s[v] == NO_VERTEX || !graph_.has_succ(v, s[v]) ||
      71           0 :                  winner(s, s[v]) != pl )
      72             :             {
      73           0 :                 if (error) *error = v;
      74           0 :                 return false;
      75             :             }
      76             :         }
      77             :         else  /* vertex lost by owner */
      78             :         {
      79             :             // Verify owner has no strategy: (necessarily passes)
      80           0 :             if (s[v] != NO_VERTEX)
      81             :             {
      82           0 :                 if (error) *error = v;
      83           0 :                 return false;
      84             :             }
      85             : 
      86             :             // Verify owner cannot move outside this winning set:
      87           0 :             for (StaticGraph::const_iterator it = graph_.succ_begin(v);
      88           0 :                  it != graph_.succ_end(v); ++it)
      89             :             {
      90           0 :                 if (winner(s, *it) != pl)
      91             :                 {
      92           0 :                     if (error) *error = v;
      93           0 :                     return false;
      94             :                 }
      95             :             }
      96             :         }
      97             :     }
      98             : 
      99             :     // Verify absence of cycles owned by opponent in winning sets
     100           0 :     for (priority_t prio = 0; prio < d(); ++prio)
     101             :     {
     102             :         /* Create set of edges incident with vertices in the winning set of
     103             :            player (1 - prio%2) consistent with strategy s and incident with
     104             :            vertices of priorities >= prio only. */
     105           0 :         StaticGraph::edge_list edges;
     106           0 :         for (verti v = 0; v < graph_.V(); ++v)
     107             :         {
     108           0 :             if (priority(v) >= prio && (int)winner(s, v) == (1 - prio%2))
     109             :             {
     110           0 :                 if (s[v] != NO_VERTEX)
     111             :                 {
     112           0 :                     if (priority(s[v]) >= prio)
     113             :                     {
     114           0 :                         edges.push_back(std::make_pair(v, s[v]));
     115             :                     }
     116             :                 }
     117             :                 else
     118             :                 {
     119           0 :                     for (StaticGraph::const_iterator it = graph_.succ_begin(v);
     120           0 :                          it != graph_.succ_end(v); ++it)
     121             :                     {
     122           0 :                         if (priority(*it) >= prio)
     123             :                         {
     124           0 :                             edges.push_back(std::make_pair(v, *it));
     125             :                         }
     126             :                     }
     127             :                 }
     128             :             }
     129             :         }
     130             : 
     131             :         /* NOTE: we should NOT compact vertices here, because then we cannot
     132             :            use their indices to determine the priority of vertices in
     133             :            VerifySCC::operator().
     134             : 
     135             :            Alternatively, we could compress the priority vector as well.
     136             :            We could share some code with make_subgame() to do this (except that
     137             :            we don't need the player vector, and we don't need bidirectional
     138             :            edges, which require sorting).
     139             :         */
     140             : 
     141             :         // Create a subgraph storing successors only:
     142           0 :         StaticGraph subgraph;
     143           0 :         subgraph.assign(edges, StaticGraph::EDGE_SUCCESSOR);
     144             : 
     145             :         // Find a vertex with priority prio on a cycle:
     146           0 :         VerifySCC verifier = { *this, subgraph, prio, error };
     147           0 :         if (decompose_graph(subgraph, verifier) != 0)
     148             :         {
     149             :             // VerifySCC has already set *error here.
     150           0 :             return false;
     151             :         }
     152           0 :     }
     153           0 :     if (error) *error = NO_VERTEX;
     154           0 :     return true;
     155             : }

Generated by: LCOV version 1.14