summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2012-01-29 21:22:54 -0800
committerAlan Mishchenko <alanmi@berkeley.edu>2012-01-29 21:22:54 -0800
commit7ea40494eb637c5c717c3fa80529bfbbec897f83 (patch)
treeb5f2502ec6dbad3dff161ce525901200229841e1 /src
parente511b872370f8f9928b08381ff53f2b8a3669ba7 (diff)
downloadabc-7ea40494eb637c5c717c3fa80529bfbbec897f83.tar.gz
abc-7ea40494eb637c5c717c3fa80529bfbbec897f83.tar.bz2
abc-7ea40494eb637c5c717c3fa80529bfbbec897f83.zip
Graph isomorphism checking code.
Diffstat (limited to 'src')
-rw-r--r--src/aig/aig/aigIso.c822
-rw-r--r--src/aig/aig/module.make1
-rw-r--r--src/aig/gia/giaAbsVta.c14
-rw-r--r--src/base/abci/abc.c3
4 files changed, 837 insertions, 3 deletions
diff --git a/src/aig/aig/aigIso.c b/src/aig/aig/aigIso.c
new file mode 100644
index 00000000..71687f14
--- /dev/null
+++ b/src/aig/aig/aigIso.c
@@ -0,0 +1,822 @@
+/**CFile****************************************************************
+
+ FileName [aigIso.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [AIG package.]
+
+ Synopsis [Graph isomorphism package.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - April 28, 2007.]
+
+ Revision [$Id: aigIso.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "aig.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+#define ISO_NUM_INTS 3
+
+typedef struct Iso_Obj_t_ Iso_Obj_t;
+struct Iso_Obj_t_
+{
+ // hashing entries (related to the parameter ISO_NUM_INTS!)
+ unsigned fFlop : 1;
+ unsigned nFinPos : 2;
+ unsigned nFoutPos : 29;
+ unsigned fMux : 1;
+ unsigned nFinNeg : 2;
+ unsigned nFoutNeg : 29;
+ int Level;
+ // other data
+ int iNext; // hash table entry
+ int iClass; // next one in class
+ int Id; // unique ID
+ Vec_Int_t * vAllies; // solved neighbors
+};
+
+typedef struct Iso_Man_t_ Iso_Man_t;
+struct Iso_Man_t_
+{
+ Aig_Man_t * pAig; // user's AIG manager
+ Iso_Obj_t * pObjs; // isomorphism objects
+ int nObjIds; // counter of object IDs
+ int nClasses; // total number of classes
+ int nEntries; // total number of entries
+ int nSingles; // total number of singletons
+ int nObjs; // total objects
+ int nBins; // hash table size
+ int * pBins; // hash table
+ Vec_Int_t * vPolRefs; // polarity references
+ Vec_Ptr_t * vSingles; // singletons
+ Vec_Ptr_t * vClasses; // other classes
+};
+
+static inline Iso_Obj_t * Iso_ManObj( Iso_Man_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL; }
+static inline int Iso_ObjId( Iso_Man_t * p, Iso_Obj_t * pObj ) { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; }
+
+static inline void Iso_ObjIncPolRef0( Vec_Int_t * vPolRefs, Aig_Obj_t * pObj ) { Vec_IntAddToEntry( vPolRefs, 2*Aig_ObjFaninId0(pObj)+Aig_ObjFaninC0(pObj), 1 ); }
+static inline void Iso_ObjIncPolRef1( Vec_Int_t * vPolRefs, Aig_Obj_t * pObj ) { Vec_IntAddToEntry( vPolRefs, 2*Aig_ObjFaninId1(pObj)+Aig_ObjFaninC1(pObj), 1 ); }
+
+#define Iso_ManForEachObj( p, pObj, i ) \
+ for ( i = 1; (i < p->nObjs) && ((pObj) = Iso_ManObj(p, i)); i++ ) if ( pIso->Level == -1 ) {} else
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Iso_ManNegEdgeNum( Aig_Man_t * pAig )
+{
+ Aig_Obj_t * pObj;
+ int i, Counter = 0;
+ Aig_ManForEachObj( pAig, pObj, i )
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ Counter += Aig_ObjFaninC0(pObj);
+ Counter += Aig_ObjFaninC1(pObj);
+ }
+ else if ( Aig_ObjIsPo(pObj) )
+ Counter += Aig_ObjFaninC0(pObj);
+ return Counter;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Iso_ManComputePolRefs( Aig_Man_t * pAig )
+{
+ Vec_Int_t * vPolRefs;
+ Aig_Obj_t * pObj;
+ int i;
+ vPolRefs = Vec_IntStart( 2 * Aig_ManObjNumMax( pAig ) );
+ Aig_ManForEachObj( pAig, pObj, i )
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ Iso_ObjIncPolRef0( vPolRefs, pObj );
+ Iso_ObjIncPolRef1( vPolRefs, pObj );
+ }
+ else if ( Aig_ObjIsPo(pObj) )
+ Iso_ObjIncPolRef0( vPolRefs, pObj );
+ return vPolRefs;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Iso_Man_t * Iso_ManStart( Aig_Man_t * pAig )
+{
+ Iso_Man_t * p;
+ p = ABC_CALLOC( Iso_Man_t, 1 );
+ p->pAig = pAig;
+ p->nObjs = Aig_ManObjNumMax( pAig );
+ p->pObjs = ABC_CALLOC( Iso_Obj_t, p->nObjs );
+ p->nBins = Abc_PrimeCudd( p->nObjs );
+ p->pBins = ABC_CALLOC( int, p->nBins );
+ p->vPolRefs = Iso_ManComputePolRefs( pAig );
+ p->vSingles = Vec_PtrAlloc( 1000 );
+ p->vClasses = Vec_PtrAlloc( 1000 );
+ p->nObjIds = 1;
+ return p;
+}
+void Iso_ManStop( Iso_Man_t * p )
+{
+ Iso_Obj_t * pIso;
+ int i;
+ Iso_ManForEachObj( p, pIso, i )
+ Vec_IntFreeP( &pIso->vAllies );
+ Vec_PtrFree( p->vClasses );
+ Vec_PtrFree( p->vSingles );
+ Vec_IntFree( p->vPolRefs );
+ ABC_FREE( p->pBins );
+ ABC_FREE( p->pObjs );
+ ABC_FREE( p );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compares two objects by their signature.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Iso_ObjCompare( Iso_Obj_t ** pp1, Iso_Obj_t ** pp2 )
+{
+ Iso_Obj_t * pIso1 = *pp1;
+ Iso_Obj_t * pIso2 = *pp2;
+ int Diff = memcmp( pIso1, pIso2, sizeof(int) * ISO_NUM_INTS );
+ if ( Diff )
+ return Diff;
+// return 0;
+ if ( pIso1->vAllies == NULL && pIso2->vAllies == NULL )
+ return 0;
+ if ( pIso1->vAllies == NULL && pIso2->vAllies != NULL )
+ return -1;
+ if ( pIso1->vAllies != NULL && pIso2->vAllies == NULL )
+ return 1;
+ Diff = Vec_IntSize(pIso1->vAllies) - Vec_IntSize(pIso2->vAllies);
+ if ( Diff )
+ return Diff;
+ return memcmp( Vec_IntArray(pIso1->vAllies), Vec_IntArray(pIso2->vAllies), Vec_IntSize(pIso1->vAllies) * sizeof(int) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two objects by their ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Iso_ObjCompareById( Iso_Obj_t ** pp1, Iso_Obj_t ** pp2 )
+{
+ Iso_Obj_t * pIso1 = *pp1;
+ Iso_Obj_t * pIso2 = *pp2;
+ return pIso1->Id - pIso2->Id;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compares two objects by their ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Iso_ObjCompareAigObjByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 )
+{
+ Aig_Obj_t * pIso1 = *pp1;
+ Aig_Obj_t * pIso2 = *pp2;
+ assert( Aig_ObjIsPi(pIso1) && Aig_ObjIsPi(pIso2) );
+ return pIso1->iData - pIso2->iData;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Iso_ObjHash( Iso_Obj_t * pIso, int nBins )
+{
+ static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741};
+ unsigned * pArray = (unsigned *)pIso;
+ unsigned i, Value = 0;
+ assert( ISO_NUM_INTS < 8 );
+ for ( i = 0; i < ISO_NUM_INTS; i++ )
+ Value ^= BigPrimes[i] * pArray[i];
+ return Value % nBins;
+}
+static inline int Iso_ObjHashAdd( Iso_Man_t * p, Iso_Obj_t * pIso )
+{
+ Iso_Obj_t * pThis;
+ int * pPlace = p->pBins + Iso_ObjHash( pIso, p->nBins );
+ p->nEntries++;
+ for ( pThis = Iso_ManObj(p, *pPlace);
+ pThis; pPlace = &pThis->iNext,
+ pThis = Iso_ManObj(p, *pPlace) )
+ if ( Iso_ObjCompare( &pThis, &pIso ) == 0 ) // equal signatures
+ {
+ if ( pThis->iClass == 0 )
+ {
+ p->nClasses++;
+ p->nSingles--;
+ }
+ // add to the list
+ pIso->iClass = pThis->iClass;
+ pThis->iClass = Iso_ObjId( p, pIso );
+ return 1;
+ }
+ // create new list
+ *pPlace = Iso_ObjId( p, pIso );
+ p->nSingles++;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Iso_Man_t * Iso_ManCreate( Aig_Man_t * pAig )
+{
+ Iso_Man_t * p;
+ Iso_Obj_t * pIso;
+ Aig_Obj_t * pObj;
+ int i;
+ p = Iso_ManStart( pAig );
+ Iso_ManForEachObj( p, pIso, i )
+ pIso->Level = -1;
+ Aig_ManForEachObj( pAig, pObj, i )
+ {
+ if ( !Aig_ObjIsPi(pObj) && !Aig_ObjIsNode(pObj) )
+ continue;
+ pIso = p->pObjs + i;
+ if ( Aig_ObjIsNode(pObj) )
+ {
+ pIso->nFinNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj);
+ pIso->nFinPos = 2 - pIso->nFinNeg;
+ pIso->fMux = Aig_ObjIsMuxType( pObj );
+ }
+ else
+ pIso->fFlop = (int)(Aig_ObjPioNum(pObj) >= Aig_ManPiNum(pAig) - Aig_ManRegNum(pAig));
+ pIso->nFoutPos = Vec_IntEntry( p->vPolRefs, 2*i );
+ pIso->nFoutNeg = Vec_IntEntry( p->vPolRefs, 2*i+1 );
+ pIso->Level = pObj->Level;
+ // add to the hash table
+ Iso_ObjHashAdd( p, pIso );
+ }
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Iso_ManCollectClasses( Iso_Man_t * p )
+{
+ Iso_Obj_t * pIso;
+ int i;
+ Vec_PtrClear( p->vSingles );
+ Vec_PtrClear( p->vClasses );
+ for ( i = 0; i < p->nBins; i++ )
+ for ( pIso = Iso_ManObj(p, p->pBins[i]); pIso; pIso = Iso_ManObj(p, pIso->iNext) )
+ {
+ assert( pIso->Id == 0 );
+ if ( pIso->iClass )
+ Vec_PtrPush( p->vClasses, pIso );
+ else
+ Vec_PtrPush( p->vSingles, pIso );
+ }
+ Vec_PtrSort( p->vSingles, (int (*)(void))Iso_ObjCompare );
+ Vec_PtrSort( p->vClasses, (int (*)(void))Iso_ObjCompare );
+ assert( Vec_PtrSize(p->vSingles) == p->nSingles );
+ assert( Vec_PtrSize(p->vClasses) == p->nClasses );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Iso_ManPrintClasses( Iso_Man_t * p, int fVerbose )
+{
+ int fOnlyCis = 1;
+ int fVeryVerbose = 0;
+ Iso_Obj_t * pIso, * pTemp;
+ int i;
+
+ // count unique objects
+ if ( fVerbose )
+ printf( "Total objects =%7d. Entries =%7d. Classes =%7d. Singles =%7d.\n",
+ p->nObjs, p->nEntries, p->nClasses, p->nSingles );
+
+ if ( !fVeryVerbose )
+ return;
+
+ Iso_ManCollectClasses( p );
+
+ printf( "Non-trivial classes:\n" );
+ Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+ {
+ if ( fOnlyCis && pIso->Level > 0 )
+ continue;
+
+ printf( "%5d : {", i );
+ for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+ {
+ if ( fOnlyCis )
+ printf( " %d", Aig_ObjPioNum(Aig_ManObj(p->pAig, Iso_ObjId(p, pTemp))) );
+ else
+ printf( " %d", Iso_ObjId(p, pTemp) );
+ printf( "(%d,%d,%d)", pTemp->Level, pTemp->nFoutPos, pTemp->nFoutNeg );
+ if ( pTemp->vAllies )
+ {
+ int Entry, k;
+ printf( "[" );
+ Vec_IntForEachEntry( pTemp->vAllies, Entry, k )
+ printf( "%s%d", k?",":"", Entry );
+ printf( "]" );
+ }
+ }
+ printf( " }\n" );
+ }
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Creates adjacency lists.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Iso_ObjAddToAllies( Iso_Obj_t * pIso, int Id )
+{
+ assert( pIso->Id == 0 );
+ if ( pIso->vAllies == NULL )
+ pIso->vAllies = Vec_IntAlloc( 8 );
+ Vec_IntPush( pIso->vAllies, Id );
+}
+void Iso_ManAssignAdjacency( Iso_Man_t * p )
+{
+ Iso_Obj_t * pIso, * pIso0, * pIso1;
+ Aig_Obj_t * pObj, * pObjLi;
+ int i;
+ // clean
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ pIso = Iso_ManObj( p, i );
+ if ( pIso->vAllies )
+ Vec_IntClear( pIso->vAllies );
+ }
+ // create
+ Aig_ManForEachNode( p->pAig, pObj, i )
+ {
+ pIso = Iso_ManObj( p, i );
+ pIso0 = Iso_ManObj( p, Aig_ObjFaninId0(pObj) );
+ pIso1 = Iso_ManObj( p, Aig_ObjFaninId1(pObj) );
+ if ( pIso->Id ) // unique - add to non-unique fanins
+ {
+ if ( pIso0->Id == 0 )
+ Iso_ObjAddToAllies( pIso0, pIso->Id );
+ if ( pIso1->Id == 0 )
+ Iso_ObjAddToAllies( pIso1, pIso->Id );
+ }
+ else // non-unique - assign unique fanins to it
+ {
+ if ( pIso0->Id != 0 )
+ Iso_ObjAddToAllies( pIso, pIso0->Id );
+ if ( pIso1->Id != 0 )
+ Iso_ObjAddToAllies( pIso, pIso1->Id );
+ }
+ }
+ // consider flops
+ Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i )
+ {
+ if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore!
+ continue;
+ pIso = Iso_ManObj( p, Aig_ObjId(pObj) );
+ pIso0 = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) );
+ if ( pIso->Id ) // unique - add to non-unique fanins
+ {
+ if ( pIso0->Id == 0 )
+ Iso_ObjAddToAllies( pIso0, pIso->Id );
+ }
+ else // non-unique - assign unique fanins to it
+ {
+ if ( pIso0->Id != 0 )
+ Iso_ObjAddToAllies( pIso, pIso0->Id );
+ }
+ }
+ // sort
+ Aig_ManForEachObj( p->pAig, pObj, i )
+ {
+ if ( i == 0 ) continue;
+ pIso = Iso_ManObj( p, i );
+ if ( pIso->vAllies )
+ Vec_IntSort( pIso->vAllies, 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Iso_ManRehashClassNodes( Iso_Man_t * p )
+{
+ Iso_Obj_t * pIso, * pTemp;
+ int i;
+ // collect nodes
+ Vec_PtrClear( p->vSingles );
+ Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+ for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+ Vec_PtrPush( p->vSingles, pTemp );
+ // clean and add nodes
+ p->nClasses = 0; // total number of classes
+ p->nEntries = 0; // total number of entries
+ p->nSingles = 0; // total number of singletons
+ memset( p->pBins, 0, sizeof(int) * p->nBins );
+ Vec_PtrForEachEntry( Iso_Obj_t *, p->vSingles, pIso, i )
+ {
+ pIso->iClass = pIso->iNext = 0;
+ Iso_ObjHashAdd( p, pIso );
+ }
+ Vec_PtrClear( p->vSingles );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns one if there are unclassified CIs.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Iso_ManCheckCis( Iso_Man_t * p )
+{
+ Aig_Obj_t * pObj;
+ int i;
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ if ( Aig_ObjRefs(pObj) > 0 && Iso_ManObj(p, Aig_ObjId(pObj))->Id == 0 )
+ return 0;
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalizes unification of combinational outputs.]
+
+ Description [Assigns IDs to the unclassified CIs in the order of obj IDs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Iso_ManFinalize( Iso_Man_t * p )
+{
+ Vec_Int_t * vRes;
+ Vec_Ptr_t * vClass, * vClass2;
+ Iso_Obj_t * pIso, * pTemp;
+ Aig_Obj_t * pObj;
+ int i, k;
+
+ vClass = Vec_PtrAlloc( Aig_ManPiNum(p->pAig)-Aig_ManRegNum(p->pAig) );
+ vClass2 = Vec_PtrAlloc( Aig_ManRegNum(p->pAig) );
+ Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i )
+ {
+ if ( pIso->Level > 0 )
+ continue;
+ Vec_PtrClear( vClass );
+ for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) )
+ {
+ assert( pTemp->Id == 0 );
+ pTemp->Id = Aig_ObjPioNum(Aig_ManObj(p->pAig, Iso_ObjId(p, pTemp)));
+ Vec_PtrPush( vClass, pTemp );
+ }
+ Vec_PtrSort( vClass, (int (*)(void))Iso_ObjCompareById );
+ // assign IDs in this order
+ Vec_PtrForEachEntry( Iso_Obj_t *, vClass, pIso, k )
+ pIso->Id = p->nObjIds++;
+ }
+
+ // assign unique IDs to the CIs
+ Vec_PtrClear( vClass );
+ Vec_PtrClear( vClass2 );
+ Aig_ManForEachPi( p->pAig, pObj, i )
+ {
+ pObj->iData = Iso_ManObj(p, Aig_ObjId(pObj))->Id;
+ if ( Aig_ObjPioNum(pObj) >= Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig) )
+ Vec_PtrPush( vClass2, pObj );
+ else
+ Vec_PtrPush( vClass, pObj );
+ }
+ // sort CIs by their IDs
+ Vec_PtrSort( vClass, (int (*)(void))Iso_ObjCompareAigObjByData );
+ Vec_PtrSort( vClass2, (int (*)(void))Iso_ObjCompareAigObjByData );
+
+ // create the result
+ vRes = Vec_IntAlloc( Aig_ManPiNum(p->pAig) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vClass, pObj, i )
+ Vec_IntPush( vRes, Aig_ObjPioNum(pObj) );
+ Vec_PtrForEachEntry( Aig_Obj_t *, vClass2, pObj, i )
+ Vec_IntPush( vRes, Aig_ObjPioNum(pObj) );
+
+ Vec_PtrFree( vClass );
+ Vec_PtrFree( vClass2 );
+ return vRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Iso_ManFindPerm( Aig_Man_t * pAig, int fVerbose )
+{
+ Iso_Man_t * p;
+ Iso_Obj_t * pIso;
+ Vec_Int_t * vRes;
+ int i;
+ p = Iso_ManCreate( pAig );
+ Iso_ManPrintClasses( p, fVerbose );
+ while ( p->nSingles )
+ {
+ // collect singletons and classes
+ Iso_ManCollectClasses( p );
+ // assign IDs to singletons
+ Vec_PtrForEachEntry( Iso_Obj_t *, p->vSingles, pIso, i )
+ pIso->Id = p->nObjIds++;
+ // check termination
+ if ( p->nClasses == 0 )
+ break;
+ // assign adjacency to classes
+ Iso_ManAssignAdjacency( p );
+ // rehash the class nodes
+ Iso_ManRehashClassNodes( p );
+ Iso_ManPrintClasses( p, fVerbose );
+ }
+ vRes = Iso_ManFinalize( p );
+ Iso_ManStop( p );
+ return vRes;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks structural equivalence of AIG1 and AIG2.]
+
+ Description [Returns 1 if AIG1 and AIG2 are structurally equivalent
+ under this mapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Iso_ManCheckMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vMap2to1, int fVerbose )
+{
+ Aig_Obj_t * pObj, * pFanin0, * pFanin1;
+ int i;
+ assert( Aig_ManPiNum(pAig1) == Aig_ManPiNum(pAig2) );
+ assert( Aig_ManPoNum(pAig1) == Aig_ManPoNum(pAig2) );
+ assert( Aig_ManRegNum(pAig1) == Aig_ManRegNum(pAig2) );
+ assert( Aig_ManNodeNum(pAig1) == Aig_ManNodeNum(pAig2) );
+ Aig_ManCleanData( pAig1 );
+ // map const and PI nodes
+ Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAig1);
+ Aig_ManForEachPi( pAig2, pObj, i )
+ pObj->pData = Aig_ManPi( pAig1, Vec_IntEntry(vMap2to1, i) );
+ // try internal nodes
+ Aig_ManForEachNode( pAig2, pObj, i )
+ {
+ pFanin0 = Aig_ObjChild0Copy( pObj );
+ pFanin1 = Aig_ObjChild1Copy( pObj );
+ pObj->pData = Aig_TableLookupTwo( pAig1, pFanin0, pFanin1 );
+ if ( pObj->pData == NULL )
+ {
+ if ( fVerbose )
+ printf( "Structural equivalence failed at node %d.\n", i );
+ return 0;
+ }
+ }
+ // make sure the first PO points to the same node
+ if ( Aig_ManPoNum(pAig1)-Aig_ManRegNum(pAig1) == 1 && Aig_ObjChild0Copy(Aig_ManPo(pAig2, 0)) != Aig_ObjChild0(Aig_ManPo(pAig1, 0)) )
+ {
+ if ( fVerbose )
+ printf( "Structural equivalence failed at primary output 0.\n" );
+ return 0;
+ }
+ return 1;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finds mapping of CIs of AIG2 into those of AIG1.]
+
+ Description [Returns the mapping of CIs of the two AIGs, or NULL
+ if there is no mapping.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Iso_ManFindMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int fVerbose )
+{
+ Vec_Int_t * vPerm1, * vPerm2, * vInvPerm2;
+ int i, Entry;
+ if ( Aig_ManPiNum(pAig1) != Aig_ManPiNum(pAig2) )
+ return NULL;
+ if ( Aig_ManPoNum(pAig1) != Aig_ManPoNum(pAig2) )
+ return NULL;
+ if ( Aig_ManRegNum(pAig1) != Aig_ManRegNum(pAig2) )
+ return NULL;
+ if ( Aig_ManNodeNum(pAig1) != Aig_ManNodeNum(pAig2) )
+ return NULL;
+ if ( Aig_ManLevelNum(pAig1) != Aig_ManLevelNum(pAig2) )
+ return NULL;
+ if ( Iso_ManNegEdgeNum(pAig1) != Iso_ManNegEdgeNum(pAig2) )
+ return NULL;
+ if ( fVerbose )
+ printf( "AIG1:\n" );
+ vPerm1 = Iso_ManFindPerm( pAig1, fVerbose );
+ if ( fVerbose )
+ printf( "AIG1:\n" );
+ vPerm2 = Iso_ManFindPerm( pAig2, fVerbose );
+ // find canonical permutation
+ // vPerm1/vPerm2 give canonical order of CIs of AIG1/AIG2
+ vInvPerm2 = Vec_IntInvert( vPerm2, -1 );
+ Vec_IntForEachEntry( vInvPerm2, Entry, i )
+ {
+ assert( Entry >= 0 && Entry < Aig_ManPiNum(pAig1) );
+ Vec_IntWriteEntry( vInvPerm2, i, Vec_IntEntry(vPerm1, Entry) );
+ }
+ Vec_IntFree( vPerm1 );
+ Vec_IntFree( vPerm2 );
+ // check if they are indeed equivalent
+ if ( !Iso_ManCheckMapping( pAig1, pAig2, vInvPerm2, fVerbose ) )
+ Vec_IntFreeP( &vInvPerm2 );
+ return vInvPerm2;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Iso_ManTestOne( Aig_Man_t * pAig, int fVerbose )
+{
+ Vec_Int_t * vPerm;
+ vPerm = Iso_ManFindPerm( pAig, fVerbose );
+ Vec_IntFree( vPerm );
+}
+
+#include "src/base/abc/abc.h"
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Iso_ManTest( Aig_Man_t * pAig1, int fVerbose )
+{
+ extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters );
+ extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan );
+ Abc_Ntk_t * pNtk;
+ Aig_Man_t * pAig2;
+ Vec_Int_t * vMap;
+
+ pNtk = Abc_NtkFromAigPhase( pAig1 );
+ Abc_NtkPermute( pNtk, 1, 0, 1 );
+ pAig2 = Abc_NtkToDar( pNtk, 0, 1 );
+ Abc_NtkDelete( pNtk );
+
+ vMap = Iso_ManFindMapping( pAig1, pAig2, fVerbose );
+ Aig_ManStop( pAig2 );
+
+ if ( vMap != NULL )
+ {
+ printf( "Mapping of AIGs is found.\n" );
+ if ( fVerbose )
+ Vec_IntPrint( vMap );
+ }
+ else
+ printf( "Mapping of AIGs is NOT found.\n" );
+ Vec_IntFreeP( &vMap );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+
diff --git a/src/aig/aig/module.make b/src/aig/aig/module.make
index aaf5bf6d..04fe8771 100644
--- a/src/aig/aig/module.make
+++ b/src/aig/aig/module.make
@@ -6,6 +6,7 @@ SRC += src/aig/aig/aigCheck.c \
src/aig/aig/aigFanout.c \
src/aig/aig/aigFrames.c \
src/aig/aig/aigInter.c \
+ src/aig/aig/aigIso.c \
src/aig/aig/aigJust.c \
src/aig/aig/aigMan.c \
src/aig/aig/aigMem.c \
diff --git a/src/aig/gia/giaAbsVta.c b/src/aig/gia/giaAbsVta.c
index 472257b2..e4741b29 100644
--- a/src/aig/gia/giaAbsVta.c
+++ b/src/aig/gia/giaAbsVta.c
@@ -342,7 +342,6 @@ int Vec_IntDoubleWidth( Vec_Int_t * p, int nWords )
-
/**Function*************************************************************
Synopsis []
@@ -377,14 +376,25 @@ static inline Vta_Obj_t * Vga_ManFind( Vta_Man_t * p, int iObj, int iFrame )
static inline Vta_Obj_t * Vga_ManFindOrAdd( Vta_Man_t * p, int iObj, int iFrame )
{
Vta_Obj_t * pThis;
- int * pPlace;
+ int i, * pPlace;
assert( iObj >= 0 && iFrame >= -1 );
if ( p->nObjs == p->nObjsAlloc )
{
+ // resize objects
p->pObjs = ABC_REALLOC( Vta_Obj_t, p->pObjs, 2 * p->nObjsAlloc );
memset( p->pObjs + p->nObjsAlloc, 0, p->nObjsAlloc * sizeof(Vta_Obj_t) );
p->nObjsAlloc *= 2;
// rehash entries in the table
+ ABC_FREE( p->pBins );
+ p->nBins = Abc_PrimeCudd( 2 * p->nBins );
+ p->pBins = ABC_CALLOC( int, p->nBins );
+ Vta_ManForEachObj( p, pThis, i )
+ {
+ pThis->iNext = 0;
+ pPlace = Vga_ManLookup( p, pThis->iObj, pThis->iFrame );
+ assert( *pPlace == 0 );
+ *pPlace = i;
+ }
}
pPlace = Vga_ManLookup( p, iObj, iFrame );
if ( *pPlace )
diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c
index 95954f54..c71cfc7b 100644
--- a/src/base/abci/abc.c
+++ b/src/base/abci/abc.c
@@ -8837,6 +8837,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
extern void Aig_ManSupportsTest( Aig_Man_t * pMan );
extern int Aig_SupportSizeTest( Aig_Man_t * pMan );
extern int Abc_NtkSuppSizeTest( Abc_Ntk_t * p );
+ extern void Iso_ManTest( Aig_Man_t * pAig, int fVerbose );
if ( pNtk )
{
Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
@@ -8844,7 +8845,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// Aig_ManInterTest( pAig, 1 );
// Aig_ManSupportsTest( pAig );
// Aig_SupportSizeTest( pAig );
- Abc_NtkSuppSizeTest( pNtk );
+ Iso_ManTest( pAig, fVerbose );
Aig_ManStop( pAig );
}
}