void clq_sep_separate( CliqueSeparation *sep, const double x[] ) { const CGraph *cgraph = sep->cgraph; clq_set_clear( sep->clqSet ); clq_set_clear( sep->clqSetOrig ); clq_sep_check_node_cap( sep ); CliqueSet *clqSetOrig = sep->clqSetOrig; clq_set_clear( clqSetOrig ); /* before extension, orig indexes */ CliqueSet *clqSet = sep->clqSet; clq_set_clear( clqSet ); /* final clique set */ int *iv = sep->iv; const double minFrac = sep->minFrac; { IntQueue queue; int i, *neighs, csize = cgraph_size(cgraph); char inQueue[csize]; //'1' if a vertices is already in queue - '0' otherwise neighs = xmalloc(sizeof(int) * csize * 10); vint_queue_init(&queue, csize); for(i = 0; i < csize; i++) { if(cgraph_degree(cgraph, i) == 0) //deleting variables that are not binary { iv[i] = -1; inQueue[i] = '0'; //just to avoid memory problems } else if(cgraph_degree(cgraph, i) == 1 || fracPart(x[i]) < minFrac) { //integer variables and variables that have conflict only with their complements are deleted iv[i] = -1; vint_queue_push(&queue, i); inQueue[i] = '1'; } else { iv[i] = cgraph_degree(cgraph, i); inQueue[i] = '0'; } } while(!vint_queue_is_empty(&queue)) { int v; vint_queue_pop(&queue, &v); int nsize = cgraph_get_all_conflicting(cgraph, v, neighs, csize * 10); for(i = 0; i < nsize; i++) { int u = neighs[i]; if(iv[u] == -1) continue; assert(iv[u] > 0); iv[u]--; //considering v was deleted if(iv[u] == 0) { iv[u] = -1; if(inQueue[u] == '0') { vint_queue_push(&queue, u); inQueue[u] = '1'; } } } } int idx = 0; for(i = 0; i < csize; i++) if(iv[i] > 0) iv[i] = idx++; free(neighs); vint_queue_clean(&queue); } CGraph *ppcg = cgraph_create_induced_subgraph( cgraph, iv ); cgraph_set_low_degree( ppcg, sep->enumUsage ); clq_sep_update_ppgraph_weights( ppcg, cgraph_size(cgraph), x ); /* if enumeration is used, iv will be update*/ if (sep->verbose) cgraph_print_summary( ppcg, "pre-processed graph - part 1" ); /* separation works with integer weights */ const int minW = (int)(1000.0 + (sep->minViol*1000.0)); char enumerationComplete = 0; if ( sep->enumUsage > 0 ) { clq_enum_set_min_weight( sep->clqEnum, minW ); int enumNodes = clq_sep_enum_all_cliques_low_degree_nodes( sep, iv, ppcg ); if (enumNodes < cgraph_size(ppcg)) { /* more processing will be needed, creating a another preprocesses graph without already enumerated nodes */ cgraph_free( &ppcg ); ppcg = cgraph_create_induced_subgraph( cgraph, iv ); cgraph_set_low_degree( ppcg, sep->enumUsage ); clq_sep_update_ppgraph_weights( ppcg, cgraph_size(cgraph), x ); if (sep->verbose) cgraph_print_summary( ppcg, "pre-processed graph - part 2" ); } else { if (sep->verbose) printf("pre-processed graph - part 2 - no nodes left. all cliques have been enumerated.\n"); enumerationComplete = 1; } } int firstGraspClique = clq_set_number_of_cliques( clqSetOrig ); if ( (!enumerationComplete) && (cgraph_size(ppcg)>=2) ) { sep->bk = bk_create( ppcg ); clock_t startBK = clock(); int stillWorkToDo = bk_run( sep->bk, minW, sep->maxTimeBK ); clock_t endBK = clock(); if (sep->verbose) { printf("bk took %.3g seconds\n", ((double)endBK-startBK)/((double)CLOCKS_PER_SEC) ); } CliqueSet *bkClqSet = bk_get_clq_set(sep->bk); if (bkClqSet) { if (clq_set_number_of_cliques( bkClqSet )) { #ifdef DEBUG int nc = clq_set_number_of_cliques( bkClqSet ); int ic; for ( ic = 0 ; (ic<nc) ; ++ic ) { const IntSet *is = clq_set_get_clique( bkClqSet, ic ); int n1, n2; if (!clq_validate( ppcg, vint_set_size(is), vint_set_get_elements(is), &n1, &n2 )) { fprintf( stderr, "Nodes %d and %d are not in conflict in ppcg.\n", n1, n2 ); exit( EXIT_FAILURE ); } int j; for ( j=0 ; (j<vint_set_size(is)) ; ++j ) { const int vidx = vint_set_get_elements(is)[j]; assert( vidx >=0 ); assert( vidx < cgraph_size(ppcg) ); } } #endif clq_set_add_using_original_indexes( clqSetOrig, bkClqSet , cgraph_get_original_node_indexes( ppcg ) ); } } if (stillWorkToDo) { Grasp *grasp = grasp_create( ppcg, minW ); if (sep->verbose) { printf("running grasp\n"); } clock_t graspStart = clock(); grasp_run( grasp ); const CliqueSet *graspCliques = grasp_solution_set(grasp); /* before extension, pp indexes */ clq_set_add_using_original_indexes( clqSetOrig, graspCliques, cgraph_get_original_node_indexes( ppcg ) ); grasp_free( &grasp ); clock_t graspEnd = clock(); if (sep->verbose) { printf("grasp took %.3f seconds.\n", ((double)graspEnd-graspStart)/((double)CLOCKS_PER_SEC) ); } } bk_free( (sep->bk) ); sep->bk = NULL; } /* extending cliques */ vmg_adjust_vector_capacity( (void**)&(sep->extended), &(sep->extendedCap), clq_set_number_of_cliques(clqSetOrig), sizeof(char) ); char *extended = sep->extended; memset( extended, 0, sizeof(char)*clq_set_number_of_cliques( clqSetOrig ) ); /* since grasp ran in a restricted subgraph, cliques found may be dominated by the ones found in the enumeration phase, checking ... */ { int i; for ( i=firstGraspClique ; (i<clq_set_number_of_cliques(clqSetOrig)) ; ++i ) { const IntSet *graspClique = clq_set_get_clique( clqSetOrig, i ); int j; for ( j=0 ; (j<firstGraspClique) ; ++j ) if ( clq_dominates( clq_set_get_clique( clqSetOrig, j ), graspClique ) ) extended[i] = 1; } } if (sep->extendCliques) { clock_t startExtend = clock(); CliqueExtender *clqe = sep->clqe; CliqueExtendingMethod clqem = CLQEM_RANDOM; if (sep->hasCosts) { clqe_set_costs( clqe, sep->costs, cgraph_size(cgraph) ); clqem = CLQEM_PRIORITY_GREEDY; } int i; for ( i=0 ; (i<clq_set_number_of_cliques( clqSetOrig )) ; ++i ) if (!extended[i]) extended[i] = clqe_extend( clqe, cgraph, clq_set_get_clique(clqSetOrig,i), clq_set_weight(clqSetOrig,i), clqem ); /* adding all extended cliques */ clq_set_add_cliques( clqSet, clqe_get_cliques( clqe ) ); clock_t endExtend = clock(); const double timeExtend = ((double)endExtend-startExtend) / ((double)CLOCKS_PER_SEC); if (sep->verbose) { printf("clique extension took %.3f seconds.\n", timeExtend); } } /* adding cliques which were not extended */ { int i; for ( i=0 ; (i<clq_set_number_of_cliques(clqSetOrig)) ; ++i ) if ( !extended[i] ) clq_set_add( clqSet, clq_set_clique_size(clqSetOrig,i), clq_set_clique_elements(clqSetOrig,i), clq_set_weight(clqSetOrig,i) ); } /* need to be informed again next call */ sep->hasCosts = 0; cgraph_free( &ppcg ); }
void clq_sep_separate( CliqueSeparation *sep, const double x[] ) { const CGraph *cgraph = sep->cgraph; clq_set_clear( sep->clqSet ); clq_set_clear( sep->clqSetOrig ); clq_sep_check_node_cap( sep ); CliqueSet *clqSetOrig = sep->clqSetOrig; clq_set_clear( clqSetOrig ); /* before extension, orig indexes */ CliqueSet *clqSet = sep->clqSet; clq_set_clear( clqSet ); /* final clique set */ int *iv = sep->iv; const double minFrac = sep->minFrac; { IntQueue queue; int i, *neighs, csize = cgraph_size(cgraph); char inQueue[csize]; //'1' if a vertices is already in queue - '0' otherwise neighs = xmalloc(sizeof(int) * csize * 10); vint_queue_init(&queue, csize); for(i = 0; i < csize; i++) { if(cgraph_degree(cgraph, i) == 0) //deleting variables that are not binary { iv[i] = -1; inQueue[i] = '0'; //just to avoid memory problems } else if(cgraph_degree(cgraph, i) == 1 || (fracPart(x[i]) < minFrac && x[i] < 0.99)) { //integer variables and variables that have conflict only with their complements are deleted iv[i] = -1; vint_queue_push(&queue, i); inQueue[i] = '1'; } else { iv[i] = cgraph_degree(cgraph, i); inQueue[i] = '0'; } } while(!vint_queue_is_empty(&queue)) { int v; vint_queue_pop(&queue, &v); int nsize = cgraph_get_all_conflicting(cgraph, v, neighs, csize * 10); for(i = 0; i < nsize; i++) { int u = neighs[i]; if(iv[u] == -1) continue; assert(iv[u] > 0); iv[u]--; //considering v was deleted if(iv[u] == 0) { iv[u] = -1; if(inQueue[u] == '0') { vint_queue_push(&queue, u); inQueue[u] = '1'; } } } } int idx = 0; for(i = 0; i < csize; i++) if(iv[i] > 0) iv[i] = idx++; free(neighs); vint_queue_clean(&queue); } CGraph *ppcg = cgraph_create_induced_subgraph( cgraph, iv ); clq_sep_update_ppgraph_weights( ppcg, cgraph_size(cgraph), x ); if (sep->verbose) cgraph_print_summary( ppcg, "pre-processed graph - part 1" ); /* separation works with integer weights */ const int minW = (int)(1000.0 + (sep->minViol*1000.0)); if(cgraph_size(ppcg)>=2) { sep->bk = bk_create( ppcg ); clock_t startBK = clock(); bk_set_max_it(sep->bk, sep->maxItBK); bk_set_min_weight(sep->bk, minW); bk_run( sep->bk ); clock_t endBK = clock(); if (sep->verbose) { printf("bk took %.3g seconds\n", ((double)endBK-startBK)/((double)CLOCKS_PER_SEC) ); } const CliqueSet *bkClqSet = bk_get_clq_set(sep->bk); if (bkClqSet) { if (clq_set_number_of_cliques( bkClqSet )) { #ifdef DEBUG int nc = clq_set_number_of_cliques( bkClqSet ); int ic; for ( ic = 0 ; (ic<nc) ; ++ic ) { const IntSet *is = clq_set_get_clique( bkClqSet, ic ); int n1, n2; if (!clq_validate( ppcg, vint_set_size(is), vint_set_get_elements(is), &n1, &n2 )) { fprintf( stderr, "Nodes %d and %d are not in conflict in ppcg.\n", n1, n2 ); exit( EXIT_FAILURE ); } int j; for ( j=0 ; (j<vint_set_size(is)) ; ++j ) { const int vidx = vint_set_get_elements(is)[j]; assert( vidx >=0 ); assert( vidx < cgraph_size(ppcg) ); } } #endif clq_set_add_using_original_indexes( clqSetOrig, bkClqSet , cgraph_get_original_node_indexes( ppcg ) ); } } bk_free( (sep->bk) ); sep->bk = NULL; } /* extending cliques */ vmg_adjust_vector_capacity( (void**)&(sep->extended), &(sep->extendedCap), clq_set_number_of_cliques(clqSetOrig), sizeof(char) ); char *extended = sep->extended; memset( extended, 0, sizeof(char)*clq_set_number_of_cliques( clqSetOrig ) ); if (sep->extendCliques) { clock_t startExtend = clock(); CliqueExtender *clqe = sep->clqe; if(sep->hasCosts) clqe_set_costs( clqe, sep->costs, cgraph_size(cgraph) ); int i; for ( i=0 ; (i<clq_set_number_of_cliques( clqSetOrig )) ; ++i ) extended[i] = clqe_extend( clqe, cgraph, clq_set_get_clique(clqSetOrig,i), clq_set_weight(clqSetOrig,i), sep->extendCliques ); /* adding all extended cliques */ clq_set_add_cliques( clqSet, clqe_get_cliques( clqe ) ); clock_t endExtend = clock(); const double timeExtend = ((double)endExtend-startExtend) / ((double)CLOCKS_PER_SEC); if (sep->verbose) { printf("clique extension took %.3f seconds.\n", timeExtend); } } /* adding cliques which were not extended */ { int i; for ( i=0 ; (i<clq_set_number_of_cliques(clqSetOrig)) ; ++i ) if ( !extended[i] ) clq_set_add( clqSet, clq_set_clique_size(clqSetOrig,i), clq_set_clique_elements(clqSetOrig,i), clq_set_weight(clqSetOrig,i) ); } /* need to be informed again next call */ sep->hasCosts = 0; cgraph_free( &ppcg ); }