Commit f9c8eb1c authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

* src/tgbatest/ltl2tgba.cc: Add option -t to output the LBTT automata.

* src/tgbaalgos/lbtt.cc, src/tgbaalgos/lbtt.hh: New files.
* src/tgbaalgos/Makefile.am (tgbaalgos_HEADERS): Add lbtt.hh.
(libtgbaalgos_la_SOURCES): Add lbtt.cc.
* src/tgba/bddprint.cc (print_sat_handler): Put a space after "!".
* src/tgbatest/readsave.test: Adjust spaces after "!".
parent a307c0d0
2003-07-08 Alexandre Duret-Lutz <aduret@src.lip6.fr>
* src/tgbatest/ltl2tgba.cc: Add option -t to output the LBTT automata.
* src/tgbaalgos/lbtt.cc, src/tgbaalgos/lbtt.hh: New files.
* src/tgbaalgos/Makefile.am (tgbaalgos_HEADERS): Add lbtt.hh.
(libtgbaalgos_la_SOURCES): Add lbtt.cc.
* src/tgba/bddprint.cc (print_sat_handler): Put a space after "!".
* src/tgbatest/readsave.test: Adjust spaces after "!".
* src/ltlvisit/dump.cc: Strip useless spot::ltl:: prefixes.
2003-07-07 Alexandre Duret-Lutz <aduret@src.lip6.fr>
......
......@@ -73,7 +73,8 @@ namespace spot
else
not_first = true;
if (varset[v] == 0)
*where << "!";
// The space is important for LBTT.
*where << "! ";
print_handler(*where, v);
}
}
......
......@@ -5,11 +5,13 @@ tgbaalgosdir = $(pkgincludedir)/tgbaalgos
tgbaalgos_HEADERS = \
dotty.hh \
lbtt.hh \
ltl2tgba.hh \
save.hh
noinst_LTLIBRARIES = libtgbaalgos.la
libtgbaalgos_la_SOURCES = \
dotty.cc \
lbtt.cc \
ltl2tgba.cc \
save.cc
#include <map>
#include <set>
#include <string>
#include <sstream>
#include "tgba/tgba.hh"
#include "save.hh"
#include "tgba/bddprint.hh"
#include "ltlvisit/tostring.hh"
#include "tgba/bddprint.hh"
namespace spot
{
struct bdd_less_than
{
bool
operator()(const bdd& left, const bdd& right) const
{
return left.id() < right.id();
}
};
// At some point we'll need to print an accepting set into LBTT's
// forma. LBTT expect numbered accepting sets, so first we'll
// number each accepting condition, and latter when we have to print
// them we'll just have to look up each of them.
class accepting_cond_splitter
{
public:
accepting_cond_splitter(bdd all_acc)
{
unsigned count = 0;
while (all_acc != bddfalse)
{
bdd acc = bdd_satone(all_acc);
all_acc &= !acc;
sm[acc] = count++;
}
}
std::ostream&
split(std::ostream& os, bdd b)
{
while (b != bddfalse)
{
bdd acc = bdd_satone(b);
b &= !acc;
os << sm[acc] << " ";
}
return os;
}
unsigned
count() const
{
return sm.size();
}
private:
typedef std::map<bdd, unsigned, bdd_less_than> split_map;
split_map sm;
};
// Convert a BDD formula to the syntax used by LBTT's transition guards.
// Conjunctions are printed by bdd_format_sat, so we just have
// to handle the other cases.
static std::string
bdd_to_lbtt(bdd b, const tgba_bdd_dict& d)
{
if (b == bddfalse)
return "f";
else if (b == bddtrue)
return "t";
else
{
bdd cube = bdd_satone(b);
b &= !cube;
if (b != bddfalse)
{
return "| " + bdd_to_lbtt(b, d) + " " + bdd_to_lbtt(cube, d);
}
else
{
std::string res = "";
for (int count = bdd_nodecount(cube); count > 1; --count)
res += "& ";
return res + bdd_format_sat(d, cube);
}
}
}
// Each state in the produced automata corresponds to
// a (state, accepting set) pair for the source automata.
typedef std::pair<state*, bdd> state_acc_pair;
struct state_acc_pair_less_than
{
bool
operator()(const state_acc_pair& left, const state_acc_pair& right) const
{
int cmp = left.first->compare(right.first);
if (cmp < 0)
return true;
if (cmp > 0)
return false;
return left.second.id() < right.second.id();
}
};
// Each state of the produced automata is numbered. Map of state seen.
typedef std::map<state_acc_pair, unsigned, state_acc_pair_less_than> acp_seen_map;
// Set of states yet to produce.
typedef std::set<state_acc_pair, state_acc_pair_less_than> todo_set;
// Each *source* car correspond to several state in the produced
// automate. A minmax_pair specify the range of such associated states.
typedef std::pair<unsigned, unsigned> minmax_pair;
typedef std::map<state*, minmax_pair, state_ptr_less_than> seen_map;
// Take a STATE from the source automata, and fill TODO with
// the list of associated states to output. Return the correponding
// range in MMP. Update SEEN, ACP_SEEN, and STATE_NUMBER.
void
fill_todo(todo_set& todo, seen_map& seen, acp_seen_map& acp_seen,
state* state, const tgba& g,
minmax_pair& mmp, unsigned& state_number)
{
typedef std::set<bdd, bdd_less_than> bdd_set;
seen_map::iterator i = seen.find(state);
if (i != seen.end())
{
mmp = i->second;
delete state;
return;
}
// Browse the successors of STATE to gather accepting
// conditions of outgoing transitions.
bdd_set acc_seen;
tgba_succ_iterator* si = g.succ_iter(state);
for (si->first(); !si->done(); si->next())
{
acc_seen.insert(si->current_accepting_conditions());
}
mmp.first = state_number;
for (bdd_set::iterator i = acc_seen.begin(); i != acc_seen.end(); ++i)
{
state_acc_pair p(state, *i);
todo.insert(p);
acp_seen[p] = state_number++;
}
mmp.second = state_number;
seen[state] = mmp;
}
std::ostream&
lbtt_reachable(std::ostream& os, const tgba& g)
{
const tgba_bdd_dict& d = g.get_dict();
std::ostringstream body;
seen_map seen;
acp_seen_map acp_seen;
todo_set todo;
unsigned state_number = 0;
minmax_pair mmp;
fill_todo(todo, seen, acp_seen,
g.get_init_state(), g, mmp, state_number);
accepting_cond_splitter acs(g.all_accepting_conditions());
while(! todo.empty())
{
state_acc_pair sap = *todo.begin();
todo.erase(todo.begin());
unsigned number = acp_seen[sap];
body << number << " "
// Mark the initial state.
<< ((number >= mmp.first && number < mmp.second) ? 1 : 0) << " ";
acs.split(body, sap.second);
body << "-1" << std::endl;
tgba_succ_iterator* si = g.succ_iter(sap.first);
for (si->first(); !si->done(); si->next())
{
// We have put the accepting conditions on the state,
// so draw only outgoing transition with these accepting
// conditions.
if (si->current_accepting_conditions() != sap.second)
continue;
minmax_pair destrange;
fill_todo(todo, seen, acp_seen,
si->current_state(), g, destrange, state_number);
// Link to all instances of the successor.
std::string s = bdd_to_lbtt(si->current_condition(), d);
for (unsigned i = destrange.first; i < destrange.second; ++i)
{
body << i << " " << s << " " << "-1" << std::endl;
}
}
body << "-1" << std::endl;
delete si;
}
os << state_number << " " << acs.count() << std::endl;
os << body.str();
// Finally delete all states used as keys in m:
for (seen_map::iterator i = seen.begin(); i != seen.end(); ++i)
delete i->first;
return os;
}
}
#ifndef SPOT_TGBAALGOS_LBTT_HH
# define SPOT_TGBAALGOS_LBTT_HH
#include "tgba/tgba.hh"
#include <iostream>
namespace spot
{
/// \brief Print reachable states in LBTT format.
///
/// Note that LBTT expects an automaton with transition
/// labeled by propositional formulae, and generalized
/// Büchi accepting conditions on \emph states. This
/// is unlike our spot::tgba automata which put
/// botg generalized accepting conditions and propositional
/// formulae) on \emph transitions.
///
/// This algorithm will therefore produce an automata
/// where accepting conditions have been moved from
/// each transition to previous state. In the worst
/// case, doing so will multiply the number of states
/// and transitions of the automata by <code>2^|Acc|</code>.
/// where <code>|Acc|</code> is the number of accepting
/// conditions used by the automata. You have been warned.
///
/// \param g The automata to print.
/// \param os Where to print.
std::ostream& lbtt_reachable(std::ostream& os, const tgba& g);
}
#endif // SPOT_TGBAALGOS_LBTT_HH
......@@ -7,6 +7,7 @@
#include "tgba/bddprint.hh"
#include "tgba/tgbabddtranslatefactory.hh"
#include "tgbaalgos/dotty.hh"
#include "tgbaalgos/lbtt.hh"
void
syntax(char* prog)
......@@ -19,10 +20,10 @@ syntax(char* prog)
<< " -A same as -a, but as a set" << std::endl
<< " -d turn on traces during parsing" << std::endl
<< " -o re-order BDD variables in the automata" << std::endl
<< std::endl
<< " -r display the relation BDD, not the reachability graph"
<< std::endl
<< " -R same as -r, but as a set" << std::endl
<< " -t display reachable states in LBTT's format" << std::endl
<< " -v display the BDD variables used by the automaton"
<< std::endl;
exit(2);
......@@ -69,6 +70,10 @@ main(int argc, char** argv)
{
output = 3;
}
else if (!strcmp(argv[formula_index], "-t"))
{
output = 6;
}
else if (!strcmp(argv[formula_index], "-v"))
{
output = 5;
......@@ -118,6 +123,9 @@ main(int argc, char** argv)
case 5:
a.get_dict().dump(std::cout);
break;
case 6:
spot::lbtt_reachable(std::cout, a);
break;
default:
assert(!"unknown output option");
}
......
......@@ -15,7 +15,7 @@ EOF
cat >expected <<EOF
acc = "c" "d";
"s1", "s2", a !b, "c" "d";
"s1", "s2", a ! b, "c" "d";
"s2", "state 3", a, "c";
"state 3", "s1", ,;
EOF
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment