Exemplo n.º 1
0
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 );
}
Exemplo n.º 2
0
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 );
}