17 #ifndef AWALI_ALGOS_SYNCHRONIZING_WORD_HH 
   18 # define AWALI_ALGOS_SYNCHRONIZING_WORD_HH 
   26 # include <unordered_set> 
   48     template <
typename Aut>
 
   54       std::unordered_set<state_t> todo;
 
   56       for (
auto s : aut->states())
 
   59       for (
auto l : aut->labelset()->letters_of(w))
 
   61           std::unordered_set<state_t> new_todo;
 
   64               auto ntf = aut->out(s, l);
 
   65               auto size = ntf.size();
 
   66               require(0 < size, 
"automaton must be complete");
 
   67               require(size < 2, 
"automaton must be deterministic");
 
   68               new_todo.insert(aut->dst_of(*ntf.begin()));
 
   70           todo = std::move(new_todo);
 
   73       return todo.size() == 1;
 
   82       template <
typename Aut>
 
   93         using weight_t = 
typename weightset_t::value_t;
 
   99         using pair_t = std::pair<state_t, state_t>;
 
  100         using origins_t = std::map<state_t, pair_t>;
 
  106           , transition_map_(aut)
 
  107           , keep_initials_(keep_initials)
 
  109           auto ctx = input_->context();
 
  110           auto ws = ctx.weightset();
 
  115               for (
auto l : input_->labelset()->genset())
 
  119             for (
auto s : input_->states())
 
  120               pair_states_.emplace(std::make_pair(s, s), this->
add_state());
 
  124             auto states = input_->states();
 
  125             auto end = std::end(
states);
 
  126             for (
auto i1 = std::begin(
states); i1 != end; ++i1)
 
  132                 for (++i2; i2 != end; ++i2)
 
  134                   pair_states_.emplace(std::make_pair(*i1, *i2),
 
  139           for (
auto ps : pair_states_)
 
  141               auto pstates = ps.first; 
 
  142               auto cstate = ps.second; 
 
  145                                                       transition_map_[pstates.second]))
 
  147                                      state_(std::get<0>(p.second).dst,
 
  148                                             std::get<1>(p.second).dst),
 
  152           for (
const auto& p: pair_states_)
 
  153             origins_.emplace(p.second, p.first);
 
  156             for (
auto s : input_->states())
 
  157               singletons_.push_back(state_(s, s));
 
  159             singletons_.push_back(q0_);
 
  164           require(!keep_initials_, 
"can't get_q0() on a pairer that " 
  174               return p.first == p.second;
 
  187           return "pair_automaton<" + automaton_t::element_type::sname() + 
">";
 
  192           return "pair_automaton<" + input_->vname(
full) + 
">";
 
  215                            const std::string& fmt = 
"text")
 const 
  222               input_->print_state_name(i->second.first, o, fmt);
 
  224               input_->print_state_name(i->second.second, o, fmt);
 
  237           if (s1 == s2 && !keep_initials_)
 
  246         using transition_map_t
 
  247           = transition_map<automaton_t, weightset_t_of<automaton_t>, 
true>;
 
  248         transition_map_t transition_map_;
 
  249         std::unordered_map<pair_t, state_t> pair_states_;
 
  251         std::vector<state_t> singletons_;
 
  253         bool keep_initials_ = 
false;
 
  257     template <
typename Aut>
 
  259     = std::shared_ptr<internal::pair_automaton_impl<Aut>>;
 
  265     template <
typename Aut>
 
  268       auto res = make_shared_ptr<pair_automaton<Aut>>(aut, keep_initials);
 
  274       template <
typename Aut>
 
  283         using pair_t = std::pair<state_t, state_t>;
 
  284         using dist_transition_t = std::pair<unsigned, transition_t>;
 
  288         std::unordered_map<state_t, dist_transition_t> paths_;
 
  289         std::unordered_set<state_t> todo_;
 
  298         void init_pair(
bool keep_initials = 
false)
 
  300           pair_ = 
pair(aut_, keep_initials);
 
  301           paths_ = 
