saigIso.c 18.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/**CFile****************************************************************

  FileName    [saigIso.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Sequential AIG package.]

  Synopsis    [Sequential cleanup.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: saigIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

***********************************************************************/

21
#include "aig/ioa/ioa.h"
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
#include "saig.h"

ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Find the canonical permutation of the COs.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Int_t * Saig_ManFindIsoPermCos( Aig_Man_t * pAig, Vec_Int_t * vPermCis )
{
48
    extern int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 );
49 50 51
    Vec_Int_t * vPermCos;
    Aig_Obj_t * pObj, * pFanin;
    int i, Entry, Diff;
52 53
    assert( Vec_IntSize(vPermCis) == Aig_ManCiNum(pAig) );
    vPermCos = Vec_IntAlloc( Aig_ManCoNum(pAig) );
54 55 56 57 58 59 60 61 62 63 64 65
    if ( Saig_ManPoNum(pAig) == 1 )
        Vec_IntPush( vPermCos, 0 );
    else
    {
        Vec_Ptr_t * vRoots = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
        Saig_ManForEachPo( pAig, pObj, i )
        {
            pFanin = Aig_ObjFanin0(pObj);
            assert( Aig_ObjIsConst1(pFanin) || pFanin->iData > 0 );
            pObj->iData = Abc_Var2Lit( pFanin->iData, Aig_ObjFaninC0(pObj) );
            Vec_PtrPush( vRoots, pObj );
        }
66
        Vec_PtrSort( vRoots, (int (*)(void))Iso_ObjCompareByData );
67
        Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i )
68
            Vec_IntPush( vPermCos, Aig_ObjCioId(pObj) );
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
        Vec_PtrFree( vRoots );
    }
    // add flop outputs
    Diff = Saig_ManPoNum(pAig) - Saig_ManPiNum(pAig);
    Vec_IntForEachEntryStart( vPermCis, Entry, i, Saig_ManPiNum(pAig) )
        Vec_IntPush( vPermCos, Entry + Diff );
    return vPermCos;
}

