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