Vcsn  2.8
Be Rational
filter.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm> // std::max
4 
5 #include <boost/range/irange.hpp>
6 #include <boost/optional.hpp>
7 
8 #include <vcsn/algos/copy.hh>
10 #include <vcsn/core/automaton.hh> // all_transitions
11 #include <vcsn/dyn/fwd.hh>
12 #include <vcsn/misc/crange.hh>
14 #include <vcsn/misc/sparse-set.hh>
15 #include <vcsn/misc/vector.hh>
16 #include <vcsn/misc/static-if.hh>
17 
18 namespace vcsn
19 {
20  namespace detail
21  {
23  template <typename Container, bool Has = false>
25  {
26  public:
27  template <typename... Args>
28  optional_container(Args&&...)
29  {}
30  };
31 
32  template <typename Container>
33  class optional_container<Container, true>
34  {
35  public:
36  template <typename... Args>
37  optional_container(Args&&... args)
38  : cont_(std::forward<Args>(args)...)
39  {}
40  protected:
41  Container cont_;
42  };
43 
47  template <Automaton Aut, bool Trans = false>
49  : public automaton_decorator<Aut>
50  , public optional_container<dynamic_bitset, Trans>
51  {
52  public:
53  using automaton_t = Aut;
59 
63 
64  using tr_cont_t = std::vector<transition_t>;
65 
66  using super_t::pre;
67  using super_t::post;
68  using super_t::src_of;
69  using super_t::dst_of;
70 
77  const boost::optional<states_t>& ss = {},
78  const boost::optional<transitions_t>& ts = {})
79  : super_t(input)
80  // FIXME: wasting space allocating the transition vector,
81  // even if we don't use it.
83  , ss_(ss ? *ss : states_t(states_size(input)))
84  {
85  if (ss)
86  {
87  ss_.set(input->pre());
88  ss_.set(input->post());
89  }
90  else
91  unhide_all_states();
92  static_if<Trans>([&ts](auto& self) {
93  if (!ts)
94  self.unhide_all_transitions();
95  })(*this);
96  }
97 
99  static symbol sname()
100  {
101  static auto res = symbol{"filter_automaton<"
103  return res;
104  }
105 
106  std::ostream& print_set(std::ostream& o, format fmt = {}) const
107  {
108  o << "filter_automaton<";
109  aut_->print_set(o, fmt);
110  return o << '>';
111  }
112 
113  bool state_has_name(state_t s) const
114  {
115  assert(has(ss_, s));
116  return aut_->state_has_name(s);
117  }
118 
119  bool has_state(state_t s) const
120  {
121  return has(ss_, s) && aut_->has_state(s);
122  }
123 
124  using super_t::has_transition;
125 
126  template <bool U = Trans>
127  std::enable_if_t<U, bool>
128  has_transition(transition_t t) const
129  {
130  return has(this->cont_, t) && aut_->has_transition(t);
131  }
132 
133  template <bool U = Trans>
134  std::enable_if_t<!U, bool>
135  has_transition(transition_t t) const
136  {
137  return aut_->has_transition(t);
138  }
139 
140  std::ostream& print_state_name(state_t s, std::ostream& o,
141  format fmt = {},
142  bool delimit = false) const
143  {
144  assert(has(ss_, s));
145  return aut_->print_state_name(s, o, fmt, delimit);
146  }
147 
148  size_t num_states() const
149  {
150  return states().size();
151  }
152 
153  size_t num_all_states() const
154  {
155  return all_states().size();
156  }
157 
158  template <typename Pred>
159  auto all_states(Pred pred) const
160  {
161  return aut_->all_states([this, pred](state_t s)
162  {
163  return pred(s) && has(ss_, s);
164  });
165  }
166 
167  auto all_states() const
168  {
169  return all_states([](state_t) { return true; });
170  }
171 
172  auto states() const
173  {
174  return all_states([this](state_t s)
175  {
176  // When transposing post() < pre().
177  return std::max(pre(), post()) < s;
178  });
179  }
180 
183  auto all_transitions() const
184  {
185  return vcsn::detail::all_transitions
186  (aut_,
187  [this](transition_t t)
188  {
189  return has_transition(t)
190  && has(ss_, aut_->src_of(t))
191  && has(ss_, aut_->dst_of(t));
192  });
193  }
194 
196  auto all_out(state_t s) const
197  {
198  return vcsn::detail::all_out(aut_, s,
199  [this](transition_t t)
200  {
201  return has_transition(t)
202  && has(ss_, aut_->dst_of(t));
203  });
204  }
205 
207  auto all_in(state_t s) const
208  {
209  return vcsn::detail::all_in(aut_, s,
210  [this](transition_t t)
211  {
212  return has_transition(t)
213  && has(ss_, aut_->src_of(t));
214  });
215  }
216 
217  void
218  hide_state(state_t s)
219  {
220  if (s < ss_.size())
221  ss_.reset(s);
222  }
223 
226  template <bool U = Trans>
227  std::enable_if_t<U, void>
228  hide_transition(transition_t t)
229  {
230  if (t < optional_container_t::cont_.size())
231  optional_container_t::cont_.reset(t);
232  }
233 
235  void
236  unhide_state(state_t s)
237  {
238  if (s < ss_.size())
239  ss_.set(s);
240  }
241 
244  template <bool U = Trans>
245  std::enable_if_t<U, void>
246  unhide_transition(transition_t t)
247  {
248  if (t < optional_container_t::cont_.size())
249  optional_container_t::cont_.set(t);
250  }
251 
255  void
256  hide_all_states()
257  {
258  ss_.reset();
259  ss_.set(aut_->pre());
260  ss_.set(aut_->post());
261  }
262 
266  void
267  unhide_all_states()
268  {
269  ss_.set();
270  }
271 
272  template <bool U = Trans>
273  std::enable_if_t<U, void>
274  unhide_all_transitions()
275  {
276  optional_container_t::cont_.set();
277  }
278 
279  template <bool U = Trans>
280  std::enable_if_t<U, void>
281  hide_all_transitions()
282  {
283  optional_container_t::cont_.reset();
284  }
285 
286  fresh_automaton_t_of<automaton_t>
287  strip() const
288  {
289  auto state_filter = [this](state_t_of<automaton_t> s)
290  {
291  return has(this->ss_, s);
292  };
293  auto transition_filter = [this](transition_t_of<automaton_t> t)
294  {
295  return this->has_transition(t);
296  };
297  return ::vcsn::copy(aut_, state_filter, transition_filter);
298  }
299 
300  protected:
302  using super_t::aut_;
303 
304  private:
306  states_t ss_;
307  };
308  }
309 
310  template <Automaton Aut, bool Trans = false>
311  using filter_automaton =
312  std::shared_ptr<detail::filter_automaton_impl<Aut, Trans>>;
313 
319  template <Automaton Aut, bool Trans = false>
320  filter_automaton<Aut, Trans>
321  filter(const Aut& aut,
322  boost::optional<dynamic_bitset> ss = {},
323  boost::optional<dynamic_bitset> ts = {})
324  {
325  return make_shared_ptr<filter_automaton<Aut, Trans>>(aut, ss, ts);
326  }
327 
332  template <Automaton Aut>
333  filter_automaton<Aut>
334  filter(const Aut& aut, const std::unordered_set<state_t_of<Aut>>& ss)
335  {
336  return filter(aut, make_dynamic_bitset(ss, states_size(aut)));
337  }
338 
339  namespace dyn
340  {
341  namespace detail
342  {
344  template <Automaton Aut, typename Unsigneds>
345  automaton
346  filter(const automaton& aut, const std::vector<unsigned>& states)
347  {
348  const auto& a = aut->as<Aut>();
349  // FIXME: This is a problem for lazy automaton.
350  auto size = states_size(a);
351  auto ss = dynamic_bitset(size);
352  for (auto s: states)
353  if (s + 2 < size)
354  ss.set(s + 2);
355  return ::vcsn::filter(a, ss);
356  }
357  }
358  }
359 }
typename detail::transition_t_of_impl< base_t< ValueSet > >::type transition_t_of
Definition: traits.hh:65
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
size_t states_size(const Aut &aut)
The largest state number, plus one.
Definition: automaton.hh:41
filter_automaton_impl(const automaton_t &input, const boost::optional< states_t > &ss={}, const boost::optional< transitions_t > &ts={})
Build a filtered view of an automaton.
Definition: filter.hh:76
state_t_of< automaton_t > state_t
Definition: filter.hh:56
label_t_of< automaton_t > label_t
Definition: filter.hh:58
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:21
transition_t_of< automaton_t > transition_t
Definition: filter.hh:57
std::ostream & print_set(std::ostream &o, format fmt={}) const
Definition: filter.hh:106
An input/output format for valuesets.
Definition: format.hh:13
Definition: a-star.hh:8
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
std::vector< transition_t > tr_cont_t
Definition: filter.hh:64
std::unordered_set< state_t_of< Aut > > states_t
Definition: accessible.hh:20
boost::dynamic_bitset<> dynamic_bitset
Aggregate an automaton, and forward calls to it.
symbol sname()
Definition: name.hh:65
Enables or not the presence of a container in a class.
Definition: filter.hh:24
std::vector< std::pair< string_t, string_t > > transitions_t
Definition: parse.hh:72
size_t transitions_size(const Aut &aut)
The largest transition number, plus one.
Definition: automaton.hh:51
Hide some states of an automaton.
Definition: filter.hh:48
Looking downstream.
STL namespace.
return res
Definition: multiply.hh:399
static symbol sname()
Static name.
Definition: filter.hh:99