Vcsn  2.8
Be Rational
inductive.hh
Go to the documentation of this file.
1 #pragma once
2 
6 #include <vcsn/dyn/automaton.hh>
7 #include <vcsn/dyn/value.hh>
8 #include <vcsn/misc/static-if.hh>
9 
10 namespace vcsn
11 {
12 
13  /*-------------------------.
14  | inductive(expression). |
15  `-------------------------*/
16 
22  template <Automaton Aut, typename ExpSet, typename Tag>
23  Aut
24  inductive(const ExpSet& rs, const typename ExpSet::value_t& r,
25  Tag = {});
26 
27  namespace rat
28  {
34  template <Automaton Aut, typename ExpSet, typename Tag>
36  : public ExpSet::const_visitor
37  {
38  public:
39  using automaton_t = Aut;
40  using expressionset_t = ExpSet;
41  using tag_t = Tag;
43 
46  using expression_t = typename expressionset_t::value_t;
51 
52  using super_t = typename expressionset_t::const_visitor;
53 
55  constexpr static const char* me() { return "inductive"; }
56 
58  : rs_{rs}
59  , as_{rs_.context()}
60  {}
61 
63  {
64  try
65  {
66  v->accept(*this);
67  return std::move(res_);
68  }
69  catch (const std::runtime_error& e)
70  {
71  raise(e, " while computing inductive of: ", to_string(rs_, v));
72  }
73  }
74 
75  private:
77  {
78  try
79  {
80  v->accept(*this);
81  return std::move(res_);
82  }
83  catch (const std::runtime_error& e)
84  {
85  raise(e, " while computing inductive of: ", to_string(rs_, v));
86  }
87  }
88 
89  using tuple_t = typename super_t::tuple_t;
90  template <bool = context_t::is_lat,
91  typename Dummy = void>
92  struct visit_tuple
93  {
95  template <size_t I>
96  auto tape_(const tuple_t& v)
97  {
98  const auto& rs = project<I>(visitor_.rs_);
99  using automaton_t =
101  return ::vcsn::inductive<automaton_t>(rs,
102  std::get<I>(v.sub()),
103  tag_t{});
104  }
105 
107  template <size_t... I>
109  {
110  return visitor_.as_.tuple(tape_<I>(v)...);
111  }
112 
114  auto operator()(const tuple_t& v)
115  {
116  visitor_.res_ = tape_(v, labelset_t::indices);
117  }
119  };
120 
121  template <typename Dummy>
122  struct visit_tuple<false, Dummy>
123  {
124  void operator()(const tuple_t&)
125  {
127  }
129  };
130 
131  void visit(const tuple_t& v, std::true_type) override
132  {
133  visit_tuple<>{*this}(v);
134  }
135 
137  {
138  res_ = as_.zero();
139  }
140 
142  {
143  res_ = as_.one();
144  }
145 
147  {
148  res_ = as_.atom(e.value());
149  }
150 
152  {
153  super_t::visit(e);
154  }
155 
157  template <Automaton AutSet>
158  using compose_mem_fn_t =
159  decltype(std::declval<AutSet>()
160  .compose(std::declval<typename AutSet::value_t>(),
161  std::declval<typename AutSet::value_t>()));
162 
164  template <typename AutSet>
166 
167 
169  {
170  detail::static_if<has_compose_mem_fn<automatonset_t>()
171  && num_tapes<context_t>() == 2>
172  ([this](const auto& e)
173  {
174  auto res = recurse(e.head());
175  for (const auto& c: e.tail())
176  res = as_.compose(res, recurse(c));
177  res_ = std::move(res);
178  },
179  [](const auto&)
180  {
181  raise("compose: context is not composable");
182  })
183  (e);
184  }
185 
187  {
188  detail::static_if<labelset_t::is_letterized()>
189  ([this](const auto& e)
190  {
191  auto res = recurse(e.head());
192  for (const auto& c: e.tail())
193  res = as_.conjunction(res, recurse(c));
194  res_ = std::move(res);
195  },
196  [this](const auto&)
197  {
198  raise("conjunction: labelset must be letterized: ",
199  *rs_.labelset());
200  })
201  (e);
202  }
203 
205  {
206  detail::static_if<labelset_t::is_letterized()>
207  ([this](const auto& e)
208  {
209  auto res = recurse(e.head());
210  for (const auto& c: e.tail())
211  res = as_.infiltrate(res, recurse(c));
212  res_ = std::move(res);
213  },
214  [this](const auto&)
215  {
216  raise("infiltrate: labelset must be letterized: ",
217  *rs_.labelset());
218  })
219  (e);
220  }
221 
223  {
224  detail::static_if<labelset_t::is_letterized()>
225  ([this](const auto& e)
226  {
227  auto res = recurse(e.head());
228  for (const auto& c: e.tail())
229  res = as_.ldivide(res, recurse(c));
230  res_ = std::move(res);
231  },
232  [this](const auto&)
233  {
234  raise("ldivide: labelset must be letterized: ",
235  *rs_.labelset());
236  })
237  (e);
238  }
239 
241  {
242  detail::static_if<labelset_t::is_letterized()>
243  ([this](const auto& e)
244  {
245  auto res = recurse(e.head());
246  for (const auto& c: e.tail())
247  res = as_.shuffle(res, recurse(c));
248  res_ = std::move(res);
249  },
250  [this](const auto&)
251  {
252  raise("shuffle: labelset must be letterized: ",
253  *rs_.labelset());
254  })
255  (e);
256  }
257 
259  {
260  auto res = recurse(e.head());
261  for (const auto& c: e.tail())
262  res = as_.add(res, recurse(c));
263  res_ = std::move(res);
264  }
265 
267  {
268  auto res = recurse(e.head());
269  for (const auto& c: e.tail())
270  res = as_.mul(res, recurse(c));
271  res_ = std::move(res);
272  }
273 
275  {
276  res_ = as_.star(recurse(e.sub()));
277  }
278 
280  {
281  detail::static_if<labelset_t::is_free()>
282  ([this](const auto& e)
283  {
284  res_ = as_.complement(recurse(e.sub()));
285  },
286  [this](const auto&)
287  {
288  raise("complement: labelset must be free: ",
289  *rs_.labelset());
290  })
291  (e);
292  }
293 
295  {
296  res_ = as_.transposition(recurse(e.sub()));
297  }
298 
300  {
301  res_ = as_.lweight(e.weight(), recurse(e.sub()));
302  }
303 
305  {
306  res_ = as_.rweight(recurse(e.sub()), e.weight());
307  }
308 
309  private:
312  automaton_t res_ = nullptr;
313  };
314  } // rat::
315 
316 
317  template <Automaton Aut, typename ExpSet, typename Tag>
318  Aut
319  inductive(const ExpSet& rs, const typename ExpSet::value_t& r, Tag)
320  {
322  return ind(r);
323  }
324 
325  namespace dyn
326  {
327  namespace detail
328  {
330  template <typename ExpSet, typename Tag>
331  automaton inductive_tag_(const ExpSet& rs,
332  const typename ExpSet::value_t& r)
333  {
335  return ::vcsn::inductive<automaton_t>(rs, r, Tag{});
336  }
337 
339  template <typename ExpSet, typename String>
340  automaton
341  inductive(const expression& exp, const std::string& algo)
342  {
343  // FIXME: So far, there is a single implementation of expressions,
344  // but we should actually be parameterized by its type too.
345  using expressionset_t = ExpSet;
346  using expression_t = typename expressionset_t::value_t;
347  const auto& e = exp->as<expressionset_t>();
348 
349  using fn_t
350  = auto(const expressionset_t&, const expression_t&) -> automaton;
351  static const auto map = getarg<std::function<fn_t>>
352  {
353  "inductive algorithm",
354  {
355  {"auto", "standard"},
356  // {"general", inductive_tag_<ExpSet, general_tag>},
357  {"standard", inductive_tag_<ExpSet, standard_tag>},
358  }
359  };
360  return map[algo](e.valueset(), e.value());
361  }
362  }
363  }
364 }
A dyn automaton.
Definition: automaton.hh:17
std::shared_ptr< detail::mutable_automaton_impl< Context > > mutable_automaton
Definition: fwd.hh:25
typename super_t::tuple_t tuple_t
Definition: inductive.hh:89
weight_t_of< context_t > weight_t
Definition: inductive.hh:49
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
auto conjunction(const value_t &l, const value_t &r) const -> value_t
Build an conjunction product: l & r.
automaton_t operator()(const expression_t &v)
Definition: inductive.hh:62
static auto add(const value_t &l, const value_t &r) -> value_t
auto rweight(const value_t &e, const weight_t &w) const -> value_t
Right-multiplication by a weight.
typename detail::state_t_of_impl< base_t< ValueSet > >::type state_t_of
Definition: traits.hh:64
Aut inductive(const ExpSet &rs, const typename ExpSet::value_t &r, Tag={})
Build an automaton by induction from an expression.
Definition: inductive.hh:319
auto shuffle(const value_t &l, const value_t &r) const -> value_t
Build a shuffle product: l : r.
An inner node with multiple children.
Definition: expression.hh:119
VCSN_RAT_VISIT(conjunction, e)
Definition: inductive.hh:186
auto one() const -> value_t
Definition: automatonset.hh:86
typename expressionset_t::value_t expression_t
Definition: inductive.hh:46
An inner node to name the subexpression.
Definition: expression.hh:290
typename detail::context_t_of_impl< base_t< ValueSet > >::type context_t_of
Definition: traits.hh:61
auto tuple(Value &&... v) const -> value_t
Build a tuple: e | f | ....
auto infiltrate(const value_t &l, const value_t &r) const -> value_t
Build an infiltration product: l &: r.
auto ldivide(const value_t &l, const value_t &r) const -> value_t
r`.
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
context_t_of< expressionset_t > context_t
Definition: inductive.hh:44
inductive_visitor(const expressionset_t &rs)
Definition: inductive.hh:57
Definition: a-star.hh:8
auto compose(const value_t &l, const value_t &r) const -> std::enable_if_t< are_composable< Ctx, Ctx >
Build a composition: l @ r.
Build an automaton by induction from an expression.
Definition: inductive.hh:35
labelset_t_of< context_t > labelset_t
Definition: inductive.hh:47
automaton_t recurse(const expression_t &v)
Definition: inductive.hh:76
auto tape_(const tuple_t &v, detail::index_sequence< I... >)
Sum of sizes for all tapes.
Definition: inductive.hh:108
VCSN_RAT_VISIT(infiltrate, e)
Definition: inductive.hh:204
static constexpr const char * me()
Name of this algorithm, for error messages.
Definition: inductive.hh:55
std::string to_string(identities i)
Wrapper around operator<<.
Definition: identities.cc:38
weightset_t_of< context_t > weightset_t
Definition: inductive.hh:48
An inner node implementing a weight.
Definition: expression.hh:256
A static list of size_t.
Definition: tuple.hh:32
auto atom(const label_t &l) const -> value_t
Definition: automatonset.hh:95
VCSN_RAT_VISIT(transposition, e)
Definition: inductive.hh:294
auto star(const value_t &e) const -> value_t
Add a star operator: e*.
return v
Definition: multiply.hh:362
auto complement(const value_t &e, std::true_type) const -> value_t
Add a complement operator: e{c}.
void visit(const tuple_t &v, std::true_type) override
Definition: inductive.hh:131
auto operator()(const tuple_t &v)
Entry point.
Definition: inductive.hh:114
typename expressionset_t::const_visitor super_t
Definition: inductive.hh:52
A mapping from strings to Values.
Definition: getargs.hh:33
static auto mul(const value_t &l, const value_t &r) -> value_t
auto tape_(const tuple_t &v)
One tape.
Definition: inductive.hh:96
value_impl< detail::expression_tag > expression
Definition: fwd.hh:31
VCSN_RAT_VISIT(complement, e)
Definition: inductive.hh:279
automaton inductive_tag_(const ExpSet &rs, const typename ExpSet::value_t &r)
Helper function to facilitate dispatch below.
Definition: inductive.hh:331
auto transposition(const value_t &e) const -> value_t
Add a transposition operator.
typename detail::weight_t_of_impl< base_t< ValueSet > >::type weight_t_of
Definition: traits.hh:66
#define BUILTIN_UNREACHABLE()
Definition: builtins.hh:13
return res
Definition: multiply.hh:399
auto zero() const -> value_t
Definition: automatonset.hh:78
auto lweight(const weight_t &w, const value_t &e) const -> value_t
Left-multiplication by a weight.
decltype(std::declval< AutSet >() .compose(std::declval< typename AutSet::value_t >(), std::declval< typename AutSet::value_t >())) compose_mem_fn_t
The type of the AutSet::compose() member function.
Definition: inductive.hh:161
state_t_of< automaton_t > state_t
Definition: inductive.hh:50