2008-01-31 05:01:00 +01:00
|
|
|
|
/*
|
|
|
|
|
|
* Revision Control Information
|
|
|
|
|
|
*
|
|
|
|
|
|
* $Source$
|
|
|
|
|
|
* $Author$
|
|
|
|
|
|
* $Revision$
|
|
|
|
|
|
* $Date$
|
|
|
|
|
|
*
|
|
|
|
|
|
*/
|
|
|
|
|
|
/*
|
|
|
|
|
|
module: sparse.c
|
|
|
|
|
|
|
|
|
|
|
|
make_sparse is a last-step cleanup to reduce the total number
|
|
|
|
|
|
of literals in the cover.
|
|
|
|
|
|
|
|
|
|
|
|
This is done by reducing the "sparse" variables (using a modified
|
|
|
|
|
|
version of irredundant rather than reduce), followed by expanding
|
|
|
|
|
|
the "dense" variables (using modified version of expand).
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "espresso.h"
|
|
|
|
|
|
|
2010-11-01 09:35:04 +01:00
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-01-31 05:01:00 +01:00
|
|
|
|
pcover make_sparse(F, D, R)
|
|
|
|
|
|
pcover F, D, R;
|
|
|
|
|
|
{
|
|
|
|
|
|
cost_t cost, best_cost;
|
|
|
|
|
|
|
|
|
|
|
|
cover_cost(F, &best_cost);
|
|
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost);
|
|
|
|
|
|
if (cost.total == best_cost.total)
|
|
|
|
|
|
break;
|
|
|
|
|
|
copy_cost(&cost, &best_cost);
|
|
|
|
|
|
|
|
|
|
|
|
EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost);
|
|
|
|
|
|
if (cost.total == best_cost.total)
|
|
|
|
|
|
break;
|
|
|
|
|
|
copy_cost(&cost, &best_cost);
|
|
|
|
|
|
} while (force_irredundant);
|
|
|
|
|
|
|
|
|
|
|
|
return F;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
mv_reduce -- perform an "optimal" reduction of the variables which
|
|
|
|
|
|
we desire to be sparse
|
|
|
|
|
|
|
|
|
|
|
|
This could be done using "reduce" and then saving just the desired
|
|
|
|
|
|
part of the reduction. Instead, this version uses IRRED to find
|
|
|
|
|
|
which cubes of an output are redundant. Note that this gets around
|
|
|
|
|
|
the cube-ordering problem.
|
|
|
|
|
|
|
|
|
|
|
|
In normal use, it is expected that the cover is irredundant and
|
|
|
|
|
|
hence no cubes will be reduced to the empty cube (however, this is
|
|
|
|
|
|
checked for and such cubes will be deleted)
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
pcover
|
|
|
|
|
|
mv_reduce(F, D)
|
|
|
|
|
|
pcover F, D;
|
|
|
|
|
|
{
|
|
|
|
|
|
register int i, var;
|
|
|
|
|
|
register pcube p, p1, last;
|
|
|
|
|
|
int index;
|
|
|
|
|
|
pcover F1, D1;
|
|
|
|
|
|
pcube *F_cube_table;
|
|
|
|
|
|
|
|
|
|
|
|
/* loop for each multiple-valued variable */
|
|
|
|
|
|
for(var = 0; var < cube.num_vars; var++) {
|
|
|
|
|
|
|
|
|
|
|
|
if (cube.sparse[var]) {
|
|
|
|
|
|
|
|
|
|
|
|
/* loop for each part of the variable */
|
|
|
|
|
|
for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
|
|
|
|
|
|
|
|
|
|
|
|
/* remember mapping of F1 cubes back to F cubes */
|
|
|
|
|
|
F_cube_table = ALLOC(pcube, F->count);
|
|
|
|
|
|
|
|
|
|
|
|
/* 'cofactor' against part #i of variable #var */
|
|
|
|
|
|
F1 = new_cover(F->count);
|
|
|
|
|
|
foreach_set(F, last, p) {
|
|
|
|
|
|
if (is_in_set(p, i)) {
|
|
|
|
|
|
F_cube_table[F1->count] = p;
|
|
|
|
|
|
p1 = GETSET(F1, F1->count++);
|
|
|
|
|
|
(void) set_diff(p1, p, cube.var_mask[var]);
|
|
|
|
|
|
set_insert(p1, i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 'cofactor' against part #i of variable #var */
|
|
|
|
|
|
/* not really necessary -- just more efficient ? */
|
|
|
|
|
|
D1 = new_cover(D->count);
|
|
|
|
|
|
foreach_set(D, last, p) {
|
|
|
|
|
|
if (is_in_set(p, i)) {
|
|
|
|
|
|
p1 = GETSET(D1, D1->count++);
|
|
|
|
|
|
(void) set_diff(p1, p, cube.var_mask[var]);
|
|
|
|
|
|
set_insert(p1, i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mark_irredundant(F1, D1);
|
|
|
|
|
|
|
|
|
|
|
|
/* now remove part i from cubes which are redundant */
|
|
|
|
|
|
index = 0;
|
|
|
|
|
|
foreach_set(F1, last, p1) {
|
|
|
|
|
|
if (! TESTP(p1, ACTIVE)) {
|
|
|
|
|
|
p = F_cube_table[index];
|
|
|
|
|
|
|
|
|
|
|
|
/* don't reduce a variable which is full
|
|
|
|
|
|
* (unless it is the output variable)
|
|
|
|
|
|
*/
|
|
|
|
|
|
if (var == cube.num_vars-1 ||
|
|
|
|
|
|
! setp_implies(cube.var_mask[var], p)) {
|
|
|
|
|
|
set_remove(p, i);
|
|
|
|
|
|
}
|
|
|
|
|
|
RESET(p, PRIME);
|
|
|
|
|
|
}
|
|
|
|
|
|
index++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
free_cover(F1);
|
|
|
|
|
|
free_cover(D1);
|
|
|
|
|
|
FREE(F_cube_table);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if any cubes disappeared */
|
|
|
|
|
|
(void) sf_active(F);
|
|
|
|
|
|
for(var = 0; var < cube.num_vars; var++) {
|
|
|
|
|
|
if (cube.sparse[var]) {
|
|
|
|
|
|
foreach_active_set(F, last, p) {
|
|
|
|
|
|
if (setp_disjoint(p, cube.var_mask[var])) {
|
|
|
|
|
|
RESET(p, ACTIVE);
|
|
|
|
|
|
F->active_count--;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (F->count != F->active_count) {
|
|
|
|
|
|
F = sf_inactive(F);
|
|
|
|
|
|
}
|
|
|
|
|
|
return F;
|
|
|
|
|
|
}
|
2010-11-01 09:35:04 +01:00
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|
|
|
|
|