1 #ifndef VCSN_ALGOS_SYNCHRONIZING_WORD_HH
2 # define VCSN_ALGOS_SYNCHRONIZING_WORD_HH
10 # include <unordered_map>
11 # include <unordered_set>
15 # include <boost/algorithm/string.hpp>
35 template <
typename Aut>
40 using automaton_t = Aut;
43 std::unordered_set<state_t> todo;
45 for (
auto s : aut->states())
48 for (
auto l : aut->labelset()->letters_of(w))
50 std::unordered_set<state_t> new_todo;
53 auto ntf = aut->out(s, l);
54 auto size = ntf.size();
55 require(0 < size,
"automaton must be complete");
56 require(size < 2,
"automaton must be deterministic");
57 new_todo.insert(aut->dst_of(*ntf.begin()));
59 todo = std::move(new_todo);
62 return todo.size() == 1;
70 template <
typename Aut,
typename LabelSet>
74 const auto& a = aut->as<Aut>();
75 const auto& w = word->as<
LabelSet>();
91 template <
typename Aut>
102 using pair_t = std::pair<state_t, state_t>;
107 std::unordered_map<state_t, dist_transition_t>
paths_;
125 if (
pair_->is_singleton(it->first))
137 "automaton is not synchronizing");
139 for (
auto s :
pair_->states())
140 if (!
pair_->is_singleton(s))
146 std::vector<transition_t> res;
148 while (!
pair_->is_singleton(bt_curr))
152 bt_curr =
pair_->dst_of(t);
159 if (
pair_->is_singleton(s))
161 return paths_.find(s)->second.first;
166 auto ntf =
pair_->out(s, l);
167 auto size = ntf.size();
168 require(0 < size,
"automaton must be complete");
169 require(size < 2,
"automaton must be deterministic");
170 return pair_->dst_of(*ntf.begin());
176 std::unordered_set<state_t> new_todo;
180 if (!
pair_->is_singleton(new_state))
181 new_todo.insert(new_state);
183 todo_ = std::move(new_todo);
204 return paths_.size() ==
pair_->states().size() - 1;
238 while (!
todo_.empty())
240 int min = std::numeric_limits<int>::max();
244 int d = (this->*(heuristic))(s);
262 while (!
todo_.empty())
264 int min = std::numeric_limits<int>::max();
269 if (!first && o.first != previous && o.second != previous)
282 assert(pair_end.first == pair_end.second);
283 previous = pair_end.first;
297 while (!
todo_.empty())
301 int min = std::numeric_limits<int>::max();
302 for (
const auto& l :
pair_->labelset()->genset())
304 int cur_min =
phi_3(l);
312 unsigned sq_bound =
aut_->states().size();
313 if (min < 0 && count++ < (sq_bound * sq_bound))
319 size_t t =
todo_.size();
320 int bound = std::min(
aut_->states().size(), (t * t - t / 2));
321 int min = std::numeric_limits<int>::max();
325 if (count++ >= bound)
386 template <
typename Aut>
398 template <
typename Aut>
401 const auto& a = aut->as<Aut>();
414 template <
typename Aut>
415 typename labelset_t_of<Aut>::word_t
419 if (boost::iequals(algo,
"greedy") || boost::iequals(algo,
"eppstein"))
421 else if (boost::iequals(algo,
"cycle"))
423 else if (boost::iequals(algo,
"synchrop"))
425 else if (boost::iequals(algo,
"synchropl"))
427 else if (boost::iequals(algo,
"fastsynchro"))
430 raise(
"synchronizing_word: invalid algorithm: ",
str_escape(algo));
438 template <
typename Aut,
typename String>
442 const auto& a = aut->as<Aut>();
454 #endif // !VCSN_ALGOS_SYNCHRONIZING_WORD_HH
labelset_t_of< Aut >::word_t synchronizing_word(const Aut &aut, const std::string &algo="greedy")
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
std::unordered_set< state_t > todo_
label synchronizing_word(const automaton &aut, const std::string &algo)
Bridge.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
std::unordered_map< state_t, dist_transition_t > paths_
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
std::pair< state_t, state_t > pair_t
int phi_2(state_t p)
Heuristic used for SynchroPL.
std::ostream & str_escape(std::ostream &os, const std::string &str)
Output a string, escaping special characters.
Paths in filesystems, i.e., file names.
synchronizer(const automaton_t &aut)
state_t_of< automaton_t > state_t
bool is_synchronizing(const automaton &aut)
Bridge.
void init_synchro(bool keep_initials=false)
bool is_synchronized_by(const automaton &aut, const label &word)
Bridge.
state_t dest_state(state_t s, const label_t &l)
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
int phi_1(state_t p)
Heuristic used for SynchroP.
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
transition_t_of< automaton_t > transition_t
void apply_label(const label_t &label)
int delta(state_t p, const std::vector< transition_t > &w)
Compute dist(d(s, w)) - dist(s).
label_t_of< automaton_t > label_t
word_t synchro(heuristic_t heuristic)
std::shared_ptr< const detail::label_base > label
auto(synchronizer::*)(state_t) -> int heuristic_t
int phi_3(const label_t &l)
Heuristic used for FastSynchro.
std::vector< transition_t > recompose_path(state_t from)
std::shared_ptr< detail::pair_automaton_impl< Aut >> pair_automaton
std::pair< unsigned, transition_t > dist_transition_t
bool is_synchronized_by(const Aut &aut, const typename labelset_t_of< Aut >::word_t &w)
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
typename labelset_t_of< automaton_t >::word_t word_t
void apply_path(const std::vector< transition_t > &path)
label make_label(const LabelSet &ls, const typename LabelSet::value_t &l)
std::unordered_map< state_t_of< Aut >, std::pair< unsigned, transition_t_of< Aut > > > paths_ibfs(const Aut &aut, std::vector< state_t_of< Aut >> start)
bool is_synchronizing(const Aut &aut)
pair_automaton< Aut > pair_
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
void init_pair(bool keep_initials=false)