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;
+ };
+}