Initial code for TGBA (Transition Generalized Bchi Automata).
Contains tgba_bdd, a BDD-encoded TGBA, and ltl_to_tgba, a LTL-to-TGBA translator using Couvreur's algorithm. * src/Makefile.am (SUBDIRS): Add tgba. (libspot_la_LIBADD): Add tgba/libtgba.la. * src/tgba/Makefile.am, src/tgba/bddfactory.cc, src/tgba/bddfactory.hh, src/tgba/dictunion.cc, src/tgba/dictunion.hh, src/tgba/ltl2tgba.cc, src/tgba/ltl2tgba.hh, src/tgba/state.hh, src/tgba/statebdd.cc, src/tgba/statebdd.hh, src/tgba/succiter.hh, src/tgba/succiterconcrete.cc, src/tgba/succiterconcrete.hh, src/tgba/succlist.hh, src/tgba/tgba.hh, src/tgba/tgbabddconcrete.cc, src/tgba/tgbabddconcrete.hh, src/tgba/tgbabddconcretefactory.cc, src/tgba/tgbabddconcretefactory.hh, src/tgba/tgbabddconcreteproduct.cc, src/tgba/tgbabddconcreteproduct.hh, src/tgba/tgbabddcoredata.cc, src/tgba/tgbabddcoredata.hh, src/tgba/tgbabdddict.cc, src/tgba/tgbabdddict.hh, src/tgba/tgbabddfactory.hh, src/tgba/tgbabddtranslatefactory.cc, src/tgba/tgbabddtranslatefactory.hh: New files.
This commit is contained in:
parent
5100c197a2
commit
c03934140f
32 changed files with 1263 additions and 2 deletions
24
ChangeLog
24
ChangeLog
|
|
@ -1,3 +1,27 @@
|
||||||
|
2003-05-26 Alexandre Duret-Lutz <aduret@src.lip6.fr>
|
||||||
|
|
||||||
|
Initial code for TGBA (Transition Generalized Büchi Automata).
|
||||||
|
Contains tgba_bdd, a BDD-encoded TGBA, and ltl_to_tgba,
|
||||||
|
a LTL-to-TGBA translator using Couvreur's algorithm.
|
||||||
|
|
||||||
|
* src/Makefile.am (SUBDIRS): Add tgba.
|
||||||
|
(libspot_la_LIBADD): Add tgba/libtgba.la.
|
||||||
|
* src/tgba/Makefile.am, src/tgba/bddfactory.cc,
|
||||||
|
src/tgba/bddfactory.hh, src/tgba/dictunion.cc,
|
||||||
|
src/tgba/dictunion.hh, src/tgba/ltl2tgba.cc, src/tgba/ltl2tgba.hh,
|
||||||
|
src/tgba/state.hh, src/tgba/statebdd.cc, src/tgba/statebdd.hh,
|
||||||
|
src/tgba/succiter.hh, src/tgba/succiterconcrete.cc,
|
||||||
|
src/tgba/succiterconcrete.hh, src/tgba/succlist.hh,
|
||||||
|
src/tgba/tgba.hh, src/tgba/tgbabddconcrete.cc,
|
||||||
|
src/tgba/tgbabddconcrete.hh, src/tgba/tgbabddconcretefactory.cc,
|
||||||
|
src/tgba/tgbabddconcretefactory.hh,
|
||||||
|
src/tgba/tgbabddconcreteproduct.cc,
|
||||||
|
src/tgba/tgbabddconcreteproduct.hh, src/tgba/tgbabddcoredata.cc,
|
||||||
|
src/tgba/tgbabddcoredata.hh, src/tgba/tgbabdddict.cc,
|
||||||
|
src/tgba/tgbabdddict.hh, src/tgba/tgbabddfactory.hh,
|
||||||
|
src/tgba/tgbabddtranslatefactory.cc,
|
||||||
|
src/tgba/tgbabddtranslatefactory.hh: New files.
|
||||||
|
|
||||||
2003-05-23 Alexandre Duret-Lutz <aduret@src.lip6.fr>
|
2003-05-23 Alexandre Duret-Lutz <aduret@src.lip6.fr>
|
||||||
|
|
||||||
* m4/gccwarn.m4: Do not use -Winline, this is inappropriate
|
* m4/gccwarn.m4: Do not use -Winline, this is inappropriate
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ AC_CONFIG_FILES([
|
||||||
src/ltltest/Makefile
|
src/ltltest/Makefile
|
||||||
src/ltltest/defs
|
src/ltltest/defs
|
||||||
src/ltlvisit/Makefile
|
src/ltlvisit/Makefile
|
||||||
|
src/tgba/Makefile
|
||||||
src/misc/Makefile
|
src/misc/Makefile
|
||||||
wrap/Makefile
|
wrap/Makefile
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
AUTOMAKE_OPTIONS = subdir-objects
|
AUTOMAKE_OPTIONS = subdir-objects
|
||||||
|
|
||||||
# List directories in the order they must be built.
|
# List directories in the order they must be built.
|
||||||
SUBDIRS = misc ltlenv ltlast ltlvisit ltlparse ltltest
|
SUBDIRS = misc ltlenv ltlast ltlvisit ltlparse ltltest tgba
|
||||||
|
|
||||||
lib_LTLIBRARIES = libspot.la
|
lib_LTLIBRARIES = libspot.la
|
||||||
libspot_la_SOURCES =
|
libspot_la_SOURCES =
|
||||||
|
|
@ -9,4 +9,5 @@ libspot_la_LIBADD = \
|
||||||
ltlenv/libltlenv.la \
|
ltlenv/libltlenv.la \
|
||||||
ltlparse/libltlparse.la \
|
ltlparse/libltlparse.la \
|
||||||
ltlvisit/libltlvisit.la \
|
ltlvisit/libltlvisit.la \
|
||||||
ltlast/libltlast.la
|
ltlast/libltlast.la \
|
||||||
|
tgba/libtgba.la
|
||||||
|
|
|
||||||
6
src/tgba/.cvsignore
Normal file
6
src/tgba/.cvsignore
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
.deps
|
||||||
|
.libs
|
||||||
|
*.lo
|
||||||
|
*.la
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
31
src/tgba/Makefile.am
Normal file
31
src/tgba/Makefile.am
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
AM_CPPFLAGS = -I$(srcdir)/..
|
||||||
|
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
||||||
|
|
||||||
|
noinst_LTLIBRARIES = libtgba.la
|
||||||
|
libtgba_la_SOURCES = \
|
||||||
|
bddfactory.cc \
|
||||||
|
bddfactory.hh \
|
||||||
|
dictunion.cc \
|
||||||
|
dictunion.hh \
|
||||||
|
ltl2tgba.cc \
|
||||||
|
ltl2tgba.hh \
|
||||||
|
state.hh \
|
||||||
|
statebdd.cc \
|
||||||
|
statebdd.hh \
|
||||||
|
succiter.hh \
|
||||||
|
succiterconcrete.cc \
|
||||||
|
succiterconcrete.hh \
|
||||||
|
tgba.hh \
|
||||||
|
tgbabddconcrete.cc \
|
||||||
|
tgbabddconcrete.hh \
|
||||||
|
tgbabddconcretefactory.cc \
|
||||||
|
tgbabddconcretefactory.hh \
|
||||||
|
tgbabddconcreteproduct.cc \
|
||||||
|
tgbabddconcreteproduct.hh \
|
||||||
|
tgbabddcoredata.cc \
|
||||||
|
tgbabddcoredata.hh \
|
||||||
|
tgbabdddict.cc \
|
||||||
|
tgbabdddict.hh \
|
||||||
|
tgbabddfactory.hh \
|
||||||
|
tgbabddtranslatefactory.cc \
|
||||||
|
tgbabddtranslatefactory.hh
|
||||||
48
src/tgba/bddfactory.cc
Normal file
48
src/tgba/bddfactory.cc
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "bddfactory.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
bdd_factory::bdd_factory()
|
||||||
|
: varused(0)
|
||||||
|
{
|
||||||
|
initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bdd_factory::create_node()
|
||||||
|
{
|
||||||
|
return create_nodes(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bdd_factory::create_pair()
|
||||||
|
{
|
||||||
|
return create_nodes(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
bdd_factory::create_nodes(int i)
|
||||||
|
{
|
||||||
|
int res = varused;
|
||||||
|
varused += i;
|
||||||
|
if (varnum < varused)
|
||||||
|
{
|
||||||
|
bdd_extvarnum(varused - varnum);
|
||||||
|
varnum = varused;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bdd_factory::initialize()
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
initialized = true;
|
||||||
|
bdd_init(50000, 5000);
|
||||||
|
bdd_setvarnum(varnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bdd_factory::initialized = false;
|
||||||
|
int bdd_factory::varnum = 2;
|
||||||
|
}
|
||||||
33
src/tgba/bddfactory.hh
Normal file
33
src/tgba/bddfactory.hh
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef SPOT_TGBA_BDDFACTORY_HH
|
||||||
|
# define SPOT_TGBA_BDDFACTORY_HH
|
||||||
|
|
||||||
|
#include <bdd.h>
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
|
||||||
|
class bdd_factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdd_factory();
|
||||||
|
|
||||||
|
int create_node();
|
||||||
|
int create_pair();
|
||||||
|
|
||||||
|
static bdd
|
||||||
|
ithvar(int i)
|
||||||
|
{
|
||||||
|
return bdd_ithvar(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void initialize();
|
||||||
|
int create_nodes(int i);
|
||||||
|
|
||||||
|
static bool initialized;
|
||||||
|
static int varnum;
|
||||||
|
int varused;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_BDDFACTORY_HH
|
||||||
75
src/tgba/dictunion.cc
Normal file
75
src/tgba/dictunion.cc
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#include <set>
|
||||||
|
#include "dictunion.hh"
|
||||||
|
#include <bdd.h>
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
|
||||||
|
tgba_bdd_dict
|
||||||
|
tgba_bdd_dict_union(const tgba_bdd_dict& l, const tgba_bdd_dict& r)
|
||||||
|
{
|
||||||
|
tgba_bdd_dict res;
|
||||||
|
|
||||||
|
std::set<const ltl::formula*> now;
|
||||||
|
std::set<const ltl::formula*> var;
|
||||||
|
std::set<const ltl::formula*> prom;
|
||||||
|
|
||||||
|
tgba_bdd_dict::fv_map::const_iterator i;
|
||||||
|
|
||||||
|
// Merge Now variables.
|
||||||
|
for (i = l.now_map.begin(); i != l.now_map.end(); ++i)
|
||||||
|
now.insert(i->first);
|
||||||
|
for (i = r.now_map.begin(); i != r.now_map.end(); ++i)
|
||||||
|
now.insert(i->first);
|
||||||
|
|
||||||
|
// Merge atomic propositions.
|
||||||
|
for (i = l.var_map.begin(); i != l.var_map.end(); ++i)
|
||||||
|
var.insert(i->first);
|
||||||
|
for (i = r.var_map.begin(); i != r.var_map.end(); ++i)
|
||||||
|
var.insert(i->first);
|
||||||
|
|
||||||
|
// Merge promises.
|
||||||
|
for (i = l.prom_map.begin(); i != l.prom_map.end(); ++i)
|
||||||
|
prom.insert(i->first);
|
||||||
|
for (i = r.prom_map.begin(); i != r.prom_map.end(); ++i)
|
||||||
|
prom.insert(i->first);
|
||||||
|
|
||||||
|
// Ensure we have enough BDD variables.
|
||||||
|
int have = bdd_extvarnum(0);
|
||||||
|
int want = now.size() * 2 + var.size() + prom.size();
|
||||||
|
if (have < want)
|
||||||
|
bdd_setvarnum(want);
|
||||||
|
|
||||||
|
// Fill in the "defragmented" union dictionary.
|
||||||
|
|
||||||
|
// FIXME: Make some experiments with ordering of prom/var/now variables.
|
||||||
|
// Maybe there is one order that usually produces smaller BDDs?
|
||||||
|
|
||||||
|
// Next BDD variable to use.
|
||||||
|
int v = 0;
|
||||||
|
|
||||||
|
std::set<const ltl::formula*>::const_iterator f;
|
||||||
|
for (f = prom.begin(); f != prom.end(); ++f)
|
||||||
|
{
|
||||||
|
res.prom_map[*f] = v;
|
||||||
|
res.prom_formula_map[v] = *f;
|
||||||
|
++v;
|
||||||
|
}
|
||||||
|
for (f = var.begin(); f != var.end(); ++f)
|
||||||
|
{
|
||||||
|
res.var_map[*f] = v;
|
||||||
|
res.var_formula_map[v] = *f;
|
||||||
|
++v;
|
||||||
|
}
|
||||||
|
for (f = now.begin(); f != now.end(); ++f)
|
||||||
|
{
|
||||||
|
res.now_map[*f] = v;
|
||||||
|
res.now_formula_map[v] = *f;
|
||||||
|
v += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (v == want);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
src/tgba/dictunion.hh
Normal file
12
src/tgba/dictunion.hh
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef SPOT_TGBA_DICTUNION_HH
|
||||||
|
# define SPOT_TGBA_DICTUNION_HH
|
||||||
|
|
||||||
|
#include "tgbabdddict.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_dict
|
||||||
|
tgba_bdd_dict_union(const tgba_bdd_dict& l, const tgba_bdd_dict& r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_DICTUNION_HH
|
||||||
183
src/tgba/ltl2tgba.cc
Normal file
183
src/tgba/ltl2tgba.cc
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
#include "ltlast/visitor.hh"
|
||||||
|
#include "ltlast/allnodes.hh"
|
||||||
|
#include "tgbabddconcretefactory.hh"
|
||||||
|
|
||||||
|
#include "ltl2tgba.hh"
|
||||||
|
// FIXME: Add ref to Couvreur's paper.
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
using namespace ltl;
|
||||||
|
class ltl_trad_visitor: public const_visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ltl_trad_visitor(tgba_bdd_concrete_factory& fact)
|
||||||
|
: fact_(fact)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual
|
||||||
|
~ltl_trad_visitor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
result()
|
||||||
|
{
|
||||||
|
return res_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
visit(const atomic_prop* node)
|
||||||
|
{
|
||||||
|
res_ = fact_.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::F:
|
||||||
|
case unop::G:
|
||||||
|
// FIXME: We can normalize on the fly, here.
|
||||||
|
assert(!"unexpected operator, normalize first");
|
||||||
|
case unop::Not:
|
||||||
|
res_ = bdd_not(recurse(node->child()));
|
||||||
|
return;
|
||||||
|
case unop::X:
|
||||||
|
// FIXME: Can be smarter on X(a U b) and X(a R b).
|
||||||
|
int v = fact_.create_state(node->child());
|
||||||
|
bdd now = fact_.ithvar(v);
|
||||||
|
bdd next = fact_.ithvar(v + 1);
|
||||||
|
fact_.add_relation(bdd_apply(now, recurse(node->child()),
|
||||||
|
bddop_biimp));
|
||||||
|
res_ = next;
|
||||||
|
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;
|
||||||
|
case binop::U:
|
||||||
|
{
|
||||||
|
int v = fact_.create_state(node);
|
||||||
|
bdd now = fact_.ithvar(v);
|
||||||
|
bdd next = fact_.ithvar(v + 1);
|
||||||
|
|
||||||
|
bdd promise_f2 =
|
||||||
|
fact_.ithvar(fact_.create_promise(node->second()));
|
||||||
|
/*
|
||||||
|
f1 U f2 <=> f2 | (f1 & X(f1 U f2))
|
||||||
|
In other words:
|
||||||
|
now <=> f2 | (f1 & next)
|
||||||
|
|
||||||
|
The rightmost conjunction, f1 & next, doesn't actually
|
||||||
|
encodes the fact that f2 should be fulfilled at some
|
||||||
|
point. We use the `promise_f2' variable for this purpose.
|
||||||
|
*/
|
||||||
|
fact_.add_relation(bdd_apply(now,
|
||||||
|
f2 | (promise_f2 & f1 & next),
|
||||||
|
bddop_biimp));
|
||||||
|
res_ = now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case binop::R:
|
||||||
|
{
|
||||||
|
int v = fact_.create_state(node);
|
||||||
|
bdd now = fact_.ithvar(v);
|
||||||
|
bdd next = fact_.ithvar(v + 1);
|
||||||
|
/*
|
||||||
|
f1 R f2 <=> f2 & (f1 | X(f1 U f2))
|
||||||
|
In other words:
|
||||||
|
now <=> f2 & (f1 | next)
|
||||||
|
*/
|
||||||
|
fact_.add_relation(bdd_apply(now, f2 & (f1 | next), bddop_biimp));
|
||||||
|
res_ = now;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Unreachable code. */
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
visit(const multop* node)
|
||||||
|
{
|
||||||
|
int op = -1;
|
||||||
|
switch (node->op())
|
||||||
|
{
|
||||||
|
case multop::And:
|
||||||
|
op = bddop_and;
|
||||||
|
res_ = bddtrue;
|
||||||
|
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)), op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
recurse(const formula* f)
|
||||||
|
{
|
||||||
|
ltl_trad_visitor v(*this);
|
||||||
|
f->accept(v);
|
||||||
|
return v.result();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bdd res_;
|
||||||
|
tgba_bdd_concrete_factory& fact_;
|
||||||
|
};
|
||||||
|
|
||||||
|
tgba_bdd_concrete
|
||||||
|
ltl_to_tgba(const formula* f)
|
||||||
|
{
|
||||||
|
tgba_bdd_concrete_factory fact;
|
||||||
|
ltl_trad_visitor v(fact);
|
||||||
|
f->accept(v);
|
||||||
|
tgba_bdd_concrete g(fact);
|
||||||
|
g.set_init_state(v.result());
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/tgba/ltl2tgba.hh
Normal file
13
src/tgba/ltl2tgba.hh
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef SPOT_TGBA_LTL2TGBA_HH
|
||||||
|
# define SPOT_TGBA_LTL2TGBA_HH
|
||||||
|
|
||||||
|
#include "ltlast/formula.hh"
|
||||||
|
#include "tgbabddconcrete.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_concrete ltl_to_tgba(const ltl::formula* f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_LTL2TGBA_HH
|
||||||
|
|
||||||
25
src/tgba/state.hh
Normal file
25
src/tgba/state.hh
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef SPOT_TGBA_STATE_HH
|
||||||
|
# define SPOT_TGBA_STATE_HH
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
class state
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Compares two states (that come from the same automaton).
|
||||||
|
//
|
||||||
|
// This method returns an integer less than, equal to, or greater
|
||||||
|
// than zero if THIS is found, respectively, to be less than, equal
|
||||||
|
// to, or greater than OTHER according to some implicit total order.
|
||||||
|
//
|
||||||
|
// This method should not be called to compare state from
|
||||||
|
// different automata.
|
||||||
|
virtual int compare(const state& other) const = 0;
|
||||||
|
|
||||||
|
virtual ~state()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_STATE_HH
|
||||||
16
src/tgba/statebdd.cc
Normal file
16
src/tgba/statebdd.cc
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "statebdd.hh"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
int
|
||||||
|
state_bdd::compare(const state& other) const
|
||||||
|
{
|
||||||
|
// This method should not be called to compare states from different
|
||||||
|
// automata, and all states from the same automaton will use the same
|
||||||
|
// state class.
|
||||||
|
const state_bdd* o = dynamic_cast<const state_bdd*>(&other);
|
||||||
|
assert(o);
|
||||||
|
return o->as_bdd().id() - state_.id();
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/tgba/statebdd.hh
Normal file
30
src/tgba/statebdd.hh
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef SPOT_TGBA_STATEBDD_HH
|
||||||
|
# define SPOT_TGBA_STATEBDD_HH
|
||||||
|
|
||||||
|
#include <bdd.h>
|
||||||
|
#include "state.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
class state_bdd: public state
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
state_bdd(bdd s)
|
||||||
|
: state_(s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
as_bdd() const
|
||||||
|
{
|
||||||
|
return state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int compare(const state& other) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bdd state_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_STATEBDD_HH
|
||||||
31
src/tgba/succiter.hh
Normal file
31
src/tgba/succiter.hh
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef SPOT_TGBA_SUCCITER_H
|
||||||
|
# define SPOT_TGBA_SUCCITER_H
|
||||||
|
|
||||||
|
#include "statebdd.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
|
||||||
|
class tgba_succ_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual
|
||||||
|
~tgba_succ_iterator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// iteration
|
||||||
|
virtual void first() = 0;
|
||||||
|
virtual void next() = 0;
|
||||||
|
virtual bool done() = 0;
|
||||||
|
|
||||||
|
// inspection
|
||||||
|
virtual state_bdd current_state() = 0;
|
||||||
|
virtual bdd current_condition() = 0;
|
||||||
|
virtual bdd current_promise() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_SUCCITER_H
|
||||||
64
src/tgba/succiterconcrete.cc
Normal file
64
src/tgba/succiterconcrete.cc
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "succiterconcrete.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_succ_iterator_concrete::tgba_succ_iterator_concrete
|
||||||
|
(const tgba_bdd_core_data& d, bdd successors)
|
||||||
|
: data_(d), succ_set_(successors), next_succ_set_(successors),
|
||||||
|
current_(bddfalse)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_succ_iterator_concrete::~tgba_succ_iterator_concrete()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_succ_iterator_concrete::first()
|
||||||
|
{
|
||||||
|
next_succ_set_ = succ_set_;
|
||||||
|
if (!done())
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_succ_iterator_concrete::next()
|
||||||
|
{
|
||||||
|
assert(!done());
|
||||||
|
|
||||||
|
// FIXME: Iterating on the successors this way (calling bdd_satone
|
||||||
|
// and NANDing out the result from the set) requires several descent
|
||||||
|
// of the BDD. Maybe it would be faster to compute all satisfying
|
||||||
|
// formula in one operation.
|
||||||
|
next_succ_set_ &= !current_;
|
||||||
|
current_ = bdd_satone(next_succ_set_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
tgba_succ_iterator_concrete::done()
|
||||||
|
{
|
||||||
|
return next_succ_set_ == bddfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_bdd
|
||||||
|
tgba_succ_iterator_concrete::current_state()
|
||||||
|
{
|
||||||
|
assert(!done());
|
||||||
|
return bdd_exist(current_, data_.notnow_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
tgba_succ_iterator_concrete::current_condition()
|
||||||
|
{
|
||||||
|
assert(!done());
|
||||||
|
return bdd_exist(current_, data_.notvar_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
tgba_succ_iterator_concrete::current_promise()
|
||||||
|
{
|
||||||
|
assert(!done());
|
||||||
|
return bdd_exist(current_, data_.notprom_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
src/tgba/succiterconcrete.hh
Normal file
33
src/tgba/succiterconcrete.hh
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef SPOT_TGBA_SUCCITERCONCRETE_HH
|
||||||
|
# define SPOT_TGBA_SUCCITERCONCRETE_HH
|
||||||
|
|
||||||
|
#include "succiter.hh"
|
||||||
|
#include "tgbabddcoredata.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
class tgba_succ_iterator_concrete: public tgba_succ_iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tgba_succ_iterator_concrete(const tgba_bdd_core_data& d, bdd successors);
|
||||||
|
virtual ~tgba_succ_iterator_concrete();
|
||||||
|
|
||||||
|
// iteration
|
||||||
|
void first();
|
||||||
|
void next();
|
||||||
|
bool done();
|
||||||
|
|
||||||
|
// inspection
|
||||||
|
state_bdd current_state();
|
||||||
|
bdd current_condition();
|
||||||
|
bdd current_promise();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const tgba_bdd_core_data& data_;
|
||||||
|
bdd succ_set_; // The set of successors.
|
||||||
|
bdd next_succ_set_; // Unexplored successors (including current_).
|
||||||
|
bdd current_; // Current successor.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_SUCCITERCONCRETE_HH
|
||||||
15
src/tgba/succlist.hh
Normal file
15
src/tgba/succlist.hh
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef SPOT_WAUTO_SUCCLIST_HH
|
||||||
|
# define SPOT_WAUTO_SUCCLIST_HH
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
|
||||||
|
struct successor_list
|
||||||
|
{
|
||||||
|
virtual
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif SPOT_WAUTO_SUCCLIST_HH
|
||||||
8
src/tgba/tgba.hh
Normal file
8
src/tgba/tgba.hh
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBA_HH
|
||||||
|
# define SPOT_TGBA_TGBA_HH
|
||||||
|
|
||||||
|
# include "tgbabddconcrete.hh"
|
||||||
|
# include "tgbabddconcreteproduct.hh"
|
||||||
|
# include "ltl2tgba.hh"
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBA_HH
|
||||||
58
src/tgba/tgbabddconcrete.cc
Normal file
58
src/tgba/tgbabddconcrete.cc
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include "tgbabddconcrete.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_concrete::tgba_bdd_concrete(const tgba_bdd_factory& fact)
|
||||||
|
: data_(fact.get_core_data()), dict_(fact.get_dict())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_bdd_concrete::tgba_bdd_concrete(const tgba_bdd_factory& fact, bdd init)
|
||||||
|
: data_(fact.get_core_data()), dict_(fact.get_dict()), init_(init)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_bdd_concrete::~tgba_bdd_concrete()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_bdd_concrete::set_init_state(bdd s)
|
||||||
|
{
|
||||||
|
init_ = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
state_bdd
|
||||||
|
tgba_bdd_concrete::get_init_state() const
|
||||||
|
{
|
||||||
|
return init_;
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_succ_iterator_concrete*
|
||||||
|
tgba_bdd_concrete::succ_iter(bdd state) const
|
||||||
|
{
|
||||||
|
bdd succ_set = bdd_replace(bdd_exist(data_.relation & state,
|
||||||
|
data_.now_set),
|
||||||
|
data_.next_to_now);
|
||||||
|
return new tgba_succ_iterator_concrete(data_, succ_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_succ_iterator_concrete*
|
||||||
|
tgba_bdd_concrete::init_iter() const
|
||||||
|
{
|
||||||
|
return new tgba_succ_iterator_concrete(data_, init_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_dict&
|
||||||
|
tgba_bdd_concrete::get_dict() const
|
||||||
|
{
|
||||||
|
return dict_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_core_data&
|
||||||
|
tgba_bdd_concrete::get_core_data() const
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
34
src/tgba/tgbabddconcrete.hh
Normal file
34
src/tgba/tgbabddconcrete.hh
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDCONCRETE_HH
|
||||||
|
# define SPOT_TGBA_TGBABDDCONCRETE_HH
|
||||||
|
|
||||||
|
#include "statebdd.hh"
|
||||||
|
#include "tgbabddfactory.hh"
|
||||||
|
#include "succiterconcrete.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
class tgba_bdd_concrete
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tgba_bdd_concrete(const tgba_bdd_factory& fact);
|
||||||
|
tgba_bdd_concrete(const tgba_bdd_factory& fact, bdd init);
|
||||||
|
~tgba_bdd_concrete();
|
||||||
|
|
||||||
|
void set_init_state(bdd s);
|
||||||
|
state_bdd get_init_state() const;
|
||||||
|
|
||||||
|
tgba_succ_iterator_concrete* succ_iter(bdd state) const;
|
||||||
|
tgba_succ_iterator_concrete* init_iter() const;
|
||||||
|
|
||||||
|
const tgba_bdd_dict& get_dict() const;
|
||||||
|
const tgba_bdd_core_data& get_core_data() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
tgba_bdd_core_data data_;
|
||||||
|
tgba_bdd_dict dict_;
|
||||||
|
bdd init_;
|
||||||
|
friend class tgba_tgba_succ_iterator;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBABDDCONCRETE_HH
|
||||||
84
src/tgba/tgbabddconcretefactory.cc
Normal file
84
src/tgba/tgbabddconcretefactory.cc
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "tgbabddconcretefactory.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_concrete_factory::~tgba_bdd_concrete_factory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tgba_bdd_concrete_factory::create_state(const ltl::formula* f)
|
||||||
|
{
|
||||||
|
// Do not build a state that already exists.
|
||||||
|
tgba_bdd_dict::fv_map::iterator sii = dict_.now_map.find(f);
|
||||||
|
if (sii != dict_.now_map.end())
|
||||||
|
return sii->second;
|
||||||
|
|
||||||
|
int num = create_pair();
|
||||||
|
|
||||||
|
dict_.now_map[f] = num;
|
||||||
|
dict_.now_formula_map[num] = f;
|
||||||
|
|
||||||
|
// Record that num+1 should be renamed as num when
|
||||||
|
// the next state becomes current.
|
||||||
|
bdd_setpair(data_.next_to_now, num + 1, num);
|
||||||
|
|
||||||
|
// Keep track of all "Now" variables for easy
|
||||||
|
// existential quantification.
|
||||||
|
data_.declare_now_next (ithvar(num), ithvar(num + 1));
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tgba_bdd_concrete_factory::create_atomic_prop(const ltl::formula* f)
|
||||||
|
{
|
||||||
|
// Do not build a variable that already exists.
|
||||||
|
tgba_bdd_dict::fv_map::iterator sii = dict_.var_map.find(f);
|
||||||
|
if (sii != dict_.var_map.end())
|
||||||
|
return sii->second;
|
||||||
|
|
||||||
|
int num = create_node();
|
||||||
|
dict_.var_map[f] = num;
|
||||||
|
dict_.var_formula_map[num] = f;
|
||||||
|
|
||||||
|
// Keep track of all atomic proposition for easy
|
||||||
|
// existential quantification.
|
||||||
|
data_.declare_atomic_prop(ithvar(num));
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tgba_bdd_concrete_factory::create_promise(const ltl::formula* f)
|
||||||
|
{
|
||||||
|
// Do not build a promise that already exists.
|
||||||
|
tgba_bdd_dict::fv_map::iterator sii = dict_.prom_map.find(f);
|
||||||
|
if (sii != dict_.prom_map.end())
|
||||||
|
return sii->second;
|
||||||
|
|
||||||
|
int num = create_node();
|
||||||
|
dict_.prom_map[f] = num;
|
||||||
|
dict_.prom_formula_map[num] = f;
|
||||||
|
|
||||||
|
// Keep track of all promises for easy existential quantification.
|
||||||
|
data_.declare_promise(ithvar(num));
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_core_data&
|
||||||
|
tgba_bdd_concrete_factory::get_core_data() const
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_dict&
|
||||||
|
tgba_bdd_concrete_factory::get_dict() const
|
||||||
|
{
|
||||||
|
return dict_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_bdd_concrete_factory::add_relation(bdd new_rel)
|
||||||
|
{
|
||||||
|
data_.relation &= new_rel;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/tgba/tgbabddconcretefactory.hh
Normal file
31
src/tgba/tgbabddconcretefactory.hh
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDCONCRETEFACTORY_HH
|
||||||
|
# define SPOT_TGBA_TGBABDDCONCRETEFACTORY_HH
|
||||||
|
|
||||||
|
#include "ltlast/formula.hh"
|
||||||
|
#include "bddfactory.hh"
|
||||||
|
#include "tgbabddfactory.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
|
||||||
|
class tgba_bdd_concrete_factory: public bdd_factory, public tgba_bdd_factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~tgba_bdd_concrete_factory();
|
||||||
|
|
||||||
|
int create_state(const ltl::formula* f);
|
||||||
|
int create_atomic_prop(const ltl::formula* f);
|
||||||
|
int create_promise(const ltl::formula* f);
|
||||||
|
|
||||||
|
const tgba_bdd_core_data& get_core_data() const;
|
||||||
|
const tgba_bdd_dict& get_dict() const;
|
||||||
|
|
||||||
|
void add_relation(bdd new_rel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
tgba_bdd_core_data data_;
|
||||||
|
tgba_bdd_dict dict_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // SPOT_TGBA_TGBABDDCONCRETEFACTORY_HH
|
||||||
59
src/tgba/tgbabddconcreteproduct.cc
Normal file
59
src/tgba/tgbabddconcreteproduct.cc
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include "tgbabddconcreteproduct.hh"
|
||||||
|
#include "tgbabddtranslatefactory.hh"
|
||||||
|
#include "dictunion.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
class tgba_bdd_product_factory: public tgba_bdd_factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tgba_bdd_product_factory(const tgba_bdd_concrete& left,
|
||||||
|
const tgba_bdd_concrete& right)
|
||||||
|
: dict_(tgba_bdd_dict_union(left.get_dict(),
|
||||||
|
right.get_dict())),
|
||||||
|
fact_left_(left, dict_),
|
||||||
|
fact_right_(right, dict_),
|
||||||
|
data_(fact_left_.get_core_data(), fact_right_.get_core_data()),
|
||||||
|
init_(fact_left_.get_init_state() & fact_right_.get_init_state())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual
|
||||||
|
~tgba_bdd_product_factory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_core_data&
|
||||||
|
get_core_data() const
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_dict&
|
||||||
|
get_dict() const
|
||||||
|
{
|
||||||
|
return dict_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
get_init_state() const
|
||||||
|
{
|
||||||
|
return init_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
tgba_bdd_dict dict_;
|
||||||
|
tgba_bdd_translate_factory fact_left_;
|
||||||
|
tgba_bdd_translate_factory fact_right_;
|
||||||
|
tgba_bdd_core_data data_;
|
||||||
|
bdd init_;
|
||||||
|
};
|
||||||
|
|
||||||
|
tgba_bdd_concrete
|
||||||
|
product(const tgba_bdd_concrete& left, const tgba_bdd_concrete& right)
|
||||||
|
{
|
||||||
|
|
||||||
|
tgba_bdd_product_factory p(left, right);
|
||||||
|
return tgba_bdd_concrete(p, p.get_init_state());
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/tgba/tgbabddconcreteproduct.hh
Normal file
12
src/tgba/tgbabddconcreteproduct.hh
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDCONCRETEPRODUCT_HH
|
||||||
|
# define SPOT_TGBA_TGBABDDCONCRETEPRODUCT_HH
|
||||||
|
|
||||||
|
#include "tgbabddconcrete.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_concrete
|
||||||
|
product(const tgba_bdd_concrete& left, const tgba_bdd_concrete& right);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBABDDCONCRETEPRODUCT_HH
|
||||||
74
src/tgba/tgbabddcoredata.cc
Normal file
74
src/tgba/tgbabddcoredata.cc
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include "tgbabddcoredata.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_core_data::tgba_bdd_core_data()
|
||||||
|
: relation(bddtrue),
|
||||||
|
now_set(bddtrue), negnow_set(bddtrue), notnow_set(bddtrue),
|
||||||
|
notvar_set(bddtrue), notprom_set(bddtrue), next_to_now(bdd_newpair())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_bdd_core_data::tgba_bdd_core_data(const tgba_bdd_core_data& copy)
|
||||||
|
: relation(copy.relation),
|
||||||
|
now_set(copy.now_set), negnow_set(copy.negnow_set),
|
||||||
|
notnow_set(copy.notnow_set), notvar_set(copy.notvar_set),
|
||||||
|
notprom_set(copy.notprom_set),
|
||||||
|
next_to_now(bdd_copypair(copy.next_to_now))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge two core_data.
|
||||||
|
tgba_bdd_core_data::tgba_bdd_core_data(const tgba_bdd_core_data& left,
|
||||||
|
const tgba_bdd_core_data& right)
|
||||||
|
: relation(left.relation & right.relation),
|
||||||
|
now_set(left.now_set & right.now_set),
|
||||||
|
negnow_set(left.negnow_set & right.negnow_set),
|
||||||
|
notnow_set(left.notnow_set & right.notnow_set),
|
||||||
|
notvar_set(left.notvar_set & right.notvar_set),
|
||||||
|
notprom_set(left.notprom_set & right.notprom_set),
|
||||||
|
next_to_now(bdd_mergepairs(left.next_to_now, right.next_to_now))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_core_data&
|
||||||
|
tgba_bdd_core_data::operator= (const tgba_bdd_core_data& copy)
|
||||||
|
{
|
||||||
|
if (this != ©)
|
||||||
|
{
|
||||||
|
this->~tgba_bdd_core_data();
|
||||||
|
new (this) tgba_bdd_core_data(copy);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_bdd_core_data::~tgba_bdd_core_data()
|
||||||
|
{
|
||||||
|
bdd_freepair(next_to_now);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_bdd_core_data::declare_now_next(bdd now, bdd next)
|
||||||
|
{
|
||||||
|
now_set &= now;
|
||||||
|
negnow_set &= !now;
|
||||||
|
notnow_set &= next;
|
||||||
|
bdd both = now & next;
|
||||||
|
notvar_set &= both;
|
||||||
|
notprom_set &= both;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_bdd_core_data::declare_atomic_prop(bdd var)
|
||||||
|
{
|
||||||
|
notnow_set &= var;
|
||||||
|
notprom_set &= var;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tgba_bdd_core_data::declare_promise(bdd prom)
|
||||||
|
{
|
||||||
|
notnow_set &= prom;
|
||||||
|
notvar_set &= prom;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/tgba/tgbabddcoredata.hh
Normal file
54
src/tgba/tgbabddcoredata.hh
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDCOREDATA_HH
|
||||||
|
# define SPOT_TGBA_TGBABDDCOREDATA_HH
|
||||||
|
|
||||||
|
#include <bdd.h>
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
struct tgba_bdd_core_data
|
||||||
|
{
|
||||||
|
// RELATION encodes the transition relation of the TGBA.
|
||||||
|
// It uses four kinds of variables:
|
||||||
|
// - "Now" variables, that encode the current state
|
||||||
|
// - "Next" variables, that encode the destination state
|
||||||
|
// - atomic propositions, which are things to verify before going on
|
||||||
|
// to the next state
|
||||||
|
// - promises: a U b, or F b, both implie that b should be verified
|
||||||
|
// eventually. We encode this with Prom[b], and check
|
||||||
|
// that promises are fullfilled in the emptyness check.
|
||||||
|
bdd relation;
|
||||||
|
|
||||||
|
// The conjunction of all Now variables, in their positive form.
|
||||||
|
bdd now_set;
|
||||||
|
// The conjunction of all Now variables, in their negated form.
|
||||||
|
bdd negnow_set;
|
||||||
|
// The (positive) conjunction of all variables which are not Now variables.
|
||||||
|
bdd notnow_set;
|
||||||
|
// The (positive) conjunction of all variables which are not atomic
|
||||||
|
// propositions.
|
||||||
|
bdd notvar_set;
|
||||||
|
// The (positive) conjunction of all variables which are not promises.
|
||||||
|
bdd notprom_set;
|
||||||
|
|
||||||
|
// Record pairings between Next and Now variables.
|
||||||
|
bddPair* next_to_now;
|
||||||
|
|
||||||
|
|
||||||
|
tgba_bdd_core_data();
|
||||||
|
tgba_bdd_core_data(const tgba_bdd_core_data& copy);
|
||||||
|
|
||||||
|
// Merge two core_data.
|
||||||
|
tgba_bdd_core_data(const tgba_bdd_core_data& left,
|
||||||
|
const tgba_bdd_core_data& right);
|
||||||
|
|
||||||
|
const tgba_bdd_core_data& operator= (const tgba_bdd_core_data& copy);
|
||||||
|
|
||||||
|
~tgba_bdd_core_data();
|
||||||
|
|
||||||
|
void declare_now_next(bdd now, bdd next);
|
||||||
|
void declare_atomic_prop(bdd var);
|
||||||
|
void declare_promise(bdd prom);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBABDDCOREDATA_HH
|
||||||
32
src/tgba/tgbabdddict.cc
Normal file
32
src/tgba/tgbabdddict.cc
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "tgbabdddict.hh"
|
||||||
|
#include "ltlvisit/tostring.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
std::ostream&
|
||||||
|
tgba_bdd_dict::dump(std::ostream& os) const
|
||||||
|
{
|
||||||
|
fv_map::const_iterator sii;
|
||||||
|
os << "Atomic Propositions:" << std::endl;
|
||||||
|
for (sii = var_map.begin(); sii != var_map.end(); ++sii)
|
||||||
|
{
|
||||||
|
os << " " << sii->second << ": ";
|
||||||
|
to_string(sii->first, os) << std::endl;
|
||||||
|
}
|
||||||
|
os << "States:" << std::endl;
|
||||||
|
for (sii = now_map.begin(); sii != now_map.end(); ++sii)
|
||||||
|
{
|
||||||
|
os << " " << sii->second << ": Now[";
|
||||||
|
to_string(sii->first, os) << "]" << std::endl;
|
||||||
|
os << " " << sii->second + 1 << ": Next[";
|
||||||
|
to_string(sii->first, os) << "]" << std::endl;
|
||||||
|
}
|
||||||
|
os << "Promises:" << std::endl;
|
||||||
|
for (sii = prom_map.begin(); sii != prom_map.end(); ++sii)
|
||||||
|
{
|
||||||
|
os << " " << sii->second << ": ";
|
||||||
|
to_string(sii->first, os) << std::endl;
|
||||||
|
}
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/tgba/tgbabdddict.hh
Normal file
30
src/tgba/tgbabdddict.hh
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDDICT_H
|
||||||
|
# define SPOT_TGBA_TGBABDDDICT_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <iostream>
|
||||||
|
#include "ltlast/formula.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
struct tgba_bdd_dict
|
||||||
|
{
|
||||||
|
// Dictionaries for BDD variables.
|
||||||
|
|
||||||
|
// formula-to-BDD-variable maps
|
||||||
|
typedef std::map<const ltl::formula*, int> fv_map;
|
||||||
|
// BDD-variable-to-formula maps
|
||||||
|
typedef std::map<int, const ltl::formula*> vf_map;
|
||||||
|
|
||||||
|
fv_map now_map;
|
||||||
|
vf_map now_formula_map;
|
||||||
|
fv_map var_map;
|
||||||
|
vf_map var_formula_map;
|
||||||
|
fv_map prom_map;
|
||||||
|
vf_map prom_formula_map;
|
||||||
|
|
||||||
|
std::ostream& dump(std::ostream& os) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBABDDDICT_H
|
||||||
17
src/tgba/tgbabddfactory.hh
Normal file
17
src/tgba/tgbabddfactory.hh
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDFACTORY_H
|
||||||
|
# define SPOT_TGBA_TGBABDDFACTORY_H
|
||||||
|
|
||||||
|
#include "tgbabddcoredata.hh"
|
||||||
|
#include "tgbabdddict.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
class tgba_bdd_factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual const tgba_bdd_core_data& get_core_data() const = 0;
|
||||||
|
virtual const tgba_bdd_dict& get_dict() const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBABDDFACTORY_H
|
||||||
93
src/tgba/tgbabddtranslatefactory.cc
Normal file
93
src/tgba/tgbabddtranslatefactory.cc
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
#include "tgbabddtranslatefactory.hh"
|
||||||
|
#include "dictunion.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
tgba_bdd_translate_factory::tgba_bdd_translate_factory
|
||||||
|
(const tgba_bdd_concrete& from, const tgba_bdd_dict& to)
|
||||||
|
: dict_(to)
|
||||||
|
{
|
||||||
|
bddPair* rewrite = compute_pairs(from.get_dict());
|
||||||
|
|
||||||
|
const tgba_bdd_core_data& in = from.get_core_data();
|
||||||
|
|
||||||
|
data_.relation = bdd_replace(in.relation, rewrite);
|
||||||
|
data_.now_set = bdd_replace(in.now_set, rewrite);
|
||||||
|
data_.negnow_set = bdd_replace(in.negnow_set, rewrite);
|
||||||
|
data_.notnow_set = bdd_replace(in.notnow_set, rewrite);
|
||||||
|
data_.notvar_set = bdd_replace(in.notvar_set, rewrite);
|
||||||
|
data_.notprom_set = bdd_replace(in.notprom_set, rewrite);
|
||||||
|
|
||||||
|
init_ = bdd_replace(from.get_init_state().as_bdd(), rewrite);
|
||||||
|
|
||||||
|
bdd_freepair(rewrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
tgba_bdd_translate_factory::~tgba_bdd_translate_factory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bddPair*
|
||||||
|
tgba_bdd_translate_factory::compute_pairs(const tgba_bdd_dict& from)
|
||||||
|
{
|
||||||
|
bddPair* rewrite = bdd_newpair();
|
||||||
|
|
||||||
|
tgba_bdd_dict::fv_map::const_iterator i_from;
|
||||||
|
tgba_bdd_dict::fv_map::const_iterator i_to;
|
||||||
|
|
||||||
|
from.dump(std::cerr);
|
||||||
|
|
||||||
|
for (i_from = from.now_map.begin(); i_from != from.now_map.end(); ++i_from)
|
||||||
|
{
|
||||||
|
i_to = dict_.now_map.find(i_from->first);
|
||||||
|
assert(i_to != dict_.now_map.end());
|
||||||
|
|
||||||
|
bdd_setpair(rewrite, i_from->second, i_to->second);
|
||||||
|
bdd_setpair(rewrite, i_from->second + 1, i_to->second + 1);
|
||||||
|
bdd_setpair(data_.next_to_now, i_to->second + 1, i_to->second);
|
||||||
|
}
|
||||||
|
for (i_from = from.var_map.begin(); i_from != from.var_map.end(); ++i_from)
|
||||||
|
{
|
||||||
|
i_to = dict_.var_map.find(i_from->first);
|
||||||
|
assert(i_to != dict_.var_map.end());
|
||||||
|
bdd_setpair(rewrite, i_from->second, i_to->second);
|
||||||
|
}
|
||||||
|
for (i_from = from.prom_map.begin();
|
||||||
|
i_from != from.prom_map.end();
|
||||||
|
++i_from)
|
||||||
|
{
|
||||||
|
i_to = dict_.prom_map.find(i_from->first);
|
||||||
|
assert(i_to != dict_.prom_map.end());
|
||||||
|
bdd_setpair(rewrite, i_from->second, i_to->second);
|
||||||
|
}
|
||||||
|
return rewrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_core_data&
|
||||||
|
tgba_bdd_translate_factory::get_core_data() const
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tgba_bdd_dict&
|
||||||
|
tgba_bdd_translate_factory::get_dict() const
|
||||||
|
{
|
||||||
|
return dict_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdd
|
||||||
|
tgba_bdd_translate_factory::get_init_state() const
|
||||||
|
{
|
||||||
|
return init_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tgba_bdd_concrete
|
||||||
|
defrag(const tgba_bdd_concrete& a)
|
||||||
|
{
|
||||||
|
const tgba_bdd_dict& ad = a.get_dict();
|
||||||
|
tgba_bdd_dict u = tgba_bdd_dict_union(ad, ad);
|
||||||
|
tgba_bdd_translate_factory f(a, u);
|
||||||
|
return tgba_bdd_concrete(f, f.get_init_state());
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/tgba/tgbabddtranslatefactory.hh
Normal file
34
src/tgba/tgbabddtranslatefactory.hh
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef SPOT_TGBA_TGBABDDTRANSLATEFACTORY_HH
|
||||||
|
# define SPOT_TGBA_TGBABDDTRANSLATEFACTORY_HH
|
||||||
|
|
||||||
|
#include "tgbabddfactory.hh"
|
||||||
|
#include "tgbabddconcrete.hh"
|
||||||
|
|
||||||
|
namespace spot
|
||||||
|
{
|
||||||
|
|
||||||
|
class tgba_bdd_translate_factory: public tgba_bdd_factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tgba_bdd_translate_factory(const tgba_bdd_concrete& from,
|
||||||
|
const tgba_bdd_dict& to);
|
||||||
|
|
||||||
|
virtual ~tgba_bdd_translate_factory();
|
||||||
|
|
||||||
|
bddPair* compute_pairs(const tgba_bdd_dict& from);
|
||||||
|
|
||||||
|
const tgba_bdd_core_data& get_core_data() const;
|
||||||
|
const tgba_bdd_dict& get_dict() const;
|
||||||
|
|
||||||
|
bdd get_init_state() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tgba_bdd_core_data data_;
|
||||||
|
tgba_bdd_dict dict_;
|
||||||
|
bdd init_;
|
||||||
|
};
|
||||||
|
|
||||||
|
tgba_bdd_concrete defrag(const tgba_bdd_concrete& a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SPOT_TGBA_TGBABDDTRANSLATEFACTORY_HH
|
||||||
Loading…
Add table
Add a link
Reference in a new issue