00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef VCSN_ALGORITHMS_ISOMORPH_HXX
00018 # define VCSN_ALGORITHMS_ISOMORPH_HXX
00019
00020 # include <vaucanson/algorithms/isomorph.hh>
00021 # include <vaucanson/algorithms/determinize.hh>
00022
00023 # include <vaucanson/automata/concept/automata_base.hh>
00024 # include <vaucanson/tools/usual_macros.hh>
00025
00026 # include <vaucanson/algorithms/internal/skeleton.hh>
00027
00028 # include <queue>
00029 # include <set>
00030 # include <list>
00031 # include <utility>
00032
00033 namespace vcsn {
00034
00035
00036
00037
00038
00039 class Trie
00040 {
00041 public:
00042 Trie* insert(std::vector<int>&);
00043
00044 public:
00045 std::list<int> A, B;
00046
00047
00048 std::list<Trie*>::iterator L;
00049
00050 private:
00051 Trie* insert_suffix(std::vector<int>&, unsigned int);
00052 std::map<int, Trie> children;
00053 };
00054
00055
00056 inline Trie* Trie::insert(std::vector<int>& S)
00057 {
00058 return insert_suffix(S, 0);
00059 }
00060
00061 inline Trie* Trie::insert_suffix(std::vector<int>& S, unsigned int p)
00062 {
00063 if (p == S.capacity() - 1)
00064 return this;
00065
00066 return children[S[p]].insert_suffix(S, p + 1);
00067 }
00068
00069
00070
00071
00072
00073
00074 template<typename A, typename T>
00075 bool
00076 are_isomorphic(const Element<A, T>& a, const Element<A, T>& b)
00077 {
00078 typedef Element<A, T> automaton_t;
00079
00080 AUTOMATON_TYPES(automaton_t);
00081
00082
00083 if ((a.states().size() != b.states().size())
00084 || (a.transitions().size() != b.transitions().size())
00085 || (a.initial().size() != b.initial().size())
00086 || (a.final().size() != b.final().size()))
00087 return false;
00088
00089
00090 int i, j , k, l;
00091 bool iso;
00092 std::list<int>::iterator it_int, it_int_B, it_int_aux;
00093
00094
00095
00096
00097 std::vector<std::list<int>::iterator> T_L_A(a.states().size());
00098
00099
00100 std::vector<std::list<int>::iterator> T_L_B(b.states().size());
00101
00102
00103
00104 Trie *T_Q_IT, *T_I, *T_T, *T_aux;
00105
00106 T_Q_IT = new Trie();
00107 T_I = new Trie();
00108 T_T = new Trie();
00109
00110 std::list<Trie*> C;
00111
00112 std::list<int> U;
00113
00114 std::vector<Trie*> class_state_A(a.states().size());
00115
00116 std::vector<Trie*> class_state_B(b.states().size());
00117
00118
00119
00120
00121 std::vector<int> perm_A(a.states().size());
00122 std::vector<int> perm_B(b.states().size());
00123
00124 Skeleton<A, T> Sa(a);
00125 Skeleton<A, T> Sb(b);
00126
00127
00128 iso = true;
00129
00130
00131
00132
00133
00134 std::vector< std::list<int> > delta_det_in_A(a.states().size());
00135 std::vector< std::list<int> > delta_det_out_A(a.states().size());
00136 std::vector< std::list<int> > delta_det_in_B(b.states().size());
00137 std::vector< std::list<int> > delta_det_out_B(b.states().size());
00138
00139
00140 for (i = 0; i < static_cast<int>(a.states().size()); i++)
00141 {
00142 if ((Sa.delta_in[i]).size() > 0)
00143 {
00144 it_int = Sa.delta_in[i].begin();
00145
00146 j = 1;
00147 for (it_int++; it_int != Sa.delta_in[i].end(); it_int++)
00148 {
00149
00150
00151 k = *(--it_int);
00152 it_int++;
00153
00154 if (Sa.transitions_labels[*it_int] != Sa.transitions_labels[k])
00155
00156 if (j == 1)
00157 delta_det_in_A[i].push_back(k);
00158
00159 else
00160
00161 j = 1;
00162
00163 else
00164 j++;
00165 }
00166
00167 if (j == 1)
00168 {
00169 delta_det_in_A[i].push_back(*(--it_int));
00170 it_int++;
00171 }
00172 }
00173 if ((Sa.delta_out[i]).size() > 0)
00174 {
00175 it_int = Sa.delta_out[i].begin();
00176
00177 j = 1;
00178 for (it_int++; it_int != Sa.delta_out[i].end(); it_int++)
00179 {
00180
00181
00182 k = *(--it_int);
00183 it_int++;
00184
00185 if (Sa.transitions_labels[*it_int] != Sa.transitions_labels[k])
00186
00187 if (j == 1)
00188 delta_det_out_A[i].push_back(k);
00189
00190 else
00191
00192 j = 1;
00193
00194 else
00195 j++;
00196 }
00197
00198 if (j == 1)
00199 {
00200 delta_det_out_A[i].push_back(*(--it_int));
00201 ++it_int;
00202 }
00203 }
00204 }
00205
00206
00207 for (i = 0; i < static_cast<int>(a.states().size()); i++)
00208 {
00209 if ((Sb.delta_in[i]).size() > 0)
00210 {
00211 it_int = Sb.delta_in[i].begin();
00212
00213 j = 1;
00214 for (it_int++; it_int != Sb.delta_in[i].end(); it_int++)
00215 {
00216
00217
00218 k = *(--it_int);
00219 it_int++;
00220
00221 if (Sb.transitions_labels[*it_int] != Sb.transitions_labels[k])
00222
00223 if (j == 1)
00224 delta_det_in_B[i].push_back(k);
00225
00226 else
00227
00228 j = 1;
00229
00230 else
00231 j++;
00232 }
00233
00234 if (j == 1)
00235 {
00236 delta_det_in_B[i].push_back(*(--it_int));
00237 ++it_int;
00238 }
00239 }
00240 if ((Sb.delta_out[i]).size() > 0)
00241 {
00242 it_int = Sb.delta_out[i].begin();
00243
00244 j = 1;
00245 for (it_int++; it_int != Sb.delta_out[i].end(); it_int++)
00246 {
00247
00248
00249 k = *(--it_int);
00250 it_int++;
00251
00252 if (Sb.transitions_labels[*it_int] != Sb.transitions_labels[k])
00253
00254 if (j == 1)
00255 delta_det_out_B[i].push_back(k);
00256
00257 else
00258
00259 j = 1;
00260
00261 else
00262 j++;
00263 }
00264
00265 if (j == 1)
00266 {
00267 delta_det_out_B[i].push_back(*(--it_int));
00268 it_int++;
00269 }
00270 }
00271 }
00272
00273
00274
00275 for (i = 0; i < static_cast<int>(a.states().size()); i++)
00276 {
00277
00278
00279
00280 std::vector<int> all_transitions_lex((Sa.delta_in[i]).size() +
00281 (Sa.delta_out[i]).size() + 1);
00282
00283
00284 for (it_int = Sa.delta_in[i].begin();
00285 it_int != Sa.delta_in[i].end(); ++it_int)
00286 all_transitions_lex.push_back(Sa.transitions_labels[*it_int]);
00287
00288 all_transitions_lex.push_back(-1);
00289
00290 for (it_int = Sa.delta_out[i].begin();
00291 it_int != Sa.delta_out[i].end(); ++it_int)
00292 all_transitions_lex.push_back(Sa.transitions_labels[*it_int]);
00293
00294
00295
00296 if (a.is_initial(Sa.states[i]))
00297 T_aux = T_I->insert(all_transitions_lex);
00298 else
00299 if (a.is_final(Sa.states[i]))
00300 T_aux = T_T->insert(all_transitions_lex);
00301 else
00302 T_aux = T_Q_IT->insert(all_transitions_lex);
00303
00304
00305 if ((T_aux->A).size() == 0)
00306 {
00307
00308 C.push_front(T_aux);
00309
00310
00311 T_aux->L = C.begin();
00312 }
00313
00314
00315 (T_aux->A).push_front(i);
00316
00317 class_state_A[i] = T_aux;
00318
00319 T_L_A[i] = (T_aux->A).begin();
00320 }
00321
00322
00323
00324
00325 for (i = 0; (i < static_cast<int>(b.states().size())) && iso; i++)
00326 {
00327
00328
00329
00330 std::vector<int> all_transitions_lex((Sb.delta_in[i]).size() +
00331 (Sb.delta_out[i]).size() + 1);
00332
00333 for (it_int = Sb.delta_in[i].begin();
00334 it_int != Sb.delta_in[i].end(); ++it_int)
00335 all_transitions_lex.push_back(Sb.transitions_labels[*it_int]);
00336
00337 all_transitions_lex.push_back(-1);
00338
00339 for (it_int = Sb.delta_out[i].begin();
00340 it_int != Sb.delta_out[i].end(); ++it_int)
00341 all_transitions_lex.push_back(Sb.transitions_labels[*it_int]);
00342
00343
00344
00345 if (b.is_initial(Sa.states[i]))
00346 T_aux = T_I->insert(all_transitions_lex);
00347 else
00348 if (b.is_final(Sa.states[i]))
00349 T_aux = T_T->insert(all_transitions_lex);
00350 else
00351 T_aux = T_Q_IT->insert(all_transitions_lex);
00352
00353
00354
00355 if ((T_aux->A).size() == (T_aux->B).size())
00356 iso = false;
00357 else
00358 {
00359
00360 (T_aux->B).push_front(i);
00361
00362 class_state_B[i] = T_aux;
00363
00364 T_L_B[i] = (T_aux->B).begin();
00365 }
00366 }
00367
00368
00369 if (!iso)
00370 return false;
00371
00372 for (i = 0; i < static_cast<int>(a.states().size()); i++)
00373 perm_A[i] = perm_B[i] = -1;
00374
00375
00376
00377
00378
00379
00380
00381
00382 std::list<Trie*>::iterator itr_C;
00383
00384 itr_C = C.begin();
00385
00386 while ((itr_C != C.end()) && iso)
00387 {
00388
00389
00390 if (((*itr_C)->A).size() != ((*itr_C)->B).size())
00391 {
00392 iso = false;
00393 itr_C++;
00394 }
00395 else
00396
00397 if (((*itr_C)->A).size() == 1)
00398 {
00399
00400
00401 U.push_front(k = (*(((*itr_C)->A).begin())));
00402 perm_A[k] = l = *(((*itr_C)->B).begin());
00403 perm_B[l] = k;
00404
00405
00406 ((*itr_C)->A).erase(((*itr_C)->A).begin());
00407 ((*itr_C)->B).erase(((*itr_C)->B).begin());
00408
00409 itr_C = C.erase(itr_C);
00410 }
00411 else
00412 itr_C++;
00413 }
00414
00415
00416 if (!iso)
00417 return false;
00418
00419
00420
00421
00422
00423
00424 while (!U.empty() && iso)
00425 {
00426
00427
00428
00429
00430 j = perm_A[i = U.front()];
00431 U.pop_front();
00432
00433
00434
00435
00436
00437
00438
00439
00440 it_int = delta_det_in_A[i].begin();
00441 it_int_aux = delta_det_in_B[j].begin();
00442 for (; it_int != delta_det_in_A[i].end() and iso; ++it_int, ++it_int_aux)
00443 {
00444
00445
00446
00447 k = Sa.origins_transitions[*it_int];
00448 l = Sb.origins_transitions[*it_int_aux];
00449
00450
00451 if (perm_A[k] >= 0)
00452 {
00453
00454
00455 if (perm_A[k] != l)
00456 iso = false;
00457 }
00458 else
00459
00460
00461 if (perm_B[l] != -1)
00462 iso = false;
00463
00464 else
00465
00466 if (class_state_A[k] != class_state_B[l])
00467 iso = false;
00468
00469
00470 else
00471 {
00472 perm_A[perm_B[l] = k] = l;
00473
00474
00475 (class_state_A[k]->A).erase(T_L_A[k]);
00476 (class_state_B[l]->B).erase(T_L_B[l]);
00477 U.push_front(k);
00478 if ((class_state_A[k]->A).size() == 1)
00479 {
00480
00481
00482
00483
00484
00485
00486
00487 T_aux = class_state_A[k];
00488 k = (T_aux->A).front();
00489 l = (T_aux->B).front();
00490 perm_A[perm_B[l] = k] = l;
00491
00492 U.push_front(k);
00493
00494
00495 C.erase(T_aux->L);
00496
00497 }
00498 }
00499 }
00500
00501
00502
00503 it_int = delta_det_out_A[i].begin();
00504 it_int_aux = delta_det_out_B[j].begin();
00505 for (; it_int != delta_det_out_A[i].end() && iso; ++it_int, ++it_int_aux)
00506 {
00507
00508
00509
00510 k = Sa.aims_transitions[*it_int];
00511 l = Sb.aims_transitions[*it_int_aux];
00512
00513
00514 if (perm_A[k] >= 0)
00515 {
00516
00517
00518 if (perm_A[k] != l)
00519 iso = false;
00520 }
00521 else
00522
00523 if (perm_B[l] != -1)
00524 iso = false;
00525
00526 else
00527
00528 if (class_state_A[k] != class_state_B[l])
00529 iso = false;
00530
00531 else
00532 {
00533 perm_A[perm_B[l] = k] = l;
00534
00535
00536 (class_state_A[k]->A).erase(T_L_A[k]);
00537 (class_state_B[l]->B).erase(T_L_B[l]);
00538 U.push_front(k);
00539
00540 if ((class_state_A[k]->A).size() == 1)
00541 {
00542
00543
00544
00545
00546
00547
00548
00549 T_aux = class_state_A[k];
00550 k = (T_aux->A).front();
00551 l = (T_aux->B).front();
00552 perm_A[perm_B[l] = k] = l;
00553
00554 U.push_front(k);
00555
00556
00557 C.erase(T_aux->L);
00558
00559 }
00560 }
00561 }
00562
00563 }
00564
00565
00566 if (!iso)
00567 return false;
00568
00569
00570
00571
00572
00573
00574 l = 0;
00575 for (itr_C = C.begin(); itr_C != C.end(); ++itr_C)
00576 l += (*itr_C)->A.size();
00577
00578
00579
00580
00581
00582
00583 std::vector<int> C_A(l);
00584 std::vector<int> C_B(l + 2 * C.size());
00585
00586
00587 std::vector<int> current(l);
00588
00589
00590
00591
00592 std::vector<int> correspondence_transitions(a.states().size());
00593
00594 for (i = 0; i < static_cast<int>(a.states().size()); ++i)
00595 correspondence_transitions[i] = 0;
00596
00597
00598
00599
00600 i = j = 0;
00601 for (itr_C = C.begin(); itr_C != C.end(); itr_C++)
00602 {
00603 it_int = ((*itr_C)->A).begin();
00604 it_int_B = ((*itr_C)->B).begin();
00605 C_A[i] = *it_int;
00606 C_B[j] = *it_int_B;
00607 current[i++] = j++;
00608 for (it_int++, it_int_B++; it_int != ((*itr_C)->A).end();
00609 it_int++, it_int_B++)
00610 {
00611 C_A[i] = *it_int;
00612 C_B[j++] = *it_int_B;
00613 current[i] = current[i - 1];
00614 i++;
00615 }
00616
00617 C_B[j++] = -1;
00618
00619 C_B[j++] = current[i - 1];
00620 }
00621
00622
00623
00624 i = 0;
00625
00626
00627
00628 while (iso && (i < static_cast<int>(C_A.size())))
00629 {
00630
00631 for (j = current[i]; (C_B[j] != -1) && (perm_B[C_B[j]] >= 0); j++)
00632 ;
00633
00634
00635 if (C_B[j] == -1)
00636 {
00637
00638
00639 if (i == 0)
00640 iso = false;
00641 else
00642 {
00643
00644
00645 current[i] = C_B[j + 1];
00646
00647
00648 i--;
00649 perm_B[perm_A[C_A[i]]] = -1;
00650 perm_A[C_A[i]] = -1;
00651 current[i]++;
00652 }
00653 }
00654
00655 else
00656 {
00657
00658 current[i] = j;
00659 perm_A[C_A[i]] = C_B[j];
00660 perm_B[C_B[j]] = C_A[i];
00661
00662
00663
00664
00665 std::list<int>::iterator int_itr_B;
00666
00667 it_int = Sa.delta_in[C_A[i]].begin();
00668 it_int_B = Sb.delta_in[C_B[j]].begin();
00669 bool b = true;
00670
00671
00672
00673 while ((it_int != Sa.delta_in[C_A[i]].end()) && b)
00674 {
00675
00676
00677
00678
00679 k = 0;
00680 for (it_int_aux = it_int;
00681 (it_int_aux != Sa.delta_in[C_A[i]].end()) &&
00682 (Sa.transitions_labels[*it_int_aux] ==
00683 Sa.transitions_labels[*it_int]);
00684 it_int_aux++, k++)
00685
00686 if (perm_A[Sa.origins_transitions[*it_int_aux]] >= 0)
00687 correspondence_transitions[Sa.origins_transitions[*it_int_aux]]++;
00688
00689
00690
00691
00692
00693 for (; (k > 0) && b; it_int_B++, k--)
00694
00695 if (perm_B[Sb.origins_transitions[*it_int_B]] >= 0)
00696
00697
00698 if (correspondence_transitions[perm_B[Sb.origins_transitions[*it_int_B]]] == 0)
00699
00700 b = false;
00701 else
00702 correspondence_transitions[perm_B[Sb.origins_transitions[*it_int_B]]]--;
00703
00704
00705
00706
00707
00708
00709
00710 for (; it_int != it_int_aux; it_int++)
00711 {
00712 if (perm_A[Sa.origins_transitions[*it_int]] >= 0)
00713 if (correspondence_transitions[Sa.origins_transitions[*it_int]] != 0)
00714 b = false;
00715
00716 correspondence_transitions[Sa.origins_transitions[*it_int]] = 0;
00717 }
00718
00719 }
00720
00721
00722 if (b)
00723 {
00724
00725
00726
00727 std::list<int>::iterator int_itr_B;
00728
00729 it_int = Sa.delta_out[C_A[i]].begin();
00730 it_int_B = Sb.delta_out[C_B[j]].begin();
00731
00732
00733
00734 while ((it_int != Sa.delta_out[C_A[i]].end()) && b)
00735 {
00736
00737
00738
00739
00740 k = 0;
00741 for (it_int_aux = it_int;
00742 (it_int_aux != Sa.delta_out[C_A[i]].end()) &&
00743 (Sa.transitions_labels[*it_int_aux] ==
00744 Sa.transitions_labels[*it_int]);
00745 it_int_aux++, k++)
00746
00747 if (perm_A[Sa.aims_transitions[*it_int_aux]] >= 0)
00748 correspondence_transitions[Sa.aims_transitions[*it_int_aux]]++;
00749
00750
00751
00752
00753
00754 for (; (k > 0) && b; it_int_B++, k--)
00755
00756 if (perm_B[Sb.aims_transitions[*it_int_B]] >= 0)
00757
00758
00759 if (correspondence_transitions[perm_B[Sb.aims_transitions[*it_int_B]]] == 0)
00760
00761
00762 b = false;
00763 else
00764 correspondence_transitions[perm_B[Sb.aims_transitions[*it_int_B]]]--;
00765
00766
00767
00768
00769
00770
00771
00772
00773 for (; it_int != it_int_aux; it_int++)
00774 {
00775 if (perm_A[Sa.aims_transitions[*it_int]] >= 0)
00776 if (correspondence_transitions[Sa.aims_transitions[*it_int]] != 0)
00777 b = false;
00778
00779 correspondence_transitions[Sa.aims_transitions[*it_int]] = 0;
00780 }
00781
00782 }
00783
00784 }
00785
00786
00787 if (b)
00788
00789 i++;
00790
00791 else
00792 {
00793
00794 perm_B[perm_A[C_A[i]]] = -1;
00795 perm_A[C_A[i]] = -1;
00796 current[i]++;
00797 }
00798
00799 }
00800
00801 }
00802
00803 return (iso);
00804
00805 }
00806
00807 }
00808
00809 #endif // ! VCSN_ALGORITHMS_ISOMORPH_HXX