/*
 * Revision Control Information
 *
 * $Source$
 * $Author$
 * $Revision$
 * $Date$
 *
 */
/*
 *  unate.c -- routines for dealing with unate functions
 */

#include "espresso.h"

ABC_NAMESPACE_IMPL_START


static pset_family abs_covered();
static pset_family abs_covered_many();
static int abs_select_restricted();

pcover map_cover_to_unate(T)
pcube *T;
{
    register unsigned int word_test, word_set, bit_test, bit_set;
    register pcube p, pA;
    pset_family A;
    pcube *T1;
    int ncol, i;

    A = sf_new(CUBELISTSIZE(T), cdata.vars_unate);
    A->count = CUBELISTSIZE(T);
    foreachi_set(A, i, p) {
    (void) set_clear(p, A->sf_size);
    }
    ncol = 0;

    for(i = 0; i < cube.size; i++) {
    if (cdata.part_zeros[i] > 0) {
        assert(ncol <= cdata.vars_unate);

        /* Copy a column from T to A */
        word_test = WHICH_WORD(i);
        bit_test = 1 << WHICH_BIT(i);
        word_set = WHICH_WORD(ncol);
        bit_set = 1 << WHICH_BIT(ncol);

        pA = A->data;
        for(T1 = T+2; (p = *T1++) != 0; ) {
        if ((p[word_test] & bit_test) == 0) {
            pA[word_set] |= bit_set;
        }
        pA += A->wsize;
        }

        ncol++;
    }
    }

    return A;
}

pcover map_unate_to_cover(A)
pset_family A;
{
    register int i, ncol, lp;
    register pcube p, pB;
    int var, nunate, *unate;
    pcube last;
    pset_family B;

    B = sf_new(A->count, cube.size);
    B->count = A->count;

    /* Find the unate variables */
    unate = ALLOC(int, cube.num_vars);
    nunate = 0;
    for(var = 0; var < cube.num_vars; var++) {
    if (cdata.is_unate[var]) {
        unate[nunate++] = var;
    }
    }

    /* Loop for each set of A */
    pB = B->data;
    foreach_set(A, last, p) {

    /* Initialize this set of B */
    INLINEset_fill(pB, cube.size);

    /* Now loop for the unate variables; if the part is in A,
     * then this variable of B should be a single 1 in the unate
     * part.
     */
    for(ncol = 0; ncol < nunate; ncol++) {
        if (is_in_set(p, ncol)) {
        lp = cube.last_part[unate[ncol]];
        for(i = cube.first_part[unate[ncol]]; i <= lp; i++) {
            if (cdata.part_zeros[i] == 0) {
            set_remove(pB, i);
            }
        }
        }
    }
    pB += B->wsize;
    }

    FREE(unate);
    return B;
}

/*
 *  unate_compl
 */

pset_family unate_compl(A)
pset_family A;
{
    register pset p, last;

    /* Make sure A is single-cube containment minimal */
/*    A = sf_rev_contain(A);*/

    foreach_set(A, last, p) {
    PUTSIZE(p, set_ord(p));
    }

    /* Recursively find the complement */
    A = unate_complement(A);

    /* Now, we can guarantee a minimal result by containing the result */
    A = sf_rev_contain(A);
    return A;
}


/*
 *  Assume SIZE(p) records the size of each set
 */
pset_family unate_complement(A)
pset_family A;            /* disposes of A */
{
    pset_family Abar;
    register pset p, p1, restrict;
    register int i;
    int max_i, min_set_ord, j;

    /* Check for no sets in the matrix -- complement is the universe */
    if (A->count == 0) {
    sf_free(A);
    Abar = sf_new(1, A->sf_size);
    (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size);

    /* Check for a single set in the maxtrix -- compute de Morgan complement */
    } else if (A->count == 1) {
    p = A->data;
    Abar = sf_new(A->sf_size, A->sf_size);
    for(i = 0; i < A->sf_size; i++) {
        if (is_in_set(p, i)) {
        p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size);
        set_insert(p1, i);
        }
    }
    sf_free(A);

    } else {

    /* Select splitting variable as the variable which belongs to a set
     * of the smallest size, and which has greatest column count
     */
    restrict = set_new(A->sf_size);
    min_set_ord = A->sf_size + 1;
    foreachi_set(A, i, p) {
        if (SIZE(p) < min_set_ord) {
        set_copy(restrict, p);
        min_set_ord = SIZE(p);
        } else if (SIZE(p) == min_set_ord) {
        set_or(restrict, restrict, p);
        }
    }

    /* Check for no data (shouldn't happen ?) */
    if (min_set_ord == 0) {
        A->count = 0;
        Abar = A;

    /* Check for "essential" columns */
    } else if (min_set_ord == 1) {
        Abar = unate_complement(abs_covered_many(A, restrict));
        sf_free(A);
        foreachi_set(Abar, i, p) {
        set_or(p, p, restrict);
        }

    /* else, recur as usual */
    } else {
        max_i = abs_select_restricted(A, restrict);

        /* Select those rows of A which are not covered by max_i,
         * recursively find all minimal covers of these rows, and
         * then add back in max_i
         */
        Abar = unate_complement(abs_covered(A, max_i));
        foreachi_set(Abar, i, p) {
        set_insert(p, max_i);
        }

        /* Now recur on A with all zero's on column max_i */
        foreachi_set(A, i, p) {
        if (is_in_set(p, max_i)) {
            set_remove(p, max_i);
            j = SIZE(p) - 1;
            PUTSIZE(p, j);
        }
        }

        Abar = sf_append(Abar, unate_complement(A));
    }
    set_free(restrict);
    }

    return Abar;
}

