示例#1
0
文件: lab12.c 项目: tomstepp/CS-159
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;
}
示例#3
0
文件: smartrel.c 项目: b1234561/EIG
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(&currentclique, 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(&currentclique);

   /* clear chunk memory */
   BMSclearChunkMemory(mem);

   debugMessage("------------coloringend-----------------\n");

   return maxsatdegree;
}