diff --git a/CMakeLists.txt b/CMakeLists.txt index e5232bec25f8c0c4c7999b161403a6f5661140d5..39aa0857cd025e125b6ca28580e012214ae4c9aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,8 +17,6 @@ add_executable(sga main.c heap.c heap.h - fibheap.c - fibheap.h tree.c tree.h decompose.c decompose.h separator.c separator.h diff --git a/README.md b/README.md deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/decompose.c b/decompose.c index 375f695a33ff9a7c72745dc93ac671e854f3f83d..556d28fd7abd30a1186d760642a0c72d5d98a7a7 100644 --- a/decompose.c +++ b/decompose.c @@ -101,7 +101,7 @@ extern int *sumSizes; void testDecompose(Graph g, int nbRuns, int algo) { int *S = malloc(g->n * sizeof(int)); // list of vertices - int *posS = malloc(g->n * sizeof(int)); // booleans for separe + int *posS = malloc(g->n * sizeof(int)); // booleans for separation int *nbCriticalNodes = malloc(g->n * sizeof(int)); // to calculate the numbers of critical nodes at each level int bestHDec = g->n+1; Node root; @@ -110,8 +110,6 @@ void testDecompose(Graph g, int nbRuns, int algo) { int nbRunsAttempted = 0; int trace = 0; - //if (g->n > 300000) nbRunsSeparation = 1; // commented 26 mai - if (perForceChoiceNotInC == NONE) perForceChoiceNotInC = (g->n > 7600) ? 10 : 0; @@ -370,7 +368,7 @@ Node decompose(int *S, int n, int pos[], int depth, Graph g, int hmax, int conne } - if (sizeForest(A)+ sizeForest(B)+ sizeForest(root) != nA+nB+nC) { + if (0) if (sizeForest(A)+ sizeForest(B)+ sizeForest(root) != nA+nB+nC) { printf("nA=%d nB=%d nC=%d A:%d B:%d root:%d\n", nA, nB, nC, sizeForest(A), sizeForest(B), sizeForest(root)); exit(0); } @@ -790,7 +788,7 @@ void allocNodes(Graph g) { void allocSets(Graph g, int max) { theSets = calloc((size_t) (g->n), sizeof(SET)); for (int i = 0; i < max; i ++) - theSets[i] = allocSet(g->n); + theSets[i] = allocSet(g->n + 100); } diff --git a/fibheap.c b/fibheap.c deleted file mode 100644 index eaef3fa39f471d0726d1198fd2cf9f1f785b2dfc..0000000000000000000000000000000000000000 --- a/fibheap.c +++ /dev/null @@ -1,419 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <limits.h> - -#include "fibheap.h" - -ARBRE_FIBO *trees = NULL; /* table d'arbres indicee sur le degre. */ -int size_trees = 32; - - -/****************** grands principes ****************** - - (1) Un noeud est marque lorsqu'il perd un fils. Quand il est decroche il - est demarque, ainsi que chaque fois qu'il devient fils d'un autre noeud. - S'il perd a nouveau un fils il est decroche et devient une racine non marquee; - (2) du coup si on note y1,...,yk les fils d'un noeud x dans leur ordre - d'arrivee, on a degre(yi)>=i-2 (ou 0 pour y1), et donc - degre(yi)=i-1 ou degre(yi)=i-2 - (3) sk : taille min d'un arbre de degre k - On montre que sk >= 2+Sum_0^{k-2}si (le 2 vient du fait qu'on compte la - racine et le premier fils qui est de taille au moins 1 car de degre 0 ou 1 ; - pour le reste on sait que size(yi)>=s_{degre(yi)}>=s_{i-2} (voir (2))). - Comme Fk = 2+Sum_0^{k-2}Fi >= phi^k, on en deduit - sk >= phi^k - et donc pour tout x de degre k, size(x)>=phi^k - et donc pour tout x de taille N, degre(x) <= log_{phi} N - Pour un tas de taille N, le degre maximal est borne par log_{phi} N. - - Donc la taille des arbres croit exponentiellement avec le degre de - la racine, ce qui induit la bonne complexite des operations de cout le - degre. - - */ - - -void afficher_elt(TYPE_ELT e) { - printf("%d", e); -} - - -/****************** Utilitaires listes. ******************/ - -NODE_FIBO newHeapNode(int u, TYPE_ELT val, LISTED suiv, LISTED prec, LISTED fils, LISTED pere, int degre, int taille, NODE_FIBO x) { - if (x == NULL) { - x = malloc(sizeof(struct node_fibo_heap)); - assert(x != NULL); - } - x->u = u; - x->val = val; - x->marque = 0; - x->suiv = suiv; - x->prec = prec; - x->fils = fils; - x->pere = pere; - x->degre = degre; - x->taille = taille; - return x; -} - -LISTED addToList(ARBRE_FIBO t, LISTED l) { -/* Insertion de l'arbre t dans la liste l. */ - if (l == NULL) { - t->suiv = t->prec = t; - return t; - } - t->suiv = l->suiv; - l->suiv = t; - t->prec = l; - t->suiv->prec = t; - return l; -} - -void removeFromList(LISTED p) -/* Utilise dans extraire_min. */ -/* On modifie le chainage de la liste. Suppose qu'il y a plus d'un noeud. */ -{ - LISTED prec = p->prec; - prec->suiv = p->suiv; - prec->suiv->prec = prec; -} - - -/****************** Utilitaires arbres. ******************/ - -ARBRE_FIBO mergeFiboTrees(ARBRE_FIBO s, ARBRE_FIBO t) -/* Comme pour les tas binomiaux on met en dessous celui qui a la plus grande - valeur a la racine et on met a jour les degres. */ -{ - if (s->val > t->val) - { - t->fils = addToList(s, t->fils); - t->degre = t->degre+1; - s->pere = t; - s->marque = 0; - return t; - } - else - { - s->fils = addToList(t, s->fils); - s->degre = s->degre+1; - t->pere = s; - t->marque = 0; - return s; - } -} - -#define FULL_AFFICHAGE - -void printFiboTree(ARBRE_FIBO p, int d) { - int i; - LISTED q; - - for (i = 0; i < d; i++) - printf(" "); - afficher_elt(p->val); -#ifdef FULL_AFFICHAGE - printf(" ["); - if (p->pere != NULL) - afficher_elt(p->pere->val); - printf("]"); - printf(" "); - afficher_elt(p->prec->val); - printf("<>"); - afficher_elt(p->suiv->val); -#endif - printf("\n"); - if ((q = p->fils) != NULL) - { - LISTED r = q; - - do - { - printFiboTree(r, d+1); - r = r->suiv; - } - while (r != q); - } -} - - -/****************** Tas de Fibonacci : utils ******************/ - - -TAS_FIBO consolidateFiboHeap(TAS_FIBO t) -/* Remise en forme du tas : on parcourt les arbres, en les stockant dans - le tableau trees[] indic'e sur les degres. Chaque fois qu'on rencontre - deux arbres de memes degres on les fusionne et on recommence. */ -{ - ARBRE_FIBO p, s; - int d, dmax = 0, i; - - if (t == NULL) - return NULL; - if (trees == NULL) - trees = malloc((size_trees+1) * sizeof(ARBRE_FIBO)); - for (i = 0; i < size_trees+1; i++) - trees[i] = NULL; - - /* Parcours de la liste des arbres en fusionnant. */ - p = t; - do - { - s = p->suiv; - d = p->degre; - while (trees[d] != NULL) - { - /* on fusionne les deux arbres de meme degre. */ - /* pas la peine de decrocher p, on reconstruira la liste des arbres*/ - p = mergeFiboTrees(trees[d], p); - trees[d] = NULL; - d = p->degre; - } - trees[d] = p; - if (d > dmax) - dmax = d; - p = s; - } - while (p != t); - - /* On parcourt la table trees[] pour reconstruire le tas. */ - for (d = 0, t = NULL; d < dmax+1; d++) - if (trees[d] != NULL) - { - trees[d]->pere = NULL; - t = addToList(trees[d], t); - if (t->val > trees[d]->val) - t = trees[d]; - } - return t; -} - - - -void printFiboHeap(TAS_FIBO T) { - TAS_FIBO p = T; - - if (T == NULL) - return; - do - { - printFiboTree(p, 0); - p = p->suiv; - } - while (p != T); -} - - - -int sizeArbreFibo(ARBRE_FIBO a) { - ARBRE_FIBO q; - int size = 1; - - if ((q = a->fils) != NULL) - { - LISTED r = q; - do - { - size += sizeArbreFibo(r); - r = r->suiv; - } - while (r != q); - } - return size; -} - - - -int sizeTasFibo(TAS_FIBO H) { - TAS_FIBO p = H; - if (p == NULL) - return 0; - int size = 0; - do - { - size += sizeArbreFibo(p); - p = p->suiv; - } - while (p != H); - return size; -} - - -/****************** Tas de Fibonacci : operations de base ******************/ -/* If p is NULL the new node is allocated in function newHeapNode(). */ -TAS_FIBO insertFiboHeap(int u, TYPE_ELT val, TAS_FIBO t, NODE_FIBO p, ARBRE_FIBO *the) -/* insertion de val dans t. On insere un nouveau maillon dans la liste et - on met a jour le min. */ -{ - if (t == NULL) - { - p = newHeapNode(u, val, NULL, NULL, NULL, NULL, 0, 1, p); - p->suiv = p->prec = p; - if (the != NULL) - *the = p; - return p; - } - - p = newHeapNode(u, val, t, t->prec, NULL, t->pere, 0, 1, p); - t->prec->suiv = p; - t->prec = p; - - if (the != NULL) - *the = p; - - if (p->val < t->val) - return p; - return t; -} - - - -TAS_FIBO unionFiboHeap(TAS_FIBO s, TAS_FIBO t) -/* L'union consiste juste a concatener les listes en gerant le min. */ -{ - LISTED lt; - - if (s == NULL) - return t; - if (t == NULL) - return s; - lt = t->prec; - lt->suiv = s->suiv; - s->suiv = t; - t->prec = s; - lt->suiv->prec = lt; - if (s->val < t->val) - return s; - return t; -} - - -int extractMinFiboHeap(TAS_FIBO *T, int free_node) -/* Extraction du minimum : on consolide le tas avec la liste des fils - du noeud extrait. */ -{ - LISTED t = *T; - LISTED p = t->suiv; - LISTED r = t->fils; - int min = t->u; - - /* On s'occuppera des peres des fils de t dans consolider. */ - if (p != t) - { - removeFromList(t); - r = unionFiboHeap(r, p); - } - if (free_node) - free(t); - *T = consolidateFiboHeap(r); - return min; -} - - - -/* #define VERSION_COURTE */ - -void decreaseKeyFiboHeap(ARBRE_FIBO p, TYPE_ELT v, TAS_FIBO *T) { - TAS_FIBO t = *T; - ARBRE_FIBO pere = p->pere; -#ifdef VERSION_COURTE - ARBRE_FIBO pi = p; -#endif - - p->val = v; - - /* Cas ou ca ne change rien */ - if (pere == NULL) - { - if (v < t->val) - *T = p; - return; - } - if (pere->val <= v) - return; - - /* Cas ou il faut decrocher le sous arbre. */ -#ifdef VERSION_COURTE - if (p->val < (*T)->val) - *T = p; - while ((pere != NULL) && ((p->marque == 1) || (p == pi))) - { - if (p->suiv == p) - pere->fils = NULL; - else - { - pere->fils = p->suiv; /* au hasard */ - removeFromList(p); - } - pere->degre--; - p->pere = NULL; - if (p != pi) - p->marque = 0; /* Pour le premier coup c'est pas bon ? */ - t = addToList(p, t); - p = pere; - pere = pere->pere; - } - if (p->marque == 1) - p->marque = 0; /* p est racine et marque. */ - else - p->marque = 1; -#else - /* On decroche le noeud. */ - pere->degre--; - if (p->suiv == p) - pere->fils = NULL; - else - { - pere->fils = p->suiv; /* au hasard */ - removeFromList(p); - } - p->pere = NULL; - /* On insere dans la liste des arbres (il y a deja au moins le pere). */ - t = addToList(p, t); - if (p->val < t->val) - *T = p; - - if (pere->pere != NULL) - { - if (pere->marque == 0) - pere->marque = 1; - else - { - p = pere; - pere = pere->pere; - while ((pere != NULL) && (p->marque == 1)) - { - if (p->suiv == p) - pere->fils = NULL; - else - { - pere->fils = p->suiv; /* au hasard */ - removeFromList(p); - } - pere->degre--; - p->pere = NULL; - p->marque = 0; - t = addToList(p, t); - /* if (p->val < t->val) *T = p; - Inutile ici car p n'est pas racine de son arbre. */ - p = pere; - pere = pere->pere; - } - if (p->marque == 1) - p->marque = 0; /* cas ou p est marque et racine dans le tas. */ - else - p->marque = 1; /* cas ou on s'arrete sur un noeud non marque. */ - } - } -#endif -} - - - -void delete_tas(ARBRE_FIBO p, TAS_FIBO *T) -{ - decreaseKeyFiboHeap(p, INT_MIN, T); - extractMinFiboHeap(T, 1); -} diff --git a/fibheap.h b/fibheap.h deleted file mode 100644 index 191b3a74fc6ff6b5222e911d9c0a597df6ec04d5..0000000000000000000000000000000000000000 --- a/fibheap.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _H_tasfibo -#define _H_tasfibo - -// #include "type_elt.h" - -typedef int TYPE_ELT; - -typedef struct node_fibo_heap * LISTED; -typedef struct node_fibo_heap * NODE_FIBO; -typedef struct node_fibo_heap * ARBRE_FIBO; -typedef struct node_fibo_heap * TAS_FIBO; - -typedef struct { - TAS_FIBO heap; - int (*lt)(int, int); -} -* heapFibo; - -struct node_fibo_heap -{ - int u; - TYPE_ELT val; - int marque; /* indique si le noeud a perdu un fils depuis la derniere - fois ou il est devenu fils d'un autre noeud. */ - LISTED suiv, prec, fils, pere; - int degre; - int taille; - - int i; /* Indice dans le tableau the. */ -}; - - - -void printFiboHeap(TAS_FIBO T); -int sizeTasFibo(TAS_FIBO H); -NODE_FIBO newHeapNode(int u, TYPE_ELT val, LISTED suiv, LISTED prec, LISTED fils, LISTED pere, int degre, int taille, NODE_FIBO x); -void decreaseKeyFiboHeap(LISTED p, TYPE_ELT v, TAS_FIBO *T); -void delete_tas(ARBRE_FIBO p, TAS_FIBO *T); -int extractMinFiboHeap(TAS_FIBO *T, int free_node); -TAS_FIBO insertFiboHeap(int u, TYPE_ELT val, TAS_FIBO t, NODE_FIBO p, ARBRE_FIBO *the); -TAS_FIBO unionFiboHeap(TAS_FIBO s, TAS_FIBO t); - - -#endif diff --git a/graph.h b/graph.h index 246ae2758f15564268f6d1a5bdea436c2aa67e9f..a425598cdb1ef3a9cad2203d29512cc36496064e 100644 --- a/graph.h +++ b/graph.h @@ -13,7 +13,6 @@ #include "lists.h" -#include "fibheap.h" #include "heap.h" #include "sets.h" @@ -39,8 +38,6 @@ struct graph { int *nadj; SET *neighbors; - - NODE_FIBO * nodes; /* reserve of nodes for Fibonacci heaps. */ }; diff --git a/main.c b/main.c index 5871e7cb9ecbace8bc0037e57d149d1c9ce8079d..97fd2642831b1029ee20bb81e5d04cb01e01a1cc 100644 --- a/main.c +++ b/main.c @@ -58,13 +58,15 @@ int perForceChoiceNotInC = NONE; // Initialized before each separation if modeEv int perChooseInCAtRandom = 1; // Choice in C at random int nbRunsSeparation = 30; // 1 or 5 +int maxTimeSeparation = 30; // test optilion 27/05: 80, 28/05: 60 int nbFlushes = 101; // default is 100, int ratioMin = 5; // min=5 max=55 int ratioMax = 55; // too small ratioMax stops the flush (>50) + int modeEvalSeparator = EVAL_CARD; // EVAL_SQRT_CARD EVAL_TREE_HEIGHT_COMPLETE_GRAPH EVAL_MINIMIZE_C EVAL_CARD EVAL_MIN_A_B double coeffHeightNbEdges = 2.0; // coefficient used to estimate the height for a given number of edges. Ponderates the evaluation against the cardinal of C. -int modeEvalAtRandom = 1; +int modeEvalAtRandom = 0; @@ -122,7 +124,7 @@ int main (int nargs, char ** args) noSwapsInFirstRuns = 0; printSolution = 1; printResult = 0; - time_limit = 1811; + time_limit = 1803; preliminaryGreedyDecomposition = 1; goto START_SOLVE; } @@ -208,6 +210,13 @@ int main (int nargs, char ** args) nbRunsSeparation = atoi(args[i]); } + else if (strcmp(args[i], "-max_time_sep") == 0) { + i ++; + if (i == nargs) + goto USAGE; + maxTimeSeparation = atoi(args[i]); + } + else if (strcmp(args[i], "-per_choice_AB") == 0) { i ++; if (i == nargs) @@ -268,12 +277,8 @@ int main (int nargs, char ** args) algo = GREEDY_ALGORITHM; } - else if (strcmp(args[i], "-separe") == 0) { // default + else if (strcmp(args[i], "-separe") == 0) { algo = SEPARE_AND_EXPLORE; - if ((i+1 < nargs) && (isdigit(args[i+1][0]))) { - i ++; - sizeSwitchToGreedy = atoi(args[i]); - } } @@ -307,10 +312,11 @@ START_SOLVE: return 0; USAGE: - printf("Usage :: ./treedepth [-file <file name>] [-runs <nb runs>] [-s <number>] [-trace] \\" - "[-save_solution <file name>] [-no_solution] [-improve] [-no_improve] [-no_pullup] [-no_swaps]\\" - "[-flushes <nb flushes>] [-per_choice_AB <per>] [-per_chrand_C <per>] [-sep_runs <nb runs>] \\" - "[-ratios <min> <max>] [-threshold <per>] [-eval <mode>] [-static_eval] [-dynamic_eval] \\" - "[-greedy] [-separe [<size to greedy>]] <file name>\n"); + printf("Usage :: ./treedepth [-file <file name>] [-greedy] [-separe] [-runs <nb runs>] [-s <number>] [-trace] \\" + "[-save_solution <file name>] [-no_solution] [-no_improve] [-no_pullup] [-no_swaps]\\" + "[-sep_runs <nb runs>] [-max_time_sep <duration>] [-flushes <nb flushes>] \\" + "[-per_choice_AB <per>] [-per_chrand_C <per>] \\" + "[-ratios <min> <max>] [-threshold <per>] [-eval <mode>] \\" + "[-greedy] [-separe]\n"); return 0; } diff --git a/main.h b/main.h index 9afcc066a6cd82eaf5d8285eabf70e8964db5cd8..aad01da1360fc9df7b89fea32ec7eae8508e94a2 100644 --- a/main.h +++ b/main.h @@ -9,8 +9,6 @@ #include <stdio.h> #include <time.h> -//#define PACE_2020 -#define TEST_PACE_2020 extern volatile sig_atomic_t stopSearch; @@ -31,6 +29,7 @@ extern int printResult; extern int nbRunsSeparation; +extern int maxTimeSeparation; extern int nbFlushes; extern int perForceChoiceNotInC; diff --git a/separator.c b/separator.c index 32a0564ac580b5f8619a21c8efc1e1aec69b2fc9..835fba6ce6dad1fb763db0018b28fda536cc8877 100644 --- a/separator.c +++ b/separator.c @@ -31,8 +31,6 @@ int useMinPartitions = 2; // 0: maintain heap, 1-2: just put min elements at the // 1: maintain mins 2: calculate mins only when necessary -int maxTimeSeparation = 120; - // // Datas structures @@ -80,11 +78,6 @@ int *component; // Warning: the preliminary call to initializeNbNeighbors() place first in the lists of neighbors // those that are in the current set S[]. It is then unnecessary to verify each time that the vertex // belongs to the current set. -// -// La separation suit une strategie d'effeuillage: on ne cherche pas a deplacer les sommets -// pour construire un bon ensemble, on cherche a enlever des morceaux un peu laches pour -// qu'il reste un noyeau dur. L'evaluation devrait dans cette optique favoriser la -// densite du noyeau restant (B pour flushBA) tout en minimisant la taille du separateur. #ifdef STATS_SEPARATION clock_t *timesSep = NULL; @@ -107,9 +100,6 @@ int searchSeparator(int *S, int n, SET V, Graph g, Separator theSeparator, int n nbCallsSearchSeparator ++; - int mode = modeEvalSeparator; - if (modeEvalSeparator == NONE) mode = rand()%3; - theSeparator->C->n = g->n+1; bestEval = -1.0; bestIsUninitialized = 1; @@ -119,6 +109,8 @@ int searchSeparator(int *S, int n, SET V, Graph g, Separator theSeparator, int n sizeMax = n * ratioMax / 100; + if ((g->n > 300000) && (depth < 6)) nbRunsSeparation = 1; // avoids WA ? + //saveNbNeighbors(S, n); if (modeEvalAtRandom) { @@ -140,11 +132,15 @@ int searchSeparator(int *S, int n, SET V, Graph g, Separator theSeparator, int n initSeparator(V, S, n, g, sep); - separe(S, n, V, g, sep, nFlushes, mode); + separe(S, n, V, g, sep, nFlushes, modeEvalSeparator); if ((stopSearch) || ((clock()-start)/CLOCKS_PER_SEC > maxTimeSeparation/(depth+1))) break; } + if (0 && depth < 3) printf("depth=%d tSep=%.1fs total=%.1fs\n", depth, + (float) (clock()-start)/CLOCKS_PER_SEC, + (float) (clock()-startTime)/CLOCKS_PER_SEC); + #ifdef STATS_SEPARATION timesSep[depth] += clock()-start; nbSearches[depth] ++; @@ -159,39 +155,12 @@ int searchSeparator(int *S, int n, SET V, Graph g, Separator theSeparator, int n else copySeparator(sep, theSeparator); - // This must not be done here the numbers of neighbors are not up to date - // Moreover the process is useless: when the best separator is built all vertices of C which have no neighbors - // in B are moved to A. If they had no neighbor in A next decomposition will discover unconnected components in A - //if (removeABDisconnectedVertices) - // selectABDisconnectedVertices(theSeparator, V, S, n, nbCallsSepare, g); - - if (verifyTheSeparator && (! verifySeparator(S, n, theSeparator))) exit(0); + //if (verifyTheSeparator && (! verifySeparator(S, n, theSeparator))) exit(0); return 1; } -#ifdef NOTDEF -An idea to start with good vertices before flushing -int essaiSeparator = 0; - if (essaiSeparator) { - heapSetCompare(C, isSmallerNeighborsInBthenA); - makeHeap(B); - makeHeap(C); - int t = rand()%nbMaxD, vertex = NONE; - for (int i = 0; ; i ++) - if (nbNeighborsInS[S[i]] == maxDegree) - if (t -- == 0) { vertex = S[i]; break; } - assert(vertex != NONE); - heapRemove(vertex, B); - heapInsert(vertex, C); - nbEdgesInB -= nbNeighborsInB[vertex]; - decreaseNbNeighborsInB(vertex, B, C, V, S, n, g); - - removeNeighborsFromB(vertex, A, B, C, V, S, n, g); - } -#endif - int chooseFirstVertex(int *S, int n, Graph g) { @@ -248,9 +217,6 @@ int separe(int *S, int n, SET V, Graph g, Separator s, int nbFlushs, int mode) { Heap B = s->B; Heap C = s->C; - // NOTE: should not maintain the heap source - // Should insert directly in destination the vertices that have no more neighbor in the source - for (int i = 0; i < nbFlushs; i ++) { if (useMinPartitions) { @@ -292,8 +258,7 @@ int separe(int *S, int n, SET V, Graph g, Separator s, int nbFlushs, int mode) { copySeparator(bestSep, s); - - if (0 && ! verifySeparator(S, n, s)) exit(0); + //if ( ! verifySeparator(S, n, s)) exit(0); return 1; } @@ -303,8 +268,6 @@ double evalSep(int nA, int nB, int nC, int mA, int mB, int mode, int direction) // Should consider here the particular cases (B->n=0, C->n=0,...) - // 1 / f(C) / g(a-b) ou / g(ma-mb) with - int min = (nA > nB) ? nB : nA; int max = (nA > nB) ? nA : nB; int delta = max-min; @@ -316,24 +279,11 @@ double evalSep(int nA, int nB, int nC, int mA, int mB, int mode, int direction) if (mode == EVAL_ESSAI) { // minimize C size while the numbers of constraints in A and B are small and closed - return (1.0 / (1+nC) / (1+nC) / sqrt(1.0+maxE-minE)); - return (sqrt((double) (nbEdgesInS - mA - mB)) / (1+nC) / (1+nC) / sqrt(1.0+maxE-minE)); - double c = 2.0 - 1.0 / pow(2, 1.0+maxE-minE); - return (1.0 / (1+nC) / (1+nC) / c); - - // evaluate tree height considering the density - //double densityA = (mA <= 1) ? 1.0 : (double) mA * 2 / A->n / (A->n-1); - //double densityB = (mB <= 1) ? 1.0 : (double) mB * 2 / B->n / (B->n-1); - double degreeA = (mA <= 1) ? 1.0 : (double) mA * 2 / nA; - double degreeB = (mB <= 1) ? 1.0 : (double) mB * 2 / nB; - double hA = sqrt((double) 2*mA) * (1.0 - pow(2, -1-degreeA)); - double hB = sqrt((double) 2*mB) * (1.0 - pow(2, -1-degreeB)); - return (1.0 / (nC + ((hA > hB) ? hA : hB))); // bof } if (mode == EVAL_TREE_HEIGHT_COMPLETE_GRAPH) - // 1/ approx tree height + // approx tree height return (1.0 / (nC + sqrt((double) (coeffHeightNbEdges * maxE )))); @@ -343,18 +293,14 @@ double evalSep(int nA, int nB, int nC, int mA, int mB, int mode, int direction) double rab = sqrt((double) (nA + nB)); double deltaSqrt = (ra > rb) ? (ra - rb) : (rb - ra); if (mode == EVAL_0) return ((rab - deltaSqrt)*(rab - deltaSqrt) / (1+nC) / (1+nC)); - if (nC > 0) - return ((rab - deltaSqrt) / nC / nC); - //return ((rab - deltaSqrt) / C->n / C->n ); + if (nC > 0) return ((rab - deltaSqrt) / nC / nC); return ((rab - deltaSqrt) / (1+nC)); - //return ((rab-deltaSqrt)*(rab-deltaSqrt)/C->n); } if (mode == EVAL_CARD) return ((double) (min) / (nC+1)); // modified 1/05 - //if (mode == EVAL_CARD) return ((C->n > 0) ? (double) (A->n+B->n-delta) / C->n : A->n+B->n+1); // heur_095.gr 3417 13667 h=13 4.07s 10 runs if (mode == EVAL_LEVEL_DENSITY) { - // The idea: evaluate the cost to place vertices of C and the smallest among A and B + // evaluate the cost to place vertices of C and the smallest among A and B // evaluating the number of vertices of these sets per level if (nA < nB) return ((double) (nA+nC) / (nC + sqrt(sqrt((double) 2.0*mB)))); else return ((double) (nB+nC) / (nC + sqrt(sqrt((double) 2.0*mA))) ); @@ -374,8 +320,6 @@ double evalSep(int nA, int nB, int nC, int mA, int mB, int mode, int direction) return 2.0 * mA / (nA - 1) / (nA - 1) / (nC + 1) / (nC + 1); } - - // few vertices if (nA+nB+nC <= 7) return ((nC > 0) ? 1.0 / (1+delta) / (1+delta) / nC : 1.0 / (1+delta)); @@ -402,8 +346,7 @@ int chooseEltInC(Heap C) { int e = C->val[rand() % (C->n)]; return e; } - //if (( ! chooseInCAtRandom) || (rand() % 100 >= perChooseInCAtRandom)) - return C->val[0]; //heapExtractMin(C); the vertex that has the fewer neighbors in the from set + return C->val[0]; // the vertex that has the fewer neighbors in the from set } @@ -422,7 +365,6 @@ int chooseEltInB(Heap B) { if (choiceModeInAandB == CHOICE_AB_MIN_AB_MAX_C) { // Search a vertex in B with minimal number of neighbors in B and max in C. - // The process works also when the vertices with the min number of neighbors are packed first in B int best = B->val[0]; int nbBMin = nbNeighborsInB[B->val[0]]; int nbCMax = nbNeighborsInS[B->val[0]] - nbNeighborsInB[B->val[0]]; @@ -467,12 +409,6 @@ int chooseEltInA(Heap A) { } -void printDebugB(Heap B) { - printf("B: min=%d nbmin=%d :: ", B->min, B->nbmin); - for (int i = 0; i < B->n; i ++) printf("%d/%d ", B->val[i], nbNeighborsInB[B->val[i]]); - printf("\n"); -} - int testSourceConnected = 0; int thresholdConComponents = 13; @@ -520,7 +456,7 @@ void flushBtoA(Heap A, Heap B, Heap C, SET V, int S[], int n, int mode, int seed if (A->n >= sizeMax) break; - if (B->n < sizeMin) break; // useless ? + if (B->n < sizeMin) break; if (A->n >= sizeMin) { int nB = B->n, nEB = nbEdgesInB; @@ -537,7 +473,7 @@ void flushBtoA(Heap A, Heap B, Heap C, SET V, int S[], int n, int mode, int seed double e = evalSep(A->n, nB, C->n, nbEdgesInA, nEB, mode, FLUSH_B_A); if ((bestIsUninitialized) || (e > bestEval)) { - // There can be vertices in C with no neighbor in B that must be poured in A + // There can be vertices in C with no neighbor in B if (1) pourCintoA(A, nbNeighborsInB, nbNeighborsInA, &nbEdgesInA, C, g, 1); bestIsUninitialized = 0; bestEval = e; @@ -568,7 +504,7 @@ void flushAtoB(Heap A, Heap B, Heap C, SET V, int S[], int n, int mode, Graph g) int e = NONE; int bestBSize = NONE; - while (1) { // (B->n < A->n) + while (1) { int sizeA = A->n; @@ -601,7 +537,7 @@ void flushAtoB(Heap A, Heap B, Heap C, SET V, int S[], int n, int mode, Graph g) if (B->n >= sizeMax) break; - if (A->n < sizeMin) break; // 25/05: If there are few vertice in A and B + if (A->n < sizeMin) break; // 25/05 if (B->n >= sizeMin) { int nA = A->n, nEA = nbEdgesInA; @@ -704,7 +640,6 @@ void removeNeighborsFromB(int e, Heap A, Heap B, Heap C, SET V, int *S, int n, G if ((nbToThrow == 0) || (C->n == 0) || (B->n <= 1)) return; - //for (int *p = g->lists[e]; p-g->lists[e] < nbNeighborsInS[e]; p ++) for (int *p = verticesToThrow; p < verticesToThrow+nbToThrow; p ++) { if ((C->n == 0) || (B->n <= 1)) return; @@ -919,7 +854,6 @@ int compareCVerticesFlushAtoB(int a, int b) { // void pourCintoA(Heap A, int nbNFrom[], int nbNTo[], int *nbEdges, Heap C, Graph g, int justAdd) { - // move isolated vertices from C to A for (int i = 0; i < C->n; i++) { int e = C->val[i]; if (nbNFrom[e] == 0) { diff --git a/swaps.c b/swaps.c index 63f36df2212c436661d642ee053c6e9e2476aff3..7cd3fd703140dddef3b5d95941c3119bc19341b1 100644 --- a/swaps.c +++ b/swaps.c @@ -66,12 +66,6 @@ int nbCallsPrune = 0; int date = 0; - - -#define NEW_PU_WITH_DATES - - - void exploreAndUpdateSetOfNodes(Node p, SET V, int date, int dates[]) { if (dates[p->vertex] == date) { addSet(p->nodes, V); @@ -116,16 +110,10 @@ int pullUpIndependentSubtreesInTheBranch(Node root, Node from, int date, Graph g if ((datePulledUp[q->vertex] == date) || (q->height+1 < p->height)) { prev = q; q = next; continue; } // Can jump some neighbors here (not counted in nbNUnder) if ((q->nodes == NULL) || (dateNodesSet[q->vertex] != date)) { -#ifdef NEW_PU_WITH_DATES if (q->nodes == NULL) q->nodes = allocSet(g->n); else clearSet(q->nodes); exploreAndUpdateSetOfNodes(q, q->nodes, date, dateNodesSet); dateNodesSet[q->vertex] = date; -#else - if (q->nodes == NULL) q->nodes = allocSet(g->n); - exploreAndBuildSetOfNodes(q, q->nodes); - dateNodesSet[q->vertex] = date; -#endif } int nb = hasNeighborsInSubtree(p->vertex, q->nodes, g); @@ -141,20 +129,16 @@ int pullUpIndependentSubtreesInTheBranch(Node root, Node from, int date, Graph g if (prev == NULL) p->fbs = q->next; else prev->next = q->next; q->next = NULL; -#ifdef NEW_PU_WITH_DATES dateNodesSet[p->vertex] = NONE; -#endif //if (p->height == q->height+1) { p->nbhmax --; if (p->nbhmax == 0) initializeHeight(p); } - // 2. search destination (do not consider to put q as the new root + // 2. search destination (do not consider to put q as the new root => loops) Node dest = p->father; int up = 1; while (dest != root) { if ( ! hasNoNeighborInSet(dest->vertex, q->nodes, g)) break; -#ifdef NEW_PU_WITH_DATES dateNodesSet[dest->vertex] = NONE; -#endif dest = dest->father; up ++; } @@ -179,8 +163,6 @@ int pullUpIndependentSubtreesInTheBranch(Node root, Node from, int date, Graph g else prev = q; - //assert(g->n == sizeTree(root)); - nbNUnder -= nb; q = next; } @@ -191,27 +173,25 @@ int pullUpIndependentSubtreesInTheBranch(Node root, Node from, int date, Graph g nbMoves += nbPU; p = p->father; } - //if ( ! verifyDecomposition(root, g)) exit(0); return nbMoves; } Node pullUpIndependentSubtreesInTree(Node root, Graph g) { - int nbPullUp; - int height1; - do { - date ++; - height1 = root->height; - //criticalNode = markCriticalBranch(root, date, 1, g); + date ++; + + while (1) { + int prevHeight = root->height; + // criticalNode = markCriticalBranch(root, date, 1, g); Node deepest = leftmostDeepestNode(root); - nbPullUp = pullUpIndependentSubtreesInTheBranch(root, deepest, date, g); - if (nbPullUp > 0) updateDepthsAndHeights(root, 0, 0); // Useless ? + int nbPullUp = pullUpIndependentSubtreesInTheBranch(root, deepest, date, g); + if ((clock()-startTime)/CLOCKS_PER_SEC >= time_limit) stopSearch = 1; if (stopSearch) break; -//if (nbPullUp > 0) printf("%d pulled up\n", nbPullUp); - } while (root->height < height1); - - updateBestDecomposition(root, g); + if (nbPullUp <= 0) break; + updateDepthsAndHeights(root, 0, 0); // Useless ? + if (0) printf("nbPU=%d %d --> %d\n", nbPullUp, prevHeight, root->height); + } return root; } @@ -264,30 +244,25 @@ Node makeSwapsInCriticalBranch(Node root, Graph g) { updateDepthsAndHeights(root, 0, 0); if (pullUpIndependentSubtrees) { - int nbPullUp, height1; PULL_UP: - if (trace) printf("start pull up %.1fs\n", (float) (clock()-startTime)/CLOCKS_PER_SEC); -#ifdef NEW_PU_WITH_DATES + root = pullUpIndependentSubtreesInTree(root, g); + +#ifdef NOTDEF date ++; -#endif + while (1) { -#ifndef NEW_PU_WITH_DATES - date ++; -#endif - height1 = root->height; + int prevHeight = root->height; // criticalNode = markCriticalBranch(root, date, 1, g); Node deepest = leftmostDeepestNode(root); - nbPullUp = pullUpIndependentSubtreesInTheBranch(root, deepest, date, g); - + int nbPullUp = pullUpIndependentSubtreesInTheBranch(root, deepest, date, g); if ((clock()-startTime)/CLOCKS_PER_SEC >= time_limit) stopSearch = 1; if (stopSearch) break; if (nbPullUp <= 0) break; - updateDepthsAndHeights(root, 0, 0); // Useless ? - if (trace) printf("nbPU=%d %d --> %d\n", nbPullUp, height1, root->height); + if (trace) printf("nbPU=%d %d --> %d\n", nbPullUp, prevHeight, root->height); } - //while (root->height < height1); +#endif updateBestDecomposition(root, g); } @@ -297,8 +272,6 @@ Node makeSwapsInCriticalBranch(Node root, Graph g) { if ( ! searchSwapsInCriticalBranch) goto TERMINATE; - if (trace) printf("start swaps %.1fs\n", (float) (clock()-startTime)/CLOCKS_PER_SEC); - int nbSwapsCompleted = 0; int height = root->height; while (1) { @@ -385,10 +358,6 @@ int selectSwaps(int *nodes, int *corr, int nb, int maxLen) { } -/* - * Idea 1: perform swaps of length 1, then length 2, .... - * Idea 2: only consider depths 90-100, then 80-100, then 70-100,... - */ #define SEARCH_FROM_ROOT @@ -727,7 +696,8 @@ int verifyCriticalBranch(Node root, Node cc, int date, Graph g) { // Calculate the lowest node of the critical path such that under this node there is no neighbors of node Node searchCriticalCorrespondant(Node node, int *maxHeight, int date, int store, Graph g) { - int vertex = node->vertex; +// Node searchCriticalCorrespondant(Node node, int treeHeight, int gainMin, int *maxHeight, int date, int store, Graph g) { + int vertex = node->vertex; int maxHeightDepSubtree = 0; // the maximal height of the subtrees that are dependent with vertex Node *ccc = dependentSubtrees; @@ -760,6 +730,7 @@ Node searchCriticalCorrespondant(Node node, int *maxHeight, int date, int store, if (the->height > maxHeightDepSubtree) maxHeightDepSubtree = the->height; } + // if (cc->depth + maxHeightDepSubtree + gainMin >= treeHeight) return NULL; } *ccc = NULL; *maxHeight = maxHeightDepSubtree; @@ -770,429 +741,6 @@ Node searchCriticalCorrespondant(Node node, int *maxHeight, int date, int store, -// -// useless -// - - - - -Node searchCriticalCorrespondantV2OLD(Node node, int nNgb, int *maxHeight, int date, int store, Graph g) { - int vertex = node->vertex; - int maxHeightDepSubtree = 0; // the maximal height of the subtrees that are dependent with vertex - - - Node p = node; - while (nNgb > 0) { - - Node q = p->fbs->next; // ignore the child corresponding to the critical path - while (q != NULL) { - if (q->nodes == NULL) { - q->nodes = allocSet(g->n); - exploreAndBuildSetOfNodes(q, q->nodes); // do not recalculate if q->nodes != NULL ? - } - int nb = hasNeighborsInSubtree(vertex, q->nodes, g); - if (nb > 0) { - if (q->height > maxHeightDepSubtree) maxHeightDepSubtree = q->height; - } - nNgb -= nb; - q = q->next; - } - - p = p->fbs; - - if (isInSet(p->vertex, NULL, g->lists[vertex], g->nadj[vertex])) { - if (maxHeightDepSubtree == 0) maxHeightDepSubtree = 1; - nNgb--; - } - - if (p == criticalNode) break; // should consider also critical node and its subtrees - } - - if (nNgb > 0) - return NULL; - - *maxHeight = maxHeightDepSubtree; - return p; -} - - -Node swapCriticalNodeWithNodesSets(Node root, Node node, Node cc, Graph g) { - // We suppose that children of node are dependent with node (in the other case they should have been pulled up) - // then the first child of node (critical) is pulled up, all the other stay with node - int vertex = node->vertex; - Node father = node->father; - Node substitute = node->fbs; - Node p; - - nbCallsSwapNode ++; - - int trace = 0; - - if (with_assertions) assert(cc != node); - if (cc == node) return root; - - if (trace) printf("swap %d@%d h%d -- %d@%d h%d\n", node->vertex, node->depth, node->height, cc->vertex, cc->depth, cc->height); - - if (0) { - // 0. Verify that node has not loose subtrees. - // NOTE: this occurs when a previous swap has moved a subtree that contains a neighbor of node, - // when swaps are not disjoint. - p = cc; - int nbSubtr = 0; - while (1) { - Node q = p->fbs->next; // the first child is the critical node, it can be ignored - while (q != NULL) { - //buildSetOfNodes(q, g); - if (hasNeighborsInSubtree(vertex, q->nodes, g)) - nbSubtr++; - q = q->next; - } - if (p == node) break; - p = p->father; - } - if (nbSubtr != nbSubtrees[vertex]) { - nbIgnoredSwaps++; - return root; - } - } - - - // 1. remove node and his dependent children, and pull up the critical child of node. - // We do not suppose that node subtrees are all dependent (should use pullUpIndependentSubtrees() for this) - Node siblings = node->next; // add children of node that are not dependent with node to siblings. - Node q = substitute->next; - node->fbs = NULL; - while (q != NULL) { - Node next = q->next; - if (hasNeighborsInSubtree(vertex, q->nodes, g)) { - // add as a child of node - if (trace) printf("[%d] move subtree node=%d h=%d / father=%d\n", q->depth, q->vertex, q->height, cc->vertex); - q->next = node->fbs; - node->fbs = q; - q->father = node; - } - else { - // add as first node in siblings - q->next = siblings; - siblings = q; - q->father = father; - } - q = next; - } - substitute->next = siblings; - - if (trace) printf("pull up node: %d @ %d h=%d --> child of %d\n", substitute->vertex, substitute->depth, substitute->height, father->vertex); - - // attach substitute to the father if any - if (father != NULL) - father->fbs = substitute; - else { - // if node is the root then the substitute becomes the root - root = substitute; - substitute->father = NULL; - if (root->next != NULL) { - Node q = root->next; - while (q != NULL) { - if (hasNeighborsInSubtree(vertex, q->nodes, g)) { printf("root dependent subtree\n"); exit(0); } - q = q->next; - } - // node had indepedent subtrees that become siblings of the new root. - Node pp = root->fbs; - while (pp->next != NULL) pp = pp->next; - pp->next = root->next; - pp = pp->next; - while (pp != NULL) { - pp->father = root; - pp = pp->next; - } - root->next = NULL; - } - } - substitute->father = father; - - - - // 2. get subtrees on the critical branch which are dependent with vertex, and add them as - // children of node. - p = substitute; - int depth = 0; - while (1) { - // add all children of p which are dependent with vertex as children of node - Node prev = p->fbs; // fbs is the critical child - if (with_assertions) assert (prev != NULL); - Node q = p->fbs->next; - while (q != NULL) { - if (q->nodes == NULL) { - // This can occur when all node neighbors have been already discovered - q->nodes = allocSet(g->n); - exploreAndBuildSetOfNodes(q, q->nodes); - } - if (hasNeighborsInSubtree(vertex, q->nodes, g)) { - // remove q from list and add as a child of node - if (trace) printf("[%d] move subtree node=%d h=%d / father=%d\n", - q->depth, q->vertex, q->height, p->vertex); - prev->next = q->next; - q->next = node->fbs; - node->fbs = q; - q->father = node; - } - else - prev = q; - q = prev->next; - } - if (p == cc) break; // the critical correspondant may have a subtree dependent of vertex - p = p->fbs; - depth ++; - } - - - - // 3. add node as a new child of cc - if (with_assertions) assert(cc->fbs != NULL); - node->next = cc->fbs->next; - cc->fbs->next = node; - node->father = cc; - - - - // 4. update heights, depths and sets of nodes - - // heights :: normally only the height of p and the heights from father to root can change. - // depths :: on the critical branch the depths loose one for all the nodes under father (correspondent comprised), - // and the depth of node becomes depth(corresp)+1, and its subtrees can also be updated (what is the usefulness of depth ?) - // sets of nodes :: sets of nodes of the children of the nodes of the critical path, not comprised the critical path, - // must be uptodate. The ones that have changed are node (the child of corresp) - - // update node (height and set of nodes) - if (node->nodes == NULL) node->nodes = allocSet(g->n); - clearSet(node->nodes); - node->height = 1; - node->depth = cc->depth; // cc->depth+1, but cc will be pulled up - p = node->fbs; - while (p != NULL) { - addSet(p->nodes, node->nodes); - if (p->height+1 > node->height) { - node->height = p->height + 1; - node->nbhmax = 1; - } else if (p->height+1 == node->height) - node->nbhmax ++; - p = p->next; - } - - changeCriticalNode = (node->height == cc->height-1); - - // update depth on branch criticalNode-cc - p = criticalNode; - while (p != cc) { - p->depth --; - //printf(" change depth %d : %d -> %d\n", p->vertex, p->depth+1, p->depth); - p = p->father; - } - - // p=cc, cc update - if (p->height < node->height+1) p->height = node->height+1; - p->depth --; - p = p->father; - - // update depth for nodes between cc and father (normally their heights do not change) - while (p != father) { - p->depth --; - p = p->father; - } - - // nodes from father to root should be smaller - while (p != NULL) { - p->height --; - if ( ! changeCriticalNode) { - // verify that there is not another child with max height, in which case the critical node changes - Node q = p->fbs->next; - while (q != NULL) { - if (q->height + 1 == p->height) changeCriticalNode = 1; - q = q->next; - } - } - p = p->father; - } - - if (with_assertions) { - if (father == NULL) assert(root->depth == 0); - else assert(substitute->depth == father->depth+1); - } - - if (trace) { - //printTree(father); - printf("AFTER swap %d@%d h%d -- %d@%d h%d father %d@%d h%d\n", node->vertex, node->depth, node->height, - cc->vertex, cc->depth, cc->height, father->vertex, father->depth, father->height); - } - return root; -} - - - - -void makeSetsOfNodesInCriticalBranch(Node node, Graph g) { - while (node != NULL) { - assert(node->fbs->height +1 == node->height); - Node p = node->fbs->next; - while (p != NULL ) { - if (p->nodes == NULL) p->nodes = allocSet(g->n); - else clearSet(p->nodes); - exploreAndBuildSetOfNodes(p, p->nodes); - p = p->next; - } - node = node->father; - } -} - - - - -// node is in the critical path. Determine if node can be swapped. cp is the bottom of the critical path -Node searchCriticalCorrespondantOLD(Node node, Node cp, SET cpNodes, Graph g) { - int vertex = node->vertex; - - // At least the node must have no neighbor in the subtree that terminates the critical path - if (hasNeighborsInSubtree(vertex, cpNodes, g)) - return NULL; - - // Search the critical correspondant of node: the lowest node ** of the critical path ** - // such that either itsef or one of its children is dependent with node. - // Then the critical subtree of cc is independent with vertex and can be pulled up. - Node p = cp->father; - // built sets of nodes for all nodes of the critical path and their children, - while (p != node) { - buildSetOfNodes(p, g); - if (hasNeighborsInSubtree(vertex, p->nodes, g)) - break; - p = p->father; - } - -#ifdef NOTDEF - // consider each child of p. Technique above is simpler - while (p != node) { - if (areNeighbours(vertex, p->vertex, g)) - break; - - Node q = p->fbs->next; // p->fbs is the node of the critical branch - // Search a child dependent with vertex - while (q != NULL) { - buildSetOfNodes(q, g); - if (hasNeighborsInSubtree(vertex, q->nodes, g)) - break; - q = q->next; - } - if (q != NULL) - break; - p = p->father; - } -#endif - - if (p == node) - return NULL; - - return p; -} - - -int listSwapsOLD(Node root, Graph g) { - - gainMax = 0; - lenMin = g->n+1; - int nbSwaps = 0; - - int depth = depthCC-1; - for (Node p = criticalNode->father; p != NULL; p = p->father, depth--) { - - if (stopSearch) - return 0; - - if (nbDeeperN[p->vertex] > limitNbDeepestNeighbors) - continue; - - // Search the critical correspondant of p and verifies if the swap is efficient - Node cc = searchCriticalCorrespondantOLD(p, criticalNode, criticalNode->nodes, g); - - if (cc != NULL) { - int gain = evaluateSwap(p, cc, g); - - if (gain <= 0) continue; - - if (gain > gainMax) { - gainMax = gain; - bestNode = p; - } - - swapGain[p->vertex] = gain; - swapLength[p->vertex] = cc->depth - p->depth; - if (swapLength[p->vertex] < lenMin) lenMin = swapLength[p->vertex]; - swapsVertices[nbSwaps] = p->vertex; - correspondent[p->vertex] = cc->vertex; - nbSwaps ++; -#ifdef NOTDEF - if (gain > gainMax) { - swapsVertices[0] = p->vertex; - swapsCorrespondents[p->vertex] = cc->vertex; - nbSwaps = 1; - gainMax = gain; - lenMin = swapLength[p->vertex]; - bestNode = p; - //if (depth < 80*depthCC/100 ) break; // make first positive swap to limit cost - } - else if (gain == gainMax) { - swapsVertices[nbSwaps] = p->vertex; - swapsCorrespondents[p->vertex] = cc->vertex; - if (swapLength[p->vertex] < lenMin) lenMin = swapLength[p->vertex]; - nbSwaps ++; - } -#endif - } - } - return nbSwaps; -} - - - -// Goes up starting from the critical correspondant, evaluating the move of the subtrees -// that are dependent of node (and should be set as new children for the node if the swap is performed). -int evaluateSwap(Node node, Node cc, Graph g) { - int maxHeight = cc->height-1; // the height the subtrees must not reach for the swap to be positive - Node p; - int vertex = node->vertex; - int gain = node->height+1; // the smallest difference with the maxHeight for dependent subtrees - - nbSubtrees[vertex] = 0; - p = cc; - while (1) { - - Node q = p->fbs->next; // the first child is the critical node, it can be ignored - while (q != NULL) { - buildSetOfNodes(q, g); - if (hasNeighborsInSubtree(vertex, q->nodes, g)) { - if (q->height >= maxHeight) - return 0; - if (maxHeight - q->height < gain) - gain = maxHeight - q->height; - nbSubtrees[vertex] ++; - } - q = q->next; - } - - if ((clock()-startTime)/CLOCKS_PER_SEC >= time_limit) { - stopSearch = 1; - return 0; - } - - if (p == node) break; - maxHeight --; - p = p->father; - } - return gain; -} - - - -