/**Function*************************************************************

  Synopsis    [Performs canonical duplication of the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Saig_ManDupIsoCanonical_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj )
{
    if ( Aig_ObjIsTravIdCurrent(pAig, pObj) )
        return;
    Aig_ObjSetTravIdCurrent(pAig, pObj);
    assert( Aig_ObjIsNode(pObj) );
    if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) || !Aig_ObjIsNode(Aig_ObjFanin1(pObj)) )
    {
        Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
        Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
    }
    else
    {
        assert( Aig_ObjFanin0(pObj)->iData != Aig_ObjFanin1(pObj)->iData );
        if ( Aig_ObjFanin0(pObj)->iData < Aig_ObjFanin1(pObj)->iData )
        {
            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
        }
        else
        {
            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) );
            Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
        }
    }
    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
}

/**Function*************************************************************

  Synopsis    [Performs canonical duplication of the AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose )
{
    Aig_Man_t * pNew;
    Aig_Obj_t * pObj;
    Vec_Int_t * vPerm, * vPermCo;
    int i, Entry;
    // derive permutations
    vPerm   = Saig_ManFindIsoPerm( pAig, fVerbose );
    vPermCo = Saig_ManFindIsoPermCos( pAig, vPerm );
    // create the new manager
    pNew = Aig_ManStart( Aig_ManNodeNum(pAig) );
    pNew->pName = Abc_UtilStrsav( pAig->pName );
    Aig_ManIncrementTravId( pAig );
    // create constant
    pObj = Aig_ManConst1(pAig);
    pObj->pData = Aig_ManConst1(pNew);
    Aig_ObjSetTravIdCurrent( pAig, pObj );
    // create PIs
    Vec_IntForEachEntry( vPerm, Entry, i )
    {
148
        pObj = Aig_ManCi(pAig, Entry);
149
        pObj->pData = Aig_ObjCreateCi(pNew);
150 151 152 153 154
        Aig_ObjSetTravIdCurrent( pAig, pObj );
    }
    // traverse from the POs
    Vec_IntForEachEntry( vPermCo, Entry, i )
    {
155
        pObj = Aig_ManCo(pAig, Entry);
156 157 158 159 160
        Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) );
    }
    // create POs
    Vec_IntForEachEntry( vPermCo, Entry, i )
    {
161
        pObj = Aig_ManCo(pAig, Entry);
162
        Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) );
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
    }
    Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) );
    Vec_IntFreeP( &vPerm );
    Vec_IntFreeP( &vPermCo );
    return pNew;
}





/**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;
190 191
    assert( Aig_ManCiNum(pAig1) == Aig_ManCiNum(pAig2) );
    assert( Aig_ManCoNum(pAig1) == Aig_ManCoNum(pAig2) );
192 193 194 195 196
    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);
197
    Aig_ManForEachCi( pAig2, pObj, i )
198
        pObj->pData = Aig_ManCi( pAig1, Vec_IntEntry(vMap2to1, i) );
199 200 201 202 203 204 205 206 207 208 209 210 211 212
    // 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
213
    if ( Aig_ManCoNum(pAig1)-Aig_ManRegNum(pAig1) == 1 && Aig_ObjChild0Copy(Aig_ManCo(pAig2, 0)) != Aig_ObjChild0(Aig_ManCo(pAig1, 0)) )
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    {
        if ( fVerbose )
            printf( "Structural equivalence failed at primary output 0.\n" );
        return 0;
    }
    return 1;    
}

//static int s_Counter;

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Iso_ManNegEdgeNum( Aig_Man_t * pAig )
{
    Aig_Obj_t * pObj;
    int i, Counter = 0;
    if ( pAig->nComplEdges > 0 )
        return pAig->nComplEdges;
    Aig_ManForEachObj( pAig, pObj, i )
        if ( Aig_ObjIsNode(pObj) )
        {
            Counter += Aig_ObjFaninC0(pObj);
            Counter += Aig_ObjFaninC1(pObj);
        }
247
        else if ( Aig_ObjIsCo(pObj) )
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
            Counter += Aig_ObjFaninC0(pObj);
    return (pAig->nComplEdges = Counter);
}

/**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, Vec_Int_t * vPerm1_, Vec_Int_t * vPerm2_, int fVerbose )
{
    Vec_Int_t * vPerm1, * vPerm2, * vInvPerm2;
    int i, Entry;
268
    if ( Aig_ManCiNum(pAig1) != Aig_ManCiNum(pAig2) )
269
        return NULL;
270
    if ( Aig_ManCoNum(pAig1) != Aig_ManCoNum(pAig2) )
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
        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;
//    s_Counter++;

    if ( fVerbose ) 
        printf( "AIG1:\n" );
    vPerm1 = vPerm1_ ? vPerm1_ : Saig_ManFindIsoPerm( pAig1, fVerbose );
    if ( fVerbose )
        printf( "AIG1:\n" );
    vPerm2 = vPerm2_ ? vPerm2_ : Saig_ManFindIsoPerm( pAig2, fVerbose );
    if ( vPerm1_ )
289
        assert( Vec_IntSize(vPerm1_) == Aig_ManCiNum(pAig1) );
290
    if ( vPerm2_ )
291
        assert( Vec_IntSize(vPerm2_) == Aig_ManCiNum(pAig2) );
292 293 294 295 296
    // find canonical permutation
    // vPerm1/vPerm2 give canonical order of CIs of AIG1/AIG2
    vInvPerm2 = Vec_IntInvert( vPerm2, -1 );
    Vec_IntForEachEntry( vInvPerm2, Entry, i )
    {
297
        assert( Entry >= 0 && Entry < Aig_ManCiNum(pAig1) );
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
        Vec_IntWriteEntry( vInvPerm2, i, Vec_IntEntry(vPerm1, Entry) );
    }
    if ( vPerm1_ == NULL )
        Vec_IntFree( vPerm1 );
    if ( vPerm2_ == NULL )
        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     []

***********************************************************************/
Aig_Man_t * Iso_ManFilterPos_old( Aig_Man_t * pAig, int fVerbose )
{
    int fVeryVerbose = 0;
    Vec_Ptr_t * vParts, * vPerms, * vAigs;
    Vec_Int_t * vPos, * vMap;
    Aig_Man_t * pPart, * pTemp;
    int i, k, nPos;

    // derive AIG for each PO
331
    nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
    vParts = Vec_PtrAlloc( nPos );
    vPerms = Vec_PtrAlloc( nPos );
    for ( i = 0; i < nPos; i++ )
    {
        pPart = Saig_ManDupCones( pAig, &i, 1 );
        vMap  = Saig_ManFindIsoPerm( pPart, fVeryVerbose );
        Vec_PtrPush( vParts, pPart ); 
        Vec_PtrPush( vPerms, vMap );
    }
//    s_Counter = 0;

    // check AIGs for each PO
    vAigs = Vec_PtrAlloc( 1000 );
    vPos  = Vec_IntAlloc( 1000 );
    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i )
    {
        if ( fVeryVerbose )
        {
            printf( "AIG %4d : ", i );
            Aig_ManPrintStats( pPart );
        }
        Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, k )
        {
            if ( fVeryVerbose )
                printf( "Comparing AIG %4d and AIG %4d.  ", Vec_IntEntry(vPos,k), i );
            vMap = Iso_ManFindMapping( pTemp, pPart, 
                (Vec_Int_t *)Vec_PtrEntry(vPerms, Vec_IntEntry(vPos,k)), 
                (Vec_Int_t *)Vec_PtrEntry(vPerms, i),
                fVeryVerbose );
            if ( vMap != NULL )
            {
                if ( fVeryVerbose )
                    printf( "Found match\n" );
365 366
//                if ( fVerbose )
//                    printf( "Found match for AIG %4d and AIG %4d.\n", Vec_IntEntry(vPos,k), i );
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
                Vec_IntFree( vMap );
                break;
            }
            if ( fVeryVerbose )
                printf( "No match.\n" );
        }
        if ( k == Vec_PtrSize(vAigs) )
        {
            Vec_PtrPush( vAigs, pPart );
            Vec_IntPush( vPos, i );
        }
    }
    // delete AIGs
    Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i )
        Aig_ManStop( pPart );
    Vec_PtrFree( vParts );
    Vec_PtrForEachEntry( Vec_Int_t *, vPerms, vMap, i )
        Vec_IntFree( vMap );
    Vec_PtrFree( vPerms );
    // derive the resulting AIG
    pPart = Saig_ManDupCones( pAig, Vec_IntArray(vPos), Vec_IntSize(vPos) );
    Vec_PtrFree( vAigs );
    Vec_IntFree( vPos );

