Awali
Another Weighted Automata library
synchronize.hh
Go to the documentation of this file.
1 // This file is part of Awali.
2 // Copyright 2016-2021 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_SYNCHRONIZE_HH
18 #define AWALI_ALGOS_SYNCHRONIZE_HH
19 
23 #include <awali/sttc/misc/add_epsilon_trans.hh> // is_epsilon
24 #include<unordered_map>
25 #include<map>
26 #include<stack>
27 #include<tuple>
28 #include<utility>
29 
30 namespace awali {
31  namespace sttc {
32  namespace internal {
33 
34 #ifndef DETAILS_APPEND
35 #define DETAILS_APPEND
36  void append(std::string & s, char c) {
37  s.append(1,c);
38  }
39  void append(std::string & s, const std::string t) {
40  s.append(t);
41  }
42 #endif
43 
44 
45  template <typename Tdc>
46  struct synchronizer {
48  using labelset0_t = typename labelset_t::template valueset_t<0>;
49  using labelset1_t = typename labelset_t::template valueset_t<1>;
52  using wordset0_value_t = typename wordset0_t::value_t;
53  using wordset1_value_t = typename wordset1_t::value_t;
54  using triple_t = std::tuple<state_t, wordset0_value_t, wordset1_value_t>;
55 
56  static Tdc algo(const Tdc& tdc, bool keep_history=true) {
57 
58  std::unordered_map<triple_t, state_t> states;
59  std::stack<triple_t> todo;
60 
61  Tdc res = make_mutable_automaton(tdc->context());
62 
63  auto get_state = [&](triple_t& triple) -> state_t {
64  auto it = states.find(triple);
65  if(it == states.end()) {
66  state_t r = res->add_state();
67  states.emplace(std::make_pair(triple, r));
68  todo.emplace(triple);
69  return r;
70  }
71  else
72  return it->second;
73  };
74 
75  //states to explore:
76  std::vector<triple_t> finals;
77 
78  for(auto i : tdc->initial_transitions()) {
79  triple_t tu{tdc->dst_of(i),wordset0_t::one(),wordset1_t::one()};
80  auto s = get_state(tu);
81  res->set_initial(s, tdc->weight_of(i));
82  todo.emplace(tu);
83  }
84  while(!todo.empty()) {
85  auto triple = todo.top();
86  todo.pop();
87  //retrieve the valuation of state s:
88  state_t s = get_state(triple);
89  for(auto tr : tdc->all_out(std::get<0>(triple))) {
90  state_t t = tdc->dst_of(tr);
91  if(t == tdc->post()) {
92  if(is_epsilon<wordset0_t>(std::get<1>(triple)) && is_epsilon<wordset1_t>(std::get<2>(triple)))
93  res->set_final(s, tdc->weight_of(tr));
94  else
95  finals.emplace_back(triple);
96  continue;
97  }
98  auto l= tdc->label_of(tr);
99  //the valuation of t is the valuation of s...
100  triple_t t_val{triple};
101  //... plus the label of the transition
102  std::get<0>(t_val)= t;
103  if(!is_epsilon<labelset0_t>(std::get<0>(l))) {
104  internal::append(std::get<1>(t_val),std::get<0>(l));
105  }
106  if(!is_epsilon<labelset1_t>(std::get<1>(l))) {
107  internal::append(std::get<2>(t_val),std::get<1>(l));
108  }
109  auto a = get_epsilon<labelset0_t>();
110  auto b = get_epsilon<labelset1_t>();
111  if(!is_epsilon<wordset0_t>(std::get<1>(t_val)) && !is_epsilon<wordset1_t>(std::get<2>(t_val))) {
112  a = std::get<1>(t_val)[0];
113  b = std::get<2>(t_val)[0];
114  std::get<1>(t_val) = std::get<1>(t_val).substr(1);
115  std::get<2>(t_val) = std::get<2>(t_val).substr(1);
116  }
117  state_t nt = get_state(t_val);
118  res->set_transition(s, nt, std::make_tuple(a,b), tdc->weight_of(tr));
119  }
120  }
121 
122  std::unordered_map<std::tuple<wordset0_value_t, wordset1_value_t>, state_t> statesf;
123  if(!finals.empty()) {
124  auto get_statef = [&](std::tuple<wordset0_value_t, wordset1_value_t>& p) -> state_t {
125  auto it = statesf.find(p);
126  if(it == statesf.end()) {
127  state_t r = res->add_state();
128  statesf.emplace(std::make_pair(p, r));
129  return r;
130  }
131  else
132  return it->second;
133  };
134  state_t s;
135  for(auto triple : finals) {
136  s = get_state(triple);
137  auto p = rem_in_tuple<0>::get(triple);
138  bool first=true;
139  while(!is_epsilon<wordset0_t>(std::get<0>(p)) || !is_epsilon<wordset1_t>(std::get<1>(p))) {
140  auto a = get_epsilon<labelset0_t>();
141  auto b = get_epsilon<labelset1_t>();
142  if(!is_epsilon<wordset0_t>(std::get<0>(p))) {
143  a=std::get<0>(p)[0];
144  std::get<0>(p) = std::get<0>(p).substr(1);
145  }
146  if(!is_epsilon<wordset1_t>(std::get<1>(p))) {
147  b=std::get<1>(p)[0];
148  std::get<1>(p) = std::get<1>(p).substr(1);
149  }
150  state_t t= get_statef(p);
151  if(first) {
152  res->set_transition(s, t, std::make_tuple(a, b),tdc->get_final_weight(std::get<0>(triple)));
153  first=false;
154  }
155  else
156  res->set_transition(s, t, std::make_tuple(a, b));
157  s=t;
158  }
159  }
160  res->set_final(s);
161  }
162  if(keep_history) {
163  auto final_history = std::make_shared<single_history<Tdc>>(tdc);
164  for(auto pp: states)
165  final_history->add_state(pp.second,std::get<0>(pp.first));
166  }
167  proper_here(res);
168  return res;
169  }
170  };
171 
172  template<typename Tdc>
175  using labelset0_t = typename labelset_t::template valueset_t<0>;
176  using labelset1_t = typename labelset_t::template valueset_t<1>;
177  private :
178  Tdc tdc_;
179  std::unordered_map<unsigned, unsigned> status;// 1: active, 2: checked
180  std::unordered_map<state_t, int> diff;// state-> diff input/output
181  public :
182  is_synchronizable_impl(Tdc tdc) : tdc_(tdc) {}
183 
184  bool test() {
185  for(auto tr : tdc_->initial_transitions()) {
186  state_t i=tdc_->dst_of(tr);
187  auto it = status.find(i);
188  if(it != status.end())
189  continue;
190  diff[i]=0;
191  if(!test_rec(i))
192  return false;
193  }
194  return true;
195  }
196 
197 
198  bool test_rec(state_t s) {
199  status[s]=1;
200  for(auto tr : tdc_->out(s)) {
201  state_t t=tdc_->dst_of(tr);
202  auto it = status.find(t);
203  if(it != status.end() && it->second == 2) // every state accessible from t is ok
204  continue;
205  int d=diff[s];
206  if(!is_epsilon<labelset0_t>(std::get<0>(tdc_->label_of(tr))))
207  ++d;
208  if(!is_epsilon<labelset1_t>(std::get<1>(tdc_->label_of(tr))))
209  --d;
210  if(it == status.end()) {// t has never been visited
211  diff[t]=d;
212  if(!test_rec(t))
213  return false;
214  }
215  else { // t is already active; it is an ancester of s
216  if(diff[t] != d)
217  return false;
218  }
219  }
220  status[s]=2;
221  return true;
222  }
223  };
224  }
225 
226  template <typename Tdc>
227  Tdc synchronize(const Tdc& tdc, bool keep_history=true) {
228  return internal::synchronizer<Tdc>::algo(tdc, keep_history);
229  }
230 
231  template<typename Tdc>
232  bool is_synchronizable(Tdc tdc) {
234  return algo.test();
235  }
236 
237  }
238 }//end of ns awali::stc
239 
240 #endif
The Boolean semring.
Definition: b.hh:38
The semiring of floating Numbers.
Definition: r.hh:34
std::vector< state_t > states(abstract_automaton_t const *aut, bool all)
void append(std::string &s, char c)
Definition: real_time.hh:35
constant< type_t::one, Label, Weight > one
Definition: fwd.hh:116
Tdc synchronize(const Tdc &tdc, bool keep_history=true)
Definition: synchronize.hh:227
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
mutable_automaton< Context > make_mutable_automaton(const Context &ctx)
Definition: mutable_automaton.hh:911
void proper_here(Aut &aut, direction_t dir=BACKWARD, bool prune=true)
Eliminate spontaneous transitions in place.
Definition: proper.hh:427
bool is_synchronizable(Tdc tdc)
Definition: synchronize.hh:232
Main namespace of Awali.
Definition: ato.hh:22
unsigned state_t
Definition: types.hh:21
Definition: synchronize.hh:173
bool test_rec(state_t s)
Definition: synchronize.hh:198
typename labelset_t::template valueset_t< 0 > labelset0_t
Definition: synchronize.hh:175
typename labelset_t::template valueset_t< 1 > labelset1_t
Definition: synchronize.hh:176
is_synchronizable_impl(Tdc tdc)
Definition: synchronize.hh:182
bool test()
Definition: synchronize.hh:184
labelset_t_of< Tdc > labelset_t
Definition: synchronize.hh:174
static auto get(const Tuple &t) -> type< Tuple >
Definition: sub_tuple.hh:119
Definition: synchronize.hh:46
std::tuple< state_t, wordset0_value_t, wordset1_value_t > triple_t
Definition: synchronize.hh:54
typename labelset_trait< labelset0_t >::wordset_t wordset0_t
Definition: synchronize.hh:50
typename wordset1_t::value_t wordset1_value_t
Definition: synchronize.hh:53
typename labelset_t::template valueset_t< 1 > labelset1_t
Definition: synchronize.hh:49
labelset_t_of< Tdc > labelset_t
Definition: synchronize.hh:47
typename labelset_trait< labelset1_t >::wordset_t wordset1_t
Definition: synchronize.hh:51
typename wordset0_t::value_t wordset0_value_t
Definition: synchronize.hh:52
static Tdc algo(const Tdc &tdc, bool keep_history=true)
Definition: synchronize.hh:56
typename labelset_t::template valueset_t< 0 > labelset0_t
Definition: synchronize.hh:48
L wordset_t
Definition: traits.hh:37