Vcsn  2.3
Be Rational
eval.hh
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 
6 #include <vcsn/core/automaton.hh> // out
7 #include <vcsn/ctx/traits.hh>
8 #include <vcsn/dyn/automaton.hh>
9 #include <vcsn/dyn/fwd.hh>
10 #include <vcsn/dyn/value.hh>
11 #include <vcsn/misc/algorithm.hh>
12 
13 namespace vcsn
14 {
15  namespace detail
16  {
17  template <Automaton Aut>
18  class evaluator
19  {
20  static_assert(labelset_t_of<Aut>::is_free(),
21  "evaluate: requires free labelset");
22 
23  using automaton_t = Aut;
27  using weight_t = typename weightset_t::value_t;
28 
29  // state -> weight.
30  using weights_t = std::vector<weight_t>;
31 
32  public:
34  : aut_(a)
35  {}
36 
37  weight_t operator()(const word_t& word) const
38  {
39  // Initialization.
40  const weight_t zero = ws_.zero();
41 
42  // An array indexed by state numbers.
43  //
44  // Do not use braces (v1{size, zero}): the type of zero might
45  // result in the compiler believing we are building a vector
46  // with two values: size and zero.
47  //
48  // We start with just two states numbered 0 and 1: pre() and
49  // post().
50  weights_t v1(2, zero);
51  v1.reserve(states_size(aut_));
52  v1[aut_->pre()] = ws_.one();
53  weights_t v2{v1};
54  v2.reserve(states_size(aut_));
55 
56  // Computation.
57  auto ls = *aut_->labelset();
58  for (auto l : ls.letters_of(ls.delimit(word)))
59  {
60  v2.assign(v2.size(), zero);
61  for (size_t s = 0; s < v1.size(); ++s)
62  if (!ws_.is_zero(v1[s])) // delete if bench >
63  for (auto t : out(aut_, s, l))
64  {
65  // Make sure the vectors are large enough for dst.
66  // Exponential growth on the capacity, but keep
67  // the actual size as small as possible.
68  auto dst = aut_->dst_of(t);
69  if (v2.size() <= dst)
70  {
71  auto capacity = v2.capacity();
72  while (capacity <= dst)
73  capacity *= 2;
74  v1.reserve(capacity);
75  v2.reserve(capacity);
76  v1.resize(dst + 1, zero);
77  v2.resize(dst + 1, zero);
78  }
79  // Introducing a reference to v2[aut_->dst_of(tr)] is
80  // tempting, but won't work for std::vector<bool>.
81  // FIXME: Specialize for Boolean?
82  v2[dst] =
83  ws_.add(v2[dst],
84  ws_.mul(v1[s], aut_->weight_of(t)));
85  }
86  std::swap(v1, v2);
87  }
88  return v1[aut_->post()];
89  }
90  private:
92  const weightset_t& ws_ = *aut_->weightset();
93  };
94 
95  } // namespace detail
96 
98  template <Automaton Aut>
99  auto
100  eval(const Aut& a, const word_t_of<Aut>& w)
101  -> std::enable_if_t<!context_t_of<Aut>::is_lao, weight_t_of<Aut>>
102  {
104  return e(w);
105  }
106 
112  template <Automaton Aut>
113  auto
114  eval(const Aut& a)
115  -> std::enable_if_t<context_t_of<Aut>::is_lao, weight_t_of<Aut>>
116  {
117  require(is_proper(a), "eval: cannot evaluate with spontaneous transitions");
118  const auto& ws = *a->weightset();
119  auto res = ws.zero();
120  for (auto init_tr: initial_transitions(a))
121  {
122  auto s = a->dst_of(init_tr);
123  auto w = a->weight_of(init_tr);
124  for (auto out: all_out(a, s))
125  {
126  assert(a->dst_of(out) == a->post());
127  res = ws.add(res, ws.mul(w, a->weight_of(out)));
128  }
129  }
130  return res;
131  }
132 
133  namespace dyn
134  {
135  namespace detail
136  {
138  template <Automaton Aut, typename LabelSet>
139  weight
140  eval(const automaton& aut, const label& lbl)
141  {
142  const auto& a = aut->as<Aut>();
143  const auto& l = lbl->as<LabelSet>().value();
144  auto res = ::vcsn::eval(a, l);
145  return {*a->weightset(), res};
146  }
147  }
148  }
149 } // namespace vcsn
const weightset_t & ws_
Definition: eval.hh:92
value_impl< detail::weight_tag > weight
Definition: fwd.hh:28
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
Definition: traits.hh:66
typename labelset_t_of< base_t< ValueSet >>::word_t word_t_of
Definition: traits.hh:90
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
Definition: traits.hh:63
size_t states_size(const Aut &aut)
The largest state number, plus one.
Definition: automaton.hh:19
automaton_t aut_
Definition: eval.hh:91
typename weightset_t::value_t weight_t
Definition: eval.hh:27
auto out(const Aut &aut, state_t_of< Aut > s)
Indexes of visible transitions leaving state s.
Definition: automaton.hh:64
state_t_of< automaton_t > state_t
Definition: eval.hh:24
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:91
A dyn Value/ValueSet.
Definition: fwd.hh:23
return res
Definition: multiply.hh:398
weightset_t_of< automaton_t > weightset_t
Definition: eval.hh:26
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
Definition: traits.hh:64
weight eval(const automaton &aut, const label &lbl)
Bridge.
Definition: eval.hh:140
Definition: a-star.hh:8
auto eval(const Aut &a, const word_t_of< Aut > &w) -> std::enable_if_t<!context_t_of< Aut >::is_lao, weight_t_of< Aut >>
General case of evaluation.
Definition: eval.hh:100
A dyn automaton.
Definition: automaton.hh:17
word_t_of< automaton_t > word_t
Definition: eval.hh:25
evaluator(const automaton_t &a)
Definition: eval.hh:33
bool is_proper(const Aut &aut)
Test whether an automaton is proper.
Definition: is-proper.hh:47
weight_t operator()(const word_t &word) const
Definition: eval.hh:37
auto initial_transitions(const Aut &aut) -> decltype(aut->all_out(aut->pre()))
Indexes of transitions to (visible) initial states.
Definition: automaton.hh:145
auto & as()
Extract wrapped typed value.
Definition: value.hh:53
std::vector< weight_t > weights_t
Definition: eval.hh:30
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
Definition: traits.hh:67
auto & as()
Extract wrapped typed automaton.
Definition: automaton.hh:37
auto all_out(const Aut &aut, state_t_of< Aut > s)
Indexes of transitions leaving state s.
Definition: automaton.hh:45