Vcsn  2.3
Be Rational
labelset.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <boost/optional.hpp>
4 #include <boost/range/algorithm/find.hpp>
5 #include <boost/range/algorithm/find_if.hpp>
6 #include <boost/range/algorithm/for_each.hpp>
7 #include <boost/range/algorithm_ext/is_sorted.hpp>
8 
9 #include <vcsn/ctx/context.hh>
10 #include <vcsn/ctx/traits.hh> // labelset_t_of
11 #include <vcsn/misc/algorithm.hh> // none_of
12 #include <vcsn/misc/functional.hh> // less
13 #include <vcsn/misc/static-if.hh>
14 #include <vcsn/misc/type_traits.hh> // detect
15 
16 namespace vcsn
17 {
18  namespace detail
19  {
21  template <typename LabelSet>
22  using generators_mem_fn_t = decltype(std::declval<LabelSet>().generators());
23 
25  template <typename LabelSet>
27 
28 
29  /*-----------.
30  | has_one. |
31  `-----------*/
32 
33  template <typename LabelSet>
34  using one_t = decltype(std::declval<LabelSet>().one());
35 
36  template <typename LabelSet>
38 
39 
40  /*-------------.
41  | label_one. |
42  `-------------*/
43 
44 #if defined __GNUC__ && !defined __clang__
45  // GCC can't figure out that this one does return, because of the template
46  // instanciation, where one of them doesn't return.
47 # pragma GCC diagnostic push
48 # pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
49 #endif
50 
52  template <typename LabelSet>
53  auto label_one(const LabelSet& ls)
54  -> typename LabelSet::value_t
55  {
56  return static_if<LabelSet::has_one()>
57  ([](const auto& ls) { return ls.one(); },
58  [](const auto& ls) -> typename LabelSet::value_t
59  {
60  raise(ls, ": does not feature a neutral");
61  })
62  (ls);
63  }
64 
65 #if defined __GNUC__ && !defined __clang__
66 # pragma GCC diagnostic pop
67 #endif
68 
69 
70  /*-------------------.
71  | make_letterized. |
72  `-------------------*/
73 
77  template <typename LabelSet>
79  {
80  static constexpr bool is_letterized = true;
81 
82  using labelset_t = LabelSet;
83  static labelset_t labelset(const labelset_t& ls)
84  {
85  return std::make_shared<labelset_t>(labelset_t{ls.genset()});
86  }
87  };
88 
89  template <typename LabelSet>
90  using letterized_t =
92 
93  template <typename LabelSet>
94  using is_letterized_t =
96 
97  template <typename LabelSet>
99  make_letterized(const LabelSet& ls)
100  {
102  }
103 
104 
105  /*---------------------------.
106  | make_letterized_context. |
107  `---------------------------*/
108 
109  template <typename Context>
110  using letterized_context =
113 
115  template <typename LabelSet, typename WeightSet>
118  {
119  return {make_letterized(*c.labelset()), *c.weightset()};
120  }
121 
122 
123  /*--------------------.
124  | make_nullableset. |
125  `--------------------*/
126 
135  template <typename LabelSet,
136  typename Enable = void>
138  {};
139 
141  template <typename LabelSet>
143 
145  template <typename LabelSet>
147  make_nullableset(const LabelSet& ls)
148  {
150  };
151 
152  /*----------------------------.
153  | make_nullableset_context. |
154  `----------------------------*/
155 
156  template <typename Ctx>
159 
161  template <typename LabelSet, typename WeightSet>
164  {
165  return {make_nullableset(*ctx.labelset()), *ctx.weightset()};
166  }
167 
168 
169  /*---------------.
170  | make_proper. |
171  `---------------*/
172 
180  template <typename LabelSet>
182  {
183  using type = LabelSet;
184  static type value(const LabelSet& ls)
185  {
186  return ls;
187  }
188  };
189 
191  template <typename LabelSet>
193 
195  template <typename LabelSet>
197  make_proper(const LabelSet& ls)
198  {
200  }
201 
202 
203  /*-----------------------.
204  | make_proper_context. |
205  `-----------------------*/
206 
207  template <typename Context>
208  using proper_context =
211 
213  template <typename LabelSet, typename WeightSet>
214  auto
217  {
218  return {make_proper(*ctx.labelset()), *ctx.weightset()};
219  }
220 
221 
222  /*---------------------.
223  | make_free_context. |
224  `---------------------*/
225 
226  template <typename Context>
227  using free_context =
230 
232  template <typename LabelSet, typename WeightSet>
235  {
236  return {make_proper(make_letterized(*c.labelset())), *c.weightset()};
237  }
238 
239 
240  /*---------------.
241  | make_wordset. |
242  `---------------*/
243 
247  template <typename ValueSet>
248  struct law_traits
249  {};
250 
252  template <typename LabelSet>
254 
256  template <typename LabelSet>
257  inline law_t<LabelSet>
258  make_wordset(const LabelSet& ls)
259  {
260  return law_traits<LabelSet>::value(ls);
261  };
262 
263  /*--------------------.
264  | make_word_context. |
265  `--------------------*/
266 
267  template <typename Ctx>
268  using word_context_t
269  = context<law_t<labelset_t_of<Ctx>>, weightset_t_of<Ctx>>;
270 
272  template <typename LabelSet, typename WeightSet>
275  {
276  return {make_wordset(*ctx.labelset()), *ctx.weightset()};
277  }
278 
279 
280  /*---------------------.
281  | print_label_class. |
282  `---------------------*/
283 
288  template <typename LabelSet>
289  std::ostream&
290  print_label_ranges_(const LabelSet& ls,
291  const std::vector<typename LabelSet::value_t>& letters,
292  const std::vector<typename LabelSet::value_t>& alphabet,
293  std::ostream& out,
294  format fmt)
295  {
296  for (auto it = std::begin(letters), letters_end = std::end(letters);
297  it != letters_end; ++it)
298  {
299  auto end = std::mismatch(it, letters_end,
300  boost::range::find(alphabet, *it),
301  alphabet.end()).first;
302  ls.print(*it, out, fmt);
303  // No range for two letters or less.
304  auto width = std::distance(it, end);
305  if (2 < width)
306  {
307  it += width - 1;
308  // Using `-` in LaTeX math mode means minus (wow, 4
309  // m-words in a row), which results in a long dash, and
310  // too much space around it.
311  out << (fmt == format::latex ? "\\textrm{-}" : "-");
312  ls.print(*it, out, fmt);
313  }
314  }
315  return out;
316  }
317 
322  template <typename LabelSet>
323  std::ostream&
324  print_label_class(const LabelSet& ls,
325  const std::vector<typename LabelSet::value_t>& letters,
326  std::ostream& out,
327  format fmt)
328  {
329  using letters_t = std::vector<typename LabelSet::value_t>;
330  // In alphabetical order.
331  auto alphabet = letters_t{};
332  for (auto l : ls.generators())
333  alphabet.emplace_back(ls.value(l));
334 
335  out << '[';
336  // If the letters are strictly increasing (hence using
337  // less_equal, not just less), and are many compared to the
338  // alphabet (say, at least two thirds), then we should probably
339  // use negated classes instead.
340  if (boost::is_sorted(letters, vcsn::less_equal<LabelSet>{})
341  && 2 * boost::distance(alphabet) < 3 * boost::distance(letters))
342  {
343  // FIXME: we can certainly do better and avoid the
344  // construction of this vector.
345  auto negated = letters_t{};
346  for (auto l: alphabet)
347  if (none_of_equal(letters, l))
348  negated.emplace_back(l);
349  out << (fmt == format::latex ? "\\hat{}" : "^");
350  print_label_ranges_(ls, negated, alphabet, out, fmt);
351  }
352  else
353  print_label_ranges_(ls, letters, alphabet, out, fmt);
354  out << ']';
355 
356  return out;
357  }
358 
359  template <typename LabelSet>
360  typename LabelSet::letters_t
361  conv_label_class_(const LabelSet& ls, std::istream& i);
362 
368  //
378  template <typename LabelSet, typename Fun>
379  void
380  conv_label_class_(const LabelSet& ls, std::istream& i, Fun fun)
381  {
382  using letter_t = typename LabelSet::letter_t;
383  using letters_t = typename LabelSet::letters_t;
384  if (i.peek() == '^')
385  {
386  i.ignore();
387  auto alphabet = letters_t{};
388  for (auto l : ls.generators())
389  alphabet.insert(l);
390  boost::for_each(set_difference(alphabet, conv_label_class_(ls, i)),
391  fun);
392  }
393  else
394  {
395  // The last letter we read, for intervals.
396  auto prev = boost::optional<letter_t>{};
397  while (i.peek() != EOF && i.peek() != ']')
398  if (i.peek() == '-')
399  {
400  i.ignore();
401  // Handle a range.
402  // FIXME: ls instead of ls.sname would be better.
403  require(prev,
404  ls.sname(), ": letter classes cannot begin with '-'");
405  require(i.peek() != ']',
406  ls.sname(), ": letter classes cannot finish with '-'");
407 
408  // [prev - l2].
409  letter_t l2 = ls.get_letter(i);
410  // Skip prev, which was already processed.
411  auto gens = ls.generators();
412  auto i = boost::range::find(gens, *prev);
413  // FIXME: Cannot use std::next here, in the case of tuples.
414  if (i != std::end(gens))
415  ++i;
416  for (;
417  i != std::end(gens) && *i < l2;
418  ++i)
419  fun(*i);
420  // The last letter. Do not do this in the loop,
421  // we might overflow the capacity of char.
422  // Check validity, so that 'z-a' is empty.
423  if (*prev < l2)
424  fun(l2);
425 
426  prev = boost::none;
427  }
428  else
429  {
430  letter_t l = ls.get_letter(i);
431  fun(l);
432  prev = l;
433  }
434  }
435  }
436 
438  template <typename LabelSet>
439  typename LabelSet::letters_t
440  conv_label_class_(const LabelSet& ls, std::istream& i)
441  {
442  using letter_t = typename LabelSet::letter_t;
443  using letters_t = typename LabelSet::letters_t;
444 
445  letters_t res;
446  conv_label_class_(ls, i, [&res](letter_t l){ res.insert(l); });
447  return res;
448  }
449  }
450 }
context< letterized_t< labelset_t_of< Context >>, weightset_t_of< Context >> letterized_context
Definition: labelset.hh:112
std::ostream & print_label_ranges_(const LabelSet &ls, const std::vector< typename LabelSet::value_t > &letters, const std::vector< typename LabelSet::value_t > &alphabet, std::ostream &out, format fmt)
Print a set of labels with ranges.
Definition: labelset.hh:290
Functor to compare Values of ValueSets.
Definition: functional.hh:89
context< law_t< labelset_t_of< Ctx >>, weightset_t_of< Ctx >> word_context_t
Definition: labelset.hh:269
law_t< LabelSet > make_wordset(const LabelSet &ls)
The wordset of a labelset.
Definition: labelset.hh:258
letterized_context< context< LabelSet, WeightSet > > make_letterized_context(const context< LabelSet, WeightSet > &c)
The letterized context for c.
Definition: labelset.hh:117
auto label_one(const LabelSet &ls) -> typename LabelSet::value_t
Enjoy type inference.
Definition: labelset.hh:53
context< nullableset_t< labelset_t_of< Ctx >>, weightset_t_of< Ctx >> nullableset_context_t
Definition: labelset.hh:158
typename nullableset_traits< LabelSet >::type nullableset_t
The smallest nullableset that includes LabelSet.
Definition: labelset.hh:142
typename proper_traits< LabelSet >::type proper_t
The type of the corresponding proper LabelSet.
Definition: labelset.hh:192
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:64
letterized_t< LabelSet > make_letterized(const LabelSet &ls)
Definition: labelset.hh:99
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
The LAW from a LAL.
Definition: labelset.hh:248
free_context< context< LabelSet, WeightSet > > make_free_context(const context< LabelSet, WeightSet > &c)
The free context for c.
Definition: labelset.hh:234
const weightset_ptr & weightset() const
Definition: context.hh:100
return res
Definition: multiply.hh:398
static constexpr bool is_letterized
Definition: labelset.hh:80
context< proper_t< letterized_t< labelset_t_of< Context >>>, weightset_t_of< Context >> free_context
Definition: labelset.hh:229
The smallest nullableset which includes LabelSet.
Definition: labelset.hh:137
decltype(std::declval< LabelSet >().generators()) generators_mem_fn_t
The type of the LabelSet::generators() member function.
Definition: labelset.hh:22
typename letterized_traits< LabelSet >::labelset_t letterized_t
Definition: labelset.hh:91
Definition: a-star.hh:8
typename law_traits< LabelSet >::type law_t
The smallest wordset that includes LabelSet.
Definition: labelset.hh:253
bool_constant< letterized_traits< LabelSet >::is_letterized > is_letterized_t
Definition: labelset.hh:95
An input/output format for valuesets.
Definition: format.hh:13
Container set_difference(const Container &s1, const Container &s2)
The set of members of s1 that are not members of s2.
Definition: algorithm.hh:171
const labelset_ptr & labelset() const
Definition: context.hh:95
nullableset_context_t< context< LabelSet, WeightSet > > make_nullableset_context(const context< LabelSet, WeightSet > &ctx)
The nullableset context of a context.
Definition: labelset.hh:163
static labelset_t labelset(const labelset_t &ls)
Definition: labelset.hh:83
std::ostream & print_label_class(const LabelSet &ls, const std::vector< typename LabelSet::value_t > &letters, std::ostream &out, format fmt)
Print a set of labels (letterized) with classes.
Definition: labelset.hh:324
A traits to compute the letterized context.
Definition: labelset.hh:78
decltype(std::declval< LabelSet >().one()) one_t
Definition: labelset.hh:34
static type value(const LabelSet &ls)
Definition: labelset.hh:184
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:67
proper_t< LabelSet > make_proper(const LabelSet &ls)
The corresponding proper LabelSet.
Definition: labelset.hh:197
Print for LaTeX.
Definition: format.hh:22
std::integral_constant< bool, B > bool_constant
Definition: type_traits.hh:12
From a labelset, its non-nullable labelset.
Definition: labelset.hh:181
context< proper_t< labelset_t_of< Context >>, weightset_t_of< Context >> proper_context
Definition: labelset.hh:210
nullableset_t< LabelSet > make_nullableset(const LabelSet &ls)
The nullableset of a labelset.
Definition: labelset.hh:147
word_context_t< context< LabelSet, WeightSet > > make_word_context(const context< LabelSet, WeightSet > &ctx)
The wordset context of a context.
Definition: labelset.hh:274
bool none_of_equal(const Range &r, const Value &value)
Definition: algorithm.hh:148
LabelSet::letters_t conv_label_class_(const LabelSet &ls, std::istream &i)
Read a set of letters (hence, guaranteed in order, and unique).
Definition: labelset.hh:440
auto make_proper_context(const context< LabelSet, WeightSet > &ctx) -> proper_context< context< LabelSet, WeightSet >>
From a context, its non-nullable context.
Definition: labelset.hh:215