Ticket #13744: 13744_rebased.patch
File 13744_rebased.patch, 35.4 KB (added by , 8 years ago) |
---|
-
sage/graphs/graph.py
# HG changeset patch # User Jeroen Demeyer <jdemeyer@cage.ugent.be> # Date 1358416461 -3600 # Node ID cb7d2191b5c56b89609eb5687573d363be2e3397 # Parent e610e237c6fd5cd0469a8428b99e27d16f1c56f7 Bug in modular_decomposition diff --git a/sage/graphs/graph.py b/sage/graphs/graph.py
a b 5309 5309 5310 5310 - :meth:`is_prime` -- Tests whether a graph is prime. 5311 5311 5312 TESTS: 5313 5314 :trac:`13744`:: 5315 5316 sage: P = Graph('Dl_') 5317 sage: P.is_prime() 5318 False 5319 5312 5320 REFERENCE: 5313 5321 5314 5322 .. [FMDec] Fabien de Montgolfier -
sage/graphs/modular_decomposition/src/dm.c
diff --git a/sage/graphs/modular_decomposition/src/dm.c b/sage/graphs/modular_decomposition/src/dm.c
a b 30 30 (pour cette notion, cf these de Christian Capelle) 31 31 grace a une technique d'affinage de partitions (cf Habib, Paul & Viennot) 32 32 Le second construit l'arbre de decomposition modulaire a partir de cette 33 permutation, cf mon memoire de DEA 34 Montpellier, decembre 2000 33 permutation, cf 34 [Anne Bergeron, Cedric Chauve, Fabien de Montgolfier, Mathieu Raffinot, 35 Computing Common Intervals of K Permutations, with Applications to Modular 36 Decomposition of Graphs. SIAM J. Discrete Math. 22(3): 1022-1039 (2008)] 37 38 Montpellier, decembre 2000 et Paris, novembre 2010 35 39 ********************************************************/ 36 40 37 41 //#include "dm_english.h" 38 42 #include <stdio.h> 39 43 #include <stdlib.h> 40 44 41 #define DEBUG 0 45 #define DEBUG 0 /* si 0 aucune sortie graphique!! */ 42 46 43 47 /* dm.h definit les constantes FEUILLE, MODULE, etc... 44 48 ainsi que les structures noeud et fils. Les autres … … 139 143 for (s = S[0]->classe; s != NULL; s = s->suiv) { 140 144 printf("[ "); 141 145 for (i = s->debut; i <= s->fin; i++) 142 printf("%i ", 1 +S[i]->nom);146 printf("%i ", S[i]->nom); 143 147 printf("] "); 144 148 } 145 149 printf("\n"); … … 192 196 int *ipivot, *imodule, *numclasse, n; 193 197 194 198 if (DEBUG) 195 printf("Raffinage avec le pivot %i\n", 1 +p->nom);199 printf("Raffinage avec le pivot %i\n", p->nom); 196 200 pivot = I->pivot; 197 201 module = I->module; 198 202 ipivot = I->ipivot; … … 302 306 X->inmodule = -1; 303 307 if (DEBUG) 304 308 printf("Dans module %i-%i ecrase %i-%i\n", 305 1 + S[Xa->debut]->nom, 1 +S[Xa->fin]->nom,306 1 + S[X->debut]->nom, 1 +S[X->fin]->nom);309 S[Xa->debut]->nom, S[Xa->fin]->nom, 310 S[X->debut]->nom, S[X->fin]->nom); 307 311 } 308 312 else { 309 313 if (X->inmodule == -1) { … … 317 321 (*imodule)++; 318 322 if (DEBUG) 319 323 printf("module empile:%i-%i\n", 320 1 + S[Z->debut]->nom, 1 +S[Z->fin]->nom);324 S[Z->debut]->nom, S[Z->fin]->nom); 321 325 } 322 326 } 323 327 } … … 333 337 Z->inpivot = (*ipivot); 334 338 (*ipivot)++; 335 339 if (DEBUG) 336 printf("pivot empile: %i-%i\n", 1 +S[Z->debut]->nom,337 1 +S[Z->fin]->nom);340 printf("pivot empile: %i-%i\n", S[Z->debut]->nom, 341 S[Z->fin]->nom); 338 342 X->whereXa = 0; 339 343 Xa->whereXa = 0; 340 344 } … … 366 370 sclasse *C1; /*premiere classe, tete de la chaine */ 367 371 sclasse *Y; /*classe qui raffine */ 368 372 sclasse *X; /*classe raffinee */ 369 sclasse *Xa, *Xc; /* morceaux de X */ 373 sclasse *Xc; /* morceau utilise de X */ 374 /* sclasse *Xa, *Xc; morceau inutilise de X */ 370 375 sommet *x; /* x in X */ 371 376 sommet *y; /* y in Y */ 372 377 sommet *centre; /* le centre du raffinage actuel */ … … 461 466 Y->firstpivot = y; /* le premier!! */ 462 467 if (DEBUG) 463 468 printf("module-pivot %i-%i: sommet %i\n", 464 1 + S[Y->debut]->nom, 1 +S[Y->fin]->nom,465 1 +y->nom);469 S[Y->debut]->nom, S[Y->fin]->nom, 470 y->nom); 466 471 Raffiner(S, y, centre, &Inf); 467 472 } 468 473 } … … 498 503 499 504 if (DEBUG) 500 505 printf("Relance dans le module %i-%i avec le sommet %i\n", 501 1 + S[X->debut]->nom, 1 + S[X->fin]->nom, 1 +x->nom);506 S[X->debut]->nom, S[X->fin]->nom, x->nom); 502 507 503 508 centre = x; /*important! */ 504 509 /* astuce: on place {x} en tete de X … … 537 542 if (DEBUG) 538 543 printS(S, n); 539 544 } 545 free(module); 546 free(pivot); 540 547 } 541 548 542 549 /*************************************************************** … … 656 663 etablir l'arbre de decomposition modulaire. 657 664 Tous les details sont dans mon memoire de DEA 658 665 ****************************************************************/ 659 noeud *nouvnoeud(int type, noeud * pere, int sommet, int n)666 noeud *nouvnoeud(int type, noeud * pere, int sommet, int fv, int lv) 660 667 { 661 668 /* cree un nouveau noeud. Noter que l'on est oblige de passer n 662 669 comme parametre car les bords et separateurs droits doivent … … 669 676 nn->type = type; 670 677 nn->pere = pere; 671 678 /* nn->fpere ne peut etre deja mis a jour... */ 672 nn->sommet = sommet; 673 nn->ps = n + 2; 674 nn->ds = -2; 675 /*ces valeurs pour distinguer "non calcule" (-2) */ 676 /* de "abscence de separateur" (-1). De plus, on fera des min et des */ 677 /* max sur les bords */ 678 nn->bg = n + 2; 679 nn->bd = -2; /* idem */ 680 679 nn->nom = sommet; 680 nn->fv=fv; 681 nn->lv=lv; 681 682 nn->fils = NULL; 682 683 nn->lastfils = NULL; 683 684 nn->id = compteur; … … 701 702 nfils->fpere = nf; 702 703 } 703 704 704 void fusionne(noeud * pere, noeud * artefact)705 {706 /*fusionne un artefact a son pere.707 utilise le champ fpere qui permet de savoir ou se greffer708 une structure fils sera detruite dans l'operation: artefact->fils */709 fils *greffe;710 fils *f;711 /* met a jour la liste des peres */712 f = artefact->fils;713 while (f != NULL) {714 f->pointe->pere = pere; /*avant c'etait ancien... */715 /* f->pointe->fpere est inchange */716 f = f->suiv;717 }718 /* greffe la liste */719 greffe = artefact->fpere;720 artefact->lastfils->suiv = greffe->suiv;721 greffe->pointe = artefact->fils->pointe;722 greffe->suiv = artefact->fils->suiv;723 artefact->fils->pointe->fpere = greffe; /*artefact->fils a disparu */724 if (pere->lastfils == greffe)725 pere->lastfils = artefact->lastfils;726 }727 728 void729 extraire(noeud * ancien, noeud * nouveau, fils * premier, fils * dernier)730 {731 /* extrait la liste [premier...dernier] des fils de l'ancien noeud,732 et en fait la liste des fils du nouveau noeud */733 fils *nf; /* il faut une structure fils de plus */734 fils *f; /*indice de mise a jour */735 nf = (fils *) fabmalloc(sizeof(fils));736 nf->pointe = premier->pointe;737 nf->suiv = premier->suiv;738 premier->pointe->fpere = nf;739 nouveau->pere = ancien;740 nouveau->fils = nf;741 nouveau->lastfils = dernier;742 nouveau->bg = premier->pointe->bg;743 nouveau->bd = dernier->pointe->bd;744 nouveau->ps = premier->pointe->bg; /* nouveau est suppose etre un */745 nouveau->ds = dernier->pointe->bd; /* module, donc bords=separateurs! */746 if (ancien->lastfils == dernier)747 ancien->lastfils = premier;748 /* ecrase l'ancier premier */749 nouveau->fpere = premier;750 premier->pointe = nouveau;751 premier->suiv = dernier->suiv;752 /* met a jour dernier */753 dernier->suiv = NULL;754 /* met a jour la liste des peres */755 f = nf;756 while (f != dernier->suiv) {757 f->pointe->pere = nouveau; /*avant c'etait ancien... */758 f->pointe->fpere = premier;759 f = f->suiv;760 }761 }762 763 705 void printnoeud(noeud * N, int level) 764 706 { 765 707 /* imprime recursivement l'arbre par parcours en profondeur */ … … 801 743 for (i = 0; i < level; i++) 802 744 printf(" |"); 803 745 printf(" +--"); 804 printf("%i\n", 1 +nfils->nom);746 printf("%i\n", nfils->nom); 805 747 } 806 748 else { 807 749 printnoeud(nfils, level + 1); … … 816 758 printnoeud(N, 0); 817 759 } 818 760 761 762 void typenoeud(noeud * N, int *L2, int *R2, sommet **S) 763 { 764 // type recursivement l'arbre 765 if(N->type == FEUILLE) 766 return; 767 else if (N->type != UNKN) 768 { 769 printf("Erreur typage!\n"); 770 return; 771 } 772 // maintenant N est supposé avoir deux fils 773 noeud *premier, *second; 774 premier = N->fils->pointe; 775 if(premier==NULL) 776 { 777 printf("Erreur typage!\n"); 778 return; 779 } 780 second = N->fils->suiv->pointe; 781 if(second==NULL) 782 { 783 printf("Erreur typage!\n"); 784 return; 785 } 786 787 sadj *a1; 788 int i = premier->fv; 789 int j = second->lv; 790 if(L2[j]<=i && j<= R2[i]) 791 // ah ah les deux premiers fils forment un module 792 // on recherche si adjacents 793 { 794 N->type = PARALLELE; // sera modifie si adjacence 795 a1=S[i]->adj; 796 while(a1!=NULL) 797 { 798 if(a1->pointe->place == S[j]->place) 799 // adjacence trouvee ! 800 { 801 N->type = SERIE; 802 break; 803 } 804 a1=a1->suiv; 805 } 806 } 807 else 808 N->type = PREMIER; 809 810 fils *ffils; 811 ffils = N->fils; 812 do { 813 typenoeud( ffils -> pointe, L2, R2, S); 814 ffils = ffils->suiv; 815 } 816 while (ffils != NULL); 817 } 818 819 819 820 noeud *algo2(graphe G, sommet **S) 820 821 { 821 822 /* algorithme de decomposition modulaire, deuxieme passe … … 824 825 */ 825 826 /* debug: S n'est utilise que pour mettre vrainom a jour */ 826 827 int n; //nombre de sommets du graphe 827 int *ouvrantes; /* tableau du nombre de parentheses ouvrantes */828 /* ouvrante[i]=3 ssi i-1(((i */829 /* ouvrante [0]=3: (((0 */830 828 831 int *fermantes; /* idem fermantes[i]=2 ssi i)))i+1832 fermante [n-1]=2 ssi n))) */833 829 int *ps; /* ps[i]=premier separateur de (i,i+1) */ 834 830 int *ds; 835 831 … … 837 833 838 834 sadj *a1, *a2; /* parcours de liste d'adjacence */ 839 835 840 noeud *racine; /*racine du pseudocoardre */841 noeud *courant, *nouveau; /* noeud courant du pseudocoarbre */842 noeud **pileinterne; /* pile des modules pour les passes 3,5,5 */843 int indicepileinterne = 0; /*pointeur dans cette pile */844 int taillepileinterne; /* taille de la pile apres la 2eme passe */845 836 846 int *adjii; /* adjii[i]=1 ssi S[i] et S[i+1] sont */ 847 /* adjacents */ 837 int *R2, *L2; // le generateur des intervalle-modules produit Capelle-like en phase 2 838 int *R, *L; // le generateur canonique des intervalle-modules 839 int *SupR, *SupL; // le support pour passer de (R2,L2) a (R,L) 840 841 int *pile; // pile utilisee pour calcule generateur 842 int sommet; // sommet de ladite pile. Indique la derniere place PLEINE 843 844 int *tab1,*tab2; // utilise pour le tri lineaire avant algo 6 845 int *fortg, *fortd; // bornes de mes modules forts 846 int nb_forts=0; // nombre de modules forts 847 848 int *newfortg, *newfortd; // tableau de modules forts utilises temporairement pour bucket sort 849 848 850 /*PROPHASE : initialisations */ 849 851 n=G.n; 850 ouvrantes = (int *) fabmalloc(n * sizeof(int));851 fermantes = (int *) fabmalloc(n * sizeof(int));852 852 ps = (int *) fabmalloc(n * sizeof(int)); 853 853 ds = (int *) fabmalloc(n * sizeof(int)); 854 pileinterne = (noeud **) fabmalloc((2 * n + 4) * sizeof(noeud *)); 855 adjii= (int *) fabmalloc(n*sizeof(int)); 856 /*pas plus de 2n+4 noeuds internes dans le pseudocoarbre */ 857 for (i = 0; i < n; i++) { 858 ouvrantes[i] = 0; 859 fermantes[i] = 0; 860 adjii[i]=0; 861 } 862 863 /* remplit adjii qui dit si S[i] adjacent a S[i+1] */ 864 for(i=0; i<n-1; i++) 865 { 866 a1=S[i]->adj; 867 while((a1!=NULL)&&(a1->pointe->place != i+1)) 868 a1=a1->suiv; 869 if( a1 == NULL) 870 adjii[i]=0; 871 else // a1->pointe->place==i+1, donc i adj i+1 872 adjii[i]=1; 873 } 874 adjii[n-1]=0; //perfectionnisme 854 R2 = (int *)fabmalloc(n * sizeof(int)); 855 L2 = (int *)fabmalloc(n * sizeof(int)); 856 SupR = (int *)fabmalloc(n * sizeof(int)); 857 SupL = (int *)fabmalloc(n * sizeof(int)); 858 R = (int *)fabmalloc(n * sizeof(int)); 859 L = (int *)fabmalloc(n * sizeof(int)); 860 pile = (int *)fabmalloc(n * sizeof(int)); 861 tab1 = (int *)fabmalloc(4 * n * sizeof(int)); 862 tab2 = (int *)fabmalloc(2 * n * sizeof(int)); 863 fortg=fabmalloc(2 * n * sizeof(int)); 864 fortd=fabmalloc(2 * n * sizeof(int)); 865 newfortg= (int *)fabmalloc(2 * n * sizeof(int)); 866 newfortd=(int *) fabmalloc(2 * n * sizeof(int)); 875 867 876 868 /* PREMIERE PASSE 877 869 on va parentheser la permutation factorisante. 878 tout bonnement, on lit S et on cherche les separateurs; 879 apres quoi ouvrantes et fermantes sont ecrites 880 complexite: O(n^2) */ 881 882 ouvrantes[0] = 1; 883 fermantes[n - 1] = 1; /* parentheses des bords */ 870 complexite: O(m) */ 871 // utilise ps ds 884 872 885 873 for (i = 0; i < n - 1; i++) { 886 874 /*recherche de ps(i,i+1) */ … … 899 887 ||((a2==NULL) && (a1->pointe->place >= i)) 900 888 ||((a1!=NULL) && (a2!=NULL) && (a1->pointe->place >= i) && (a2->pointe->place >= i))) 901 889 //pas de separateur 902 ps[i]= i+1;890 ps[i]=-1; 903 891 else 904 892 { 905 893 if((a1==NULL) || (a1->pointe->place >= i)) … … 915 903 else 916 904 ps[i]=min(a1->pointe->place , a2->pointe->place); 917 905 } 918 ouvrantes[ps[i]]++; /* marque la fracture gauche, if any */919 fermantes[i]++;920 906 } 921 907 if (DEBUG) 922 printf("ps(%i,%i)=%i \n", i , i+1, ps[i]);923 908 printf("ps(%i,%i)=%i ps(%i,%i)=%i\n", i , i+1, ps[i], 909 S[i]->nom, S[i + 1]->nom, ps[i]==-1?-1:S[ps[i]]->nom ); 924 910 /*recherche de ds(i,i+1) 925 911 plus penible encore!*/ 926 912 a1=S[i]->adj; … … 942 928 ||((a2==NULL) && (a1->pointe->place <= i+1)) 943 929 ||((a1!=NULL) && (a2!=NULL) && (a1->pointe->place <= i+1) && (a2->pointe->place <= i+1))) 944 930 //pas de separateur 945 ds[i]= i+1;931 ds[i]=-1; 946 932 else 947 933 { 948 934 if((a1==NULL) || (a1->pointe->place <= i+1)) … … 961 947 962 948 963 949 //ds[i] = j; 964 ouvrantes[i + 1]++; /* marque la fracture gauche, if any */965 fermantes[ds[i]]++; /* attention aux decalages d'indices */966 950 } 967 951 if (DEBUG) 968 printf("ds(%i,%i)=%i \n", i,i+1,ds[i]);969 //S[i]->nom + 1, S[i + 1]->nom + 1, S[ds[i]]->nom + 1);952 printf("ds(%i,%i)=%i ds(%i,%i)=%i\n", i,i+1,ds[i], 953 S[i]->nom, S[i + 1]->nom, ds[i]==-1?-1:S[ds[i]]->nom ); 970 954 } 971 955 972 /*DEUXIEME PASSE: construction du pseudocoarbre */ 956 /* DEUXIEMME PASSE 957 Calcule le generateur des interval-modules comme algo 9 du papier DAM 958 */ 959 int v; 960 // utilise ps ds L2 R2 pile 973 961 974 racine = nouvnoeud(UNKN, NULL, -1, n); 975 courant = racine; 976 for (i = 0; i < n; i++) { 977 /*1: on lit des parentheses ouvrantes: descentes */ 978 for (j = 0; j < ouvrantes[i]; j++) { 979 /*Descente vers un nouveau noeud */ 980 nouveau = nouvnoeud(UNKN, courant, -1, n); 981 ajoutfils(courant, nouveau); /*on l'ajoute... */ 982 courant = nouveau; /* et on descent */ 983 if (DEBUG) 984 printf("("); 962 // algo 9 963 // Attention s[v] dans l'algo est ds[v-1] !! 964 sommet = -1; 965 966 for(v = n-1; v>=0; v--) 967 if(ds[v-1] != -1) 968 { 969 L2[v]=v; 970 while( pile[sommet] < ds[v-1]) 971 L2[pile[sommet--]]=v; 985 972 } 986 /* 2: on lit le sommet: feuille */ 987 nouveau = nouvnoeud(FEUILLE, courant, i, n); 988 ajoutfils(courant, nouveau); /*on ajoute le bebe... */ 989 (*nouveau).ps = i; 990 (*nouveau).ds = i; 991 (*nouveau).bg = i; 992 (*nouveau).bd = i; 993 nouveau->nom = S[i]->nom; 994 /* et pourquoi pas i ? Je m'embrouille... */ 995 if (DEBUG) 996 printf(" %i ", S[i]->nom + 1); 973 else 974 pile[++sommet]=v; 997 975 998 /*3: on lit des parentheses fermantes: remontees */ 999 for (j = 0; j < fermantes[i]; j++) { 1000 /*ASTUCE: ici on va en profiter pour supprimer les 1001 noeuds a un fils, afin d'economiser une passe */ 1002 if (courant->fils == courant->lastfils) { /*just one son */ 1003 courant->pere->lastfils->pointe = courant->fils->pointe; 1004 courant->fils->pointe->pere = courant->pere; 1005 courant->fils->pointe->fpere = courant->pere->lastfils; 1006 /* explication: le dernier fils de courant.pere est 1007 actuellement courant himself. Il est donc pointe par 1008 courant.pere.lastfils.pointe. Il suffit de changer ce 1009 pointeur pour qu'il pointe maintenant non plus sur courant, 1010 mais sur l'unique fils de courant: courant.fils.pointe. 1011 Ouf! */ 1012 /* NB: courant est maintenant deconnecte de l'arbre. 1013 on pourrait faire un free() mais bon... */ 1014 } 1015 else { 1016 /*on empile ce noeud interne. 1017 L'ordre est celui de la postvisite d'un DFS */ 1018 pileinterne[indicepileinterne] = courant; 1019 indicepileinterne++; 1020 } 1021 /* et dans tous les cas: on remonte! */ 1022 courant = courant->pere; 1023 if (DEBUG) 1024 printf(")"); 976 while(sommet>=0) 977 L2[pile[sommet--]]=0; 978 979 sommet = -1; 980 // algo 9 symétrique 981 //re-attention là c'est ps[v] 982 for(v = 0 ; v<=n-1; v++) 983 if(ps[v] != -1) 984 { 985 R2[v]=v; 986 while( pile[sommet] > ps[v]) 987 R2[pile[sommet--]]=v; 1025 988 } 1026 } 989 else 990 pile[++sommet]=v; 991 992 while(sommet>=0) 993 R2[pile[sommet--]]=n-1; 994 1027 995 if (DEBUG) 996 { printf("L2 = ["); 997 for(v = 0;v<n;v++) 998 printf("%i ",L2[v]); 999 printf("]\nR2 = ["); 1000 for(v = 0;v<n;v++) 1001 printf("%i ",R2[v]); 1002 printf("]\n"); 1003 for(i=0;i<n;i++) 1004 for(j=i+1;j<n;j++) 1005 if(L2[j]<=i && j<= R2[i]) 1006 printf("[%i-%i] module\n",i,j); 1007 1008 } 1009 1010 1011 1012 /* TROISIEME PASSE 1013 generateur canonique. Algos 3 et 5 du papier de DAM 1014 */ 1015 1016 // Algo 3, R 1017 pile[0]=0; 1018 sommet =0; 1019 for(i=1;i<n;i++) 1020 { 1021 while(R2[pile[sommet]] < i) 1022 sommet --; 1023 SupR[i]=pile[sommet]; 1024 pile[++sommet]=i; 1025 } 1026 1027 // Algo 3, L 1028 1029 pile[0]=n-1; 1030 sommet =0; 1031 for(i=n-2;i>=0;i--) 1032 { 1033 while(L2[pile[sommet]] > i) 1034 sommet --; 1035 SupL[i]=pile[sommet]; 1036 pile[++sommet]=i; 1037 } 1038 1039 if (DEBUG) 1040 { 1041 printf("SupL = ["); 1042 for(v = 0;v<n;v++) 1043 printf("%i ",SupL[v]); 1044 printf("]\nSupR = ["); 1045 for(v = 0;v<n;v++) 1046 printf("%i ",SupR[v]); 1047 printf("]\n"); 1048 } 1049 1050 // Algo 5, R 1051 int k; 1052 R[0]=n-1; 1053 for(k=1;k<n;k++) 1054 R[k]=k; 1055 for(k=n-1;k>=1;k--) 1056 if(L2[R[k]] <= SupR[k] && R[k] <= R2[SupR[k]]) 1057 R[SupR[k]] = max(R[k], R[SupR[k]]); 1058 1059 // Algo 5, L 1060 L[n-1]=0; 1061 for(k=0;k<n-1;k++) 1062 L[k]=k; 1063 for(k=0;k<n-1;k++) 1064 if(L2[SupL[k]] <= L[k] && SupL[k] <= R2[L[k]]) 1065 L[SupL[k]] = min(L[k], L[SupL[k]]); 1066 1067 if (DEBUG) 1068 { printf("L = ["); 1069 for(v = 0;v<n;v++) 1070 printf("%i ",L[v]); 1071 printf("]\nR = ["); 1072 for(v = 0;v<n;v++) 1073 printf("%i ",R[v]); 1074 printf("]\n"); 1075 for(i=0;i<n;i++) 1076 for(j=i+1;j<n;j++) 1077 if(L[j]<=i && j<= R[i]) 1078 printf("[%i-%i] module\n",i,j); 1079 1080 } 1081 1082 /* QUATRIEME PASSE 1083 strong modules. Algo 6 du papier de DAM 1084 */ 1085 //1 remplit le tableau des bornes 1086 // astuce : on met 2a pour a borne gauche et 2a+1 pour a borne droite. Puis tri lineaire 1087 1088 for(i = 0; i<n; i++) 1089 { 1090 // intervalle (L[i]..i) 1091 tab1[4*i] = 2*L[i]; 1092 tab1[4*i+1] = 2*i+1; 1093 // intervalle (i..R[i]) 1094 tab1[4*i+2] = 2*i; 1095 tab1[4*i+3] = 2*R[i]+1; 1096 } 1097 // tableau des fréquences 1098 1099 for( i=0;i<2*n;i++) 1100 tab2[i]=0; 1101 for( i=0;i<4*n;i++) 1102 tab2[tab1[i]]++; 1103 // tri 1104 j = 0; 1105 for( i=0;i<2*n;i++) 1106 while(tab2[i]-->0) 1107 { 1108 tab1[j++] = i; 1109 } 1110 1111 // Algo 6 du papier de DAM 1112 // j'utilise maintenant tab2 comme stack de sommet : sommet 1113 sommet = -1; 1114 1115 1116 for( i=0;i<4*n;i++) 1117 { 1118 int ai,s; //meme noms de variables que papier 1119 ai=tab1[i]; 1120 if((ai%2)==0) 1121 tab2[++sommet] = ai; 1122 else 1123 { 1124 ai/=2; 1125 s = tab2[sommet--]/2; 1126 1127 if(nb_forts == 0 || (fortg[nb_forts - 1] != s) || (fortd[nb_forts - 1] != ai)) 1128 { 1129 fortg[nb_forts] = s; 1130 fortd[nb_forts] = ai; 1131 nb_forts++; 1132 } 1133 } 1134 } 1135 if(DEBUG) 1136 { 1137 printf("Modules forts :\n"); 1138 for( i=0;i<nb_forts;i++) 1139 printf("[%i %i] ", fortg[i], fortd[i]); 1028 1140 printf("\n"); 1141 } 1029 1142 1030 /* on enleve un ptit defaut */ 1031 racine = racine->fils->pointe; 1032 racine->pere = NULL; 1033 racine->fpere = NULL; 1034 if (DEBUG) { 1035 printf("Arbre apres la deuxieme passe:\n"); 1036 printnoeud(racine, 0); 1037 } 1143 // TRI des modules forts par bornes droites decroissantes 1144 for( i=0;i<n;i++) 1145 tab1[i]=0; 1146 for( i=0;i<nb_forts;i++) 1147 tab1[fortd[i]]++; 1148 for( i=1;i<n;i++) 1149 tab1[i]+=tab1[i-1]; 1038 1150 1039 /*TROISIEME PASSE */ 1040 /* A ce stade, on a un pseudocoarbre de racine racine, 1041 sans noeuds a un fils, et dont les etiquettes sont 1042 FEUIILLE ou UNKN. Il y a une pile des noeuds UNKN, stockes 1043 dans l'ordre de la postvisite d'un parcours en profondeur. 1044 On va s'en servir pour faire remonter les bords et les 1045 separateurs de bas en haut */ 1151 // tab1 = tableau des frequences cumulées 1152 for( i=0;i<nb_forts;i++) 1153 { 1154 int pos = (nb_forts-1)-(tab1[fortd[i]]-1); 1155 newfortg[ pos ] = fortg[i]; 1156 newfortd[ pos ] = fortd[i]; 1157 tab1[fortd[i]]--; 1158 } 1159 if(DEBUG) 1160 { 1161 printf("Modules forts :\n"); 1162 for( i=0;i<nb_forts;i++) 1163 printf("[%i %i] ", newfortg[i], newfortd[i]); 1164 printf("\n"); 1165 } 1046 1166 1047 taillepileinterne = indicepileinterne; 1048 for (indicepileinterne = 0; indicepileinterne < taillepileinterne; 1049 indicepileinterne++) { 1050 noeud *scanne; 1051 fils *nextfils; 1052 noeud *succourant; 1053 /* scanne est le noeud (pere) que l'on regarde; 1054 nextfils parcours sa liste de fils; 1055 courant est le fils actuellement examine et 1056 succourant=succ(courant) */ 1057 noeud *debutnoeud; 1058 fils *debutfils; 1059 /*deux variables utilise pour la recherche de jumeaux: 1060 debut du bloc max */ 1167 // now tri par bornes gauches croissantes 1168 for( i=0;i<n;i++) 1169 tab1[i]=0; 1170 for( i=0;i<nb_forts;i++) 1171 tab1[newfortg[i]]++; 1172 for( i=1;i<n;i++) 1173 tab1[i]+=tab1[i-1]; 1061 1174 1062 scanne = pileinterne[indicepileinterne]; /*he oui, la pile */ 1063 nextfils = scanne->fils; /*on commence au premier fils */ 1064 do { 1065 /*la boucle chiante... cf mon memoire de DEA */ 1066 courant = nextfils->pointe; 1067 /* bords */ 1068 scanne->bg = min(scanne->bg, courant->bg); 1069 scanne->bd = max(scanne->bd, courant->bd); 1070 /*separateurs */ 1071 scanne->ps = min(scanne->ps, courant->ps); 1072 if (scanne->fils->pointe != courant) 1073 /*ce n'est pas le premier fils */ 1074 scanne->ps = min(scanne->ps, ps[(courant->bg) - 1]); 1075 scanne->ds = max(scanne->ds, courant->ds); 1076 if (scanne->lastfils->pointe != courant) 1077 /*ce n'est pas le dernier fils */ 1078 scanne->ds = max(scanne->ds, ds[courant->bd]); 1175 // tab1 = tableau des frequences cumulées 1176 for( i = nb_forts-1 ; i>=0 ; i--)// parcours de droite a gauche car on retourne tout 1177 { 1178 int pos = tab1[newfortg[i]]-1; 1179 // printf("[%i %i] en pos %i\n",newfortg[i],newfortd[i],pos); 1180 fortg[ pos ] = newfortg[i]; 1181 fortd[ pos ] = newfortd[i]; 1182 tab1[newfortg[i]]--; 1183 } 1184 if(DEBUG) 1185 { 1186 printf("Modules forts :\n"); 1187 for( i=0;i<nb_forts;i++) 1188 printf("[%i %i] ", fortg[i], fortd[i]); 1189 printf("\n"); 1190 } 1079 1191 1080 nextfils = nextfils->suiv; 1081 } 1082 while (nextfils != NULL); 1192 // Finally algo 7 du papier : construit l'arbre 1193 noeud* racine = nouvnoeud( UNKN, NULL, -1, 0, n-1); 1083 1194 1195 noeud *F = racine; 1196 noeud *Nouv; 1197 for(k=1; k< nb_forts; ) 1198 { 1199 if(F->fv <= fortg[k] && F->lv >= fortd[k] ) 1200 { 1201 if(fortg[k]==fortd[k]) // on a une feuille 1202 Nouv = nouvnoeud(FEUILLE, F, S[fortg[k]]->nom, fortg[k], fortd[k]); 1203 else 1204 Nouv = nouvnoeud(UNKN, F, -1, fortg[k], fortd[k]); 1205 ajoutfils(F, Nouv); 1206 // printf("nouv [%i %i] de pere [%i %i]\n", 1207 // fortg[k], fortd[k], F->fv, F->lv); 1208 F = Nouv; 1209 k++; 1084 1210 1085 if (DEBUG) 1086 printf("noeud %i-%i: ps=%i ds=%i", 1 + scanne->bg, 1087 1 + scanne->bd, 1 + scanne->ps, 1 + scanne->ds); 1211 } 1212 else 1213 { 1214 // printf("remonte car [%i %i] pas fils de [%i %i]\n", 1215 // fortg[k], fortd[k], F->fv, F->lv); 1216 F = F->pere; 1217 } 1218 } 1219 if(DEBUG) 1220 { 1221 printf("arbre avant typage :\n"); 1222 printarbre(racine); 1223 } 1088 1224 1089 /* maintenant le test tout simple pour savoir si on a un module: */ 1090 if (((scanne->ps) == (scanne->bg)) 1091 && ((scanne->ds) == (scanne->bd))) { 1092 /*on a un module */ 1093 scanne->type = MODULE; 1094 if (DEBUG) 1095 printf(" Module.\n"); 1096 } 1097 else { 1098 scanne->type = ARTEFACT; 1099 if (DEBUG) 1100 printf(" artefact.\n"); 1101 } 1102 } 1225 /* CINQUIEME PASSE : typage */ 1226 // Methode : on teste grace au generateur la modularite des deux premiers fils. 1227 // Ensuite si module est serie si adjacence parallele sinon 1228 typenoeud(racine, L2, R2, S); 1103 1229 1104 if (DEBUG) { 1105 printf("Arbre apres la troisieme passe:\n"); 1106 printnoeud(racine, 0); 1107 } 1230 if(DEBUG) 1231 { 1232 printf("\n arbre final :\n"); 1233 printarbre(racine); 1234 } 1235 /* nettoie un peu */ 1236 free(ps); 1237 free(ds); 1238 free(R2); 1239 free(L2); 1240 free(SupR); 1241 free(SupL); 1242 free(R); 1243 free(L); 1244 free(pile); 1245 free(tab1); 1246 free(tab2); 1247 free(fortg); 1248 free(fortd); 1249 free(newfortg); 1250 free(newfortd); 1108 1251 1109 /* QUATRIEME PASSE */1110 /* technique:on se contente de fusionner les artefacts a leurs parents1111 ca se fait de bas en haut grace a pileinterne (toujours elle!) */1112 1252 1113 for (indicepileinterne = 0; indicepileinterne < taillepileinterne;1114 indicepileinterne++) {1115 noeud *scanne;1116 scanne = pileinterne[indicepileinterne]; /*he oui, la pile */1117 if (scanne->type == ARTEFACT) {1118 /*attention! La pile peut contenir des noeuds deconnectes */1119 fusionne(scanne->pere, scanne);1120 if (DEBUG)1121 printf("Artefact elimine: %i-%i\n", 1 + scanne->bg,1122 1 + scanne->bd);1123 }1124 }1125 if (DEBUG) {1126 printf("Arbre apres la quatrieme passe:\n");1127 printnoeud(racine, 0);1128 }1129 1130 /* CINQIEME ET DERNIERE PASSE */1131 /* on va typer les noeuds et extraire les fusions.1132 comment on fait? Ben, la pile.... */1133 for (indicepileinterne = 0; indicepileinterne < taillepileinterne;1134 indicepileinterne++) {1135 noeud *scanne;1136 fils *nextfils;1137 noeud *succourant;1138 /* scanne est le noeud (pere) que l'on regarde;1139 nextfils parcours sa liste de fils;1140 courant est le fils actuellement examine et1141 succourant=succ(courant) */1142 noeud *debutnoeud;1143 fils *debutfils;1144 /*deux variables utilise pour la recherche de jumeaux:1145 debut du bloc max */1146 1147 scanne = pileinterne[indicepileinterne];1148 if (scanne->type != MODULE)1149 continue; /* je traite que les modules */1150 1151 nextfils = scanne->fils; /*on commence au premier fils */1152 while (1) {1153 courant = nextfils->pointe;1154 succourant = nextfils->suiv->pointe;1155 if (ps[courant->bd] >= courant->bg1156 && ds[courant->bd] <= succourant->bd) {1157 /*Des jumeaux!! ->serie ou parallele! */1158 /* on va determiner le bloc max de jumeaux consecutifs */1159 debutnoeud = courant;1160 debutfils = nextfils;1161 while (ps[courant->bd] >= courant->bg &&1162 ds[courant->bd] <= succourant->bd &&1163 nextfils->suiv != NULL) {1164 nextfils = nextfils->suiv;1165 courant = nextfils->pointe;1166 if (nextfils->suiv == NULL)1167 break;1168 succourant = nextfils->suiv->pointe;1169 }1170 /*maintenant on connait la taille du bloc: il va de1171 debutnoeud a courant inclus,1172 et dans la liste des fils de scanne,1173 il s'etend de debutfils a nextfils inclus.1174 On extrait cette liste pour en faire les fils d'un1175 nouveau noeud... sauf si pas la peine! */1176 if (debutfils == scanne->fils1177 && nextfils == scanne->lastfils) {1178 /* le noeud scanne etait serie ou parallele */1179 if ( adjii[debutnoeud->bd] !=0)1180 scanne->type = SERIE;1181 else1182 scanne->type = PARALLELE;1183 }1184 else {1185 if ( adjii[debutnoeud->bd]!=0)1186 /*seule cette ligne distingue G de G' !! */1187 {1188 nouveau = nouvnoeud(SERIE, scanne, -1, n);1189 if (DEBUG)1190 printf("Module serie extrait: %i-%i\n",1191 1 + debutnoeud->bg, 1 + courant->bd);1192 }1193 else {1194 nouveau = nouvnoeud(PARALLELE, scanne, -1, n);1195 if (DEBUG)1196 printf("Module parallele extrait: %i-%i\n",1197 1 + debutnoeud->bg, 1 + courant->bd);1198 }1199 extraire(scanne, nouveau, debutfils, nextfils);1200 }1201 }1202 if (scanne->type == MODULE)1203 scanne->type = PREMIER;1204 if (nextfils->suiv == NULL || nextfils->suiv->suiv == NULL1205 || nextfils->suiv->suiv->suiv == NULL)1206 break;1207 nextfils = nextfils->suiv;1208 }1209 }1210 if (DEBUG) {1211 printf("Arbre final:\n");1212 printnoeud(racine, 0);1213 }1214 1253 return racine; 1215 1254 } 1216 1255 … … 1252 1291 /* affiche la permutation factorisante */ 1253 1292 { 1254 1293 int i; 1255 printf( "Place (nouvelle num) "); 1294 printf("Attention dans debug maintenant usage des NOUVEAUX noms\n"); 1295 printf( "Place (nouveaux noms, nouvelle numerotation) "); 1256 1296 for(i=0;i<n;i++) 1257 1297 printf("%3i ",S[i]->place); 1258 printf("\nNom (ancienne num) :");1298 printf("\nNom (ancienne num) : "); 1259 1299 for(i=0;i<n;i++) 1260 1300 printf("%3i ",S[i]->nom); 1261 1301 printf("\n"); 1262 1302 } 1263 1303 1304 void nettoie(sommet **S, int n) 1305 { 1306 // Detruit la copie locale du graphe 1307 // normalement, apres, tous les mallocs sont 1308 // annules sauf ceux de l'arbre (le resultat) 1309 int i; 1310 sommet * scourant; 1311 sadj *a,*atmp; 1312 for (i = 0; i < n; i++) { 1313 /* initialisation des sommets */ 1314 /* notre bebe est le sommet i dans M */ 1315 scourant = S[i]; 1316 a=scourant->adj; 1317 while(a!=NULL) 1318 { 1319 atmp=a->suiv; 1320 free(a); 1321 a=atmp; 1322 } 1323 free(scourant->classe); // efface toutes les classes car sont singletons 1324 free(scourant); 1325 } 1326 free(S); 1327 } 1264 1328 1265 1329 /* la fonction principale; qui fait pas grand'chose....*/ 1266 1330 noeud *decomposition_modulaire(graphe G) … … 1282 1346 PrintS2(S,G.n); 1283 1347 } 1284 1348 Racine = algo2(G, S); /* deuxieme partie: calcul de l'arbre */ 1349 1350 nettoie(S, G.n); 1351 1285 1352 return Racine; 1286 1353 } -
sage/graphs/modular_decomposition/src/dm_english.h
diff --git a/sage/graphs/modular_decomposition/src/dm_english.h b/sage/graphs/modular_decomposition/src/dm_english.h
a b 66 66 Each internal node is labelled SERIE (for series), PARALLELE (for parallel) or PREMIER (for prime) depending of the quotient's type. 67 67 Each leaf is labelled FEUILLE and also contains the vertex number of the leaf. 68 68 As the tree is an inclusion tree, the vertex-set corresponding to an internal node correspond to the vertices numbers of the leaves that descend from that tree. The function decomposition_modulaire() return a pointer to the root of the tree. 69 69 */ 70 70 71 71 72 72 /* define the type of nodes. UNKN,MODULE,ARTEFACT are for internal use*/ … … 85 85 int type; // is FEUILLE, SERIE, PARALLELE or PREMIER 86 86 struct Noeud *pere; // adress of parent node, NULL if root 87 87 struct Fils *fpere; // points the head of the linked list of sons (if type is not FEUILLE, else is NULL) 88 int ps; // internal use89 int bg; // internal use90 int ds; // internal use91 int bd; // internal use92 int sommet; // internal use93 88 int nom; // if type=FEUILLE, number of the corresponding vertex of the graph 94 89 struct Fils *fils; // points the head of the linked list of sons 95 90 struct Fils *lastfils; // internal use (points the last item in the listed list of sons) 96 91 int id; // internal use (node unique ID) 92 int fv; // internal use (first vertex in factorizing permutation) 93 int lv; // internal use (last vertex in factorizing permutation) 94 97 95 } noeud; 98 96 99 97 /* linked list that strore the sons of an internal node (in any order) */ -
sage/graphs/modular_decomposition/src/random.c
diff --git a/sage/graphs/modular_decomposition/src/random.c b/sage/graphs/modular_decomposition/src/random.c
a b 67 67 { 68 68 if(VERBEUX) 69 69 { 70 printf("Ajacence de %i: ",i +1);70 printf("Ajacence de %i: ",i); 71 71 for(a=G.G[i]; a!=NULL; a=a->suiv) 72 printf("%i ", 1+a->s);72 printf("%i ",a->s); 73 73 } 74 74 for(j=i+1;j<n;j++) 75 75 { … … 86 86 a->suiv=G.G[j]; 87 87 G.G[j]=a; 88 88 if(VERBEUX) 89 printf("%i ",j +1);89 printf("%i ",j); 90 90 } 91 91 } 92 92 if(VERBEUX)