paths_ibfs(pair_, pair_->singletons());
 
  304             for (
auto it = paths_.begin(); it != paths_.end(); )
 
  306                 if (pair_->is_singleton(it->first))
 
  313         void init_synchro(
bool keep_initials = 
false)
 
  315           init_pair(keep_initials);
 
  316           require(pair_->states().size() == paths_.size() +
 
  317                   pair_->singletons().size(), 
"automaton is not synchronizing");
 
  319           for (
auto s : pair_->states())
 
  320             if (!pair_->is_singleton(s))
 
  324         std::vector<transition_t> recompose_path(
state_t from)
 
  326           std::vector<transition_t> res;
 
  328           while (!pair_->is_singleton(bt_curr))
 
  332               bt_curr = pair_->dst_of(t);
 
  339           if (pair_->is_singleton(s))
 
  341           return paths_.find(s)->second.first;
 
  346           auto ntf = pair_->out(s, l);
 
  347           auto size = ntf.size();
 
  348           require(0 < size, 
"automaton must be complete");
 
  349           require(size < 2, 
"automaton must be deterministic");
 
  350           return pair_->dst_of(*ntf.begin());
 
  353         void apply_label(
const label_t& label)
 
  355           res_ = aut_->labelset()->concat(res_, label);
 
  356           std::unordered_set<state_t> new_todo;
 
  359               auto add_state = dest_state(s, label);
 
  360               if (!pair_->is_singleton(add_state))
 
  361                 new_todo.insert(add_state);
 
  363           todo_ = std::move(new_todo);
 
  368         void apply_path(
const std::vector<transition_t>& path)
 
  371             apply_label(pair_->label_of(t));
 
  384           return paths_.size() == pair_->states().size() - 1;
 
  389           return synchro(&synchronizer::dist);
 
  399           return synchro(&synchronizer::phi_1);
 
  404           return synchro(&synchronizer::phi_2);
 
  409           return fastsynchro_();
 
  415         word_t synchro(heuristic_t heuristic)
 
  418           while (!todo_.empty())
 
  424                   int d = (this->*(heuristic))(s);
 
  432               apply_path(recompose_path(s_min));
 
  442           while (!todo_.empty())
 
  448                   pair_t o = pair_->get_origin(s);
 
  449                   if (!first && o.first != previous && o.second != previous)
 
  459               const auto& path = recompose_path(s_min);
 
  460               pair_t pair_end = pair_->get_origin(
 
  461                                                   pair_->dst_of(path[path.size() - 1]));
 
  462               assert(pair_end.first == pair_end.second);
 
  463               previous = pair_end.first;
 
  477           while (!todo_.empty())
 
  482               for (
const auto& l : pair_->labelset()->genset())
 
  484                   int cur_min = phi_3(l);
 
  492               unsigned sq_bound = aut_->states().size();
 
  493               if (
min < 0 && count++ < (sq_bound * sq_bound))
 
  499                   size_t t = todo_.size();
 
  500                   int bound = 
std::min(aut_->states().size(), (t * t - t / 2));
 
  505                       if (count++ >= bound)
 
  514                   apply_path(recompose_path(s_min));
 
  521         int delta(
state_t p, 
const std::vector<transition_t>& w)
 
  525             np = dest_state(np, pair_->label_of(t));
 
  526           return dist(np) - dist(p);
 
  535           auto w = recompose_path(p);
 
  546           return phi_1(p) + dist(p);
 
  555             res += dist(dest_state(s, l)) - dist(s);
 
  566     template <
typename Aut>
 
  577     template <
typename Aut>
 
  582       if (algo == 
"greedy" || algo == 
"eppstein")
 
  584       else if (algo == 
"cycle")
 
  586       else if (algo == 
"synchrop")
 
  588       else if (algo == 
"synchropl")
 
  590       else if (algo == 
"fastsynchro")
 
  593         raise(
"synchronizing_word: invalid algorithm: ", 
str_escape(algo));
 
  609     template <
typename Ctx>
 
  610     mutable_automaton<Ctx>
 
  611     cerny(
const Ctx& ctx, 
unsigned num_states)
 
  613       require(0 < num_states, 
"num_states must be > 0");
 
  616       automaton_t res = make_shared_ptr<automaton_t>(ctx);
 
  618       std::vector<state_t> 
states;
 
  619       states.reserve(num_states);
 
  621       for (
unsigned i = 0; i < num_states; ++i)
 
  622         states.push_back(res->add_state());
 
  624       for (
unsigned i = 0; i < num_states; ++i)
 
  627           for (
auto l : ctx.labelset()->genset())
 
  629               auto dest = (la || i == num_states - 1) ? (i + 1) % num_states : i;
 
  631                                   ctx.weightset()->one());
 
  636       res->set_initial(
states[0]);
 
  637       res->set_final(
states[0]);
 
carries the algebraic settings of automata
Definition: context.hh:40
 
Aggregate an automaton, and forward calls to it.
Definition: automaton_decorator.hh:36
 
auto print_state(Args &&... args) const -> decltype(aut_-> print_state(std::forward< Args >(args)...))
Definition: automaton_decorator.hh:154
 
auto states(Args &&... args) const -> decltype(aut_-> states(std::forward< Args >(args)...))
Definition: automaton_decorator.hh:157
 
auto add_state(Args &&... args) -> decltype(aut_-> add_state(std::forward< Args >(args)...))
Definition: automaton_decorator.hh:187
 
