/* Global variables used: */ /* These must be saved and restored in re-entrance. */ static TLS_ATTR int *clique_size; /* c[i] == max. clique size in {0,1,...,i-1} */ static TLS_ATTR set_t current_clique; /* Current clique being searched. */ static TLS_ATTR set_t best_clique; /* Largest/heaviest clique found so far. */ #if0 staticstruct tms cputimer; /* Timer for opts->time_function() */ staticstruct timeval realtimer; /* Timer for opts->time_function() */ #endif static TLS_ATTR int clique_list_count=0; /* No. of cliques in opts->clique_list[] */ static TLS_ATTR int weight_multiplier=1; /* Weights multiplied by this when passing
* to time_function(). */
/* List cache (contains memory blocks of size g->n * sizeof(int)) */ static TLS_ATTR int **temp_list=NULL; static TLS_ATTR int temp_count=0;
/* *Macrosforre-entrance.ENTRANCE_SAVE()mustbecalledimmediately *aftervariabledefinitions,ENTRANCE_RESTORE()restoresglobal *variablestooriginalvalues.entrance_levelshouldbeincreased *anddecreasedaccordingly.
*/ staticint entrance_level=0; /* How many levels for entrance have occurred? */
#define ENTRANCE_SAVE() \ int *old_clique_size = clique_size; \
set_t old_current_clique = current_clique; \
set_t old_best_clique = best_clique; \ int old_clique_list_count = clique_list_count; \ int old_weight_multiplier = weight_multiplier; \ int **old_temp_list = temp_list; \ int old_temp_count = temp_count; /* structtmsold_cputimer;\ structtimevalold_realtimer;\ memcpy(&old_cputimer,&cputimer,sizeof(structtms));\ memcpy(&old_realtimer,&realtimer,sizeof(structtimeval))
*/
/* Number of clock ticks per second (as returned by sysconf(_SC_CLK_TCK)) */ staticint clocks_per_sec=0;
/* Recursion and helper functions */ static boolean sub_unweighted_single(int *table, int size, int min_size,
graph_t *g); staticint sub_unweighted_all(int *table, int size, int min_size, int max_size,
boolean maximal, graph_t *g,
clique_options *opts); staticint sub_weighted_all(int *table, int size, int weight, int current_weight, int prune_low, int prune_high, int min_weight, int max_weight, boolean maximal,
graph_t *g, clique_options *opts);
if (min_size) { if (clique_size[v]>=min_size) {
temp_list[temp_count++]=newtable; return clique_size[v];
} if (clique_size[v]+g->n-i-1 < min_size) {
temp_list[temp_count++]=newtable; return0;
}
}
}
temp_list[temp_count++]=newtable;
if (min_size) return0; return clique_size[v];
}
/* *sub_unweighted_single() * *Recursionfunctionforsearchingforasinglecliqueofsizemin_size. * *table-subsetoftheverticesingraph *size-sizeoftable *min_size-sizeofcliquetolookforwithinthesubgraph *(decreasedwitheveryrecursion) *g-thegraph * *ReturnsTRUEifacliqueofsizemin_sizeisfound,FALSEotherwise. *Ifacliqueofsizemin_sizeisfound,itisstoredincurrent_clique. * *clique_size[]forallvaluesintablemustbedefinedandcorrect, *otherwiseinaccurateresultsmayoccur.
*/ static boolean sub_unweighted_single(int *table, int size, int min_size,
graph_t *g) { int i; int v; int *newtable; int *p1, *p2;
/* Zero or one vertices needed anymore. */ if (min_size <= 1) { if (size>0 && min_size==1) {
set_empty(current_clique);
SET_ADD_ELEMENT(current_clique,table[0]); returnTRUE;
} if (min_size==0) {
set_empty(current_clique); returnTRUE;
} returnFALSE;
} if (size < min_size) returnFALSE;
/* Dynamic memory allocation with cache */ if (temp_count) {
temp_count--;
newtable=temp_list[temp_count];
} else {
newtable=malloc(g->n * sizeof(int));
}
for (i = size-1; i >= 0; i--) {
v = table[i];
if (clique_size[v] < min_size) break; /* This is faster when compiling with gcc than placing
* this in the for-loop condition. */ if (i+1 < min_size) break;
/* Very ugly code, but works faster than "for (i=...)" */
p1 = newtable; for (p2=table; p2 < table+i; p2++) { int w = *p2; if (GRAPH_IS_EDGE(g, v, w)) {
*p1 = w;
p1++;
}
}
/* Avoid unneccessary loops (next size == p1-newtable) */ if (p1-newtable < min_size-1) continue; /* Now p1-newtable >= min_size-1 >= 2-1 == 1, so we can use
* p1-newtable-1 safely. */ if (clique_size[newtable[p1-newtable-1]] < min_size-1) continue;
/* *sub_unweighted_all() * *Recursionfunctionforsearchingforallcliquesofgivensize. * *table-subsetofverticesofgraphg *size-sizeoftable *min_size-minimumsizeofcliquestosearchfor(decreasedwith *everyrecursion) *max_size-maximumsizeofcliquestosearchfor(decreasedwith *everyrecursion).Ifnoupperlimitisdesired,use *eg.INT_MAX *maximal-requirecliquestobemaximal(passedthrough) *g-thegraph *opts-storageoptions * *Allcliquesofsuitablesizefoundarestoredaccordingtoopts. * *Returnsthenumberofcliquesfound.Ifuser_functionreturnsFALSE, *thenthenumberofcliquesisreturnednegative. * *Usescurrent_cliquetostorethecurrently-being-searchedclique. *clique_size[]forallvaluesintablemustbedefinedandcorrect, *otherwiseinaccurateresultsmayoccur.
*/ staticint sub_unweighted_all(int *table, int size, int min_size, int max_size,
boolean maximal, graph_t *g,
clique_options *opts) { int i; int v; int n; int *newtable; int *p1, *p2; int count=0; /* Amount of cliques found */
if (min_size <= 0) { if ((!maximal) || is_maximal(current_clique,g)) { /* We've found one. Store it. */
count++; if (!store_clique(current_clique,g,opts)) { return -count;
}
} if (max_size <= 0) { /* If we add another element, size will be too big. */ return count;
}
}
if (size < min_size) { return count;
}
/* Dynamic memory allocation with cache */ if (temp_count) {
temp_count--;
newtable=temp_list[temp_count];
} else {
newtable=malloc(g->n * sizeof(int));
}
for (i=size-1; i>=0; i--) {
v = table[i]; if (clique_size[v] < min_size) { break;
} if (i+1 < min_size) { break;
}
/* Very ugly code, but works faster than "for (i=...)" */
p1 = newtable; for (p2=table; p2 < table+i; p2++) { int w = *p2; if (GRAPH_IS_EDGE(g, v, w)) {
*p1 = w;
p1++;
}
}
/* *weighted_clique_search_single() * *Searchesforasinglecliqueofweightatleastmin_weight,andat *mostmax_weight.Storesmaximumcliquesizesintoclique_size[] *(ormin_weight-1,whicheverissmaller). * *table-theorderoftheverticesingtouse *min_weight-minimumweightofcliquetosearchfor.Ifmin_weight==0, *thensearchesforamaximumweightclique *max_weight-maximumweightofcliquetosearchfor.Ifnoupperlimit *isdesired,useeg.INT_MAX *g-thegraph *opts-timeprintingoptions * *opts->time_functioniscalledaftereachbase-levelrecursion,if *non-NULL. * *Returns0ifacliqueofrequestedweightwasnotfound(alsoif *time_functionrequestedanabort),otherwisereturns>=1. *Ifmin_weight==0(searchformaximum-weightclique),thenthereturn *valueistheweightofthecliquefound.Thefoundcliqueisstored *inbest_clique. * *Note:DoesNOTuseopts->user_functionofopts->clique_list.
*/ staticint weighted_clique_search_single(int *table, int min_weight, int max_weight, graph_t *g,
clique_options *opts) { #if0 struct timeval timeval; struct tms tms; #endif int i,j; int v; int *newtable; int newsize; int newweight; int search_weight; int min_w;
clique_options localopts;
if (min_weight==0)
min_w=INT_MAX; else
min_w=min_weight;
if (min_weight==1) { /* min_weight==1 may cause trouble in the routine, and *it'strivialtocheckasit'sowncase.
* We write nothing to clique_size[]. */ for (i=0; i < g->n; i++) { if (g->weights[table[i]] <= max_weight) {
set_empty(best_clique);
SET_ADD_ELEMENT(best_clique,table[i]); return g->weights[table[i]];
}
} return0;
}
/* *sub_weighted_all() * *Recursionfunctionforsearchingforallcliquesofgivenweight. * *table-subsetofverticesofgraphg *size-sizeoftable *weight-totalweightofverticesintable *current_weight-weightofcliquefoundsofar *prune_low-ignoreallcliqueswithweightlessorequaltothisvalue *(oftenheaviestcliquefoundsofar)(passedthrough) *prune_high-maximumweightpossibleforcliqueinthissubgraph *(passedthrough) *min_size-minimumweightofcliquestosearchfor(passedthrough) *Mustbegreaterthan0. *max_size-maximumweightofcliquestosearchfor(passedthrough) *Ifnoupperlimitisdesired,useeg.INT_MAX *maximal-searchonlyformaximalcliques *g-thegraph *opts-storageoptions * *Allcliquesofsuitableweightfoundarestoredaccordingtoopts. * *Returnsweightofheaviestcliquefound(prune_lowifaheavierclique *hasn'tbeenfound);ifacliquewithweightatleastmin_sizeisfound *thenmin_size-1isreturned.Ifcliquestoragefailed,-1isreturned. * *Thelargestcliquefoundsmallerthanmax_weightisstoredin *best_clique,ifnon-NULL. * *Usescurrent_cliquetostorethecurrently-being-searchedclique. *clique_size[]forallvaluesintablemustbedefinedandcorrect, *otherwiseinaccurateresultsmayoccur. * *Tosearchforasinglemaximumclique,usemin_weight==max_weight==INT_MAX, *withbest_cliquenon-NULL.Tosearchforasinglegiven-weightclique, *useopts->clique_listandopts->user_function=false_function.When *searchingforallcliques,min_weightshouldbegiventheminimumweight *desired.
*/ staticint sub_weighted_all(int *table, int size, int weight, int current_weight, int prune_low, int prune_high, int min_weight, int max_weight, boolean maximal,
graph_t *g, clique_options *opts) { int i; int v,w; int *newtable; int *p1, *p2; int newweight;
if (current_weight >= min_weight) { if ((current_weight <= max_weight) &&
((!maximal) || is_maximal(current_clique,g))) { /* We've found one. Store it. */ if (!store_clique(current_clique,g,opts)) { return -1;
}
} if (current_weight >= max_weight) { /* Clique too heavy. */ return min_weight-1;
}
} if (size <= 0) { /* current_weight < min_weight, prune_low < min_weight,
* so return value is always < min_weight. */ if (current_weight>prune_low) { if (best_clique)
set_copy(best_clique,current_clique); if (current_weight < min_weight) return current_weight; else return min_weight-1;
} else { return prune_low;
}
}
/* Dynamic memory allocation with cache */ if (temp_count) {
temp_count--;
newtable=temp_list[temp_count];
} else {
newtable=malloc(g->n * sizeof(int));
}
for (i = size-1; i >= 0; i--) {
v = table[i]; if (current_weight+clique_size[v] <= prune_low) { /* Dealing with subset without heavy enough clique. */ break;
} if (current_weight+weight <= prune_low) { /* Even if all elements are added, won't do. */ break;
}
/* Very ugly code, but works faster than "for (i=...)" */
p1 = newtable;
newweight = 0; for (p2=table; p2 < table+i; p2++) {
w = *p2; if (GRAPH_IS_EDGE(g, v, w)) {
*p1 = w;
newweight += g->weights[w];
p1++;
}
}
w=g->weights[v];
weight-=w; /* Avoid a few unneccessary loops */ if (current_weight+w+newweight <= prune_low) { continue;
}
/* Search as normal until there is a chance to find a suitable
* clique. */ if (unweighted_clique_search_single(table,min_size,g,opts)==0) {
count=0; goto cleanreturn;
}
if (min_size==0 && max_size==0) {
min_size=max_size=clique_size[table[g->n-1]];
maximal=FALSE; /* No need to test, since we're searching
* for maximum cliques. */
} if (max_size==0) {
max_size=INT_MAX;
}
for (i=0; i < g->n-1; i++) if (clique_size[table[i]] >= min_size) break;
count=unweighted_clique_search_all(table,i,min_size,max_size,
maximal,g,opts);
if ((max_weight>0) && (min_weight>max_weight)) { /* state was not changed */
entrance_level--; return NULL;
}
#if0 if (clocks_per_sec==0)
clocks_per_sec=sysconf(_SC_CLK_TCK);
ASSERT(clocks_per_sec>0); #endif
/* Check whether we can use unweighted routines. */ if (!graph_weighted(g)) {
min_weight=DIV_UP(min_weight,g->weights[0]); if (max_weight) {
max_weight=DIV_DOWN(max_weight,g->weights[0]); if (max_weight < min_weight) { /* state was not changed */
entrance_level--; return NULL;
}
}
if (weighted_clique_search_single(table,min_weight,max_weight,
g,opts)==0) { /* Requested clique has not been found. */
set_free(best_clique);
best_clique=NULL; goto cleanreturn;
} if (maximal && (min_weight>0)) {
maximalize_clique(best_clique,g); if (graph_subgraph_weight(g,best_clique) > max_weight) {
clique_options localopts;
if ((max_weight>0) && (min_weight>max_weight)) { /* state was not changed */
entrance_level--; return0;
}
#if0 if (clocks_per_sec==0)
clocks_per_sec=sysconf(_SC_CLK_TCK);
ASSERT(clocks_per_sec>0); #endif
if (!graph_weighted(g)) {
min_weight=DIV_UP(min_weight,g->weights[0]); if (max_weight) {
max_weight=DIV_DOWN(max_weight,g->weights[0]); if (max_weight < min_weight) { /* state was not changed */
entrance_level--; return0;
}
}
/* First phase */
n=weighted_clique_search_single(table,min_weight,INT_MAX,g,opts); if (n==0) { /* Requested clique has not been found. */ goto cleanreturn;
}
if (min_weight==0) {
min_weight=n;
max_weight=n;
maximal=FALSE; /* They're maximum cliques already. */
} if (max_weight==0)
max_weight=INT_MAX;
for (i=0; i < g->n; i++) if ((clique_size[table[i]] >= min_weight) ||
(clique_size[table[i]] == 0)) break;
/* Second phase */
n=weighted_clique_search_all(table,i,min_weight,max_weight,maximal,
g,opts);
cleanreturn: /* Free resources */ for (i=0; i < temp_count; i++)
free(temp_list[i]);
free(temp_list);
free(table);
set_free(current_clique);
set_free(best_clique);
free(clique_size);
ENTRANCE_RESTORE();
entrance_level--;
return n;
}
/* *clique_print_time() * *Reportscurrentrunninginformationevery0.1secondsorwhenvalues *change. * *level-re-entrancelevel *i-currentrecursionlevel *n-maximumrecursionlevel *max-weightofheaviestcliquefound *cputime-CPUtimeusedinalgorithmsofar *realtime-realtimeusedinalgorithmsofar *opts-printsinformationto(FILE*)opts->output(orstdoutifNULL) * *ReturnsalwaysTRUE(ie.neverrequestsabort).
*/
boolean clique_print_time(int level, int i, int n, int max, double cputime, double realtime,
clique_options *opts) { staticfloat prev_time=100; staticint prev_i=100; staticint prev_max=100; staticint prev_level=0;
FILE *fp=opts->output; int j;
if (fp==NULL)
fp=stdout;
if (ABS(prev_time-realtime)>0.1 || i==n || i<prev_i || max!=prev_max ||
level!=prev_level) { for (j=1; j<level; j++)
fprintf(fp," "); if (realtime-prev_time < 0.01 || i<=prev_i)
fprintf(fp,"%3d/%d (max %2d) %2.2f s " "(0.00 s/round)\n",i,n,max,
realtime); else
fprintf(fp,"%3d/%d (max %2d) %2.2f s " "(%2.2f s/round)\n",
i,n,max,realtime,
(realtime-prev_time)/(i-prev_i));
prev_time=realtime;
prev_i=i;
prev_max=max;
prev_level=level;
} returnTRUE;
}
/* *clique_print_time_always() * *Reportscurrentrunninginformation. * *level-re-entrancelevel *i-currentrecursionlevel *n-maximumrecursionlevel *max-largestcliquefound *cputime-CPUtimeusedinalgorithmsofar *realtime-realtimeusedinalgorithmsofar *opts-printsinformationto(FILE*)opts->output(orstdoutifNULL) * *ReturnsalwaysTRUE(ie.neverrequestsabort).
*/
boolean clique_print_time_always(int level, int i, int n, int max, double cputime, double realtime,
clique_options *opts) { staticfloat prev_time=100; staticint prev_i=100;
FILE *fp=opts->output; int j;
if (fp==NULL)
fp=stdout;
for (j=1; j<level; j++)
fprintf(fp," ");
if (realtime-prev_time < 0.01 || i<=prev_i)
fprintf(fp,"%3d/%d (max %2d) %2.2f s (0.00 s/round)\n",
i,n,max,realtime); else
fprintf(fp,"%3d/%d (max %2d) %2.2f s (%2.2f s/round)\n",
i,n,max,realtime,(realtime-prev_time)/(i-prev_i));
prev_time=realtime;
prev_i=i;
/* Free/alloc extra edge-sets */ for (i=size; i < g->n; i++)
set_free(g->edges[i]);
g->edges=realloc(g->edges, size * sizeof(set_t)); for (i=g->n; i < size; i++)
g->edges[i]=set_new(size);
/* Resize original sets */ for (i=0; i < MIN(g->n,size); i++) {
g->edges[i]=set_resize(g->edges[i],size);
}
for (i=0; i < g->n; i++) {
printf("%2d",i); if (weighted) {
printf(" w=%d",g->weights[i]); if (g->weights[i] <= 0) {
printf("*NON-POSITIVE*");
nonpos++;
}
} if (weight < INT_MAX)
weight+=g->weights[i];
printf(" ->"); for (j=0; j < g->n; j++) { if (SET_CONTAINS_FAST(g->edges[i],j)) {
printf(" %d",j); if (i==j) {
printf("*REFLEXIVE*");
refl++;
} if (!SET_CONTAINS_FAST(g->edges[j],i)) {
printf("*ASYMMERTIC*");
asymm++;
}
}
} for (j=g->n; j < SET_ARRAY_LENGTH(g->edges[i])*ELEMENTSIZE;
j++) { if (SET_CONTAINS_FAST(g->edges[i],j)) {
printf(" %d*NON-EXISTENT*",j);
extra++;
}
}
printf("\n");
}
if (asymm)
printf(" WARNING: Graph contained %d asymmetric edges!\n",
asymm); if (refl)
printf(" WARNING: Graph contained %d reflexive edges!\n",
refl); if (nonpos)
printf(" WARNING: Graph contained %d non-positive vertex " "weights!\n",nonpos); if (extra)
printf(" WARNING: Graph contained %d edges to " "non-existent vertices!\n",extra); if (weight>=INT_MAX)
printf(" WARNING: Total graph weight >= INT_MAX!\n"); return;
}
/* *graph_test() * *Testsgraphgtobevalid.Checksthatgisnon-NULL,theedgesare *symmetricandanti-reflexive,andthatallvertexweightsarepositive. *Ifoutputisnon-NULL,printsafewlinestellingthestatusofthegraph *tofiledescriptoroutput. * *ReturnsTRUEifthegraphisvalid,FALSEotherwise.
*/
boolean graph_test(graph_t *g,FILE *output) { int i,j; int edges=0; int asymm=0; int nonpos=0; int refl=0; int extra=0; unsignedint weight=0;
boolean weighted;
ASSERT((sizeof(setelement)*8)==ELEMENTSIZE);
if (g==NULL) { if (output)
fprintf(output," WARNING: Graph pointer is NULL!\n"); returnFALSE;
}
weighted=graph_weighted(g);
for (i=0; i < g->n; i++) { if (g->edges[i]==NULL) { if (output)
fprintf(output," WARNING: Graph edge set " "NULL!\n" " (further warning suppressed)\n"); returnFALSE;
} if (SET_MAX_SIZE(g->edges[i]) < g->n) { if (output)
fprintf(output," WARNING: Graph edge set " "too small!\n" " (further warnings suppressed)\n"); returnFALSE;
} for (j=0; j < g->n; j++) { if (SET_CONTAINS_FAST(g->edges[i],j)) {
edges++; if (i==j) {
refl++;
} if (!SET_CONTAINS_FAST(g->edges[j],i)) {
asymm++;
}
}
} for (j=g->n; j < SET_ARRAY_LENGTH(g->edges[i])*ELEMENTSIZE;
j++) { if (SET_CONTAINS_FAST(g->edges[i],j))
extra++;
} if (g->weights[i] <= 0)
nonpos++; if (weight<INT_MAX)
weight += g->weights[i];
}
edges/=2; /* Each is counted twice. */
if (output) { /* Semi-weighted means all weights are equal, but not 1. */
fprintf(output,"%s graph has %d vertices, %d edges " "(density %.2f).\n",
weighted?"Weighted":
((g->weights[0]==1)?"Unweighted":"Semi-weighted"),
g->n,edges,(float)edges/((float)(g->n - 1)*(g->n)/2));
if (asymm)
fprintf(output," WARNING: Graph contained %d " "asymmetric edges!\n",asymm); if (refl)
fprintf(output," WARNING: Graph contained %d " "reflexive edges!\n",refl); if (nonpos)
fprintf(output," WARNING: Graph contained %d " "non-positive vertex weights!\n",nonpos); if (extra)
fprintf(output," WARNING: Graph contained %d edges " "to non-existent vertices!\n",extra); if (weight>=INT_MAX)
fprintf(output," WARNING: Total graph weight >= " "INT_MAX!\n"); if (asymm==0 && refl==0 && nonpos==0 && extra==0 &&
weight<INT_MAX)
fprintf(output,"Graph OK.\n");
}
if (asymm || refl || nonpos || extra || weight>=INT_MAX) returnFALSE;
returnTRUE;
}
/* *graph_test_regular() * *Returnsthevertexdegreeforregulargraphs,or-1ifthegraphis *notregular.
*/ int graph_test_regular(graph_t *g) { int i,n;
n=set_size(g->edges[0]);
for (i=1; i < g->n; i++) { if (set_size(g->edges[i]) != n) return -1;
} return n;
}
/* *reorder_by_reverse() * *Returnsareverseidentityordering.
*/ int *reorder_by_reverse(graph_t *g,boolean weighted) { int i; int *order;
order=malloc(g->n * sizeof(int)); for (i=0; i < g->n; i++)
order[i]=g->n-i-1; return order;
}
/* *reorder_by_greedy_coloring() * *Equivalenttoreorder_by_weighted_greedy_coloringor *reorder_by_unweighted_greedy_coloringaccordingtothevalueofweighted.
*/ int *reorder_by_greedy_coloring(graph_t *g,boolean weighted) { if (weighted) return reorder_by_weighted_greedy_coloring(g,weighted); else return reorder_by_unweighted_greedy_coloring(g,weighted);
}
/* *reorder_by_unweighted_greedy_coloring() * *Returnsanorderingforthegraphgbycoloringthecliqueone *coloratatime,alwaysaddingthevertexoflargestdegreewithin *theuncoloredgraph,andnumberingthesevertices0,1,... * *Experimentallyefficientforusewithunweightedgraphs.
*/ int *reorder_by_unweighted_greedy_coloring(graph_t *g,boolean weighted) { int i,j,v;
boolean *tmp_used; int *degree; /* -1 for used vertices */ int *order; int maxdegree,maxvertex=0;
boolean samecolor;
for (i=0; i < g->n; i++) { for (j=0; j < g->n; j++) {
ASSERT(!((i==j) && GRAPH_IS_EDGE(g,i,j))); if (GRAPH_IS_EDGE(g,i,j))
degree[i]++;
}
}
v=0; while (v < g->n) { /* Reset tmp_used. */
memset(tmp_used,0,g->n * sizeof(boolean));
do { /* Find vertex to be colored. */
maxdegree=0;
samecolor=FALSE; for (i=0; i < g->n; i++) { if (!tmp_used[i] && degree[i] >= maxdegree) {
maxvertex=i;
maxdegree=degree[i];
samecolor=TRUE;
}
} if (samecolor) {
order[v]=maxvertex;
degree[maxvertex]=-1;
v++;
/* Mark neighbors not to color with same
* color and update neighbor degrees. */ for (i=0; i < g->n; i++) { if (GRAPH_IS_EDGE(g,maxvertex,i)) {
tmp_used[i]=TRUE;
degree[i]--;
}
}
}
} while (samecolor);
}
free(tmp_used);
free(degree); return order;
}
/* *reorder_by_weighted_greedy_coloring() * *Returnsanorderingforthegraphgbycoloringthecliqueone *coloratatime,alwaysaddingthevertexthat(inorderofimportance): *1.hastheminimumweightintheremaininggraph *2.hasthelargestsumofweightssurroundingthevertex * *Experimentallyefficientforusewithweightedgraphs.
*/ int *reorder_by_weighted_greedy_coloring(graph_t *g, boolean weighted) { int i,j,p=0; int cnt; int *nwt; /* Sum of surrounding vertices' weights */ int min_wt,max_nwt;
boolean *used; int *order;
for (i=0; i < g->n; i++) {
nwt[i]=0; for (j=0; j < g->n; j++) if (GRAPH_IS_EDGE(g, i, j))
nwt[i] += g->weights[j];
}
for (cnt=0; cnt < g->n; cnt++) {
min_wt=INT_MAX;
max_nwt=-1; for (i=g->n-1; i>=0; i--) if ((!used[i]) && (g->weights[i] < min_wt))
min_wt=g->weights[i]; for (i=g->n-1; i>=0; i--) { if (used[i] || (g->weights[i] > min_wt)) continue; if (nwt[i] > max_nwt) {
max_nwt=nwt[i];
p=i;
}
}
order[cnt]=p;
used[p]=TRUE; for (j=0; j < g->n; j++) if ((!used[j]) && (GRAPH_IS_EDGE(g, p, j)))
nwt[j] -= g->weights[p];
}
free(nwt);
free(used);
ASSERT(reorder_is_bijection(order,g->n));
return order;
}
/* *reorder_by_degree() * *Returnsareorderingofthegraphgsothattheverticeswithlargest *degrees(mostneighbors)arefirst.
*/ int *reorder_by_degree(graph_t *g, boolean weighted) { int i,j,v; int *degree; int *order; int maxdegree,maxvertex=0;
/* This is an interface between nauty and cliquer for finding
cliques of a given size in an undirected graph. */
int
find_clique(graph *g, int m, int n, int min, int max, boolean maximal) /* If there is a clique of size [min,max], perhaps required to be maximal,thenreturnitssize.Ifthereisnone,return0. Itisrequiredthatmin<=max.Usemin=max=0toaskfor
maximum cliques. */
{
graph_t *gg;
set_t cliq;
set *gi; int i,j,size;
gg = graph_new(n);
for (i = 0, gi = g; i < n; ++i, gi += m) for (j = i; (j = nextelement(gi,m,j)) >= 0; )
GRAPH_ADD_EDGE(gg,i,j);
int
find_indset(graph *g, int m, int n, int min, int max, boolean maximal) /* If there is an independent set of size [min,max], perhaps required tobemaximal,thenreturnitssize.Ifthereisnone,return0. Itisrequiredthatmin<=max.Usemin=max=0toaskfor
maximum independent sets. */
{
graph_t *gg;
set_t cliq;
set *gi; int i,j,jj,size;
gg = graph_new(n);
/* Make gg the complement of g */ for (i = 0, gi = g; i < n; ++i, gi += m)
{ for (j = jj = i; (j = nextelement(gi,m,j)) >= 0; )
{ while (++jj < j) GRAPH_ADD_EDGE(gg,i,jj);
} while (++jj < n) GRAPH_ADD_EDGE(gg,i,jj);
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.111Bemerkung:
(vorverarbeitet am 2026-06-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.