graph: Implement a directed graph.
* src/graph/graph.hh, src/graph/Makefile.am, src/graphtest/graph.cc, src/graphtest/graph.test, src/graphtest/defs.in, src/graphtest/Makefile.am: New files. * src/Makefile.am, configure.ac: Add graph/ and graphtest/. * README: Mention these directories.
This commit is contained in:
parent
7bcf655350
commit
f7711e9a63
10 changed files with 931 additions and 8 deletions
2
README
2
README
|
|
@ -148,6 +148,8 @@ src/ Sources for libspot.
|
||||||
dstarparse/ Parser for the output of ltl2dstar.
|
dstarparse/ Parser for the output of ltl2dstar.
|
||||||
eltlparse/ Parser for ELTL formulae.
|
eltlparse/ Parser for ELTL formulae.
|
||||||
eltltest/ Tests for ELTL nodes in ltlast/ and eltlparse/.
|
eltltest/ Tests for ELTL nodes in ltlast/ and eltlparse/.
|
||||||
|
graph/ Graph representations.
|
||||||
|
graphtest/ Graph representations.
|
||||||
kripke/ Kripke Structure interface.
|
kripke/ Kripke Structure interface.
|
||||||
kripkeparse/ Parser for explicit Kripke.
|
kripkeparse/ Parser for explicit Kripke.
|
||||||
kripketest/ Tests for kripke explicit.
|
kripketest/ Tests for kripke explicit.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Laboratoire
|
# Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Laboratoire
|
||||||
# de Recherche et Développement de l'Epita (LRDE).
|
# de Recherche et Développement de l'Epita (LRDE).
|
||||||
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Laboratoire d'Informatique de
|
# Copyright (C) 2003, 2004, 2005, 2006, 2007 Laboratoire
|
||||||
# Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC), Université
|
# d'Informatique de Paris 6 (LIP6), département Systèmes Répartis
|
||||||
# Pierre et Marie Curie.
|
# Coopératifs (SRC), Université Pierre et Marie Curie.
|
||||||
#
|
#
|
||||||
# This file is part of Spot, a model checking library.
|
# This file is part of Spot, a model checking library.
|
||||||
#
|
#
|
||||||
|
|
@ -181,6 +181,9 @@ AC_CONFIG_FILES([
|
||||||
src/eltltest/defs
|
src/eltltest/defs
|
||||||
src/eltltest/Makefile
|
src/eltltest/Makefile
|
||||||
src/kripke/Makefile
|
src/kripke/Makefile
|
||||||
|
src/graph/Makefile
|
||||||
|
src/graphtest/Makefile
|
||||||
|
src/graphtest/defs
|
||||||
src/ltlast/Makefile
|
src/ltlast/Makefile
|
||||||
src/ltlenv/Makefile
|
src/ltlenv/Makefile
|
||||||
src/ltlparse/Makefile
|
src/ltlparse/Makefile
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
## -*- coding: utf-8 -*-
|
## -*- coding: utf-8 -*-
|
||||||
## Copyright (C) 2009, 2010, 2012, 2013 Laboratoire de Recherche et
|
## Copyright (C) 2009, 2010, 2012, 2013, 2014 Laboratoire de Recherche
|
||||||
## Développement de l'Epita (LRDE).
|
## et Développement de l'Epita (LRDE).
|
||||||
## Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
## Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||||
## département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
## département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||||
## et Marie Curie.
|
## et Marie Curie.
|
||||||
|
|
@ -25,10 +25,10 @@ AUTOMAKE_OPTIONS = subdir-objects
|
||||||
# List directories in the order they must be built. Keep tests at the
|
# List directories in the order they must be built. Keep tests at the
|
||||||
# end, after building '.' (since the current directory contains
|
# end, after building '.' (since the current directory contains
|
||||||
# libspot.la needed by the tests)
|
# libspot.la needed by the tests)
|
||||||
SUBDIRS = misc priv ltlenv ltlast ltlvisit ltlparse eltlparse tgba \
|
SUBDIRS = misc priv ltlenv ltlast ltlvisit ltlparse eltlparse graph \
|
||||||
tgbaalgos tgbaparse ta taalgos kripke saba sabaalgos \
|
tgba tgbaalgos tgbaparse ta taalgos kripke saba sabaalgos \
|
||||||
neverparse kripkeparse dstarparse . bin ltltest eltltest \
|
neverparse kripkeparse dstarparse . bin ltltest eltltest \
|
||||||
tgbatest sabatest kripketest sanity
|
graphtest tgbatest sabatest kripketest sanity
|
||||||
|
|
||||||
lib_LTLIBRARIES = libspot.la
|
lib_LTLIBRARIES = libspot.la
|
||||||
libspot_la_SOURCES =
|
libspot_la_SOURCES =
|
||||||
|
|
|
||||||
27
src/graph/Makefile.am
Normal file
27
src/graph/Makefile.am
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
## -*- coding: utf-8 -*-
|
||||||
|
## Copyright (C) 2014 Laboratoire de Recherche et Développement de
|
||||||
|
## l'Epita (LRDE).
|
||||||
|
##
|
||||||
|
## 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I$(srcdir)/..
|
||||||
|
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
||||||
|
|
||||||
|
graphdir = $(pkgincludedir)/graph
|
||||||
|
|
||||||
|
graph_HEADERS = \
|
||||||
|
graph.hh
|
||||||
371
src/graph/graph.hh
Normal file
371
src/graph/graph.hh
Normal file
|
|
@ -0,0 +1,371 @@
|
||||||
|
// -*- coding: utf-8 -*-
|
||||||
|
// Copyright (C) 2014 Laboratoire de Recherche et Développement 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef SPOT_GRAPH_GRAPH_HH
|
||||||
|
# define SPOT_GRAPH_GRAPH_HH
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
template <typename State_Data, typename Trans_Data, bool Alternating = false>
|
||||||
|
class digraph;
|
||||||
|
|
||||||
|
namespace internal
|
||||||
|
{
|
||||||
|
// The boxed_label class stores Data as an attribute called
|
||||||
|
// "label" if boxed is true. It is an empty class if Data is
|
||||||
|
// void, and it simply inherits from Data if boxed is false.
|
||||||
|
//
|
||||||
|
// The data() method offers an homogeneous access to the Data
|
||||||
|
// instance.
|
||||||
|
|
||||||
|
template <typename Data, bool boxed = !std::is_class<Data>::value>
|
||||||
|
struct boxed_label
|
||||||
|
{
|
||||||
|
Data label;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
boxed_label(Args&&... args):
|
||||||
|
label{std::forward<Args>(args)...}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Data is a POD type, G++ 4.8.2 wants default values for all
|
||||||
|
// label fields unless we define this default constructor here.
|
||||||
|
explicit boxed_label()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Data& data()
|
||||||
|
{
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Data& data() const
|
||||||
|
{
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct boxed_label<void, true>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Data>
|
||||||
|
struct boxed_label<Data, false>: public Data
|
||||||
|
{
|
||||||
|
template <typename... Args>
|
||||||
|
boxed_label(Args&&... args):
|
||||||
|
Data{std::forward<Args>(args)...}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Data is a POS type, G++ 4.8.2 wants default values for all
|
||||||
|
// label fields unless we define this default constructor here.
|
||||||
|
explicit boxed_label()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Data& data()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Data& data() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
// State storage for digraphs
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// We have two implementations, one with attached State_Data, and
|
||||||
|
// one without.
|
||||||
|
|
||||||
|
template <typename Transition, typename State_Data>
|
||||||
|
struct distate_storage: public State_Data
|
||||||
|
{
|
||||||
|
Transition succ; // First outgoing transition (used when iterating)
|
||||||
|
Transition succ_tail; // Last outgoing transition (used for
|
||||||
|
// appending new transitions)
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
distate_storage(Args&&... args):
|
||||||
|
State_Data{std::forward<Args>(args)...},
|
||||||
|
succ(0),
|
||||||
|
succ_tail(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
// Transition storage
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Again two implementation: one with label, and one without.
|
||||||
|
|
||||||
|
template <typename State, typename Transition, typename Trans_Data>
|
||||||
|
struct trans_storage: public Trans_Data
|
||||||
|
{
|
||||||
|
typedef Transition transition;
|
||||||
|
|
||||||
|
State dst; // destination
|
||||||
|
Transition next_succ; // next outgoing transition with same
|
||||||
|
// source, or 0
|
||||||
|
explicit trans_storage()
|
||||||
|
: Trans_Data{}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
trans_storage(State dst, Transition next_succ, Args&&... args)
|
||||||
|
: Trans_Data{std::forward<Args>(args)...},
|
||||||
|
dst(dst), next_succ(next_succ)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
// Transition iterator
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// This holds a graph and a transition number that is the start of
|
||||||
|
// a list, and it iterates over all the trans_storage_t elements
|
||||||
|
// of that list.
|
||||||
|
|
||||||
|
template <typename Graph>
|
||||||
|
class trans_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Graph::transition transition;
|
||||||
|
typedef typename Graph::trans_storage_t trans_storage_t;
|
||||||
|
|
||||||
|
trans_iterator(Graph* g, transition t): t_(t), g_(g)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(trans_iterator o)
|
||||||
|
{
|
||||||
|
return t_ == o.t_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(trans_iterator o)
|
||||||
|
{
|
||||||
|
return t_ != o.t_;
|
||||||
|
}
|
||||||
|
|
||||||
|
typename std::conditional<std::is_const<Graph>::value,
|
||||||
|
const trans_storage_t&,
|
||||||
|
trans_storage_t&>::type
|
||||||
|
operator*()
|
||||||
|
{
|
||||||
|
return g_->transitions_[t_];
|
||||||
|
}
|
||||||
|
|
||||||
|
trans_iterator operator++()
|
||||||
|
{
|
||||||
|
t_ = operator*().next_succ;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
trans_iterator operator++(int)
|
||||||
|
{
|
||||||
|
trans_iterator ti = *this;
|
||||||
|
t_ = operator*().next_succ;
|
||||||
|
return ti;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
transition t_;
|
||||||
|
Graph* g_;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
// State OUT
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Fake container listing the outgoing transitions of a state.
|
||||||
|
|
||||||
|
template <typename Graph>
|
||||||
|
class state_out
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Graph::transition transition;
|
||||||
|
state_out(Graph* g, transition t):
|
||||||
|
t_(t), g_(g)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
trans_iterator<Graph> begin()
|
||||||
|
{
|
||||||
|
return {g_, t_};
|
||||||
|
}
|
||||||
|
|
||||||
|
trans_iterator<Graph> end()
|
||||||
|
{
|
||||||
|
return {nullptr, 0};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
transition t_;
|
||||||
|
Graph* g_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// The actual graph implementation
|
||||||
|
|
||||||
|
template <typename State_Data, typename Trans_Data, bool Alternating>
|
||||||
|
class digraph
|
||||||
|
{
|
||||||
|
friend class internal::trans_iterator<digraph>;
|
||||||
|
friend class internal::trans_iterator<const digraph>;
|
||||||
|
public:
|
||||||
|
static constexpr bool alternating()
|
||||||
|
{
|
||||||
|
return Alternating;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extra data to store on each state or transition.
|
||||||
|
typedef State_Data state_data_t;
|
||||||
|
typedef Trans_Data trans_data_t;
|
||||||
|
|
||||||
|
// State and transitions are identified by their indices in some
|
||||||
|
// vector.
|
||||||
|
typedef unsigned state;
|
||||||
|
typedef unsigned transition;
|
||||||
|
|
||||||
|
// The type of an output state (when seen from a transition)
|
||||||
|
// depends on the kind of graph we build
|
||||||
|
typedef typename std::conditional<Alternating,
|
||||||
|
std::vector<state>,
|
||||||
|
state>::type out_state;
|
||||||
|
|
||||||
|
typedef internal::distate_storage<transition,
|
||||||
|
internal::boxed_label<State_Data>>
|
||||||
|
state_storage_t;
|
||||||
|
typedef internal::trans_storage<out_state, transition,
|
||||||
|
internal::boxed_label<Trans_Data>>
|
||||||
|
trans_storage_t;
|
||||||
|
typedef std::vector<state_storage_t> state_vector;
|
||||||
|
typedef std::vector<trans_storage_t> trans_vector;
|
||||||
|
protected:
|
||||||
|
state_vector states_;
|
||||||
|
trans_vector transitions_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \brief construct an empty graph
|
||||||
|
///
|
||||||
|
/// Construct an empty graph, and reserve space for \a max_states
|
||||||
|
/// states and \a max_trans transitions. These are not hard
|
||||||
|
/// limits, but just hints to pre-allocate a data structure that
|
||||||
|
/// may hold that much items.
|
||||||
|
digraph(unsigned max_states = 10, unsigned max_trans = 0)
|
||||||
|
{
|
||||||
|
states_.reserve(max_states);
|
||||||
|
if (max_trans == 0)
|
||||||
|
max_trans = max_states * 2;
|
||||||
|
transitions_.reserve(max_trans + 1);
|
||||||
|
// Transition number 0 is not used, because we use this index
|
||||||
|
// to mark the absence of a transition.
|
||||||
|
transitions_.resize(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
state new_state(Args&&... args)
|
||||||
|
{
|
||||||
|
state s = states_.size();
|
||||||
|
states_.emplace_back(std::forward<Args>(args)...);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// May not be called on states with no data.
|
||||||
|
State_Data
|
||||||
|
state_data(state s)
|
||||||
|
{
|
||||||
|
return states_[s].data();
|
||||||
|
}
|
||||||
|
|
||||||
|
// May not be called on states with no data.
|
||||||
|
State_Data
|
||||||
|
state_data(state s) const
|
||||||
|
{
|
||||||
|
return states_[s].data();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
transition
|
||||||
|
new_transition(state src, out_state dst, Args&&... args)
|
||||||
|
{
|
||||||
|
transition t = transitions_.size();
|
||||||
|
transitions_.emplace_back(dst, 0, std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
transition st = states_[src].succ_tail;
|
||||||
|
if (!st)
|
||||||
|
states_[src].succ = t;
|
||||||
|
else
|
||||||
|
transitions_[st].next_succ = t;
|
||||||
|
states_[src].succ_tail = t;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal::state_out<digraph>
|
||||||
|
out(state src)
|
||||||
|
{
|
||||||
|
return {this, states_[src].succ};
|
||||||
|
}
|
||||||
|
|
||||||
|
internal::state_out<const digraph>
|
||||||
|
out(state src) const
|
||||||
|
{
|
||||||
|
return {this, states_[src].succ};
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned nb_states() const
|
||||||
|
{
|
||||||
|
return states_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned nb_trans() const
|
||||||
|
{
|
||||||
|
return transitions_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
const state_vector& states() const
|
||||||
|
{
|
||||||
|
return states_;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_vector& states()
|
||||||
|
{
|
||||||
|
return states_;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_GRAPH_GRAPH_HH
|
||||||
2
src/graphtest/.gitignore
vendored
Normal file
2
src/graphtest/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
graphtest
|
||||||
|
defs
|
||||||
34
src/graphtest/Makefile.am
Normal file
34
src/graphtest/Makefile.am
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
## -*- coding: utf-8 -*-
|
||||||
|
## Copyright (C) 2014 Laboratoire de Recherche et Développement de
|
||||||
|
## l'Epita (LRDE).
|
||||||
|
##
|
||||||
|
## 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I$(srcdir)/.. -I.. $(BUDDY_CPPFLAGS)
|
||||||
|
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
||||||
|
LDADD = ../libspot.la
|
||||||
|
|
||||||
|
noinst_PROGRAMS = graph
|
||||||
|
|
||||||
|
graph_SOURCES = graph.cc
|
||||||
|
|
||||||
|
TESTS = graph.test
|
||||||
|
|
||||||
|
EXTRA_DIST = $(TESTS)
|
||||||
|
|
||||||
|
distclean-local:
|
||||||
|
rm -rf $(TESTS:.test=.dir)
|
||||||
85
src/graphtest/defs.in
Normal file
85
src/graphtest/defs.in
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
# -*- mode: shell-script; coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2009, 2010, 2012, 2013, 2014 Laboratoire de Recherche
|
||||||
|
# et Développement de l'Epita (LRDE).
|
||||||
|
# Copyright (C) 2003, 2004, 2006 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# Ensure we are running from the right directory.
|
||||||
|
test -f ./defs || {
|
||||||
|
echo "defs: not found in current directory" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# If srcdir is not set, then we are not running from `make check'.
|
||||||
|
if test -z "$srcdir"; then
|
||||||
|
# compute $srcdir.
|
||||||
|
srcdir=`echo "$0" | sed -e 's,/[^\\/]*$,,'`
|
||||||
|
test $srcdir = $0 && srcdir=.
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure $srcdir is set correctly.
|
||||||
|
test -f $srcdir/defs.in || {
|
||||||
|
echo "$srcdir/defs.in not found, check \$srcdir" 1>&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "== Running test $0"
|
||||||
|
|
||||||
|
me=`echo "$0" | sed -e 's,.*[\\/],,;s/\.test$//'`
|
||||||
|
|
||||||
|
testSubDir=$me.dir
|
||||||
|
chmod -R a+rwx $testSubDir > /dev/null 2>&1
|
||||||
|
rm -rf $testSubDir > /dev/null 2>&1
|
||||||
|
mkdir $testSubDir
|
||||||
|
cd $testSubDir
|
||||||
|
|
||||||
|
# Adjust srcdir now that we are in a subdirectory. We still want
|
||||||
|
# $srcdir to point to the source directory corresponding to the build
|
||||||
|
# directory that contains $testSubDir.
|
||||||
|
case $srcdir in
|
||||||
|
[\\/$]* | ?:[\\/]* );;
|
||||||
|
*) srcdir=../$srcdir
|
||||||
|
esac
|
||||||
|
|
||||||
|
DOT='@DOT@'
|
||||||
|
top_builddir='../@top_builddir@'
|
||||||
|
VALGRIND='@VALGRIND@'
|
||||||
|
PYTHON='@PYTHON@'
|
||||||
|
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
expected_exitcode=$1
|
||||||
|
shift
|
||||||
|
exitcode=0
|
||||||
|
if test -n "$VALGRIND"; then
|
||||||
|
exec 6>valgrind.err
|
||||||
|
GLIBCPP_FORCE_NEW=1 \
|
||||||
|
../../../libtool --mode=execute \
|
||||||
|
$VALGRIND --tool=memcheck --leak-check=yes --log-fd=6 -q "$@" ||
|
||||||
|
exitcode=$?
|
||||||
|
cat valgrind.err 1>&2
|
||||||
|
test -z "`sed 1q valgrind.err`" || exit 50
|
||||||
|
rm -f valgrind.err
|
||||||
|
else
|
||||||
|
"$@" || exitcode=$?
|
||||||
|
fi
|
||||||
|
test $exitcode = $expected_exitcode || exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
set -x
|
||||||
312
src/graphtest/graph.cc
Normal file
312
src/graphtest/graph.cc
Normal file
|
|
@ -0,0 +1,312 @@
|
||||||
|
// -*- coding: utf-8 -*-
|
||||||
|
// Copyright (C) 2014 Laboratoire de Recherche et Développement 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "graph/graph.hh"
|
||||||
|
|
||||||
|
template <typename SL, typename TL>
|
||||||
|
void
|
||||||
|
dot_state(std::ostream& out, spot::digraph<SL, TL>& g, unsigned n)
|
||||||
|
{
|
||||||
|
out << " [label=\"" << g.state_data(n) << "\"]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TL>
|
||||||
|
void
|
||||||
|
dot_state(std::ostream& out, spot::digraph<void, TL>&, unsigned)
|
||||||
|
{
|
||||||
|
out << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SL, typename TL, typename TR>
|
||||||
|
void
|
||||||
|
dot_trans(std::ostream& out, spot::digraph<SL, TL>&, TR& tr)
|
||||||
|
{
|
||||||
|
out << " [label=\"" << tr.data() << "\"]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename SL, typename TR>
|
||||||
|
void
|
||||||
|
dot_trans(std::ostream& out, spot::digraph<SL, void>&, TR&)
|
||||||
|
{
|
||||||
|
out << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename SL, typename TL>
|
||||||
|
void
|
||||||
|
dot(std::ostream& out, spot::digraph<SL, TL>& g)
|
||||||
|
{
|
||||||
|
out << "digraph {\n";
|
||||||
|
unsigned c = g.nb_states();
|
||||||
|
for (unsigned s = 0; s < c; ++s)
|
||||||
|
{
|
||||||
|
out << ' ' << s;
|
||||||
|
dot_state(out, g, s);
|
||||||
|
for (auto& t: g.out(s))
|
||||||
|
{
|
||||||
|
out << ' ' << s << " -> " << t.dst;
|
||||||
|
dot_trans(out, g, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool g1(const spot::digraph<void, void>& g,
|
||||||
|
unsigned s, int e)
|
||||||
|
{
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s))
|
||||||
|
{
|
||||||
|
(void) t;
|
||||||
|
++f;
|
||||||
|
}
|
||||||
|
return f == e;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f1()
|
||||||
|
{
|
||||||
|
spot::digraph<void, void> g(3);
|
||||||
|
|
||||||
|
auto s1 = g.new_state();
|
||||||
|
auto s2 = g.new_state();
|
||||||
|
auto s3 = g.new_state();
|
||||||
|
g.new_transition(s1, s2);
|
||||||
|
g.new_transition(s1, s3);
|
||||||
|
g.new_transition(s2, s3);
|
||||||
|
g.new_transition(s3, s1);
|
||||||
|
g.new_transition(s3, s2);
|
||||||
|
g.new_transition(s3, s3);
|
||||||
|
|
||||||
|
dot(std::cout, g);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
(void) t;
|
||||||
|
++f;
|
||||||
|
}
|
||||||
|
return f == 2
|
||||||
|
&& g1(g, s3, 3)
|
||||||
|
&& g1(g, s2, 1)
|
||||||
|
&& g1(g, s1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool f2()
|
||||||
|
{
|
||||||
|
spot::digraph<int, void> g(3);
|
||||||
|
|
||||||
|
auto s1 = g.new_state(1);
|
||||||
|
auto s2 = g.new_state(2);
|
||||||
|
auto s3 = g.new_state(3);
|
||||||
|
g.new_transition(s1, s2);
|
||||||
|
g.new_transition(s1, s3);
|
||||||
|
g.new_transition(s2, s3);
|
||||||
|
g.new_transition(s3, s2);
|
||||||
|
|
||||||
|
dot(std::cout, g);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
f += g.state_data(t.dst);
|
||||||
|
}
|
||||||
|
return f == 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f3()
|
||||||
|
{
|
||||||
|
spot::digraph<void, int> g(3);
|
||||||
|
|
||||||
|
auto s1 = g.new_state();
|
||||||
|
auto s2 = g.new_state();
|
||||||
|
auto s3 = g.new_state();
|
||||||
|
g.new_transition(s1, s2, 1);
|
||||||
|
g.new_transition(s1, s3, 2);
|
||||||
|
g.new_transition(s2, s3, 3);
|
||||||
|
g.new_transition(s3, s2, 4);
|
||||||
|
|
||||||
|
dot(std::cout, g);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
f += t.label;
|
||||||
|
}
|
||||||
|
return f == 3 && g.states().size() == 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f4()
|
||||||
|
{
|
||||||
|
spot::digraph<int, int> g(3);
|
||||||
|
|
||||||
|
auto s1 = g.new_state(2);
|
||||||
|
auto s2 = g.new_state(3);
|
||||||
|
auto s3 = g.new_state(4);
|
||||||
|
g.new_transition(s1, s2, 1);
|
||||||
|
g.new_transition(s1, s3, 2);
|
||||||
|
g.new_transition(s2, s3, 3);
|
||||||
|
g.new_transition(s3, s2, 4);
|
||||||
|
|
||||||
|
dot(std::cout, g);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
f += t.label * g.state_data(t.dst);
|
||||||
|
}
|
||||||
|
return f == 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f5()
|
||||||
|
{
|
||||||
|
spot::digraph<void, std::pair<int, float>> g(3);
|
||||||
|
|
||||||
|
auto s1 = g.new_state();
|
||||||
|
auto s2 = g.new_state();
|
||||||
|
auto s3 = g.new_state();
|
||||||
|
g.new_transition(s1, s2, std::make_pair(1, 1.2f));
|
||||||
|
g.new_transition(s1, s3, std::make_pair(2, 1.3f));
|
||||||
|
g.new_transition(s2, s3, std::make_pair(3, 1.4f));
|
||||||
|
g.new_transition(s3, s2, std::make_pair(4, 1.5f));
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
float h = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
f += std::get<0>(t);
|
||||||
|
h += std::get<1>(t);
|
||||||
|
}
|
||||||
|
return f == 3 && (h > 2.49 && h < 2.51);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f6()
|
||||||
|
{
|
||||||
|
spot::digraph<void, std::pair<int, float>> g(3);
|
||||||
|
|
||||||
|
auto s1 = g.new_state();
|
||||||
|
auto s2 = g.new_state();
|
||||||
|
auto s3 = g.new_state();
|
||||||
|
g.new_transition(s1, s2, 1, 1.2f);
|
||||||
|
g.new_transition(s1, s3, 2, 1.3f);
|
||||||
|
g.new_transition(s2, s3, 3, 1.4f);
|
||||||
|
g.new_transition(s3, s2, 4, 1.5f);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
float h = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
f += t.first;
|
||||||
|
h += t.second;
|
||||||
|
}
|
||||||
|
return f == 3 && (h > 2.49 && h < 2.51);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool f7()
|
||||||
|
{
|
||||||
|
spot::digraph<int, int, true> g(3);
|
||||||
|
auto s1 = g.new_state(2);
|
||||||
|
auto s2 = g.new_state(3);
|
||||||
|
auto s3 = g.new_state(4);
|
||||||
|
g.new_transition(s1, {s2, s3}, 1);
|
||||||
|
g.new_transition(s1, {s3}, 2);
|
||||||
|
g.new_transition(s2, {s3}, 3);
|
||||||
|
g.new_transition(s3, {s2}, 4);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
for (auto& tt: t.dst)
|
||||||
|
{
|
||||||
|
f += t.label * g.state_data(tt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f == 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct int_pair
|
||||||
|
{
|
||||||
|
int one;
|
||||||
|
int two;
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, int_pair p)
|
||||||
|
{
|
||||||
|
os << '(' << p.one << ',' << p.two << ')';
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if __GNUC__ <= 4 && __GNUC_MINOR__ <= 6
|
||||||
|
int_pair(int one, int two)
|
||||||
|
: one(one), two(two)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int_pair()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
bool f8()
|
||||||
|
{
|
||||||
|
spot::digraph<int_pair, int_pair> g(3);
|
||||||
|
auto s1 = g.new_state(2, 4);
|
||||||
|
auto s2 = g.new_state(3, 6);
|
||||||
|
auto s3 = g.new_state(4, 8);
|
||||||
|
g.new_transition(s1, s2, 1, 3);
|
||||||
|
g.new_transition(s1, s3, 2, 5);
|
||||||
|
g.new_transition(s2, s3, 3, 7);
|
||||||
|
g.new_transition(s3, s2, 4, 9);
|
||||||
|
|
||||||
|
dot(std::cout, g);
|
||||||
|
|
||||||
|
int f = 0;
|
||||||
|
for (auto& t: g.out(s1))
|
||||||
|
{
|
||||||
|
f += t.one * g.state_data(t.dst).one;
|
||||||
|
f += t.two * g.state_data(t.dst).two;
|
||||||
|
}
|
||||||
|
return f == 69;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
bool a1 = f1();
|
||||||
|
bool a2 = f2();
|
||||||
|
bool a3 = f3();
|
||||||
|
bool a4 = f4();
|
||||||
|
bool a5 = f5();
|
||||||
|
bool a6 = f6();
|
||||||
|
bool a7 = f7();
|
||||||
|
bool a8 = f8();
|
||||||
|
std::cout << a1 << ' '
|
||||||
|
<< a2 << ' '
|
||||||
|
<< a3 << ' '
|
||||||
|
<< a4 << ' '
|
||||||
|
<< a5 << ' '
|
||||||
|
<< a6 << ' '
|
||||||
|
<< a7 << ' '
|
||||||
|
<< a8 << '\n';
|
||||||
|
return !(a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8);
|
||||||
|
}
|
||||||
87
src/graphtest/graph.test
Executable file
87
src/graphtest/graph.test
Executable file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2014 Laboratoire de Recherche et Développement de
|
||||||
|
# l'Epita (LRDE).
|
||||||
|
#
|
||||||
|
# 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# While running some benchmark, Tomáš Babiak found that Spot took too
|
||||||
|
# much time (i.e. >1h) to translate those six formulae. It turns out
|
||||||
|
# that the WDBA minimization was performed after the degeneralization
|
||||||
|
# algorithm, while this is not necessary (WDBA will produce a BA, so
|
||||||
|
# we may as well skip degeneralization). Translating these formulae
|
||||||
|
# in the test-suite ensure that they don't take too much time (the
|
||||||
|
# buildfarm will timeout if it does).
|
||||||
|
|
||||||
|
. ./defs
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
run 0 ../graph > stdout
|
||||||
|
|
||||||
|
cat >expected <<EOF
|
||||||
|
digraph {
|
||||||
|
0
|
||||||
|
0 -> 1
|
||||||
|
0 -> 2
|
||||||
|
1
|
||||||
|
1 -> 2
|
||||||
|
2
|
||||||
|
2 -> 0
|
||||||
|
2 -> 1
|
||||||
|
2 -> 2
|
||||||
|
}
|
||||||
|
digraph {
|
||||||
|
0 [label="1"]
|
||||||
|
0 -> 1
|
||||||
|
0 -> 2
|
||||||
|
1 [label="2"]
|
||||||
|
1 -> 2
|
||||||
|
2 [label="3"]
|
||||||
|
2 -> 1
|
||||||
|
}
|
||||||
|
digraph {
|
||||||
|
0
|
||||||
|
0 -> 1 [label="1"]
|
||||||
|
0 -> 2 [label="2"]
|
||||||
|
1
|
||||||
|
1 -> 2 [label="3"]
|
||||||
|
2
|
||||||
|
2 -> 1 [label="4"]
|
||||||
|
}
|
||||||
|
digraph {
|
||||||
|
0 [label="2"]
|
||||||
|
0 -> 1 [label="1"]
|
||||||
|
0 -> 2 [label="2"]
|
||||||
|
1 [label="3"]
|
||||||
|
1 -> 2 [label="3"]
|
||||||
|
2 [label="4"]
|
||||||
|
2 -> 1 [label="4"]
|
||||||
|
}
|
||||||
|
digraph {
|
||||||
|
0 [label="(2,4)"]
|
||||||
|
0 -> 1 [label="(1,3)"]
|
||||||
|
0 -> 2 [label="(2,5)"]
|
||||||
|
1 [label="(3,6)"]
|
||||||
|
1 -> 2 [label="(3,7)"]
|
||||||
|
2 [label="(4,8)"]
|
||||||
|
2 -> 1 [label="(4,9)"]
|
||||||
|
}
|
||||||
|
1 1 1 1 1 1 1 1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
diff stdout expected
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue