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

dupexp, simulation: use tgba_digraph.

* src/tgbaalgos/dupexp.cc, src/tgbaalgos/dupexp.hh: Produce
a tgba_digraph instead of a tgba_explicit_number.
* src/tgbaalgos/simulation.cc: First pass to adjust to the use of
tgba_digraph as a return of tgba_dupexp_dfs() and tgba_dupexp_bfs().
Some maps have been replaced by vectors because states are indexed,
but more simplifications could be done.
parent 1f70e674
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2009, 2011, 2012 Laboratoire de Recherche et // Copyright (C) 2009, 2011, 2012, 2014 Laboratoire de Recherche et
// Développement de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004 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
...@@ -35,29 +35,38 @@ namespace spot ...@@ -35,29 +35,38 @@ namespace spot
{ {
public: public:
dupexp_iter(const tgba* a) dupexp_iter(const tgba* a)
: T(a), out_(new tgba_explicit_number(a->get_dict())) : T(a), out_(new tgba_digraph(a->get_dict()))
{ {
out_->copy_acceptance_conditions_of(a); out_->copy_acceptance_conditions_of(a);
a->get_dict()->register_all_variables_of(a, out_);
} }
tgba_explicit_number* tgba_digraph*
result() result()
{ {
return out_; return out_;
} }
void virtual void
process_state(const state*, int n, tgba_succ_iterator*)
{
unsigned ns = out_->get_graph().new_state();
assert(ns == static_cast<unsigned>(n) - 1);
(void)ns;
}
virtual void
process_link(const state*, int in, process_link(const state*, int in,
const state*, int out, const state*, int out,
const tgba_succ_iterator* si) const tgba_succ_iterator* si)
{ {
state_explicit_number::transition* t = out_->create_transition(in, out); out_->get_graph().new_transition(in - 1, out - 1,
out_->add_conditions(t, si->current_condition()); si->current_condition(),
out_->add_acceptance_conditions(t, si->current_acceptance_conditions()); si->current_acceptance_conditions());
} }
protected: protected:
tgba_explicit_number* out_; tgba_digraph* out_;
}; };
template <typename T> template <typename T>
...@@ -68,14 +77,16 @@ namespace spot ...@@ -68,14 +77,16 @@ namespace spot
std::map<const state*, std::map<const state*,
const state*, const state*,
state_ptr_less_than>& relation) state_ptr_less_than>& relation)
: dupexp_iter<T>(a), : dupexp_iter<T>(a), relation_(relation)
relation_(relation)
{ {
} }
void process_state(const state* s, int n, tgba_succ_iterator*) virtual void
end()
{ {
relation_[this->out_->add_state(n)] = const_cast<state*>(s); for (auto s: this->seen)
relation_[this->out_->state_from_number(s.second - 1)]
= const_cast<state*>(s.first);
} }
std::map<const state*, const state*, state_ptr_less_than>& relation_; std::map<const state*, const state*, state_ptr_less_than>& relation_;
...@@ -83,7 +94,7 @@ namespace spot ...@@ -83,7 +94,7 @@ namespace spot
} // anonymous } // anonymous
tgba_explicit_number* tgba_digraph*
tgba_dupexp_bfs(const tgba* aut) tgba_dupexp_bfs(const tgba* aut)
{ {
dupexp_iter<tgba_reachable_iterator_breadth_first> di(aut); dupexp_iter<tgba_reachable_iterator_breadth_first> di(aut);
...@@ -91,7 +102,7 @@ namespace spot ...@@ -91,7 +102,7 @@ namespace spot
return di.result(); return di.result();
} }
tgba_explicit_number* tgba_digraph*
tgba_dupexp_dfs(const tgba* aut) tgba_dupexp_dfs(const tgba* aut)
{ {
dupexp_iter<tgba_reachable_iterator_depth_first> di(aut); dupexp_iter<tgba_reachable_iterator_depth_first> di(aut);
...@@ -99,7 +110,7 @@ namespace spot ...@@ -99,7 +110,7 @@ namespace spot
return di.result(); return di.result();
} }
tgba_explicit_number* tgba_digraph*
tgba_dupexp_bfs(const tgba* aut, tgba_dupexp_bfs(const tgba* aut,
std::map<const state*, std::map<const state*,
const state*, state_ptr_less_than>& rel) const state*, state_ptr_less_than>& rel)
...@@ -110,7 +121,7 @@ namespace spot ...@@ -110,7 +121,7 @@ namespace spot
return di.result(); return di.result();
} }
tgba_explicit_number* tgba_digraph*
tgba_dupexp_dfs(const tgba* aut, tgba_dupexp_dfs(const tgba* aut,
std::map<const state*, std::map<const state*,
const state*, state_ptr_less_than>& rel) const state*, state_ptr_less_than>& rel)
......
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2012, 2013 Laboratoire de Recherche et Développement // Copyright (C) 2012, 2013, 2014 Laboratoire de Recherche et
// de l'Epita (LRDE). // Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris // Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC), // 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
// Université Pierre et Marie Curie. // Université Pierre et Marie Curie.
...@@ -23,32 +23,32 @@ ...@@ -23,32 +23,32 @@
#ifndef SPOT_TGBAALGOS_DUPEXP_HH #ifndef SPOT_TGBAALGOS_DUPEXP_HH
# define SPOT_TGBAALGOS_DUPEXP_HH # define SPOT_TGBAALGOS_DUPEXP_HH
# include "tgba/tgbaexplicit.hh" # include "tgba/tgbagraph.hh"
namespace spot namespace spot
{ {
/// \ingroup tgba_misc /// \ingroup tgba_misc
/// \brief Build an explicit automata from all states of \a aut, /// \brief Build an explicit automaton from all states of \a aut,
/// numbering states in bread first order as they are processed. /// numbering states in bread first order as they are processed.
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tgba_dupexp_bfs(const tgba* aut); tgba_dupexp_bfs(const tgba* aut);
/// \ingroup tgba_misc /// \ingroup tgba_misc
/// \brief Build an explicit automata from all states of \a aut, /// \brief Build an explicit automaton from all states of \a aut,
/// numbering states in depth first order as they are processed. /// numbering states in depth first order as they are processed.
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tgba_dupexp_dfs(const tgba* aut); tgba_dupexp_dfs(const tgba* aut);
/// \ingroup tgba_misc /// \ingroup tgba_misc
/// \brief Build an explicit automata from all states of \a aut, /// \brief Build an explicit automaton from all states of \a aut,
/// numbering states in bread first order as they are processed. /// numbering states in bread first order as they are processed.
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tgba_dupexp_bfs(const tgba* aut, tgba_dupexp_bfs(const tgba* aut,
std::map<const state*, const state*, std::map<const state*, const state*,
state_ptr_less_than>& relation); state_ptr_less_than>& relation);
/// \ingroup tgba_misc /// \ingroup tgba_misc
/// \brief Build an explicit automata from all states of \a aut, /// \brief Build an explicit automata from all states of \a aut,
/// numbering states in depth first order as they are processed. /// numbering states in depth first order as they are processed.
SPOT_API tgba_explicit_number* SPOT_API tgba_digraph*
tgba_dupexp_dfs(const tgba* aut, tgba_dupexp_dfs(const tgba* aut,
std::map<const state*, const state*, std::map<const state*, const state*,
state_ptr_less_than>& relation); state_ptr_less_than>& relation);
......
...@@ -103,14 +103,13 @@ namespace spot ...@@ -103,14 +103,13 @@ namespace spot
typedef std::unordered_map<const state*, bdd, typedef std::unordered_map<const state*, bdd,
state_ptr_hash, state_ptr_hash,
state_ptr_equal> map_state_bdd; state_ptr_equal> map_state_bdd;
typedef std::vector<bdd> vector_state_bdd;
typedef std::unordered_map<const state*, unsigned,
state_ptr_hash,
state_ptr_equal> map_state_unsigned;
typedef std::map<const state*, const state*, typedef std::map<const state*, const state*,
state_ptr_less_than> map_state_state; state_ptr_less_than> map_state_state;
typedef std::vector<const state*> vector_state_state;
// Get the list of state for each class. // Get the list of state for each class.
typedef std::map<bdd, std::list<const state*>, typedef std::map<bdd, std::list<const state*>,
...@@ -214,7 +213,7 @@ namespace spot ...@@ -214,7 +213,7 @@ namespace spot
// This class takes an automaton, and return a (maybe new) // This class takes an automaton, and return a (maybe new)
// automaton. If Cosimulation is equal to true, we create a new // automaton. If Cosimulation is equal to true, we create a new
// automaton. Otherwise, we create a new one. The returned // automaton. Otherwise, we reuse the input one. The returned
// automaton is similar to the old one, except that the acceptance // automaton is similar to the old one, except that the acceptance
// condition on the transitions are complemented. // condition on the transitions are complemented.
// There is a specialization below. // There is a specialization below.
...@@ -223,50 +222,46 @@ namespace spot ...@@ -223,50 +222,46 @@ namespace spot
public tgba_reachable_iterator_depth_first public tgba_reachable_iterator_depth_first
{ {
public: public:
acc_compl_automaton(const tgba* a) acc_compl_automaton(const tgba* a)
: tgba_reachable_iterator_depth_first(a), : tgba_reachable_iterator_depth_first(a),
size(0), ea_(down_cast<tgba_digraph*>(const_cast<tgba*>(a))),
ea_(down_cast<tgba_explicit_number*>(const_cast<tgba*>(a))), ac_(ea_->all_acceptance_conditions(),
ac_(ea_->all_acceptance_conditions(), ea_->neg_acceptance_conditions())
ea_->neg_acceptance_conditions()) {
{ assert(ea_);
assert(ea_); out_ = ea_;
out_ = ea_; }
}
void process_link(const state*, int,
void process_link(const state*, int, const state*, int,
const state*, int, const tgba_succ_iterator* si)
const tgba_succ_iterator* si) {
{ bdd& acc = ea_->trans_data(si).acc;
bdd acc = ac_.complement(si->current_acceptance_conditions()); acc = ac_.complement(acc);
}
typename tgba_explicit_number::transition* t =
ea_->get_transition(si);
virtual void
t->acceptance_conditions = acc; end()
} {
unsigned s = seen.size();
void process_state(const state* s, int, tgba_succ_iterator*) old_name_.resize(s);
{ for (unsigned i = 0; i < s; ++i)
++size; old_name_[i] = ea_->state_from_number(i);
previous_class_[s] = bddfalse; size = s;
old_name_[s] = s; }
order_.push_back(s);
} ~acc_compl_automaton()
{
~acc_compl_automaton() }
{
}
public: public:
size_t size; size_t size;
tgba_explicit_number* out_; tgba_digraph* out_;
map_state_bdd previous_class_; vector_state_state old_name_;
std::list<const state*> order_;
map_state_state old_name_;
private: private:
tgba_explicit_number* ea_; tgba_digraph* ea_;
acc_compl ac_; acc_compl ac_;
}; };
...@@ -280,72 +275,64 @@ namespace spot ...@@ -280,72 +275,64 @@ namespace spot
acc_compl_automaton(const tgba* a) acc_compl_automaton(const tgba* a)
: tgba_reachable_iterator_depth_first(a), : tgba_reachable_iterator_depth_first(a),
size(0), size(0),
out_(new tgba_explicit_number(a->get_dict())), out_(new tgba_digraph(a->get_dict())),
ac_(a->all_acceptance_conditions(), ac_(a->all_acceptance_conditions(),
a->neg_acceptance_conditions()), a->neg_acceptance_conditions()),
current_max(0) current_max(0),
ea_(down_cast<tgba_digraph*>(const_cast<tgba*>(a)))
{ {
a->get_dict()->register_all_variables_of(a, out_); a->get_dict()->register_all_variables_of(a, out_);
out_->set_acceptance_conditions(a->all_acceptance_conditions()); out_->copy_acceptance_conditions_of(a);
const state* init_ = a->get_init_state(); const state* init_ = a->get_init_state();
out_->set_init_state(get_state(init_));
init_->destroy(); init_->destroy();
} }
inline unsigned virtual void
get_state(const state* s) process_link(const state*, int src,
{ const state* out_s, int dst,
map_state_unsigned::const_iterator i = state2int.find(s); const tgba_succ_iterator* si)
if (i == state2int.end())
{
i = state2int.insert(std::make_pair(s, ++current_max)).first;
state* in_new_aut = out_->add_state(current_max);
previous_class_[in_new_aut] = bddfalse;
old_name_[in_new_aut] = s;
order_.push_back(in_new_aut);
}
return i->second;
}
void process_link(const state* in_s,
int,
const state* out_s,
int,
const tgba_succ_iterator* si)
{ {
unsigned src = get_state(in_s); auto& g = out_->get_graph();
unsigned dst = get_state(out_s); {
// Create as many states as needed.
// Note the order of src and dst: the transition is reversed. unsigned m = std::max(src - 1, dst - 1);
tgba_explicit_number::transition* t for (unsigned ms = out_->num_states(); ms <= m; ++ms)
= out_->create_transition(dst, src); g.new_state();
}
t->condition = si->current_condition(); bdd acc;
if (!Sba) if (!Sba)
{ {
bdd acc = ac_.complement(si->current_acceptance_conditions()); acc = ac_.complement(si->current_acceptance_conditions());
t->acceptance_conditions = acc;
} }
else else
{ {
// If the acceptance is interpreted as state-based, to // If the acceptance is interpreted as state-based, to
// apply the reverse simulation on a SBA, we should pull // apply the reverse simulation on a SBA, we should pull
// the acceptance of the destination state on its incoming // the acceptance of the destination state on its incoming
// arcs (which now become outgoing args after // arcs (which now become outgoing arcs after
// transposition). // transposition).
for (auto it: out_->succ(out_s)) acc = bddfalse;
for (auto it: ea_->succ(out_s))
{ {
bdd acc = ac_.complement(it->current_acceptance_conditions()); acc = ac_.complement(it->current_acceptance_conditions());
t->acceptance_conditions = acc;
break; break;
} }
} }
// Note the order of src and dst: the transition is reversed.
g.new_transition(dst - 1, src - 1,
si->current_condition(), acc);
} }
void process_state(const state*, int, tgba_succ_iterator*) virtual void end()
{ {
++size; unsigned s = this->seen.size();
old_name_.resize(s);
for (unsigned i = 0; i < s; ++i)
old_name_[i] = ea_->state_from_number(i);
size = s;
} }
~acc_compl_automaton() ~acc_compl_automaton()
...@@ -354,15 +341,13 @@ namespace spot ...@@ -354,15 +341,13 @@ namespace spot
public: public:
size_t size; size_t size;
tgba_explicit_number* out_; tgba_digraph* out_;
map_state_bdd previous_class_; vector_state_state old_name_;
std::list<const state*> order_;
map_state_state old_name_;
private: private:
acc_compl ac_; acc_compl ac_;
map_state_unsigned state2int;
unsigned current_max; unsigned current_max;
tgba_digraph* ea_;
}; };
// The direct_simulation. If Cosimulation is true, we are doing a // The direct_simulation. If Cosimulation is true, we are doing a
...@@ -392,6 +377,7 @@ namespace spot ...@@ -392,6 +377,7 @@ namespace spot
scc_map_->build_map(); scc_map_->build_map();
old_a_ = a_; old_a_ = a_;
acc_compl_automaton<Cosimulation, Sba> acc_compl(a_); acc_compl_automaton<Cosimulation, Sba> acc_compl(a_);
// We'll start our work by replacing all the acceptance // We'll start our work by replacing all the acceptance
...@@ -426,11 +412,10 @@ namespace spot ...@@ -426,11 +412,10 @@ namespace spot
used_var_.push_back(init); used_var_.push_back(init);
// We fetch the result the run of acc_compl_automaton which // Initialize all classes to init.
// has recorded all the state in a hash table, and we set all previous_class_.resize(size_a_);
// to init. for (unsigned s = 0; s < size_a_; ++s)
for (auto& p: acc_compl.previous_class_) previous_class_[s] = init;
previous_class_[p.first] = init;
// Put all the anonymous variable in a queue, and record all // Put all the anonymous variable in a queue, and record all
// of these in a variable all_class_var_ which will be used // of these in a variable all_class_var_ which will be used
...@@ -444,8 +429,6 @@ namespace spot ...@@ -444,8 +429,6 @@ namespace spot
} }
relation_[init] = init; relation_[init] = init;
std::swap(order_, acc_compl.order_);
} }
...@@ -481,10 +464,10 @@ namespace spot ...@@ -481,10 +464,10 @@ namespace spot
// no outgoing transition. // no outgoing transition.
if (p.first == bddfalse) if (p.first == bddfalse)
for (auto s: p.second) for (auto s: p.second)
previous_class_[s] = bddfalse; previous_class_[a_->state_number(s)] = bddfalse;
else else
for (auto s: p.second) for (auto s: p.second)
previous_class_[s] = *it_bdd; previous_class_[a_->state_number(s)] = *it_bdd;
++it_bdd; ++it_bdd;
} }
} }
...@@ -532,8 +515,9 @@ namespace spot ...@@ -532,8 +515,9 @@ namespace spot
// automaton. // automaton.
if (map_cst_ if (map_cst_
&& ((it = map_cst_ && ((it = map_cst_
->find(std::make_pair(new_original_[old_name_[src]], ->find(std::make_pair
new_original_[old_name_[dst]]))) (new_original_[old_name_[a_->state_number(src)]],
new_original_[old_name_[a_->state_number(dst)]])))
!= map_cst_->end())) != map_cst_->end()))
{ {
acc = it->second; acc = it->second;
...@@ -547,7 +531,7 @@ namespace spot ...@@ -547,7 +531,7 @@ namespace spot
// the label of the transition and the class of the // the label of the transition and the class of the
// destination and all the class it implies. // destination and all the class it implies.
bdd to_add = acc & sit->current_condition() bdd to_add = acc & sit->current_condition()
& relation_[previous_class_[dst]]; & relation_[previous_class_[a_->state_number(dst)]];
res |= to_add; res |= to_add;
dst->destroy(); dst->destroy();
...@@ -564,15 +548,11 @@ namespace spot ...@@ -564,15 +548,11 @@ namespace spot
void update_sig() void update_sig()
{ {
// Here we suppose that previous_class_ always contains for (unsigned s = 0; s < size_a_; ++s)
// all the reachable states of this automaton. We do not {
// have to make (again) a traversal. We just have to run const state* src = a_->state_from_number(s);
// through this map. bdd_lstate_[compute_sig(src)].push_back(src);
for (auto s: order_) }
{
const state* src = previous_class_.find(s)->first;
bdd_lstate_[compute_sig(src)].push_back(src);
}
} }
...@@ -723,7 +703,7 @@ namespace spot ...@@ -723,7 +703,7 @@ namespace spot
for (auto& p: bdd_lstate_) for (auto& p: bdd_lstate_)