Awali
Another Weighted Automata library
derivation.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2023 Sylvain Lombardy, Victor Marsault, Jacques Sakarovitch
3 //
4 // Awali is a free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 #ifndef AWALI_ALGOS_DERIVATION_HH
18 # define AWALI_ALGOS_DERIVATION_HH
19 
25 #include <awali/sttc/ctx/fwd.hh>
26 #include <awali/sttc/misc/raise.hh>
29 # include <stack>
30 # include <iostream>
31 # include <unordered_map>
32 
33 # if DEBUG
34 # define DEBUG_IFELSE(Then, Else) Then
35 # else
36 # define DEBUG_IFELSE(Then, Else) Else
37 # endif
38 
39 # define DEBUG_IF(Then) DEBUG_IFELSE(Then,)
40 
41 namespace awali { namespace sttc {
42 
43 
44  /*---------------------.
45  | derivation(ratexp). |
46  `---------------------*/
47 
48  namespace rat
49  {
50  template <typename RatExpSet>
52  : public RatExpSet::const_visitor
53  {
54  public:
55  using ratexpset_t = RatExpSet;
59  using ratexp_t = typename ratexpset_t::value_t;
61  using weight_t = typename weightset_t::value_t;
62 
65 
66  using super_type = typename ratexpset_t::const_visitor;
67  using node_t = typename super_type::node_t;
68 
69  constexpr static const char* me() { return "derivation"; }
70 
72  : rs_(rs)
73  {}
74 
76  operator()(const ratexp_t& v, label_t var)
77  {
78  variable_ = var;
79  v->accept(*this);
80  return std::move(res_);
81  }
82 
83  // FIXME: duplicate with expand.
84  ratexp_t
86  {
87  ratexp_t res = rs_.zero();
88  for (const auto& m: p)
89  res = rs_.add(res, rs_.lmul(m.second, m.first));
90  return res;
91  }
92 
95 
97  {
98  res_ = ps_.zero();
99  cst_ = ws_.zero();
100  }
101 
103  {
104  res_ = ps_.zero();
105  cst_ = ws_.one();
106  }
107 
109  {
110  if (e.value() == variable_)
111  res_ = ps_.one();
112  else
113  res_ = ps_.zero();
114  cst_ = ws_.zero();
115  }
116 
118  {
119  polynomial_t res = ps_.zero();
120  weight_t w = ws_.zero();
121  for (const auto& v: e)
122  {
123  v->accept(*this);
124  ps_.add_here(res, res_);
125  w = ws_.add(w, cst_);
126  }
127  res_ = std::move(res);
128  cst_ =w;
129  }
130 
132  {
133  // We generate a sum.
134  auto res = ps_.zero();
135  // Accumulate the product of the constant terms of the
136  // previous factors.
137  weight_t w = ws_.one();
138  for (unsigned i = 0, n = e.size(); i < n; ++i)
139  {
140  const auto& v = e[i];
141  v->accept(*this);
142  for (unsigned j = i + 1; j < n; ++j)
143  res_ = ps_.rmul_letter(res_, e[j]);
144  ps_.add_here(res, ps_.lmul(w, res_));
145  w = ws_.mul(w, cst_);
146  }
147  res_ = std::move(res);
148  cst_ = w;
149  }
150 
154 
156  {
157  e.sub()->accept(*this);
158  // We need a copy of e, but without its weights.
159  cst_ = ws_.star(cst_);
160  res_ = ps_.lmul(cst_,
161  ps_.rmul_letter(res_, e.shared_from_this()));
162  }
163 
165  {
166  e.sub()->accept(*this);
167  cst_ = ws_.add(cst_, ws_.one());
168  }
169 
171  {
172  e.sub()->accept(*this);
173  // We need a copy of e, but without its weights.
174  cst_ = ws_.plus(cst_);
175  res_ = ps_.rmul_letter(res_, rs_.star(e.sub()));
176  }
178  {
179  e.sub()->accept(*this);
180  res_ = ps_.lmul(e.weight(), res_);
181  cst_ = ws_.mul( e.weight(), cst_);
182  }
183 
185  {
186  e.sub()->accept(*this);
187  polynomial_t res;
188  for (const auto& m: res_)
189  ps_.add_here(res, rs_.rmul(m.first, e.weight()), m.second);
190  res_ = res;
191  cst_ = ws_.mul(cst_, e.weight());
192  }
193 
194  private:
195  ratexpset_t rs_;
197  weightset_t ws_ = *rs_.weightset();
200  polynomial_t res_;
202  label_t variable_;
203  weight_t cst_;
204  };
205 
206  } // rat::
207 
209  template <typename RatExpSet>
210  inline
211  rat::ratexp_polynomial_t<RatExpSet>
212  derivation(const RatExpSet& rs,
213  const typename RatExpSet::ratexp_t& e,
215  bool breaking = false)
216  {
217  static_assert(RatExpSet::context_t::labelset_t::is_free(),
218  "requires free labelset");
220  auto res = derivation(e, a);
221  if (breaking)
222  res = split(rs, res);
223  return res;
224  }
225 
226 
228  template <typename RatExpSet>
229  inline
230  rat::ratexp_polynomial_t<RatExpSet>
231  derivation(const RatExpSet& rs,
234  bool breaking = false)
235  {
236  auto ps = rat::make_ratexp_polynomialset(rs);
237  using polynomial_t = rat::ratexp_polynomial_t<RatExpSet>;
238  polynomial_t res;
239  for (const auto& m: p)
240  res = ps.add(res,
241  ps.lmul(m.second, derivation(rs, m.first, a, breaking)));
242  return res;
243  }
244 
245 
247  template <typename RatExpSet>
248  inline
249  rat::ratexp_polynomial_t<RatExpSet>
250  derivation(const RatExpSet& rs,
251  const typename RatExpSet::ratexp_t& e,
253  bool breaking = false)
254  {
255  auto i = std::begin(word);
256  auto end = std::end(word);
257  require(i != end, "derivation: word cannot be empty");
258  auto res = derivation(rs, e, *i, breaking);
259  for (++i; i != end; ++i)
260  res = derivation(rs, res, *i, breaking);
261  return res;
262  }
263 
264  /*-----------------------.
265  | derived_term(ratexp). |
266  `-----------------------*/
267 
268  namespace internal
269  {
270  template <typename RatExpSet>
272  {
273  using ratexpset_t = RatExpSet;
274  using ratexp_t = typename ratexpset_t::value_t;
275 
278 
280 
284 
286  using smap = std::unordered_map<ratexp_t, state_t,
289 
290  derived_termer(const ratexpset_t& rs, bool breaking = false, bool keep_history = true)
291  : rs_(rs)
292  , breaking_(breaking)
293  , res_{make_shared_ptr<automaton_t>(rs_.context())}
294  , keep_history_(keep_history)
295  {}
296 
300  {
301  // Benches show that the map_.emplace technique is slower, and
302  // then that operator[] is faster than emplace.
303  state_t res;
304  auto i = map_.find(r);
305  if (i == std::end(map_))
306  {
307  DEBUG_IF(std::cerr << "New state: "; rs_.print(r, std::cerr) << '\n'; );
308  res = res_->add_state();
309  map_[r] = res;
310  todo_.push(r);
311  }
312  else
313  res = i->second;
314  return res;
315  }
316 
318  {
319  weightset_t ws = *rs_.weightset();
320  // Turn the ratexp into a polynomial.
321  {
322  polynomial_t initial
323  = breaking_ ? split(rs_, ratexp)
324  : polynomial_t{{ratexp, ws.one()}};
325  for (const auto& p: initial)
326  // Also loads todo_.
327  res_->set_initial(state(p.first), p.second);
328  }
329 
330  const auto& ls = rs_.labelset()->genset();
331  rat::derivation_visitor<RatExpSet> derivator{rs_};
332  while (!todo_.empty())
333  {
334  ratexp_t src = todo_.top();
335  auto s = map_[src];
336  todo_.pop();
337  res_->set_final(s, constant_term(rs_, src));
338  for (auto l : ls) {
339  auto der = derivator(src, l);
340  if (breaking_)
341  der = split(rs_, der);
342 
343  for (const auto& m: der)
344  res_->add_transition(s, state(m.first), l, m.second);
345  }
346  }
347  if(keep_history_) {
348  auto history = std::make_shared<ratexp_history<ratexpset_t>>(rs_);
349  res_->set_history(history);
350  for (const auto& p: map_)
351  {
352  history->add_state(p.second, p.first);
353  }
354  }
355  return std::move(res_);
356  }
357 
358  private:
360  ratexpset_t rs_;
362  bool breaking_ = false;
363  //The map from rat exps into states
364  smap map_;
366  automaton_t res_;
368  std::stack<ratexp_t> todo_;
369 
370  bool keep_history_;
371  };
372  }
373 
375  template <typename RatExpSet>
376  inline
377  mutable_automaton<typename RatExpSet::context_t>
378  derived_term(const RatExpSet& rs, const typename RatExpSet::ratexp_t& r,
379  bool breaking = false, bool keep_history = true)
380  {
381  internal::derived_termer<RatExpSet> dt{rs, breaking, keep_history};
382  return dt(r);
383  }
384 
385 
386 }}//end of ns awali::stc
387 
388 #endif // !AWALI_ALGOS_DERIVATION_HH
carries the algebraic settings of automata
Definition: context.hh:40
The semiring of Natural numbers.
Definition: n.hh:34
Linear combination of labels: map labels to weights.
Definition: polynomialset.hh:69
const value_t & one() const
Definition: polynomialset.hh:349
std::map< label_t, weight_t, internal::less< labelset_t > > value_t
Definition: polynomialset.hh:83
value_t & add_here(value_t &v, const value_t &p) const
v += p.
Definition: polynomialset.hh:130
const value_t & zero() const
Definition: polynomialset.hh:375
value_t lmul(const weight_t &w, const value_t &v) const
Left exterior product.
Definition: polynomialset.hh:263
value_t rmul_letter(const value_t &v, const label_t &rhs) const
Right product.
Definition: polynomialset.hh:299
The semiring of floating Numbers.
Definition: r.hh:35
Definition: ratexp.hh:280
Definition: ratexp.hh:262
Definition: derivation.hh:53
typename ratexpset_t::const_visitor super_type
Definition: derivation.hh:66
ratexp_polynomialset_t< ratexpset_t > polynomialset_t
Definition: derivation.hh:63
derivation_visitor(const ratexpset_t &rs)
Definition: derivation.hh:71
AWALI_RAT_VISIT(zero,)
Definition: derivation.hh:96
typename super_type::node_t node_t
Definition: derivation.hh:67
context_t_of< ratexpset_t > context_t
Definition: derivation.hh:56
weightset_t_of< ratexpset_t > weightset_t
Definition: derivation.hh:60
ratexp_t ratexp(const polynomial_t p)
Definition: derivation.hh:85
constexpr static const char * me()
Definition: derivation.hh:69
RatExpSet ratexpset_t
Definition: derivation.hh:55
AWALI_RAT_VISIT(atom, e)
Definition: derivation.hh:108
labelset_t_of< context_t > labelset_t
Definition: derivation.hh:57
AWALI_RAT_VISIT(prod, e)
Definition: derivation.hh:131
AWALI_RAT_VISIT(plus, e)
Definition: derivation.hh:170
typename ratexpset_t::value_t ratexp_t
Definition: derivation.hh:59
typename weightset_t::value_t weight_t
Definition: derivation.hh:61
AWALI_RAT_VISIT(sum, e)
Definition: derivation.hh:117
polynomial_t operator()(const ratexp_t &v, label_t var)
Definition: derivation.hh:76
label_t_of< context_t > label_t
Definition: derivation.hh:58
typename polynomialset_t::value_t polynomial_t
Definition: derivation.hh:64
AWALI_RAT_VISIT(maybe, e)
Definition: derivation.hh:164
AWALI_RAT_VISIT(rweight, e)
Definition: derivation.hh:184
AWALI_RAT_VISIT(one,)
Definition: derivation.hh:102
AWALI_RAT_VISIT(lweight, e)
Definition: derivation.hh:177
Definition: ratexp.hh:176
An inner node with multiple children.
Definition: ratexp.hh:115
An inner node implementing a weight.
Definition: ratexp.hh:208
This is useful to make hashes with labels or weights as keys without using non-default constructors; ...
Definition: hash.hh:42
This is useful to make hashes with labels or weights as keys without using non-default constructors; ...
Definition: hash.hh:58
typename ratexp_polynomialset_t< RatExpSet >::value_t ratexp_polynomial_t
Type of polynomials of ratexps from the RatExpSet type.
Definition: split.hh:42
std::shared_ptr< const node< Label, Weight > > ratexp
Definition: fwd.hh:182
ratexp_polynomialset_t< RatExpSet > make_ratexp_polynomialset(const RatExpSet &rs)
From a RatExpSet to its polynomialset.
Definition: split.hh:48
mutable_automaton< typename RatExpSet::context_t > derived_term(const RatExpSet &rs, const typename RatExpSet::ratexp_t &r, bool breaking=false, bool keep_history=true)
Derive a ratexp wrt to a string.
Definition: derivation.hh:378
typename internal::label_t_of_impl< internal::base_t< ValueSet > >::type label_t_of
Helper to retrieve the type of the labels of a value set.
Definition: traits.hh:71
rat::ratexp_polynomial_t< RatExpSet > derivation(const RatExpSet &rs, const typename RatExpSet::ratexp_t &e, label_t_of< RatExpSet > a, bool breaking=false)
Derive a ratexp wrt to a letter.
Definition: derivation.hh:212
SharedPtr make_shared_ptr(Args &&... args)
Same as std::make_shared, but parameterized by the shared_ptr type, not the (pointed to) element_type...
Definition: memory.hh:29
typename internal::context_t_of_impl< internal::base_t< ValueSet > >::type context_t_of
Helper to retrieve the type of the context of a value set.
Definition: traits.hh:66
typename internal::labelset_t_of_impl< internal::base_t< ValueSet > >::type labelset_t_of
Helper to retrieve the type of the labelset of a value set.
Definition: traits.hh:76
weight_t_of< RatExpSet > constant_term(const RatExpSet &rs, const typename RatExpSet::ratexp_t &e)
Definition: constant_term.hh:165
rat::ratexp_polynomial_t< RatExpSet > split(const RatExpSet &rs, const typename RatExpSet::ratexp_t &e)
Split a ratexp.
Definition: split.hh:253
std::shared_ptr< internal::mutable_automaton_impl< Context > > mutable_automaton
Definition: mutable_automaton.hh:45
void require(bool b, Args &&... args)
If b is not verified, raise an error with args as message.
Definition: raise.hh:55
typename internal::weightset_t_of_impl< internal::base_t< ValueSet > >::type weightset_t_of
Helper to retrieve the type of the weightset of a value set.
Definition: traits.hh:86
Main namespace of Awali.
Definition: ato.hh:22
unsigned state_t
Definition: types.hh:21
Definition: derivation.hh:272
typename ratexpset_t::value_t ratexp_t
Definition: derivation.hh:274
weightset_t_of< context_t > weightset_t
Definition: derivation.hh:277
mutable_automaton< context_t > automaton_t
Definition: derivation.hh:279
typename polynomialset_t::value_t polynomial_t
Definition: derivation.hh:283
RatExpSet ratexpset_t
Definition: derivation.hh:273
context_t_of< ratexpset_t > context_t
Definition: derivation.hh:276
derived_termer(const ratexpset_t &rs, bool breaking=false, bool keep_history=true)
Definition: derivation.hh:290
std::unordered_map< ratexp_t, state_t, utils::hash< ratexpset_t >, utils::equal_to< ratexpset_t > > smap
Symbolic states to state handlers.
Definition: derivation.hh:288
state_t state(const ratexp_t &r)
The state for ratexp r.
Definition: derivation.hh:299
automaton_t operator()(const ratexp_t &ratexp)
Definition: derivation.hh:317
trait that computes the related types of a labelset
Definition: traits.hh:34
#define DEBUG_IF(Then)
Definition: derivation.hh:39
#define AWALI_RAT_UNSUPPORTED(Type)
Definition: visitor.hh:75