int main() { int weights[MAX]; //input array of weights int size; //size of array for class int class; //input of class size size = getweights(weights); class = getclass(size); sort(weights, size); findmin(weights, size, class); return(0); }
/** gets index of the node in a given set of nodes with maximum weight */ static int getMaxWeightIndex( TCLIQUE_GETNNODES((*getnnodes)), /**< user function to get the number of nodes */ TCLIQUE_GETWEIGHTS((*getweights)), /**< user function to get the node weights */ TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure */ int* V, /**< non-zero weighted nodes for branching */ int nV /**< number of non-zero weighted nodes for branching */ ) { const TCLIQUE_WEIGHT* weights; TCLIQUE_WEIGHT maxweight; int maxweightindex; int i; assert(getnnodes != NULL); assert(getweights != NULL); assert(tcliquegraph != NULL); assert(nV > 0); weights = getweights(tcliquegraph); maxweightindex = -1; maxweight = 0; /* try to improve maxweight */ for( i = 0 ; i < nV; i++ ) { assert(0 <= V[i] && V[i] < getnnodes(tcliquegraph)); assert(weights[V[i]] > 0); if( weights[V[i]] > maxweight) { /* node has larger weight */ maxweight = weights[V[i]]; maxweightindex = i; } } assert(maxweightindex >= 0); return maxweightindex; }
int main(int argc, char **argv) { char **eglist ; int numeg ; int i, j, k, pos; int *vv ; SNP *cupt, *cupt2 ; Indiv *indx ; double y1, y2, y ; int n0, n1, nkill ; int nindiv = 0 ; int nignore, numrisks = 1 ; SNP **xsnplist ; Indiv **xindlist ; int *xindex ; int nrows, ncols, m ; double *XTX, *cc, *evecs, *ww ; double *lambda ; double *tvecs ; int weightmode = NO ; int t ; double *xmean, *xfancy ; double *ldmat = NULL, *ldmat2 = NULL; double *ldvv = NULL, *ldvv2 = NULL, *vv2 = NULL ; int chrom, numclear ; double gdis ; int outliter, numoutiter, *badlist, nbad ; int a, b, n ; FILE *outlfile ; int xblock, blocksize=10000 ; double *tblock ; OUTLINFO *outpt ; int *idperm, *vecind ; // for sort readcommands(argc, argv) ; printf("## smartrel version: %s\n", WVERSION) ; packmode = YES ; setomode(&outputmode, omode) ; if (parname == NULL) return 0 ; if (xchrom == (numchrom+1)) noxdata = NO ; if (fstonly) { printf("fstonly\n") ; numeigs = 0 ; numoutliter = 0 ; numoutiter = 0 ; outputname = NULL ; snpeigname = NULL ; } if (fancynorm) printf("norm used\n\n") ; else printf("no norm used\n\n") ; nostatslim = MAX(nostatslim, 3) ; outlfile = ofile = stdout; if (outputname != NULL) openit(outputname, &ofile, "w") ; if (outliername != NULL) openit(outliername, &outlfile, "w") ; if (fstdetailsname != NULL) openit(fstdetailsname, &fstdetails, "w") ; numsnps = getsnps(snpname, &snpmarkers, 0.0, badsnpname, &nignore, numrisks) ; numindivs = getindivs(indivname, &indivmarkers) ; k = getgenos(genotypename, snpmarkers, indivmarkers, numsnps, numindivs, nignore) ; if (poplistname != NULL) { ZALLOC(eglist, numindivs, char *) ; numeg = loadlist(eglist, poplistname) ; seteglist(indivmarkers, numindivs, poplistname); } else { setstatus(indivmarkers, numindivs, NULL) ; ZALLOC(eglist, MAXPOPS, char *) ; numeg = makeeglist(eglist, MAXPOPS, indivmarkers, numindivs) ; } for (i=0; i<numeg; i++) { /* printf("%3d %s\n",i, eglist[i]) ; */ } nindiv=0 ; for (i=0; i<numindivs; i++) { indx = indivmarkers[i] ; if(indx -> affstatus == YES) ++nindiv ; } for (i=0; i<numsnps; i++) { cupt = snpmarkers[i] ; chrom = cupt -> chrom ; if ((noxdata) && (chrom == (numchrom+1))) cupt-> ignore = YES ; if (chrom == 0) cupt -> ignore = YES ; if (chrom > (numchrom+1)) cupt -> ignore = YES ; } for (i=0; i<numsnps; i++) { cupt = snpmarkers[i] ; pos = nnint(cupt -> physpos) ; if ((xchrom>0) && (cupt -> chrom != xchrom)) cupt -> ignore = YES ; if ((xchrom > 0) && (pos < lopos)) cupt -> ignore = YES ; if ((xchrom > 0) && (pos > hipos)) cupt -> ignore = YES ; if (cupt -> ignore) continue ; if (numvalidgtx(indivmarkers, cupt, YES) <= 1) { printf("nodata: %20s\n", cupt -> ID) ; cupt -> ignore = YES ; } } if (killr2) { nkill = killhir2(snpmarkers, numsnps, numindivs, r2physlim, r2genlim, r2thresh) ; if (nkill>0) printf("killhir2. number of snps killed: %d\n", nkill) ; } ZALLOC(vv, numindivs, int) ; numvalidgtallind(vv, snpmarkers, numsnps, numindivs) ; for (i=0; i<numindivs; ++i) { if (vv[i] == 0) { indx = indivmarkers[i] ; indx -> ignore = YES ; } } free(vv) ; numsnps = rmsnps(snpmarkers, numsnps, NULL) ; // rid ignorable snps if (missingmode) { setmiss(snpmarkers, numsnps) ; fancynorm = NO ; } if (weightname != NULL) { weightmode = YES ; getweights(weightname, snpmarkers, numsnps) ; } if (ldregress>0) { ZALLOC(ldvv, ldregress*numindivs, double) ; ZALLOC(ldvv2, ldregress*numindivs, double) ; ZALLOC(vv2, numindivs, double) ; ZALLOC(ldmat, ldregress*ldregress, double) ; ZALLOC(ldmat2, ldregress*ldregress, double) ; setidmat(ldmat, ldregress) ; vst(ldmat, ldmat, 1.0e-6, ldregress*ldregress) ; } ZALLOC(xindex, numindivs, int) ; ZALLOC(xindlist, numindivs, Indiv *) ; ZALLOC(xsnplist, numsnps, SNP *) ; if (popsizelimit > 0) { setplimit(indivmarkers, numindivs, eglist, numeg, popsizelimit) ; } nrows = loadindx(xindlist, xindex, indivmarkers, numindivs) ; ncols = loadsnpx(xsnplist, snpmarkers, numsnps, indivmarkers) ; printf("number of samples used: %d number of snps used: %d\n", nrows, ncols) ; /** cupt = xsnplist[0] ; for (j=0; j<nrows; ++j) { k = xindex[j] ; g = getgtypes(cupt, k) ; indx = indivmarkers[k] ; t = indxindex(eglist, numeg, indx -> egroup) ; printf("yy1 %20s %20s %20s %d %d %d\n", cupt ->ID, indx -> ID, indx -> egroup, j, k, g) ; } printf("yya: ") ; printimat(xindex, 1, nrows) ; printf("zzindxa: %s\n", indivmarkers[230] -> egroup) ; */ /* printf("## nrows: %d ncols %d\n", nrows, ncols) ; */ ZALLOC(xmean, ncols, double) ; ZALLOC(xfancy, ncols, double) ; ZALLOC(XTX, nrows*nrows, double) ; ZALLOC(evecs, nrows*nrows, double) ; ZALLOC(tvecs, nrows*nrows, double) ; ZALLOC(lambda, nrows, double) ; ZALLOC(cc, nrows, double) ; ZALLOC(ww, nrows, double) ; ZALLOC(badlist, nrows, int) ; blocksize = MIN(blocksize, ncols) ; ZALLOC(tblock, nrows*blocksize, double) ; // xfancy is multiplier for column xmean is mean to take off // badlist is list of rows to delete (outlier removal) numoutiter = 1 ; if (numoutliter>=1) { numoutiter = numoutliter+1 ; ZALLOC(outinfo, nrows, OUTLINFO *) ; for (k=0; k<nrows; k++) { ZALLOC(outinfo[k], 1, OUTLINFO) ; } /* fprintf(outlfile, "##%18s %4s %6s %9s\n", "ID", "iter","eigvec", "score") ; */ } for (outliter = 1; outliter <= numoutiter ; ++outliter) { if (fstonly) { setidmat(XTX, nrows) ; vclear(lambda, 1.0, nrows) ; break ; } if (outliter>1) { ncols = loadsnpx(xsnplist, snpmarkers, numsnps, indivmarkers) ; } vzero(XTX, nrows*nrows) ; vzero(tblock, nrows*blocksize) ; xblock = 0 ; vzero(xmean, ncols) ; vclear(xfancy, 1.0, ncols) ; for (i=0; i<ncols; i++) { cupt = xsnplist[i] ; chrom = cupt -> chrom ; getcolxz(cc, cupt, xindex, nrows, i, xmean, xfancy, &n0, &n1) ; t = MIN(n0, n1) ; if (t <= minallelecnt) { cupt -> ignore = YES ; vzero(cc, nrows) ; } if (weightmode) { vst(cc, cc, xsnplist[i] -> weight, nrows) ; } if (ldregress>0) { numclear = 0 ; for (k=1; k<= ldregress; ++k) { j = i-k ; if (j<0) { numclear = ldregress-k+1 ; break ; } cupt2 = xsnplist[j] ; if (cupt2 -> chrom != chrom) gdis = ldlimit + 1.0 ; else gdis = cupt -> genpos - cupt2 -> genpos ; if (gdis>=ldlimit) { numclear = ldregress-k+1 ; break ; } } if (numclear>0) clearld(ldmat, ldvv, ldregress, nrows, numclear) ; ldreg(ldmat, ldmat2, cc, vv2, ldvv, ldvv2, ldregress, nrows) ; copyarr(ldmat2, ldmat, ldregress*ldregress) ; copyarr(vv2, cc, nrows) ; copyarr(ldvv2, ldvv, ldregress*nrows) ; } copyarr(cc, tblock+xblock*nrows, nrows) ; ++xblock ; /** this is the key code to parallelize */ if (xblock==blocksize) { domult(tvecs, tblock, xblock, nrows) ; vvp(XTX, XTX, tvecs, nrows*nrows) ; xblock = 0 ; vzero(tblock, nrows*blocksize) ; } } if (xblock>0) { domult(tvecs, tblock, xblock, nrows) ; vvp(XTX, XTX, tvecs, nrows*nrows) ; } symit(XTX, nrows) ; /** a = 0; b=0 ; printf("zz1 %12.6f ", XTX[a*nrows+b]) ; a = nrows-1; b=nrows-1 ; printf(" %12.6f %15.9g\n", XTX[a*nrows+b], asum(XTX, nrows*nrows)) ; */ if (verbose) { printdiag(XTX, nrows) ; } y = trace(XTX, nrows) / (double) (nrows-1) ; if (isnan(y)) fatalx("bad XTX matrix\n") ; /* printf("trace: %9.3f\n", y) ; */ if (y<=0.0) fatalx("XTX has zero trace (perhaps no data)\n") ; vst(XTX, XTX, 1.0/y, nrows * nrows) ; /// mean eigenvalue is 1 eigvecs(XTX, lambda, evecs, nrows) ; // eigenvalues are in decreasing order if (outliter > numoutliter) break ; // last pass skips outliers numoutleigs = MIN(numoutleigs, nrows-1) ; nbad = ridoutlier(evecs, nrows, numoutleigs, outlthresh, badlist, outinfo) ; if (nbad == 0) break ; for (i=0; i<nbad; i++) { j = badlist[i] ; indx = xindlist[j] ; outpt = outinfo[j] ; fprintf(outlfile, "REMOVED outlier %s iter %d evec %d sigmage %.3f\n", indx -> ID, outliter, outpt -> vecno, outpt -> score) ; indx -> ignore = YES ; } nrows = loadindx(xindlist, xindex, indivmarkers, numindivs) ; printf("number of samples after outlier removal: %d\n", nrows) ; } if (outliername != NULL) fclose(outlfile) ; m = numgtz(lambda, nrows) ; /* printf("matrix rank: %d\n", m) ; */ if (m==0) fatalx("no data\n") ; /** smartrel code */ for (i=0; i<numeigs; i++) { y = sqrt(lambda[i]) ; vst(ww, evecs+i*nrows, y, nrows) ; subouter(XTX, ww, nrows) ; } free(tvecs) ; n = 0 ; ZALLOC(vecind, nrows*nrows/2, int) ; for (i=0; i<nrows; i++) { for (j=i+1; j<nrows; j++) { k = i*nrows + j ; y1 = XTX[i*nrows+i] ; y2 = XTX[j*nrows+j] ; y = XTX[k]/sqrt(y1*y2) ; y += 1/(double)(nrows-1); if (y<relthresh) continue ; vecind[n] = k ; evecs[n] = -y ; ++n ; } } free(XTX) ; if (n==0) { printf("## nothing above relthresh!\n") ; printf("##end of smartrel run\n") ; return 0 ; } ZALLOC(idperm, n, int) ; sortit(evecs, idperm, n) ; for (i=0; i<n; i++) { j = idperm[i] ; k = vecind[j] ; a = k/nrows ; b = k%nrows ; printf("rel: %20s ", xindlist[a] ->ID) ; printf("%20s ", xindlist[b] ->ID) ; printf(" %9.3f", -evecs[i]) ; printnl() ; } printf("##end of smartrel run\n") ; return 0 ; }
/** finds maximum weight clique */ void tcliqueMaxClique( TCLIQUE_GETNNODES((*getnnodes)), /**< user function to get the number of nodes */ TCLIQUE_GETWEIGHTS((*getweights)), /**< user function to get the node weights */ TCLIQUE_ISEDGE ((*isedge)), /**< user function to check for existence of an edge */ TCLIQUE_SELECTADJNODES((*selectadjnodes)), /**< user function to select adjacent edges */ TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure that is passed to graph callbacks */ TCLIQUE_NEWSOL ((*newsol)), /**< user function to call on every new solution */ TCLIQUE_DATA* tcliquedata, /**< user data to pass to new solution callback function */ int* maxcliquenodes, /**< pointer to store nodes of the maximum weight clique */ int* nmaxcliquenodes, /**< pointer to store number of nodes in the maximum weight clique */ TCLIQUE_WEIGHT* maxcliqueweight, /**< pointer to store weight of the maximum weight clique */ TCLIQUE_WEIGHT maxfirstnodeweight, /**< maximum weight of branching nodes in level 0; 0 if not used * for cliques with at least one fractional node) */ TCLIQUE_WEIGHT minweight, /**< lower bound for weight of generated cliques */ int maxntreenodes, /**< maximal number of nodes of b&b tree */ int backtrackfreq, /**< frequency to backtrack to first level of tree (0: no premature backtracking) */ int maxnzeroextensions, /**< maximal number of zero-valued variables extending the clique */ int fixednode, /**< node that is forced to be in the clique, or -1; must have positive weight */ TCLIQUE_STATUS* status /**< pointer to store the status of the solving call */ ) { CLIQUEHASH* cliquehash; const TCLIQUE_WEIGHT* weights; int* buffer; int* K; int* V; int* Vzero; int nnodes; int nV; int nVzero; int i; BMS_CHKMEM* mem; NBC* gsd; TCLIQUE_Bool* iscolored; int* curcliquenodes; int ncurcliquenodes; TCLIQUE_WEIGHT curcliqueweight; int* tmpcliquenodes; int ntreenodes; int backtracklevel; assert(maxcliquenodes != NULL); assert(nmaxcliquenodes != NULL); assert(maxcliqueweight != NULL); assert(maxntreenodes >= 0); assert(backtrackfreq >= 0); assert(maxnzeroextensions >= 0); assert(status != NULL); *status = TCLIQUE_OPTIMAL; /* use default graph callbacks, if NULL pointers are given */ if( getnnodes == NULL ) getnnodes = tcliqueGetNNodes; if( getweights == NULL ) getweights = tcliqueGetWeights; if( isedge == NULL ) isedge = tcliqueIsEdge; if( selectadjnodes == NULL ) selectadjnodes = tcliqueSelectAdjnodes; /* get number of nodes */ nnodes = getnnodes(tcliquegraph); debugMessage("calculating maximal weighted clique in graph (%d nodes)\n", nnodes); /* set up data structures */ if( newsol != NULL ) createCliquehash(&cliquehash, CLIQUEHASH_INITSIZE); else cliquehash = NULL; ALLOC_ABORT( BMSallocMemoryArray(&buffer, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&K, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&V, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&Vzero, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&gsd, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&iscolored, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&curcliquenodes, nnodes) ); ALLOC_ABORT( BMSallocMemoryArray(&tmpcliquenodes, nnodes) ); /* set weight and number of nodes of maximum weighted clique */ *nmaxcliquenodes = 0; *maxcliqueweight = minweight-1; ncurcliquenodes = 0; curcliqueweight = 0; ntreenodes = 0; /* set up V and Vzero */ weights = getweights(tcliquegraph); assert(weights != NULL); nV = 0; nVzero = 0; for( i = 0 ; i < nnodes; i++ ) { if( weights[i] == 0 ) { Vzero[nVzero] = i; nVzero++; } else { V[nV] = i; nV++; } } /* initialize own memory allocator for coloring */ mem = BMScreateChunkMemory(sizeof(LIST_ITV), CHUNK_SIZE, -1); /* branch to find maximum weight clique */ backtracklevel = branch(getnnodes, getweights, isedge, selectadjnodes, tcliquegraph, newsol, tcliquedata, mem, cliquehash, buffer, 0, V, nV, Vzero, nVzero, gsd, iscolored, K, 0, maxcliquenodes, nmaxcliquenodes, maxcliqueweight, curcliquenodes, &ncurcliquenodes, &curcliqueweight, tmpcliquenodes, maxfirstnodeweight, &ntreenodes, maxntreenodes, backtrackfreq, maxnzeroextensions, fixednode, status); if( backtracklevel != INT_MAX && *status == TCLIQUE_OPTIMAL ) *status = TCLIQUE_USERABORT; /* delete own memory allocator for coloring */ BMSdestroyChunkMemory(&mem); /* free data structures */ BMSfreeMemoryArray(&tmpcliquenodes); BMSfreeMemoryArray(&curcliquenodes); BMSfreeMemoryArray(&iscolored); BMSfreeMemoryArray(&gsd); BMSfreeMemoryArray(&Vzero); BMSfreeMemoryArray(&V); BMSfreeMemoryArray(&K); BMSfreeMemoryArray(&buffer); if( newsol != NULL ) freeCliquehash(&cliquehash); }
/** branches the searching tree, branching nodes are selected in decreasing order of their apriori bound, * returns the level to which we should backtrack, or INT_MAX for continuing normally */ static int branch( TCLIQUE_GETNNODES((*getnnodes)), /**< user function to get the number of nodes */ TCLIQUE_GETWEIGHTS((*getweights)), /**< user function to get the node weights */ TCLIQUE_ISEDGE ((*isedge)), /**< user function to check for existence of an edge */ TCLIQUE_SELECTADJNODES((*selectadjnodes)), /**< user function to select adjacent edges */ TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure */ TCLIQUE_NEWSOL ((*newsol)), /**< user function to call on every new solution */ TCLIQUE_DATA* tcliquedata, /**< user data to pass to user callback function */ BMS_CHKMEM* mem, /**< block memory */ CLIQUEHASH* cliquehash, /**< clique hash table */ int* buffer, /**< buffer of size nnodes */ int level, /**< level of b&b tree */ int* V, /**< non-zero weighted nodes for branching */ int nV, /**< number of non-zero weighted nodes for branching */ int* Vzero, /**< zero weighted nodes */ int nVzero, /**< number of zero weighted nodes */ NBC* gsd, /**< neighbour color information of all nodes */ TCLIQUE_Bool* iscolored, /**< coloring status of all nodes */ int* K, /**< nodes from the b&b tree */ TCLIQUE_WEIGHT weightK, /**< weight of the nodes from b&b tree */ int* maxcliquenodes, /**< pointer to store nodes of the maximum weight clique */ int* nmaxcliquenodes, /**< pointer to store number of nodes in the maximum weight clique */ TCLIQUE_WEIGHT* maxcliqueweight, /**< pointer to store weight of the maximum weight clique */ int* curcliquenodes, /**< pointer to store nodes of currenct clique */ int* ncurcliquenodes, /**< pointer to store number of nodes in current clique */ TCLIQUE_WEIGHT* curcliqueweight, /**< pointer to store weight of current clique */ int* tmpcliquenodes, /**< buffer for storing the temporary clique */ TCLIQUE_WEIGHT maxfirstnodeweight, /**< maximum weight of branching nodes in level 0; 0 if not used ** (for cliques with at least one fractional node) */ int* ntreenodes, /**< pointer to store number of nodes of b&b tree */ int maxntreenodes, /**< maximal number of nodes of b&b tree */ int backtrackfreq, /**< frequency to backtrack to first level of tree (0: no premature backtracking) */ int maxnzeroextensions, /**< maximal number of zero-valued variables extending the clique */ int fixednode, /**< node that is forced to be in the clique, or -1; must have positive weight */ TCLIQUE_STATUS* status /**< pointer to store the status of the solving call */ ) { TCLIQUE_Bool isleaf; const TCLIQUE_WEIGHT* weights; TCLIQUE_WEIGHT* apbound; TCLIQUE_WEIGHT subgraphweight; TCLIQUE_WEIGHT weightKold; TCLIQUE_WEIGHT tmpcliqueweight; int backtracklevel; int ntmpcliquenodes; int i; assert(getnnodes != NULL); assert(getweights != NULL); assert(selectadjnodes != NULL); assert(mem != NULL); assert(V != NULL); assert(gsd != NULL); assert(iscolored != NULL); assert(K != NULL); assert(maxcliqueweight != NULL); assert(curcliquenodes != NULL); assert(ncurcliquenodes != NULL); assert(curcliqueweight != NULL); assert(ntreenodes != NULL); assert(maxfirstnodeweight >= 0); assert(*ntreenodes >= 0); assert(maxntreenodes >= 0); assert(status != NULL); /* increase the number of nodes, and stop solving, if the node limit is exceeded */ (*ntreenodes)++; #ifdef TCLIQUE_DEBUG debugMessage("(level %d, treenode %d) maxclique = %d, curclique = %d [mem=%lld (%lld), cliques=%d]\n", level, *ntreenodes, *maxcliqueweight, *curcliqueweight, BMSgetChunkMemoryUsed(mem), BMSgetMemoryUsed(), cliquehash == NULL ? 0 : cliquehash->ncliques); debugMessage(" -> current branching (weight %d):", weightK); for( i = 0; i < level; ++i ) debugPrintf(" %d", K[i]); debugPrintf("\n"); debugMessage(" -> branching candidates:"); for( i = 0; i < nV; ++i ) debugPrintf(" %d", V[i]); debugPrintf("\n"); #endif if( *ntreenodes > maxntreenodes ) { *status = TCLIQUE_NODELIMIT; return TRUE; } weights = getweights(tcliquegraph); backtracklevel = INT_MAX; isleaf = TRUE; /* allocate temporary memory for a priori bounds */ ALLOC_ABORT( BMSallocMemoryArray(&apbound, nV) ); BMSclearMemoryArray(apbound, nV); /* use coloring relaxation to generate an upper bound for the current subtree and a heuristic solution */ subgraphweight = boundSubgraph(getnnodes, getweights, isedge, selectadjnodes, tcliquegraph, mem, buffer, V, nV, gsd, iscolored, apbound, tmpcliquenodes, &ntmpcliquenodes, &tmpcliqueweight); #ifndef NDEBUG /* check correctness of V and apbound arrays */ for( i = 0; i < nV; ++i ) { assert(0 <= V[i] && V[i] < getnnodes(tcliquegraph)); assert(i == 0 || V[i-1] < V[i]); assert(apbound[i] >= 0); assert((apbound[i] == 0) == (weights[V[i]] == 0)); } #endif /* check, whether the heuristic solution is better than the current subtree's solution; * if the user wanted to have a fixed variable inside the clique and we are in level 0, we first have to * fix this variable in this level (the current clique might not contain the fixed node) */ if( weightK + tmpcliqueweight > *curcliqueweight && (level > 0 || fixednode == -1) ) { /* install the newly generated clique as current clique */ for( i = 0; i < level; ++i ) curcliquenodes[i] = K[i]; for( i = 0; i < ntmpcliquenodes; ++i ) curcliquenodes[level+i] = tmpcliquenodes[i]; *ncurcliquenodes = level + ntmpcliquenodes; *curcliqueweight = weightK + tmpcliqueweight; #ifdef TCLIQUE_DEBUG debugMessage(" -> new current clique with weight %d at node %d in level %d:", *curcliqueweight, *ntreenodes, level); for( i = 0; i < *ncurcliquenodes; ++i ) debugPrintf(" %d", curcliquenodes[i]); debugPrintf("\n"); #endif } /* discard subtree, if the upper bound is not better than the weight of the currently best clique; * if only 2 nodes are left, the maximal weighted clique was already calculated in boundSubgraph() and nothing * more has to be done; * however, if the user wanted to have a fixed node and we are in the first decision level, we have to continue */ if( weightK + subgraphweight > *maxcliqueweight && (nV > 2 || (fixednode >= 0 && level == 0)) ) { int* Vcurrent; int nVcurrent; int nValive; int branchingnode; assert(nV > 0); /* process current subtree */ level++; /* set up data structures */ ALLOC_ABORT( BMSallocMemoryArray(&Vcurrent, nV-1) ); nValive = nV; weightKold = weightK; debugMessage("============================ branching level %d ===============================\n", level); /* branch on the nodes of V by decreasing order of their apriori bound */ while( backtracklevel >= level && nValive > 0 ) { int branchidx; /* check if we meet the backtracking frequency - in this case abort the search until we have reached first level */ if( level > 1 && backtrackfreq > 0 && (*ntreenodes) % backtrackfreq == 0 ) { backtracklevel = 1; break; } /* get next branching node */ if( level == 1 && fixednode >= 0 ) { /* select the fixed node as first "branching" candidate */ for( branchidx = 0; branchidx < nValive && V[branchidx] != fixednode; branchidx++ ) {} assert(branchidx < nValive); assert(V[branchidx] == fixednode); } else if( level == 1 && maxfirstnodeweight > 0 ) branchidx = getMaxApBoundIndexNotMaxWeight(V, nValive, apbound, weights, maxfirstnodeweight); else branchidx = getMaxApBoundIndex(nValive, apbound); if( branchidx < 0 ) break; assert(0 <= branchidx && branchidx < nValive && nValive <= nV); assert(apbound[branchidx] > 0); assert(weights[V[branchidx]] > 0); /* test a priori bound */ if( (weightKold + apbound[branchidx]) <= *maxcliqueweight ) break; debugMessage("%d. branching in level %d (treenode %d): bidx=%d, node %d, weight %d, upperbound: %d+%d = %d, maxclique=%d\n", nV-nValive+1, level, *ntreenodes, branchidx, V[branchidx], weights[V[branchidx]], weightKold, apbound[branchidx], weightKold + apbound[branchidx], *maxcliqueweight); /* because we branch on this node, the node is no leaf in the tree */ isleaf = FALSE; /* update the set of nodes from the b&b tree * K = K & {branchingnode} */ branchingnode = V[branchidx]; K[level-1] = branchingnode; weightK = weightKold + weights[branchingnode]; /* update the set of nodes for branching * V = V \ {branchingnode} */ nValive--; for( i = branchidx; i < nValive; ++i ) { V[i] = V[i+1]; apbound[i] = apbound[i+1]; } /* set the nodes for the next level of b&b tree * Vcurrent = nodes of V, that are adjacent to branchingnode */ nVcurrent = selectadjnodes(tcliquegraph, branchingnode, V, nValive, Vcurrent); /* process the selected subtree */ backtracklevel = branch(getnnodes, getweights, isedge, selectadjnodes, tcliquegraph, newsol, tcliquedata, mem, cliquehash, buffer, level, Vcurrent, nVcurrent, Vzero, nVzero, gsd, iscolored, K, weightK, maxcliquenodes, nmaxcliquenodes, maxcliqueweight, curcliquenodes, ncurcliquenodes, curcliqueweight, tmpcliquenodes, maxfirstnodeweight, ntreenodes, maxntreenodes, backtrackfreq, maxnzeroextensions, -1, status); /* if all other candidates stayed in the candidate list, the current branching was optimal and * there is no need to try the remaining ones */ if( nVcurrent == nValive ) { debugMessage("branching on node %d was optimal - ignoring remaining candidates\n", branchingnode); nValive = 0; } /* if we had a fixed node, ignore all other nodes */ if( fixednode >= 0 ) nValive = 0; } debugMessage("========================== branching level %d end =============================\n\n", level); /* free data structures */ BMSfreeMemoryArray(&Vcurrent); } /* check, whether any branchings have been applied, or if this node is a leaf of the branching tree */ if( isleaf ) { /* the current clique is the best clique found on the path to this leaf * -> check, whether it is an improvement to the currently best clique */ if( *curcliqueweight > *maxcliqueweight ) { TCLIQUE_Bool stopsolving; debugMessage("found clique of weight %d at node %d in level %d\n", *curcliqueweight, *ntreenodes, level); newSolution(selectadjnodes, tcliquegraph, newsol, tcliquedata, cliquehash, buffer, Vzero, nVzero, maxnzeroextensions, curcliquenodes, *ncurcliquenodes, *curcliqueweight, maxcliquenodes, nmaxcliquenodes, maxcliqueweight, &stopsolving); if( stopsolving ) { debugMessage(" -> solving terminated by callback method\n"); backtracklevel = 0; } } /* discard the current clique */ *ncurcliquenodes = 0; *curcliqueweight = 0; } #ifdef TCLIQUE_DEBUG if( level > backtracklevel ) { debugMessage("premature backtracking after %d nodes - level %d\n", *ntreenodes, level); } #endif /* free data structures */ BMSfreeMemoryArray(&apbound); return backtracklevel; }
/** tries to find a clique, if V has only one or two nodes */ static void reduced( TCLIQUE_GETWEIGHTS((*getweights)), /**< user function to get the node weights */ TCLIQUE_ISEDGE ((*isedge)), /**< user function to check for existence of an edge */ TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure */ int* V, /**< non-zero weighted nodes for branching */ int nV, /**< number of non-zero weighted nodes for branching */ TCLIQUE_WEIGHT* apbound, /**< apriori bound of nodes for branching */ int* tmpcliquenodes, /**< buffer for storing the temporary clique */ int* ntmpcliquenodes, /**< pointer to store number of nodes of the temporary clique */ TCLIQUE_WEIGHT* tmpcliqueweight /**< pointer to store weight of the temporary clique */ ) { const TCLIQUE_WEIGHT* weights; assert(getweights != NULL); assert(isedge != NULL); assert(tcliquegraph != NULL); assert(V != NULL); assert(0 <= nV && nV <= 2); assert(apbound != NULL); assert(tmpcliquenodes != NULL); assert(ntmpcliquenodes != NULL); assert(tmpcliqueweight != NULL); weights = getweights(tcliquegraph); assert(nV == 0 || weights[V[0]] > 0); assert(nV <= 1 || weights[V[1]] > 0); if( nV >= 1 ) apbound[0] = weights[V[0]]; if( nV >= 2 ) apbound[1] = weights[V[1]]; /* check if nodes are adjacent */ if( nV >= 2 && isedge(tcliquegraph, V[0], V[1]) ) { assert(isedge(tcliquegraph, V[1], V[0])); /* put nodes into clique */ tmpcliquenodes[0] = V[0]; tmpcliquenodes[1] = V[1]; *ntmpcliquenodes = 2; *tmpcliqueweight = weights[V[0]] + weights[V[1]]; apbound[0] += weights[V[1]]; } else if( nV >= 2 && weights[V[1]] > weights[V[0]] ) { /* put V[1] into clique */ tmpcliquenodes[0] = V[1]; *ntmpcliquenodes = 1; *tmpcliqueweight = weights[V[1]]; } else if( nV >= 1 ) { /* put V[0] into clique */ tmpcliquenodes[0] = V[0]; *ntmpcliquenodes = 1; *tmpcliqueweight = weights[V[0]]; } else { *tmpcliqueweight = 0; *ntmpcliquenodes = 0; } }
/** colors the positive weighted nodes of a given set of nodes V with the lowest possible number of colors and * finds a clique in the graph induced by V, an upper bound and an apriori bound for further branching steps */ TCLIQUE_WEIGHT tcliqueColoring( TCLIQUE_GETNNODES((*getnnodes)), /**< user function to get the number of nodes */ TCLIQUE_GETWEIGHTS((*getweights)), /**< user function to get the node weights */ TCLIQUE_SELECTADJNODES((*selectadjnodes)), /**< user function to select adjacent edges */ TCLIQUE_GRAPH* tcliquegraph, /**< pointer to graph data structure */ BMS_CHKMEM* mem, /**< block memory */ int* buffer, /**< buffer of size nnodes */ int* V, /**< non-zero weighted nodes for branching */ int nV, /**< number of non-zero weighted nodes for branching */ NBC* gsd, /**< neighbor color information of all nodes */ TCLIQUE_Bool* iscolored, /**< coloring status of all nodes */ TCLIQUE_WEIGHT* apbound, /**< pointer to store apriori bound of nodes for branching */ int* clique, /**< buffer for storing the clique */ int* nclique, /**< pointer to store number of nodes in the clique */ TCLIQUE_WEIGHT* weightclique /**< pointer to store the weight of the clique */ ) { const TCLIQUE_WEIGHT* weights; TCLIQUE_WEIGHT maxsatdegree; TCLIQUE_WEIGHT range; TCLIQUE_Bool growclique; int node; int nodeVindex; int i; int j; LIST_ITV* colorinterval; LIST_ITV nwcitv; LIST_ITV* pnc; LIST_ITV* lcitv; LIST_ITV* item; LIST_ITV* tmpitem; int* workclique; int* currentclique; int ncurrentclique; int weightcurrentclique; int* Vadj; int nVadj; int adjidx; assert(getnnodes != NULL); assert(getweights != NULL); assert(selectadjnodes != NULL); assert(buffer != NULL); assert(V != NULL); assert(nV > 0); assert(clique != NULL); assert(nclique != NULL); assert(weightclique != NULL); assert(gsd != NULL); assert(iscolored != NULL); weights = getweights(tcliquegraph); assert(weights != NULL); /* initialize maximum weight clique found so far */ growclique = TRUE; *nclique = 0; *weightclique = 0; /* get node of V with maximum weight */ nodeVindex = getMaxWeightIndex(getnnodes, getweights, tcliquegraph, V, nV); node = V[nodeVindex]; assert(0 <= node && node < getnnodes(tcliquegraph)); range = weights[node]; assert(range > 0); /* set up data structures for coloring */ BMSclearMemoryArray(iscolored, nV); /* new-memory */ BMSclearMemoryArray(gsd, nV); /* new-memory */ iscolored[nodeVindex] = TRUE; /* color the first node */ debugMessage("---------------coloring-----------------\n"); debugMessage("1. node choosen: vindex=%d, vertex=%d, satdeg=%d, range=%d)\n", nodeVindex, node, gsd[nodeVindex].satdeg, range); /* set apriori bound: apbound(v_i) = satdeg(v_i) + weight(v_i) */ apbound[nodeVindex] = range; assert(apbound[nodeVindex] > 0); /* update maximum saturation degree: maxsatdeg = max { satdeg(v_i) + weight(v_i) | v_i in V } */ maxsatdegree = range; debugMessage("-> updated neighbors:\n"); /* set neighbor color of the adjacent nodes of node */ Vadj = buffer; nVadj = selectadjnodes(tcliquegraph, node, V, nV, Vadj); for( i = 0, adjidx = 0; i < nV && adjidx < nVadj; ++i ) { assert(V[i] <= Vadj[adjidx]); /* Vadj is a subset of V */ if( V[i] == Vadj[adjidx] ) { /* node is adjacent to itself, but we do not need to color it again */ if( i == nodeVindex ) { /* go to the next node in Vadj */ adjidx++; continue; } debugMessage(" nodeVindex=%d, node=%d, weight=%d, satdegold=%d -> ", i, V[i], weights[V[i]], gsd[i].satdeg); /* sets satdeg for adjacent node */ gsd[i].satdeg = range; /* creates new color interval [1,range] */ ALLOC_ABORT( BMSallocChunkMemory(mem, &colorinterval) ); colorinterval->next = NULL; colorinterval->itv.inf = 1; colorinterval->itv.sup = range; /* colorinterval is the first added element of the list of neighborcolors of the adjacent node */ gsd[i].lcitv = colorinterval; /* go to the next node in Vadj */ adjidx++; debugPrintf("satdegnew=%d, nbc=[%d,%d]\n", gsd[i].satdeg, gsd[i].lcitv->itv.inf, gsd[i].lcitv->itv.sup); } } /* set up data structures for the current clique */ ALLOC_ABORT( BMSallocMemoryArray(¤tclique, nV) ); workclique = clique; /* add node to the current clique */ currentclique[0] = node; ncurrentclique = 1; weightcurrentclique = range; /* color all other nodes of V */ for( i = 0 ; i < nV-1; i++ ) { assert((workclique == clique) != (currentclique == clique)); /* selects the next uncolored node to color */ nodeVindex = getMaxSatdegIndex(V, nV, gsd, iscolored, weights); if( nodeVindex == -1 ) /* no uncolored nodes left */ break; node = V[nodeVindex]; assert(0 <= node && node < getnnodes(tcliquegraph)); range = weights[node]; assert(range > 0); iscolored[nodeVindex] = TRUE; debugMessage("%d. node choosen: vindex=%d, vertex=%d, satdeg=%d, range=%d, growclique=%u, weight=%d)\n", i+2, nodeVindex, node, gsd[nodeVindex].satdeg, range, growclique, weightcurrentclique); /* set apriori bound: apbound(v_i) = satdeg(v_i) + weight(v_i) */ apbound[nodeVindex] = gsd[nodeVindex].satdeg + range; assert(apbound[nodeVindex] > 0); /* update maximum saturation degree: maxsatdeg = max { satdeg(v_i) + weight(v_i) | v_i in V } */ if( maxsatdegree < apbound[nodeVindex] ) maxsatdegree = apbound[nodeVindex]; /* update clique */ if( gsd[nodeVindex].satdeg == 0 ) { /* current node is not adjacent to nodes of current clique, * i.e. current clique can not be increased */ debugMessage("current node not adjacend to current clique (weight:%d) -> starting new clique\n", weightcurrentclique); /* check, if weight of current clique is larger than weight of maximum weight clique found so far */ if( weightcurrentclique > *weightclique ) { int* tmp; /* update maximum weight clique found so far */ assert((workclique == clique) != (currentclique == clique)); tmp = workclique; *weightclique = weightcurrentclique; *nclique = ncurrentclique; workclique = currentclique; currentclique = tmp; assert((workclique == clique) != (currentclique == clique)); } weightcurrentclique = 0; ncurrentclique = 0; growclique = TRUE; } if( growclique ) { /* check, if the current node is still adjacent to all nodes in the clique */ if( gsd[nodeVindex].satdeg == weightcurrentclique ) { assert(ncurrentclique < nV); currentclique[ncurrentclique] = node; ncurrentclique++; weightcurrentclique += range; #ifdef TCLIQUE_DEBUG { int k; debugMessage("current clique (size:%d, weight:%d):", ncurrentclique, weightcurrentclique); for( k = 0; k < ncurrentclique; ++k ) debugPrintf(" %d", currentclique[k]); debugPrintf("\n"); } #endif } else { debugMessage("node satdeg: %d, clique weight: %d -> stop growing clique\n", gsd[nodeVindex].satdeg, weightcurrentclique); growclique = FALSE; } } /* search for fitting color intervals for current node */ pnc = &nwcitv; if( gsd[nodeVindex].lcitv == NULL ) { /* current node has no colored neighbors yet: create new color interval [1,range] */ ALLOC_ABORT( BMSallocChunkMemory(mem, &colorinterval) ); colorinterval->next = NULL; colorinterval->itv.inf = 1; colorinterval->itv.sup = range; /* add the new colorinterval [1, range] to the list of chosen colorintervals for node */ pnc->next = colorinterval; pnc = colorinterval; } else { int tocolor; int dif; /* current node has colored neighbors */ tocolor = range; lcitv = gsd[nodeVindex].lcitv; /* check, if first neighbor color interval [inf, sup] has inf > 1 */ if( lcitv->itv.inf != 1 ) { /* create new interval [1, min{range, inf}] */ dif = lcitv->itv.inf - 1 ; if( dif > tocolor ) dif = tocolor; ALLOC_ABORT( BMSallocChunkMemory(mem, &colorinterval) ); colorinterval->next = NULL; colorinterval->itv.inf = 1; colorinterval->itv.sup = dif; tocolor -= dif; pnc->next = colorinterval; pnc = colorinterval; } /* as long as node is not colored with all colors, create new color interval by filling * the gaps in the existing neighbor color intervals of the neighbors of node */ while( tocolor > 0 ) { dif = tocolor; ALLOC_ABORT( BMSallocChunkMemory(mem, &colorinterval) ); colorinterval->next = NULL; colorinterval->itv.inf = lcitv->itv.sup+1; if( lcitv->next != NULL ) { int min; min = lcitv->next->itv.inf - lcitv->itv.sup - 1; if( dif > min ) dif = min; lcitv = lcitv->next; } colorinterval->itv.sup = colorinterval->itv.inf + dif - 1; tocolor -= dif; pnc->next = colorinterval; pnc = colorinterval; } } debugMessage("-> updated neighbors:\n"); /* update saturation degree and neighbor colorintervals of all neighbors of node */ Vadj = buffer; nVadj = selectadjnodes(tcliquegraph, node, V, nV, Vadj); for( j = 0, adjidx = 0; j < nV && adjidx < nVadj; ++j ) { assert(V[j] <= Vadj[adjidx]); /* Vadj is a subset of V */ if( V[j] == Vadj[adjidx] ) { if( !iscolored[j] ) { debugMessage(" nodeVindex=%d, node=%d, weight=%d, satdegold=%d -> ", j, V[j], weights[V[j]], gsd[j].satdeg); updateNeighbor(mem, &gsd[j], nwcitv.next); debugPrintf("satdegnew=%d, nbc=[%d,%d]\n", gsd[j].satdeg, gsd[j].lcitv->itv.inf, gsd[j].lcitv->itv.sup); } /* go to the next node in Vadj */ adjidx++; } } /* free data structure of created colorintervals */ item = nwcitv.next; while( item != NULL ) { tmpitem = item->next; BMSfreeChunkMemory(mem, &item); item = tmpitem; } /* free data structure of neighbor colorinterval of node just colored */ item = gsd[nodeVindex].lcitv; while( item != NULL ) { tmpitem = item->next; BMSfreeChunkMemory(mem, &item); item = tmpitem; } } assert((workclique == clique) != (currentclique == clique)); /* update maximum weight clique found so far */ if( weightcurrentclique > *weightclique ) { int* tmp; tmp = workclique; *weightclique = weightcurrentclique; *nclique = ncurrentclique; workclique = currentclique; currentclique = tmp; } assert((workclique == clique) != (currentclique == clique)); /* move the found clique to the provided clique pointer, if it is not the memory array */ if( workclique != clique ) { assert(clique == currentclique); assert(*nclique <= nV); BMScopyMemoryArray(clique, workclique, *nclique); currentclique = workclique; } /* free data structures */ BMSfreeMemoryArray(¤tclique); /* clear chunk memory */ BMSclearChunkMemory(mem); debugMessage("------------coloringend-----------------\n"); return maxsatdegree; }