Awali
Another Weighted Automata library
concatenate.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_CONCATENATE_HH
18 # define AWALI_ALGOS_CONCATENATE_HH
19 
20 # include <unordered_set>
21 # include <vector>
22 
23 #include <awali/common/priority.hh>
24 #include <awali/sttc/algos/copy.hh>
26 #include <awali/sttc/algos/product.hh> // join_automata
28 #include <awali/sttc/algos/sum.hh>
30 #include <awali/sttc/misc/raise.hh> // require
31 
32 namespace awali {
33  namespace sttc {
34 
35  /*,------------------------------------.
36  | concatenate(automaton, automaton). |
37  `------------------------------------'*/
38 
41  namespace internal {
43  template <typename A, typename B, typename P>
44  A&
46  {
47  if(!is_standard(b))
48  b=standard(b);
49  //using automaton_t = A;
50  auto& ws = *res->weightset();
51  auto& ls = *res->labelset();
52  auto& wsb = *b->weightset();
53  auto& lsb = *b->labelset();
54 
55  // The set of the current (left-hand side) final transitions.
56  auto ftr_ = res->final_transitions();
57  // Store these transitions by copy.
58  using transs_t = std::vector<transition_t>;
59  transs_t ftr{ begin(ftr_), end(ftr_) };
60 
61  state_t b_initial = b->dst_of(*(b->initial_transitions().begin()));
62  // State in B -> state in Res.
63  // The initial state of b is not copied.
64  std::unordered_map<state_t, state_t> m;
65  m.emplace(b->post(), res->post());
66  for (auto s: b->states())
67  if (!b->is_initial(s))
68  m.emplace(s, res->add_state());
69 
70  // Import all the B transitions, except the initial ones
71  // and those from its (genuine) initial state.
72  //
73  // FIXME: provide generalized copy() that returns the map of
74  // states orig -> copy.
75  for (auto t: b->all_transitions())
76  if (b->src_of(t) != b->pre() && b->src_of(t) != b_initial)
77  res->new_transition_copy(m[b->src_of(t)], m[b->dst_of(t)], b, t);
78 
79  // Branch all the final transitions of res to the successors of
80  // b's initial state.
81  for (auto t1: ftr)
82  {
83  // Remove the previous final transition first, as we might add
84  // a final transition for the same state later.
85  //
86  // For instance on "{2}a+({3}\e+{5}a)", the final state s1 of
87  // {2}a will be made final thanks to {3}\e. So if we compute
88  // the new transitions from s1 and then remove t1, we will
89  // have removed the fact that s1 is final thanks to {3}\e.
90  //
91  // Besides, s1 will become final with weight {3}, which might
92  // interfere with {5}a too.
93  auto s1 = res->src_of(t1);
94  auto w1 = res->weight_of(t1);
95  res->del_transition(t1);
96  for (auto t2: b->all_out(b_initial))
97  res->set_transition(s1,
98  m[b->dst_of(t2)],
99  ls.conv(lsb,b->label_of(t2)),
100  ws.mul(w1, ws.conv(wsb,b->weight_of(t2))));
101  }
102  return res;
103  }
104 
105  template <typename A, typename B, typename P>
106  auto
107  concatenate_here(A& res, B b, priority::TWO<P>) -> typename std::enable_if<labelset_t_of<A>::has_one(),A&>::type
108  {
109  //using automaton_t = A;
110  const auto& ws = *res->weightset();
111 // const auto& wsb = *b->weightset();
112  auto one=res->labelset()->one();
113 
114  // The set of the final transitions of res;
115  auto ftr_ = res->final_transitions();
116  // Store these transitions by copy.
117  using transs_t = std::vector<transition_t>;
118  transs_t ftr{ begin(ftr_), end(ftr_) };
119 
120  copier<B,A> cp(b,res);
121  cp([](state_t) { return true; });
122  const auto& iom=cp.in_out_map();
123  //The set of initial states of b in res
124  std::unordered_set<state_t> ist;
125  for(auto itb : b->initial_transitions())
126  ist.emplace(iom.at(b->dst_of(itb)));
127  // The set of the initial transitions of the copy of b in res;
128  transs_t itr;
129  for(auto tr : res->initial_transitions())
130  if(ist.find(res->dst_of(tr))!=ist.end())
131  itr.emplace_back(tr);
132 
133  for(auto ft: ftr)
134  for(auto it: itr)
135  res->new_transition(res->src_of(ft),
136  res->dst_of(it),
137  one,
138  ws.mul(res->weight_of(ft), res->weight_of(it)));
139  for(auto ft: ftr)
140  res->del_transition(ft);
141  for(auto it: itr)
142  res->del_transition(it);
143  return res;
144  }
145  }//internal
146 
159  template <typename A, typename B>
160  A&
161  concatenate_here(A& res, const B& aut)
162  {
164  }
165 
188  template <typename Aut1, typename Aut2>
189  inline
190  auto
191  concatenate(const Aut1& aut1, const Aut2& aut2)
192  -> decltype(join_automata(aut1, aut2))
193  {
194  auto res = join_automata(aut1, aut2);
195  copy_into(aut1, res, false);
196  concatenate_here(res, aut2);
197  return res;
198  }
199 
200  /*-----------------------------.
201  | chain(automaton, min, max). |
202  `-----------------------------*/
203 
218  template <typename Aut>
219  Aut
220  chain(const Aut& aut, unsigned min, int max)
221  {
222  Aut res =
223  make_shared_ptr<Aut>(aut->context());
224  if (max < 0)
225  {
226  res = star(aut);
227  if (min != 0)
228  res = concatenate(chain(aut, min, min), res);
229  }
230  else
231  {
232  if (min < 0)
233  min = 0;
234  if (min == 0)
235  {
236  auto s = res->add_state();
237  res->set_initial(s);
238  res->set_final(s);
239  }
240  else
241  {
242  res = sttc::copy(aut);
243  for (unsigned n = 1; n < min; ++n)
244  concatenate_here(res, aut);
245  }
246  if (min < max)
247  {
248  // Aut sum = automatonset.one();
249  Aut sum = make_shared_ptr<Aut>(aut->context());
250  {
251  auto s = sum->add_state();
252  sum->set_initial(s);
253  sum->set_final(s);
254  }
255  for (int n = 1; n <= max - min; ++n)
256  sum = sttc::sum(sum, chain(aut, n, n));
257  res = sttc::concatenate(res, sum);
258  }
259  }
260  return res;
261  }
262 
263 
264  /*------------------------------.
265  | concatenate(ratexp, ratexp). |
266  `------------------------------*/
267 
278  template <typename ValueSet>
279  inline
280  typename ValueSet::value_t
281  concatenate(const ValueSet& vs,
282  const typename ValueSet::value_t& lhs,
283  const typename ValueSet::value_t& rhs)
284  {
285  return vs.mul(lhs, rhs);
286  }
287 
288 
289  /*--------------------------.
290  | chain(ratexp, min, max). |
291  `--------------------------*/
292 
307  template <typename RatExpSet>
308  typename RatExpSet::ratexp_t
309  chain(const RatExpSet& rs, const typename RatExpSet::ratexp_t& r,
310  unsigned min, int max)
311  {
312  typename RatExpSet::ratexp_t res;
313  if (max < 0)
314  {
315  res = rs.star(r);
316  if (min > 0)
317  res = rs.mul(chain(rs, r, min, min), res);
318  }
319  else
320  {
321  if (min == 0)
322  res = rs.one();
323  else
324  {
325  res = r;
326  for (unsigned n = 1; n < min; ++n)
327  res = rs.mul(res, r);
328  }
329  if (min < max)
330  {
331  typename RatExpSet::ratexp_t sum = rs.one();
332  for (int n = 1; n <= max - min; ++n)
333  sum = rs.add(sum, chain(rs, r, n, n));
334  res = rs.mul(res, sum);
335  }
336  }
337  return res;
338  }
339 
340 
341  /*----------------------.
342  | mul(weight, weight). |
343  `----------------------*/
344 
345 
346 }
347 }//end of ns awali::stc
348 
349 #endif // !AWALI_ALGOS_CONCATENATE_HH
The Boolean semring.
Definition: b.hh:38
The semiring of Natural numbers.
Definition: n.hh:34
The semiring of floating Numbers.
Definition: r.hh:35
static value_t mul(const value_t l, const value_t r)
Definition: r.hh:83
static constexpr TOP< void > value
Definition: priority.hh:93
Definition: priority.hh:52
A & concatenate_here(A &res, B b, priority::ONE< P >)
Definition: concatenate.hh:45
auto sum(const Aut1 &aut1, const Aut2 &aut2, bool sum_standard=false) -> decltype(join_automata(aut1, aut2))
sums two automata
Definition: sum.hh:137
auto concatenate(const Aut1 &aut1, const Aut2 &aut2) -> decltype(join_automata(aut1, aut2))
Concatenates two automata.
Definition: concatenate.hh:191
bool is_standard(const Aut &a)
Definition: standard.hh:40
Aut::element_type::automaton_nocv_t star(const Aut &aut)
Star of an automaton.
Definition: star.hh:100
A & concatenate_here(A &res, const B &aut)
Concatenation of an automaton to another one.
Definition: concatenate.hh:161
void copy_into(const AutIn &in, AutOut &out, Pred keep_state, bool keep_history=true, bool transpose=false)
Copy an automaton.
Definition: copy.hh:144
Aut standard(Aut &aut, bool keep_history=true)
Definition: standard.hh:92
AutOut copy(const AutIn &input, Pred keep_state, bool keep_history=true, bool transpose=false)
A copy of input keeping only its states that are accepted by keep_state.
Definition: copy.hh:189
auto join_automata(Auts &&... auts) -> decltype(make_mutable_automaton(join(auts->context()...)))
Join between automata.
Definition: product.hh:39
Aut chain(const Aut &aut, unsigned min, int max)
chains automata to compute powers of a series
Definition: concatenate.hh:220
ATTRIBUTE_CONST int max(int a, int b)
Definition: arith.hh:54
ATTRIBUTE_CONST int min(int a, int b)
Definition: arith.hh:48
Main namespace of Awali.
Definition: ato.hh:22
unsigned state_t
Definition: types.hh:21
Copy an automaton.
Definition: copy.hh:41
const InOutMap & in_out_map() const
Definition: copy.hh:126