Awali
Another Weighted Automata library
derivation.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2022 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  res_ = ps_.lmul(e.weight(), res_);
168  cst_ = ws_.mul( e.weight(), cst_);
169  }
170 
172  {
173  e.sub()->accept(*this);
174  polynomial_t res;
175  for (const auto& m: res_)
176  ps_.add_here(res, rs_.rmul(m.first, e.weight()), m.second);
177  res_ = res;
178  cst_ = ws_.mul(cst_, e.weight());
179  }
180 
181  private:
182  ratexpset_t rs_;
184  weightset_t ws_ = *rs_.weightset();
187  polynomial_t res_;
189  label_t variable_;
190  weight_t cst_;
191  };
192 
193  } // rat::
194 
196  template <typename RatExpSet>
197  inline
198  rat::ratexp_polynomial_t<RatExpSet>
199  derivation(const RatExpSet& rs,
200  const typename RatExpSet::ratexp_t& e,
202  bool breaking = false)
203  {
204  static_assert(RatExpSet::context_t::labelset_t::is_free(),
205  "requires free labelset");
207  auto res = derivation(e, a);
208  if (breaking)
209  res = split(rs, res);
210  return res;
211  }
212 
213 
215  template <typename RatExpSet>
216  inline
217  rat::ratexp_polynomial_t<RatExpSet>
218  derivation(const RatExpSet& rs,
221  bool breaking = false)
222  {
223  auto ps = rat::make_ratexp_polynomialset(rs);
224  using polynomial_t = rat::ratexp_polynomial_t<RatExpSet>;
225  polynomial_t res;
226  for (const auto& m: p)
227  res = ps.add(res,
228  ps.lmul(m.second, derivation(rs, m.first, a, breaking)));
229  return res;
230  }
231 
232 
234  template <typename RatExpSet>
235  inline
236  rat::ratexp_polynomial_t<RatExpSet>
237  derivation(const RatExpSet& rs,
238  const typename RatExpSet::ratexp_t& e,
240  bool breaking = false)
241  {
242  auto i = std::begin(word);
243  auto end = std::end(word);
244  require(i != end, "derivation: word cannot be empty");
245  auto res = derivation(rs, e, *i, breaking);
246  for (++i; i != end; ++i)
247  res = derivation(rs, res, *i, breaking);
248  return res;
249  }
250 
251  /*-----------------------.
252  | derived_term(ratexp). |
253  `-----------------------*/
254 
255  namespace internal
256  {
257  template <typename RatExpSet>
259  {
260  using ratexpset_t = RatExpSet;
261  using ratexp_t = typename ratexpset_t::value_t;
262 
265 
267 
271 
273  using smap = std::unordered_map<ratexp_t, state_t,
276 
277  derived_termer(const ratexpset_t& rs, bool breaking = false, bool keep_history = true)
278  : rs_(rs)
279  , breaking_(breaking)
280  , res_{make_shared_ptr<automaton_t>(rs_.context())}
281  , keep_history_(keep_history)
282  {}
283 
287  {
288  // Benches show that the map_.emplace technique is slower, and
289  // then that operator[] is faster than emplace.
290  state_t res;
291  auto i = map_.find(r);
292  if (i == std::end(map_))
293  {
294  DEBUG_IF(std::cerr << "New state: "; rs_.print(r, std::cerr) << '\n'; );
295  res = res_->add_state();
296  map_[r] = res;
297  todo_.push(r);
298  }
299  else
300  res = i->second;
301  return res;
302  }
303 
305  {
306  weightset_t ws = *rs_.weightset();
307  // Turn the ratexp into a polynomial.
308  {
309  polynomial_t initial
310  = breaking_ ? split(rs_, ratexp)
311  : polynomial_t{{ratexp, ws.one()}};
312  for (const auto& p: initial)
313  // Also loads todo_.
314  res_->set_initial(state(p.first), p.second);
315  }
316 
317  const auto& ls = rs_.labelset()->genset();
318  rat::derivation_visitor<RatExpSet> derivator{rs_};
319  while (!todo_.empty())
320  {
321  ratexp_t src = todo_.top();
322  auto s = map_[src];
323  todo_.pop();
324  res_->set_final(s, constant_term(rs_, src));
325  for (auto l : ls) {
326  auto der = derivator(src, l);
327  if (breaking_)
328  der = split(rs_, der);
329 
330  for (const auto& m: der)
331  res_->add_transition(s, state(m.first), l, m.second);
332  }
333  }
334  if(keep_history_) {
335  auto history = std::make_shared<ratexp_history<ratexpset_t>>(rs_);
336  res_->set_history(history);
337  for (const auto& p: map_)
338  {
339  history->add_state(p.second, p.first);
340  }
341  }
342  return std::move(res_);
343  }
344 
345  private:
347  ratexpset_t rs_;
349  bool breaking_ = false;
350  //The map from rat exps into states
351  smap map_;
353  automaton_t res_;
355  std::stack<ratexp_t> todo_;
356 
357  bool keep_history_;
358  };
359  }
360 
362  template <typename RatExpSet>
363  inline
364  mutable_automaton<typename RatExpSet::context_t>
365  derived_term(const RatExpSet& rs, const typename RatExpSet::ratexp_t& r,
366  bool breaking = false, bool keep_history = true)
367  {
368  internal::derived_termer<RatExpSet> dt{rs, breaking, keep_history};
369  return dt(r);
370  }
371 
372 
373 }}//end of ns awali::stc
374 
375 #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:327
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:353
value_t lmul(const weight_t &w, const value_t &v) const
Left exterior product.
Definition: polynomialset.hh:241
value_t rmul_letter(const value_t &v, const label_t &rhs) const
Right product.
Definition: polynomialset.hh:277
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
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(rweight, e)
Definition: derivation.hh:171
AWALI_RAT_VISIT(one,)
Definition: derivation.hh:102
AWALI_RAT_VISIT(lweight, e)
Definition: derivation.hh:164
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:172
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:365
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:199
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:155
rat::ratexp_polynomial_t< RatExpSet > split(const RatExpSet &rs, const typename RatExpSet::ratexp_t &e)
Split a ratexp.
Definition: split.hh:243
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:259
typename ratexpset_t::value_t ratexp_t
Definition: derivation.hh:261
weightset_t_of< context_t > weightset_t
Definition: derivation.hh:264
mutable_automaton< context_t > automaton_t
Definition: derivation.hh:266
typename polynomialset_t::value_t polynomial_t
Definition: derivation.hh:270
RatExpSet ratexpset_t
Definition: derivation.hh:260
context_t_of< ratexpset_t > context_t
Definition: derivation.hh:263
derived_termer(const ratexpset_t &rs, bool breaking=false, bool keep_history=true)
Definition: derivation.hh:277
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:275
state_t state(const ratexp_t &r)
The state for ratexp r.
Definition: derivation.hh:286
automaton_t operator()(const ratexp_t &ratexp)
Definition: derivation.hh:304
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:73