diff --git a/README b/README index 2195f09a8..72615f049 100644 --- a/README +++ b/README @@ -284,6 +284,7 @@ spot/ Sources for libspot. kripke/ Kripke Structure interface. tl/ Temporal Logic formulas and algorithms. misc/ Miscellaneous support files. + mc/ All algorithms useful for model checking parseaut/ Parser for automata in multiple formats. parsetl/ Parser for LTL/PSL formulas. priv/ Private algorithms, used internally but not exported. diff --git a/configure.ac b/configure.ac index 6f25d894f..5039b5adb 100644 --- a/configure.ac +++ b/configure.ac @@ -234,6 +234,7 @@ AC_CONFIG_FILES([ spot/ltsmin/Makefile spot/Makefile spot/misc/Makefile + spot/mc/Makefile spot/parseaut/Makefile spot/parsetl/Makefile spot/priv/Makefile diff --git a/spot/mc/Makefile.am b/spot/mc/Makefile.am new file mode 100644 index 000000000..f463a9e6a --- /dev/null +++ b/spot/mc/Makefile.am @@ -0,0 +1,30 @@ +## -*- coding: utf-8 -*- +## Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Laboratoire +## de Recherche et Développement de l'Epita (LRDE). +## Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), +## département Systèmes Répartis Coopératifs (SRC), Université Pierre +## 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 +## the Free Software Foundation; either version 3 of the License, or +## (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 +## along with this program. If not, see . + +AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) $(BUDDY_CPPFLAGS) +AM_CXXFLAGS = $(WARNING_CXXFLAGS) + +mcdir = $(pkgincludedir)/mc + +mc_HEADERS = reachability.hh + +noinst_LTLIBRARIES = libmc.la diff --git a/spot/mc/reachability.hh b/spot/mc/reachability.hh new file mode 100644 index 000000000..97dd09fa5 --- /dev/null +++ b/spot/mc/reachability.hh @@ -0,0 +1,117 @@ +// -*- coding: utf-8 -*- +// Copyright (C) 2015, 2016 Laboratoire de Recherche et +// Developpement de l'Epita +// +// 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 +// the Free Software Foundation; either version 3 of the License, or +// (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 +// along with this program. If not, see . + +#pragma once + +#include + +namespace spot +{ + /// \brief This template class provide a sequential reachability + /// of a kripkecube. The algorithm uses a single DFS since it + /// is the most efficient in a sequential setting + template + class SPOT_API seq_reach_kripke + { + public: + seq_reach_kripke(kripkecube& sys): + sys_(sys) + { + assert(is_a_kripkecube(sys)); + visited.reserve(2000000); + todo.reserve(100000); + } + + ~seq_reach_kripke() + { + // States will be destroyed by the system, so just clear map + visited.clear(); + } + + Visitor& self() + { + return static_cast(*this); + } + + void run() + { + self().setup(); + State initial = sys_.initial(); + todo.push_back({initial, sys_.succ(initial)}); + visited[initial] = ++dfs_number; + self().push(initial, dfs_number); + while (!todo.empty()) + { + if (todo.back().it->done()) + { + sys_.recycle(todo.back().it); + todo.pop_back(); + } + else + { + ++transitions; + State dst = todo.back().it->state(); + auto it = visited.insert({dst, dfs_number+1}); + if (it.second) + { + ++dfs_number; + self().push(dst, dfs_number); + self().edge(visited[todo.back().s], dfs_number); + todo.back().it->next(); + todo.push_back({dst, sys_.succ(dst)}); + } + else + { + self().edge(visited[todo.back().s], visited[dst]); + todo.back().it->next(); + } + } + } + self().finalize(); + } + + unsigned int states() + { + return dfs_number; + } + + unsigned int trans() + { + return transitions; + } + + protected: + struct todo_element + { + State s; + SuccIterator* it; + }; + kripkecube& sys_; + std::vector todo; + // FIXME: The system already handle a set of visited states so + // this map is redundant: an we avoid this new map? + typedef std::unordered_map visited_map; + visited_map visited; + unsigned int dfs_number = 0; + unsigned int transitions = 0; + }; +}