Start the ELTL translation (LACIM).

Merge all eltlast/ files into formula.hh (except automatop.hh).
This commit is contained in:
Damien Lefortier 2008-06-18 15:11:25 +02:00
parent 862302590c
commit 8c0d1003b0
55 changed files with 2000 additions and 422 deletions

View file

@ -1,3 +1,22 @@
2008-06-12 Damien Lefortier <dam@lrde.epita.fr>
Add ELTL visitors in eltlvisit/ and start the ELTL translation (LACIM).
Merge all eltlast/ files into formula.hh (except automatop.hh).
* src/eltlast/allnodes.hh, src/eltlast/atomic_prop.hh,
src/eltlast/binop.hh, src/eltlast/constant.hh, src/eltlast/multop.hh,
src/eltlast/refformula.hh, src/eltlast/unop.hh,
src/eltlast/visitor.hh: Delete and merge all these files into ...
* src/eltlast/formula.hh: ... this one.
* src/eltlvisit/: Add some visitors (clone, destroy, ...).
* src/internal/baseformula.hh, src/internal/baseformula.cc:
Add base_formula, a new base class of internal::formula.
* src/tgba/bdddict.cc src/tgba/bdddict.hh, src/tgba/bddprint.cc,
src/tgba/tgbabddconcretefactory.cc, src/tgba/tgbabddconcretefactory.hh
Replace ltl::formula by internal::base_formula.
* src/tgbatest/eltl2tgba.cc: Beginning of the ELTL translation (LACIM).
* m4/boost.m4: Add AX_BOOST_BASE([MINIMUM-VERSION]).
2008-06-12 Alexandre Duret-Lutz <adl@lrde.epita.fr>
* iface/nips/nipstest/dotty.test,

View file

@ -44,6 +44,7 @@ AC_LANG(C++)
AX_CHECK_BUDDY
AX_CHECK_LBTT
AX_CHECK_GSPNLIB
AX_BOOST_BASE([1.34])
AC_CHECK_FUNCS([srand48 drand48])
@ -88,6 +89,7 @@ AC_CONFIG_FILES([
src/eltlparse/Makefile
src/eltltest/Makefile
src/eltltest/defs
src/eltlvisit/Makefile
src/evtgba/Makefile
src/evtgbaalgos/Makefile
src/evtgbaparse/Makefile

194
m4/boost.m4 Normal file
View file

@ -0,0 +1,194 @@
##### http://autoconf-archive.cryp.to/ax_boost_base.html
#
# SYNOPSIS
#
# AX_BOOST_BASE([MINIMUM-VERSION])
#
# DESCRIPTION
#
# Test for the Boost C++ libraries of a particular version (or newer)
#
# If no path to the installed boost library is given the macro
# searchs under /usr, /usr/local, /opt and /opt/local and evaluates
# the $BOOST_ROOT environment variable. Further documentation is
# available at <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
#
# And sets:
#
# HAVE_BOOST
#
# LAST MODIFICATION
#
# 2007-07-28
#
# COPYLEFT
#
# Copyright (c) 2007 Thomas Porschberg <thomas@randspringer.de>
#
# Copying and distribution of this file, with or without
# modification, are permitted in any medium without royalty provided
# the copyright notice and this notice are preserved.
AC_DEFUN([AX_BOOST_BASE],
[
AC_ARG_WITH([boost],
AS_HELP_STRING([--with-boost@<:@=DIR@:>@], [use boost (default is yes) - it is possible to specify the root directory for boost (optional)]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ac_boost_path=""
else
want_boost="yes"
ac_boost_path="$withval"
fi
],
[want_boost="yes"])
if test "x$want_boost" = "xyes"; then
boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
if test "x$boost_lib_version_req_sub_minor" = "x" ; then
boost_lib_version_req_sub_minor="0"
fi
WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
succeeded=no
dnl first we check the system location for boost libraries
dnl this location ist chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
if test "$ac_boost_path" != ""; then
BOOST_LDFLAGS="-L$ac_boost_path/lib"
BOOST_CPPFLAGS="-I$ac_boost_path/include"
else
for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
BOOST_LDFLAGS="-L$ac_boost_path_tmp/lib"
BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
break;
fi
done
fi
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
AC_LANG_PUSH(C++)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@%:@include <boost/version.hpp>
]], [[
#if BOOST_VERSION >= $WANT_BOOST_VERSION
// Everything is okay
#else
# error Boost version is too old
#endif
]])],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
],[
])
AC_LANG_POP([C++])
dnl if we found no boost with system layout we search for boost libraries
dnl built and installed without the --layout=system option or for a staged(not installed) version
if test "x$succeeded" != "xyes"; then
_version=0
if test "$ac_boost_path" != ""; then
BOOST_LDFLAGS="-L$ac_boost_path/lib"
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
if test "$V_CHECK" = "1" ; then
_version=$_version_tmp
fi
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
done
fi
else
for ac_boost_path in /usr /usr/local /opt /opt/local ; do
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
if test "$V_CHECK" = "1" ; then
_version=$_version_tmp
best_path=$ac_boost_path
fi
done
fi
done
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
BOOST_LDFLAGS="-L$best_path/lib"
if test "x$BOOST_ROOT" != "x"; then
if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/lib" && test -r "$BOOST_ROOT/stage/lib"; then
version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
V_CHECK=`expr $stage_version_shorten \>\= $_version`
if test "$V_CHECK" = "1" ; then
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
BOOST_CPPFLAGS="-I$BOOST_ROOT"
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/lib"
fi
fi
fi
fi
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
AC_LANG_PUSH(C++)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@%:@include <boost/version.hpp>
]], [[
#if BOOST_VERSION >= $WANT_BOOST_VERSION
// Everything is okay
#else
# error Boost version is too old
#endif
]])],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
],[
])
AC_LANG_POP([C++])
fi
if test "$succeeded" != "yes" ; then
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
if test "$_version" = "0" ; then
AC_MSG_ERROR([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
else
AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
fi
else
AC_SUBST(BOOST_CPPFLAGS)
AC_SUBST(BOOST_LDFLAGS)
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
fi
fi
])

View file

@ -24,7 +24,7 @@ AUTOMAKE_OPTIONS = subdir-objects
# List directories in the order they must be built.
# Keep tests at the end.
SUBDIRS = misc ltlenv ltlast ltlvisit ltlparse internal \
eltlenv eltlast eltlparse \
eltlenv eltlast eltlvisit eltlparse \
tgba tgbaalgos tgbaparse \
evtgba evtgbaalgos evtgbaparse . \
ltltest eltltest tgbatest evtgbatest sanity
@ -36,8 +36,10 @@ libspot_la_LIBADD = \
misc/libmisc.la \
ltlparse/libltlparse.la \
ltlvisit/libltlvisit.la \
internal/libinternal.la \
eltlast/libeltlast.la \
eltlparse/libeltlparse.la \
eltlvisit/libeltlvisit.la \
tgba/libtgba.la \
tgbaalgos/libtgbaalgos.la \
tgbaparse/libtgbaparse.la \

View file

@ -25,20 +25,11 @@ AM_CXXFLAGS = $(WARNING_CXXFLAGS)
eltlastdir = $(pkgincludedir)/eltlast
eltlast_HEADERS = \
allnodes.hh \
atomic_prop.hh \
automatop.hh \
binop.hh \
constant.hh \
formula.hh \
multop.hh \
nfa.hh \
refformula.hh \
unop.hh \
visitor.hh
nfa.hh
noinst_LTLIBRARIES = libeltlast.la
libeltlast_la_SOURCES = \
automatop.cc \
nfa.cc
nfa.cc

View file

@ -1,36 +0,0 @@
// 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/allnodes.hh
/// \brief Define all ELTL node types.
///
/// This file is usually needed when \b defining a visitor.
#ifndef SPOT_ELTLAST_ALLNODES_HH
# define SPOT_ELTLAST_ALLNODES_HH
# include "binop.hh"
# include "unop.hh"
# include "multop.hh"
# include "atomic_prop.hh"
# include "constant.hh"
# include "automatop.hh"
#endif // SPOT_ELTLAST_ALLNODES_HH

View file

@ -19,7 +19,6 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "visitor.hh"
#include "automatop.hh"
namespace spot

View file

@ -24,14 +24,16 @@
#ifndef SPOT_ELTLAST_AUTOMATOP_HH
# define SPOT_ELTLAST_AUTOMATOP_HH
# include "multop.hh"
# include "refformula.hh"
# include "formula.hh"
# include "nfa.hh"
namespace spot
{
namespace eltl
{
/// \brief Counted-reference formulae.
/// \ingroup eltl_ast
typedef spot::internal::ref_formula<eltl_t> ref_formula;
/// \brief Automaton operators.
/// \ingroup eltl_ast

View file

@ -25,6 +25,11 @@
# define SPOT_ELTLAST_FORMULA_HH
# include "internal/formula.hh"
# include "internal/atomic_prop.hh"
# include "internal/constant.hh"
# include "internal/unop.hh"
# include "internal/binop.hh"
# include "internal/multop.hh"
namespace spot
{
@ -40,7 +45,21 @@ namespace spot
/// \addtogroup eltl_ast ELTL Abstract Syntax Tree
/// \ingroup eltl
/// \addtogroup eltl_environment ELTL environments
/// \ingroup eltl
/// ELTL environment implementations.
/// \addtogroup eltl_algorithm Algorithms for ELTL formulae
/// \ingroup eltl
/// \addtogroup eltl_io Input/Output of ELTL formulae
/// \ingroup eltl_algorithm
/// \addtogroup eltl_visitor Derivable visitors
/// \ingroup eltl_algorithm
/// Forward declarations
struct eltl_t;
struct visitor;
struct const_visitor;
@ -50,11 +69,33 @@ namespace spot
///
/// The only way you can work with a formula is to
/// build a spot::eltl::visitor or spot::eltl::const_visitor.
typedef spot::internal::formula<eltl_t> formula;
/// Forward declarations
formula* clone(const formula* f);
std::ostream& to_string(const formula* f, std::ostream& os);
void destroy(const formula* f);
struct eltl_t
{
typedef spot::eltl::visitor visitor;
typedef spot::eltl::const_visitor const_visitor;
static formula* clone_(const formula* f)
{
return clone(f);
}
static std::ostream& to_string_(const formula* f, std::ostream& os)
{
return to_string(f, os);
}
static void destroy_(const formula* f)
{
destroy(f);
}
enum binop { Xor, Implies, Equiv };
const char* binop_name(binop op) const
{
@ -86,10 +127,73 @@ namespace spot
}
};
typedef spot::internal::formula<eltl_t> formula;
typedef spot::internal::formula_ptr_less_than formula_ptr_less_than;
typedef spot::internal::formula_ptr_hash formula_ptr_hash;
/// \brief Atomic propositions.
/// \ingroup eltl_ast
typedef spot::internal::atomic_prop<eltl_t> atomic_prop;
/// \brief A constant (True or False)
/// \ingroup eltl_ast
typedef spot::internal::constant<eltl_t> constant;
/// \brief Unary operators.
/// \ingroup eltl_ast
typedef spot::internal::unop<eltl_t> unop;
/// \brief Binary operator.
/// \ingroup eltl_ast
typedef spot::internal::binop<eltl_t> binop;
/// \brief Multi-operand operators.
/// \ingroup eltl_ast
///
/// These operators are considered commutative and associative.
typedef spot::internal::multop<eltl_t> multop;
// Forward declaration.
struct automatop;
/// \brief Formula visitor that can modify the formula.
/// \ingroup eltl_essential
///
/// Writing visitors is the prefered way
/// to traverse a formula, since it doesn't
/// involve any cast.
///
/// If you do not need to modify the visited formula, inherit from
/// spot::eltl:const_visitor instead.
struct visitor
{
virtual ~visitor() {}
virtual void visit(atomic_prop* node) = 0;
virtual void visit(constant* node) = 0;
virtual void visit(binop* node) = 0;
virtual void visit(unop* node) = 0;
virtual void visit(multop* node) = 0;
virtual void visit(automatop* node) = 0;
};
/// \brief Formula visitor that cannot modify the formula.
///
/// Writing visitors is the prefered way
/// to traverse a formula, since it doesn't
/// involve any cast.
///
/// If you want to modify the visited formula, inherit from
/// spot::eltl:visitor instead.
struct const_visitor
{
virtual ~const_visitor() {}
virtual void visit(const atomic_prop* node) = 0;
virtual void visit(const constant* node) = 0;
virtual void visit(const binop* node) = 0;
virtual void visit(const unop* node) = 0;
virtual void visit(const multop* node) = 0;
virtual void visit(const automatop* node) = 0;
};
typedef spot::internal::formula_ptr_less_than<eltl_t> formula_ptr_less_than;
typedef spot::internal::formula_ptr_hash<eltl_t> formula_ptr_hash;
}
}

View file

@ -61,7 +61,7 @@ namespace spot
}
void
nfa::add_transition(const std::string& s, const std::string& d, unsigned c)
nfa::add_transition(const std::string& s, const std::string& d, int c)
{
state* source = add_state(s);
nfa::transition* t = new transition;
@ -90,7 +90,7 @@ namespace spot
return finals_.find(state) != finals_.end();
}
unsigned
int
nfa::arity()
{
return arity_ + 1;

View file

@ -51,7 +51,7 @@ namespace spot
/// Explicit transitions.
struct transition
{
unsigned cost;
int cost;
const state* dest;
};
@ -59,7 +59,7 @@ namespace spot
~nfa();
void
add_transition(const std::string& s, const std::string& d, unsigned c);
add_transition(const std::string& s, const std::string& d, int c);
void
set_init_state(const std::string& state);
@ -72,7 +72,7 @@ namespace spot
is_final(const std::string& state);
/// \brief Get the `arity' i.e. max t.cost, for each transition t.
unsigned
int
arity();
/// \brief Return an iterator on the first succesor (if any) of \a state.
@ -103,7 +103,7 @@ namespace spot
sn_map sn_;
state* init_;
unsigned arity_;
int arity_;
std::set<std::string> finals_;
/// Explicitly disllow use of implicity generated member functions

View file

@ -1,82 +0,0 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/visitor.hh
/// \brief ELTL visitor interface
#ifndef SPOT_ELTLAST_VISITOR_HH
# define SPOT_ELTLAST_VISITOR_HH
# include "binop.hh"
# include "unop.hh"
# include "multop.hh"
# include "atomic_prop.hh"
# include "constant.hh"
namespace spot
{
namespace eltl
{
// Forward declaration.
struct automatop;
/// \brief Formula visitor that can modify the formula.
/// \ingroup eltl_essential
///
/// Writing visitors is the prefered way
/// to traverse a formula, since it doesn't
/// involve any cast.
///
/// If you do not need to modify the visited formula, inherit from
/// spot::eltl:const_visitor instead.
struct visitor
{
virtual ~visitor() {}
virtual void visit(atomic_prop* node) = 0;
virtual void visit(constant* node) = 0;
virtual void visit(binop* node) = 0;
virtual void visit(unop* node) = 0;
virtual void visit(multop* node) = 0;
virtual void visit(automatop* node) = 0;
};
/// \brief Formula visitor that cannot modify the formula.
///
/// Writing visitors is the prefered way
/// to traverse a formula, since it doesn't
/// involve any cast.
///
/// If you want to modify the visited formula, inherit from
/// spot::eltl:visitor instead.
struct const_visitor
{
virtual ~const_visitor() {}
virtual void visit(const atomic_prop* node) = 0;
virtual void visit(const constant* node) = 0;
virtual void visit(const binop* node) = 0;
virtual void visit(const unop* node) = 0;
virtual void visit(const multop* node) = 0;
virtual void visit(const automatop* node) = 0;
};
}
}
#endif // SPOT_ELTLAST_VISITOR_HH

View file

@ -22,10 +22,11 @@
%{
#include <string>
#include <sstream>
#include <limits>
#include <cerrno>
#include <limits.h>
#include "public.hh"
#include "eltlast/allnodes.hh"
#include "eltlast/automatop.hh"
// Implementation detail for error handling.
namespace spot
@ -87,7 +88,8 @@ using namespace spot::eltl;
OP_IMPLIES "implication operator"
OP_EQUIV "equivalent operator"
%token EQ "="
%token ACC "accept"
EQ "="
LPAREN "("
RPAREN ")"
COMMA ","
@ -131,6 +133,7 @@ nfa_list: /* empty. */
nfa: IDENT "=" "(" nfa_def ")"
{
nmap[*$1] = nfa::ptr($4);
delete $1;
}
;
@ -142,7 +145,8 @@ nfa_def: /* empty. */
{
errno = 0;
long i = strtol($4->c_str(), 0, 10);
if (i > INT_MAX || i < INT_MIN || errno == ERANGE)
if (i > std::numeric_limits<long>::max() ||
i < std::numeric_limits<long>::min() || errno == ERANGE)
{
std::string s = "out of range integer `";
s += *$4;
@ -156,7 +160,12 @@ nfa_def: /* empty. */
$1->add_transition(*$2, *$3, i);
$$ = $1;
}
| nfa_def EQ STATE
| nfa_def STATE STATE CONST_TRUE
{
$1->add_transition(*$2, *$3, -1);
$$ = $1;
}
| nfa_def ACC STATE
{
$1->set_final(*$3);
}

View file

@ -59,6 +59,10 @@ eol \n|\r|\n\r|\r\n
/* Rules for the automaton definitions part. */
<INITIAL>"=" return token::EQ;
<IINTIAL>"accept" return token::ACC;
<INITIAL>[tT][rR][uU][eE] {
return token::CONST_TRUE;
}
<INITIAL>"(" return token::LPAREN;
<INITIAL>")" return token::RPAREN;
<INITIAL>"%" BEGIN(formula);

View file

@ -23,7 +23,6 @@
# define SPOT_ELTLPARSE_PUBLIC_HH
# include "eltlast/formula.hh"
# include "eltlast/visitor.hh"
// Unfortunately Bison 2.3 uses the same guards in all parsers :(
# undef BISON_LOCATION_HH
# undef BISON_POSITION_HH

View file

@ -4,9 +4,9 @@
set -e
cat >prelude <<EOF
S=(
X=(
0 1 \$0
= 1
accept 1
)
EOF
@ -15,13 +15,26 @@ include prelude
A=(
0 1 \$2
1 2 \$0
= 0
accept 0
)
%
A(1,a,a|b)&S(1)
A(1,a,a|b)&X(f)
EOF
run 0 ./acc input || exit 1
cat >input <<EOF
X=(
0 1 true
1 2 \$0
accept 2
)
U=(
0 0 \$0
0 1 \$1
accept 1
)
EOF
cat >input <<EOF
A=(
)

42
src/eltlvisit/Makefile.am Normal file
View file

@ -0,0 +1,42 @@
## Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
AM_CPPFLAGS = -I$(srcdir)/.. $(BUDDY_CPPFLAGS)
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
eltlvisitdir = $(pkgincludedir)/eltlvisit
eltlvisit_HEADERS = \
clone.hh \
destroy.hh \
lunabbrev.hh \
nenoform.hh \
postfix.hh \
tostring.hh
noinst_LTLIBRARIES = libeltlvisit.la
libeltlvisit_la_SOURCES = \
clone.cc \
destroy.cc \
lunabbrev.cc \
nenoform.cc \
postfix.cc \
tostring.cc

103
src/eltlvisit/clone.cc Normal file
View file

@ -0,0 +1,103 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "eltlast/automatop.hh"
#include "clone.hh"
#include "destroy.hh"
namespace spot
{
namespace eltl
{
clone_visitor::clone_visitor()
{
}
clone_visitor::~clone_visitor()
{
}
formula*
clone_visitor::result() const
{
return result_;
}
void
clone_visitor::visit(atomic_prop* ap)
{
result_ = ap->ref();
}
void
clone_visitor::visit(constant* c)
{
result_ = c->ref();
}
void
clone_visitor::visit(unop* uo)
{
result_ = unop::instance(uo->op(), recurse(uo->child()));
}
void
clone_visitor::visit(binop* bo)
{
result_ = binop::instance(bo->op(),
recurse(bo->first()), recurse(bo->second()));
}
void
clone_visitor::visit(multop* mo)
{
multop::vec* res = new multop::vec;
unsigned mos = mo->size();
for (unsigned i = 0; i < mos; ++i)
res->push_back(recurse(mo->nth(i)));
result_ = multop::instance(mo->op(), res);
}
formula*
clone_visitor::recurse(formula* f)
{
return clone(f);
}
void
clone_visitor::visit(automatop* ao)
{
automatop::vec* res = new automatop::vec;
for (unsigned i = 0; i < ao->size(); ++i)
res->push_back(recurse(ao->nth(i)));
result_ = automatop::instance(res);
// FIXME: nfa clone !
}
formula*
clone(const formula* f)
{
clone_visitor v;
const_cast<formula*>(f)->accept(v);
return v.result();
}
}
}

64
src/eltlvisit/clone.hh Normal file
View file

@ -0,0 +1,64 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#ifndef SPOT_ELTLVISIT_CLONE_HH
# define SPOT_ELTLVISIT_CLONE_HH
#include "eltlast/formula.hh"
namespace spot
{
namespace eltl
{
/// \brief Clone a formula.
/// \ingroup eltl_visitor
///
/// This visitor is public, because it's convenient to derive from
/// it and override part of its methods. But if you just want the
/// functionality, consider using spot::eltl::clone instead.
class clone_visitor : public visitor
{
public:
clone_visitor();
virtual ~clone_visitor();
formula* result() const;
void visit(atomic_prop* ap);
void visit(unop* uo);
void visit(binop* bo);
void visit(multop* mo);
void visit(constant* c);
void visit(automatop* ao);
virtual formula* recurse(formula* f);
protected:
formula* result_;
};
/// \brief Clone a formula.
/// \ingroup eltl_essential
formula* clone(const formula* f);
}
}
#endif // SPOT_ELTLVISIT_LUNABBREV_HH

View file

@ -19,24 +19,24 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/unop.hh
/// \brief ELTL unary operators
#ifndef SPOT_ELTLAST_UNOP_HH
# define SPOT_ELTLAST_UNOP_HH
# include "formula.hh"
# include "internal/unop.hh"
#include "eltlvisit/destroy.hh"
#include "eltlvisit/clone.hh"
namespace spot
{
namespace eltl
{
void
destroy_visitor::doit_default(formula* c)
{
formula::unref(c);
}
/// \brief Unary operators.
/// \ingroup eltl_ast
typedef spot::internal::unop<eltl_t> unop;
void
destroy(const formula* f)
{
destroy_visitor v;
const_cast<formula*>(f)->accept(v);
}
}
}
#endif // SPOT_ELTLAST_UNOP_HH

View file

@ -1,5 +1,5 @@
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// Copyright (C) 2008 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.
@ -19,24 +19,32 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/constant.hh
/// \brief ELTL constants
#ifndef SPOT_ELTLAST_CONSTANT_HH
# define SPOT_ELTLAST_CONSTANT_HH
#ifndef SPOT_ELTLVISIT_DESTROY_HH
# define SPOT_ELTLVISIT_DESTROY_HH
# include "formula.hh"
# include "internal/constant.hh"
#include "eltlvisit/postfix.hh"
namespace spot
{
namespace eltl
{
/// \ingroup eltl_visitor
///
/// This visitor is public, because it's convenient to write the
/// destroy method of the base_formula class. But if you just
/// want the functionality, consider using spot::eltl::destroy
/// instead.
class destroy_visitor: public postfix_visitor
{
public:
virtual void
doit_default(formula* c);
};
/// \brief A constant (True or False)
/// \ingroup eltl_ast
typedef spot::internal::constant<eltl_t> constant;
/// \brief Destroys a formula
/// \ingroup eltl_essential
void destroy(const formula *f);
}
}
#endif // SPOT_ELTLAST_CONSTANT_HH
#endif // SPOT_ELTLVISIT_DESTROY_HH

View file

@ -0,0 +1,96 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include <cassert>
#include "clone.hh"
#include "destroy.hh"
#include "lunabbrev.hh"
namespace spot
{
namespace eltl
{
unabbreviate_logic_visitor::unabbreviate_logic_visitor()
{
}
unabbreviate_logic_visitor::~unabbreviate_logic_visitor()
{
}
void
unabbreviate_logic_visitor::visit(binop* bo)
{
formula* f1 = recurse(bo->first());
formula* f2 = recurse(bo->second());
switch (bo->op())
{
/* f1 ^ f2 == (f1 & !f2) | (f2 & !f1) */
case binop::Xor:
result_ = multop::instance(multop::Or,
multop::instance(multop::And, clone(f1),
unop::instance(unop::Not,
f2)),
multop::instance(multop::And, clone(f2),
unop::instance(unop::Not,
f1)));
return;
/* f1 => f2 == !f1 | f2 */
case binop::Implies:
result_ = multop::instance(multop::Or,
unop::instance(unop::Not, f1), f2);
return;
/* f1 <=> f2 == (f1 & f2) | (!f1 & !f2) */
case binop::Equiv:
result_ = multop::instance(multop::Or,
multop::instance(multop::And,
clone(f1), clone(f2)),
multop::instance(multop::And,
unop::instance(unop::Not,
f1),
unop::instance(unop::Not,
f2)));
return;
default:
result_ = binop::instance(bo->op(), f1, f2);
return;
}
/* Unreachable code. */
assert(0);
}
formula*
unabbreviate_logic_visitor::recurse(formula* f)
{
return unabbreviate_logic(f);
}
formula*
unabbreviate_logic(const formula* f)
{
unabbreviate_logic_visitor v;
const_cast<formula*>(f)->accept(v);
return v.result();
}
}
}

View file

@ -0,0 +1,68 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#ifndef SPOT_ELTLVISIT_LUNABBREV_HH
# define SPOT_ELTLVISIT_LUNABBREV_HH
#include "clone.hh"
namespace spot
{
namespace eltl
{
/// \brief Clone and rewrite a formula to remove most of the
/// abbreviated logical operators.
/// \ingroup eltl_visitor
///
/// This will rewrite binary operators such as binop::Implies,
/// binop::Equals, and binop::Xor, using only unop::Not,
/// multop::Or, and multop::And.
///
/// This visitor is public, because it's convenient to derive from
/// it and override some of its methods. But if you just want the
/// functionality, consider using spot::ltl::unabbreviate_logic
/// instead.
class unabbreviate_logic_visitor : public clone_visitor
{
typedef clone_visitor super;
public:
unabbreviate_logic_visitor();
virtual ~unabbreviate_logic_visitor();
using super::visit;
void visit(binop* bo);
virtual formula* recurse(formula* f);
};
/// \brief Clone and rewrite a formula to remove most of the
/// abbreviated logical operators.
/// \ingroup eltl_rewriting
///
/// This will rewrite binary operators such as binop::Implies,
/// binop::Equals, and binop::Xor, using only unop::Not,
/// multop::Or, and multop::And.
formula* unabbreviate_logic(const formula* f);
}
}
#endif // SPOT_ELTLVISIT_LUNABBREV_HH

187
src/eltlvisit/nenoform.cc Normal file
View file

@ -0,0 +1,187 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "nenoform.hh"
#include "clone.hh"
#include "destroy.hh"
#include <cassert>
namespace spot
{
namespace eltl
{
namespace
{
class negative_normal_form_visitor: public visitor
{
public:
negative_normal_form_visitor(bool negated)
: negated_(negated)
{
}
virtual
~negative_normal_form_visitor()
{
}
formula* result() const
{
return result_;
}
void
visit(atomic_prop* ap)
{
formula* f = ap->ref();
if (negated_)
result_ = unop::instance(unop::Not, f);
else
result_ = f;
}
void
visit(constant* c)
{
if (!negated_)
{
result_ = c;
return;
}
switch (c->val())
{
case constant::True:
result_ = constant::false_instance();
return;
case constant::False:
result_ = constant::true_instance();
return;
}
/* Unreachable code. */
assert(0);
}
void
visit(unop* uo)
{
formula* f = uo->child();
switch (uo->op())
{
case unop::Not:
result_ = recurse_(f, negated_ ^ true);
return;
}
/* Unreachable code. */
assert(0);
}
void
visit(binop* bo)
{
formula* f1 = bo->first();
formula* f2 = bo->second();
switch (bo->op())
{
case binop::Xor:
/* !(a ^ b) == a <=> b */
result_ = binop::instance(negated_ ? binop::Equiv : binop::Xor,
recurse_(f1, false),
recurse_(f2, false));
return;
case binop::Equiv:
/* !(a <=> b) == a ^ b */
result_ = binop::instance(negated_ ? binop::Xor : binop::Equiv,
recurse_(f1, false),
recurse_(f2, false));
return;
case binop::Implies:
if (negated_)
/* !(a => b) == a & !b */
result_ = multop::instance(multop::And,
recurse_(f1, false),
recurse_(f2, true));
else
result_ = binop::instance(binop::Implies,
recurse(f1), recurse(f2));
return;
}
/* Unreachable code. */
assert(0);
}
void
visit(multop* mo)
{
/* !(a & b & c) == !a | !b | !c */
/* !(a | b | c) == !a & !b & !c */
multop::type op = mo->op();
if (negated_)
switch (op)
{
case multop::And:
op = multop::Or;
break;
case multop::Or:
op = multop::And;
break;
}
multop::vec* res = new multop::vec;
unsigned mos = mo->size();
for (unsigned i = 0; i < mos; ++i)
res->push_back(recurse(mo->nth(i)));
result_ = multop::instance(op, res);
}
void
visit(automatop* ao)
{
(void) ao;
}
formula*
recurse_(formula* f, bool negated)
{
return negative_normal_form(f, negated);
}
formula*
recurse(formula* f)
{
return recurse_(f, negated_);
}
protected:
formula* result_;
bool negated_;
};
}
formula*
negative_normal_form(const formula* f, bool negated)
{
negative_normal_form_visitor v(negated);
const_cast<formula*>(f)->accept(v);
return v.result();
}
}
}

51
src/eltlvisit/nenoform.hh Normal file
View file

@ -0,0 +1,51 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#ifndef SPOT_ELTLVISIT_NENOFORM_HH
# define SPOT_ELTLVISIT_NENOFORM_HH
#include "eltlast/formula.hh"
namespace spot
{
namespace eltl
{
/// \brief Build the negative normal form of \a f.
/// \ingroup eltl_rewriting
///
/// All negations of the formula are pushed in front of the
/// atomic propositions.
///
/// \param f The formula to normalize.
/// \param negated If \c true, return the negative normal form of
/// \c !f
///
/// Note that this will not remove abbreviated operators. If you
/// want to remove abbreviations, call
/// spot::eltl::unabbreviate_logic first. (Calling these
/// functions after spot::eltl::negative_normal_form would likely
/// produce a formula which is not in negative normal form.)
formula* negative_normal_form(const formula* f, bool negated = false);
}
}
#endif // SPOT_ELTLVISIT_NENOFORM_HH

125
src/eltlvisit/postfix.cc Normal file
View file

@ -0,0 +1,125 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "eltlast/automatop.hh"
#include "postfix.hh"
namespace spot
{
namespace eltl
{
postfix_visitor::postfix_visitor()
{
}
postfix_visitor::~postfix_visitor()
{
}
void
postfix_visitor::visit(atomic_prop* ap)
{
doit(ap);
}
void
postfix_visitor::visit(unop* uo)
{
uo->child()->accept(*this);
doit(uo);
}
void
postfix_visitor::visit(binop* bo)
{
bo->first()->accept(*this);
bo->second()->accept(*this);
doit(bo);
}
void
postfix_visitor::visit(multop* mo)
{
unsigned s = mo->size();
for (unsigned i = 0; i < s; ++i)
mo->nth(i)->accept(*this);
doit(mo);
}
void
postfix_visitor::visit(constant* c)
{
doit(c);
}
void
postfix_visitor::visit(automatop* ao)
{
unsigned s = ao->size();
for (unsigned i = 0; i < s; ++i)
ao->nth(i)->accept(*this);
doit(ao);
}
void
postfix_visitor::doit(atomic_prop* ap)
{
doit_default(ap);
}
void
postfix_visitor::doit(unop* uo)
{
doit_default(uo);
}
void
postfix_visitor::doit(binop* bo)
{
doit_default(bo);
}
void
postfix_visitor::doit(multop* mo)
{
doit_default(mo);
}
void
postfix_visitor::doit(constant* c)
{
doit_default(c);
}
void
postfix_visitor::doit(automatop* c)
{
doit_default(c);
}
void
postfix_visitor::doit_default(formula* f)
{
(void)f;
// Dummy implementation that does nothing.
}
}
}

View file

@ -19,24 +19,43 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/refformula.hh
/// \brief Reference-counted ELTL formulae
#ifndef SPOT_ELTLAST_REFFORMULA_HH
# define SPOT_ELTLAST_REFFORMULA_HH
#ifndef SPOT_ELTLVISIT_POSTFIX_HH
# define SPOT_ELTLVISIT_POSTFIX_HH
# include "formula.hh"
# include "internal/refformula.hh"
#include "eltlast/formula.hh"
namespace spot
{
namespace eltl
{
/// \brief Apply an algorithm on each node of an AST,
/// during a postfix traversal.
/// \ingroup eltl_visitor
///
/// Override one or more of the postifix_visitor::doit methods
/// with the algorithm to apply.
class postfix_visitor : public visitor
{
public:
postfix_visitor();
virtual ~postfix_visitor();
/// \brief A reference-counted ELTL formula.
/// \ingroup eltl_ast
typedef spot::internal::ref_formula<eltl_t> ref_formula;
void visit(atomic_prop* ap);
void visit(unop* uo);
void visit(binop* bo);
void visit(multop* mo);
void visit(constant* c);
void visit(automatop* ao);
virtual void doit(atomic_prop* ap);
virtual void doit(unop* uo);
virtual void doit(binop* bo);
virtual void doit(multop* mo);
virtual void doit(constant* c);
virtual void doit(automatop* ao);
virtual void doit_default(formula* f);
};
}
}
#endif // SPOT_ELTLAST_REFFORMULA_HH
#endif // SPOT_ELTLVISIT_POSTFIX_HH

198
src/eltlvisit/tostring.cc Normal file
View file

@ -0,0 +1,198 @@
// Copyright (C) 2003, 2004, 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include <cassert>
#include <sstream>
#include <ctype.h>
#include <ostream>
#include <cstring>
#include "tostring.hh"
namespace spot
{
namespace eltl
{
namespace
{
static bool
is_bare_word(const char* str)
{
// Bare words cannot be empty, start with the letter of a unary
// operator, or be the name of an existing constant. Also they
// should start with an letter.
if (!*str
|| *str == 'F'
|| *str == 'G'
|| *str == 'X'
|| !(isalpha(*str) || *str == '_')
|| !strcasecmp(str, "true")
|| !strcasecmp(str, "false"))
return false;
// The remaining of the word must be alphanumeric.
while (*++str)
if (!(isalnum(*str) || *str == '_'))
return false;
return true;
}
class to_string_visitor: public const_visitor
{
public:
to_string_visitor(std::ostream& os)
: os_(os), top_level_(true)
{
}
virtual
~to_string_visitor()
{
}
void
visit(const atomic_prop* ap)
{
std::string str = ap->name();
if (!is_bare_word(str.c_str()))
{
os_ << '"' << str << '"';
}
else
{
os_ << str;
}
}
void
visit(const constant* c)
{
os_ << c->val_name();
}
void
visit(const binop* bo)
{
bool top_level = top_level_;
top_level_ = false;
if (!top_level)
os_ << "(";
bo->first()->accept(*this);
switch (bo->op())
{
case binop::Xor:
os_ << " ^ ";
break;
case binop::Implies:
os_ << " => ";
break;
case binop::Equiv:
os_ << " <=> ";
break;
}
bo->second()->accept(*this);
if (!top_level)
os_ << ")";
}
void
visit(const unop* uo)
{
// The parser treats F0, F1, G0, G1, X0, and X1 as atomic
// propositions. So make sure we output F(0), G(1), etc.
bool need_parent = !!dynamic_cast<const constant*>(uo->child());
switch (uo->op())
{
case unop::Not:
os_ << "!";
need_parent = false;
break;
}
top_level_ = false;
if (need_parent)
os_ << "(";
uo->child()->accept(*this);
if (need_parent)
os_ << ")";
}
void
visit(const multop* mo)
{
bool top_level = top_level_;
top_level_ = false;
if (!top_level)
os_ << "(";
unsigned max = mo->size();
mo->nth(0)->accept(*this);
const char* ch = " ";
switch (mo->op())
{
case multop::Or:
ch = " | ";
break;
case multop::And:
ch = " & ";
break;
}
for (unsigned n = 1; n < max; ++n)
{
os_ << ch;
mo->nth(n)->accept(*this);
}
if (!top_level)
os_ << ")";
}
void
visit(const automatop*)
{
// FIXME !
os_ << "AP";
}
protected:
std::ostream& os_;
bool top_level_;
};
} // anonymous
std::ostream&
to_string(const formula* f, std::ostream& os)
{
to_string_visitor v(os);
f->accept(v);
return os;
}
std::string
to_string(const formula* f)
{
std::ostringstream os;
to_string(f, os);
return os.str();
}
}
}

View file

@ -1,4 +1,4 @@
// Copyright (C) 2008 Laboratoire d'Informatique de Paris 6 (LIP6),
// Copyright (C) 2003, 2004, 2008 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
//
@ -19,27 +19,30 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/binop.hh
/// \brief ELTL binary operators
///
/// This does not include \c AND and \c OR operators. These are
/// considered to be multi-operand operators (see spot::eltl::multop).
#ifndef SPOT_ELTLAST_BINOP_HH
# define SPOT_ELTLAST_BINOP_HH
#ifndef SPOT_ELTLVISIT_TOSTRING_HH
# define SPOT_ELTLVISIT_TOSTRING_HH
# include "formula.hh"
# include "internal/binop.hh"
#include <iosfwd>
#include "eltlast/formula.hh"
namespace spot
{
namespace eltl
{
/// \addtogroup eltl_io
/// @{
/// \brief Binary operator.
/// \ingroup eltl_ast
typedef spot::internal::binop<eltl_t> binop;
/// \brief Output a formula as a (parsable) string.
/// \param f The formula to translate.
/// \param os The stream where it should be output.
std::ostream& to_string(const formula* f, std::ostream& os);
/// \brief Convert a formula into a (parsable) string.
/// \param f The formula to translate.
std::string to_string(const formula* f);
/// @}
}
}
#endif // SPOT_ELTLAST_BINOP_HH
#endif // SPOT_ELTLVISIT_TOSTRING_HH

View file

@ -86,10 +86,10 @@ namespace spot
bdd low = bdd_low(one);
if (low == bddfalse)
{
const ltl::formula* v =
const internal::base_formula* v =
automata_->get_dict()->var_formula_map[bdd_var(one)];
res->add_transition(name_[in],
to_string(v),
v->to_string(),
ss,
name_[out]);
break;
@ -121,8 +121,8 @@ namespace spot
bdd low = bdd_low(one);
if (low == bddfalse)
{
const ltl::formula* v =
automata_->get_dict()->acc_formula_map[bdd_var(one)];
const ltl::formula* v = dynamic_cast<const ltl::formula*>(
automata_->get_dict()->acc_formula_map[bdd_var(one)]);
ss.insert(rsymbol(to_string(v)));
break;
}

View file

@ -24,7 +24,6 @@
#include <cstdlib>
#include <cstring>
#include "ltlvisit/destroy.hh"
#include "ltlast/allnodes.hh"
#include "ltlparse/public.hh"
#include "evtgbaparse/public.hh"
#include "evtgbaalgos/save.hh"

View file

@ -19,9 +19,13 @@
## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
## 02111-1307, USA.
internaldir = $(pkgincludedir)/libinternal
AM_CPPFLAGS = -I$(srcdir)/..
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
internaldir = $(pkgincludedir)/internal
internal_HEADERS = \
baseformula.hh \
refformula.hh \
refformula.hxx \
formula.hh \
@ -42,3 +46,7 @@ internal_HEADERS = \
declenv.hh \
declenv.hxx \
environment.hh
noinst_LTLIBRARIES = libinternal.la
libinternal_la_SOURCES = \
baseformula.cc

View file

@ -1,5 +1,5 @@
// Copyright (C) 2008 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// Copyright (C) 2008 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.
@ -19,26 +19,38 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/multop.hh
/// \brief ELTL multi-operand operators
#ifndef SPOT_ELTLAST_MULTOP_HH
# define SPOT_ELTLAST_MULTOP_HH
# include "formula.hh"
# include "internal/multop.hh"
#include <sstream>
#include "baseformula.hh"
namespace spot
{
namespace eltl
namespace internal
{
std::string
base_formula::to_string() const
{
std::ostringstream os;
to_string(os);
return os.str();
}
/// \brief Multi-operand operators.
/// \ingroup eltl_ast
///
/// These operators are considered commutative and associative.
typedef spot::internal::multop<eltl_t> multop;
const std::string&
base_formula::dump() const
{
return dump_;
}
size_t
base_formula::hash() const
{
return hash_key_;
}
void
base_formula::set_key_()
{
string_hash sh;
hash_key_ = sh(dump_);
}
}
}
#endif // SPOT_ELTLAST_MULTOP_HH

119
src/internal/baseformula.hh Normal file
View file

@ -0,0 +1,119 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#ifndef SPOT_INTERNAL_BASEFORMULA_HH
# define SPOT_INTERNAL_BASEFORMULA_HH
# include <cassert>
# include "misc/hash.hh"
namespace spot
{
namespace internal
{
class base_formula
{
public:
/// \brief Output a formula as a (parsable) string.
std::string to_string() const;
/// Some visitors virtual versions (LTL | ELTL).
virtual base_formula* clone() const = 0;
virtual std::ostream& to_string(std::ostream& os) const = 0;
virtual void destroy() const = 0;
/// Return a canonic representation of the formula
const std::string& dump() const;
/// Return a hash_key for the formula.
size_t hash() const;
protected:
virtual ~base_formula() {};
/// \brief Compute key_ from dump_.
///
/// Should be called once in each object, after dump_ has been set.
void set_key_();
/// The canonic representation of the formula
std::string dump_;
/// \brief The hash key of this formula.
///
/// Initialized by set_key_().
size_t hash_key_;
};
/// \brief Strict Weak Ordering for <code>const base_formula*</code>.
/// \ingroup generic_essentials
///
/// This is meant to be used as a comparison functor for STL
/// \c map whose key are of type <code>const base_formula*</code>.
///
/// For instance here is how one could declare
/// a map of \c const::base_formula*.
/// \code
/// // Remember how many times each formula has been seen.
/// std::map<const spot::internal::base_formula*, int,
/// spot::internal::formula_ptr_less_than> seen;
/// \endcode
struct formula_ptr_less_than:
public std::binary_function<const base_formula*,
const base_formula*, bool>
{
bool
operator()(const base_formula* left, const base_formula* right) const
{
assert(left);
assert(right);
size_t l = left->hash();
size_t r = right->hash();
if (1 != r)
return l < r;
return left->dump() < right->dump();
}
};
/// \brief Hash Function for <code>const formula*</code>.
/// \ingroup generic_essentials
/// \ingroup hash_funcs
///
/// This is meant to be used as a hash functor for Sgi's
/// \c hash_map whose key are of type <code>const base_formula*</code>.
///
/// For instance here is how one could declare
/// a map of \c const::base_formula*.
/// \code
/// // Remember how many times each formula has been seen.
/// Sgi::hash_map<const spot::internal::base_formula*, int,
/// const spot::internal::formula_ptr_hash> seen;
/// \endcode
struct formula_ptr_hash:
public std::unary_function<const base_formula*, size_t>
{
size_t
operator()(const base_formula* that) const
{
assert(that);
return that->hash();
}
};
}
}
#endif // SPOT_INTERNAL_BASEFORMULA_HH

View file

@ -1,6 +1,6 @@
// Copyright (C) 2003, 2004, 2005, 2008 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
// Copyright (C) 2003, 2004, 2005, 2008 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.
//
@ -24,10 +24,8 @@
#ifndef SPOT_INTERNAL_FORMULA_HH
# define SPOT_INTERNAL_FORMULA_HH
# include <string>
# include <cassert>
# include "predecl.hh"
# include "misc/hash.hh"
# include "baseformula.hh"
namespace spot
{
@ -40,12 +38,16 @@ namespace spot
/// The only way you can work with a formula is to
/// build a T::visitor or T::const_visitor.
template<typename T>
class formula : public T
class formula : public T, public base_formula
{
public:
typedef typename T::visitor visitor;
typedef typename T::const_visitor const_visitor;
virtual base_formula* clone() const;
virtual std::ostream& to_string(std::ostream& os) const;
virtual void destroy() const;
/// Entry point for T::visitor instances.
virtual void accept(visitor& v) = 0;
/// Entry point for T::const_visitor instances.
@ -65,16 +67,6 @@ namespace spot
/// this method directly as it doesn't touch the children. If you
/// want to release a whole formula, use a destroy() visitor instead.
static void unref(formula<T>* f);
/// Return a canonic representation of the formula
const std::string& dump() const;
/// Return a hash_key for the formula.
size_t
hash() const
{
return hash_key_;
}
protected:
virtual ~formula();
@ -83,77 +75,7 @@ namespace spot
/// \brief decrement reference counter if any, return true when
/// the instance must be deleted (usually when the counter hits 0).
virtual bool unref_();
/// \brief Compute key_ from dump_.
///
/// Should be called once in each object, after dump_ has been set.
void set_key_();
/// The canonic representation of the formula
std::string dump_;
/// \brief The hash key of this formula.
///
/// Initialized by set_key_().
size_t hash_key_;
};
/// \brief Strict Weak Ordering for <code>const formula*</code>.
/// \ingroup generic_essentials
///
/// This is meant to be used as a comparison functor for
/// STL \c map whose key are of type <code>const formula<T>*</code>.
///
/// For instance here is how one could declare
/// a map of \c const::formula*.
/// \code
/// // Remember how many times each formula has been seen.
/// template<typename T>
/// std::map<const spot::internal::formula<T>*, int,
/// spot::internal::formula_ptr_less_than<T> > seen;
/// \endcode
template<typename T>
struct formula_ptr_less_than:
public std::binary_function<const formula<T>*, const formula<T>*, bool>
{
bool
operator()(const formula<T>* left, const formula<T>* right) const
{
assert(left);
assert(right);
size_t l = left->hash();
size_t r = right->hash();
if (1 != r)
return l < r;
return left->dump() < right->dump();
}
};
/// \brief Hash Function for <code>const formula*</code>.
/// \ingroup generic_essentials
/// \ingroup hash_funcs
///
/// This is meant to be used as a hash functor for
/// Sgi's \c hash_map whose key are of type <code>const formula*</code>.
///
/// For instance here is how one could declare
/// a map of \c const::formula*.
/// \code
/// // Remember how many times each formula has been seen.
/// template<typename T>
/// Sgi::hash_map<const spot::internal::formula<T>*, int,
/// const spot::internal::formula_ptr_hash<T> > seen;
/// \endcode
template<typename T>
struct formula_ptr_hash:
public std::unary_function<const formula<T>*, size_t>
{
size_t
operator()(const formula<T>* that) const
{
assert(that);
return that->hash();
}
};
}
}

View file

@ -67,18 +67,24 @@ namespace spot
}
template<typename T>
const std::string&
formula<T>::dump() const
base_formula*
formula<T>::clone() const
{
return dump_;
return T::clone_(this);
}
template<typename T>
std::ostream&
formula<T>::to_string(std::ostream& os) const
{
return T::to_string_(this, os);
}
template<typename T>
void
formula<T>::set_key_()
formula<T>::destroy() const
{
string_hash sh;
hash_key_ = sh(dump_);
T::destroy_(this);
}
}
}

View file

@ -150,7 +150,7 @@ namespace spot
v->insert(v->end(), inlined.begin(), inlined.end());
}
std::sort(v->begin(), v->end(), formula_ptr_less_than<T>());
std::sort(v->begin(), v->end(), formula_ptr_less_than());
// Remove duplicates. We can't use std::unique(), because we
// must destroy() any formula we drop.

