pdrCore.c 55.1 KB
Newer Older
1 2 3 4 5 6
/**CFile****************************************************************

  FileName    [pdrCore.c]

  SystemName  [ABC: Logic synthesis and verification system.]

7
  PackageName [Property driven reachability.]
8 9 10 11 12 13 14 15 16 17 18 19 20 21

  Synopsis    [Core procedures.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - November 20, 2010.]

  Revision    [$Id: pdrCore.c,v 1.00 2010/11/20 00:00:00 alanmi Exp $]

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

#include "pdrInt.h"
Alan Mishchenko committed
22
#include "base/main/main.h"
23
#include "misc/hash/hash.h"
24 25 26 27 28 29 30 31

ABC_NAMESPACE_IMPL_START


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

32
extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved );
Alan Mishchenko committed
33
extern int Gia_ManToBridgeAbort( FILE * pFile, int Size, unsigned char * pBuffer );
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

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

  Synopsis    [Returns 1 if the state could be blocked.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars )
{
    memset( pPars, 0, sizeof(Pdr_Par_t) );
53 54 55 56 57 58
//    pPars->iOutput        =      -1;  // zero-based output number
    pPars->nRecycle       =     300;  // limit on vars for recycling
    pPars->nFrameMax      =   10000;  // limit on number of timeframes
    pPars->nTimeOut       =       0;  // timeout in seconds
    pPars->nTimeOutGap    =       0;  // timeout in seconds since the last solved
    pPars->nConfLimit     =       0;  // limit on SAT solver conflicts
59
    pPars->nConfGenLimit  =       0;  // limit on SAT solver conflicts during generalization
60
    pPars->nRestLimit     =       0;  // limit on the number of proof-obligations
61
    pPars->nRandomSeed   = 91648253;  // value to seed the SAT solver with
62 63
    pPars->fTwoRounds     =       0;  // use two rounds for generalization
    pPars->fMonoCnf       =       0;  // monolythic CNF
64
    pPars->fNewXSim       =       0;  // updated X-valued simulation
65 66
    pPars->fFlopPrio      =       0;  // use structural flop priorities
    pPars->fFlopOrder     =       0;  // order flops for 'analyze_final' during generalization
67
    pPars->fDumpInv       =       0;  // dump inductive invariant
68
    pPars->fUseSupp       =       1;  // using support variables in the invariant
69
    pPars->fShortest      =       0;  // forces bug traces to be shortest
70
    pPars->fUsePropOut    =       1;  // use property output
71 72 73 74
    pPars->fSkipDown      =       1;  // apply down in generalization
    pPars->fCtgs          =       0;  // handle CTGs in down
    pPars->fUseAbs        =       0;  // use abstraction 
    pPars->fUseSimpleRef  =       0;  // simplified CEX refinement
75 76 77 78
    pPars->fVerbose       =       0;  // verbose output
    pPars->fVeryVerbose   =       0;  // very verbose output
    pPars->fNotVerbose    =       0;  // not printing line-by-line progress
    pPars->iFrame         =      -1;  // explored up to this frame
79 80
    pPars->nFailOuts      =       0;  // the number of disproved outputs
    pPars->nDropOuts      =       0;  // the number of timed out outputs
81
    pPars->timeLastSolved =       0;  // last one solved
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
}

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

  Synopsis    [Reduces clause using analyzeFinal.]

  Description [Assumes that the SAT solver just terminated an UNSAT call.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Pdr_Set_t * Pdr_ManReduceClause( Pdr_Man_t * p, int k, Pdr_Set_t * pCube )
{
    Pdr_Set_t * pCubeMin;
    Vec_Int_t * vLits;
    int i, Entry, nCoreLits, * pCoreLits;
    // get relevant SAT literals
    nCoreLits = sat_solver_final(Pdr_ManSolver(p, k), &pCoreLits);
    // translate them into register literals and remove auxiliary
    vLits = Pdr_ManLitsToCube( p, k, pCoreLits, nCoreLits );
    // skip if there is no improvement
    if ( Vec_IntSize(vLits) == pCube->nLits )
        return NULL;
    assert( Vec_IntSize(vLits) < pCube->nLits );
    // if the cube overlaps with init, add any literal
    Vec_IntForEachEntry( vLits, Entry, i )
110
        if ( Abc_LitIsCompl(Entry) == 0 ) // positive literal
111 112 113 114 115
            break;
    if ( i == Vec_IntSize(vLits) ) // only negative literals
    {
        // add the first positive literal
        for ( i = 0; i < pCube->nLits; i++ )
116
            if ( Abc_LitIsCompl(pCube->Lits[i]) == 0 ) // positive literal
117 118 119 120 121 122 123 124 125 126 127 128 129
            {
                Vec_IntPush( vLits, pCube->Lits[i] );
                break;
            }
        assert( i < pCube->nLits );
    }
    // generate a starting cube
    pCubeMin  = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits), Vec_IntSize(vLits) );
    assert( !Pdr_SetIsInit(pCubeMin, -1) );
/*
    // make sure the cube works
    {
    int RetValue;
130
    RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0, 0, 1 );
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    assert( RetValue );
    }
*/
    return pCubeMin;
}

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

  Synopsis    [Returns 1 if the state could be blocked.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Pdr_ManPushClauses( Pdr_Man_t * p )
{
    Pdr_Set_t * pTemp, * pCubeK, * pCubeK1;
    Vec_Ptr_t * vArrayK, * vArrayK1;
152
    int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1;
153
    int iStartFrame = p->pPars->fShiftStart ? p->iUseFrame : 1;
154
    int Counter = 0;
155
    abctime clk = Abc_Clock();
156
    assert( p->iUseFrame > 0 );
157
    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, iStartFrame, kMax )
158 159
    {
        Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
160
        vArrayK1 = Vec_VecEntry( p->vClauses, k+1 );
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
        {
            Counter++;

            // remove cubes in the same frame that are contained by pCubeK
            Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
            {
                if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
                    continue;
                Pdr_SetDeref( pTemp );
                Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
                Vec_PtrPop(vArrayK);
                m--;
            }

            // check if the clause can be moved to the next frame
177
            RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0, 0, 1 );
178 179 180
            if ( RetValue2 == -1 )
                return -1;
            if ( !RetValue2 )
181 182 183 184 185 186 187
                continue;

            {
                Pdr_Set_t * pCubeMin;
                pCubeMin = Pdr_ManReduceClause( p, k, pCubeK );
                if ( pCubeMin != NULL )
                {
188
//                Abc_Print( 1, "%d ", pCubeK->nLits - pCubeMin->nLits );
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
                    Pdr_SetDeref( pCubeK );
                    pCubeK = pCubeMin;
                }
            }

            // if it can be moved, add it to the next frame
            Pdr_ManSolverAddClause( p, k+1, pCubeK );
            // check if the clause subsumes others
            Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i )
            {
                if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1
                    continue;
                Pdr_SetDeref( pCubeK1 );
                Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) );
                Vec_PtrPop(vArrayK1);
                i--;
            }
            // add the last clause
            Vec_PtrPush( vArrayK1, pCubeK );
            Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) );
            Vec_PtrPop(vArrayK);
            j--;
        }
        if ( Vec_PtrSize(vArrayK) == 0 )
            RetValue = 1;
    }

    // clean up the last one
217
    vArrayK = Vec_VecEntry( p->vClauses, kMax );
