bfssteps.cc 2.84 KB
Newer Older
1 2 3 4 5
// -*- coding: utf-8 -*-
// Copyright (C) 2014, 2015 Laboratoire de Recherche et Développement
// de l'Epita (LRDE)
// Copyright (C) 2004  Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
6 7 8 9 10 11
// et Marie Curie.
//
// This file is part of Spot, a model checking library.
//
// Spot is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
12
// the Free Software Foundation; either version 3 of the License, or
13 14 15 16 17 18 19 20
// (at your option) any later version.
//
// Spot is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
21
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
22

23 24
#include <deque>
#include <utility>
25
#include "twa/twa.hh"
26 27 28 29 30
#include "bfssteps.hh"

namespace spot
{

31
  bfs_steps::bfs_steps(const const_twa_ptr& a)
32 33 34 35 36 37 38 39
    : a_(a)
  {
  }

  bfs_steps::~bfs_steps()
  {
  }

40
  void
41 42 43
  bfs_steps::finalize(const std::map<const state*, twa_run::step,
                state_ptr_less_than>& father, const twa_run::step& s,
                const state* start, twa_run::steps& l)
44
  {
45 46
    twa_run::steps p;
    twa_run::step current = s;
47 48
    for (;;)
      {
49
        twa_run::step tmp = current;
50 51 52 53
        tmp.s = tmp.s->clone();
        p.push_front(tmp);
        if (current.s == start)
          break;
54
        std::map<const state*, twa_run::step,
55
            state_ptr_less_than>::const_iterator it = father.find(current.s);
Alexandre Duret-Lutz's avatar
Alexandre Duret-Lutz committed
56
        assert(it != father.end());
57 58 59 60 61
        current = it->second;
      }
    l.splice(l.end(), p);
  }

62
  const state*
63
  bfs_steps::search(const state* start, twa_run::steps& l)
64 65 66
  {
    // Records backlinks to parent state during the BFS.
    // (This also stores the propositions of this link.)
67
    std::map<const state*, twa_run::step,
68 69 70 71 72 73 74 75 76 77
      state_ptr_less_than> father;
    // BFS queue.
    std::deque<const state*> todo;
    // Initial state.
    todo.push_back(start);

    while (!todo.empty())
      {
	const state* src = todo.front();
	todo.pop_front();
78
	for (auto i: a_->succ(src))
79 80 81 82 83 84 85
	  {
	    const state* dest = filter(i->current_state());

	    if (!dest)
	      continue;

	    bdd cond = i->current_condition();
86
	    acc_cond::mark_t acc = i->current_acceptance_conditions();
87
	    twa_run::step s = { src, cond, acc };
88 89 90 91

	    if (match(s, dest))
	      {
		// Found it!
92
                finalize(father, s, start, l);
93 94 95 96 97 98 99 100 101 102 103 104
		return dest;
	      }

	    // Common case: record backlinks and continue BFS
	    // for unvisited states.
	    if (father.find(dest) == father.end())
	      {
		todo.push_back(dest);
		father[dest] = s;
	      }
	  }
      }
105
    return nullptr;
106 107 108
  }

}