|
Go to the documentation of this file.
38 #define CHUNK_SIZE (64)
39 #define CLIQUEHASH_INITSIZE (1024)
78 assert(clique != NULL);
84 for( i = 0; i < nnodes; ++i )
90 for( j = i; j > 0 && node < (*clique)->nodes[j-1]; --j )
91 (*clique)->nodes[j] = (*clique)->nodes[j-1];
92 (*clique)->nodes[j] = node;
94 (*clique)->nnodes = nnodes;
103 assert(clique != NULL);
104 assert(*clique != NULL);
125 assert(clique1 != NULL);
126 assert(clique2 != NULL);
130 clique2smaller = FALSE;
131 while( pos1 < clique1->nnodes && pos2 < clique2->nnodes )
133 if( clique1->nodes[pos1] < clique2->nodes[pos2] )
138 return (clique2smaller ? +1 : -1);
140 else if( clique1->nodes[pos1] > clique2->nodes[pos2] )
146 clique2smaller = TRUE;
156 if( pos1 < clique1->nnodes )
157 return (clique2smaller ? +1 : -1);
172 assert(cliquehash != NULL);
174 for( i = 0; i < cliquehash->ncliques-1; ++i )
175 assert( compSubcliques(cliquehash->cliques[i], cliquehash->cliques[i+1]) < 0);
178 #define checkCliquehash(cliquehash)
188 assert(cliquehash != NULL);
189 assert(tablesize > 0);
193 (*cliquehash)->cliquessize = tablesize;
194 (*cliquehash)->ncliques = 0;
205 assert(cliquehash != NULL);
208 for( i = 0; i < cliquehash->ncliques; ++i )
211 cliquehash->ncliques = 0;
220 assert(cliquehash != NULL);
221 assert(*cliquehash != NULL);
238 assert(cliquehash != NULL);
240 if( num > cliquehash->cliquessize )
244 newsize = 2*cliquehash->cliquessize;
249 cliquehash->cliquessize = newsize;
251 assert(cliquehash->cliquessize >= num);
257 void printCliquehash(
263 assert(cliquehash != NULL);
265 debugMessage( "cliquehash (%d cliques):\n", cliquehash->ncliques);
266 for( i = 0; i < cliquehash->ncliques; ++i )
271 for( j = 0; j < cliquehash->cliques[i]->nnodes; ++j )
272 debugPrintf( " %d", cliquehash->cliques[i]->nodes[j]);
291 assert(cliquehash != NULL);
292 assert(cliquehash->cliquessize > 0);
293 assert(clique != NULL);
294 assert(insertpos != NULL);
298 right = cliquehash->ncliques-1;
299 while( left <= right )
301 middle = (left+right)/2;
316 for( middle = left-1; middle >= 0; --middle )
337 assert(cliquehash != NULL);
338 assert(clique != NULL);
339 assert(0 <= insertpos && insertpos <= cliquehash->ncliques);
345 for( i = cliquehash->ncliques; i > insertpos; --i )
346 cliquehash->cliques[i] = cliquehash->cliques[i-1];
347 cliquehash->cliques[insertpos] = clique;
348 cliquehash->ncliques++;
353 debug(printCliquehash(cliquehash));
371 int maxnzeroextensions,
381 assert(selectadjnodes != NULL);
382 assert(buffer != NULL);
383 assert(Vzero != NULL);
384 assert(curcliquenodes != NULL);
385 assert(ncurcliquenodes != NULL);
387 debugMessage( "extending temporary clique (size %d) with zero-weighted nodes (nVzero=%d)\n", *ncurcliquenodes, nVzero);
389 if( maxnzeroextensions == 0 )
398 for( i = 0; i < *ncurcliquenodes && nzerocands > 0; ++i )
400 nzerocands = selectadjnodes(tcliquegraph, curcliquenodes[i], zerocands, nzerocands, zerocands);
405 while( nzerocands > 0 )
408 curcliquenodes[*ncurcliquenodes] = zerocands[0];
409 (*ncurcliquenodes)++;
413 if( nzeroextensions >= maxnzeroextensions )
417 nzerocands = selectadjnodes(tcliquegraph, curcliquenodes[(*ncurcliquenodes)-1], zerocands, nzerocands, zerocands);
435 int maxnzeroextensions,
440 int* nmaxcliquenodes,
449 assert(curcliquenodes != NULL);
450 assert(maxcliquenodes != NULL);
451 assert(nmaxcliquenodes != NULL);
452 assert(maxcliqueweight != NULL);
453 assert(curcliqueweight > *maxcliqueweight);
454 assert(stopsolving != NULL);
455 assert(newsol == NULL || cliquehash != NULL);
458 *stopsolving = FALSE;
465 if( cliquehash->ncliques > 0 )
468 acceptsol = ! inCliquehash(cliquehash, clique, &insertpos);
477 curcliquenodes, &ncurcliquenodes);
482 newsol(tcliquedata, curcliquenodes, ncurcliquenodes, curcliqueweight, maxcliqueweight, &acceptsol, stopsolving);
494 assert(insertpos == 0);
495 assert(cliquehash->ncliques == 0);
514 *nmaxcliquenodes = ncurcliquenodes;
515 if( curcliqueweight > *maxcliqueweight )
516 *maxcliqueweight = curcliqueweight;
520 debugMessage( " -> clique %s (weight %d):", acceptsol ? "accepted" : "rejected", curcliqueweight);
523 for( i = 0; i < ncurcliquenodes; ++i )
540 int* ntmpcliquenodes,
546 assert(getweights != NULL);
547 assert(isedge != NULL);
548 assert(tcliquegraph != NULL);
550 assert(0 <= nV && nV <= 2);
551 assert(apbound != NULL);
552 assert(tmpcliquenodes != NULL);
553 assert(ntmpcliquenodes != NULL);
554 assert(tmpcliqueweight != NULL);
556 weights = getweights(tcliquegraph);
557 assert(nV == 0 || weights[V[0]] > 0);
558 assert(nV <= 1 || weights[V[1]] > 0);
561 apbound[0] = weights[V[0]];
563 apbound[1] = weights[V[1]];
566 if( nV >= 2 && isedge(tcliquegraph, V[0], V[1]) )
568 assert(isedge(tcliquegraph, V[1], V[0]));
571 tmpcliquenodes[0] = V[0];
572 tmpcliquenodes[1] = V[1];
573 *ntmpcliquenodes = 2;
574 *tmpcliqueweight = weights[V[0]] + weights[V[1]];
575 apbound[0] += weights[V[1]];
577 else if( nV >= 2 && weights[V[1]] > weights[V[0]] )
580 tmpcliquenodes[0] = V[1];
581 *ntmpcliquenodes = 1;
582 *tmpcliqueweight = weights[V[1]];
587 tmpcliquenodes[0] = V[0];
588 *ntmpcliquenodes = 1;
589 *tmpcliqueweight = weights[V[0]];
593 *tmpcliqueweight = 0;
594 *ntmpcliquenodes = 0;
614 int* ntmpcliquenodes,
618 assert(tmpcliqueweight != NULL);
624 reduced(getweights, isedge, tcliquegraph, V, nV, apbound, tmpcliquenodes, ntmpcliquenodes, tmpcliqueweight);
625 return *tmpcliqueweight;
630 return tcliqueColoring(getnnodes, getweights, selectadjnodes, tcliquegraph,
631 mem, buffer, V, nV, gsd, iscolored, apbound,
632 tmpcliquenodes, ntmpcliquenodes, tmpcliqueweight);
647 assert(apbound != NULL);
652 for( i = 0 ; i < nV; i++ )
654 assert(apbound[i] > 0);
655 if( apbound[i] >= maxapbound )
657 maxapbound = apbound[i];
682 assert(apbound != NULL);
687 for( i = 0 ; i < nV; i++ )
689 assert(apbound[i] > 0);
690 assert(weights[V[i]] > 0);
692 if( apbound[i] >= maxapbound && weights[V[i]] <= maxweight )
694 maxapbound = apbound[i];
727 int* nmaxcliquenodes,
730 int* ncurcliquenodes,
738 int maxnzeroextensions,
753 assert(getnnodes != NULL);
754 assert(getweights != NULL);
755 assert(selectadjnodes != NULL);
759 assert(iscolored != NULL);
761 assert(maxcliqueweight != NULL);
762 assert(curcliquenodes != NULL);
763 assert(ncurcliquenodes != NULL);
764 assert(curcliqueweight != NULL);
765 assert(ntreenodes != NULL);
766 assert(maxfirstnodeweight >= 0);
767 assert(*ntreenodes >= 0);
768 assert(maxntreenodes >= 0);
769 assert(status != NULL);
774 debugMessage( "(level %d, treenode %d) maxclique = %d, curclique = %d [mem=%lld (%lld), cliques=%d]\n",
775 level, *ntreenodes, *maxcliqueweight, *curcliqueweight,
778 debugMessage( " -> current branching (weight %d):", weightK);
779 for( i = 0; i < level; ++i )
783 for( i = 0; i < nV; ++i )
787 if( *ntreenodes > maxntreenodes )
793 weights = getweights(tcliquegraph);
794 backtracklevel = INT_MAX;
802 subgraphweight = boundSubgraph(getnnodes, getweights, isedge, selectadjnodes, tcliquegraph,
803 mem, buffer, V, nV, gsd, iscolored, apbound,
804 tmpcliquenodes, &ntmpcliquenodes, &tmpcliqueweight);
808 for( i = 0; i < nV; ++i )
810 assert(0 <= V[i] && V[i] < getnnodes(tcliquegraph));
811 assert(i == 0 || V[i-1] < V[i]);
812 assert(apbound[i] >= 0);
813 assert((apbound[i] == 0) == (weights[V[i]] == 0));
821 if( weightK + tmpcliqueweight > *curcliqueweight && (level > 0 || fixednode == -1) )
824 for( i = 0; i < level; ++i )
825 curcliquenodes[i] = K[i];
826 for( i = 0; i < ntmpcliquenodes; ++i )
827 curcliquenodes[level+i] = tmpcliquenodes[i];
828 *ncurcliquenodes = level + ntmpcliquenodes;
829 *curcliqueweight = weightK + tmpcliqueweight;
832 debugMessage( " -> new current clique with weight %d at node %d in level %d:",
833 *curcliqueweight, *ntreenodes, level);
834 for( i = 0; i < *ncurcliquenodes; ++i )
845 if( weightK + subgraphweight > *maxcliqueweight && (nV > 2 || (fixednode >= 0 && level == 0)) )
861 weightKold = weightK;
863 debugMessage( "============================ branching level %d ===============================\n", level);
866 while( backtracklevel >= level && nValive > 0 )
871 if( level > 1 && backtrackfreq > 0 && (*ntreenodes) % backtrackfreq == 0 )
878 if( level == 1 && fixednode >= 0 )
881 for( branchidx = 0; branchidx < nValive && V[branchidx] != fixednode; branchidx++ )
883 assert(branchidx < nValive);
884 assert(V[branchidx] == fixednode);
886 else if( level == 1 && maxfirstnodeweight > 0 )
892 assert(0 <= branchidx && branchidx < nValive && nValive <= nV);
893 assert(apbound[branchidx] > 0);
894 assert(weights[V[branchidx]] > 0);
897 if( (weightKold + apbound[branchidx]) <= *maxcliqueweight )
900 debugMessage( "%d. branching in level %d (treenode %d): bidx=%d, node %d, weight %d, upperbound: %d+%d = %d, maxclique=%d\n",
901 nV-nValive+1, level, *ntreenodes, branchidx, V[branchidx], weights[V[branchidx]], weightKold,
902 apbound[branchidx], weightKold + apbound[branchidx], *maxcliqueweight);
910 branchingnode = V[branchidx];
911 K[level-1] = branchingnode;
912 weightK = weightKold + weights[branchingnode];
918 for( i = branchidx; i < nValive; ++i )
921 apbound[i] = apbound[i+1];
927 nVcurrent = selectadjnodes(tcliquegraph, branchingnode, V, nValive, Vcurrent);
930 backtracklevel = branch(getnnodes, getweights, isedge, selectadjnodes, tcliquegraph, newsol, tcliquedata,
931 mem, cliquehash, buffer,
932 level, Vcurrent, nVcurrent, Vzero, nVzero, gsd, iscolored, K, weightK,
933 maxcliquenodes, nmaxcliquenodes, maxcliqueweight,
934 curcliquenodes, ncurcliquenodes, curcliqueweight, tmpcliquenodes,
935 maxfirstnodeweight, ntreenodes, maxntreenodes, backtrackfreq, maxnzeroextensions, -1, status);
940 if( nVcurrent == nValive )
942 debugMessage( "branching on node %d was optimal - ignoring remaining candidates\n", branchingnode);
951 debugMessage( "========================== branching level %d end =============================\n\n", level);
963 if( *curcliqueweight > *maxcliqueweight )
967 debugMessage( "found clique of weight %d at node %d in level %d\n", *curcliqueweight, *ntreenodes, level);
968 newSolution(selectadjnodes, tcliquegraph, newsol, tcliquedata, cliquehash, buffer, Vzero, nVzero,
969 maxnzeroextensions, curcliquenodes, *ncurcliquenodes, *curcliqueweight,
970 maxcliquenodes, nmaxcliquenodes, maxcliqueweight, &stopsolving);
974 debugMessage( " -> solving terminated by callback method\n");
980 *ncurcliquenodes = 0;
981 *curcliqueweight = 0;
985 if( level > backtracklevel )
987 debugMessage( "premature backtracking after %d nodes - level %d\n", *ntreenodes, level);
994 return backtracklevel;
1006 int* maxcliquenodes,
1007 int* nmaxcliquenodes,
1014 int maxnzeroextensions,
1033 int* curcliquenodes;
1034 int ncurcliquenodes;
1036 int* tmpcliquenodes;
1040 assert(maxcliquenodes != NULL);
1041 assert(nmaxcliquenodes != NULL);
1042 assert(maxcliqueweight != NULL);
1043 assert(maxntreenodes >= 0);
1044 assert(backtrackfreq >= 0);
1045 assert(maxnzeroextensions >= 0);
1046 assert(status != NULL);
1051 if( getnnodes == NULL )
1052 getnnodes = tcliqueGetNNodes;
1053 if( getweights == NULL )
1054 getweights = tcliqueGetWeights;
1055 if( isedge == NULL )
1056 isedge = tcliqueIsEdge;
1057 if( selectadjnodes == NULL )
1058 selectadjnodes = tcliqueSelectAdjnodes;
1061 nnodes = getnnodes(tcliquegraph);
1063 debugMessage( "calculating maximal weighted clique in graph (%d nodes)\n", nnodes);
1066 if( newsol != NULL )
1080 *nmaxcliquenodes = 0;
1081 *maxcliqueweight = minweight-1;
1082 ncurcliquenodes = 0;
1083 curcliqueweight = 0;
1087 weights = getweights(tcliquegraph);
1088 assert(weights != NULL);
1091 for( i = 0 ; i < nnodes; i++ )
1093 if( weights[i] == 0 )
1109 backtracklevel = branch(getnnodes, getweights, isedge, selectadjnodes, tcliquegraph, newsol, tcliquedata, mem,
1110 cliquehash, buffer, 0, V, nV, Vzero, nVzero, gsd, iscolored, K, 0,
1111 maxcliquenodes, nmaxcliquenodes, maxcliqueweight,
1112 curcliquenodes, &ncurcliquenodes, &curcliqueweight, tmpcliquenodes,
1113 maxfirstnodeweight, &nbbtreenodes, maxntreenodes, backtrackfreq, maxnzeroextensions, fixednode, status);
1115 if ( ntreenodes != NULL )
1116 *ntreenodes = nbbtreenodes;
1133 if( newsol != NULL )
|