Vcsn  2.8
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>
88 #undef DEFINE
89 
91  using value_t = typename node_t::value_t;
93  using type_t = typename node_t::type_t;
95  using values_t = typename node_t::values_t;
96 
97  template <type_t Type>
99  template <type_t Type>
101 
102  using word_t = value_t;
103  using letter_t = value_t;
104 
106  static symbol sname();
108  static self_t make(std::istream& is);
109 
114 
118  bool open(bool o) const;
119 
121  const context_t& context() const;
122 
124  identities_t identities() const;
125 
127  const labelset_ptr& labelset() const;
129  const weightset_ptr& weightset() const;
130 
132  static value_t special()
133  {
134  return atom(labelset_t::special());
135  }
136 
138  static bool is_special(const value_t& v)
139  {
140  return equal(special(), v);
141  }
142 
144  bool is_letter(value_t) const
145  {
146  return false;
147  }
148 
152  bool is_zero(const value_t& v) const ATTRIBUTE_PURE;
153 
157  static bool is_one(const value_t& v) ATTRIBUTE_PURE;
158 
160  bool is_universal(const value_t& v) const ATTRIBUTE_PURE;
161 
163  static constexpr bool is_letterized()
164  {
165  return false;
166  }
167 
169  static constexpr bool is_commutative()
170  {
171  return false;
172  }
173 
175  static constexpr bool is_idempotent()
176  {
177  // FIXME: well, the truth is that we are idempotent if the
178  // weightset is, _and_ we apply ACI to addition.
179  return weightset_t::is_idempotent();
180  }
181 
183  static constexpr bool show_one()
184  {
185  return false;
186  }
187 
189  static constexpr bool has_lightening_weights()
190  {
191  return weightset_t::has_lightening_weights();
192  }
193 
195  static constexpr bool has_one()
196  {
197  return true;
198  }
199 
201  static constexpr bool is_expressionset()
202  {
203  return true;
204  }
205 
207  static constexpr bool is_free()
208  {
209  return false;
210  }
211 
213  static constexpr star_status_t star_status()
214  {
216  }
217 
218  template <typename GenSet>
219  auto conv(const letterset<GenSet>& ls,
220  typename letterset<GenSet>::value_t v) const -> value_t;
221  auto conv(b, typename b::value_t v) const -> value_t;
222  auto conv(const z& ws, typename z::value_t v) const -> value_t;
223  auto conv(const q& ws, typename q::value_t v) const -> value_t;
224  auto conv(const r& ws, typename r::value_t v) const -> value_t;
225  auto conv(const nmin& ws, typename nmin::value_t v) const -> value_t;
226  auto conv(const zmin& ws, typename zmin::value_t v) const -> value_t;
227  template <typename Ctx2>
228  auto conv(const expressionset<Ctx2>& ws,
229  typename expressionset<Ctx2>::value_t v) const -> value_t;
230 
232  static auto size(const value_t& v) -> size_t;
233 
235  static auto compare(const value_t& l, const value_t& r) -> int;
236 
238  static auto less(const value_t& l, const value_t& r) -> bool;
239 
244  static bool less_linear(const value_t& l, const value_t& r);
245 
247  static auto equal(const value_t& l, const value_t& r) -> bool;
248 
250  static auto hash(const value_t& v) -> size_t;
251 
253  static auto atom(const label_t& v) -> value_t;
254 
256  auto name(const value_t& v, symbol name) const -> value_t;
257 
258  // Concrete type implementation.
259  static auto zero() -> value_t;
260  static auto one() -> value_t;
261  auto add(const value_t& l, const value_t& r) const -> value_t;
262  auto mul(const value_t& l, const value_t& r) const -> value_t;
263 
273  auto concat(const value_t& l, const value_t& r) const -> value_t;
274 
276  auto compose(const value_t& l, const value_t& r) const -> value_t;
277 
279  auto conjunction(const value_t& l, const value_t& r) const -> value_t;
280 
282  auto infiltrate(const value_t& l, const value_t& r) const -> value_t;
283 
285  auto shuffle(const value_t& l, const value_t& r) const -> value_t;
286 
288  template <typename... Value>
289  auto tuple(Value&&... v) const -> value_t;
290 
292  auto power(const value_t& e, unsigned n) const -> value_t;
293 
295  auto ldivide(const value_t& l, const value_t& r) const -> value_t;
296 
298  auto rdivide(const value_t& l, const value_t& r) const -> value_t;
299 
301  auto star(const value_t& e) const -> value_t;
302 
304  auto complement(const value_t& e) const -> value_t;
306  auto transposition(const value_t& e) const -> value_t;
308  auto rweight(const value_t& e, const weight_t& w) const -> value_t;
310  auto lweight(const weight_t& w, const value_t& e) const -> value_t;
312  auto transpose(const value_t& e) const -> value_t;
313 
315  auto word(label_t l) const -> word_t
316  {
317  return l;
318  }
319 
321  template <typename... Args>
322  auto letter_class(Args&&... chars) const -> value_t;
323 
325  auto conv(std::istream& is, bool = true) const -> value_t;
326 
328  auto conv(const self_t&, const value_t& v) const -> value_t;
329 
331  template <typename Fun>
332  void convs(std::istream&, Fun) const
333  {
334  raise(*this, ": ranges not implemented");
335  }
336 
337  auto print(const value_t& v,
338  std::ostream& o = std::cout, format fmt = {}) const
339  -> std::ostream&;
340 
342  auto print_set(std::ostream& o, format fmt = {}) const
343  -> std::ostream&;
344 
346  template <unsigned Tape, typename Ctx = context_t>
347  using project_t
349 
351  template <unsigned Tape>
352  auto project() const
353  -> project_t<Tape>
354  {
355  return vcsn::detail::project<Tape>(self());
356  }
357 
359  template <size_t Tape>
360  auto project(const value_t& v) const
361  -> decltype(::vcsn::rat::project<Tape>(this->self(), v))
362  {
363  return ::vcsn::rat::project<Tape>(self(), v);
364  }
365 
366  template <typename Sequence>
368 
369  template <size_t... I>
370  struct as_tupleset_impl<detail::index_sequence<I...>>
371  {
374 
375  static type value(const self_t& self)
376  {
377  return {detail::project<I>(self)...};
378  }
379  };
380 
382  template <typename Ctx = context_t>
383  using as_tupleset_t
385 
390  template <typename Ctx = context_t>
391  auto as_tupleset() const
392  -> std::enable_if_t<Ctx::is_lat, as_tupleset_t<Ctx>>
393  {
395  }
396 
397  private:
400  auto add_(values_t&& vs) const -> value_t;
401 
402  auto add_linear_(const add_t& addends, const value_t& r) const -> value_t;
403  auto add_linear_(const add_t& s1, const add_t& s2) const -> value_t;
404 
408  auto add_linear_(const value_t& l, const value_t& r) const -> value_t;
409 
412  static auto unwrap_possible_lweight_(const value_t& e) -> value_t;
415  static type_t type_ignoring_lweight_(const value_t& e);
419 
423  template <type_t Type>
424  void gather_(values_t& res, const value_t& v) const;
425 
430  template <type_t Type>
431  values_t gather_(const value_t& l, const value_t& r) const;
432 
434  auto concat_(const value_t& l, const value_t& r, std::true_type) const -> value_t;
436  auto concat_(const value_t& l, const value_t& r, std::false_type) const -> value_t;
437 
439  template <typename LabelSet_, typename... Args>
440  auto letter_class_(const Args&&... chars, std::true_type) const -> value_t;
441 
443  template <typename LabelSet_>
444  value_t
445  letter_class_(std::set<std::pair<typename LabelSet_::letter_t,
446  typename LabelSet_::letter_t>> chars,
447  bool accept,
448  std::false_type) const;
449 
451  template <typename Dummy = void>
453  {
455  static bool is_label(const tuple_t& v)
456  {
457  return is_label_(v, labelset_t::indices);
458  }
459 
462  label_t as_label(const tuple_t& v) const
463  {
464  return as_label_(v, labelset_t::indices);
465  }
466 
468  template <size_t... I>
470  {
471  for (auto b: {(std::get<I>(v.sub())->type() == type_t::atom
472  || (std::get<I>(v.sub())->type() == type_t::one
473  && labelset_t::template valueset_t<I>::has_one()))...})
474  if (!b)
475  return false;
476  return true;
477  }
478 
479  template <size_t... I>
481  {
482  return label_t{as_label_<I>(v)...};
483  }
484 
486  template <size_t I>
487  typename project_t<I>::label_t as_label_(const tuple_t& v) const
488  {
489  if (std::get<I>(v.sub())->type() == type_t::one)
490  return detail::label_one(rs_.labelset()->template set<I>());
491  else
492  return std::dynamic_pointer_cast<const typename project_t<I>::atom_t>
493  (std::get<I>(v.sub()))->value();
494  }
495  const self_t& rs_;
496  };
497 
498  private:
503  };
504  } // rat::
505 
506  namespace detail
507  {
509  template <typename Ctx>
511  {
513  static type value(const type& ls)
514  {
515  return ls;
516  }
517  };
518 
520  template <typename Ctx>
522  {
524  static type value(const type& ls)
525  {
526  return ls;
527  }
528  };
529 
531  template <typename Ctx1, typename Ctx2>
532  struct join_impl<expressionset<Ctx1>, expressionset<Ctx2>>
533  {
537 
538  static type join(const type1& a, const type2& b)
539  {
540  return {vcsn::join(a.context(), b.context()),
541  vcsn::join(a.identities(), b.identities())};
542  }
543  };
544 
546  // FIXME: what about the other labelsets?
547  template <typename GenSet1, typename Ctx2>
548  struct join_impl<letterset<GenSet1>, expressionset<Ctx2>>
549  {
555 
556  static type join(const type1& a, const type2& b)
557  {
558  return {context_t{vcsn::join(a, *b.labelset()), *b.weightset()},
559  b.identities()};
560  }
561  };
562 
563  // B. FIXME: screams for refactoring!
564  template <typename Context>
565  struct join_impl<b, expressionset<Context>>
566  {
568  static type join(const b&, const type& rhs)
569  {
570  return rhs;
571  }
572  };
573 
574  template <typename W1, typename W2>
576 
577  template <typename WeightSet, typename Context>
579  {
580  using type1 = WeightSet;
585  static type join(const type1& ws, const type2& rs)
586  {
587  return {context_t{*rs.labelset(), vcsn::join(ws, *rs.weightset())},
588  rs.identities()};
589  }
590  };
591 #define JOIN_IMPL_SIMPLE(WS) \
592  template <typename Context> \
593  struct join_impl<WS, expressionset<Context>> \
594  : public join_impl_simple<WS, expressionset<Context>> \
595  {};
596 
597 
602 
603 #undef JOIN_IMPL_SIMPLE
604 
605  }
606 
608  template <typename LabelSet, typename WeightSet>
609  auto
611  rat::identities ids = {})
613  {
614  return {ctx, ids};
615  }
616 
618  template <typename Context>
619  auto
621  rat::identities ids = {})
623  {
624  return {rs.context(), ids};
625  }
626 
628  template <typename Context>
629  struct is_multitape<expressionset<Context>>
630  : is_multitape<Context>
631  {};
632 
634  template <typename Ctx1, typename Ctx2>
635  auto
638  {
639  return {meet(a.context(), b.context()),
640  meet(a.identities(), b.identities())};
641  }
642 
643 
644  /*----------------.
645  | random_label. |
646  `----------------*/
647 
649  template <typename Context,
650  typename RandomGenerator = std::default_random_engine>
653  RandomGenerator& gen = RandomGenerator())
654  {
655  return rs.atom(random_label(*rs.labelset(), gen));
656  }
657 } // namespace vcsn
658 
660 
661 // This is ugly, yet I don't know how to address this circular
662 // dependency another way: expressionset.hxx uses is-valid-expression.hh,
663 // which, of course, also uses expressionset.hh.
664 //
665 // So let's have expressionset.hh first accept a forward declaration (via
666 // algos/fwd.hh), then provide here the needed definition. Do not
667 // leave this inside the CPP guard.
668 
static auto less(const value_t &l, const value_t &r) -> bool
Whether l < r.
static weight_t possibly_implicit_lweight_(const value_t &e)
The weight of e if it&#39;s an lweight, otherwise the weight one().
typename context_t::labelset_ptr labelset_ptr
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
rat::type_t type_t
The possible types of expressions.
Definition: expression.hh:27
auto concat_(const value_t &l, const value_t &r, std::true_type) const -> value_t
If labelset is wordset.
static bool is_label_(const tuple_t &v, detail::index_sequence< I... >)
Are all the components on I... labels?
void convs(std::istream &, Fun) const
Read a range of expressions.
static bool is_special(const value_t &v)
When used as a LabelSet.
static self_t make(std::istream &is)
Build from the description in is.
static type join(const b &, const type &rhs)
static constexpr star_status_t star_status()
When used as WeightSet.
static auto compare(const value_t &l, const value_t &r) -> int
Three-way comparison.
Implementation of labels are letters.
Definition: fwd.hh:10
project_t< I >::label_t as_label_(const tuple_t &v) const
The expression on tape I is actually a label: get it.
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.
typename weightset_t::value_t weight_t
identities_t identities() const
Accessor to the identities set.
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:54
auto add(const value_t &l, const value_t &r) const -> value_t
std::vector< value_t > values_t
Definition: expression.hh:90
auto power(const value_t &e, unsigned n) const -> value_t
Add a power operator: e{n}.
An inner node with multiple children.
Definition: expression.hh:119
const identities_t ids_
The set of rewriting rules to apply.
#define DEFINE(Type)
Type of expressions.
The LAW from a LAL.
Definition: labelset.hh:249
static auto equal(const value_t &l, const value_t &r) -> bool
Whether l == r.
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).
const context_t & context() const
Accessor to the context.
auto project() const -> project_t< Tape >
The expressionset for the Tape-th tape.
always valid.
Definition: star-status.hh:17
static auto zero() -> value_t
auto transpose(const value_t &e) const -> value_t
The transposed of this rational expression.
typename node_t::values_t values_t
A list (vector) of expressions.
letter_t value_t
Definition: letterset.hh:33
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:21
auto ldivide(const value_t &l, const value_t &r) const -> value_t
r`.
labelset_t_of< context_t > labelset_t
const labelset_ptr & labelset() const
Accessor to the labelset.
bool is_zero(const value_t &v) const ATTRIBUTE_PURE
Whether v is the \\z.
auto lweight(const weight_t &w, const value_t &e) const -> value_t
Left-multiplication by a weight.
static constexpr bool is_idempotent()
When used as WeightSet.
auto tuple(Value &&... v) const -> value_t
Build a tuple: e | f | ....
An inner node to name the subexpression.
Definition: expression.hh:290
auto add_linear_(const add_t &addends, const value_t &r) const -> value_t
static auto unwrap_possible_lweight_(const value_t &e) -> value_t
If e is an lweight, then its child, otherwise e.
context_t ctx_
The context of the expressions.
An expressionset can implement several different sets of identities on expressions.
Definition: identities.hh:20
static auto hash(const value_t &v) -> size_t
Hash v.
static constexpr bool has_one()
When used as WeightSet.
static constexpr bool has_lightening_weights()
When used as WeightSet.
An input/output format for valuesets.
Definition: format.hh:13
bool open(bool o) const
Whether unknown letters should be added, or rejected.
static constexpr bool is_letterized()
When used as a labelset.
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
identities meet(identities i1, identities i2)
More restricted of these identities (min).
Definition: identities.cc:72
bool is_letter(value_t) const
When used as a LabelSet.
const values_t sub() const
Definition: expression.hh:211
auto add_(values_t &&vs) const -> value_t
From a list of values, build a sum, taking care of the empty and singleton cases. ...
label_t_of< context_t > label_t
#define JOIN_IMPL_SIMPLE(WS)
auto join(const ValueSet &vs) -> ValueSet
The join of a single valueset.
Definition: join.hh:44
An inner node.
Definition: expression.hh:102
pair_automaton< Aut > pair(const Aut &aut, bool keep_initials=false)
Definition: pair.hh:252
A structure that implements the computation of join(V1, V2).
Definition: join.hh:18
auto compose(const value_t &l, const value_t &r) const -> value_t
Build a composition: l @ r.
typename detail::labelset_t_of_impl< base_t< ValueSet > >::type labelset_t_of
Definition: traits.hh:63
auto as_tupleset() const -> std::enable_if_t< Ctx::is_lat, as_tupleset_t< Ctx >>
If we are multitape, ourself as a tupleset.
static constexpr bool is_free()
When used as WeightSet.
auto star(const value_t &e) const -> value_t
Add a star operator: e*.
auto mul(const value_t &l, const value_t &r) const -> value_t
auto letter_class_(const Args &&... chars, std::true_type) const -> value_t
If labelset is oneset.
auto shuffle(const value_t &l, const value_t &r) const -> value_t
Build a shuffle product: l : r.
Definition: a-star.hh:8
auto infiltrate(const value_t &l, const value_t &r) const -> value_t
Build an infiltration product: l &: r.
std::shared_ptr< const node_t > value_t
An expression usable with value semantics.
Definition: expression.hh:89
Implementation of nodes of tuple of rational expressions.
Definition: expression.hh:174
star_status_t
Definition: star-status.hh:5
std::string type(const automaton &a)
The implementation type of a.
Definition: others.cc:238
typename detail::label_t_of_impl< base_t< ValueSet > >::type label_t_of
Definition: traits.hh:62
The abstract parameterized, root for all rational expression types.
Definition: expression.hh:81
static bool less_linear(const value_t &l, const value_t &r)
Whether l < r, ignoring lweight.
typename node_t::value_t value_t
An expression (a shared pointer to a tree).
label_t as_label(const tuple_t &v) const
All the components are (single-tape) labels: make this a multitape label.
The smallest nullableset which includes LabelSet.
Definition: labelset.hh:138
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.
auto name(const value_t &v, symbol name) const -> value_t
Build a named expression.
bool is_universal(const value_t &v) const ATTRIBUTE_PURE
Whether v is the 0{c}.
An inner node implementing a weight.
Definition: expression.hh:256
A static list of size_t.
Definition: tuple.hh:32
auto make_expressionset(const context< LabelSet, WeightSet > &ctx, rat::identities ids={}) -> expressionset< context< LabelSet, WeightSet >>
Shorthand to expressionset constructor.
auto print_set(std::ostream &o, format fmt={}) const -> std::ostream &
Format the description of this expressionset.
auto conv(const letterset< GenSet > &ls, typename letterset< GenSet >::value_t v) const -> value_t
static bool is_one(const value_t &v) ATTRIBUTE_PURE
Whether v is the \\e.
return v
Definition: multiply.hh:362
weightset_t_of< context_t > weightset_t
auto rdivide(const value_t &l, const value_t &r) const -> value_t
Build a right division: l {/} r.
static dyn::context ctx(const driver &d)
Get the context of the driver.
Definition: parse.cc:84
Turn a tuple of expressions that are labels into a multi-tape label.
const weightset_ptr & weightset() const
Accessor to the weightset.
A typed expression set.
static auto size(const value_t &v) -> size_t
The size of v.
The root from which to derive the final node types.
Definition: expression.hh:317
static bool is_label(const tuple_t &v)
Are all the components labels?
auto project(const value_t &v) const -> decltype(::vcsn::rat::project< Tape >(this->self(), v))
Project a multitape expression.
static symbol sname()
Static description key.
static identities ids(const driver &d)
Get the identities of the driver.
Definition: parse.cc:91
::vcsn::rat::identities identities
Sets of identities on expressions.
Definition: fwd.hh:17
static constexpr bool is_commutative()
When used as WeightSet.
auto conjunction(const value_t &l, const value_t &r) const -> value_t
Build an conjunction product: l & r.
static constexpr bool show_one()
When used as WeightSet.
auto complement(const value_t &e) const -> value_t
Add a complement operator: e{c}.
static value_t special()
When used as a LabelSet.
void gather_(values_t &res, const value_t &v) const
Push v in res, applying associativity if possible.
Whether a ValueSet, or a context, is multitape.
Definition: traits.hh:117
auto letter_class(Args &&... chars) const -> value_t
An expression matching one character amongst chars.
static constexpr bool is_expressionset()
When used as WeightSet.
static auto atom(const label_t &v) -> value_t
Build a label.
STL namespace.
static auto one() -> value_t
auto transposition(const value_t &e) const -> value_t
Add a transposition operator.
auto rweight(const value_t &e, const weight_t &w) const -> value_t
Right-multiplication by a weight.
expressionset_impl(const context_t &ctx, identities_t ids={})
Constructor.
return res
Definition: multiply.hh:399
typename context_t::weightset_ptr weightset_ptr
expressionset< Context >::value_t random_label(const expressionset< Context > &rs, RandomGenerator &gen=RandomGenerator())
Random label from expressionset: limited to a single label.
auto word(label_t l) const -> word_t
Make a `word&#39; out of an expression.
auto print(const value_t &v, std::ostream &o=std::cout, format fmt={}) const -> std::ostream &
typename node_t::type_t type_t
Type tag for AST classes.
label_t as_label_(const tuple_t &v, detail::index_sequence< I... >) const