pset_family exact_minimum_cover(T)
IN pset_family T;
{
    register pset p, last, p1;
    register int i, n;
    int lev, lvl;
    pset nlast;
    pset_family temp;
    long start = ptime();
    struct {
    pset_family sf;
    int level;
    } stack[32];                /* 32 suffices for 2 ** 32 cubes ! */

    if (T->count <= 0)
    return sf_new(1, T->sf_size);
    for(n = T->count, lev = 0; n != 0; n >>= 1, lev++)   ;

    /* A simple heuristic ordering */
    T = lex_sort(sf_save(T));

    /* Push a full set on the stack to get things started */
    n = 1;
    stack[0].sf = sf_new(1, T->sf_size);
    stack[0].level = lev;
    set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size);

    nlast = GETSET(T, T->count - 1);
    foreach_set(T, last, p) {

    /* "unstack" the set into a family */
    temp = sf_new(set_ord(p), T->sf_size);
    for(i = 0; i < T->sf_size; i++)
        if (is_in_set(p, i)) {
        p1 = set_fill(GETSET(temp, temp->count++), T->sf_size);
        set_remove(p1, i);
        }
    stack[n].sf = temp;
    stack[n++].level = lev;

    /* Pop the stack and perform (leveled) intersections */
    while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) {
        temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE);
        lvl = MIN(stack[n-1].level, stack[n-2].level) - 1;
        if (debug & MINCOV && lvl < 10) {
        printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n",
            lvl, temp->count, stack[n-1].sf->count,
            stack[n-2].sf->count, print_time(ptime() - start));
        (void) fflush(stdout);
        }
        sf_free(stack[n-2].sf);
        sf_free(stack[n-1].sf);
        stack[n-2].sf = temp;
        stack[n-2].level = lvl;
        n--;
    }
    }

    temp = stack[0].sf;
    p1 = set_fill(set_new(T->sf_size), T->sf_size);
    foreach_set(temp, last, p)
    INLINEset_diff(p, p1, p);
    set_free(p1);
    if (debug & MINCOV1) {
    printf("MINCOV: family of all minimal coverings is\n");
    sf_print(temp);
    }
    sf_free(T);         /* this is the copy of T we made ... */
    return temp;
}

/*
 *  unate_intersect -- intersect two unate covers
 *
 *  If largest_only is TRUE, then only the largest cube(s) are returned
 */

#define MAGIC 500               /* save 500 cubes before containment */

pset_family unate_intersect(A, B, largest_only)
pset_family A, B;
bool largest_only;
{
    register pset pi, pj, lasti, lastj, pt;
    pset_family T, Tsave;
    bool save;
    int maxord, ord;

    /* How large should each temporary result cover be ? */
    T = sf_new(MAGIC, A->sf_size);
    Tsave = NULL;
    maxord = 0;
    pt = T->data;

    /* Form pairwise intersection of each set of A with each cube of B */
    foreach_set(A, lasti, pi) {

    foreach_set(B, lastj, pj) {

        save = set_andp(pt, pi, pj);

        /* Check if we want the largest only */
        if (save && largest_only) {
        if ((ord = set_ord(pt)) > maxord) {
            /* discard Tsave and T */
            if (Tsave != NULL) {
            sf_free(Tsave);
            Tsave = NULL;
            }
            pt = T->data;
            T->count = 0;
            /* Re-create pt (which was just thrown away) */
            (void) set_and(pt, pi, pj);
            maxord = ord;
        } else if (ord < maxord) {
            save = FALSE;
        }
        }

        if (save) {
        if (++T->count >= T->capacity) {
            T = sf_contain(T);
            Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
            T = sf_new(MAGIC, A->sf_size);
            pt = T->data;
        } else {
            pt += T->wsize;
        }
        }
    }
    }


    /* Contain the final result and merge it into Tsave */
    T = sf_contain(T);
    Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);

    return Tsave;
}

/*
 *  abs_covered -- after selecting a new column for the selected set,
 *  create a new matrix which is only those rows which are still uncovered
 */
static pset_family
abs_covered(A, pick)
pset_family A;
register int pick;
{
    register pset last, p, pdest;
    register pset_family Aprime;

    Aprime = sf_new(A->count, A->sf_size);
    pdest = Aprime->data;
    foreach_set(A, last, p)
    if (! is_in_set(p, pick)) {
        INLINEset_copy(pdest, p);
        Aprime->count++;
        pdest += Aprime->wsize;
    }
    return Aprime;
}


/*
 *  abs_covered_many -- after selecting many columns for ther selected set,
 *  create a new matrix which is only those rows which are still uncovered
 */
static pset_family
abs_covered_many(A, pick_set)
pset_family A;
register pset pick_set;
{
    register pset last, p, pdest;
    register pset_family Aprime;

    Aprime = sf_new(A->count, A->sf_size);
    pdest = Aprime->data;
    foreach_set(A, last, p)
    if (setp_disjoint(p, pick_set)) {
        INLINEset_copy(pdest, p);
        Aprime->count++;
        pdest += Aprime->wsize;
    }
    return Aprime;
}


/*
 *  abs_select_restricted -- select the column of maximum column count which
 *  also belongs to the set "restrict"; weight each column of a set as
 *  1 / (set_ord(p) - 1).
 */
static int
abs_select_restricted(A, restrict)
pset_family A;
pset restrict;
{
    register int i, best_var, best_count, *count;

    /* Sum the elements in these columns */
    count = sf_count_restricted(A, restrict);

    /* Find which variable has maximum weight */
    best_var = -1;
    best_count = 0;
    for(i = 0; i < A->sf_size; i++) {
    if (count[i] > best_count) {
        best_var = i;
        best_count = count[i];
    }
    }
    FREE(count);

    if (best_var == -1)
    fatal("abs_select_restricted: should not have best_var == -1");

    return best_var;
}
ABC_NAMESPACE_IMPL_END

