Example #1
0
_seq<intT> setCover(Graph GS) {
    double epsilon = 0.01;
    intT m = maxElt(GS);
    cout << "m = " << m << endl;

    bucketTime.start();
    pair<bucket*, int> B = putInBuckets(GS, epsilon);
    bucketTime.stop();
    bucket* allBuckets = B.first;
    int numBuckets = B.second;

    set* S = newA(set, GS.n);    // holds sets for current bucket
    set* ST = newA(set, GS.n);   // temporarily S (pack is not inplace)
    int l = 0;                   // size of S
    bool* flag = newA(bool, GS.n);
    intT* inCover = newA(intT, GS.n);
    intT nInCover = 0;
    intT totalWork = 0;
    intT* elts = newA(intT,m);
    intT threshold = GS.n;
    for (int i = 0; i < m; i++) elts[i] = INT_MAX;

    // loop over all buckets, largest degree first
    for (int i = numBuckets-1; i >= 0; i--) {
        bucket currentB = allBuckets[i];

        intT degreeThreshold = ceil(pow(1.0+epsilon,i));
        if (degreeThreshold == threshold && currentB.n == 0) continue;
        else threshold = degreeThreshold;
        packTime.start();

        // pack leftover sets that are below threshold down for the next round
        for (int j = 0; j < l; j++)
            flag[j] = (S[j].degree > 0 && S[j].degree < threshold);
        intT ln = sequence::pack(S, ST, flag, l);

        // pack leftover sets greater than threshold above for this round
        for (int j = 0; j < l; j++)
            flag[j] = (S[j].degree >= threshold);
        intT lb = sequence::pack(S, ST+ln, flag, l);

        // copy prebucketed bucket i to end, also for this round
        for (int j = 0; j < currentB.n; j++)
            ST[j+ln+lb] = currentB.S[j];

        lb = lb + currentB.n;   // total number in this round
        l = ln + lb;            // total number including those for next round
        swap(ST,S);             // since pack is not in place
        set* SB = S + ln;       // pointer to bottom of sets for this round
        packTime.stop();

        if (lb > 0) { // is there anything to do in this round?

            manisTime.start();
            intT work = processBucket(SB, elts, lb, threshold);
            totalWork += work;
            manisTime.stop();
            packTime.start();

            // check which sets were selected by manis to be in the set cover
            for (int j = 0; j < lb; j++)
                flag[j] = SB[j].degree < 0;

            // add these to inCover and label by their original ID
            int nNew = sequence::packIndex(inCover+nInCover, flag, lb);
            for (int j = nInCover; j < nInCover + nNew; j++)
                inCover[j] = SB[inCover[j]].id;
            nInCover = nInCover + nNew;
            packTime.stop();
            cout << "i = " << i << " bc = " << currentB.n << " l = " << l << " lb = " << lb
                 << " work = " << work << " new = " << nNew << " threshold = " << threshold << endl;
        }
    }
    cout << "Set cover size = " << nInCover << endl;
    cout << "Total work = " << totalWork << endl;
    cout << "Bucket Time = " << bucketTime.total() << endl;
    cout << "Manis Time = " << manisTime.total() << endl;
    cout << "Pack Time = " << packTime.total() << endl;

    free(elts);
    free(S);
    free(ST);
    free(flag);
    freeBuckets(allBuckets);
    return _seq<intT>(inCover, nInCover);
}