218 219 220 221 222 223 224 225 226
    Vec_PtrSort( vArrayK, (int (*)(void))Pdr_SetCompare );
    Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
    {
        // remove cubes in the same frame that are contained by pCubeK
        Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
        {
            if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
                continue;
/*
227
            Abc_Print( 1, "===\n" );
228
            Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL );
229
            Abc_Print( 1, "\n" );
230
            Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL );
231
            Abc_Print( 1, "\n" );
232 233 234 235 236 237 238
*/
            Pdr_SetDeref( pTemp );
            Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
            Vec_PtrPop(vArrayK);
            m--;
        }
    }
239
    p->tPush += Abc_Clock() - clk;
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    return RetValue;
}

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

  Synopsis    [Returns 1 if the clause is contained in higher clauses.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Pdr_ManCheckContainment( Pdr_Man_t * p, int k, Pdr_Set_t * pSet )
{
    Pdr_Set_t * pThis;
    Vec_Ptr_t * vArrayK;
    int i, j, kMax = Vec_PtrSize(p->vSolvers)-1;
259
    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 )
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
        Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pThis, j )
            if ( Pdr_SetContains( pSet, pThis ) )
                return 1;
    return 0;
}


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

  Synopsis    [Sorts literals by priority.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int * Pdr_ManSortByPriority( Pdr_Man_t * p, Pdr_Set_t * pCube )
{
    int * pPrios = Vec_IntArray(p->vPrio);
    int * pArray = p->pOrder;
    int temp, i, j, best_i, nSize = pCube->nLits;
    // initialize variable order
    for ( i = 0; i < nSize; i++ )
        pArray[i] = i;
    for ( i = 0; i < nSize-1; i++ )
    {
        best_i = i;
        for ( j = i+1; j < nSize; j++ )
//            if ( pArray[j] < pArray[best_i] )
291
            if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] ) // list lower priority first (these will be removed first)
292
                best_i = j;
293 294
        temp = pArray[i];
        pArray[i] = pArray[best_i];
295 296 297 298
        pArray[best_i] = temp;
    }
/*
    for ( i = 0; i < pCube->nLits; i++ )
299 300
        Abc_Print( 1, "%2d : %5d    %5d  %5d\n", i, pArray[i], pCube->Lits[pArray[i]]>>1, pPrios[pCube->Lits[pArray[i]]>>1] );
    Abc_Print( 1, "\n" );
301 302 303 304 305 306 307
*/
    return pArray;
}


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

308 309 310 311 312 313 314 315 316 317 318 319
  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int ZPdr_ManSimpleMic( Pdr_Man_t * p, int k, Pdr_Set_t ** ppCube )
{
    int * pOrder;
320
    int i, j, Lit, RetValue;
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
    Pdr_Set_t * pCubeTmp;
    // perform generalization
    if ( p->pPars->fSkipGeneral )
      return 0;

    // sort literals by their occurences
    pOrder = Pdr_ManSortByPriority( p, *ppCube );
    // try removing literals
    for ( j = 0; j < (*ppCube)->nLits; j++ )
    {
        // use ordering
    //        i = j;
        i = pOrder[j];

        assert( (*ppCube)->Lits[i] != -1 );
        // check init state
        if ( Pdr_SetIsInit(*ppCube, i) )
            continue;
        // try removing this literal
        Lit = (*ppCube)->Lits[i]; (*ppCube)->Lits[i] = -1; 
341
        RetValue = Pdr_ManCheckCube( p, k, *ppCube, NULL, p->pPars->nConfLimit, 0, 1 );
342 343 344 345 346 347 348 349 350 351 352
        if ( RetValue == -1 )
            return -1;
        (*ppCube)->Lits[i] = Lit;
        if ( RetValue == 0 )
            continue;

        // success - update the cube
        *ppCube = Pdr_SetCreateFrom( pCubeTmp = *ppCube, i );
        Pdr_SetDeref( pCubeTmp );
        assert( (*ppCube)->nLits > 0 );

353
        // get the ordering by decreasing priority
354
        pOrder = Pdr_ManSortByPriority( p, *ppCube );
355
        j--;
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
    }
    return 0;
}


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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int ZPdr_ManDown( Pdr_Man_t * p, int k, Pdr_Set_t ** ppCube, Pdr_Set_t * pPred, Hash_Int_t * keep, Pdr_Set_t * pIndCube, int * added )
{
    int RetValue = 0, CtgRetValue, i, ctgAttempts, l, micResult;
    int kMax = Vec_PtrSize(p->vSolvers)-1;
    Pdr_Set_t * pCubeTmp, * pCubeMin, * pCtg;
    while ( RetValue == 0 )
    {
        ctgAttempts = 0;
        while ( p->pPars->fCtgs && RetValue == 0 && k > 1 && ctgAttempts < 3 )
        {
383
            pCtg = Pdr_SetDup( pPred );
384 385 386 387 388 389 390 391 392 393 394 395 396
            //Check CTG for inductiveness
            if ( Pdr_SetIsInit( pCtg, -1 ) )
            {
                Pdr_SetDeref( pCtg );
                break;
            }
            if (*added == 0)
            {
                for ( i = 1; i <= k; i++ )
                    Pdr_ManSolverAddClause( p, i, pIndCube);
                *added = 1;
            }
            ctgAttempts++;
397
            CtgRetValue = Pdr_ManCheckCube( p, k-1, pCtg, NULL, p->pPars->nConfLimit, 0, 1 );
398 399 400 401 402 403 404 405 406 407
            if ( CtgRetValue != 1 )
            {
                Pdr_SetDeref( pCtg );
                break;
            }
            pCubeMin = Pdr_ManReduceClause( p, k-1, pCtg );
            if ( pCubeMin == NULL )
                pCubeMin = Pdr_SetDup ( pCtg );

            for ( l = k; l < kMax; l++ )
408
                if ( !Pdr_ManCheckCube( p, l, pCubeMin, NULL, 0, 0, 1 ) )
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
                    break;
            micResult = ZPdr_ManSimpleMic( p, l-1, &pCubeMin );
            assert ( micResult != -1 );

            // add new clause
            if ( p->pPars->fVeryVerbose )
            {
                Abc_Print( 1, "Adding cube " );
                Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
                Abc_Print( 1, " to frame %d.\n", l );
            }
            // set priority flops
            for ( i = 0; i < pCubeMin->nLits; i++ )
            {
                assert( pCubeMin->Lits[i] >= 0 );
                assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
425 426
                if ( (Vec_IntEntry(p->vPrio, pCubeMin->Lits[i] / 2) >> p->nPrioShift) == 0 )
                    p->nAbsFlops++;
427
                Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 << p->nPrioShift );
428 429 430 431 432 433 434
            }

            Vec_VecPush( p->vClauses, l, pCubeMin );   // consume ref
            p->nCubes++;
            // add clause
            for ( i = 1; i <= l; i++ )
                Pdr_ManSolverAddClause( p, i, pCubeMin );
435 436
            Pdr_SetDeref( pPred );
            RetValue = Pdr_ManCheckCube( p, k, *ppCube, &pPred, p->pPars->nConfLimit, 0, 1 );
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
            assert( RetValue >= 0 );
            Pdr_SetDeref( pCtg );
            if ( RetValue == 1 )
            {
                //printf ("IT'S A ONE\n");
                return 1;
            }
        }

        //join
        if ( p->pPars->fVeryVerbose )
        {
            printf("Cube:\n");
            ZPdr_SetPrint( *ppCube );
            printf("\nPred:\n");
            ZPdr_SetPrint( pPred );
        }
        *ppCube = ZPdr_SetIntersection( pCubeTmp = *ppCube, pPred, keep );
        Pdr_SetDeref( pCubeTmp );
        Pdr_SetDeref( pPred );
        if ( *ppCube == NULL )
            return 0;
        if ( p->pPars->fVeryVerbose )
        {
461 462
            printf("Intersection:\n");
            ZPdr_SetPrint( *ppCube );
463 464 465
        }
        if ( Pdr_SetIsInit( *ppCube, -1 ) )
        {
466 467 468
            if ( p->pPars->fVeryVerbose )
                printf ("Failed initiation\n");
            return 0;
469
        }
470
        RetValue = Pdr_ManCheckCube( p, k, *ppCube, &pPred, p->pPars->nConfLimit, 0, 1 );
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
        if ( RetValue == -1 )
            return -1;
        if ( RetValue == 1 )
        {
            //printf ("*********IT'S A ONE\n");
            break;
        }
        if ( RetValue == 0 && (*ppCube)->nLits == 1)
        {
            Pdr_SetDeref( pPred ); // fixed memory leak
            // A workaround for the incomplete assignment returned by the SAT
            // solver
            return 0;
        }
    }
    return 1;
}
488 489 490

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

491
  Synopsis    [Specialized sorting of flops based on priority.]
492 493 494 495 496 497 498 499

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
500
static inline int Vec_IntSelectSortPrioReverseLit( int * pArray, int nSize, Vec_Int_t * vPrios )
501 502 503 504 505 506
{
    int i, j, best_i;
    for ( i = 0; i < nSize-1; i++ )
    {
        best_i = i;
        for ( j = i+1; j < nSize; j++ )
507
            if ( Vec_IntEntry(vPrios, Abc_Lit2Var(pArray[j])) > Vec_IntEntry(vPrios, Abc_Lit2Var(pArray[best_i])) ) // prefer higher priority
508 509 510
                best_i = j;
        ABC_SWAP( int, pArray[i], pArray[best_i] );
    }
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
    return 1;
}

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

  Synopsis    [Performs generalization using a different idea.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Pdr_ManGeneralize2( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppCubeMin )
{
527
#if 0
528 529
    int fUseMinAss = 0;
    sat_solver * pSat = Pdr_ManFetchSolver( p, k );
530
    int Order = Vec_IntSelectSortPrioReverseLit( pCube->Lits, pCube->nLits, p->vPrio );
531 532 533 534 535 536 537 538 539 540 541 542 543 544
    Vec_Int_t * vLits1 = Pdr_ManCubeToLits( p, k, pCube, 1, 0 );
    int RetValue, Count = 0, iLit, Lits[2], nLits = Vec_IntSize( vLits1 );
    // create free variables
    int i, iUseVar, iAndVar;
    iAndVar = Pdr_ManFreeVar(p, k);
    for ( i = 1; i < nLits; i++ )
        Pdr_ManFreeVar(p, k);
    iUseVar = Pdr_ManFreeVar(p, k);
    for ( i = 1; i < nLits; i++ )
        Pdr_ManFreeVar(p, k);
    assert( iUseVar == iAndVar + nLits );
    // if there is only one positive literal, put it in front and always assume
    if ( fUseMinAss )
    {
545
        for ( i = 0; i < pCube->nLits && Count < 2; i++ )
546 547 548 549 550 551 552
            Count += !Abc_LitIsCompl(pCube->Lits[i]);
        if ( Count == 1 )
        {
            for ( i = 0; i < pCube->nLits; i++ )
                if ( !Abc_LitIsCompl(pCube->Lits[i]) )
                    break;
            assert( i < pCube->nLits );
553 554 555 556
            iLit = pCube->Lits[i];
            for ( ; i > 0; i-- )
                pCube->Lits[i] = pCube->Lits[i-1];
            pCube->Lits[0] = iLit;
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
        }
    }
    // add clauses for the additional AND-gates
    Vec_IntForEachEntry( vLits1, iLit, i )
    {
        sat_solver_add_buffer_enable( pSat, iAndVar + i, Abc_Lit2Var(iLit), iUseVar + i, Abc_LitIsCompl(iLit) );
        Vec_IntWriteEntry( vLits1, i, Abc_Var2Lit(iAndVar + i, 0) );
    }
    // add clauses for the additional OR-gate
    RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits1), Vec_IntLimit(vLits1) );
    assert( RetValue == 1 );
    // add implications
    vLits1 = Pdr_ManCubeToLits( p, k, pCube, 0, 1 );
    assert( Vec_IntSize(vLits1) == nLits );
    Vec_IntForEachEntry( vLits1, iLit, i )
    {
        Lits[0] = Abc_Var2Lit(iUseVar + i, 1);
        Lits[1] = iLit;
        RetValue = sat_solver_addclause( pSat, Lits, Lits+2 );
        assert( RetValue == 1 );
        Vec_IntWriteEntry( vLits1, i, Abc_Var2Lit(iUseVar + i, 0) );
    }
    sat_solver_compress( pSat );
    // perform minimization
    if ( fUseMinAss )
    {
583
        if ( Count == 1 ) // always assume the only positive literal
584
        {
585
            if ( !sat_solver_push(pSat, Vec_IntEntry(vLits1, 0)) ) // UNSAT with the first (mandatory) literal
586 587
                nLits = 1;
            else
588
                nLits = 1 + sat_solver_minimize_assumptions2( pSat, Vec_IntArray(vLits1)+1, nLits-1, p->pPars->nConfLimit );
589 590 591
            sat_solver_pop(pSat); // unassume the first literal
        }
        else
592
            nLits = sat_solver_minimize_assumptions2( pSat, Vec_IntArray(vLits1), nLits, p->pPars->nConfLimit );
593 594 595 596 597
        Vec_IntShrink( vLits1, nLits );
    }
    else
    {
        // try removing one literal at a time in the old-fashioned way
598
        int k, Entry;
599
        Vec_Int_t * vTemp = Vec_IntAlloc( nLits );
600
        for ( i = nLits - 1; i >= 0; i-- )
601
        {
602 603 604 605 606 607 608 609 610
            // if we are about to remove a positive lit, make sure at least one positive lit remains
            if ( !Abc_LitIsCompl(Vec_IntEntry(vLits1, i)) )
            {
                Vec_IntForEachEntry( vLits1, iLit, k )
                    if ( iLit != -1 && k != i && !Abc_LitIsCompl(iLit) )
                        break;
                if ( k == Vec_IntSize(vLits1) ) // no other positive literals, except the i-th one
                    continue;
            }
611 612 613 614 615
            // load remaining literals
            Vec_IntClear( vTemp );
            Vec_IntForEachEntry( vLits1, Entry, k )
                if ( Entry != -1 && k != i )
                    Vec_IntPush( vTemp, Entry );
616 617
                else if ( Entry != -1 ) // assume opposite literal
                    Vec_IntPush( vTemp, Abc_LitNot(Entry) );
618 619
            // solve with assumptions
            RetValue = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), p->pPars->nConfLimit, 0, 0, 0 );
