Vcsn  2.1
Be Rational
pair.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 
7 #include <vcsn/dyn/automaton.hh>
8 #include <vcsn/misc/map.hh>
10 #include <vcsn/misc/pair.hh> // hash<pair>.
11 #include <vcsn/misc/zip-maps.hh>
12 
13 namespace vcsn
14 {
15 
16  /*-----------------.
17  | pair_automaton. |
18  `-----------------*/
19 
20  namespace detail
21  {
22 
25  template <typename Aut>
27 #if 0
28  // See comments below.
29  : public automaton_decorator<fresh_automaton_t_of<Aut>>
30 #else
31  : public automaton_decorator<mutable_automaton<context_t_of<Aut>>>
32 #endif
33  {
34  public:
35  using automaton_t = Aut;
37  // FIXME: cannot use fresh_automaton_t_of<Aut>. To see why, run
38  // the tests/python/focus.py test. We should probably stop
39  // having make_free_context behave a special way with
40  // focus_automaton, rather we should call a special function to
41  // duplicate a focus_automaton.
42 #if 0
43  template <typename Ctx = context_t>
46 #else
47  template <typename Ctx = context_t>
50 #endif
55  using weight_t = typename weightset_t::value_t;
56 
57  private:
60  using pair_t = std::pair<state_t, state_t>;
61  using origins_t = std::map<state_t, pair_t>;
62 
63  public:
64  pair_automaton_impl(const automaton_t& aut, bool keep_initials = false)
65  : super_t(aut->context())
66  , input_(aut)
67  , transition_map_(aut)
68  , keep_initials_(keep_initials)
69  {
70  auto ctx = input_->context();
71  auto ws = ctx.weightset();
72 
73  if (keep_initials_)
74  for (auto s : input_->states())
75  pair_states_.emplace(std::make_pair(s, s), this->new_state());
76  else
77  {
78  q0_ = this->new_state(); // q0 special state
79  for (auto l : input_->labelset()->genset())
80  this->add_transition(q0_, q0_, l, ws->one());
81  }
82 
83  // States are "ordered": (s1, s2) is defined only for s1 < s2.
84  {
85  auto states = input_->states();
86  auto end = std::end(states);
87  for (auto i1 = std::begin(states); i1 != end; ++i1)
88  {
89  // FIXME: cannot use i2 = std::next(i1) with clang 3.5
90  // and Boost 1.55.
91  // https://svn.boost.org/trac/boost/ticket/9984
92  auto i2 = i1;
93  for (++i2; i2 != end; ++i2)
94  // s1 < s2, no need for make_ordered_pair.
95  pair_states_.emplace(std::make_pair(*i1, *i2),
96  this->new_state());
97  }
98  }
99 
100  for (auto ps : pair_states_)
101  {
102  auto pstates = ps.first; // pair of states
103  auto cstate = ps.second; // current state
104 
105  for (const auto& p : zip_maps(transition_map_[pstates.first],
106  transition_map_[pstates.second]))
107  this->add_transition(cstate,
108  state_(std::get<0>(p.second).dst,
109  std::get<1>(p.second).dst),
110  p.first, ws->one());
111  }
112 
113  for (const auto& p: pair_states_)
114  origins_.emplace(p.second, p.first);
115 
116  if (keep_initials_)
117  for (auto s : input_->states())
118  singletons_.push_back(state_(s, s));
119  else
120  singletons_.push_back(q0_);
121  }
122 
123  static symbol sname()
124  {
125  static symbol res("pair_automaton<"
127  return res;
128  }
129 
130  std::ostream& print_set(std::ostream& o, format fmt = {}) const
131  {
132  o << "pair_automaton<";
133  input_->print_set(o, fmt);
134  return o << '>';
135  }
136 
137  state_t get_q0() const
138  {
139  require(!keep_initials_,
140  "can't get_q0() on a pairer that keeps origins");
141  return q0_;
142  }
143 
144  bool is_singleton(state_t s) const
145  {
146  if (keep_initials_)
147  {
148  pair_t p = get_origin(s);
149  return p.first == p.second;
150  }
151  else
152  return s == q0_;
153  }
154 
155  const std::vector<state_t>& singletons() const
156  {
157  return singletons_;
158  }
159 
160  const std::unordered_map<pair_t, state_t>& get_map_pair() const
161  {
162  return pair_states_;
163  }
164 
166  const origins_t& origins() const
167  {
168  return origins_;
169  }
170 
171  const pair_t get_origin(state_t s) const
172  {
173  auto i = origins().find(s);
174  require(i != std::end(origins()), "state not found in origins");
175  return i->second;
176  }
177 
178  bool state_has_name(state_t s) const
179  {
180  return has(origins(), s);
181  }
182 
183  std::ostream&
184  print_state_name(state_t ss, std::ostream& o,
185  format fmt = {},
186  bool delimit = false) const
187  {
188  auto i = origins().find(ss);
189  if (i == std::end(origins()))
190  this->print_state(ss, o);
191  else
192  {
193  if (delimit)
194  o << '{';
195  input_->print_state_name(i->second.first, o, fmt);
196  if (!is_singleton(ss))
197  {
198  o << ", ";
199  input_->print_state_name(i->second.second, o, fmt);
200  }
201  if (delimit)
202  o << '}';
203  }
204  return o;
205  }
206 
207  private:
211  {
212  // Benches show it is slightly faster to handle this case
213  // especially rather that mapping these "diagonal states" to
214  // q0_ in pair_states_.
215  if (s1 == s2 && !keep_initials_)
216  return q0_;
217  else
218  return pair_states_[make_ordered_pair(s1, s2)];
219  }
220 
226  std::unordered_map<pair_t, state_t> pair_states_;
228  std::vector<state_t> singletons_;
229  state_t q0_ = this->null_state();
230  bool keep_initials_ = false;
231  };
232  }
233 
234  template <typename Aut>
235  using pair_automaton
236  = std::shared_ptr<detail::pair_automaton_impl<Aut>>;
237 
238  /*------------------.
239  | pair(automaton). |
240  `------------------*/
241 
242  template <typename Aut>
243  pair_automaton<Aut> pair(const Aut& aut, bool keep_initials = false)
244  {
245  return make_shared_ptr<pair_automaton<Aut>>(aut, keep_initials);
246  }
247 
248  namespace dyn
249  {
250  namespace detail
251  {
253  template <typename Aut, typename>
254  automaton
255  pair(const automaton& aut, bool keep_initials)
256  {
257  const auto& a = aut->as<Aut>();
258  return make_automaton(::vcsn::pair(a, keep_initials));
259  }
260  }
261  }
262 }
std::pair< T, T > make_ordered_pair(T e1, T e2)
Definition: pair.hh:34
The pair automaton is used by several algorithms for synchronizing words.
Definition: pair.hh:26
std::ostream & print_set(std::ostream &o, format fmt={}) const
Definition: pair.hh:130
auto new_state(Args &&...args) -> decltype(aut_-> new_state(std::forward< Args >(args)...))
static constexpr auto null_state(Args &&...args) -> decltype(element_type::null_state(std::forward< Args >(args)...))
std::unordered_map< pair_t, state_t > pair_states_
Definition: pair.hh:226
transition_t_of< automaton_t > transition_t
Definition: pair.hh:53
weightset_t_of< automaton_t > weightset_t
Definition: pair.hh:54
auto states(Args &&...args) const -> decltype(aut_-> states(std::forward< Args >(args)...))
const std::vector< state_t > & singletons() const
Definition: pair.hh:155
context_t_of< automaton_t > context_t
Definition: pair.hh:36
std::ostream & print_state_name(state_t ss, std::ostream &o, format fmt={}, bool delimit=false) const
Definition: pair.hh:184
transition_map_t transition_map_
Definition: pair.hh:225
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:48
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
Definition: traits.hh:45
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:51
std::shared_ptr< detail::pair_automaton_impl< Aut >> pair_automaton
Definition: pair.hh:236
Aggregate an automaton, and forward calls to it.
state_t state_(state_t s1, state_t s2)
The state in the result automaton that corresponds to (s1, s2).
Definition: pair.hh:210
std::map< state_t, pair_t > origins_t
Definition: pair.hh:61
zipped_maps< Dereference, Maps...> zip_maps(Maps &&...maps)
Definition: zip-maps.hh:250
auto print_state(Args &&...args) const -> decltype(aut_-> print_state(std::forward< Args >(args)...))
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Definition: traits.hh:57
state_t get_q0() const
Definition: pair.hh:137
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
Definition: automaton.hh:75
bool state_has_name(state_t s) const
Definition: pair.hh:178
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:80
bool is_singleton(state_t s) const
Definition: pair.hh:144
const origins_t & origins() const
A map from result state to tuple of original states.
Definition: pair.hh:166
An input/output format.
Definition: format.hh:11
std::shared_ptr< detail::automaton_base > automaton
Definition: automaton.hh:69
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:75
auto add_transition(Args &&...args) -> decltype(aut_-> add_transition(std::forward< Args >(args)...))
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:49
typename weightset_t::value_t weight_t
Definition: pair.hh:55
symbol sname()
Definition: name.hh:67
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
std::vector< state_t > singletons_
Definition: pair.hh:228
automaton_t input_
Input automaton.
Definition: pair.hh:222
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
Definition: pair.hh:243
state_t_of< automaton_t > state_t
Definition: pair.hh:52
const std::unordered_map< pair_t, state_t > & get_map_pair() const
Definition: pair.hh:160
ATTRIBUTE_PURE bool has(const std::deque< T, Allocator > &s, const T &e)
Whether e is member of s.
Definition: deque.hh:13
pair_automaton_impl(const automaton_t &aut, bool keep_initials=false)
Definition: pair.hh:64
mutable_automaton< Ctx > fresh_automaton_t
When creating a copy of this automaton type.
Definition: pair.hh:49
const pair_t get_origin(state_t s) const
Definition: pair.hh:171
std::pair< state_t, state_t > pair_t
The semantics of the result states: ordered pair of input states.
Definition: pair.hh:60
std::shared_ptr< detail::mutable_automaton_impl< Context >> mutable_automaton
Definition: fwd.hh:24