spot/src/tgbaalgos/lbtt.cc
Alexandre Duret-Lutz e341cc9ab6 * iface/gspn/eesrg.cc, iface/gspn/eesrg.hh, iface/gspn/gspn.cc,
iface/gspn/gspn.hh, src/tgba/bdddict.cc, src/tgba/bdddict.hh,
src/tgba/bddprint.hh, src/tgba/succiter.hh,
src/tgba/succiterconcrete.cc, src/tgba/succiterconcrete.hh,
src/tgba/tgba.hh, src/tgba/tgbabddconcrete.cc,
src/tgba/tgbabddconcrete.hh, src/tgba/tgbabddconcretefactory.cc,
src/tgba/tgbabddconcretefactory.hh, src/tgba/tgbabddcoredata.cc,
src/tgba/tgbabddcoredata.hh, src/tgba/tgbaexplicit.cc,
src/tgba/tgbaexplicit.hh, src/tgba/tgbaproduct.cc,
src/tgba/tgbaproduct.hh, src/tgba/tgbatba.cc, src/tgba/tgbatba.hh,
src/tgbaalgos/dotty.cc, src/tgbaalgos/dupexp.cc,
src/tgbaalgos/emptinesscheck.cc, src/tgbaalgos/emptinesscheck.hh,
src/tgbaalgos/lbtt.cc, src/tgbaalgos/lbtt.hh,
src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/ltl2tgba_lacim.cc,
src/tgbaalgos/save.cc, src/tgbatest/explicit.cc,
src/tgbatest/ltl2tgba.cc, src/tgbaparse/tgbaparse.yy,
wrap/python/tests/ltl2tgba.py:
Rewrite `accepting condition' as `acceptance condition'.
The symbols which have been renamed are:
tgba::all_accepting_conditions
tgba::neg_accepting_conditions
succ_iterator::current_accepting_conditions
bdd_dict::register_accepting_variable
bdd_dict::register_accepting_variables
bdd_dict::is_registered_accepting_variable
tgba_bdd_concrete_factory::declare_accepting_condition
tgba_bdd_core_data::accepting_conditions
tgba_bdd_core_data::all_accepting_conditions
tgba_explicit::declare_accepting_condition
tgba_explicit::complement_all_accepting_conditions
tgba_explicit::has_accepting_condition
tgba_explicit::get_accepting_condition
tgba_explicit::add_accepting_condition
tgba_explicit::all_accepting_conditions
tgba_explicit::neg_accepting_conditions
state_tba_proxy::acceptance_cond
accepting_cond_splitter
2003-11-28 16:34:42 +00:00

280 lines
8 KiB
C++

// Copyright (C) 2003 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 "misc/hash.hh"
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <functional>
#include "tgba/tgba.hh"
#include "save.hh"
#include "tgba/bddprint.hh"
#include "ltlvisit/tostring.hh"
#include "tgba/bddprint.hh"
#include "misc/bddlt.hh"
namespace spot
{
// At some point we'll need to print an acceptance set into LBTT's
// format. LBTT expects numbered acceptance sets, so first we'll
// number each acceptance condition, and latter when we have to print
// them we'll just have to look up each of them.
class acceptance_cond_splitter
{
public:
acceptance_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 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, acceptance set) pair for the source automata.
typedef std::pair<state*, bdd> state_acc_pair;
struct state_acc_pair_equal :
public std::binary_function<const state_acc_pair&,
const state_acc_pair&, bool>
{
bool
operator()(const state_acc_pair& left, const state_acc_pair& right) const
{
if (left.first->compare(right.first))
return false;
return left.second.id() == right.second.id();
}
};
struct state_acc_pair_hash :
public std::unary_function<const state_acc_pair&, size_t>
{
bool
operator()(const state_acc_pair& that) const
{
// We assume there will be far more states than acceptance conditions.
// Hence we keep only 8 bits for the latter.
return (that.first->hash() << 8) + (that.second.id() & 0xFF);
}
};
// Each state of the produced automata is numbered. Map of state seen.
typedef Sgi::hash_map<state_acc_pair, unsigned, state_acc_pair_hash,
state_acc_pair_equal> acp_seen_map;
// Set of states yet to produce.
typedef Sgi::hash_set<state_acc_pair, state_acc_pair_hash,
state_acc_pair_equal> todo_set;
// Each *source* state corresponds to several states in the produced
// automata. A minmax_pair specifies the range of such associated states.
typedef std::pair<unsigned, unsigned> minmax_pair;
typedef Sgi::hash_map<state*, minmax_pair,
state_ptr_hash, state_ptr_equal> seen_map;
// Take a STATE from the source automaton, and fill TODO with
// the list of associated states to output. Return the correponding
// range in MMP. Update SEEN, ACP_SEEN, and STATE_NUMBER.
//
// INIT must be set to true when registering the initial state.
// This allows us to create an additional state if required. (LBTT
// supports only one initial state, so whenever the initial state
// of the source automaton has to be split, we need to create
// a supplementary state, to act as initial state for LBTT.)
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,
bool init)
{
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 acceptance
// 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_acceptance_conditions());
}
// Order the creation of the supplementary initial state if needed.
// Use bddtrue as acceptance condition because it cannot conflict
// with other (state, acceptance cond) pairs in the maps.
if (init && acc_seen.size() > 1)
{
state_acc_pair p(state, bddtrue);
todo.insert(p);
acp_seen[p] = state_number++;
}
// Order the creation of normal states.
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 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, true);
acceptance_cond_splitter acs(g->all_acceptance_conditions());
while(! todo.empty())
{
state_acc_pair sap = *todo.begin();
todo.erase(todo.begin());
unsigned number = acp_seen[sap];
// number == 0 is the initial state. bddtrue as an acceptance
// conditions indicates a "fake" initial state introduced
// because the original initial state was split into many
// states (with different acceptance conditions).
// As this "fake" state has no input transitions, there is
// no point in computing any acceptance conditions.
body << number << (number ? " 0 " : " 1 ");
if (sap.second != bddtrue)
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 acceptance conditions on the state,
// so draw only outgoing transition with these acceptance
// conditions.
if (sap.second != bddtrue
&& si->current_acceptance_conditions() != sap.second)
continue;
minmax_pair destrange;
fill_todo(todo, seen, acp_seen,
si->current_state(), g, destrange, state_number, false);
// 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 << 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.
seen_map::const_iterator s = seen.begin();
while (s != seen.end())
{
// Advance the iterator before deleting the "key" pointer.
const state* ptr = s->first;
++s;
delete ptr;
}
return os;
}
}