620 621 622 623 624 625 626 627
            // commit the literal
            if ( RetValue == l_False )
            {
                int LitNot = Abc_LitNot(Vec_IntEntry(vLits1, i));
                int RetValue = sat_solver_addclause( pSat, &LitNot, &LitNot+1 );
                assert( RetValue );
            }
            // update the clause
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
            if ( RetValue == l_False )
                Vec_IntWriteEntry( vLits1, i, -1 );
        }
        Vec_IntFree( vTemp );
        // compact
        k = 0;
        Vec_IntForEachEntry( vLits1, Entry, i )
            if ( Entry != -1 )
                Vec_IntWriteEntry( vLits1, k++, Entry );
        Vec_IntShrink( vLits1, k );
    }
    // remap auxiliary literals into original literals
    Vec_IntForEachEntry( vLits1, iLit, i )
        Vec_IntWriteEntry( vLits1, i, pCube->Lits[Abc_Lit2Var(iLit)-iUseVar] );
    // make sure the cube has at least one positive literal
    if ( fUseMinAss )
    {
        Vec_IntForEachEntry( vLits1, iLit, i )
            if ( !Abc_LitIsCompl(iLit) )
                break;
648
        if ( i == Vec_IntSize(vLits1) ) // has no positive literals
649 650 651 652 653 654 655
        {
            // find positive lit in the cube
            for ( i = 0; i < pCube->nLits; i++ )
                if ( !Abc_LitIsCompl(pCube->Lits[i]) )
                    break;
            assert( i < pCube->nLits );
            Vec_IntPush( vLits1, pCube->Lits[i] );
656
//            printf( "-" );
657
        }
658 659
//        else
//            printf( "+" );
660 661 662 663
    }
    // create a subset cube
    *ppCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits1), Vec_IntSize(vLits1) );
    assert( !Pdr_SetIsInit(*ppCubeMin, -1) );
664
    Order = 0;
665
#endif
666
    return 0;
667 668
}

