Vcsn  2.0
Be Rational
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
pair.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <map>
4 #include <unordered_map>
5 #include <vector>
6 
9 #include <vcsn/misc/zip-maps.hh>
10 
11 namespace vcsn
12 {
13 
14  /*-----------------.
15  | pair_automaton. |
16  `-----------------*/
17 
18  namespace detail
19  {
20 
23  template <typename Aut>
25  : public automaton_decorator<mutable_automaton<context_t_of<Aut>>>
26  {
27  public:
28  using automaton_t = Aut;
34  using weight_t = typename weightset_t::value_t;
36 
37  private:
40  using pair_t = std::pair<state_t, state_t>;
41  using origins_t = std::map<state_t, pair_t>;
42 
43  public:
44  pair_automaton_impl(const automaton_t& aut, bool keep_initials = false)
45  : super_t(aut->context())
46  , input_(aut)
47  , transition_map_(aut)
48  , keep_initials_(keep_initials)
49  {
50  auto ctx = input_->context();
51  auto ws = ctx.weightset();
52 
53  if (!keep_initials_)
54  {
55  q0_ = this->new_state(); // q0 special state
56  for (auto l : input_->labelset()->genset())
57  this->add_transition(q0_, q0_, l, ws->one());
58  }
59  else
60  for (auto s : input_->states())
61  pair_states_.emplace(std::make_pair(s, s), this->new_state());
62 
63  // States are "ordered": (s1, s2) is defined only for s1 < s2.
64  {
65  auto states = input_->states();
66  auto end = std::end(states);
67  for (auto i1 = std::begin(states); i1 != end; ++i1)
68  {
69  // FIXME: cannot use i2 = std::next(i1) with clang 3.5
70  // and Boost 1.55.
71  // https://svn.boost.org/trac/boost/ticket/9984
72  auto i2 = i1;
73  for (++i2; i2 != end; ++i2)
74  // s1 < s2, no need for make_ordered_pair.
75  pair_states_.emplace(std::make_pair(*i1, *i2),
76  this->new_state());
77  }
78  }
79 
80  for (auto ps : pair_states_)
81  {
82  auto pstates = ps.first; // pair of states
83  auto cstate = ps.second; // current state
84 
85  for (const auto& p : zip_maps(transition_map_[pstates.first],
86  transition_map_[pstates.second]))
87  this->add_transition(cstate,
88  state_(std::get<0>(p.second).dst,
89  std::get<1>(p.second).dst),
90  p.first, ws->one());
91  }
92 
93  for (const auto& p: pair_states_)
94  origins_.emplace(p.second, p.first);
95 
96  if (keep_initials_)
97  for (auto s : input_->states())
98  singletons_.push_back(state_(s, s));
99  else
100  singletons_.push_back(q0_);
101  }
102 
103  state_t get_q0() const
104  {
106  "can't get_q0() on a pairer that keeps origins");
107  return q0_;
108  }
109 
110  bool is_singleton(state_t s) const
111  {
112  if (keep_initials_)
113  {
114  pair_t p = get_origin(s);
115  return p.first == p.second;
116  }
117  else
118  return s == q0_;
119  }
120 
121  const std::vector<state_t>& singletons()
122  {
123  return singletons_;
124  }
125 
126  static std::string sname()
127  {
128  return "pair_automaton<" + automaton_t::element_type::sname() + ">";
129  }
130 
131  std::string vname(bool full = true) const
132  {
133  return "pair_automaton<" + input_->vname(full) + ">";
134  }
135 
136  const std::unordered_map<pair_t, state_t>& get_map_pair() const
137  {
138  return pair_states_;
139  }
140 
142  const origins_t& origins() const
143  {
144  return origins_;
145  }
146 
147  const pair_t get_origin(state_t s) const
148  {
149  auto i = origins().find(s);
150  require(i != std::end(origins()), "state not found in origins");
151  return i->second;
152  }
153 
154  bool state_has_name(state_t s) const
155  {
156  return (s != super_t::pre()
157  && s != super_t::post()
158  && has(origins(), s));
159  }
160 
161  std::ostream&
162  print_state_name(state_t ss, std::ostream& o,
163  const std::string& fmt = "text") const
164  {
165  auto i = origins().find(ss);
166  if (i == std::end(origins()))
167  this->print_state(ss, o);
168  else
169  {
170  input_->print_state_name(i->second.first, o, fmt);
171  o << ", ";
172  input_->print_state_name(i->second.second, o, fmt);
173  }
174  return o;
175  }
176 
177  private:
181  {
182  // Benches show it is slightly faster to handle this case
183  // especially rather that mapping these "diagonal states" to
184  // q0_ in pair_states_.
185  if (s1 == s2 && !keep_initials_)
186  return q0_;
187  else
188  return pair_states_[make_ordered_pair(s1, s2)];
189  }
190 
194  using transition_map_t
197  std::unordered_map<pair_t, state_t> pair_states_;
199  std::vector<state_t> singletons_;
201  bool keep_initials_ = false;
202  };
203  }
204 
205  template <typename Aut>
206  using pair_automaton
207  = std::shared_ptr<detail::pair_automaton_impl<Aut>>;
208 
209  /*------------------.
210  | pair(automaton). |
211  `------------------*/
212 
213  template <typename Aut>
214  pair_automaton<Aut> pair(const Aut& aut, bool keep_initials = false)
215  {
216  auto res = make_shared_ptr<pair_automaton<Aut>>(aut, keep_initials);
217  return res;
218  }
219 
220  namespace dyn
221  {
222  namespace detail
223  {
225  template <typename Aut, typename>
226  automaton
227  pair(const automaton& aut, bool keep_initials = false)
228  {
229  const auto& a = aut->as<Aut>();
230  return make_automaton(::vcsn::pair(a, keep_initials));
231  }
232 
233  REGISTER_DECLARE(pair, (const automaton&, bool) -> automaton);
234  }
235  }
236 }
state_t get_q0() const
Definition: pair.hh:103
typename weightset_t::value_t weight_t
Definition: pair.hh:34
bool state_has_name(state_t s) const
Definition: pair.hh:154
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:71
const origins_t & origins() const
A map from result state to tuple of original states.
Definition: pair.hh:142
std::vector< state_t > singletons_
Definition: pair.hh:199
auto states(Args &&...args) const -> decltype(aut_-> states(std::forward< Args >(args)...))
state_t_of< automaton_t > state_t
Definition: pair.hh:31
const std::unordered_map< pair_t, state_t > & get_map_pair() const
Definition: pair.hh:136
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
Definition: pair.hh:214
std::string sname()
Definition: name.hh:31
const pair_t get_origin(state_t s) const
Definition: pair.hh:147
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:77
std::shared_ptr< detail::mutable_automaton_impl< Context >> mutable_automaton
Definition: fwd.hh:25
automaton_t input_
Input automaton.
Definition: pair.hh:192
std::pair< state_t, state_t > pair_t
The semantics of the result states: ordered pair of input states.
Definition: pair.hh:40
static std::string sname()
Definition: pair.hh:126
auto new_state(Args &&...args) -> decltype(aut_-> new_state(std::forward< Args >(args)...))
std::string vname(bool full=true) const
Definition: pair.hh:131
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:32
pair_automaton_impl(const automaton_t &aut, bool keep_initials=false)
Definition: pair.hh:44
Aggregate an automaton, and forward calls to it.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:38
weightset_t_of< automaton_t > weightset_t
Definition: pair.hh:33
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:36
context_t_of< automaton_t > context_t
Definition: pair.hh:30
automaton pair(const automaton &aut, bool keep_initials=false)
Bridge.
Definition: pair.hh:227
transition_map_t transition_map_
Definition: pair.hh:196
The pair automaton is used by several algorithms for synchronizing words.
Definition: pair.hh:24
std::unordered_map< pair_t, state_t > pair_states_
Definition: pair.hh:197
transition_t_of< automaton_t > transition_t
Definition: pair.hh:32
std::shared_ptr< detail::pair_automaton_impl< Aut >> pair_automaton
Definition: pair.hh:207
zipped_maps< Dereference, Maps...> zip_maps(Maps &&...maps)
Definition: zip-maps.hh:257
static constexpr auto pre(Args &&...args) -> decltype(automaton_t::element_type::pre(std::forward< Args >(args)...))
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:35
bool is_singleton(state_t s) const
Definition: pair.hh:110
std::ostream & print_state_name(state_t ss, std::ostream &o, const std::string &fmt="text") const
Definition: pair.hh:162
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
std::pair< T, T > make_ordered_pair(T e1, T e2)
Definition: pair.hh:36
auto print_state(Args &&...args) const -> decltype(aut_-> print_state(std::forward< Args >(args)...))
mutable_automaton< context_t_of< Aut >> automaton_nocv_t
Definition: pair.hh:29
bool has(const std::map< Key, Value, Compare, Alloc > &s, const Key &e)
Definition: map.hh:35
static constexpr auto post(Args &&...args) -> decltype(automaton_t::element_type::post(std::forward< Args >(args)...))
state_t state_(state_t s1, state_t s2)
The state in the result automaton that corresponds to (s1, s2).
Definition: pair.hh:180
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:39
const std::vector< state_t > & singletons()
Definition: pair.hh:121
std::map< state_t, pair_t > origins_t
Definition: pair.hh:41