From 7d247a08f7ece422d6a7df77c483a14f1dff4e12 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 26 Dec 2024 00:37:37 -0800 Subject: [PATCH] Experiments with bound-set evaluation. --- src/base/abci/abc.c | 126 +++++++++ src/misc/util/module.make | 1 + src/misc/util/utilBSet.c | 562 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 689 insertions(+) create mode 100644 src/misc/util/utilBSet.c diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c index 824c09003..140b2db4e 100644 --- a/src/base/abci/abc.c +++ b/src/base/abci/abc.c @@ -156,6 +156,7 @@ static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, cha static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBsEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv ); @@ -958,6 +959,7 @@ void Abc_Init( Abc_Frame_t * pAbc ) Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "bseval", Abc_CommandBsEval, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); @@ -9155,6 +9157,130 @@ int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) return 1; } +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ); + extern void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ); + extern void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fVerbose ); + int c, nVars = 0, nBVars = 0, nFuncs = 0, nMints = 0, fTryAll = 0, fVerbose = 0; char * pTtStr = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IBRMavh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 2 || nVars > 16 ) + goto usage; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + nBVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBVars < 1 || nBVars > 16 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = atoi(argv[globalUtilOptind]); + if ( nFuncs < 1 ) + goto usage; + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fTryAll ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + pTtStr = argv[globalUtilOptind]; + if ( pTtStr ) + { + nVars = Abc_Base2Log((int)strlen(pTtStr)) + 2; + if ( (1 << (nVars-2)) != (int)strlen(pTtStr) ) + { + Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (nVars-2)), strlen(pTtStr) ); + return 1; + } + } + if ( nVars == 0 ) + { + Abc_Print( -1, "The number of variables should be specified on the command line.\n" ); + return 1; + } + if ( nBVars == 0 ) + { + Abc_Print( -1, "The bound set size should be specified on the command line.\n" ); + return 1; + } + if ( nFuncs ) + Abc_BSEvalBestGen( nVars, nBVars, nFuncs, nMints, fTryAll, fVerbose ); + else if ( pTtStr ) + { + word pTruth[1024] = {0}; + Abc_TtReadHex( pTruth, pTtStr ); + if ( fTryAll ) + Abc_BSEvalBestTest( pTruth, nVars, nBVars, fVerbose ); + else + Abc_BSEvalOneTest( pTruth, nVars, nBVars, fVerbose ); + } + return 0; + +usage: + Abc_Print( -2, "usage: bseval [-IBRM ] [-avh] \n" ); + Abc_Print( -2, "\t bound set evaluation\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-B : the number of bound set variables [default = %d]\n", nBVars ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = unused]\n" ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); + Abc_Print( -2, "\t-a : toggle trying all bound sets of this size [default = %s]\n", fTryAll ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : truth table in hex notation\n" ); + return 1; +} + /**Function************************************************************* Synopsis [] diff --git a/src/misc/util/module.make b/src/misc/util/module.make index 66e87653f..bf3538360 100644 --- a/src/misc/util/module.make +++ b/src/misc/util/module.make @@ -1,4 +1,5 @@ SRC += src/misc/util/utilBridge.c \ + src/misc/util/utilBSet.c \ src/misc/util/utilCex.c \ src/misc/util/utilColor.c \ src/misc/util/utilFile.c \ diff --git a/src/misc/util/utilBSet.c b/src/misc/util/utilBSet.c new file mode 100644 index 000000000..7f95e97d0 --- /dev/null +++ b/src/misc/util/utilBSet.c @@ -0,0 +1,562 @@ +/**CFile**************************************************************** + + FileName [utilBSet.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Bound set evaluation.] + + Synopsis [Bound set evaluation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 25, 2024.] + + Revision [$Id: utilBSet.c,v 1.00 2024/12/25 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +#include "misc/extra/extra.h" +#include "misc/util/utilTruth.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_BSEval_t_ Abc_BSEval_t; +struct Abc_BSEval_t_ +{ + int nVars; + int nBVars; + Vec_Int_t * vPairs; // perm pairs + Vec_Int_t * vCounts; // cofactor counts + Vec_Int_t * vTable; // hash table + Vec_Int_t * vUsed; // used entries + Vec_Wrd_t * vStore; // cofactors +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Bound-set evalution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_TtGetCM1( word * p, int nVars ) +{ + int Counts[4] = {0}; + int i, Res = 0, nDigits = 1 << (nVars - 1); + for ( i = 0; i < nDigits; i++ ) + Counts[Abc_TtGetQua(p, i)]++; + for ( i = 0; i < 4; i++ ) + Res += Counts[i] > 0; + return Res; +} +int Abc_TtGetCM2( word * p, int nVars ) +{ + int Counts[16] = {0}; + int i, Res = 0, nDigits = 1 << (nVars - 2); + for ( i = 0; i < nDigits; i++ ) + Counts[Abc_TtGetHex(p, i)]++; + for ( i = 0; i < 16; i++ ) + Res += Counts[i] > 0; + return Res; +} +int Abc_TtGetCM3( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) +{ + unsigned char * q = (unsigned char *)p; + int i, Digit, nDigits = 1 << (nVars - 3); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) { + if ( pCounts[q[i]] ) + continue; + pCounts[q[i]] = 1; + Vec_IntPush(vUsed, q[i]); + } + Vec_IntForEachEntry( vUsed, Digit, i ) + pCounts[Digit] = 0; + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM4( word * p, int nVars, int * pCounts, Vec_Int_t * vUsed ) +{ + unsigned short * q = (unsigned short *)p; + int i, Digit, nDigits = 1 << (nVars - 4); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) { + if ( pCounts[q[i]] ) + continue; + pCounts[q[i]] = 1; + Vec_IntPush(vUsed, q[i]); + } + Vec_IntForEachEntry( vUsed, Digit, i ) + pCounts[Digit] = 0; + return Vec_IntSize(vUsed); +} + +// https://en.wikipedia.org/wiki/Jenkins_hash_function +int Abc_TtGetKey( unsigned char * p, int nSize, int nTableSize ) +{ + int i = 0; unsigned hash = 0; + while ( i != nSize ) + { + hash += p[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + return (int)(hash % nTableSize); +} +int Abc_TtHashLookup5( int Entry, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + int Key = Abc_TtGetKey( (unsigned char*)&Entry, 4, Vec_IntSize(vTable) ); + int * pTable = Vec_IntArray(vTable); + for ( ; pTable[Key]; Key = (Key + 1) % Vec_IntSize(vTable) ) + if ( Entry == (int)Vec_WrdEntry(vStore, pTable[Key]) ) + return 0; + assert( pTable[Key] == -1 ); + pTable[Key] = Vec_WrdSize(vStore); + Vec_WrdPush( vStore, (word)Entry ); + Vec_IntPush( vUsed, Key ); + return 1; +} +int Abc_TtGetCM5( word * p, int nVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + unsigned * q = (unsigned *)p; + int i, Item, nDigits = 1 << (nVars - 5); + Vec_WrdClear( vStore ); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) + Abc_TtHashLookup5( q[i], vTable, vStore, vUsed ); + Vec_IntForEachEntry( vUsed, Item, i ) + Vec_IntWriteEntry( vTable, Item, -1 ); + return Vec_IntSize(vUsed); +} +int Abc_TtHashLookup6( word * pEntry, int nWords, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + int i, Key = Abc_TtGetKey( (unsigned char*)&pEntry, 8*nWords, Vec_IntSize(vTable) ); + int * pTable = Vec_IntArray(vTable); + for ( ; pTable[Key]; Key = (Key + 1) % Vec_IntSize(vTable) ) + if ( !memcmp(pEntry, Vec_WrdEntryP(vStore, pTable[Key]), 8*nWords) ) + return 0; + assert( pTable[Key] == -1 ); + pTable[Key] = Vec_WrdSize(vStore); + for ( i = 0; i < nWords; i++ ) + Vec_WrdPush( vStore, pEntry[i] ); + Vec_IntPush( vUsed, Key ); + return 1; +} +int Abc_TtGetCM6( word * p, int nVars, int nFVars, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + assert( nFVars >= 6 && nFVars < nVars ); + int i, Item, nDigits = 1 << (nVars - nFVars), nWords = 1 << (nFVars - 6); + Vec_WrdClear( vStore ); + Vec_IntClear( vUsed ); + for ( i = 0; i < nDigits; i++ ) + Abc_TtHashLookup6( p + i*nWords, nWords, vTable, vStore, vUsed ); + Vec_IntForEachEntry( vUsed, Item, i ) + Vec_IntWriteEntry( vTable, Item, -1 ); + return Vec_IntSize(vUsed); +} +int Abc_TtGetCM( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed ) +{ + if ( nFVars == 1 ) + return Abc_TtGetCM1( p, nVars ); + if ( nFVars == 2 ) + return Abc_TtGetCM2( p, nVars ); + if ( nFVars == 3 ) + return Abc_TtGetCM3( p, nVars, Vec_IntArray(vCounts), vUsed ); + if ( nFVars == 4 ) + return Abc_TtGetCM4( p, nVars, Vec_IntArray(vCounts), vUsed ); + if ( nFVars == 5 ) + return Abc_TtGetCM5( p, nVars, vTable, vStore, vUsed ); + if ( nFVars == 6 ) + return Abc_TtGetCM6( p, nVars, nFVars, vTable, vStore, vUsed ); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Permutation generation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Abc_TtPermGen( int * currPerm, int nVars, word * pT, int nTtVars ) +{ + int i = nVars - 1; + while ( i >= 0 && currPerm[i - 1] >= currPerm[i] ) + i--; + if (i >= 0) + { + int j = nVars; + while ( j > i && currPerm[j - 1] <= currPerm[i - 1 ]) + j--; + ABC_SWAP( int, currPerm[i - 1], currPerm[j - 1] ) + if ( pT ) Abc_TtSwapVars( pT, nTtVars, i-1, j-1 ); + i++; + j = nVars; + while ( i < j ) + { + ABC_SWAP( int, currPerm[i - 1], currPerm[j - 1] ) + if ( pT ) Abc_TtSwapVars( pT, nTtVars, i-1, j-1 ); + i++; + j--; + } + } +} +static int Abc_TtFactorial(int nVars) +{ + int i, Res = 1; + for ( i = 1; i <= nVars; i++ ) + Res *= i; + return Res; +} +void Abc_TtPermGenTest() +{ + int i, k, nVars = 5, currPerm[5] = {0}; + for ( i = 0; i < nVars; i++ ) + currPerm[i] = i; + int fact = Abc_TtFactorial( nVars ); + for ( i = 0; i < fact; i++ ) + { + printf( "%3d :", i ); + for ( k = 0; k < nVars; k++ ) + printf( " %d", currPerm[k] ); + printf( "\n" ); + Abc_TtPermGen( currPerm, nVars, NULL, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Combination generation.] + + Description [https://stackoverflow.com/questions/22650522/how-to-generate-chases-sequence] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenChaseNext(int a[], int w[], int *r) +{ + int found_r = 0; + int j; + for (j = *r; !w[j]; j++) { + int b = a[j] + 1; + int n = a[j + 1]; + if (b < (w[j + 1] ? n - (2 - (n & 1)) : n)) { + if ((b & 1) == 0 && b + 1 < n) b++; + a[j] = b; + if (!found_r) *r = j > 1 ? j - 1 : 0; + return; + } + w[j] = a[j] - 1 >= j; + if (w[j] && !found_r) { + *r = j; + found_r = 1; + } + } + int b = a[j] - 1; + if ((b & 1) != 0 && b - 1 >= j) b--; + a[j] = b; + w[j] = b - 1 >= j; + if (!found_r) *r = j; +} +Vec_Int_t * Abc_GenChasePairs( int N, int T ) +{ + Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); + int j, z, r = 0, Count = 0, a[32], b[32], w[32]; + for ( j = 0; j < T + 1; j++ ) { + a[j] = N - (T - j); + w[j] = 1; + } + do { + for ( z = 0; z <= T; z++ ) + b[z] = a[z]; + Abc_GenChaseNext( a, w, &r ); + for ( z = 0; z < T; z++ ) { + if ( a[z] == b[z] ) + continue; + Vec_IntPushTwo( vPairs, b[z], a[z] ); + if ( 0 ) { + printf( "%3d : ", Count++ ); + for (j = T - 1; j > -1; j--) printf("%x", b[j]); + printf( " %d <-> %d ", b[z], a[z] ); + for (j = T - 1; j > -1; j--) printf("%x", a[j]); + printf( "\n" ); + } + break; + } + } while (a[T] == N); + Vec_IntPushTwo( vPairs, 0, 0 ); + return vPairs; +} +void Abc_GenChasePrint( int Count, int * pPerm, int nVars, int nFVars, int Var0, int Var1 ) +{ + int k; + printf( "%3d : ", Count++ ); + for ( k = nVars-1; k >= nFVars; k-- ) + printf( "%d", pPerm[k] ); + printf( " " ); + for ( k = nFVars-1; k >= 0; k-- ) + printf( "%d", pPerm[k] ); + printf( " %d <-> %d\n", Var0, Var1 ); +} +void Abc_GenChaseTest() +{ + int nVars = 4; + int nFVars = 2; + Vec_Int_t * vPairs = Abc_GenChasePairs( nVars, nVars-nFVars ); + int i, Var0, Var1, Pla2Var[32], Var2Pla[32]; + for ( i = 0; i < nVars; i++ ) + Pla2Var[i] = Var2Pla[i] = i; + int Count = 0; + Vec_IntForEachEntryDouble( vPairs, Var0, Var1, i ) { + Abc_GenChasePrint( Count++, Pla2Var, nVars, nFVars, Var0, Var1 ); + int iPlace0 = Var2Pla[Var0]; + int iPlace1 = Var2Pla[Var1]; + //Abc_TtSwapVars( pTruth, nVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + } + Vec_IntFree( vPairs ); +} + + +/**Function************************************************************* + + Synopsis [Bound-set evalution for one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_BSEval_t * Abc_BSEvalAlloc() +{ + Abc_BSEval_t * p = ABC_CALLOC( Abc_BSEval_t, 1 ); + p->vCounts = Vec_IntStart( 1 << 16 ); + p->vTable = Vec_IntStartFull( 997 ); + p->vUsed = Vec_IntAlloc(100); + p->vStore = Vec_WrdAlloc(1000); + return p; +} +void Abc_BSEvalFree( Abc_BSEval_t * p ) +{ + Vec_IntFreeP( &p->vPairs ); + Vec_IntFree( p->vCounts ); + Vec_IntFree( p->vTable ); + Vec_IntFree( p->vUsed ); + Vec_WrdFree( p->vStore ); + ABC_FREE( p ); +} +void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ) +{ + assert( nVars > nBVars ); + Abc_BSEval_t * p = Abc_BSEvalAlloc(); + if ( p->nVars != nVars || p->nBVars != nBVars ) { + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nVars, nBVars ); + p->nVars = nVars; + p->nBVars = nBVars; + } + int Best = Abc_TtGetCM( pT, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + printf( "Function: " ); Extra_PrintHex( stdout, (unsigned *)pT, nVars ); printf( "\n" ); + printf( "The column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best ); + Abc_BSEvalFree(p); +} +int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest ) +{ + int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32]; + int nPermVars = nVars-nCVars; + assert( p->nVars == nPermVars && p->nBVars == nPermVars-nFVars ); + for ( i = 0; i < nVars; i++ ) + Pla2Var[i] = Var2Pla[i] = i; + if ( pPermBest ) + for ( i = 0; i < nVars; i++ ) + pPermBest[i] = i; + int CostBest = 1 << nVars; + //int Count = 0; + Vec_IntForEachEntryDouble( p->vPairs, Var0, Var1, i ) { + //Abc_GenChasePrint( Count++, Pla2Var, nVars, nFVars, Var0, Var1 ); + int CostThis = Abc_TtGetCM( pIn, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + if ( CostBest > CostThis ) { + CostBest = CostThis; + if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 ); + if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nPermVars ); + } + if ( fVerbose ) + { + printf( "%3d : ", i/2 ); + for ( k = nCVars-1; k >= 0; k-- ) + printf( " %d", nVars-nCVars+k ); + printf( " " ); + for ( k = nPermVars-1; k >= nFVars; k-- ) + printf( " %d", Pla2Var[k] ); + printf( " " ); + for ( k = nFVars-1; k >= 0; k-- ) + printf( " %d", Pla2Var[k] ); + printf( " : Myu = %3d", CostThis ); + printf( "\n" ); + } + int iPlace0 = Var2Pla[Var0]; + int iPlace1 = Var2Pla[Var1]; + if ( iPlace0 == iPlace1 ) + continue; + Abc_TtSwapVars( pIn, nVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + } + for ( i = 0; i < nPermVars; i++ ) + { + int iPlace0 = i; + int iPlace1 = Var2Pla[i]; + if ( iPlace0 == iPlace1 ) + continue; + Abc_TtSwapVars( pIn, nVars, iPlace0, iPlace1 ); + Var2Pla[Pla2Var[iPlace0]] = iPlace1; + Var2Pla[Pla2Var[iPlace1]] = iPlace0; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + Pla2Var[iPlace1] ^= Pla2Var[iPlace0]; + Pla2Var[iPlace0] ^= Pla2Var[iPlace1]; + } + return CostBest; +} +void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fVerbose ) +{ + assert( nVars > nBVars ); + Abc_BSEval_t * p = Abc_BSEvalAlloc(); int i, pPerm[32] = {0}; + if ( p->nVars != nVars || p->nBVars != nBVars ) { + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nVars, nBVars ); + p->nVars = nVars; + p->nBVars = nBVars; + } + word * pFun = ABC_ALLOC( word, Abc_TtWordNum(nVars) ); + int Best = Abc_BSEvalBest( p, pIn, pFun, nVars, 0, nVars-nBVars, fVerbose, pPerm ); + printf( "The minimum column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best ); + printf( "Original: " ); Extra_PrintHex( stdout, (unsigned *)pIn, nVars ); printf( "\n" ); + printf( "Permuted: " ); Extra_PrintHex( stdout, (unsigned *)pFun, nVars ); printf( "\n" ); + printf( "Permutation is " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + ABC_FREE( pFun ); + Abc_BSEvalFree(p); +} + +/**Function************************************************************* + + Synopsis [Testing on random functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fVerbose ) +{ + assert( nVars > nBVars ); + abctime clkTotal = Abc_Clock(); + Abc_BSEval_t * p = Abc_BSEvalAlloc(); + Vec_Int_t * vCounts = Vec_IntStart( 1 << nVars ); + int i, k, Count, nWords = Abc_TtWordNum(nVars); + word * pFun = ABC_ALLOC( word, nWords ); + if ( p->nVars != nVars || p->nBVars != nBVars ) { + Vec_IntFreeP( &p->vPairs ); + p->vPairs = Abc_GenChasePairs( nVars, nBVars ); + p->nVars = nVars; + p->nBVars = nBVars; + } + Abc_Random(1); + //printf( "\n" ); + for ( i = 0; i < nFuncs; i++ ) { + if ( nMints == 0 ) + for ( k = 0; k < nWords; k++ ) + pFun[k] = Abc_RandomW(0); + else { + Abc_TtClear( pFun, nWords ); + for ( k = 0; k < nMints; k++ ) { + int iMint = 0; + do iMint = Abc_Random(0) % (1 << nVars); + while ( Abc_TtGetBit(pFun, iMint) ); + Abc_TtSetBit( pFun, iMint ); + } + } + if ( fVerbose ) { + printf( "Function %5d ", i ); + if ( nMints ) + printf( "with %d positive minterms ", nMints ); + if ( nVars <= 8 ) { + printf( "has truth table: " ); + Extra_PrintHex( stdout, (unsigned *)pFun, nVars ); + } + if ( fTryAll ) + printf( "\n" ); + else + printf( " " ); + } + if ( fTryAll ) + Count = Abc_BSEvalBest( p, pFun, NULL, nVars, 0, nVars-nBVars, fVerbose, NULL ); + else + Count = Abc_TtGetCM( pFun, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed ); + if ( fVerbose ) + printf( "Myu = %d\n", Count ); + Vec_IntAddToEntry( vCounts, Count, 1 ); + } + ABC_FREE( pFun ); + Abc_BSEvalFree(p); + if ( nMints ) + printf( "Generated %d random %d-var functions with %d positive minterms.\n", nFuncs, nVars, nMints ); + else + printf( "Generated %d random %d-var functions.\n", nFuncs, nVars ); + printf( "Distribution of the %s column multiplicity for bound set size %d is as follows:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars ); + assert( Vec_IntSum(vCounts) == nFuncs ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs ); + printf( "\n" ); + Vec_IntFree( vCounts ); + Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END +