Vcsn  2.5
Be Rational
expressionset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <set>
4 #include <string>
5 
9 #include <vcsn/ctx/context.hh>
12 #include <vcsn/labelset/oneset.hh>
13 #include <vcsn/misc/raise.hh>
14 #include <vcsn/misc/star-status.hh>
15 #include <vcsn/misc/symbol.hh>
16 #include <vcsn/weightset/b.hh>
17 #include <vcsn/weightset/nmin.hh>
18 #include <vcsn/weightset/q.hh>
19 #include <vcsn/weightset/r.hh>
20 #include <vcsn/weightset/z.hh>
21 #include <vcsn/weightset/zmin.hh>
22 
23 #include <vcsn/core/rat/project.hh>
24 
25 namespace vcsn
26 {
27  namespace rat
28  {
31  template <typename Context>
33  {
34  public:
36  using context_t = Context;
40  using labelset_ptr = typename context_t::labelset_ptr;
41  using weightset_ptr = typename context_t::weightset_ptr;
43  using weight_t = typename weightset_t::value_t;
46 
47  private:
58  const self_t& self() const { return static_cast<const self_t&>(*this); }
59 
60  public:
62  //
63  // See http://stackoverflow.com/questions/15537023 to know why we
64  // add the vcsn::rat:: part: GCC wants it, Clang does not care,
65  // both are right.
66 #define DEFINE(Type) \
67  using Type ## _t = vcsn::rat::Type<context_t>
87 #undef DEFINE
88 
90  using value_t = typename node_t::value_t;
92  using type_t = typename node_t::type_t;
94  using values_t = typename node_t::values_t;
95 
96  template <type_t Type>
98  template <type_t Type>
100 
101  using word_t = value_t;
102  using letter_t = value_t;
103 
105  static symbol sname();
107  static self_t make(std::istream& is);
108 
113 
117  bool open(bool o) const;
118 
120  const context_t& context() const;
121 
123  identities_t identities() const;
124 
126  const labelset_ptr& labelset() const;
128  const weightset_ptr& weightset() const;
129 
131  static value_t special()
132  {
133  return atom(labelset_t::special());
134  }
135 
137  static bool is_special(const value_t& v)
138  {
139  return equal(special(), v);
140  }
141 
143  bool is_letter(value_t) const
144  {
145  return false;
146  }
147 
151  bool is_zero(const value_t& v) const ATTRIBUTE_PURE;
152 
156  static bool is_one(const value_t& v) ATTRIBUTE_PURE;
157 
159  bool is_universal(const value_t& v) const ATTRIBUTE_PURE;
160 
162  static constexpr bool is_letterized()
163  {
164  return false;
165  }
166 
168  static constexpr bool is_commutative()
169  {
170  return false;
171  }
172 
174  static constexpr bool is_idempotent()
175  {
176  // FIXME: well, the truth is that we are idempotent if the
177  // weightset is, _and_ we apply ACI to addition.
178  return weightset_t::is_idempotent();
179  }
180 
182  static constexpr bool show_one()
183  {
184  return false;
185  }
186 
188  static constexpr bool has_lightening_weights()
189  {
190  return weightset_t::has_lightening_weights();
191  }
192 
194  static constexpr bool has_one()
195  {
196  return true;
197  }
198 
200  static constexpr bool is_expressionset()
201  {
202  return true;
203  }
204 
206  static constexpr bool is_free()
207  {
208  return false;
209  }
210 
212  static constexpr star_status_t star_status()
213  {
215  }
216 
217  template <typename GenSet>
218  auto conv(const letterset<GenSet>& ls,
219  typename letterset<GenSet>::value_t v) const -> value_t;
220  auto conv(b, typename b::value_t v) const -> value_t;
221  auto conv(const z& ws, typename z::value_t v) const -> value_t;
222  auto conv(const q& ws, typename q::value_t v) const -> value_t;
223  auto conv(const r& ws, typename r::value_t v) const -> value_t;
224  auto conv(const nmin& ws, typename nmin::value_t v) const -> value_t;
225  auto conv(const zmin& ws, typename zmin::value_t v) const -> value_t;
226  template <typename Ctx2>
227  auto conv(const expressionset<Ctx2>& ws,
228  typename expressionset<Ctx2>::value_t v) const -> value_t;
229 
231  static auto size(const value_t& v) -> size_t;
232 
234  static auto compare(const value_t& l, const value_t& r) -> int;
235 
237  static auto less(const value_t& l, const value_t& r) -> bool;
238 
243  static bool less_linear(const value_t& l, const value_t& r);
244 
246  static auto equal(const value_t& l, const value_t& r) -> bool;
247 
249  static auto hash(const value_t& v) -> size_t;
250 
252  static auto atom(const label_t& v) -> value_t;
253 
254  // Concrete type implementation.
255  auto zero() const -> value_t;
256  static auto one() -> value_t;
257  auto add(const value_t& l, const value_t& r) const -> value_t;
258  auto mul(const value_t& l, const value_t& r) const -> value_t;
259 
269  auto concat(const value_t& l, const value_t& r) const -> value_t;
270 
272  auto compose(const value_t& l, const value_t& r) const -> value_t;
273 
275  auto conjunction(const value_t& l, const value_t& r) const -> value_t;
276 
278  auto infiltrate(const value_t& l, const value_t& r) const -> value_t;
279 
281  auto shuffle(const value_t& l, const value_t& r) const -> value_t;
282 
284  template <typename... Value>
285  auto tuple(Value&&... v) const -> value_t;
286 
288  auto power(const value_t& e, unsigned n) const -> value_t;
289 
291  auto ldivide(const value_t& l, const value_t& r) const -> value_t;
292 
294  auto rdivide(const value_t& l, const value_t& r) const -> value_t;
295 
297  auto star(const value_t& e) const -> value_t;
298 
300  auto complement(const value_t& e) const -> value_t;
302  auto transposition(const value_t& e) const -> value_t;
304  auto rweight(const value_t& e, const weight_t& w) const -> value_t;
306  auto lweight(const weight_t& w, const value_t& e) const -> value_t;
308  auto transpose(const value_t& e) const -> value_t;
309 
311  auto word(label_t l) const -> word_t
312  {
313  return l;
314  }
315 
317  template <typename... Args>
318  auto letter_class(Args&&... chars) const -> value_t;
319 
321  auto conv(std::istream& is, bool = true) const -> value_t;
322 
324  auto conv(const self_t&, const value_t& v) const -> value_t;
325 
327  template <typename Fun>
328  void convs(std::istream&, Fun) const
329  {
330  raise(*this, ": ranges not implemented");
331  }
332 
333  auto print(const value_t& v,
334  std::ostream& o = std::cout, format fmt = {}) const
335  -> std::ostream&;
336 
338  auto print_set(std::ostream& o, format fmt = {}) const
339  -> std::ostream&;
340 
342  template <unsigned Tape, typename Ctx = context_t>
343  using project_t
345 
347  template <unsigned Tape>
348  auto project() const
349  -> project_t<Tape>
350  {
351  return vcsn::detail::project<Tape>(self());
352  }
353 
355  template <size_t Tape>
356  auto project(const value_t& v) const
357  -> decltype(::vcsn::rat::project<Tape>(this->self(), v))
358  {
359  return ::vcsn::rat::project<Tape>(self(), v);
360  }
361 
362  template <typename Sequence>
364 
365  template <size_t... I>
366  struct as_tupleset_impl<detail::index_sequence<I...>>
367  {
370 
371  static type value(const self_t& self)
372  {
373  return {detail::project<I>(self)...};
374  }
375  };
376 
378  template <typename Ctx = context_t>
379  using as_tupleset_t
381 
386  template <typename Ctx = context_t>
387  auto as_tupleset() const
388  -> std::enable_if_t<Ctx::is_lat, as_tupleset_t<Ctx>>
389  {
391  }
392 
393  private:
396  auto add_(values_t&& vs) const -> value_t;
397 
398  auto add_linear_(const add_t& addends, const value_t& r) const -> value_t;
399  auto add_linear_(const add_t& s1, const add_t& s2) const -> value_t;
400 
404  auto add_linear_(const value_t& l, const value_t& r) const -> value_t;
405 
408  static auto unwrap_possible_lweight_(const value_t& e) -> value_t;
411  static type_t type_ignoring_lweight_(const value_t& e);
415 
419  template <type_t Type>
420  void gather_(values_t& res, const value_t& v) const;
421 
426  template <type_t Type>
427  values_t gather_(const value_t& l, const value_t& r) const;
428 
430  auto concat_(const value_t& l, const value_t& r, std::true_type) const -> value_t;
432  auto concat_(const value_t& l, const value_t& r, std::false_type) const -> value_t;
433 
435  template <typename LabelSet_, typename... Args>
436  auto letter_class_(const Args&&... chars, std::true_type) const -> value_t;
437 
439  template <typename LabelSet_>
440  value_t
441  letter_class_(std::set<std::pair<typename LabelSet_::letter_t,
442  typename LabelSet_::letter_t>> chars,
443  bool accept,
444  std::false_type) const;
445 
447  template <typename Dummy = void>
449  {
451  static bool is_label(const tuple_t& v)
452  {
453  return is_label_(v, labelset_t::indices);
454  }
455 
458  label_t as_label(const tuple_t& v) const
459  {
460  return as_label_(v, labelset_t::indices);
461  }
462 
464  template <size_t... I>
466  {
467  for (auto b: {(std::get<I>(v.sub())->type() == type_t::atom
468  || (std::get<I>(v.sub())->type() == type_t::one
469  && labelset_t::template valueset_t<I>::has_one()))...})
470  if (!b)
471  return false;
472  return true;
473  }
474 
475  template <size_t... I>
477  {
478  return label_t{as_label_<I>(v)...};
479  }
480 
482  template <size_t I>
483  typename project_t<I>::label_t as_label_(const tuple_t& v) const
484  {
485  if (std::get<I>(v.sub())->type() == type_t::one)
486  return detail::label_one(rs_.labelset()->template set<I>());
487  else
488  return std::dynamic_pointer_cast<const typename project_t<I>::atom_t>
489  (std::get<I>(v.sub()))->value();
490  }
491  const self_t& rs_;
492  };
493 
494  private:
499  };
500  } // rat::
501 
502  namespace detail
503  {
505  template <typename Ctx>
507  {
509  static type value(const type& ls)
510  {
511  return ls;
512  }
513  };
514 
516  template <typename Ctx>
518  {
520  static type value(const type& ls)
521  {
522  return ls;
523  }
524  };
525 
527  template <typename Ctx1, typename Ctx2>
528  struct join_impl<expressionset<Ctx1>, expressionset<Ctx2>>
529  {
533 
534  static type join(const type1& a, const type2& b)
535  {
536  return {vcsn::join(a.context(), b.context()),
537  vcsn::join(a.identities(), b.identities())};
538  }
539  };
540 
542  // FIXME: what about the other labelsets?
543  template <typename GenSet1, typename Ctx2>
544  struct join_impl<letterset<GenSet1>, expressionset<Ctx2>>
545  {
551 
552  static type join(const type1& a, const type2& b)
553  {
554  return {context_t{vcsn::join(a, *b.labelset()), *b.weightset()},
555  b.identities()};
556  }
557  };
558 
559  // B. FIXME: screams for refactoring!
560  template <typename Context>
561  struct join_impl<b, expressionset<Context>>
562  {
564  static type join(const b&, const type& rhs)
565  {
566  return rhs;
567  }
568  };
569 
570  template <typename W1, typename W2>
572 
573  template <typename WeightSet, typename Context>
575  {
576  using type1 = WeightSet;
581  static type join(const type1& ws, const type2& rs)
582  {
583  return {context_t{*rs.labelset(), vcsn::join(ws, *rs.weightset())},
584  rs.identities()};
585  }
586  };
587 #define JOIN_IMPL_SIMPLE(WS) \
588  template <typename Context> \
589  struct join_impl<WS, expressionset<Context>> \
590  : public join_impl_simple<WS, expressionset<Context>> \
591  {};
592 
593 
598 
599 #undef JOIN_IMPL_SIMPLE
600 
601  }
602 
604  template <typename LabelSet, typename WeightSet>
605  auto
607  rat::identities ids = {})
609  {
610  return {ctx, ids};
611  }
612 
614  template <typename Context>
615  auto
617  rat::identities ids = {})
619  {
620  return {rs.context(), ids};
621  }
622 
624  template <typename Ctx1, typename Ctx2>
625  auto
628  {
629  return {meet(a.context(), b.context()),
630  meet(a.identities(), b.identities())};
631  }
632 
633 
634  /*----------------.
635  | random_label. |
636  `----------------*/
637 
639  template <typename Context,
640  typename RandomGenerator = std::default_random_engine>
643  RandomGenerator& gen = RandomGenerator())
644  {
645  return rs.atom(random_label(*rs.labelset(), gen));
646  }
647 } // namespace vcsn
648 
650 
651 // This is ugly, yet I don't know how to address this circular
652 // dependency another way: expressionset.hxx uses is-valid-expression.hh,
653 // which, of course, also uses expressionset.hh.
654 //
655 // So let's have expressionset.hh first accept a forward declaration (via
656 // algos/fwd.hh), then provide here the needed definition. Do not
657 // leave this inside the CPP guard.
658 
auto transpose(const value_t &e) const -> value_t
The transposed of this rational expression.
auto zero() const -> value_t
auto letter_class_(const Args &&... chars, std::true_type) const -> value_t
If labelset is oneset.
auto transposition(const value_t &e) const -> value_t
Add a transposition operator.
std::shared_ptr< const node_t > value_t
An expression usable with value semantics.
Definition: expression.hh:88
typename node_t::type_t type_t
Type tag for AST classes.
::vcsn::rat::identities identities
Sets of identities on expressions.
Definition: fwd.hh:17
context_t ctx_
The context of the expressions.
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:55
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:173
typename node_t::values_t values_t
A list (vector) of expressions.
auto concat(const value_t &l, const value_t &r) const -> value_t
Similar to mul, but in the case of LAW, merge the labels.
The abstract parameterized, root for all rational expression types.
Definition: expression.hh:80
auto concat_(const value_t &l, const value_t &r, std::true_type) const -> value_t
If labelset is wordset.
auto conjunction(const value_t &l, const value_t &r) const -> value_t
Build an conjunction product: l & r.
The smallest nullableset which includes LabelSet.
Definition: labelset.hh:139
return v
Definition: multiply.hh:361
Definition: a-star.hh:8
project_t< I >::label_t as_label_(const tuple_t &v) const
The expression on tape I is actually a label: get it.
return res
Definition: multiply.hh:398
typename weightset_t::value_t weight_t
auto rdivide(const value_t &l, const value_t &r) const -> value_t
Build a right division: l {/} r.
typename as_tupleset_impl< typename labelset_t_of< Ctx >::indices_t::type >::type as_tupleset_t
If we are multitape, our type as a tupleset.
identities meet(identities i1, identities i2)
Definition: identities.cc:76
identities_t identities() const
Accessor to the identities set.
auto star(const value_t &e) const -> value_t
Add a star operator: e*.
const identities_t ids_
The set of rewriting rules to apply.
static constexpr bool show_one()
When used as WeightSet.
auto ldivide(const value_t &l, const value_t &r) const -> value_t
r`.
static bool is_special(const value_t &v)
When used as a LabelSet.
letter_t value_t
Definition: letterset.hh:33
std::vector< value_t > values_t
Definition: expression.hh:89
static bool is_label_(const tuple_t &v, detail::index_sequence< I... >)
Are all the components on I... labels?
static auto atom(const label_t &v) -> value_t
Build a label.
expressionset_impl(const context_t &ctx, identities_t ids={})
Constructor.
bool open(bool o) const
Whether unknown letters should be added, or rejected.
An expressionset can implement several different sets of identities on expressions.
Definition: identities.hh:20
bool is_universal(const value_t &v) const ATTRIBUTE_PURE
Whether v is the 0{c}.
static auto one() -> value_t
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:21
typename node_t::value_t value_t
An expression (a shared pointer to a tree).
STL namespace.
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:82
auto project(const value_t &v) const -> decltype(::vcsn::rat::project< Tape >(this->self(), v))
Project a multitape expression.
static auto equal(const value_t &l, const value_t &r) -> bool
Whether l == r.
auto infiltrate(const value_t &l, const value_t &r) const -> value_t
Build an infiltration product: l &: r.
label_t as_label_(const tuple_t &v, detail::index_sequence< I... >) const
void convs(std::istream &, Fun) const
Read a range of expressions.
A typed expression set.
star_status_t
Definition: star-status.hh:5
static auto hash(const value_t &v) -> size_t
Hash v.
weightset_t_of< context_t > weightset_t
static bool is_one(const value_t &v) ATTRIBUTE_PURE
Whether v is the \\e.
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
Definition: pair.hh:252
static self_t make(std::istream &is)
Build from the description in is.
static symbol sname()
Static description key.
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
decltype(join(std::declval< ValueSets >()...)) join_t
The type of the join of the ValueSets.
Definition: join.hh:78
typename detail::weightset_t_of_impl< base_t< ValueSet > >::type weightset_t_of
Definition: traits.hh:67
static identities ids(const driver &d)
Get the identities of the driver.
Definition: parse.cc:89
rat::type_t type_t
The possible types of expressions.
Definition: expression.hh:26
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
auto tuple(Value &&... v) const -> value_t
Build a tuple: e | f | ....
static value_t special()
When used as a LabelSet.
auto add(const value_t &l, const value_t &r) const -> value_t
#define DEFINE(Type)
Type of expressions.
const context_t & context() const
Accessor to the context.
auto word(label_t l) const -> word_t
Make a `word&#39; out of an expression.
const values_t sub() const
Definition: expression.hh:210
labelset_t_of< context_t > labelset_t
The root from which to derive the final node types.
Definition: expression.hh:289
const labelset_ptr & labelset() const
Accessor to the labelset.
static constexpr bool is_commutative()
When used as WeightSet.
label_t_of< context_t > label_t
static auto less(const value_t &l, const value_t &r) -> bool
Whether l < r.
label_t as_label(const tuple_t &v) const
All the components are (single-tape) labels: make this a multitape label.
auto conv(const letterset< GenSet > &ls, typename letterset< GenSet >::value_t v) const -> value_t
static constexpr bool is_free()
When used as WeightSet.
auto letter_class(Args &&... chars) const -> value_t
An expression matching one character amongst chars.
An input/output format for valuesets.
Definition: format.hh:13
static constexpr bool is_expressionset()
When used as WeightSet.
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
static constexpr bool is_idempotent()
When used as WeightSet.
static auto compare(const value_t &l, const value_t &r) -> int
Three-way comparison.
auto shuffle(const value_t &l, const value_t &r) const -> value_t
Build a shuffle product: l : r.
void gather_(values_t &res, const value_t &v) const
Push v in res, applying associativity if possible.
A structure that implements the computation of join(V1, V2).
Definition: join.hh:18
static auto size(const value_t &v) -> size_t
The size of v.
static constexpr bool has_one()
When used as WeightSet.
auto compose(const value_t &l, const value_t &r) const -> value_t
Build a composition: l @ r.
An inner node with multiple children.
Definition: expression.hh:118
auto print(const value_t &v, std::ostream &o=std::cout, format fmt={}) const -> std::ostream &
The LAW from a LAL.
Definition: labelset.hh:250
auto project() const -> project_t< Tape >
The expressionset for the Tape-th tape.
#define JOIN_IMPL_SIMPLE(WS)
An inner node implementing a weight.
Definition: expression.hh:255
static auto unwrap_possible_lweight_(const value_t &e) -> value_t
If e is an lweight, then its child, otherwise e.
expressionset< Context >::value_t random_label(const expressionset< Context > &rs, RandomGenerator &gen=RandomGenerator())
Random label from expressionset: limited to a single label.
static bool less_linear(const value_t &l, const value_t &r)
Whether l < r, ignoring lweight.
auto print_set(std::ostream &o, format fmt={}) const -> std::ostream &
Format the description of this expressionset.
static bool is_label(const tuple_t &v)
Are all the components labels?
Implementation of labels are letters.
Definition: fwd.hh:10
bool is_letter(value_t) const
When used as a LabelSet.
auto lweight(const weight_t &w, const value_t &e) const -> value_t
Left-multiplication by a weight.
static constexpr bool is_letterized()
When used as a labelset.
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:239
static weight_t possibly_implicit_lweight_(const value_t &e)
The weight of e if it&#39;s an lweight, otherwise the weight one().
static type_t type_ignoring_lweight_(const value_t &e)
The type of e, or the type of its child if e is a lweight.
Request the set implementation (bool weights).
typename context_t::labelset_ptr labelset_ptr
static constexpr star_status_t star_status()
When used as WeightSet.
auto make_expressionset(const context< LabelSet, WeightSet > &ctx, rat::identities ids={}) -> expressionset< context< LabelSet, WeightSet >>
Shorthand to expressionset constructor.
static type join(const b &, const type &rhs)
const weightset_ptr & weightset() const
Accessor to the weightset.
auto add_(values_t &&vs) const -> value_t
From a list of values, build a sum, taking care of the empty and singleton cases. ...
Turn a tuple of expressions that are labels into a multi-tape label.
auto as_tupleset() const -> std::enable_if_t< Ctx::is_lat, as_tupleset_t< Ctx >>
If we are multitape, ourself as a tupleset.
always valid.
Definition: star-status.hh:17
auto add_linear_(const add_t &addends, const value_t &r) const -> value_t
typename context_t::weightset_ptr weightset_ptr
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
static constexpr bool has_lightening_weights()
When used as WeightSet.
auto complement(const value_t &e) const -> value_t
Add a complement operator: e{c}.
auto rweight(const value_t &e, const weight_t &w) const -> value_t
Right-multiplication by a weight.
An inner node.
Definition: expression.hh:101
auto mul(const value_t &l, const value_t &r) const -> value_t
bool is_zero(const value_t &v) const ATTRIBUTE_PURE
Whether v is the \\z.
auto power(const value_t &e, unsigned n) const -> value_t
Add a power operator: e{n}.