//    printf( "The number of all checks %d.  Complex checks %d.\n", nPos*(nPos-1)/2, s_Counter );
    return pPart;
}

/**Function*************************************************************

  Synopsis    [Takes multi-output sequential AIG.]

  Description [Returns candidate equivalence classes of POs.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Iso_StoCompareVecStr( Vec_Str_t ** p1, Vec_Str_t ** p2 )
{
    return Vec_StrCompareVec( *p1, *p2 );
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
422
Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose )
423
{
424
//    int fVeryVerbose = 0;
425 426 427 428
    Aig_Man_t * pPart, * pTemp;
    Vec_Ptr_t * vBuffers, * vClasses;
    Vec_Int_t * vLevel, * vRemain;
    Vec_Str_t * vStr, * vPrev;
429
    int i, nPos;
430 431
    abctime clk = Abc_Clock();
    abctime clkDup = 0, clkAig = 0, clkIso = 0, clk2;
432
    *pvPosEquivs = NULL;
433 434

    // derive AIG for each PO
435
    nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig);
436 437 438
    vBuffers = Vec_PtrAlloc( nPos );
    for ( i = 0; i < nPos; i++ )
    {
439
        if ( i % 100 == 0 )
440 441
            printf( "%6d finished...\r", i );

442
        clk2 = Abc_Clock();
443
        pPart = Saig_ManDupCones( pAig, &i, 1 );
444
        clkDup += Abc_Clock() - clk2;
445

446
        clk2 = Abc_Clock();
447
        pTemp = Saig_ManDupIsoCanonical( pPart, 0 );
448
        clkIso += Abc_Clock() - clk2;
449

450
        clk2 = Abc_Clock();
451
        vStr  = Ioa_WriteAigerIntoMemoryStr( pTemp );
452
        clkAig += Abc_Clock() - clk2;
453

454 455 456 457 458 459 460 461
        Vec_PtrPush( vBuffers, vStr );
        Aig_ManStop( pTemp );
        Aig_ManStop( pPart );
        // remember the output number in nCap (attention: hack!)
        vStr->nCap = i;
    }
//    s_Counter = 0;
    if ( fVerbose )
462 463 464 465 466
    {
    Abc_PrintTime( 1, "Duplicate time", clkDup );
    Abc_PrintTime( 1, "Isomorph  time", clkIso );
    Abc_PrintTime( 1, "AIGER     time", clkAig );
    }
467 468

    // sort the infos
469
    clk = Abc_Clock();
470 471 472
    Vec_PtrSort( vBuffers, (int (*)(void))Iso_StoCompareVecStr );

    // create classes
473
    clk = Abc_Clock();
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
    vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) );
    // start the first class
    Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) );
    vPrev = (Vec_Str_t *)Vec_PtrEntry( vBuffers, 0 );
    Vec_IntPush( vLevel, vPrev->nCap );
    // consider other classes
    Vec_PtrForEachEntryStart( Vec_Str_t *, vBuffers, vStr, i, 1 )
    {
        if ( Vec_StrCompareVec(vPrev, vStr) )
            Vec_PtrPush( vClasses, Vec_IntAlloc(4) );
        vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses );
        Vec_IntPush( vLevel, vStr->nCap );
        vPrev = vStr;
    }
    Vec_VecFree( (Vec_Vec_t *)vBuffers );

    if ( fVerbose )
491
    Abc_PrintTime( 1, "Sorting   time", Abc_Clock() - clk );
492 493 494 495 496
//    Abc_PrintTime( 1, "Traversal time", time_Trav );

    // report the results
//    Vec_VecPrintInt( (Vec_Vec_t *)vClasses );
//    printf( "Devided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) );
497
/*
498 499 500 501 502 503 504 505 506
    if ( fVerbose )
    {
        Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
            if ( Vec_IntSize(vLevel) > 1 )
                printf( "%d ", Vec_IntSize(vLevel) );
            else
                nUnique++;
        printf( " Unique = %d\n", nUnique );
    }
507
*/
508 509 510 511 512 513

    // canonicize order
    Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
        Vec_IntSort( vLevel, 0 );
     Vec_VecSortByFirstInt( (Vec_Vec_t *)vClasses, 0 );
       
