Commit 7ea40494 by Alan Mishchenko

Graph isomorphism checking code.

parent e511b872
...@@ -3043,6 +3043,10 @@ SOURCE=.\src\aig\aig\aigInter.c ...@@ -3043,6 +3043,10 @@ SOURCE=.\src\aig\aig\aigInter.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\src\aig\aig\aigIso.c
# End Source File
# Begin Source File
SOURCE=.\src\aig\aig\aigJust.c SOURCE=.\src\aig\aig\aigJust.c
# End Source File # End Source File
# Begin Source File # Begin Source File
...@@ -3195,6 +3199,10 @@ SOURCE=.\src\aig\saig\saigConstr2.c ...@@ -3195,6 +3199,10 @@ SOURCE=.\src\aig\saig\saigConstr2.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\src\aig\saig\saigDual.c
# End Source File
# Begin Source File
SOURCE=.\src\aig\saig\saigDup.c SOURCE=.\src\aig\saig\saigDup.c
# End Source File # End Source File
# Begin Source File # Begin Source File
......
/**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
...@@ -6,6 +6,7 @@ SRC += src/aig/aig/aigCheck.c \ ...@@ -6,6 +6,7 @@ SRC += src/aig/aig/aigCheck.c \
src/aig/aig/aigFanout.c \ src/aig/aig/aigFanout.c \
src/aig/aig/aigFrames.c \ src/aig/aig/aigFrames.c \
src/aig/aig/aigInter.c \ src/aig/aig/aigInter.c \
src/aig/aig/aigIso.c \
src/aig/aig/aigJust.c \ src/aig/aig/aigJust.c \
src/aig/aig/aigMan.c \ src/aig/aig/aigMan.c \
src/aig/aig/aigMem.c \ src/aig/aig/aigMem.c \
......
...@@ -342,7 +342,6 @@ int Vec_IntDoubleWidth( Vec_Int_t * p, int nWords ) ...@@ -342,7 +342,6 @@ int Vec_IntDoubleWidth( Vec_Int_t * p, int nWords )
/**Function************************************************************* /**Function*************************************************************
Synopsis [] Synopsis []
...@@ -377,14 +376,25 @@ static inline Vta_Obj_t * Vga_ManFind( Vta_Man_t * p, int iObj, int iFrame ) ...@@ -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 ) static inline Vta_Obj_t * Vga_ManFindOrAdd( Vta_Man_t * p, int iObj, int iFrame )
{ {
Vta_Obj_t * pThis; Vta_Obj_t * pThis;
int * pPlace; int i, * pPlace;
assert( iObj >= 0 && iFrame >= -1 ); assert( iObj >= 0 && iFrame >= -1 );
if ( p->nObjs == p->nObjsAlloc ) if ( p->nObjs == p->nObjsAlloc )
{ {
// resize objects
p->pObjs = ABC_REALLOC( Vta_Obj_t, p->pObjs, 2 * p->nObjsAlloc ); p->pObjs = ABC_REALLOC( Vta_Obj_t, p->pObjs, 2 * p->nObjsAlloc );
memset( p->pObjs + p->nObjsAlloc, 0, p->nObjsAlloc * sizeof(Vta_Obj_t) ); memset( p->pObjs + p->nObjsAlloc, 0, p->nObjsAlloc * sizeof(Vta_Obj_t) );
p->nObjsAlloc *= 2; p->nObjsAlloc *= 2;
// rehash entries in the table // 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 ); pPlace = Vga_ManLookup( p, iObj, iFrame );
if ( *pPlace ) if ( *pPlace )
......
...@@ -8837,6 +8837,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -8837,6 +8837,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
extern void Aig_ManSupportsTest( Aig_Man_t * pMan ); extern void Aig_ManSupportsTest( Aig_Man_t * pMan );
extern int Aig_SupportSizeTest( Aig_Man_t * pMan ); extern int Aig_SupportSizeTest( Aig_Man_t * pMan );
extern int Abc_NtkSuppSizeTest( Abc_Ntk_t * p ); extern int Abc_NtkSuppSizeTest( Abc_Ntk_t * p );
extern void Iso_ManTest( Aig_Man_t * pAig, int fVerbose );
if ( pNtk ) if ( pNtk )
{ {
Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 );
...@@ -8844,7 +8845,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) ...@@ -8844,7 +8845,7 @@ int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv )
// Aig_ManInterTest( pAig, 1 ); // Aig_ManInterTest( pAig, 1 );
// Aig_ManSupportsTest( pAig ); // Aig_ManSupportsTest( pAig );
// Aig_SupportSizeTest( pAig ); // Aig_SupportSizeTest( pAig );
Abc_NtkSuppSizeTest( pNtk ); Iso_ManTest( pAig, fVerbose );
Aig_ManStop( pAig ); Aig_ManStop( pAig );
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment