Adding command "cuts".

This commit is contained in:
Alan Mishchenko 2025-11-23 11:58:34 -08:00
parent c956f02eb0
commit 6d2bedd609
2 changed files with 199 additions and 54 deletions

View File

@ -29,9 +29,9 @@ ABC_NAMESPACE_IMPL_START
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define GIA_MAX_CUTSIZE 8
#define GIA_MAX_CUTNUM 257
#define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1)
#define GIA_MAX_CUTSIZE 14
#define GIA_MAX_CUTNUM 257
#define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1)
#define GIA_CUT_NO_LEAF 0xF
@ -649,7 +649,7 @@ void Gia_StoComputeCuts( Gia_Man_t * pGia )
printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] );
printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) );
printf( "\n" );
printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ",
printf( "The number of nodes with maximum cut count (%d cuts) = %d nodes (out of %d). ",
p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) );
Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart );
}
@ -724,7 +724,7 @@ Vec_Wec_t * Gia_ManExtractCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int
printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] );
printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) );
printf( "\n" );
printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ",
printf( "The number of nodes with maximum cut count (%d cuts) = %d nodes (out of %d). ",
p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) );
Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart );
}
@ -999,7 +999,7 @@ Vec_Wec_t * Gia_ManExploreCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int
printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] );
printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) );
printf( "\n" );
printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ",
printf( "The number of nodes with maximum cut count (%d cuts) = %d nodes (out of %d). ",
p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) );
Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart );
}
@ -1027,12 +1027,12 @@ void Gia_ManExploreCutsTest( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fV
SeeAlso []
***********************************************************************/
Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fVerbose0 )
Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fTruth0, int fVerbose0 )
{
int nCutSize = nCutSize0;
int nCutNum = nCutNum0;
int fCutMin = 1;
int fTruthMin = 1;
int fCutMin = fTruth0;
int fTruthMin = fTruth0;
int fVerbose = fVerbose0;
Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose );
Gia_Obj_t * pObj; int i, iObj;
@ -1057,15 +1057,90 @@ Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0,
printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] );
printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) );
printf( "\n" );
printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ",
printf( "The number of nodes with maximum cut count (%d cuts) = %d nodes (out of %d). ",
p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) );
Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart );
}
return p;
}
int Gia_ManCountSelfCuts( Gia_Man_t * p, Gia_Sto_t * pSto )
{
Vec_Int_t * vLevel; int i, k, * pCut, nNodes = 0;
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) {
Gia_Obj_t * pObj = Gia_ManObj(p, i);
if ( !Gia_ObjIsAnd(pObj) )
continue;
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k )
nNodes += pCut[0] == 2 && pCut[1] == Gia_ObjFaninId0p(p, pObj) && pCut[2] == Gia_ObjFaninId1p(p, pObj);
}
return nNodes;
}
void Gia_ManDumpCuts( Gia_Man_t * p, Gia_Sto_t * pSto, FILE * pFile, int fVerbose, char * pFileName )
{
Vec_Int_t * vLevel; int i, k, c, * pCut, nCuts = 0, nNodes = 0;
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) {
if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) )
continue;
int nNodeCuts = 0;
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) {
if ( pCut[0] == 1 )
continue;
fprintf( pFile, "%d ", i );
for ( c = 1; c <= pCut[0]; c++ )
fprintf( pFile, "%d ", pCut[c] );
fprintf( pFile, "1\n" );
nNodeCuts++;
nNodes++;
}
nCuts += nNodeCuts;
}
Gia_Obj_t * pObj;
Gia_ManForEachCo( p, pObj, i )
fprintf( pFile, "%d %d 0\n", Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj) );
if ( fVerbose )
printf( "Dumped %d cuts for %d nodes into file \"%s\".\n", nCuts, nNodes, pFileName ? pFileName : "stdout" );
}
void Gia_ManComputeCutsCore( Gia_Man_t * pGia, int nCutSize, int nCutNum, int fTruth, int fVerbose, int fDumpText, int fDumpBin, char * pFileName )
{
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fTruth, fVerbose );
if ( fDumpText ) {
FILE * pFile = pFileName ? fopen(pFileName, "wb") : stdout;
if ( !pFile ) return;
Gia_ManDumpCuts( pGia, pSto, pFile, fVerbose, pFileName );
}
else if ( fDumpBin ) {
FILE * pFile = pFileName ? fopen(pFileName, "wb") : NULL;
if ( !pFile ) return;
Gia_ManDumpCuts( pGia, pSto, pFile, fVerbose, pFileName );
}
//printf( "The number of nodes with self-cuts = %d (out of %d).\n", Gia_ManCountSelfCuts(pGia, pSto), Gia_ManAndNum(pGia) );
Gia_StoFree( pSto );
}
Vec_Wec_t * Gia_ManCompute54Cuts( Gia_Man_t * pGia, int fVerbose )
{
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( pGia, 5, 16, 0, fVerbose );
Vec_Wec_t * vRes = Vec_WecAlloc( 1000 );
Vec_Int_t * vLevel; int i, k, c, * pCut;
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) {
if ( !Gia_ObjIsAnd(Gia_ManObj(pGia, i)) )
continue;
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) {
if ( pCut[0] != 4 && pCut[0] != 5 )
continue;
Vec_Int_t * vCut = Vec_WecPushLevel( vRes );
for ( c = 1; c <= pCut[0]; c++ )
Vec_IntPush( vCut, pCut[c] );
Vec_IntPush( vCut, i );
}
}
Gia_StoFree( pSto );
return vRes;
}
void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose )
{
Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose );
Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, 1, fVerbose );
Vec_Int_t * vLevel; int i, j, k, * pCut;
Vec_Int_t * vNodes = Vec_IntAlloc( 100 );
Vec_Wec_t * vCuts = Vec_WecAlloc( 100 );
@ -1101,7 +1176,7 @@ void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int n
Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose )
{
Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_PtrSize(vTtMems) );
Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose );
Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, 1, fVerbose );
Vec_Int_t * vLevel, * vTemp; int i, k, c, * pCut;
abctime clkStart = Abc_Clock();
for ( i = 0; i < Vec_PtrSize(vTtMems); i++ )
@ -1136,7 +1211,7 @@ Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nC
}
Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFuncs, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose )
{
Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose );
Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, 1, fVerbose );
Vec_Int_t * vLevel; int i, j, k, * pCut;
abctime clkStart = Abc_Clock();
assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) );
@ -1168,46 +1243,6 @@ Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFun
return vRes;
}
/**Function*************************************************************
Synopsis [Function enumeration.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_ManDumpCuts( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose )
{
FILE * pFile = fopen( "input.txt", "wb" ); if ( !pFile ) return;
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 );
Vec_Int_t * vLevel; int i, k, c, * pCut, nCuts = 0, nNodes = 0;
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) {
if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) )
continue;
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) {
if ( pCut[0] == 1 )
continue;
fprintf( pFile, "%d ", i );
for ( c = 1; c <= pCut[0]; c++ )
fprintf( pFile, "%d ", pCut[c] );
fprintf( pFile, "1\n" );
nCuts += pCut[0];
nNodes++;
}
}
Gia_Obj_t * pObj;
Gia_ManForEachCo( p, pObj, i ) {
fprintf( pFile, "%d %d 0\n", Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj) );
}
fclose( pFile );
Gia_StoFree( pSto );
if ( fVerbose )
printf( "Dumped %d cuts for %d nodes into file \"input.txt\".\n", nCuts, nNodes );
}
/**Function*************************************************************
Synopsis [Function enumeration.]
@ -1221,7 +1256,7 @@ void Gia_ManDumpCuts( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose )
***********************************************************************/
Vec_Wrd_t * Gia_ManCollectCutFuncs( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose )
{
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 );
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 1, 0 );
Vec_Wrd_t * vFuncs = Vec_WrdAlloc( 1000 ); Vec_Int_t * vLevel; int i, k, * pCut;
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) )
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] == nCutSize ) {

View File

@ -649,6 +649,7 @@ static int Abc_CommandAbc9MulFind ( Abc_Frame_t * pAbc, int argc, cha
static int Abc_CommandAbc9MulFind3 ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9BsFind ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9AndCare ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Cuts ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv );
@ -1480,6 +1481,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "ABC9", "&mulfind3", Abc_CommandAbc9MulFind3, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&bsfind", Abc_CommandAbc9BsFind, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&andcare", Abc_CommandAbc9AndCare, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&cuts", Abc_CommandAbc9Cuts, 0 );
Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 );
@ -58195,6 +58197,114 @@ usage:
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandAbc9Cuts( Abc_Frame_t * pAbc, int argc, char ** argv )
{
extern void Gia_ManComputeCutsCore( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fTruth0, int fVerbose0, int fDumpText, int fDumpBin, char * pFileName );
int nCutSize = 6;
int nCutNum = 16;
int fTruth = 1;
int fVerbose = 1;
int fDumpText = 0;
int fDumpBin = 0;
int c;
char * pFileName = NULL;
Extra_UtilGetoptReset();
while ( ( c = Extra_UtilGetopt( argc, argv, "KCtdbvh" ) ) != EOF )
{
switch ( c )
{
case 'K':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" );
goto usage;
}
nCutSize = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nCutSize < 0 )
goto usage;
break;
case 'C':
if ( globalUtilOptind >= argc )
{
Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" );
goto usage;
}
nCutNum = atoi(argv[globalUtilOptind]);
globalUtilOptind++;
if ( nCutNum < 0 )
goto usage;
break;
case 't':
fTruth ^= 1;
break;
case 'd':
fDumpText ^= 1;
break;
case 'b':
fDumpBin ^= 1;
break;
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pAbc->pGia == NULL )
{
Abc_Print( -1, "Abc_CommandAbc9Cuts(): There is no AIG.\n" );
return 0;
}
if ( argc == globalUtilOptind + 1 )
pFileName = argv[globalUtilOptind];
else if ( argc != globalUtilOptind )
{
Abc_Print( 1,"Abc_CommandAbc9Cuts(): Trailing arguments on the command line.\n" );
return 0;
}
if ( nCutSize < 2 || nCutSize > 14 )
{
Abc_Print( -1, "The number of cut leaves should belong to the range: %d <= K <= %d.\n", 2, 14 );
return 1;
}
if ( nCutNum < 2 || nCutNum > 256 )
{
Abc_Print( -1, "The number of cuts per node should belong to the range: %d <= C <= %d.\n", 2, 256 );
return 1;
}
if ( fDumpBin && !pFileName )
{
Abc_Print( -1, "Output binary file name should be provided on the command line.\n" );
return 1;
}
Gia_ManComputeCutsCore( pAbc->pGia, nCutSize, nCutNum, fTruth, fVerbose, fDumpText, fDumpBin, pFileName );
return 0;
usage:
Abc_Print( -2, "usage: cuts [-KC num] [-tdbvh]\n" );
Abc_Print( -2, "\t computes K-input cuts for the nodes in the current AIG\n" );
Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", 2, 14, nCutSize );
Abc_Print( -2, "\t-C num : max number of cuts at a node (%d <= num <= %d) [default = %d]\n", 2, 256, nCutNum );
Abc_Print( -2, "\t-t : toggle truth table computation and cut minimization [default = %s]\n", fTruth? "yes": "no" );
Abc_Print( -2, "\t-d : toggle dumping cuts into a text file [default = %s]\n", fDumpText? "yes": "no" );
Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fDumpBin? "yes": "no" );
Abc_Print( -2, "\t-h : print the command usage\n");
return 1;
}
/**Function*************************************************************