/*
 * Revision Control Information
 *
 * $Source$
 * $Author$
 * $Revision$
 * $Date$
 *
 */
/*
    module: gasp.c

    The "last_gasp" heuristic computes the reduction of each cube in
    the cover (without replacement) and then performs an expansion of
    these cubes.  The cubes which expand to cover some other cube are
    added to the original cover and irredundant finds a minimal subset.

    If one of the reduced cubes expands to cover some other reduced
    cube, then the new prime thus generated is a candidate for reducing
    the size of the cover.

    super_gasp is a variation on this strategy which extracts a minimal
    subset from the set of all prime implicants which cover all
    maximally reduced cubes.
*/

#include "espresso.h"

ABC_NAMESPACE_IMPL_START



/*
 *  reduce_gasp -- compute the maximal reduction of each cube of F
 *
 *  If a cube does not reduce, it remains prime; otherwise, it is marked
 *  as nonprime.   If the cube is redundant (should NEVER happen here) we
 *  just crap out ...
 *
 *  A cover with all of the cubes of F is returned.  Those that did
 *  reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
 *  The cubes are in the same order as in F.
 */
static pcover reduce_gasp(F, D)
pcover F, D;
{
    pcube p, last, cunder, *FD;
    pcover G;

    G = new_cover(F->count);
    FD = cube2list(F, D);

    /* Reduce cubes of F without replacement */
    foreach_set(F, last, p) {
    cunder = reduce_cube(FD, p);
    if (setp_empty(cunder)) {
        fatal("empty reduction in reduce_gasp, shouldn't happen");
    } else if (setp_equal(cunder, p)) {
        SET(cunder, PRIME);            /* just to make sure */
        G = sf_addset(G, p);        /* it did not reduce ... */
    } else {
        RESET(cunder, PRIME);        /* it reduced ... */
        G = sf_addset(G, cunder);
    }
    if (debug & GASP) {
        printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
    }
    free_cube(cunder);
    }

    free_cubelist(FD);
    return G;
}

/*
 *  expand_gasp -- expand each nonprime cube of F into a prime implicant
 *
 *  The gasp strategy differs in that only those cubes which expand to
 *  cover some other cube are saved; also, all cubes are expanded
 *  regardless of whether they become covered or not.
 */

pcover expand_gasp(F, D, R, Foriginal)
INOUT pcover F;
IN pcover D;
IN pcover R;
IN pcover Foriginal;
{
    int c1index;
    pcover G;

    /* Try to expand each nonprime and noncovered cube */
    G = new_cover(10);
    for(c1index = 0; c1index < F->count; c1index++) {
    expand1_gasp(F, D, R, Foriginal, c1index, &G);
    }
    G = sf_dupl(G);
    G = expand(G, R, /*nonsparse*/ FALSE);    /* Make them prime ! */
    return G;
}



/*
 *  expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
 */
void expand1_gasp(F, D, R, Foriginal, c1index, G)
pcover F;        /* reduced cubes of ON-set */
pcover D;        /* DC-set */
pcover R;        /* OFF-set */
pcover Foriginal;    /* ON-set before reduction (same order as F) */
int c1index;        /* which index of F (or Freduced) to be checked */
pcover *G;
{
    register int c2index;
    register pcube p, last, c2under;
    pcube RAISE, FREESET, temp, *FD, c2essential;
    pcover F1;

    if (debug & EXPAND1) {
    printf("\nEXPAND1_GASP:    \t%s\n", pc1(GETSET(F, c1index)));
    }

    RAISE = new_cube();
    FREESET = new_cube();
    temp = new_cube();

    /* Initialize the OFF-set */
    R->active_count = R->count;
    foreach_set(R, last, p) {
    SET(p, ACTIVE);
    }
    /* Initialize the reduced ON-set, all nonprime cubes become active */
    F->active_count = F->count;
    foreachi_set(F, c2index, c2under) {
    if (c1index == c2index || TESTP(c2under, PRIME)) {
        F->active_count--;
        RESET(c2under, ACTIVE);
    } else {
        SET(c2under, ACTIVE);
    }
    }

    /* Initialize the raising and unassigned sets */
    (void) set_copy(RAISE, GETSET(F, c1index));
    (void) set_diff(FREESET, cube.fullset, RAISE);

    /* Determine parts which must be lowered */
    essen_parts(R, F, RAISE, FREESET);

    /* Determine parts which can always be raised */
    essen_raising(R, RAISE, FREESET);

    /* See which, if any, of the reduced cubes we can cover */
    foreachi_set(F, c2index, c2under) {
    if (TESTP(c2under, ACTIVE)) {
        /* See if this cube can be covered by an expansion */
        if (setp_implies(c2under, RAISE) ||
          feasibly_covered(R, c2under, RAISE, temp)) {
        
        /* See if c1under can expanded to cover c2 reduced against
         * (F - c1) u c1under; if so, c2 can definitely be removed !
         */

        /* Copy F and replace c1 with c1under */
        F1 = sf_save(Foriginal);
        (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));

        /* Reduce c2 against ((F - c1) u c1under) */
        FD = cube2list(F1, D);
        c2essential = reduce_cube(FD, GETSET(F1, c2index));
        free_cubelist(FD);
        sf_free(F1);

        /* See if c2essential is covered by an expansion of c1under */
        if (feasibly_covered(R, c2essential, RAISE, temp)) {
            (void) set_or(temp, RAISE, c2essential);
            RESET(temp, PRIME);        /* cube not prime */
            *G = sf_addset(*G, temp);
        }
        set_free(c2essential);
        }
    }
    }

    free_cube(RAISE);
    free_cube(FREESET);
    free_cube(temp);
}

/* irred_gasp -- Add new primes to F and find an irredundant subset */
pcover irred_gasp(F, D, G)
pcover F, D, G;                 /* G is disposed of */
{
    if (G->count != 0)
    F = irredundant(sf_append(F, G), D);
    else
    free_cover(G);
    return F;
}


/* last_gasp */
pcover last_gasp(F, D, R, cost)
pcover F, D, R;
cost_t *cost;
{
    pcover G, G1;

    EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
    EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
    free_cover(G);
    EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
    return F;
}


/* super_gasp */
pcover super_gasp(F, D, R, cost)
pcover F, D, R;
cost_t *cost;
{
    pcover G, G1;

    EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
    EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
    free_cover(G);
    EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
    EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
    return F;
}
ABC_NAMESPACE_IMPL_END