View file

@ -64,14 +64,43 @@ namespace spot
/// \addtogroup ltl_misc Miscellaneous algorithms for LTL formulae
/// \ingroup ltl_algorithm
struct ltl_t;
struct visitor;
struct const_visitor;
/// \brief An LTL formula.
/// \ingroup ltl_essential
/// \ingroup ltl_ast
///
/// The only way you can work with a formula is to
/// build a spot::ltl::visitor or spot::ltl::const_visitor.
typedef spot::internal::formula<ltl_t> formula;
/// Forward declarations
formula* clone(const formula* f);
std::ostream& to_string(const formula* f, std::ostream& os);
void destroy(const formula* f);
struct ltl_t
{
typedef spot::ltl::visitor visitor;
typedef spot::ltl::const_visitor const_visitor;
static formula* clone_(const formula* f)
{
return clone(f);
}
static std::ostream& to_string_(const formula* f, std::ostream& os)
{
return to_string(f, os);
}
static void destroy_(const formula* f)
{
destroy(f);
}
enum binop { Xor, Implies, Equiv, U, R };
const char* binop_name(binop op) const
{
@ -113,18 +142,8 @@ namespace spot
}
};
/// \brief An LTL formula.
/// \ingroup ltl_essential
/// \ingroup ltl_ast
///
/// The only way you can work with a formula is to
/// build a spot::ltl::visitor or spot::ltl::const_visitor.
typedef spot::internal::formula<ltl_t> formula;
typedef spot::internal::formula_ptr_less_than<ltl_t> formula_ptr_less_than;
typedef spot::internal::formula_ptr_hash<ltl_t> formula_ptr_hash;
typedef spot::internal::formula_ptr_less_than formula_ptr_less_than;
typedef spot::internal::formula_ptr_hash formula_ptr_hash;
/// \brief Atomic propositions.
/// \ingroup ltl_ast