669 670
/**Function*************************************************************

671 672 673 674 675 676 677 678 679 680 681
  Synopsis    [Returns 1 if the state could be blocked.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Pdr_ManGeneralize( Pdr_Man_t * p, int k, Pdr_Set_t * pCube, Pdr_Set_t ** ppPred, Pdr_Set_t ** ppCubeMin )
{
682
    Pdr_Set_t * pCubeMin, * pCubeTmp = NULL, * pPred = NULL, * pCubeCpy = NULL;
683
    int i, j, Lit, RetValue;
684
    abctime clk = Abc_Clock();
685
    int * pOrder;
686 687
    int added = 0;
    Hash_Int_t * keep = NULL;
688 689
    // if there is no induction, return
    *ppCubeMin = NULL;
690
    if ( p->pPars->fFlopOrder )
691
        Vec_IntSelectSortPrioReverseLit( pCube->Lits, pCube->nLits, p->vPrio );
692
    RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit, 0, 1 );
693 694
    if ( p->pPars->fFlopOrder )
        Vec_IntSelectSort( pCube->Lits, pCube->nLits );
695 696 697 698
    if ( RetValue == -1 )
        return -1;
    if ( RetValue == 0 )
    {
699
        p->tGeneral += clock() - clk;
700 701
        return 0;
    }
702

703 704 705 706 707 708
    // reduce clause using assumptions
//    pCubeMin = Pdr_SetDup( pCube );
    pCubeMin = Pdr_ManReduceClause( p, k, pCube );
    if ( pCubeMin == NULL )
        pCubeMin = Pdr_SetDup( pCube );

709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
    // perform simplified generalization
    if ( p->pPars->fSimpleGeneral )
    {
        assert( pCubeMin->nLits > 0 );
        if ( pCubeMin->nLits > 1 )
        {
            RetValue = Pdr_ManGeneralize2( p, k, pCubeMin, ppCubeMin );
            Pdr_SetDeref( pCubeMin );
            assert( ppCubeMin != NULL );
            pCubeMin = *ppCubeMin;
        }
        *ppCubeMin = pCubeMin;
        if ( p->pPars->fVeryVerbose )
        {
            printf("Cube:\n");
            for ( i = 0; i < pCubeMin->nLits; i++)
                printf ("%d ", pCubeMin->Lits[i]);
            printf("\n");
        }
        p->tGeneral += Abc_Clock() - clk;
        return 1;
    }
    
    keep = p->pPars->fSkipDown ? NULL : Hash_IntAlloc( 1 );

734 735
    // perform generalization
    if ( !p->pPars->fSkipGeneral )
736
    {
737 738 739 740 741 742 743 744 745 746
        // assume the unminimized cube
        if ( p->pPars->fSimpleGeneral )
        {
            sat_solver *  pSat = Pdr_ManFetchSolver( p, k );
            Vec_Int_t * vLits1 = Pdr_ManCubeToLits( p, k, pCubeMin, 1, 0 );
            int RetValue1 = sat_solver_addclause( pSat, Vec_IntArray(vLits1), Vec_IntArray(vLits1) + Vec_IntSize(vLits1) );
            assert( RetValue1 == 1 );
            sat_solver_compress( pSat );
        }

747 748 749 750
        // sort literals by their occurences
        pOrder = Pdr_ManSortByPriority( p, pCubeMin );
        // try removing literals
        for ( j = 0; j < pCubeMin->nLits; j++ )
751
        {
752 753 754 755 756
            // use ordering
    //        i = j;
            i = pOrder[j];

            assert( pCubeMin->Lits[i] != -1 );
757 758 759 760 761 762 763
            if ( keep && Hash_IntExists( keep, pCubeMin->Lits[i] ) )
            {
                //printf("Undroppable\n");
                continue;
            }

            // check init state
764 765
            if ( Pdr_SetIsInit(pCubeMin, i) )
                continue;
766

767
            // try removing this literal
768 769
            Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; 
            if ( p->pPars->fSkipDown )
770
                RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit, 1, !p->pPars->fSimpleGeneral );
771
            else
772
                RetValue = Pdr_ManCheckCube( p, k, pCubeMin, &pPred, p->pPars->nConfLimit, 1, !p->pPars->fSimpleGeneral );
773 774 775 776 777 778 779
            if ( RetValue == -1 )
            {
                Pdr_SetDeref( pCubeMin );
                return -1;
            }
            pCubeMin->Lits[i] = Lit;
            if ( RetValue == 0 )
780
            {
781 782
                if ( p->pPars->fSkipDown )
                    continue;
783 784
                pCubeCpy = Pdr_SetCreateFrom( pCubeMin, i );
                RetValue = ZPdr_ManDown( p, k, &pCubeCpy, pPred, keep, pCubeMin, &added );
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
                if ( p->pPars->fCtgs )
                    //CTG handling code messes up with the internal order array
                    pOrder = Pdr_ManSortByPriority( p, pCubeMin );
                if ( RetValue == -1 )
                {
                    Pdr_SetDeref( pCubeMin );
                    Pdr_SetDeref( pCubeCpy );
                    Pdr_SetDeref( pPred );
                    return -1;
                }
                if ( RetValue == 0 )
                {
                    if ( keep ) 
                        Hash_IntWriteEntry( keep, pCubeMin->Lits[i], 0 );
                    if ( pCubeCpy )
                        Pdr_SetDeref( pCubeCpy );
                    continue;
                }
                //Inductive subclause
                added = 0;
                Pdr_SetDeref( pCubeMin );
                pCubeMin = pCubeCpy;
                assert( pCubeMin->nLits > 0 );
808
                pOrder = Pdr_ManSortByPriority( p, pCubeMin );
809
                j = -1;
810
                continue;
811 812
            }
            added = 0;
813 814 815 816 817 818

            // success - update the cube
            pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
            Pdr_SetDeref( pCubeTmp );
            assert( pCubeMin->nLits > 0 );

819 820 821 822 823 824 825 826 827 828
            // assume the minimized cube
            if ( p->pPars->fSimpleGeneral )
            {
                sat_solver *  pSat = Pdr_ManFetchSolver( p, k );
                Vec_Int_t * vLits1 = Pdr_ManCubeToLits( p, k, pCubeMin, 1, 0 );
                int RetValue1 = sat_solver_addclause( pSat, Vec_IntArray(vLits1), Vec_IntArray(vLits1) + Vec_IntSize(vLits1) );
                assert( RetValue1 == 1 );
                sat_solver_compress( pSat );
            }

829
            // get the ordering by decreasing priority
830
            pOrder = Pdr_ManSortByPriority( p, pCubeMin );
831
            j--;
832 833
        }

834 835
        if ( p->pPars->fTwoRounds )
        for ( j = 0; j < pCubeMin->nLits; j++ )
836
        {
837 838 839 840 841 842 843 844 845
            // use ordering
    //        i = j;
            i = pOrder[j];

            // check init state
            assert( pCubeMin->Lits[i] != -1 );
            if ( Pdr_SetIsInit(pCubeMin, i) )
                continue;
            // try removing this literal
846
            Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; 
847
            RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit, 0, 1 );
848 849 850 851 852 853 854 855 856 857 858 859 860 861
            if ( RetValue == -1 )
            {
                Pdr_SetDeref( pCubeMin );
                return -1;
            }
            pCubeMin->Lits[i] = Lit;
            if ( RetValue == 0 )
                continue;

            // success - update the cube
            pCubeMin = Pdr_SetCreateFrom( pCubeTmp = pCubeMin, i );
            Pdr_SetDeref( pCubeTmp );
            assert( pCubeMin->nLits > 0 );

862
            // get the ordering by decreasing priority
863
            pOrder = Pdr_ManSortByPriority( p, pCubeMin );
864
            j--;
865 866 867 868
        }
    }

    assert( ppCubeMin != NULL );
869 870 871 872
    if ( p->pPars->fVeryVerbose )
    {
        printf("Cube:\n");
        for ( i = 0; i < pCubeMin->nLits; i++)
873
            printf ("%d ", pCubeMin->Lits[i]);
874 875
        printf("\n");
    }
876
    *ppCubeMin = pCubeMin;
877
    p->tGeneral += Abc_Clock() - clk;
878
    if ( keep ) Hash_IntFree( keep );
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
    return 1;
}

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

  Synopsis    [Returns 1 if the state could be blocked.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Pdr_ManBlockCube( Pdr_Man_t * p, Pdr_Set_t * pCube )
{
    Pdr_Obl_t * pThis;
    Pdr_Set_t * pPred, * pCubeMin;
    int i, k, RetValue, Prio = ABC_INFINITY, Counter = 0;
898
    int kMax = Vec_PtrSize(p->vSolvers)-1;
899
    abctime clk;
900 901
    p->nBlocks++;
    // create first proof obligation
902
//    assert( p->pQueue == NULL );
903 904 905 906 907 908 909
    pThis = Pdr_OblStart( kMax, Prio--, pCube, NULL ); // consume ref
    Pdr_QueuePush( p, pThis );
    // try to solve it recursively
    while ( !Pdr_QueueIsEmpty(p) )
    {
        Counter++;
        pThis = Pdr_QueueHead( p );
910
        if ( pThis->iFrame == 0 || (p->pPars->fUseAbs && Pdr_SetIsInit(pThis->pState, -1)) )
911
            return 0; // SAT
912 913
        if ( pThis->iFrame > kMax ) // finished this level
            return 1;
Alan Mishchenko committed
914 915
        if ( p->nQueLim && p->nQueCur >= p->nQueLim )
        {
Alan Mishchenko committed
916
            p->nQueLim = p->nQueLim * 3 / 2;
Alan Mishchenko committed
917 918 919
            Pdr_QueueStop( p );
            return 1; // restart
        }
920 921 922
        pThis = Pdr_QueuePop( p );
        assert( pThis->iFrame > 0 );
        assert( !Pdr_SetIsInit(pThis->pState, -1) );
923
        p->iUseFrame = Abc_MinInt( p->iUseFrame, pThis->iFrame );
924
        clk = Abc_Clock();
925 926
        if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) )
        {
927
            p->tContain += Abc_Clock() - clk;
928 929 930
            Pdr_OblDeref( pThis );
            continue;
        }
931
        p->tContain += Abc_Clock() - clk;
932 933

        // check if the cube is already contained
934
        RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState );
935
        if ( RetValue == -1 ) // resource limit is reached
936 937 938 939 940
        {
            Pdr_OblDeref( pThis );
            return -1;
        }
        if ( RetValue ) // cube is blocked by clauses in this frame
941 942 943 944 945 946 947 948
        {
            Pdr_OblDeref( pThis );
            continue;
        }

        // check if the cube holds with relative induction
        pCubeMin = NULL;
        RetValue = Pdr_ManGeneralize( p, pThis->iFrame-1, pThis->pState, &pPred, &pCubeMin );
949
        if ( RetValue == -1 ) // resource limit is reached
950 951 952 953 954 955 956 957 958 959 960 961
        {
            Pdr_OblDeref( pThis );
            return -1;
        }
        if ( RetValue ) // cube is blocked inductively in this frame
        {
            assert( pCubeMin != NULL );
            // k is the last frame where pCubeMin holds
            k = pThis->iFrame;
            // check other frames
            assert( pPred == NULL );
            for ( k = pThis->iFrame; k < kMax; k++ )
962
            {
963
                RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0, 0, 1 );
964 965 966 967 968 969
                if ( RetValue == -1 )
                {
                    Pdr_OblDeref( pThis );
                    return -1;
                }
                if ( !RetValue )
970
                    break;
971
            }
972 973 974
            // add new clause
            if ( p->pPars->fVeryVerbose )
            {
Alan Mishchenko committed
975 976 977
                Abc_Print( 1, "Adding cube " );
                Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
                Abc_Print( 1, " to frame %d.\n", k );
978 979 980 981 982 983
            }
            // set priority flops
            for ( i = 0; i < pCubeMin->nLits; i++ )
            {
                assert( pCubeMin->Lits[i] >= 0 );
                assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
984 985
                if ( (Vec_IntEntry(p->vPrio, pCubeMin->Lits[i] / 2) >> p->nPrioShift) == 0 )
                    p->nAbsFlops++;
986
                Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 << p->nPrioShift );
987 988 989 990 991 992 993
            }
            Vec_VecPush( p->vClauses, k, pCubeMin );   // consume ref
            p->nCubes++;
            // add clause
            for ( i = 1; i <= k; i++ )
                Pdr_ManSolverAddClause( p, i, pCubeMin );
            // schedule proof obligation
994
            if ( (k < kMax || p->pPars->fReuseProofOblig) && !p->pPars->fShortest )
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
            {
                pThis->iFrame = k+1;
                pThis->prio   = Prio--;
                Pdr_QueuePush( p, pThis );
            }
            else
            {
                Pdr_OblDeref( pThis );
            }
        }
        else
        {
            assert( pCubeMin == NULL );
            assert( pPred != NULL );
            pThis->prio = Prio--;
            Pdr_QueuePush( p, pThis );
            pThis = Pdr_OblStart( pThis->iFrame-1, Prio--, pPred, Pdr_OblRef(pThis) );
            Pdr_QueuePush( p, pThis );
        }

1015 1016 1017
        // check termination
        if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) )
            return -1;
1018
        if ( p->timeToStop && Abc_Clock() > p->timeToStop )
1019
            return -1;
1020
        if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne )
1021
            return -1;
1022
        if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
1023
            return -1;
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
    }
    return 1;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Pdr_ManSolveInt( Pdr_Man_t * p )
{
    int fPrintClauses = 0;
1042
    Pdr_Set_t * pCube = NULL;
1043
    Aig_Obj_t * pObj;
1044
    Abc_Cex_t * pCexNew;
1045
    int iFrame, RetValue = -1;
1046
    int nOutDigits = Abc_Base10Log( Saig_ManPoNum(p->pAig) );
1047 1048
    abctime clkStart = Abc_Clock(), clkOne = 0;
    p->timeToStop = p->pPars->nTimeOut ? p->pPars->nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0;
1049
    assert( Vec_PtrSize(p->vSolvers) == 0 );
1050 1051
    // in the multi-output mode, mark trivial POs (those fed by const0) as solved 
    if ( p->pPars->fSolveAll )
1052
        Saig_ManForEachPo( p->pAig, pObj, iFrame )
1053 1054
            if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p->pAig) )
            {
1055
                Vec_IntWriteEntry( p->pPars->vOutMap, iFrame, 1 ); // unsat
1056 1057
                p->pPars->nProveOuts++;
                if ( p->pPars->fUseBridge )
1058
                    Gia_ManToBridgeResult( stdout, 1, NULL, iFrame );
1059
            }
1060
    // create the first timeframe
1061
    p->pPars->timeLastSolved = Abc_Clock();
1062
    Pdr_ManCreateSolver( p, (iFrame = 0) );
1063 1064
    while ( 1 )
    {
1065
        int fRefined = 0;
1066
        if ( p->pPars->fUseAbs && p->vAbsFlops == NULL && iFrame == 1 )
1067
        {
1068
//            int i, Prio;
1069 1070 1071 1072
            assert( p->vAbsFlops == NULL );
            p->vAbsFlops  = Vec_IntStart( Saig_ManRegNum(p->pAig) );
            p->vMapFf2Ppi = Vec_IntStartFull( Saig_ManRegNum(p->pAig) );
            p->vMapPpi2Ff = Vec_IntAlloc( 100 );
1073 1074 1075
//            Vec_IntForEachEntry( p->vPrio, Prio, i )
//                if ( Prio >> p->nPrioShift  )
//                    Vec_IntWriteEntry( p->vAbsFlops, i, 1 );
1076
        }
1077
        //if ( p->pPars->fUseAbs && p->vAbsFlops )
1078
        //    printf( "Starting frame %d with %d (%d) flops.\n", iFrame, Vec_IntCountPositive(p->vAbsFlops), Vec_IntCountPositive(p->vPrio) );
1079 1080 1081
        p->nFrames = iFrame;
        assert( iFrame == Vec_PtrSize(p->vSolvers)-1 );
        p->iUseFrame = Abc_MaxInt(iFrame, 1);
1082
        Saig_ManForEachPo( p->pAig, pObj, p->iOutCur )
1083
        {
1084
            // skip disproved outputs
1085 1086
            if ( p->vCexes && Vec_PtrEntry(p->vCexes, p->iOutCur) )
                continue;
1087 1088 1089
            // skip output whose time has run out
            if ( p->pTime4Outs && p->pTime4Outs[p->iOutCur] == 0 )
                continue;
1090 1091 1092 1093 1094
            // check if the output is trivially solved
            if ( Aig_ObjChild0(pObj) == Aig_ManConst0(p->pAig) )
                continue;
            // check if the output is trivially solved
            if ( Aig_ObjChild0(pObj) == Aig_ManConst1(p->pAig) )
1095
            {
1096 1097
                if ( !p->pPars->fSolveAll )
                {
1098
                    pCexNew = Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), iFrame*Saig_ManPoNum(p->pAig)+p->iOutCur );
1099
                    p->pAig->pSeqModel = pCexNew;
1100 1101
                    return 0; // SAT
                }
1102
                pCexNew = (p->pPars->fUseBridge || p->pPars->fStoreCex) ? Abc_CexMakeTriv( Aig_ManRegNum(p->pAig), Saig_ManPiNum(p->pAig), Saig_ManPoNum(p->pAig), iFrame*Saig_ManPoNum(p->pAig)+p->iOutCur ) : (Abc_Cex_t *)(ABC_PTRINT_T)1;
1103
                p->pPars->nFailOuts++;
1104
                if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, 0 );
1105
                if ( !p->pPars->fNotVerbose )
1106
                Abc_Print( 1, "Output %*d was trivially asserted in frame %2d (solved %*d out of %*d outputs).\n",
1107
                    nOutDigits, p->iOutCur, iFrame, nOutDigits, p->pPars->nFailOuts, nOutDigits, Saig_ManPoNum(p->pAig) );
1108
                assert( Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL );
1109 1110 1111
                if ( p->pPars->fUseBridge )
                    Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo );
                Vec_PtrWriteEntry( p->vCexes, p->iOutCur, pCexNew );
1112 1113
                if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(p->iOutCur, p->pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, p->iOutCur) : NULL) )
                {
1114
                    if ( p->pPars->fVerbose )
1115
                        Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1116
                    if ( !p->pPars->fSilent )
1117 1118
                        Abc_Print( 1, "Quitting due to callback on fail in frame %d.\n", iFrame );
                    p->pPars->iFrame = iFrame;
1119 1120
                    return -1;
                }
1121 1122
                if ( p->pPars->nFailOuts + p->pPars->nDropOuts == Saig_ManPoNum(p->pAig) )
                    return p->pPars->nFailOuts ? 0 : -1; // SAT or UNDEC
1123
                p->pPars->timeLastSolved = Abc_Clock();
1124
                continue;
1125
            }
1126
            // try to solve this output
1127 1128 1129
            if ( p->pTime4Outs )
            {
                assert( p->pTime4Outs[p->iOutCur] > 0 );
1130 1131
                clkOne = Abc_Clock();
                p->timeToStopOne = p->pTime4Outs[p->iOutCur] + Abc_Clock();
1132
            }
1133
            while ( 1 )
1134
            {
1135
                if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
1136
                {
1137
                    if ( p->pPars->fVerbose )
1138
                        Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1139
                    if ( !p->pPars->fSilent )
1140 1141
                        Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOutGap, iFrame );
                    p->pPars->iFrame = iFrame;
1142
                    return -1;
1143
                }
1144
                RetValue = Pdr_ManCheckCube( p, iFrame, NULL, &pCube, p->pPars->nConfLimit, 0, 1 );
1145 1146 1147
                if ( RetValue == 1 )
                    break;
                if ( RetValue == -1 )
1148
                {
1149
                    if ( p->pPars->fVerbose )
1150
                        Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1151
                    if ( p->timeToStop && Abc_Clock() > p->timeToStop )
1152
                        Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOut, iFrame );
1153
                    else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
1154
                        Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOutGap, iFrame );
1155 1156 1157 1158 1159 1160 1161
                    else if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne )
                    {
                        Pdr_QueueClean( p );
                        pCube = NULL;
                        break; // keep solving
                    }
                    else if ( p->pPars->nConfLimit )
1162
                        Abc_Print( 1, "Reached conflict limit (%d) in frame %d.\n",  p->pPars->nConfLimit, iFrame );
1163
                    else if ( p->pPars->fVerbose )
1164 1165
                        Abc_Print( 1, "Computation cancelled by the callback in frame %d.\n", iFrame );
                    p->pPars->iFrame = iFrame;
1166
                    return -1;
1167
                }
1168 1169 1170 1171 1172
                if ( RetValue == 0 )
                {
                    RetValue = Pdr_ManBlockCube( p, pCube );
                    if ( RetValue == -1 )
                    {
1173
                        if ( p->pPars->fVerbose )
1174
                            Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1175
                        if ( p->timeToStop && Abc_Clock() > p->timeToStop )
1176
                            Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOut, iFrame );
1177
                        else if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
1178
                            Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOutGap, iFrame );
1179
                        else if ( p->timeToStopOne && Abc_Clock() > p->timeToStopOne )
1180 1181 1182 1183 1184
                        {
                            Pdr_QueueClean( p );
                            pCube = NULL;
                            break; // keep solving
                        }
1185
                        else if ( p->pPars->nConfLimit )
1186
                            Abc_Print( 1, "Reached conflict limit (%d) in frame %d.\n",  p->pPars->nConfLimit, iFrame );
1187
                        else if ( p->pPars->fVerbose )
1188 1189
                            Abc_Print( 1, "Computation cancelled by the callback in frame %d.\n", iFrame );
                        p->pPars->iFrame = iFrame;
1190
                        return -1;
1191 1192 1193 1194 1195
                    }
                    if ( RetValue == 0 )
                    {
                        if ( fPrintClauses )
                        {
1196
                            Abc_Print( 1, "*** Clauses after frame %d:\n", iFrame );
1197 1198
                            Pdr_ManPrintClauses( p, 0 );
                        }
1199
                        if ( p->pPars->fVerbose && !p->pPars->fUseAbs )
1200
                            Pdr_ManPrintProgress( p, !p->pPars->fSolveAll, Abc_Clock() - clkStart );
1201
                        p->pPars->iFrame = iFrame;
1202 1203
                        if ( !p->pPars->fSolveAll )
                        {
1204
                            abctime clk = Abc_Clock();
1205
                            Abc_Cex_t * pCex = Pdr_ManDeriveCexAbs(p);
1206
                            p->tAbs += Abc_Clock() - clk;
1207 1208 1209 1210 1211
                            if ( pCex == NULL )
                            {
                                assert( p->pPars->fUseAbs );
                                Pdr_QueueClean( p );
                                pCube = NULL;
1212
                                fRefined = 1;
1213 1214 1215
                                break; // keep solving
                            }
                            p->pAig->pSeqModel = pCex;
1216 1217 1218
                            return 0; // SAT
                        }
                        p->pPars->nFailOuts++;
1219
                        pCexNew = (p->pPars->fUseBridge || p->pPars->fStoreCex) ? Pdr_ManDeriveCex(p) : (Abc_Cex_t *)(ABC_PTRINT_T)1;
1220
                        if ( p->pPars->vOutMap ) Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, 0 );
1221
                        assert( Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL );
1222 1223 1224
                        if ( p->pPars->fUseBridge )
                            Gia_ManToBridgeResult( stdout, 0, pCexNew, pCexNew->iPo );
                        Vec_PtrWriteEntry( p->vCexes, p->iOutCur, pCexNew );
1225 1226
                        if ( p->pPars->pFuncOnFail && p->pPars->pFuncOnFail(p->iOutCur, p->pPars->fStoreCex ? (Abc_Cex_t *)Vec_PtrEntry(p->vCexes, p->iOutCur) : NULL) )
                        {
1227
                            if ( p->pPars->fVerbose )
1228
                                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1229
                            if ( !p->pPars->fSilent )
1230 1231
                                Abc_Print( 1, "Quitting due to callback on fail in frame %d.\n", iFrame );
                            p->pPars->iFrame = iFrame;
1232 1233
                            return -1;
                        }
1234
                        if ( !p->pPars->fNotVerbose )
1235
                            Abc_Print( 1, "Output %*d was asserted in frame %2d (%2d) (solved %*d out of %*d outputs).\n",
1236
                                nOutDigits, p->iOutCur, iFrame, iFrame, nOutDigits, p->pPars->nFailOuts, nOutDigits, Saig_ManPoNum(p->pAig) );
1237 1238
                        if ( p->pPars->nFailOuts == Saig_ManPoNum(p->pAig) )
                            return 0; // all SAT
1239 1240 1241
                        Pdr_QueueClean( p );
                        pCube = NULL;
                        break; // keep solving
1242
                    }
1243
                    if ( p->pPars->fVerbose )
1244
                        Pdr_ManPrintProgress( p, 0, Abc_Clock() - clkStart );
1245
                }
1246
            }
1247 1248
            if ( fRefined )
                break;
1249 1250
            if ( p->pTime4Outs )
            {
1251
                abctime timeSince = Abc_Clock() - clkOne;
1252 1253
                assert( p->pTime4Outs[p->iOutCur] > 0 );
                p->pTime4Outs[p->iOutCur] = (p->pTime4Outs[p->iOutCur] > timeSince) ? p->pTime4Outs[p->iOutCur] - timeSince : 0;
1254
                if ( p->pTime4Outs[p->iOutCur] == 0 && Vec_PtrEntry(p->vCexes, p->iOutCur) == NULL ) // undecided
1255 1256
                {
                    p->pPars->nDropOuts++;
1257 1258
                    if ( p->pPars->vOutMap ) 
                        Vec_IntWriteEntry( p->pPars->vOutMap, p->iOutCur, -1 );
1259
                    if ( !p->pPars->fNotVerbose ) 
1260
                        Abc_Print( 1, "Timing out on output %*d in frame %d.\n", nOutDigits, p->iOutCur, iFrame );
1261
                }
1262
                p->timeToStopOne = 0;
1263
            }
1264
        }
1265 1266 1267 1268 1269 1270 1271
        if ( p->pPars->fUseAbs && p->vAbsFlops && !fRefined )
        {
            int i, Used;
            Vec_IntForEachEntry( p->vAbsFlops, Used, i )
                if ( Used && (Vec_IntEntry(p->vPrio, i) >> p->nPrioShift) == 0 )
                    Vec_IntWriteEntry( p->vAbsFlops, i, 0 );
        }
1272
        if ( p->pPars->fVerbose )
1273
            Pdr_ManPrintProgress( p, !fRefined, Abc_Clock() - clkStart );
1274 1275
        if ( fRefined )
            continue;
1276 1277
        //if ( p->pPars->fUseAbs && p->vAbsFlops )
        //    printf( "Finished frame %d with %d (%d) flops.\n", iFrame, Vec_IntCountPositive(p->vAbsFlops), Vec_IntCountPositive(p->vPrio) );
1278 1279 1280
        // open a new timeframe
        p->nQueLim = p->pPars->nRestLimit;
        assert( pCube == NULL );
1281 1282
        Pdr_ManSetPropertyOutput( p, iFrame );
        Pdr_ManCreateSolver( p, ++iFrame );
1283 1284
        if ( fPrintClauses )
        {
1285
            Abc_Print( 1, "*** Clauses after frame %d:\n", iFrame );
1286 1287 1288 1289 1290
            Pdr_ManPrintClauses( p, 0 );
        }
        // push clauses into this timeframe
        RetValue = Pdr_ManPushClauses( p );
        if ( RetValue == -1 )
1291
        {
1292
            if ( p->pPars->fVerbose )
1293
                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1294
            if ( !p->pPars->fSilent )
1295
            {
1296
                if ( p->timeToStop && Abc_Clock() > p->timeToStop )
1297
                    Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOut, iFrame );
1298
                else
1299
                    Abc_Print( 1, "Reached conflict limit (%d) in frame.\n",  p->pPars->nConfLimit, iFrame );
1300
            }
1301
            p->pPars->iFrame = iFrame;
1302
            return -1;
1303 1304 1305
        }
        if ( RetValue )
        {
1306
            if ( p->pPars->fVerbose )
1307
                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1308 1309 1310 1311
            if ( !p->pPars->fSilent )
                Pdr_ManReportInvariant( p );
            if ( !p->pPars->fSilent )
                Pdr_ManVerifyInvariant( p );
1312
            p->pPars->iFrame = iFrame;
1313 1314 1315
            // count the number of UNSAT outputs
            p->pPars->nProveOuts = Saig_ManPoNum(p->pAig) - p->pPars->nFailOuts - p->pPars->nDropOuts;
            // convert previously 'unknown' into 'unsat'
1316
            if ( p->pPars->vOutMap )
1317 1318
                for ( iFrame = 0; iFrame < Saig_ManPoNum(p->pAig); iFrame++ )
                    if ( Vec_IntEntry(p->pPars->vOutMap, iFrame) == -2 ) // unknown
1319
                    {
1320
                        Vec_IntWriteEntry( p->pPars->vOutMap, iFrame, 1 ); // unsat
1321
                        if ( p->pPars->fUseBridge )
1322
                            Gia_ManToBridgeResult( stdout, 1, NULL, iFrame );
1323
                    }
1324 1325 1326 1327
            if ( p->pPars->nProveOuts == Saig_ManPoNum(p->pAig) )
                return 1; // UNSAT
            if ( p->pPars->nFailOuts > 0 )
                return 0; // SAT
1328
            return -1;
1329
        }
1330
        if ( p->pPars->fVerbose )
1331
            Pdr_ManPrintProgress( p, 0, Abc_Clock() - clkStart );
1332

1333 1334 1335
        // check termination
        if ( p->pPars->pFuncStop && p->pPars->pFuncStop(p->pPars->RunId) )
        {
1336
            p->pPars->iFrame = iFrame;
1337
            return -1;
1338
        }
1339
        if ( p->timeToStop && Abc_Clock() > p->timeToStop )
1340 1341 1342
        {
            if ( fPrintClauses )
            {
1343
                Abc_Print( 1, "*** Clauses after frame %d:\n", iFrame );
1344 1345
                Pdr_ManPrintClauses( p, 0 );
            }
1346
            if ( p->pPars->fVerbose )
1347
                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1348
            if ( !p->pPars->fSilent )
1349 1350
                Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOut, iFrame );
            p->pPars->iFrame = iFrame;
1351
            return -1;
1352
        }
1353
        if ( p->pPars->nTimeOutGap && p->pPars->timeLastSolved && Abc_Clock() > p->pPars->timeLastSolved + p->pPars->nTimeOutGap * CLOCKS_PER_SEC )
1354 1355 1356
        {
            if ( fPrintClauses )
            {
1357
                Abc_Print( 1, "*** Clauses after frame %d:\n", iFrame );
1358 1359
                Pdr_ManPrintClauses( p, 0 );
            }
1360
            if ( p->pPars->fVerbose )
1361
                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1362
            if ( !p->pPars->fSilent )
1363 1364
                Abc_Print( 1, "Reached gap timeout (%d seconds) in frame %d.\n",  p->pPars->nTimeOutGap, iFrame );
            p->pPars->iFrame = iFrame;
1365
            return -1;
1366
        }
1367
        if ( p->pPars->nFrameMax && iFrame >= p->pPars->nFrameMax )
1368
        {
1369
            if ( p->pPars->fVerbose )
1370
                Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
1371 1372
            if ( !p->pPars->fSilent )
                Abc_Print( 1, "Reached limit on the number of timeframes (%d).\n", p->pPars->nFrameMax );
1373
            p->pPars->iFrame = iFrame;
1374
            return -1;
1375
        }
1376
    }
1377 1378
    assert( 0 );
    return -1;
1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1392
int Pdr_ManSolve( Aig_Man_t * pAig, Pdr_Par_t * pPars )
1393 1394
{
    Pdr_Man_t * p;
1395
    int k, RetValue;
1396
    abctime clk = Abc_Clock();
1397 1398
    if ( pPars->nTimeOutOne && !pPars->fSolveAll )
        pPars->nTimeOutOne = 0;
1399
    if ( pPars->nTimeOutOne && pPars->nTimeOut == 0 )
1400
        pPars->nTimeOut = pPars->nTimeOutOne * Saig_ManPoNum(pAig) / 1000 + (int)((pPars->nTimeOutOne * Saig_ManPoNum(pAig) % 1000) > 0);
1401 1402 1403
    if ( pPars->fVerbose )
    {
//    Abc_Print( 1, "Running PDR by Niklas Een (aka IC3 by Aaron Bradley) with these parameters:\n" );
1404 1405 1406 1407
        Abc_Print( 1, "VarMax = %d. FrameMax = %d. QueMax = %d. TimeMax = %d. ",
            pPars->nRecycle,
            pPars->nFrameMax,
            pPars->nRestLimit,
1408
            pPars->nTimeOut );
1409 1410 1411
        Abc_Print( 1, "MonoCNF = %s. SkipGen = %s. SolveAll = %s.\n",
            pPars->fMonoCnf ?     "yes" : "no",
            pPars->fSkipGeneral ? "yes" : "no",
1412
            pPars->fSolveAll ?    "yes" : "no" );
1413 1414 1415
    }
    ABC_FREE( pAig->pSeqModel );
    p = Pdr_ManStart( pAig, pPars, NULL );
1416
    RetValue = Pdr_ManSolveInt( p );
1417 1418 1419 1420 1421 1422 1423 1424
    if ( RetValue == 0 )
        assert( pAig->pSeqModel != NULL || p->vCexes != NULL );
    if ( p->vCexes )
    {
        assert( p->pAig->vSeqModelVec == NULL );
        p->pAig->vSeqModelVec = p->vCexes;
        p->vCexes = NULL;
    }
1425
    if ( p->pPars->fDumpInv )
1426
    {
1427
        char * pFileName = Extra_FileNameGenericAppend(p->pAig->pName, "_inv.pla");
1428
        Abc_FrameSetInv( Pdr_ManDeriveInfinityClauses( p, RetValue!=1 ) );
1429
        Pdr_ManDumpClauses( p, pFileName, RetValue==1 );
1430
    }
1431 1432
    else if ( RetValue == 1 )
        Abc_FrameSetInv( Pdr_ManDeriveInfinityClauses( p, RetValue!=1 ) );
1433
    p->tTotal += Abc_Clock() - clk;
1434
    Pdr_ManStop( p );
1435
    pPars->iFrame--;
1436 1437 1438 1439 1440
    // convert all -2 (unknown) entries into -1 (undec)
    if ( pPars->vOutMap )
        for ( k = 0; k < Saig_ManPoNum(pAig); k++ )
            if ( Vec_IntEntry(pPars->vOutMap, k) == -2 ) // unknown
                Vec_IntWriteEntry( pPars->vOutMap, k, -1 ); // undec
Alan Mishchenko committed
1441 1442
    if ( pPars->fUseBridge )
        Gia_ManToBridgeAbort( stdout, 7, (unsigned char *)"timeout" );
1443 1444 1445 1446 1447 1448 1449 1450 1451
    return RetValue;
}

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


ABC_NAMESPACE_IMPL_END