auto add_transition(Args &&... args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
Definition: automaton_decorator.hh:181
 
Definition: synchronizing_word.hh:86
 
typename weightset_t::value_t weight_t
Definition: synchronizing_word.hh:93
 
mutable_automaton< context_t_of< Aut > > automaton_nocv_t
Definition: synchronizing_word.hh:89
 
state_t get_q0() const
Definition: synchronizing_word.hh:162
 
static std::string sname()
Definition: synchronizing_word.hh:185
 
const std::unordered_map< pair_t, state_t > & get_map_pair() const
Definition: synchronizing_word.hh:195
 
Aut automaton_t
Definition: synchronizing_word.hh:88
 
bool is_singleton(state_t s) const
Definition: synchronizing_word.hh:169
 
pair_automaton_impl(const automaton_t &aut, bool keep_initials=false)
Definition: synchronizing_word.hh:103
 
weightset_t_of< automaton_t > weightset_t
Definition: synchronizing_word.hh:92
 
const std::vector< state_t > & singletons()
Definition: synchronizing_word.hh:180
 
std::ostream & print_state_name(state_t ss, std::ostream &o, const std::string &fmt="text") const
Definition: synchronizing_word.hh:214
 
const origins_t & origins() const
A map from result state to tuple of original states.
Definition: synchronizing_word.hh:201
 
const pair_t get_origin(state_t s) const
Definition: synchronizing_word.hh:206
 
std::string vname(bool full=true) const
Definition: synchronizing_word.hh:190
 
context_t_of< automaton_t > context_t
Definition: synchronizing_word.hh:91
 
std::vector< state_t > states(abstract_automaton_t const *aut, bool all)
 
any_t word_t
Type for words; it is an alias to any_t since the precise type depends on the context (most of the ti...
Definition: typedefs.hh:67
 
json_ast_t from(std::istream &i)
Builds a json_ast_t from an input stream.
 
zipped_maps< Dereference, Maps... > zip_maps(Maps &&... maps)
Definition: zip_maps.hh:274
 
std::string to_string(identities i)
 
std::pair< T, T > make_ordered_pair(T e1, T e2)
Definition: pair.hh:52
 
typename internal::label_t_of_impl< internal::base_t< ValueSet > >::type label_t_of
Helper to retrieve the type of the labels of a value set.
Definition: traits.hh:71
 
std::shared_ptr< internal::pair_automaton_impl< Aut > > pair_automaton
Definition: synchronizing_word.hh:259
 
bool is_synchronizing(const Aut &aut)
Definition: synchronizing_word.hh:567
 
std::ostream & str_escape(std::ostream &os, const int c)
Definition: escape.hh:30
 
typename internal::context_t_of_impl< internal::base_t< ValueSet > >::type context_t_of
Helper to retrieve the type of the context of a value set.
Definition: traits.hh:66
 
mutable_automaton< Ctx > cerny(const Ctx &ctx, unsigned num_states)
Cerny automata are automata whose synchronizing word length is always (n - 1)^2, the upper bound of t...
Definition: synchronizing_word.hh:611
 
typename internal::labelset_t_of_impl< internal::base_t< ValueSet > >::type labelset_t_of
Helper to retrieve the type of the labelset of a value set.
Definition: traits.hh:76
 
std::unordered_map< state_t, std::pair< unsigned, transition_t > > paths_ibfs(const Aut &aut, std::vector< state_t > start)
Definition: distance.hh:40
 
std::shared_ptr< internal::mutable_automaton_impl< Context > > mutable_automaton
Definition: mutable_automaton.hh:45
 
void require(bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:55
 
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
Definition: synchronizing_word.hh:266
 
labelset_t_of< Aut >::word_t synchronizing_word(const Aut &aut, const std::string &algo="greedy")
Definition: synchronizing_word.hh:579
 
typename internal::weightset_t_of_impl< internal::base_t< ValueSet > >::type weightset_t_of
Helper to retrieve the type of the weightset of a value set.
Definition: traits.hh:86
 
bool is_synchronized_by(const Aut &aut, const typename labelset_t_of< Aut >::word_t &w)
Definition: synchronizing_word.hh:50
 
ATTRIBUTE_CONST int max(int a, int b)
Definition: arith.hh:54
 
ATTRIBUTE_CONST int min(int a, int b)
Definition: arith.hh:48
 
static const std::string full
Completely version of Awali as a std::string.
Definition: version.hh:42
 
Main namespace of Awali.
Definition: ato.hh:22
 
unsigned state_t
Definition: types.hh:21
 
unsigned transition_t
Definition: types.hh:22
 
Definition: synchronize.hh:47
 
word_t cycle()
Definition: synchronizing_word.hh:392
 
word_t greedy()
Definition: synchronizing_word.hh:387
 
word_t synchroP()
Definition: synchronizing_word.hh:397
 
synchronizer(const automaton_t &aut)
Definition: synchronizing_word.hh:293
 
word_t synchroPL()
Definition: synchronizing_word.hh:402
 
Aut automaton_t
Definition: synchronizing_word.hh:278
 
typename labelset_t_of< automaton_t >::word_t word_t
Definition: synchronizing_word.hh:279
 
bool is_synchronizing()
Definition: synchronizing_word.hh:381
 
label_t_of< automaton_t > label_t
Definition: synchronizing_word.hh:280
 
word_t fastsynchro()
Definition: synchronizing_word.hh:407