View file

@ -25,17 +25,10 @@ namespace spot
{
namespace ltl
{
namespace
void
destroy_visitor::doit_default(formula* c)
{
class destroy_visitor: public postfix_visitor
{
public:
virtual void
doit_default(formula* c)
{
formula::unref(c);
}
};
formula::unref(c);
}
void

View file

@ -28,6 +28,19 @@ namespace spot
{
namespace ltl
{
/// \ingroup ltl_visitor
///
/// This visitor is public, because it's convenient to write the
/// destroy method of the base_formula class. But if you just
/// want the functionality, consider using spot::ltl::destroy
/// instead.
class destroy_visitor: public postfix_visitor
{
public:
virtual void
doit_default(formula* c);
};
/// \brief Destroys a formula
/// \ingroup ltl_essential
void destroy(const formula *f);

View file

@ -25,7 +25,6 @@
#include <ltlvisit/clone.hh>
#include <ltlvisit/destroy.hh>
#include <ltlvisit/tostring.hh>
#include <ltlvisit/tostring.hh>
#include <ltlenv/defaultenv.hh>
#include "bdddict.hh"
@ -47,7 +46,8 @@ namespace spot
}
int
bdd_dict::register_proposition(const ltl::formula* f, const void* for_me)
bdd_dict::register_proposition(const internal::base_formula* f,
const void* for_me)
{
int num;
// Do not build a variable that already exists.
@ -58,7 +58,7 @@ namespace spot
}
else
{
f = clone(f);
f = f->clone();
num = allocate_variables(1);
var_map[f] = num;
var_formula_map[num] = f;
@ -82,7 +82,8 @@ namespace spot
}
int
bdd_dict::register_state(const ltl::formula* f, const void* for_me)
bdd_dict::register_state(const internal::base_formula* f,
const void* for_me)
{
int num;
// Do not build a state that already exists.
@ -93,7 +94,7 @@ namespace spot
}
else
{
f = ltl::clone(f);
f = f->clone();
num = allocate_variables(2);
now_map[f] = num;
now_formula_map[num] = f;
@ -107,8 +108,8 @@ namespace spot
}
int
bdd_dict::register_acceptance_variable(const ltl::formula* f,
const void* for_me)
bdd_dict::register_acceptance_variable(const internal::base_formula* f,
const void* for_me)
{
int num;
// Do not build an acceptance variable that already exists.
@ -119,7 +120,7 @@ namespace spot
}
else
{
f = clone(f);
f = f->clone();
num = allocate_variables(1);
acc_map[f] = num;
acc_formula_map[num] = f;
@ -150,13 +151,14 @@ namespace spot
assert(i != acc_formula_map.end());
std::ostringstream s;
// FIXME: We could be smarter and reuse unused "$n" numbers.
s << ltl::to_string(i->second) << "$"
s << i->second->to_string()
<< "$"
<< ++clone_counts[var];
ltl::formula* f =
internal::base_formula* f =
ltl::atomic_prop::instance(s.str(),
ltl::default_environment::instance());
int res = register_acceptance_variable(f, for_me);
ltl::destroy(f);
f->destroy();
return res;
}
@ -233,7 +235,7 @@ namespace spot
// Let's free it. First, we need to find
// if this is a Now, a Var, or an Acc variable.
int n = 1;
const ltl::formula* f = 0;
const internal::base_formula* f = 0;
vf_map::iterator vi = var_formula_map.find(var);
if (vi != var_formula_map.end())
{
@ -278,7 +280,7 @@ namespace spot
// formula itself.
release_variables(var, n);
if (f)
ltl::destroy(f);
f->destroy();
var_refs.erase(cur);
}
@ -297,7 +299,8 @@ namespace spot
}
bool
bdd_dict::is_registered_proposition(const ltl::formula* f, const void* by_me)
bdd_dict::is_registered_proposition(const internal::base_formula* f,
const void* by_me)
{
fv_map::iterator fi = var_map.find(f);
if (fi == var_map.end())
@ -307,7 +310,8 @@ namespace spot
}
bool
bdd_dict::is_registered_state(const ltl::formula* f, const void* by_me)
bdd_dict::is_registered_state(const internal::base_formula* f,
const void* by_me)
{
fv_map::iterator fi = now_map.find(f);
if (fi == now_map.end())
@ -317,7 +321,7 @@ namespace spot
}
bool
bdd_dict::is_registered_acceptance_variable(const ltl::formula* f,
bdd_dict::is_registered_acceptance_variable(const internal::base_formula* f,
const void* by_me)
{
fv_map::iterator fi = acc_map.find(f);
@ -336,23 +340,23 @@ namespace spot
{
os << " " << fi->second << " (x"
<< var_refs.find(fi->second)->second.size() << "): ";
to_string(fi->first, os) << std::endl;
fi->first->to_string(os) << std::endl;
}
os << "States:" << std::endl;
for (fi = now_map.begin(); fi != now_map.end(); ++fi)
{
int refs = var_refs.find(fi->second)->second.size();
os << " " << fi->second << " (x" << refs << "): Now[";
to_string(fi->first, os) << "]" << std::endl;
fi->first->to_string(os) << "]" << std::endl;
os << " " << fi->second + 1 << " (x" << refs << "): Next[";
to_string(fi->first, os) << "]" << std::endl;
fi->first->to_string(os) << "]" << std::endl;
}
os << "Acceptance Conditions:" << std::endl;
for (fi = acc_map.begin(); fi != acc_map.end(); ++fi)
{
os << " " << fi->second << " (x"
<< var_refs.find(fi->second)->second.size() << "): Acc[";
to_string(fi->first, os) << "]" << std::endl;
fi->first->to_string(os) << "]" << std::endl;
}
os << "Ref counts:" << std::endl;
vr_map::const_iterator ri;

View file

@ -1,6 +1,6 @@
// 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.
// 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.
//
@ -27,7 +27,7 @@
#include <map>
#include <iosfwd>
#include <bdd.h>
#include "ltlast/formula.hh"
#include "internal/baseformula.hh"
#include "misc/bddalloc.hh"
namespace spot
@ -43,9 +43,9 @@ namespace spot
~bdd_dict();
/// Formula-to-BDD-variable maps.
typedef std::map<const ltl::formula*, int> fv_map;
typedef std::map<const internal::base_formula*, int> fv_map;
/// BDD-variable-to-formula maps.
typedef std::map<int, const ltl::formula*> vf_map;
typedef std::map<int, const internal::base_formula*> vf_map;
fv_map now_map; ///< Maps formulae to "Now" BDD variables
vf_map now_formula_map; ///< Maps "Now" BDD variables to formulae
@ -77,7 +77,8 @@ namespace spot
///
/// \return The variable number. Use bdd_ithvar() or bdd_nithvar()
/// to convert this to a BDD.
int register_proposition(const ltl::formula* f, const void* for_me);
int
register_proposition(const internal::base_formula* f, const void* for_me);
/// \brief Register BDD variables as atomic propositions.
///
@ -99,7 +100,7 @@ namespace spot
/// \return The first variable number. Add one to get the second
/// variable. Use bdd_ithvar() or bdd_nithvar() to convert this
/// to a BDD.
int register_state(const ltl::formula* f, const void* for_me);
int register_state(const internal::base_formula* f, const void* for_me);
/// \brief Register an atomic proposition.
///
@ -111,7 +112,8 @@ namespace spot
///
/// \return The variable number. Use bdd_ithvar() or bdd_nithvar()
/// to convert this to a BDD.
int register_acceptance_variable(const ltl::formula* f, const void* for_me);
int register_acceptance_variable(const internal::base_formula* f,
const void* for_me);
/// \brief Clone an acceptance variable VAR for FOR_ME.
///
@ -156,9 +158,12 @@ namespace spot
/// @{
/// Check whether formula \a f has already been registered by \a by_me.
bool is_registered_proposition(const ltl::formula* f, const void* by_me);
bool is_registered_state(const ltl::formula* f, const void* by_me);
bool is_registered_acceptance_variable(const ltl::formula* f,
bool is_registered_proposition(const internal::base_formula* f,
const void* by_me);
bool is_registered_state(const internal::base_formula* f,
const void* by_me);
bool is_registered_acceptance_variable(const internal::base_formula* f,
const void* by_me);
/// @}

View file

@ -23,9 +23,7 @@
#include <cassert>
#include <ostream>
#include "bddprint.hh"
#include "ltlvisit/tostring.hh"
#include "formula2bdd.hh"
#include "ltlvisit/destroy.hh"
namespace spot
{
@ -42,7 +40,7 @@ namespace spot
bdd_dict::vf_map::const_iterator isi =
dict->var_formula_map.find(var);
if (isi != dict->var_formula_map.end())
to_string(isi->second, o);
isi->second->to_string(o);
else
{
isi = dict->acc_formula_map.find(var);
@ -51,12 +49,12 @@ namespace spot
if (want_acc)
{
o << "Acc[";
to_string(isi->second, o) << "]";
isi->second->to_string(o) << "]";
}
else
{
o << "\"";
to_string(isi->second, o) << "\"";
isi->second->to_string(o) << "\"";
}
}
else
@ -64,14 +62,14 @@ namespace spot
isi = dict->now_formula_map.find(var);
if (isi != dict->now_formula_map.end())
{
o << "Now["; to_string(isi->second, o) << "]";
o << "Now["; isi->second->to_string(o) << "]";
}
else
{
isi = dict->now_formula_map.find(var - 1);
if (isi != dict->now_formula_map.end())
{
o << "Next["; to_string(isi->second, o) << "]";
o << "Next["; isi->second->to_string(o) << "]";
}
else
{

View file

@ -162,7 +162,7 @@ namespace spot
int var = bdd_var(b);
bdd_dict::vf_map::const_iterator isi = d->var_formula_map.find(var);
assert(isi != d->var_formula_map.end());
formula* res = clone(isi->second);
formula* res = clone(dynamic_cast<const ltl::formula*>(isi->second));
bdd high = bdd_high(b);
if (high == bddfalse)

View file

@ -19,9 +19,8 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "ltlvisit/clone.hh"
#include "ltlvisit/destroy.hh"
#include "tgbabddconcretefactory.hh"
namespace spot
{
tgba_bdd_concrete_factory::tgba_bdd_concrete_factory(bdd_dict* dict)
@ -33,12 +32,12 @@ namespace spot
{
acc_map_::iterator ai;
for (ai = acc_.begin(); ai != acc_.end(); ++ai)
destroy(ai->first);
ai->first->destroy();
get_dict()->unregister_all_my_variables(this);
}
int
tgba_bdd_concrete_factory::create_state(const ltl::formula* f)
tgba_bdd_concrete_factory::create_state(const internal::base_formula* f)
{
int num = get_dict()->register_state(f, this);
// Keep track of all "Now" variables for easy
@ -48,7 +47,7 @@ namespace spot
}
int
tgba_bdd_concrete_factory::create_atomic_prop(const ltl::formula* f)
tgba_bdd_concrete_factory::create_atomic_prop(const internal::base_formula* f)
{
int num = get_dict()->register_proposition(f, this);
// Keep track of all atomic proposition for easy
@ -58,8 +57,9 @@ namespace spot
}
void
tgba_bdd_concrete_factory::declare_acceptance_condition(bdd b,
const ltl::formula* a)
tgba_bdd_concrete_factory::declare_acceptance_condition(
bdd b,
const internal::base_formula* a)
{
// Maintain a conjunction of BDDs associated to A. We will latter
// (in tgba_bdd_concrete_factory::finish()) associate this
@ -67,7 +67,7 @@ namespace spot
acc_map_::iterator ai = acc_.find(a);
if (ai == acc_.end())
{
a = clone(a);
a = a->clone();
acc_[a] = b;
}
else

View file

@ -23,7 +23,7 @@
# define SPOT_TGBA_TGBABDDCONCRETEFACTORY_HH
#include "misc/hash.hh"
#include "ltlast/formula.hh"
#include "internal/baseformula.hh"
#include "tgbabddfactory.hh"
namespace spot
@ -45,7 +45,7 @@ namespace spot
/// The state variables are not created if they already exist.
/// Instead their existing variable numbers are returned.
/// Variable numbers can be turned into BDD using ithvar().
int create_state(const ltl::formula* f);
int create_state(const internal::base_formula* f);
/// Create an atomic proposition variable for formula \a f.
///
@ -55,7 +55,7 @@ namespace spot
/// The atomic proposition is not created if it already exists.
/// Instead its existing variable number is returned. Variable numbers
/// can be turned into BDD using ithvar().
int create_atomic_prop(const ltl::formula* f);
int create_atomic_prop(const internal::base_formula* f);
/// Declare an acceptance condition.
///
@ -68,7 +68,7 @@ namespace spot
/// \param b a BDD indicating which variables are in the
/// acceptance set
/// \param a the formula associated
void declare_acceptance_condition(bdd b, const ltl::formula* a);
void declare_acceptance_condition(bdd b, const internal::base_formula* a);
const tgba_bdd_core_data& get_core_data() const;
bdd_dict* get_dict() const;
@ -86,8 +86,8 @@ namespace spot
private:
tgba_bdd_core_data data_; ///< Core data for the new automata.
typedef Sgi::hash_map<const ltl::formula*, bdd,
ltl::formula_ptr_hash> acc_map_;
typedef Sgi::hash_map<const internal::base_formula*, bdd,
internal::formula_ptr_hash> acc_map_;
acc_map_ acc_; ///< BDD associated to each acceptance condition
};

View file

@ -1,6 +1,6 @@
// Copyright (C) 2003, 2004, 2005, 2008 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
// Copyright (C) 2003, 2004, 2005, 2008 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.
//
@ -23,6 +23,7 @@
#include "tgbatba.hh"
#include "bddprint.hh"
#include "misc/hashfunc.hh"
#include "ltlast/formula.hh"
namespace spot
{

View file

@ -31,6 +31,7 @@ tgbaalgos_HEADERS = \
dotty.hh \
dottydec.hh \
dupexp.hh \
eltl2tgba_lacim.hh \
emptiness.hh \
emptiness_stats.hh \
gv04.hh \
@ -60,6 +61,7 @@ libtgbaalgos_la_SOURCES = \
dotty.cc \
dottydec.cc \
dupexp.cc \
eltl2tgba_lacim.cc \
emptiness.cc \
gv04.cc \
lbtt.cc \

View file

@ -0,0 +1,188 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#include "eltlast/formula.hh"
#include "eltlvisit/lunabbrev.hh"
#include "eltlvisit/nenoform.hh"
#include "eltlvisit/destroy.hh"
#include "tgba/tgbabddconcretefactory.hh"
#include <cassert>
#include "eltl2tgba_lacim.hh"
namespace spot
{
namespace
{
using namespace eltl;
/// \brief Recursively translate a formula into a BDD.
class eltl_trad_visitor: public const_visitor
{
public:
eltl_trad_visitor(tgba_bdd_concrete_factory& fact, bool root = false)
: fact_(fact), root_(root)
{
}
virtual
~eltl_trad_visitor()
{
}
bdd
result()
{
return res_;
}
void
visit(const atomic_prop* node)
{
res_ = bdd_ithvar(fact_.create_atomic_prop(node));
}
void
visit(const constant* node)
{
switch (node->val())
{
case constant::True:
res_ = bddtrue;
return;
case constant::False:
res_ = bddfalse;
return;
}
/* Unreachable code. */
assert(0);
}
void
visit(const unop* node)
{
switch (node->op())
{
case unop::Not:
{
res_ = bdd_not(recurse(node->child()));
return;
}
}
/* Unreachable code. */
assert(0);
}
void
visit(const binop* node)
{
bdd f1 = recurse(node->first());
bdd f2 = recurse(node->second());
switch (node->op())
{
case binop::Xor:
res_ = bdd_apply(f1, f2, bddop_xor);
return;
case binop::Implies:
res_ = bdd_apply(f1, f2, bddop_imp);
return;
case binop::Equiv:
res_ = bdd_apply(f1, f2, bddop_biimp);
return;
}
/* Unreachable code. */
assert(0);
}
void
visit(const multop* node)
{
int op = -1;
bool root = false;
switch (node->op())
{
case multop::And:
op = bddop_and;
res_ = bddtrue;
// When the root formula is a conjunction it's ok to
// consider all children as root formulae. This allows the
// root-G trick to save many more variable. (See the
// translation of G.)
root = root_;
break;
case multop::Or:
op = bddop_or;
res_ = bddfalse;
break;
}
assert(op != -1);
unsigned s = node->size();
for (unsigned n = 0; n < s; ++n)
{
res_ = bdd_apply(res_, recurse(node->nth(n), root), op);
}
}
void
visit (const automatop* node)
{
// FIXME.
(void) node;
}
bdd
recurse(const formula* f, bool root = false)
{
eltl_trad_visitor v(fact_, root);
f->accept(v);
return v.result();
}
private:
bdd res_;
tgba_bdd_concrete_factory& fact_;
bool root_;
};
} // anonymous
tgba_bdd_concrete*
eltl_to_tgba_lacim(const eltl::formula* f, bdd_dict* dict)
{
// Normalize the formula. We want all the negations on
// the atomic propositions. We also suppress logic
// abbreviations such as <=>, =>, or XOR, since they
// would involve negations at the BDD level.
const eltl::formula* f1 = eltl::unabbreviate_logic(f);
const eltl::formula* f2 = eltl::negative_normal_form(f1);
eltl::destroy(f1);
// Traverse the formula and draft the automaton in a factory.
tgba_bdd_concrete_factory fact(dict);
eltl_trad_visitor v(fact, true);
f2->accept(v);
eltl::destroy(f2);
fact.finish();
// Finally setup the resulting automaton.
return new tgba_bdd_concrete(fact, v.result());
}
}

View file

@ -0,0 +1,55 @@
// Copyright (C) 2008 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 2 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 Spot; see the file COPYING. If not, write to the Free
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
#ifndef SPOT_TGBAALGOS_ELTL2TGBA_LACIM_HH
# define SPOT_TGBAALGOS_ELTL2TGBA_LACIM_HH
#include "eltlast/formula.hh"
#include "tgba/tgbabddconcrete.hh"
namespace spot
{
/// \brief Build a spot::tgba_bdd_concrete from an ELTL formula.
/// \ingroup tgba_eltl
///
/// This is based on the following paper.
/// \verbatim
/// @InProceedings{ couvreur.00.lacim,
/// author = {Jean-Michel Couvreur},
/// title = {Un point de vue symbolique sur la logique temporelle
/// lin{\'e}aire},
/// booktitle = {Actes du Colloque LaCIM 2000},
/// month = {August},
/// year = {2000},
/// pages = {131--140},
/// volume = {27},
/// series = {Publications du LaCIM},
/// publisher = {Universit{\'e} du Qu{\'e}bec {\`a} Montr{\'e}al},
/// editor = {Pierre Leroux}
/// }
/// \endverbatim
/// \param f The formula to translate into an automaton.
/// \param dict The spot::bdd_dict the constructed automata should use.
/// \return A spot::tgba_bdd_concrete that recognizes the language of \a f.
tgba_bdd_concrete* eltl_to_tgba_lacim(const eltl::formula* f, bdd_dict* dict);
}
#endif // SPOT_TGBAALGOS_LTL2TGBA_LACIM_HH

View file

@ -64,7 +64,7 @@ namespace spot
{
fv_map::iterator i;
for (i = next_map.begin(); i != next_map.end(); ++i)
destroy(i->first);
destroy(dynamic_cast<const ltl::formula*>(i->first));
dict->unregister_all_my_variables(this);
}
@ -125,7 +125,7 @@ namespace spot
for (fi = next_map.begin(); fi != next_map.end(); ++fi)
{
os << " " << fi->second << ": Next[";
to_string(fi->first, os) << "]" << std::endl;
fi->first->to_string(os) << "]" << std::endl;
}
os << "Shared Dict:" << std::endl;
dict->dump(os);
@ -137,13 +137,13 @@ namespace spot
{
vf_map::const_iterator isi = next_formula_map.find(var);
if (isi != next_formula_map.end())
return clone(isi->second);
return dynamic_cast<ltl::formula*>(isi->second->clone());
isi = dict->acc_formula_map.find(var);
if (isi != dict->acc_formula_map.end())
return clone(isi->second);
return dynamic_cast<ltl::formula*>(isi->second->clone());
isi = dict->var_formula_map.find(var);
if (isi != dict->var_formula_map.end())
return clone(isi->second);
return dynamic_cast<ltl::formula*>(isi->second->clone());
assert(0);
// Never reached, but some GCC versions complain about
// a missing return otherwise.

View file

@ -84,7 +84,7 @@ namespace spot
bdd_dict::vf_map::const_iterator vi =
d->acc_formula_map.find(v);
assert(vi != d->acc_formula_map.end());
std::string s = ltl::to_string(vi->second);
std::string s = vi->second->to_string();
if (dynamic_cast<const ltl::atomic_prop*>(vi->second)
&& s[0] == '"')
{

View file

@ -25,7 +25,7 @@ LDADD = ../libspot.la
# These are the most used test programs, and they are also useful
# to run manually outside the test suite. Always build them.
noinst_PROGRAMS = ltl2tgba randtgba
noinst_PROGRAMS = ltl2tgba randtgba eltl2tgba
check_SCRIPTS = defs
# Keep this sorted alphabetically.
@ -46,6 +46,7 @@ check_PROGRAMS = \
# Keep this sorted alphabetically.
bddprod_SOURCES = ltlprod.cc
bddprod_CXXFLAGS = -DBDD_CONCRETE_PRODUCT
eltl2tgba_SOURCES = eltl2tgba.cc
explicit_SOURCES = explicit.cc
expldot_SOURCES = powerset.cc
expldot_CXXFLAGS = -DDOTTY
@ -85,7 +86,8 @@ TESTS = \
emptchke.test \
dfs.test \
emptchkr.test \
spotlbtt.test
spotlbtt.test \
eltl2tgba.test
EXTRA_DIST = $(TESTS)

View file

@ -1,5 +1,5 @@
// Copyright (C) 2008 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.
//
// This file is part of Spot, a model checking library.
@ -19,24 +19,32 @@
// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
/// \file eltlast/atomic_prop.hh
/// \brief ELTL atomic propositions
#ifndef SPOT_ELTLAST_ATOMIC_PROP_HH
# define SPOT_ELTLAST_ATOMIC_PROP_HH
#include <iostream>
#include <cassert>
#include "eltlparse/public.hh"
#include "tgbaalgos/eltl2tgba_lacim.hh"
#include "tgbaalgos/dotty.hh"
# include "formula.hh"
# include "internal/atomic_prop.hh"
namespace spot
int
main(int argc, char** argv)
{
namespace eltl
spot::eltl::parse_error_list p;
const spot::eltl::formula* f = spot::eltl::parse(
argv[1], p, spot::eltl::default_environment::instance(), argc > 2);
if (spot::eltl::format_parse_errors(std::cerr, p))
{
/// \brief Atomic propositions.
/// \ingroup eltl_ast
typedef spot::internal::atomic_prop<eltl_t> atomic_prop;
if (f != 0)
std::cout << f->dump() << std::endl;
return 1;
}
}
#endif // SPOT_ELTLAST_ATOMICPROP_HH
assert(f != 0);
std::cout << f->dump() << std::endl;
spot::bdd_dict* dict = new spot::bdd_dict();
spot::tgba_bdd_concrete* concrete = spot::eltl_to_tgba_lacim(f, dict);
spot::dotty_reachable(std::cout, concrete);
delete concrete;
}

40
src/tgbatest/eltl2tgba.test Executable file
View file

@ -0,0 +1,40 @@
#!/bin/sh
. ./defs || exit -1
set -e
check ()
{
run 0 ./eltl2tgba "$1" || exit 1
}
cat >input <<EOF
A=(
)
%
1
EOF
check input
exit 0
cat >input1 <<EOF
X=(
0 1 true
1 2 \$0
accept 2
)
U=(
0 0 \$0
0 1 \$1
accept 1
)
EOF
cat >input <<EOF
include input1
%
X(a)
EOF
check input