Vcsn  2.1
Be Rational
filter.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm> // std::max
4 #include <boost/range/irange.hpp>
5 #include <vcsn/algos/copy.hh>
7 #include <vcsn/misc/crange.hh>
8 #include <vcsn/dyn/fwd.hh>
10 #include <vcsn/misc/vector.hh>
11 
12 namespace vcsn
13 {
14  namespace detail
15  {
17  template <typename Aut>
19  : public automaton_decorator<Aut>
20  {
21  public:
22  using automaton_t = Aut;
27 
32  using states_t = std::unordered_set<state_t>;
33 
34  using tr_cont_t = std::vector<transition_t>;
35 
36  using super_t::pre;
37  using super_t::post;
38  using super_t::src_of;
39  using super_t::dst_of;
40 
41  filter_automaton_impl(const automaton_t& input, const states_t& ss)
42  : super_t(input), ss_(ss)
43  {
44  ss_.emplace(input->pre());
45  ss_.emplace(input->post());
46  }
47 
49  static symbol sname()
50  {
51  static symbol res("filter_automaton<"
53  return res;
54  }
55 
56  std::ostream& print_set(std::ostream& o, format fmt = {}) const
57  {
58  o << "filter_automaton<";
59  aut_->print_set(o, fmt);
60  return o << '>';
61  }
62 
63  bool state_has_name(state_t s) const
64  {
65  assert(has(ss_, s));
66  return aut_->state_has_name(s);
67  }
68 
69  bool has_state(state_t s) const
70  {
71  return has(ss_, s) && aut_->has_state(s);
72  }
73 
74  std::ostream& print_state_name(state_t s, std::ostream& o,
75  format fmt = {},
76  bool delimit = false) const
77  {
78  assert(has(ss_, s));
79  return aut_->print_state_name(s, o, fmt, delimit);
80  }
81 
82  size_t num_states() const
83  {
84  return states().size();
85  }
86 
87  size_t num_all_states() const
88  {
89  return all_states().size();
90  }
91 
92  // FIXME: clang workaround.
93  template <typename Pred>
94  struct has_state_p
95  {
96  bool operator()(state_t s) const
97  {
98  return pred(s) && has(aut_.ss_, s);
99  }
100  const filter_automaton_impl& aut_;
101  Pred pred;
102  };
103 
104  template <typename Pred>
105  auto all_states(Pred pred) const
106  -> decltype(this->aut_->all_states(has_state_p<Pred>{*this, pred}))
107  {
108  return aut_->all_states(has_state_p<Pred>{*this, pred});
109  }
110 
111  // FIXME: clang workaround.
112  struct all_states_p
113  {
114  bool operator()(state_t) const { return true; };
115  };
116 
117  auto all_states() const
118  -> decltype(this->all_states(all_states_p{}))
119  {
120  return all_states(all_states_p{});
121  }
122 
123  // FIXME: clang workaround.
124  struct visible_state_p
125  {
126  bool operator()(state_t s) const
127  {
128  // When transposing post() < pre().
129  return std::max(pre(), post()) < s;
130  }
131  const filter_automaton_impl& aut_;
132  };
133 
134  auto states() const
135  -> decltype(this->all_states(visible_state_p{*this}))
136  {
137  return all_states(visible_state_p{*this});
138  }
139 
140  // FIXME: clang workaround.
141  template <typename Pred>
142  struct has_transition_p
143  {
144  bool operator()(transition_t t) const
145  {
146  return (pred(t)
147  && has(aut_.ss_, aut_.src_of(t))
148  && has(aut_.ss_, aut_.dst_of(t)));
149  }
150  const filter_automaton_impl& aut_;
151  Pred pred;
152  };
153 
154  template <typename Pred>
155  auto all_transitions(Pred pred) const
156  -> decltype(this->aut_->all_transitions(has_transition_p<Pred>{*this,
157  pred}))
158  {
159  return aut_->all_transitions(has_transition_p<Pred>{*this, pred});
160  }
161 
162  // FIXME: clang workaround.
163  struct all_transitions_p
164  {
165  bool operator()(transition_t) const { return true; };
166  };
167 
170  auto all_transitions() const
171  -> decltype(this->all_transitions(all_transitions_p{}))
172  {
173  return all_transitions(all_transitions_p{});
174  }
175 
177  auto transitions() const
178  -> decltype(this->all_transitions(has_transition_p<all_transitions_p>
179  {*this, all_transitions_p{}}))
180  {
181  auto pred
182  = has_transition_p<all_transitions_p>{*this, all_transitions_p{}};
183  return all_transitions(pred);
184  }
185 
186  // FIXME: clang workaround.
187  template <typename Pred>
188  struct has_dst_p
189  {
190  bool operator()(transition_t t) const
191  {
192  return pred(t) && has(aut_.ss_, aut_.dst_of(t));
193  }
194  const filter_automaton_impl& aut_;
195  Pred pred;
196  };
197 
198  template <typename Pred>
199  auto all_out(state_t s, Pred pred) const
200  -> decltype(this->aut_->all_out(s, has_dst_p<Pred>{*this, pred}))
201  {
202  return aut_->all_out(s, has_dst_p<Pred>{*this, pred});
203  }
204 
205  auto all_out(state_t s) const
206  -> decltype(this->all_out(s, all_transitions_p{}))
207  {
208  return all_out(s, all_transitions_p{});
209  }
210 
211  // FIXME: clang workaround.
212  struct not_to_post_p
213  {
214  bool operator()(transition_t t) const
215  {
216  return aut_.dst_of(t) != aut_.post();
217  }
218  const filter_automaton_impl& aut_;
219  };
220 
221  auto out(state_t s) const
222  -> decltype(this->all_out(s, not_to_post_p{*this}))
223  {
224  return all_out(s, not_to_post_p{*this});
225  }
226 
227  // FIXME: clang workaround.
228  struct label_equal_p
229  {
230  bool operator()(transition_t t) const
231  {
232  return aut_.labelset()->equal(aut_.label_of(t), label_);
233  }
234  const filter_automaton_impl& aut_;
235  label_t label_;
236  };
237 
238  auto out(state_t s, label_t l) const
239  -> decltype(this->all_out(s, label_equal_p{*this, l}))
240  {
241  return all_out(s, label_equal_p{*this, l});
242  }
243 
244  // FIXME: clang workaround.
245  template <typename Pred>
246  struct has_src_p
247  {
248  bool operator()(transition_t t) const
249  {
250  return pred(t) && has(aut_.ss_, aut_.src_of(t));
251  }
252  const filter_automaton_impl& aut_;
253  Pred pred;
254  };
255 
256  template <typename Pred>
257  auto all_in(state_t s, Pred pred) const
258  -> decltype(this->aut_->all_in(s, has_src_p<Pred>{*this, pred}))
259  {
260  return aut_->all_in(s, has_src_p<Pred>{*this, pred});
261  }
262 
263  auto all_in(state_t s) const
264  -> decltype(this->all_in(s, all_transitions_p{}))
265  {
266  return all_in(s, all_transitions_p{});
267  }
268 
269  // FIXME: clang workaround.
270  struct not_from_pre_p
271  {
272  bool operator()(transition_t t) const
273  {
274  return aut_.src_of(t) != aut_.pre();
275  }
276  const filter_automaton_impl& aut_;
277  };
278 
279  auto in(state_t s) const
280  -> decltype(this->all_in(s, not_from_pre_p{*this}))
281  {
282  return all_in(s, not_from_pre_p{*this});
283  }
284 
285  auto in(state_t s, label_t l) const
286  -> decltype(this->all_in(s, label_equal_p{*this, l}))
287  {
288  return all_in(s, label_equal_p{*this, l});
289  }
290 
291  fresh_automaton_t_of<automaton_t>
292  strip() const
293  {
294  return ::vcsn::copy(aut_, ss_);
295  }
296 
298  auto initial_transitions() const
299  -> decltype(this->out(pre()))
300  {
301  return out(pre());
302  }
303 
305  auto final_transitions() const
306  -> decltype(this->in(post()))
307  {
308  return in(post());
309  }
310 
311  protected:
313  using super_t::aut_;
314 
315  private:
317  states_t ss_;
318  };
319  }
320 
321  template <typename Aut>
322  using filter_automaton =
323  std::shared_ptr<detail::filter_automaton_impl<Aut>>;
324 
326  template <typename Aut>
327  inline
328  filter_automaton<Aut>
329  filter(const Aut& aut, const std::unordered_set<state_t_of<Aut>>& ss)
330  {
331  return make_shared_ptr<filter_automaton<Aut>>(aut, ss);
332  }
333 
334  namespace dyn
335  {
336  namespace detail
337  {
339  template <typename Aut, typename Unsigneds>
340  automaton
341  filter(const automaton& aut, const std::vector<unsigned>& states)
342  {
343  const auto& a = aut->as<Aut>();
344  auto ss = std::unordered_set<state_t_of<Aut>>{};
345  // FIXME: this is wrong, of course.
346  for (auto s: states)
347  ss.emplace(s + 2);
348  return make_automaton(::vcsn::filter(a, ss));
349  }
350  }
351  }
352 }
std::unordered_set< state_t > states_t
States set that we want to filter.
Definition: filter.hh:32
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
Definition: traits.hh:46
static constexpr auto pre(Args &&...args) -> decltype(element_type::pre(std::forward< Args >(args)...))
static constexpr auto post(Args &&...args) -> decltype(element_type::post(std::forward< Args >(args)...))
state_t_of< automaton_t > state_t
Definition: filter.hh:24
label_t_of< automaton_t > label_t
Definition: filter.hh:26
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:48
Aggregate an automaton, and forward calls to it.
static symbol sname()
Static name.
Definition: filter.hh:49
filter_automaton_impl(const automaton_t &input, const states_t &ss)
Definition: filter.hh:41
Hide some states of an automaton.
Definition: filter.hh:18
states_t ss_
The states we keep.
Definition: filter.hh:317
An input/output format.
Definition: format.hh:11
typename detail::transition_t_of_impl< base_t< ValueSet >>::type transition_t_of
Definition: traits.hh:49
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
auto src_of(Args &&...args) const -> decltype(aut_-> src_of(std::forward< Args >(args)...))
std::ostream & print_set(std::ostream &o, format fmt={}) const
Definition: filter.hh:56
auto dst_of(Args &&...args) const -> decltype(aut_-> dst_of(std::forward< Args >(args)...))
std::vector< transition_t > tr_cont_t
Definition: filter.hh:34
transition_t_of< automaton_t > transition_t
Definition: filter.hh:25
automaton_t aut_
The wrapped automaton, possibly const.