17 #ifndef VCSN_ALGORITHMS_ISOMORPH_HXX
18 # define VCSN_ALGORITHMS_ISOMORPH_HXX
23 # include <vaucanson/automata/concept/automata_base.hh>
24 # include <vaucanson/misc/usual_macros.hh>
47 Trie* insert(std::vector<int>&);
53 std::list<Trie*>::iterator L;
58 Trie* insert_suffix(std::vector<int>&,
unsigned int);
59 std::map<int, Trie> children;
64 : A(), B(), L(), L_is_valid(false), children()
69 Trie::Trie (
const Trie& t)
71 L(), L_is_valid(t.L_is_valid), children(t.children)
79 inline Trie* Trie::insert(std::vector<int>& S)
81 return insert_suffix(S, 0);
84 inline Trie* Trie::insert_suffix(std::vector<int>& S,
unsigned int p)
86 if (p == S.capacity() - 1)
89 return children[S[p]].insert_suffix(S, p + 1);
98 template<
typename A,
typename T>
103 typedef Element<A, T> auto_t;
104 AUTOMATON_TYPES(auto_t);
106 typedef std::vector<int> trans_t;
107 typedef std::list<int> state_list_t;
108 typedef std::vector<state_list_t> delta_t;
110 struct automaton_vars
114 automaton_vars(
const automaton_t& aut)
117 perm(aut.states().size(), -1),
118 T_L(aut.states().size(), state_list_t().end()),
119 delta_det_in(aut.states().size()),
120 delta_det_out(aut.states().size()),
121 class_state(aut.states().size())
129 delta_det_in.clear();
130 delta_det_out.clear();
137 const automaton_t aut;
147 std::vector<state_list_t::iterator> T_L;
152 delta_t delta_det_in;
153 delta_t delta_det_out;
156 std::vector<Trie*> class_state;
159 Isomorpher(
const automaton_t& a,
const automaton_t& b)
167 if (fails_on_quick_tests())
170 list_in_out_det_trans(a_);
171 list_in_out_det_trans(b_);
173 if (!construct_tries())
179 if (!analyse_det_trans())
185 return backtracking();
195 fails_on_quick_tests()
197 return a_.aut.states().size() != b_.aut.states().size()
198 || a_.aut.transitions().size() != b_.aut.transitions().size()
199 || a_.aut.initial().size() != b_.aut.initial().size()
200 || a_.aut.final().size() != b_.aut.final().size();
210 list_in_out_det_trans(automaton_vars& av)
212 for (
int i = 0; i < static_cast<int>(av.aut.states().size()); i++)
214 if (av.s.delta_in[i].size() > 0)
215 list_det_trans(av, av.delta_det_in, av.s.delta_in, i);
217 if (av.s.delta_out[i].size() > 0)
218 list_det_trans(av, av.delta_det_out, av.s.delta_out, i);
234 for (
int i = 0; i < static_cast<int>(a_.aut.states().size()); i++)
236 Trie *T_aux = add_all_transitions_to_trie(a_, i);
239 if (T_aux->A.size() == 0)
242 C_.push_front(T_aux);
245 T_aux->L = C_.begin();
249 T_aux->A.push_front(i);
251 a_.class_state[i] = T_aux;
253 a_.T_L[i] = T_aux->A.begin();
258 for (
int i = 0; i < static_cast<int>(b_.aut.states().size()); i++)
260 Trie *T_aux = add_all_transitions_to_trie(b_, i);
264 if (T_aux->A.size() == T_aux->B.size())
268 T_aux->B.push_front(i);
270 b_.class_state[i] = T_aux;
272 b_.T_L[i] = T_aux->B.begin();
290 construct_list_of_classes_with_one_state(std::list<int>& U)
292 std::list<Trie*>::iterator itr_C = C_.begin();
294 while (itr_C != C_.end())
298 if ((*itr_C)->A.size() != (*itr_C)->B.size())
302 if ((*itr_C)->A.size() == 1)
306 int k = *((*itr_C)->A.begin());
308 int l = *((*itr_C)->B.begin());
313 ((*itr_C)->A).erase((*itr_C)->A.begin());
314 ((*itr_C)->B).erase((*itr_C)->B.begin());
316 itr_C = C_.erase(itr_C);
334 list_det_trans(automaton_vars& av,
336 const delta_t& delta_in_or_out,
339 state_list_t::const_iterator it = delta_in_or_out[i].begin();
343 for (it++; it != delta_in_or_out[i].end(); it++)
350 if (av.s.transitions_labels[*it] != av.s.transitions_labels[k])
353 delta_det[i].push_back(k);
365 delta_det[i].push_back(*(--it));
378 add_all_transitions_to_trie(
const automaton_vars& av,
384 trans_t all_transitions_lex(av.s.delta_in[i].size() +
385 av.s.delta_out[i].size() + 1);
388 for (state_list_t::const_iterator it = av.s.delta_in[i].begin();
389 it != av.s.delta_in[i].end(); ++it)
390 all_transitions_lex.push_back(av.s.transitions_labels[*it]);
392 all_transitions_lex.push_back(-1);
395 for (state_list_t::const_iterator it = av.s.delta_out[i].begin();
396 it != av.s.delta_out[i].end(); ++it)
397 all_transitions_lex.push_back(av.s.transitions_labels[*it]);
401 if (av.aut.is_initial(av.s.states[i]))
402 return T_I_.insert(all_transitions_lex);
403 if (av.aut.is_final(av.s.states[i]))
404 return T_T_.insert(all_transitions_lex);
406 return T_Q_IT_.insert(all_transitions_lex);
424 if (!construct_list_of_classes_with_one_state(U))
427 for (; !U.empty(); U.pop_front())
428 if (!do_analyse_det_trans(U,
431 a_.s.src_transitions,
432 b_.s.src_transitions)
433 || !do_analyse_det_trans(U,
436 a_.s.dst_transitions,
437 b_.s.dst_transitions))
445 do_analyse_det_trans(std::list<int>& U,
446 const delta_t& delta_det_A,
447 const delta_t& delta_det_B,
448 const trans_t& transitions_A,
449 const trans_t& transitions_B)
461 state_list_t::const_iterator it = delta_det_A[i].begin();
462 state_list_t::const_iterator it_aux = delta_det_B[j].begin();
463 for (; it != delta_det_A[i].end(); ++it, ++it_aux)
468 int k = transitions_A[*it];
469 int l = transitions_B[*it_aux];
483 if (b_.perm[l] != -1)
488 if (a_.class_state[k] != b_.class_state[l])
492 a_.perm[b_.perm[l] = k] = l;
495 a_.class_state[k]->A.erase(a_.T_L[k]);
496 b_.class_state[l]->B.erase(b_.T_L[l]);
498 if (a_.class_state[k]->A.size() == 1)
506 Trie* T_aux = a_.class_state[k];
507 k = T_aux->A.front();
508 l = T_aux->B.front();
509 a_.perm[b_.perm[l] = k] = l;
531 for (std::list<Trie*>::iterator it = C_.begin();
532 it != C_.end(); ++it)
533 l += (*it)->A.size();
541 trans_t C_B(l + 2 * C_.size());
549 trans_t correspondence_transitions(a_.aut.states().size(), 0);
551 list_remaining(C_A, C_B, current);
560 while (i < static_cast<int>(C_A.size()))
564 for (j = current[i]; C_B[j] != -1 && b_.perm[C_B[j]] >= 0; j++)
578 current[i] = C_B[j + 1];
582 b_.perm[a_.perm[C_A[i]]] = -1;
583 a_.perm[C_A[i]] = -1;
591 a_.perm[C_A[i]] = C_B[j];
592 b_.perm[C_B[j]] = C_A[i];
594 rvalue = (test_correspondence(a_.s.delta_in, b_.s.delta_in,
595 a_.s.src_transitions,
596 b_.s.src_transitions,
598 correspondence_transitions)
599 && test_correspondence(a_.s.delta_out, b_.s.delta_out,
600 a_.s.dst_transitions,
601 b_.s.dst_transitions,
603 correspondence_transitions));
613 b_.perm[a_.perm[C_A[i]]] = -1;
614 a_.perm[C_A[i]] = -1;
628 list_remaining(trans_t& C_A,
633 for (std::list<Trie*>::iterator it = C_.begin(); it != C_.end();
636 state_list_t::iterator it_A = (*it)->A.begin();
637 state_list_t::iterator it_B = (*it)->B.begin();
641 for (it_A++, it_B++; it_A != (*it)->A.end();
646 current[i] = current[i - 1];
652 C_B[j++] = current[i - 1];
661 test_correspondence(
const delta_t& delta_A,
662 const delta_t& delta_B,
663 const trans_t& transitions_A,
664 const trans_t& transitions_B,
669 trans_t& correspondence_transitions)
671 state_list_t::const_iterator it_A = delta_A[C_A[i]].begin();
672 state_list_t::const_iterator it_B = delta_B[C_B[j]].begin();
676 while (it_A != delta_A[C_A[i]].end())
683 state_list_t::const_iterator it_aux;
685 (it_aux != delta_A[C_A[i]].end()) &&
686 (a_.s.transitions_labels[*it_aux] ==
687 a_.s.transitions_labels[*it_A]);
690 if (a_.perm[transitions_A[*it_aux]] >= 0)
691 correspondence_transitions[transitions_A[*it_aux]]++;
697 for (; (k > 0); it_B++, k--)
699 if (b_.perm[transitions_B[*it_B]] >= 0)
703 if (correspondence_transitions[b_.perm[transitions_B[*it_B]]]
708 correspondence_transitions[b_.perm[transitions_B[*it_B]]]--;
717 for (; it_A != it_aux; it_A++)
719 if (a_.perm[transitions_A[*it_A]] >= 0)
720 if (correspondence_transitions[transitions_A[*it_A]] != 0)
723 correspondence_transitions[transitions_A[*it_A]] = 0;
747 template<
typename A,
typename T>
751 BENCH_TASK_SCOPED(
"are_isomorphic");
753 Isomorpher<A, T> isomorpher(a, b);
760 #endif // ! VCSN_ALGORITHMS_ISOMORPH_HXX