/** frees memory of reader */ SCIP_RETCODE SCIPreaderFree( SCIP_READER** reader, /**< pointer to reader data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(reader != NULL); assert(*reader != NULL); assert(set != NULL); /* call destructor of reader */ if( (*reader)->readerfree != NULL ) { SCIP_CALL( (*reader)->readerfree(set->scip, *reader) ); } /* free clock */ SCIPclockFree(&(*reader)->readingtime); BMSfreeMemoryArray(&(*reader)->name); BMSfreeMemoryArray(&(*reader)->desc); BMSfreeMemoryArray(&(*reader)->extension); BMSfreeMemory(reader); return SCIP_OKAY; }
/** calls destructor and frees memory of primal heuristic */ SCIP_RETCODE SCIPheurFree( SCIP_HEUR** heur, /**< pointer to primal heuristic data structure */ SCIP_SET* set /**< global SCIP settings */ ) { int d; assert(heur != NULL); assert(*heur != NULL); assert(!(*heur)->initialized); assert(set != NULL); assert((*heur)->divesets != NULL || (*heur)->ndivesets == 0); /* call destructor of primal heuristic */ if( (*heur)->heurfree != NULL ) { SCIP_CALL( (*heur)->heurfree(set->scip, *heur) ); } for( d = 0; d < (*heur)->ndivesets; ++d ) { assert((*heur)->divesets[d] != NULL); divesetFree(&((*heur)->divesets[d])); } BMSfreeMemoryArrayNull(&(*heur)->divesets); SCIPclockFree(&(*heur)->heurclock); SCIPclockFree(&(*heur)->setuptime); BMSfreeMemoryArray(&(*heur)->name); BMSfreeMemoryArray(&(*heur)->desc); BMSfreeMemory(heur); return SCIP_OKAY; }
/** Handle start tag */ static void handle_starttag( PPOS* ppos ) { XML_NODE* node; char* name; assert(ppos != NULL); if ((name = get_name(ppos)) == NULL) { xml_error(ppos, "Missing name in tagstart"); ppos->state = STATE_ERROR; } else { if (NULL == (node = xml_new_node(name, ppos->lineno))) { xml_error(ppos, "Can't create new node"); ppos->state = STATE_ERROR; } else { xml_append_child(top_pstack(ppos), node); if ( push_pstack(ppos, node) ) ppos->state = STATE_IN_TAG; else ppos->state = STATE_ERROR; } BMSfreeMemoryArray(&name); } }
SCIP_Bool create_graph (int n, int m, GRAPH** gr) { assert( gr != NULL ); BMSallocMemory(gr); if( *gr == NULL ) return FALSE; BMSallocMemoryArray( &(*gr)->nodes, n ); if( (*gr)->nodes == NULL ) { BMSfreeMemory(gr); return FALSE; } BMSallocMemoryArray( &(*gr)->edges, m ); if( (*gr)->edges == NULL ) { BMSfreeMemoryArray(&(*gr)->nodes); BMSfreeMemory(gr); return FALSE; } (*gr)->nuses = 1; (*gr)->nnodes = n; (*gr)->nedges = m/2; (*gr)->nedgesnonzero = m/2; return TRUE; }
/** free node */ void xml_free_node( XML_NODE* node ) { XML_NODE* n; if (node == NULL) return; n = node->first_child; while (n != NULL) { XML_NODE* m; m = n->next_sibl; xml_free_node(n); n = m; } xml_free_attr(node->attr_list); if (node->data != NULL) { BMSfreeMemoryArray(&node->data); } assert(node->name != NULL); BMSfreeMemoryArray(&node->name); BMSfreeMemory(&node); #if 0 if (n != NULL) { xml_free_node(n->first_child); xml_free_node(n->next_sibl); xml_free_attr(n->attr_list); if (n->data != NULL) { BMSfreeMemoryArray(&n->data); } assert(n->name != NULL); BMSfreeMemoryArray(&n->name); BMSfreeMemory(&n); } #endif }
/** Read the value of an attribute from the input stream. * * The value has to be between two " or ' (the other character is then valid as well). The function * returns a pointer to allocated memory containing the value or it returns NULL in case of an * error. */ static char* get_attrval( PPOS* ppos ) { char* attr = NULL; int c; int stop; size_t len = 0; size_t size = 0; assert(ppos != NULL); /* The following is not allowed according to the specification (the value has to be directly * after the equation sign). */ c = skip_space(ppos); if ((c != '"') && (c != '\'')) { xml_error(ppos, "Atribute value does not start with \" or \'"); return NULL; } stop = c; for(;;) { if (len == size) { size += ATTR_EXT_SIZE; if ( attr == NULL ) { ALLOC_ABORT( BMSallocMemoryArray(&attr, size) ); } else { ALLOC_ABORT( BMSreallocMemoryArray(&attr, size) ); } } assert(attr != NULL); assert(size > len); c = getsymbol(ppos); if ((c == stop) || (c == EOF)) break; attr[len++] = (char)c; } if (c != EOF) attr[len] = '\0'; else { BMSfreeMemoryArray(&attr); attr = NULL; } return attr; }
/** Get name of a TAG or attribute from the input stream. * * Either it returns a pointer to allocated memory which contains the name or it returns NULL if * there is some error. */ static char* get_name( PPOS* ppos ) { char* name = NULL; size_t size = 0; size_t len = 0; int c; assert(ppos != NULL); c = getsymbol(ppos); if (!isalpha(c) && (c != '_') && (c != ':')) { xml_error(ppos, "Name starting with illegal charater"); return NULL; } /* The following is wrong: Here almost all characters that we casted to unicode are feasible */ while (isalnum(c) || (c == '_') || (c == ':') || (c == '.') || (c == '-')) { if (len + 1 >= size) { size += NAME_EXT_SIZE; if ( name == NULL ) { ALLOC_ABORT( BMSallocMemoryArray(&name, size) ); } else { ALLOC_ABORT( BMSreallocMemoryArray(&name, size) ); } } assert(name != NULL); assert(size > len); name[len++] = (char)c; c = getsymbol(ppos); } if (c != EOF) ungetsymbol(ppos, c); assert(name != NULL); if (len == 0) { BMSfreeMemoryArray(&name); name = NULL; } else name[len] = '\0'; return name; }
/** activates all display lines fitting in the display w.r. to priority */ SCIP_RETCODE SCIPdispAutoActivate( SCIP_SET* set /**< global SCIP settings */ ) { SCIP_DISP** disps; int totalwidth; int width; int i; assert(set != NULL); /* sort display columns w.r. to their priority */ SCIP_ALLOC( BMSduplicateMemoryArray(&disps, set->disps, set->ndisps) ); SCIPsortPtr((void**)disps, dispComp, set->ndisps); totalwidth = 0; /* first activate all columns with display status ON */ for( i = 0; i < set->ndisps; ++i ) { width = disps[i]->width; if( disps[i]->stripline ) width++; if( disps[i]->dispstatus == SCIP_DISPSTATUS_ON ) { disps[i]->active = TRUE; totalwidth += width; } else disps[i]->active = FALSE; } /* beginning with highest priority display column, activate AUTO columns as long as it fits into display width */ for( i = 0; i < set->ndisps; ++i ) { if( disps[i]->dispstatus == SCIP_DISPSTATUS_AUTO ) { assert(!disps[i]->active); width = disps[i]->width; if( disps[i]->stripline ) width++; if( totalwidth + width <= set->disp_width ) { disps[i]->active = TRUE; totalwidth += width; } } } /* free temporary memory */ BMSfreeMemoryArray(&disps); return SCIP_OKAY; }
/** frees a clique */ static void freeClique( CLIQUE** clique /**< pointer to the clique */ ) { assert(clique != NULL); assert(*clique != NULL); BMSfreeMemoryArray(&(*clique)->nodes); BMSfreeMemory(clique); }
/** frees memory of a diveset */ static void divesetFree( SCIP_DIVESET** diveset /**< general diving settings */ ) { assert(*diveset != NULL); assert((*diveset)->name != NULL); BMSfreeMemoryArray(&(*diveset)->name); BMSfreeMemory(diveset); }
SCIP_RETCODE SCIPpolicyFree( SCIP* scip, SCIP_POLICY** policy ) { assert(scip != NULL); assert(policy != NULL); assert((*policy)->weights != NULL); BMSfreeMemoryArray(&(*policy)->weights); SCIPfreeBlockMemory(scip, policy); return SCIP_OKAY; }
/** calls destructor and frees memory of variable pricer */ SCIP_RETCODE SCIPpricerFree( SCIP_PRICER** pricer, /**< pointer to variable pricer data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(pricer != NULL); assert(*pricer != NULL); assert(!(*pricer)->initialized); assert(set != NULL); /* call destructor of variable pricer */ if( (*pricer)->pricerfree != NULL ) { SCIP_CALL( (*pricer)->pricerfree(set->scip, *pricer) ); } SCIPclockFree(&(*pricer)->pricerclock); BMSfreeMemoryArray(&(*pricer)->name); BMSfreeMemoryArray(&(*pricer)->desc); BMSfreeMemory(pricer); return SCIP_OKAY; }
/** frees memory of display column */ SCIP_RETCODE SCIPdispFree( SCIP_DISP** disp, /**< pointer to display column data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(disp != NULL); assert(*disp != NULL); assert(!(*disp)->initialized); assert(set != NULL); /* call destructor of display column */ if( (*disp)->dispfree != NULL ) { SCIP_CALL( (*disp)->dispfree(set->scip, *disp) ); } BMSfreeMemoryArray(&(*disp)->name); BMSfreeMemoryArray(&(*disp)->desc); BMSfreeMemoryArray(&(*disp)->header); BMSfreeMemory(disp); return SCIP_OKAY; }
/** calls destructor and frees memory of separator */ SCIP_RETCODE SCIPsepaFree( SCIP_SEPA** sepa, /**< pointer to separator data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(sepa != NULL); assert(*sepa != NULL); assert(!(*sepa)->initialized); assert(set != NULL); /* call destructor of separator */ if( (*sepa)->sepafree != NULL ) { SCIP_CALL( (*sepa)->sepafree(set->scip, *sepa) ); } SCIPclockFree(&(*sepa)->sepaclock); SCIPclockFree(&(*sepa)->setuptime); BMSfreeMemoryArray(&(*sepa)->name); BMSfreeMemoryArray(&(*sepa)->desc); BMSfreeMemory(sepa); return SCIP_OKAY; }
/** free attribute */ static void xml_free_attr( XML_ATTR* attr ) { XML_ATTR* a; a = attr; while (a != NULL) { XML_ATTR* b; b = a->next; assert(a->name != NULL); assert(a->value != NULL); BMSfreeMemoryArray(&a->name); BMSfreeMemoryArray(&a->value); BMSfreeMemory(&a); a = b; } #if 0 if (a != NULL) { xml_free_attr(a->next); assert(a->name != NULL); assert(a->value != NULL); BMSfreeMemoryArray(&a->name); BMSfreeMemoryArray(&a->value); BMSfreeMemory(&a); } #endif }
/** frees memory of presolver */ SCIP_RETCODE SCIPpresolFree( SCIP_PRESOL** presol, /**< pointer to presolver data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(presol != NULL); assert(*presol != NULL); assert(!(*presol)->initialized); assert(set != NULL); /* call destructor of presolver */ if( (*presol)->presolfree != NULL ) { SCIP_CALL( (*presol)->presolfree(set->scip, *presol) ); } SCIPclockFree(&(*presol)->presolclock); SCIPclockFree(&(*presol)->setuptime); BMSfreeMemoryArray(&(*presol)->name); BMSfreeMemoryArray(&(*presol)->desc); BMSfreeMemory(presol); return SCIP_OKAY; }
/** frees the table for storing cliques and all inserted cliques */ static void freeCliquehash( CLIQUEHASH** cliquehash /**< pointer to the clique hash table */ ) { assert(cliquehash != NULL); assert(*cliquehash != NULL); /* free the cliques in the table */ clearCliquehash(*cliquehash); /* free the table data structure */ BMSfreeMemoryArray(&(*cliquehash)->cliques); BMSfreeMemory(cliquehash); }
/** calls destructor and frees memory of relaxation handler */ SCIP_RETCODE SCIPrelaxFree( SCIP_RELAX** relax, /**< pointer to relaxation handler data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(relax != NULL); assert(*relax != NULL); assert(!(*relax)->initialized); assert(set != NULL); /* call destructor of relaxation handler */ if( (*relax)->relaxfree != NULL ) { SCIP_CALL( (*relax)->relaxfree(set->scip, *relax) ); } SCIPclockFree(&(*relax)->relaxclock); SCIPclockFree(&(*relax)->setuptime); BMSfreeMemoryArray(&(*relax)->name); BMSfreeMemoryArray(&(*relax)->desc); BMSfreeMemory(relax); return SCIP_OKAY; }
/** calls destructor and frees memory of tree compression */ SCIP_RETCODE SCIPcomprFree( SCIP_COMPR** compr, /**< pointer to tree compression data structure */ SCIP_SET* set /**< global SCIP settings */ ) { assert(compr != NULL); assert(*compr != NULL); assert(!(*compr)->initialized); assert(set != NULL); /* call destructor of tree compression */ if( (*compr)->comprfree != NULL ) { SCIP_CALL( (*compr)->comprfree(set->scip, *compr) ); } SCIPclockFree(&(*compr)->comprclock); SCIPclockFree(&(*compr)->setuptime); BMSfreeMemoryArray(&(*compr)->name); BMSfreeMemoryArray(&(*compr)->desc); BMSfreeMemory(compr); return SCIP_OKAY; }
/** Handle end tag */ static void handle_endtag( PPOS* ppos ) { char* name; int c; assert(ppos != NULL); if ((name = get_name(ppos)) == NULL) xml_error(ppos, "Missing name in endtag"); else { c = skip_space(ppos); if (c != '>') { xml_error(ppos, "Missing '>' in endtag"); ppos->state = STATE_ERROR; } else { if (strcmp(name, top_pstack(ppos)->name)) { xml_error(ppos, "Name of endtag does not match starttag"); ppos->state = STATE_ERROR; } else { if ( pop_pstack(ppos) ) ppos->state = STATE_PCDATA; else ppos->state = STATE_ERROR; } BMSfreeMemoryArray(&name); } } }
/* Handles PCDATA */ static void proc_pcdata( PPOS* ppos /**< input stream position */ ) { XML_NODE* node; char* data = NULL; size_t size = 0; size_t len = 0; int c; assert(ppos != NULL); assert(ppos->state == STATE_PCDATA); #ifndef SPEC_LIKE_SPACE_HANDLING if ((c = skip_space(ppos)) != EOF) ungetsymbol(ppos, c); #endif c = getsymbol(ppos); while ((c != EOF) && (c != '<')) { if (len >= size - 1) /* leave space for terminating '\0' */ { size += DATA_EXT_SIZE; if ( data == NULL ) { ALLOC_ABORT( BMSallocMemoryArray(&data, size) ); } else { ALLOC_ABORT( BMSreallocMemoryArray(&data, size) ); } } assert(data != NULL); assert(size > len + 1); data[len++] = (char)c; c = getsymbol(ppos); } if (data == NULL) { if (c == EOF) ppos->state = STATE_EOF; else if (c == '<') { ppos->state = STATE_BEFORE; ungetsymbol(ppos, c); } else { ppos->state = STATE_ERROR; } } else { assert(len < size); data[len] = '\0'; if (c == EOF) ppos->state = STATE_ERROR; else { ungetsymbol(ppos, c); if (NULL == (node = xml_new_node("#PCDATA", ppos->lineno))) { xml_error(ppos, "Can't create new node"); ppos->state = STATE_ERROR; } else { BMSduplicateMemoryArray(&node->data, data, strlen(data)+1); xml_append_child(top_pstack(ppos), node); ppos->state = STATE_BEFORE; } BMSfreeMemoryArray(&data); } } }
/** Handles declarations that start with a <!. * * This includes comments. Does currenlty not work very well, because of DTDs. */ static void handle_decl( PPOS* ppos ) { enum XmlSection { IS_COMMENT, IS_ATTLIST, IS_DOCTYPE, IS_ELEMENT, IS_ENTITY, IS_NOTATION, IS_CDATA }; typedef enum XmlSection XMLSECTION; static struct { const char* name; XMLSECTION what; } key[] = { { "--", IS_COMMENT }, { "ATTLIST", IS_ATTLIST }, { "DOCTYPE", IS_DOCTYPE }, { "ELEMENT", IS_ELEMENT }, { "ENTITY", IS_ENTITY }, { "NOTATION", IS_NOTATION }, { "[CDATA[", IS_CDATA } }; XML_NODE* node; char* data; int c; int k = 0; int beg = 0; int end = (sizeof(key) / sizeof(key[0])) - 1; assert(ppos != NULL); assert(ppos->state == STATE_BEFORE); do { c = getsymbol(ppos); for(; (beg <= end) && (c != key[beg].name[k]); beg++) ; for(; (end >= beg) && (c != key[end].name[k]); end--) ; k++; } while(beg < end); if (beg != end) { xml_error(ppos, "Unknown declaration"); while((c != EOF) && (c != '>')) c = getsymbol(ppos); } else { assert(beg == end); assert(beg < (int)(sizeof(key) / sizeof(*key))); switch(key[beg].what) { case IS_COMMENT : if (do_comment(ppos)) ppos->state = STATE_ERROR; break; case IS_CDATA : if ((data = do_cdata(ppos)) == NULL) ppos->state = STATE_ERROR; else { if (NULL == (node = xml_new_node("#CDATA", ppos->lineno))) { xml_error(ppos, "Can't create new node"); ppos->state = STATE_ERROR; } else { BMSduplicateMemoryArray(&node->data, data, strlen(data)+1); BMSfreeMemoryArray(&data); xml_append_child(top_pstack(ppos), node); } } break; case IS_ATTLIST : case IS_ELEMENT : case IS_NOTATION : case IS_ENTITY : case IS_DOCTYPE : break; default : abort(); } } }
/** writes problem data to file with given reader or returns SCIP_DIDNOTRUN */ SCIP_RETCODE SCIPreaderWrite( SCIP_READER* reader, /**< reader */ SCIP_PROB* prob, /**< problem data */ SCIP_SET* set, /**< global SCIP settings */ FILE* file, /**< output file (or NULL for standard output) */ const char* extension, /**< file format */ SCIP_Bool genericnames, /**< using generic variable and constraint names? */ SCIP_RESULT* result /**< pointer to store the result of the callback method */ ) { SCIP_RETCODE retcode; assert(reader != NULL); assert(set != NULL); assert(extension != NULL); assert(result != NULL); /* check, if reader is applicable on the given file */ if( readerIsApplicable(reader, extension) && reader->readerwrite != NULL ) { SCIP_VAR** vars; int nvars; SCIP_VAR** fixedvars; int nfixedvars; SCIP_CONS** conss; int nconss; int i; SCIP_CONS* cons; char* name; const char* consname; const char** varnames; const char** fixedvarnames; const char** consnames; varnames = NULL; fixedvarnames = NULL; consnames = NULL; vars = prob->vars; nvars = prob->nvars; fixedvars = prob->fixedvars; nfixedvars = prob->nfixedvars; /* case of the transformed problem, we want to write currently valid problem */ if( prob->transformed ) { SCIP_CONSHDLR** conshdlrs; int nconshdlrs; conshdlrs = set->conshdlrs; nconshdlrs = set->nconshdlrs; /* collect number of constraints which have to be enforced; these are the constraints which currency (locally) * enabled; these also includes the local constraints */ nconss = 0; for( i = 0; i < nconshdlrs; ++i ) { /* check if all constraints of the constraint handler should be written */ if( set->write_allconss ) nconss += SCIPconshdlrGetNConss(conshdlrs[i]); else nconss += SCIPconshdlrGetNEnfoConss(conshdlrs[i]); } SCIPdebugMessage("Writing %d constraints.\n", nconss); SCIP_ALLOC( BMSallocMemoryArray(&conss, nconss) ); /* copy the constraints */ nconss = 0; for( i = 0; i < nconshdlrs; ++i ) { SCIP_CONS** conshdlrconss; int nconshdlrconss; int c; /* check if all constraints of the constraint handler should be written */ if( set->write_allconss ) { conshdlrconss = SCIPconshdlrGetConss(conshdlrs[i]); nconshdlrconss = SCIPconshdlrGetNConss(conshdlrs[i]); } else { conshdlrconss = SCIPconshdlrGetEnfoConss(conshdlrs[i]); nconshdlrconss = SCIPconshdlrGetNEnfoConss(conshdlrs[i]); } SCIPdebugMessage("Conshdlr <%s> has %d constraints to write from all in all %d constraints.\n", SCIPconshdlrGetName(conshdlrs[i]), nconshdlrconss, SCIPconshdlrGetNConss(conshdlrs[i])); for( c = 0; c < nconshdlrconss; ++c ) { conss[nconss] = conshdlrconss[c]; nconss++; } } } else { conss = prob->conss; nconss = prob->nconss; } if( genericnames ) { SCIP_VAR* var; int size; /* save variable and constraint names and replace these names by generic names */ /* allocate memory for saving the original variable and constraint names */ SCIP_ALLOC( BMSallocMemoryArray(&varnames, nvars) ); SCIP_ALLOC( BMSallocMemoryArray(&fixedvarnames, nfixedvars) ); SCIP_ALLOC( BMSallocMemoryArray(&consnames, nconss) ); /* compute length of the generic variable names: * - nvars + 1 to avoid log of zero * - +3 (zero at end + 'x' + 1 because we round down) * Example: 10 -> need 4 chars ("x10\0") */ size = (int) log10(nvars+1.0) + 3; for( i = 0; i < nvars; ++i ) { var = vars[i]; varnames[i] = SCIPvarGetName(var); SCIP_ALLOC( BMSallocMemoryArray(&name, size) ); (void) SCIPsnprintf(name, size, "x%d", i + set->write_genoffset); SCIPvarSetNamePointer(var, name); } /* compute length of the generic variable names */ size = (int) log10(nfixedvars+1.0) + 3; for( i = 0; i < nfixedvars; ++i ) { var = fixedvars[i]; fixedvarnames[i] = SCIPvarGetName(var); SCIP_ALLOC( BMSallocMemoryArray(&name, size) ); (void) SCIPsnprintf(name, size, "y%d", i); SCIPvarSetNamePointer(var, name); } /* compute length of the generic constraint names */ size = (int) log10(nconss+1.0) + 3; for( i = 0; i < nconss; ++i ) { cons = conss[i]; consnames[i] = SCIPconsGetName(cons); SCIP_ALLOC( BMSallocMemoryArray(&name, size) ); (void) SCIPsnprintf(name, size, "c%d", i); SCIPconsSetNamePointer(cons, name); } } /* call reader to write problem */ retcode = reader->readerwrite(set->scip, reader, file, prob->name, prob->probdata, prob->transformed, prob->transformed ? SCIP_OBJSENSE_MINIMIZE : prob->objsense, prob->objscale, prob->objoffset, vars, nvars, prob->nbinvars, prob->nintvars, prob->nimplvars, prob->ncontvars, fixedvars, nfixedvars, prob->startnvars, conss, nconss, prob->maxnconss, prob->startnconss, genericnames, result); /* reset variable and constraint names to original names */ if( genericnames ) { assert(varnames != NULL); assert(fixedvarnames != NULL); assert(consnames != NULL); for( i = 0; i < nvars; ++i ) resetVarname(vars[i], varnames[i]); for( i = 0; i < nfixedvars; ++i ) resetVarname(fixedvars[i], fixedvarnames[i]); for( i = 0; i < nconss; ++i ) { cons = conss[i]; /* get pointer to temporary generic name and free the memory */ consname = SCIPconsGetName(cons); BMSfreeMemory(&consname); /* reset name */ SCIPconsSetNamePointer(cons, consnames[i]); } /* free memory */ BMSfreeMemoryArray(&varnames); BMSfreeMemoryArray(&fixedvarnames); BMSfreeMemoryArray(&consnames); } if( prob->transformed ) { /* free memory */ BMSfreeMemoryArray(&conss); } } else { *result = SCIP_DIDNOTRUN; retcode = SCIP_OKAY; } /* check for reader errors */ if( retcode == SCIP_WRITEERROR ) return retcode; SCIP_CALL( retcode ); return SCIP_OKAY; }
/** 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); }
/** Parse file */ XML_NODE* xml_process( const char* filename /**< XML file name */ ) { PPOS ppos; XML_NODE* node = NULL; XML_ATTR* attr; int result = FALSE; char* myfilename; ALLOC_FALSE( BMSduplicateMemoryArray(&myfilename, filename, strlen(filename) + 5) ); #ifdef WITH_ZLIB if (access(filename, R_OK) != 0) { strcat(myfilename, ".gz"); /* If .gz also does not work, revert to the old name * to get a better error message. */ if (access(myfilename, R_OK) != 0) strcpy(myfilename, filename); } #endif ppos.fp = FOPEN(myfilename, "r"); if ( ppos.fp == NULL ) perror(myfilename); else { ppos.filename = myfilename; ppos.buf[0] = '\0'; ppos.pos = 0; ppos.lineno = 1; ppos.nextsym = 0; ppos.lastsym = 0; ppos.state = STATE_BEFORE; ppos.top = NULL; node = xml_new_node("#ROOT", ppos.lineno); if ( node == NULL ) { xml_error(&ppos, "Can't create new node"); } else { attr = xml_new_attr("filename", myfilename); if ( attr == NULL ) xml_error(&ppos, "Can't create new attribute"); else { xml_add_attr(node, attr); /* push root node on stack and start to process */ if ( push_pstack(&ppos, node) ) { result = xml_parse(&ppos); clear_pstack(&ppos); } } } if ( ! result && (node != NULL) ) { xml_errmsg(&ppos, "Parsing error, processing stopped", TRUE, __FILE__, __LINE__); xml_free_node(node); node = NULL; } if (FCLOSE(ppos.fp)) perror(myfilename); } BMSfreeMemoryArray(&myfilename); return node; }
/** 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; }
/** Handles a CDATA section. * * Returns a pointer to allocated memory containing the data of this section or NULL in case of an * error. */ static char* do_cdata( PPOS* ppos ) { char* data = NULL; size_t size = 0; size_t len = 0; int state = 0; int c; assert(ppos != NULL); for(;;) { c = getsymbol(ppos); if (c == EOF) break; if (c == ']') state++; else if ((c == '>') && (state >= 2)) break; else state = 0; if (len == size) { size += DATA_EXT_SIZE; if ( data == NULL ) { ALLOC_ABORT( BMSallocMemoryArray(&data, size) ); } else { ALLOC_ABORT( BMSreallocMemoryArray(&data, size) ); } } assert(data != NULL); assert(size > len); data[len++] = (char)c; } assert(data != NULL); if (c != EOF) { assert(len >= 2); data[len - 2] = '\0'; } else { BMSfreeMemoryArray(&data); data = NULL; xml_error(ppos, "Unexpected EOF in CDATA"); } return data; }
/** Process tag */ static void proc_in_tag( PPOS* ppos /**< input stream position */ ) { XML_ATTR* attr; int c; int empty = FALSE; char* name; char* value; assert(ppos != NULL); assert(ppos->state == STATE_IN_TAG); c = skip_space(ppos); if ((c == '/') || (c == '>') || (c == EOF)) { if (c == '/') { empty = TRUE; c = getsymbol(ppos); } if (c == EOF) { xml_error(ppos, "Unexpected EOF while in a tag"); ppos->state = STATE_ERROR; } if (c == '>') { ppos->state = STATE_PCDATA; if (empty && ! pop_pstack(ppos)) ppos->state = STATE_ERROR; } else { xml_error(ppos, "Expected tag end marker '>'"); ppos->state = STATE_ERROR; } } else { ungetsymbol(ppos, c); if ((name = get_name(ppos)) == NULL) { xml_error(ppos, "No name for attribute"); ppos->state = STATE_ERROR; } else { c = skip_space(ppos); if ((c != '=') || ((value = get_attrval(ppos)) == NULL)) { xml_error(ppos, "Missing attribute value"); ppos->state = STATE_ERROR; BMSfreeMemoryArray(&name); } else { if (NULL == (attr = xml_new_attr(name, value))) { xml_error(ppos, "Can't create new attribute"); ppos->state = STATE_ERROR; } else { xml_add_attr(top_pstack(ppos), attr); } BMSfreeMemoryArray(&name); BMSfreeMemoryArray(&value); } } } }
/** 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; }