Vcsn  2.3
Be Rational
nullableset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <set>
5 #include <sstream>
6 
7 #include <vcsn/alphabets/setalpha.hh> // intersect
8 #include <vcsn/core/kind.hh>
9 #include <vcsn/labelset/fwd.hh>
12 #include <vcsn/labelset/oneset.hh>
13 #include <vcsn/misc/escape.hh>
14 #include <vcsn/misc/functional.hh>
15 #include <vcsn/misc/raise.hh>
16 
17 namespace vcsn
18 {
19  namespace detail
20  {
27  template <typename LabelSet>
29  {
30  using labelset_t = LabelSet;
31  using value_t = std::pair<typename labelset_t::value_t, bool>;
32 
33  ATTRIBUTE_PURE
34  static constexpr value_t
35  one()
36  {
37  return value_t{labelset_t::special(), true};
38  }
39 
40  ATTRIBUTE_PURE
41  static constexpr value_t
43  {
44  return value_t{labelset_t::special(), false};
45  }
46 
47  template <typename Ls>
48  ATTRIBUTE_PURE
49  static std::enable_if_t<Ls::has_one(), bool>
50  is_one_(const value_t& l)
51  {
52  return std::get<1>(l) || Ls::is_one(get_value(l));
53  }
54 
55  template <typename Ls>
56  ATTRIBUTE_PURE
57  static std::enable_if_t<!Ls::has_one(), bool>
58  is_one_(const value_t& l)
59  {
60  return std::get<1>(l);
61  }
62 
63  ATTRIBUTE_PURE
64  static bool
65  is_one(const value_t& l)
66  {
67  return is_one_<labelset_t>(l);
68  }
69 
70  template <typename Value>
71  static Value
72  transpose(const labelset_t& ls, Value l)
73  {
74  // This is not robust enough: Value is word_t, then it's not
75  // valid to call is_one on it. Since I'm unsure of the future
76  // of nullableset, let's not waste time on this now.
77  if (is_one(l))
78  return l;
79  else
80  return {ls.transpose(get_value(l)), false};
81  }
82 
83  template <typename... Args>
84  static value_t
85  value(const labelset_t& ls, Args&&... args)
86  {
87  return {ls.value(std::forward<Args>(args)...), false};
88  }
89 
90  ATTRIBUTE_PURE
91  static typename labelset_t::value_t
93  {
94  return std::get<0>(v);
95  }
96  };
97 
104  template <typename GenSet>
105  struct nullable_helper<letterset<GenSet>>
106  {
107  using genset_t = GenSet;
109  using value_t = typename labelset_t::value_t;
110 
111  ATTRIBUTE_PURE
112  static constexpr value_t
114  {
115  return genset_t::special();
116  }
117 
118  ATTRIBUTE_PURE
119  static constexpr value_t
120  one()
121  {
122  return genset_t::one_letter();
123  }
124 
125  ATTRIBUTE_PURE
126  static bool
128  {
129  return l == one();
130  }
131 
132  template <typename Value>
133  static Value
134  transpose(const labelset_t& ls, const Value& l)
135  {
136  return ls.transpose(l);
137  }
138 
139  template <typename... Args>
140  static value_t
141  value(const labelset_t& ls, Args&&... args)
142  {
143  return ls.value(std::forward<Args>(args)...);
144  }
145 
146  ATTRIBUTE_PURE
147  static value_t
149  {
150  return v;
151  }
152  };
153  }
154 
156  template <typename LabelSet>
157  class nullableset
158  {
159  public:
160  using labelset_t = LabelSet;
161  using labelset_ptr = std::shared_ptr<const labelset_t>;
165 
166  using value_t = typename helper_t::value_t;
167  using letter_t = typename labelset_t::letter_t;
168  using word_t = typename labelset_t::word_t;
169 
170  private:
174 
175  public:
176  using genset_ptr = decltype(ls_->genset());
177  using genset_t = decltype(ls_->generators());
178 
179  public:
181  : ls_{ls}
182  {}
183 
184  nullableset(const labelset_t& ls = {})
185  : nullableset{std::make_shared<const labelset_t>(ls)}
186  {}
187 
188  static symbol sname()
189  {
190  static auto res = symbol{"nullableset<" + labelset_t::sname() + '>'};
191  return res;
192  }
193 
195  static nullableset make(std::istream& is)
196  {
197  // name: nullableset<lal_char(abc)>.
198  // ^^^^^^^^^^^^
199  // labelset
200  eat(is, "nullableset<");
201  auto ls = labelset_t::make(is);
202  eat(is, '>');
203  return {ls};
204  }
205 
209  bool open(bool o) const
210  {
211  return this->ls_->open(o);
212  }
213 
214  static constexpr bool
216  {
217  return true;
218  }
219 
220  static constexpr bool
222  {
223  return false;
224  }
225 
226  static constexpr bool
228  {
229  return labelset_t::is_letterized();
230  }
231 
232  static constexpr bool is_free()
233  {
234  return false;
235  }
236 
237  ATTRIBUTE_PURE
238  static constexpr value_t
239  one()
240  {
241  return helper_t::one();
242  }
243 
244  ATTRIBUTE_PURE
245  static bool
247  {
248  return helper_t::is_one(l);
249  }
250 
251  bool
253  {
254  return is_one(v) || ls_->is_valid(get_value(v));
255  }
256 
257  genset_ptr
258  genset() const
259  {
260  return ls_->genset();
261  }
262 
264  genset_t
265  generators() const
266  {
267  return ls_->generators();
268  }
269 
270  value_t
272  {
273  return v;
274  }
275 
276  value_t
277  conv(oneset, typename oneset::value_t) const
278  {
279  return one();
280  }
281 
285  template <typename LabelSet_>
286  value_t
287  conv(const LabelSet_& ls, typename LabelSet_::value_t v) const
288  {
289  return value(ls_->conv(ls, v));
290  }
291 
292  const labelset_ptr labelset() const
293  {
294  return ls_;
295  }
296 
297  template <typename... Args>
298  value_t
299  value(Args&&... args) const
300  {
301  return helper_t::value(*ls_, std::forward<Args>(args)...);
302  }
303 
304  word_t
305  word(const value_t& l) const
306  {
307  if (is_one(l))
308  return make_wordset(*labelset()).one();
309  else
310  return ls_->word(get_value(l));
311  }
312 
314  auto static
316  -> decltype(labelset_t::letters_of(v))
317  {
318  return labelset_t::letters_of(v);
319  }
320 
323  auto
325  -> decltype(ls_->letters_of_padded(v, l))
326  {
327  return ls_->letters_of_padded(v, l);
328  }
329 
330  auto
332  -> decltype(this->letters_of_padded(this->word(v), l))
333  {
334  return letters_of_padded(word(v), l);
335  }
336 
338  static bool equal(const value_t& l, const value_t& r)
339  {
340  if (is_one(l))
341  return is_one(r);
342  else
343  return !is_one(r) && labelset_t::equal(get_value(l), get_value(r));
344  }
345 
347  static bool less(const value_t& l, const value_t& r)
348  {
349  if (is_one(r))
350  return false;
351  else if (is_one(l))
352  return true;
353  else
354  return labelset_t::less(get_value(l), get_value(r));
355  }
356 
358  value_t mul(const value_t& l, const value_t& r) const
359  {
360  if (is_one(r))
361  return l;
362  else if (is_one(l))
363  return r;
364  else
365  raise(*this, ": mul: invalid arguments: ",
366  to_string(*this, l), ", ", to_string(*this, r));
367  }
368 
370  value_t lgcd(const value_t& l, const value_t& r) const
371  {
372  if (equal(l, r))
373  return l;
374  else if (is_one(l) || is_one(r))
375  return one();
376  else
377  return value(ls_->lgcd(get_value(l), get_value(r)));
378  }
379 
381  value_t ldivide(const value_t& l, const value_t& r) const
382  {
383  if (equal(l, r))
384  return one();
385  else if (is_one(l))
386  return r;
387  else if (is_one(r))
388  raise(*this, ": ldivide: invalid arguments: ",
389  to_string(*this, l), ", ", to_string(*this, r));
390  else
391  return value(ls_->ldivide(get_value(l), get_value(r)));
392  }
393 
394  static value_t
396  {
397  return helper_t::special();
398  }
399 
400  static bool
402  {
403  return !is_one(v) && labelset_t::is_special(get_value(v));
404  }
405 
406  static size_t size(const value_t& v)
407  {
408  return is_one(v) ? 0 : labelset_t::size(get_value(v));
409  }
410 
411  // FIXME: specialize for both implementation.
412  static size_t hash(const value_t& v)
413  {
414  // Do not use get_value when is_one. Let's hash one() as 0.
415  return is_one(v) ? 0 : labelset_t::hash(get_value(v));
416  }
417 
418  letter_t
419  get_letter(std::istream& i, bool quoted = true) const
420  {
421  return ls_->get_letter(i, quoted);
422  }
423 
425  value_t
426  conv(std::istream& i, bool quoted = true) const
427  {
428  // Check for '\e', otherwise pass it to the inner labelset.
429  if (i.good() && i.peek() == '\\')
430  {
431  i.ignore();
432  int c = i.peek();
433  if (c == 'e')
434  {
435  i.ignore();
436  return {};
437  }
438  else
439  i.unget();
440  }
441  return value(ls_->conv(i, quoted));
442  }
443 
453  template <typename Fun>
454  void convs(std::istream& i, Fun&& fun) const
455  {
456  ls_->convs(i,
457  [this,fun](const typename labelset_t::value_t& l)
458  {
459  fun(value(l));
460  });
461  }
462 
463  value_t conjunction(const value_t& l, const value_t& r) const
464  {
465  if (is_one(l) && is_one(r))
466  return l;
467  else if (!is_one(l) && !is_one(r))
468  return ls_->conjunction(get_value(l), get_value(r));
469  else
470  raise(*this,
471  ": conjunction: invalid operation (lhs and rhs are not equal): ",
472  to_string(*this, l), ", ", to_string(*this, r));
473  }
474 
476  std::ostream&
477  print(const value_t& l, std::ostream& o = std::cout,
478  format fmt = {}) const
479  {
480  if (is_one(l))
481  o << (fmt == format::latex ? "\\varepsilon"
482  : fmt == format::utf8 ? "ε"
483  : "\\e");
484  else
485  ls_->print(get_value(l), o, fmt);
486  return o;
487  }
488 
489  value_t
490  zero() const
491  {
492  return value(ls_->zero());
493  }
494 
495  bool
496  is_zero(const value_t& v) const
497  {
498  return !is_one(v) && ls_->is_zero(get_value(v));
499  }
500 
501  bool
502  is_letter(const value_t& v) const
503  {
504  return !is_one(v) && ls_->is_letter(get_value(v));
505  }
506 
508  template <typename Value>
509  Value
510  transpose(const Value& l) const
511  {
512  return helper_t::transpose(*ls_, l);
513  }
514 
516  std::ostream&
517  print_set(std::ostream& o, format fmt = {}) const
518  {
519  switch (fmt.kind())
520  {
521  case format::latex:
522  o << "(";
523  ls_->print_set(o, fmt);
524  o << ")^?";
525  break;
526 
527  case format::sname:
528  o << "nullableset<";
529  ls_->print_set(o, fmt);
530  o << '>';
531  break;
532 
533  case format::text:
534  case format::utf8:
535  ls_->print_set(o, fmt);
536  o << '?';
537  break;
538 
539  case format::raw:
540  assert(0);
541  break;
542  }
543 
544  return o;
545  }
546 
548  static typename labelset_t::value_t
549  get_value(const value_t& v)
550  {
551  assert(!is_one(v));
552  return helper_t::get_value(v);
553  }
554  };
555 
556  namespace detail
557  {
559  template <typename LabelSet>
560  struct letterized_traits<nullableset<LabelSet>>
561  {
562  using traits = letterized_traits<LabelSet>;
563  static constexpr bool is_letterized = traits::is_letterized;
564 
565  using labelset_t = typename traits::labelset_t;
566 
567  static labelset_t labelset(const nullableset<LabelSet>& ls)
568  {
569  return make_letterized(*ls.labelset());
570  }
571  };
572 
574  template <typename LabelSet>
575  struct nullableset_traits<nullableset<LabelSet>>
576  {
577  using type = nullableset<LabelSet>;
578  static type value(const nullableset<LabelSet>& ls)
579  {
580  return ls;
581  }
582  };
583 
584  template <typename LabelSet>
585  struct proper_traits<nullableset<LabelSet>>
586  {
587  using type = LabelSet;
588  static type value(const nullableset<LabelSet>& ls)
589  {
590  return *ls.labelset();
591  }
592  };
593 
595  template <typename LabelSet>
596  struct law_traits<nullableset<LabelSet>>
597  {
598  using type = law_t<LabelSet>;
599  static type value(const nullableset<LabelSet>& ls)
600  {
601  return make_wordset(*ls.labelset());
602  }
603  };
604 
605  /*-------.
606  | Join. |
607  `-------*/
608 
610  template <typename LS>
611  struct join_impl<oneset, LS,
612  std::enable_if_t<!LS::has_one()>>
613  {
614  using type = nullableset<LS>;
615  static type join(const oneset&, const LS& ls)
616  {
617  return {ls};
618  }
619  };
620 
622  template <typename LS>
623  struct join_impl<oneset, LS,
624  std::enable_if_t<LS::has_one()>>
625  {
626  using type = LS;
627  static type join(const oneset&, const LS& ls)
628  {
629  return ls;
630  }
631  };
632 
634  template <typename LS1, typename LS2>
635  struct join_impl<nullableset<LS1>, LS2>
636  {
637  using type = nullableset<join_t<LS1, LS2>>;
638  static type join(const nullableset<LS1>& ls1, const LS2& ls2)
639  {
640  return {::vcsn::join(*ls1.labelset(), ls2)};
641  }
642  };
643 
648  template <typename LS1, typename LS2>
649  struct join_impl<nullableset<LS1>, nullableset<LS2>>
650  {
651  using type = nullableset<join_t<LS1, LS2>>;
652  static type join(const nullableset<LS1>& ls1,
653  const nullableset<LS2>& ls2)
654  {
655  return {::vcsn::join(*ls1.labelset(), *ls2.labelset())};
656  }
657  };
658  }
659 
660  /*-------.
661  | Meet. |
662  `-------*/
663 
664 #define DEFINE(Lhs, Rhs, Res) \
665  template <typename GenSet> \
666  Res \
667  meet(const Lhs& lhs, const Rhs& rhs) \
668  { \
669  return {set_intersection(*lhs.genset(), *rhs.genset())}; \
670  }
671 
673  DEFINE(nullableset<letterset<GenSet>>,
674  nullableset<letterset<GenSet>>, nullableset<letterset<GenSet>>);
675 
676  DEFINE(letterset<GenSet>,
677  nullableset<letterset<GenSet>>, nullableset<letterset<GenSet>>);
678 
679  DEFINE(nullableset<letterset<GenSet>>,
680  letterset<GenSet>, nullableset<letterset<GenSet>>);
681 
682  template <typename Lls, typename Rls>
683  nullableset<meet_t<Lls, Rls>>
684  meet(const nullableset<Lls>& lhs, const nullableset<Rls>& rhs)
685  {
686  return nullableset<meet_t<Lls, Rls>>{meet(*lhs.labelset(),
687  *rhs.labelset())};
688  }
689 
690 #undef DEFINE
691 
692 }
return v
Definition: multiply.hh:361
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:246
static size_t size(const value_t &v)
Definition: nullableset.hh:406
value_t ldivide(const value_t &l, const value_t &r) const
Compute l \ r = l^{-1}r.
Definition: nullableset.hh:381
static size_t hash(const value_t &v)
Definition: nullableset.hh:412
static bool is_special(const value_t &v)
Definition: nullableset.hh:401
value_t zero() const
Definition: nullableset.hh:490
std::ostream & print_set(std::ostream &o, format fmt={}) const
Print labelset description.
Definition: nullableset.hh:517
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:35
typename labelset_t::letter_t letter_t
Definition: nullableset.hh:167
static Value transpose(const labelset_t &ls, const Value &l)
Definition: nullableset.hh:134
boost::flyweight< std::string, boost::flyweights::no_tracking, boost::flyweights::intermodule_holder > symbol
An internalized string.
Definition: symbol.hh:23
value_t conv(const LabelSet_ &ls, typename LabelSet_::value_t v) const
Conversion from another type: first by the wrapped labelset, and then by our wrappers (in case the wr...
Definition: nullableset.hh:287
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:258
value_t value(Args &&...args) const
Definition: nullableset.hh:299
bool is_letter(const value_t &v) const
Definition: nullableset.hh:502
static labelset_t::value_t get_value(const value_t &v)
The (inner) value when it (the outer value) is not one.
Definition: nullableset.hh:549
decltype(ls_->genset()) genset_ptr
Definition: nullableset.hh:176
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:141
symbol sname()
Definition: name.hh:65
bool value_t
Definition: oneset.hh:20
Implementation of labels are letters.
Definition: fwd.hh:10
std::enable_if_t<!is_letterized_t< labelset_t_of< Aut > >{}, bool > is_letterized(const Aut &aut)
Definition: letterize.hh:161
word_t word(const value_t &l) const
Definition: nullableset.hh:305
value_t conv(std::istream &i, bool quoted=true) const
Read a label from a stream.
Definition: nullableset.hh:426
static constexpr bool has_one()
Definition: nullableset.hh:215
size_t size(const ExpSet &rs, const typename ExpSet::value_t &r)
value_t conv(self_t, value_t v) const
Definition: nullableset.hh:271
bool open(bool o) const
Whether unknown letters should be added, or rejected.
Definition: nullableset.hh:209
Add support for an empty word to a LabelSet that does not provide such special label to this end...
Definition: nullableset.hh:28
typename helper_t::value_t value_t
Definition: nullableset.hh:166
static bool equal(const value_t &l, const value_t &r)
Whether l == r.
Definition: nullableset.hh:338
Print as a parsable type string.
Definition: format.hh:26
static auto letters_of(const word_t &v) -> decltype(labelset_t::letters_of(v))
Prepare to iterate over the letters of v.
Definition: nullableset.hh:315
Implementation of labels are nullables (letter or empty).
Definition: fwd.hh:14
static ATTRIBUTE_PURE bool is_one(value_t l)
Definition: nullableset.hh:127
nullableset(const labelset_ptr &ls)
Definition: nullableset.hh:180
std::ostream & print(const value_t &l, std::ostream &o=std::cout, format fmt={}) const
Print label to stream.
Definition: nullableset.hh:477
genset_ptr genset() const
Definition: nullableset.hh:258
static ATTRIBUTE_PURE labelset_t::value_t get_value(const value_t &v)
Definition: nullableset.hh:92
return res
Definition: multiply.hh:398
value_t mul(const value_t &l, const value_t &r) const
The concatenation.
Definition: nullableset.hh:358
static symbol sname()
Definition: nullableset.hh:188
value_t conv(oneset, typename oneset::value_t) const
Definition: nullableset.hh:277
value_t lgcd(const value_t &l, const value_t &r) const
The longest common prefix.
Definition: nullableset.hh:370
bool is_zero(const value_t &v) const
Definition: nullableset.hh:496
Implementation of labels are ones: there is a single instance of label.
Definition: oneset.hh:16
labelset_ptr ls_
The wrapped LabelSet.
Definition: nullableset.hh:173
void convs(std::istream &i, Fun &&fun) const
Process a label class.
Definition: nullableset.hh:454
static ATTRIBUTE_PURE value_t get_value(const value_t &v)
Definition: nullableset.hh:148
letter_t value_t
Definition: letterset.hh:32
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:239
static constexpr bool is_free()
Definition: nullableset.hh:232
static ATTRIBUTE_PURE std::enable_if_t<!Ls::has_one(), bool > is_one_(const value_t &l)
Definition: nullableset.hh:58
Value transpose(const Value &l) const
Mirror label.
Definition: nullableset.hh:510
value_t conjunction(const value_t &l, const value_t &r) const
Definition: nullableset.hh:463
static bool less(const value_t &l, const value_t &r)
Whether l < r.
Definition: nullableset.hh:347
static constexpr bool is_letterized()
Definition: nullableset.hh:227
Definition: a-star.hh:8
bool is_special(const Aut &aut, transition_t_of< Aut > t)
Whether this transition is from pre or to post.
Definition: automaton.hh:207
An input/output format for valuesets.
Definition: format.hh:13
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:113
auto letters_of_padded(value_t v, letter_t l) const -> decltype(this->letters_of_padded(this->word(v), l))
Definition: nullableset.hh:331
static ATTRIBUTE_PURE constexpr value_t one()
Definition: nullableset.hh:120
std::string to_string(direction d)
Conversion to string.
Definition: direction.cc:7
value_t value(Args &&...args) const
Value constructor.
Definition: letterset.hh:82
Print as rich UTF-8 text, escaped.
Definition: format.hh:30
std::shared_ptr< const labelset_t > labelset_ptr
Definition: nullableset.hh:161
nullableset(const labelset_t &ls={})
Definition: nullableset.hh:184
static nullableset make(std::istream &is)
Build from the description in is.
Definition: nullableset.hh:195
static ATTRIBUTE_PURE bool is_one(const value_t &l)
Definition: nullableset.hh:65
bool is_valid(value_t v) const
Definition: nullableset.hh:252
std::pair< typename labelset_t::value_t, bool > value_t
Definition: nullableset.hh:31
static ATTRIBUTE_PURE std::enable_if_t< Ls::has_one(), bool > is_one_(const value_t &l)
Definition: nullableset.hh:50
static Value transpose(const labelset_t &ls, Value l)
Definition: nullableset.hh:72
ATTRIBUTE_PURE auto transpose(Args &&...args) const -> decltype(this->genset() -> transpose(std::forward< Args >(args)...))
decltype(ls_->generators()) genset_t
Definition: nullableset.hh:177
static value_t special()
Definition: nullableset.hh:395
genset_t generators() const
The generators. Meaningful for labelsets only.
Definition: nullableset.hh:265
Print for LaTeX.
Definition: format.hh:22
const labelset_ptr labelset() const
Definition: nullableset.hh:292
Provide a variadic mul on top of a binary mul(), and one().
Definition: fwd.hh:46
typename labelset_t::word_t word_t
Definition: nullableset.hh:168
static value_t value(const labelset_t &ls, Args &&...args)
Definition: nullableset.hh:85
static constexpr bool is_expressionset()
Definition: nullableset.hh:221
letter_t get_letter(std::istream &i, bool quoted=true) const
Definition: nullableset.hh:419
auto letters_of_padded(const word_t &v, letter_t l) const -> decltype(ls_->letters_of_padded(v, l))
Prepare to iterate over the letters of v.
Definition: nullableset.hh:324
char eat(std::istream &is, char c)
Check lookahead character and advance.
Definition: stream.cc:90
static ATTRIBUTE_PURE constexpr value_t special()
Definition: nullableset.hh:42
weightset_mixin< detail::r_impl > r
Definition: fwd.hh:54