powerset: use tgba_digraph instead of tgba_explicit_number.

* src/tgbaalgos/powerset.cc, src/tgbaalgos/powerset.hh:
Use tgba_digraph.
* src/tgba/tgbagraph.hh: Improve interface.
* src/tgbaalgos/minimize.cc, src/tgbatest/powerset.cc: Adjust.
This commit is contained in:
Alexandre Duret-Lutz 2014-07-07 18:57:43 +02:00
parent 7602bd1a37
commit d80a7cd9bd
5 changed files with 59 additions and 54 deletions

View file

@ -77,7 +77,7 @@ namespace spot
{ {
} }
tgba_graph_trans_data(bdd cond, bdd acc) tgba_graph_trans_data(bdd cond, bdd acc = bddfalse)
: cond(cond), acc(acc) : cond(cond), acc(acc)
{ {
} }
@ -162,7 +162,10 @@ namespace spot
public: public:
tgba_digraph(bdd_dict* dict) tgba_digraph(bdd_dict* dict)
: dict_(dict), init_(nullptr) : dict_(dict),
all_acceptance_conditions_(bddfalse),
neg_acceptance_conditions_(bddtrue),
init_(nullptr)
{ {
} }

View file

@ -209,7 +209,7 @@ namespace spot
bool bool
wdba_scc_is_accepting(const tgba_explicit_number* det_a, unsigned scc_n, wdba_scc_is_accepting(const tgba_digraph* det_a, unsigned scc_n,
const tgba* orig_a, scc_map& sm, power_map& pm) const tgba* orig_a, scc_map& sm, power_map& pm)
{ {
// Get some state from the SCC #n. // Get some state from the SCC #n.
@ -244,24 +244,25 @@ namespace spot
bool accepting = false; bool accepting = false;
// Iterate on each original state corresponding to start. // Iterate on each original state corresponding to start.
const power_map::power_state& ps = pm.states_of(det_a->get_label(start)); const power_map::power_state& ps =
for (power_map::power_state::const_iterator it = ps.begin(); pm.states_of(det_a->state_number(start));
it != ps.end() && !accepting; ++it) for (auto& it: ps)
{ {
// Contrustruct a product between // Contrustruct a product between
// LOOP_A, and ORIG_A starting in *IT. // LOOP_A, and ORIG_A starting in *IT.
tgba* p = new tgba_product_init(&loop_a, orig_a, tgba* p = new tgba_product_init(&loop_a, orig_a, loop_a_init, it);
loop_a_init, *it);
emptiness_check* ec = couvreur99(p); emptiness_check* ec = couvreur99(p);
emptiness_check_result* res = ec->check(); emptiness_check_result* res = ec->check();
if (res)
accepting = true;
delete res; delete res;
delete ec; delete ec;
delete p; delete p;
if (res)
{
accepting = true;
break;
}
} }
loop_a_init->destroy(); loop_a_init->destroy();
@ -270,7 +271,7 @@ namespace spot
} }
sba_explicit_number* minimize_dfa(const tgba_explicit_number* det_a, sba_explicit_number* minimize_dfa(const tgba_digraph* det_a,
hash_set* final, hash_set* non_final) hash_set* final, hash_set* non_final)
{ {
typedef std::list<hash_set*> partition_t; typedef std::list<hash_set*> partition_t;
@ -481,7 +482,7 @@ namespace spot
{ {
hash_set* final = new hash_set; hash_set* final = new hash_set;
hash_set* non_final = new hash_set; hash_set* non_final = new hash_set;
tgba_explicit_number* det_a; tgba_digraph* det_a;
{ {
power_map pm; power_map pm;
@ -500,7 +501,7 @@ namespace spot
hash_set* final = new hash_set; hash_set* final = new hash_set;
hash_set* non_final = new hash_set; hash_set* non_final = new hash_set;
tgba_explicit_number* det_a; tgba_digraph* det_a;
{ {
power_map pm; power_map pm;

View file

@ -42,7 +42,7 @@
namespace spot namespace spot
{ {
tgba_explicit_number* tgba_digraph*
tgba_powerset(const tgba* aut, power_map& pm, bool merge) tgba_powerset(const tgba* aut, power_map& pm, bool merge)
{ {
typedef power_map::power_state power_state; typedef power_map::power_state power_state;
@ -51,19 +51,22 @@ namespace spot
power_set seen; power_set seen;
todo_list todo; todo_list todo;
tgba_explicit_number* res = new tgba_explicit_number(aut->get_dict()); auto d = aut->get_dict();
auto res = new tgba_digraph(d);
d->register_all_variables_of(aut, res);
d->unregister_all_typed_variables(bdd_dict::acc, res);
auto& g = res->get_graph();
{ {
power_state ps; power_state ps;
const state* s = pm.canonicalize(aut->get_init_state()); const state* s = pm.canonicalize(aut->get_init_state());
ps.insert(s); ps.insert(s);
todo.push_back(ps); todo.push_back(ps);
seen[ps] = 1; unsigned num = g.new_state();
pm.map_[1] = ps; seen[ps] = num;
pm.map_[num] = ps;
} }
unsigned state_num = 1;
while (!todo.empty()) while (!todo.empty())
{ {
power_state src = todo.front(); power_state src = todo.front();
@ -92,21 +95,18 @@ namespace spot
// Add that transition. // Add that transition.
power_set::const_iterator i = seen.find(dest); power_set::const_iterator i = seen.find(dest);
int dest_num; int dest_num;
state_explicit_number::transition* t;
if (i != seen.end()) if (i != seen.end())
{ {
dest_num = i->second; dest_num = i->second;
t = res->create_transition(seen[src], dest_num);
} }
else else
{ {
dest_num = ++state_num; dest_num = g.new_state();
seen[dest] = dest_num; seen[dest] = dest_num;
pm.map_[dest_num] = dest; pm.map_[dest_num] = dest;
todo.push_back(dest); todo.push_back(dest);
t = res->create_transition(seen[src], dest_num);
} }
res->add_conditions(t, cond); g.new_transition(seen[src], dest_num, cond);
} }
} }
if (merge) if (merge)
@ -114,7 +114,7 @@ namespace spot
return res; return res;
} }
tgba_explicit_number* tgba_digraph*
tgba_powerset(const tgba* aut) tgba_powerset(const tgba* aut)
{ {
power_map pm; power_map pm;
@ -129,7 +129,7 @@ namespace spot
{ {
public: public:
typedef dfs_stack::const_iterator cycle_iter; typedef dfs_stack::const_iterator cycle_iter;
typedef state_explicit_number::transition trans; typedef tgba_graph_trans_data trans;
typedef std::set<trans*> trans_set; typedef std::set<trans*> trans_set;
typedef std::vector<trans_set> set_set; typedef std::vector<trans_set> set_set;
protected: protected:
@ -170,31 +170,32 @@ namespace spot
bdd acc = aut_->all_acceptance_conditions(); bdd acc = aut_->all_acceptance_conditions();
for (auto i: all_) for (auto i: all_)
i->acceptance_conditions = acc; i->acc = acc;
return threshold_ != 0 && cycles_left_ == 0; return threshold_ != 0 && cycles_left_ == 0;
} }
bool is_cycle_accepting(cycle_iter begin, trans_set& ts) const bool is_cycle_accepting(cycle_iter begin, trans_set& ts) const
{ {
tgba_explicit_number* a = auto a = down_cast<tgba_digraph*>(const_cast<tgba*>(aut_));
down_cast<tgba_explicit_number*>(const_cast<tgba*>(aut_));
// Build an automaton representing this loop. // Build an automaton representing this loop.
tgba_explicit_number loop_a(aut_->get_dict()); tgba_digraph loop_a(aut_->get_dict());
auto& g = loop_a.get_graph();
int loop_size = std::distance(begin, dfs_.end()); int loop_size = std::distance(begin, dfs_.end());
g.new_states(loop_size);
int n; int n;
cycle_iter i; cycle_iter i;
for (n = 1, i = begin; n <= loop_size; ++n, ++i) for (n = 1, i = begin; n <= loop_size; ++n, ++i)
{ {
trans* t = a->get_transition(i->succ); trans* t = &a->trans_data(i->succ);
loop_a.create_transition(n - 1, n % loop_size)->condition = g.new_transition(n - 1, n % loop_size, t->cond);
t->condition;
if (reject_.find(t) == reject_.end()) if (reject_.find(t) == reject_.end())
ts.insert(t); ts.insert(t);
} }
assert(i == dfs_.end()); assert(i == dfs_.end());
const state* loop_a_init = loop_a.get_init_state(); const state* loop_a_init = loop_a.get_init_state();
assert(loop_a.get_label(loop_a_init) == 0); assert(loop_a.state_number(loop_a_init) == 0);
// Check if the loop is accepting in the original automaton. // Check if the loop is accepting in the original automaton.
bool accepting = false; bool accepting = false;
@ -202,7 +203,7 @@ namespace spot
// Iterate on each original state corresponding to the // Iterate on each original state corresponding to the
// start of the loop in the determinized automaton. // start of the loop in the determinized automaton.
const power_map::power_state& ps = const power_map::power_state& ps =
refmap_.states_of(a->get_label(begin->ts->first)); refmap_.states_of(a->state_number(begin->ts->first));
for (auto s: ps) for (auto s: ps)
{ {
// Construct a product between // Construct a product between
@ -213,13 +214,14 @@ namespace spot
couvreur99_check* ec = down_cast<couvreur99_check*>(couvreur99(p)); couvreur99_check* ec = down_cast<couvreur99_check*>(couvreur99(p));
assert(ec); assert(ec);
emptiness_check_result* res = ec->check(); emptiness_check_result* res = ec->check();
if (res)
accepting = true;
delete res; delete res;
delete ec; delete ec;
delete p; delete p;
if (accepting) if (res)
break; {
accepting = true;
break;
}
} }
loop_a_init->destroy(); loop_a_init->destroy();
@ -277,7 +279,7 @@ namespace spot
}; };
static bool static bool
fix_dba_acceptance(tgba_explicit_number* det, fix_dba_acceptance(tgba_digraph* det,
const tgba* ref, power_map& refmap, const tgba* ref, power_map& refmap,
unsigned threshold) unsigned threshold)
{ {
@ -298,7 +300,7 @@ namespace spot
} }
} }
tgba_explicit_number* tgba_digraph*
tba_determinize(const tgba* aut, tba_determinize(const tgba* aut,
unsigned threshold_states, unsigned threshold_cycles) unsigned threshold_states, unsigned threshold_cycles)
{ {
@ -306,7 +308,7 @@ namespace spot
// Do not merge transitions in the deterministic automaton. If we // Do not merge transitions in the deterministic automaton. If we
// add two self-loops labeled by "a" and "!a", we do not want // add two self-loops labeled by "a" and "!a", we do not want
// these to be merged as "1" before the acceptance has been fixed. // these to be merged as "1" before the acceptance has been fixed.
tgba_explicit_number* det = tgba_powerset(aut, pm, false); auto det = tgba_powerset(aut, pm, false);
if ((threshold_states > 0) if ((threshold_states > 0)
&& (pm.map_.size() > pm.states_.size() * threshold_states)) && (pm.map_.size() > pm.states_.size() * threshold_states))
@ -336,8 +338,7 @@ namespace spot
if (aut->number_of_acceptance_conditions() > 1) if (aut->number_of_acceptance_conditions() > 1)
return 0; return 0;
tgba_explicit_number* det = auto det = tba_determinize(aut, threshold_states, threshold_cycles);
tba_determinize(aut, threshold_states, threshold_cycles);
if (!det) if (!det)
return 0; return 0;

View file

@ -25,7 +25,7 @@
# include <list> # include <list>
# include <map> # include <map>
# include "tgba/tgbaexplicit.hh" # include "tgba/tgbagraph.hh"
namespace spot namespace spot
{ {
@ -33,12 +33,12 @@ namespace spot
struct SPOT_API power_map struct SPOT_API power_map
{ {
typedef std::set<const state*, state_ptr_less_than> power_state; typedef std::set<const state*, state_ptr_less_than> power_state;
typedef std::map<int, power_state> power_map_data; typedef std::map<unsigned, power_state> power_map_data;
const power_state& const power_state&
states_of(int s) const states_of(unsigned s) const
{ {
return map_.find(s)->second; return map_.at(s);
} }
const state* const state*
@ -64,9 +64,9 @@ namespace spot
/// The \a merge argument can be set to false to prevent merging of /// The \a merge argument can be set to false to prevent merging of
/// transitions. /// transitions.
//@{ //@{
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tgba_powerset(const tgba* aut, power_map& pm, bool merge = true); tgba_powerset(const tgba* aut, power_map& pm, bool merge = true);
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tgba_powerset(const tgba* aut); tgba_powerset(const tgba* aut);
//@} //@}
@ -106,7 +106,7 @@ namespace spot
/// If \a threshold_cycles is non null, abort the construction /// If \a threshold_cycles is non null, abort the construction
/// whenever an SCC of the constructed automaton has more than \a /// whenever an SCC of the constructed automaton has more than \a
/// threshold_cycles cycles. /// threshold_cycles cycles.
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tba_determinize(const tgba* aut, tba_determinize(const tgba* aut,
unsigned threshold_states = 0, unsigned threshold_states = 0,
unsigned threshold_cycles = 0); unsigned threshold_cycles = 0);

View file

@ -55,7 +55,7 @@ main(int argc, char** argv)
#ifndef DOTTY #ifndef DOTTY
spot::tgba_explicit_number* e = spot::tgba_powerset(a); auto e = spot::tgba_powerset(a);
spot::tgba_save_reachable(std::cout, e); spot::tgba_save_reachable(std::cout, e);
delete e; delete e;
#else #else