514 515 516 517 518 519 520 521 522 523
    // collect the first ones
    vRemain = Vec_IntAlloc( 100 );
    Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i )
        Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) );

    // derive the resulting AIG
    pPart = Saig_ManDupCones( pAig, Vec_IntArray(vRemain), Vec_IntSize(vRemain) );
    Vec_IntFree( vRemain );

//    return (Vec_Vec_t *)vClasses;
524 525
//    Vec_VecFree( (Vec_Vec_t *)vClasses );
    *pvPosEquivs = vClasses;
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
    return pPart;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Iso_ManTest( Aig_Man_t * pAig, int fVerbose )
{
    Vec_Int_t * vPerm;
543
    abctime clk = Abc_Clock();
544 545
    vPerm = Saig_ManFindIsoPerm( pAig, fVerbose );
    Vec_IntFree( vPerm );
546
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
547 548 549 550 551 552 553 554 555 556 557 558 559 560
    return NULL;
}

/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
561
Aig_Man_t * Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose )
562 563
{ 
    Aig_Man_t * pPart;
564
    abctime clk = Abc_Clock();
565
    pPart = Iso_ManFilterPos( pAig, pvPosEquivs, fVerbose );
566
    printf( "Reduced %d outputs to %d outputs.  ", Saig_ManPoNum(pAig), Saig_ManPoNum(pPart) );
567
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
568
    if ( fVerbose && *pvPosEquivs && Saig_ManPoNum(pAig) != Vec_PtrSize(*pvPosEquivs) )
569 570 571 572 573
    {
        printf( "Nontrivial classes:\n" );
        Vec_VecPrintInt( (Vec_Vec_t *)*pvPosEquivs, 1 );
    }
//    Aig_ManStopP( &pPart );
574 575 576
    return pPart;
}

577
ABC_NAMESPACE_IMPL_END
578

579
#include "base/abc/abc.h"
580

581 582
ABC_NAMESPACE_IMPL_START

583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Iso_ManTest888( 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 );
603
    Abc_NtkPermute( pNtk, 1, 0, 1, NULL );
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
    pAig2 = Abc_NtkToDar( pNtk, 0, 1 );
    Abc_NtkDelete( pNtk );

    vMap = Iso_ManFindMapping( pAig1, pAig2, NULL, NULL, 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 );
    return NULL;
}

////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END