pdrCore.c 55.3 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
    pPars->pInvFileName   =    NULL;  // invariant file name
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
}

/**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 )
111
        if ( Abc_LitIsCompl(Entry) == 0 ) // positive literal
112 113 114 115 116
            break;
    if ( i == Vec_IntSize(vLits) ) // only negative literals
    {
        // add the first positive literal
        for ( i = 0; i < pCube->nLits; i++ )
117
            if ( Abc_LitIsCompl(pCube->Lits[i]) == 0 ) // positive literal
118 119 120 121 122 123 124 125 126 127 128 129 130
            {
                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;
131
    RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0, 0, 1 );
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
    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;
153
    int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1;
154
    int iStartFrame = p->pPars->fShiftStart ? p->iUseFrame : 1;
155
    int Counter = 0;
156
    abctime clk = Abc_Clock();
157
    assert( p->iUseFrame > 0 );
158
    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, iStartFrame, kMax )
159
    {
160
        Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare );
161
        vArrayK1 = Vec_VecEntry( p->vClauses, k+1 );
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
        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
178
            RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, NULL, 0, 0, 1 );
179 180 181
            if ( RetValue2 == -1 )
                return -1;
            if ( !RetValue2 )
182 183 184 185 186 187 188
                continue;

            {
                Pdr_Set_t * pCubeMin;
                pCubeMin = Pdr_ManReduceClause( p, k, pCubeK );
                if ( pCubeMin != NULL )
                {
189
//                Abc_Print( 1, "%d ", pCubeK->nLits - pCubeMin->nLits );
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 217
                    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
218
    vArrayK = Vec_VecEntry( p->vClauses, kMax );
219
    Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare );
220 221 222 223 224 225 226 227
    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;
/*
228
            Abc_Print( 1, "===\n" );
229
            Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL );
230
            Abc_Print( 1, "\n" );
231
            Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL );
232
            Abc_Print( 1, "\n" );
233 234 235 236 237 238 239
*/
            Pdr_SetDeref( pTemp );
            Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
            Vec_PtrPop(vArrayK);
            m--;
        }
    }
240
    p->tPush += Abc_Clock() - clk;
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
    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;
260
    Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, i, k, kMax+1 )
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 291
        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] )
292
            if ( pPrios[pCube->Lits[pArray[j]]>>1] < pPrios[pCube->Lits[pArray[best_i]]>>1] ) // list lower priority first (these will be removed first)
293
                best_i = j;
294 295
        temp = pArray[i];
        pArray[i] = pArray[best_i];
296 297 298 299
        pArray[best_i] = temp;
    }
/*
    for ( i = 0; i < pCube->nLits; i++ )
300 301
        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" );
302 303 304 305 306 307 308
*/
    return pArray;
}


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

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int ZPdr_ManSimpleMic( Pdr_Man_t * p, int k, Pdr_Set_t ** ppCube )
{
    int * pOrder;
321
    int i, j, Lit, RetValue;
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
    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; 
342
        RetValue = Pdr_ManCheckCube( p, k, *ppCube, NULL, p->pPars->nConfLimit, 0, 1 );
343 344 345 346 347 348 349 350 351 352 353
        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 );

354
        // get the ordering by decreasing priority
355
        pOrder = Pdr_ManSortByPriority( p, *ppCube );
356
        j--;
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 383
    }
    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 )
        {
384
            pCtg = Pdr_SetDup( pPred );
385 386 387 388 389 390 391 392 393 394 395 396 397
            //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++;
398
            CtgRetValue = Pdr_ManCheckCube( p, k-1, pCtg, NULL, p->pPars->nConfLimit, 0, 1 );
399 400 401 402 403 404 405 406 407 408
            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++ )
409
                if ( !Pdr_ManCheckCube( p, l, pCubeMin, NULL, 0, 0, 1 ) )
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
                    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) );
426 427
                if ( (Vec_IntEntry(p->vPrio, pCubeMin->Lits[i] / 2) >> p->nPrioShift) == 0 )
                    p->nAbsFlops++;
428
                Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 << p->nPrioShift );
429 430 431 432 433 434 435
            }

            Vec_VecPush( p->vClauses, l, pCubeMin );   // consume ref
            p->nCubes++;
            // add clause
            for ( i = 1; i <= l; i++ )
                Pdr_ManSolverAddClause( p, i, pCubeMin );
436 437
            Pdr_SetDeref( pPred );
            RetValue = Pdr_ManCheckCube( p, k, *ppCube, &pPred, p->pPars->nConfLimit, 0, 1 );
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
            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 )
        {
462 463
            printf("Intersection:\n");
            ZPdr_SetPrint( *ppCube );
464 465 466
        }
        if ( Pdr_SetIsInit( *ppCube, -1 ) )
        {
467 468 469
            if ( p->pPars->fVeryVerbose )
                printf ("Failed initiation\n");
            return 0;
470
        }
471
        RetValue = Pdr_ManCheckCube( p, k, *ppCube, &pPred, p->pPars->nConfLimit, 0, 1 );
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
        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;
}
489 490 491

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

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

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
501
static inline int Vec_IntSelectSortPrioReverseLit( int * pArray, int nSize, Vec_Int_t * vPrios )
502 503 504 505 506 507
{
    int i, j, best_i;
    for ( i = 0; i < nSize-1; i++ )
    {
        best_i = i;
        for ( j = i+1; j < nSize; j++ )
508
            if ( Vec_IntEntry(vPrios, Abc_Lit2Var(pArray[j])) > Vec_IntEntry(vPrios, Abc_Lit2Var(pArray[best_i])) ) // prefer higher priority
509 510 511
                best_i = j;
        ABC_SWAP( int, pArray[i], pArray[best_i] );
    }
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
    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 )
{
528
#if 0
529 530
    int fUseMinAss = 0;
    sat_solver * pSat = Pdr_ManFetchSolver( p, k );
531
    int Order = Vec_IntSelectSortPrioReverseLit( pCube->Lits, pCube->nLits, p->vPrio );
532 533 534 535 536 537 538 539 540 541 542 543 544 545
    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 )
    {
546
        for ( i = 0; i < pCube->nLits && Count < 2; i++ )
547 548 549 550 551 552 553
            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 );
554 555 556 557
            iLit = pCube->Lits[i];
            for ( ; i > 0; i-- )
                pCube->Lits[i] = pCube->Lits[i-1];
            pCube->Lits[0] = iLit;
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 583
        }
    }
    // 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 )
    {
584
        if ( Count == 1 ) // always assume the only positive literal
585
        {
586
            if ( !sat_solver_push(pSat, Vec_IntEntry(vLits1, 0)) ) // UNSAT with the first (mandatory) literal
587 588
                nLits = 1;
            else
589
                nLits = 1 + sat_solver_minimize_assumptions2( pSat, Vec_IntArray(vLits1)+1, nLits-1, p->pPars->nConfLimit );
590 591 592
            sat_solver_pop(pSat); // unassume the first literal
        }
        else
593
            nLits = sat_solver_minimize_assumptions2( pSat, Vec_IntArray(vLits1), nLits, p->pPars->nConfLimit );
594 595 596 597 598
        Vec_IntShrink( vLits1, nLits );
    }
    else
    {
        // try removing one literal at a time in the old-fashioned way
599
        int k, Entry;
600
        Vec_Int_t * vTemp = Vec_IntAlloc( nLits );
601
        for ( i = nLits - 1; i >= 0; i-- )
602
        {
603 604 605 606 607 608 609 610 611
            // 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;
            }
612 613 614 615 616
            // load remaining literals
            Vec_IntClear( vTemp );
            Vec_IntForEachEntry( vLits1, Entry, k )
                if ( Entry != -1 && k != i )
                    Vec_IntPush( vTemp, Entry );
617 618
                else if ( Entry != -1 ) // assume opposite literal
                    Vec_IntPush( vTemp, Abc_LitNot(Entry) );
619 620
            // solve with assumptions
            RetValue = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), p->pPars->nConfLimit, 0, 0, 0 );
621 622 623 624 625 626 627 628
            // 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
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
            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;
649
        if ( i == Vec_IntSize(vLits1) ) // has no positive literals
650 651 652 653 654 655 656
        {
            // 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] );
657
//            printf( "-" );
658
        }
659 660
//        else
//            printf( "+" );
661 662 663 664
    }
    // create a subset cube
    *ppCubeMin = Pdr_SetCreateSubset( pCube, Vec_IntArray(vLits1), Vec_IntSize(vLits1) );
    assert( !Pdr_SetIsInit(*ppCubeMin, -1) );
665
    Order = 0;
666
#endif
667
    return 0;
668 669
}

670 671
/**Function*************************************************************

672 673 674 675 676 677 678 679 680 681 682
  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 )
{
683
    Pdr_Set_t * pCubeMin, * pCubeTmp = NULL, * pPred = NULL, * pCubeCpy = NULL;
684
    int i, j, Lit, RetValue;
685
    abctime clk = Abc_Clock();
686
    int * pOrder;
687 688
    int added = 0;
    Hash_Int_t * keep = NULL;
689 690
    // if there is no induction, return
    *ppCubeMin = NULL;
691
    if ( p->pPars->fFlopOrder )
692
        Vec_IntSelectSortPrioReverseLit( pCube->Lits, pCube->nLits, p->vPrio );
693
    RetValue = Pdr_ManCheckCube( p, k, pCube, ppPred, p->pPars->nConfLimit, 0, 1 );
694 695
    if ( p->pPars->fFlopOrder )
        Vec_IntSelectSort( pCube->Lits, pCube->nLits );
696 697 698 699
    if ( RetValue == -1 )
        return -1;
    if ( RetValue == 0 )
    {
700
        p->tGeneral += clock() - clk;
701 702
        return 0;
    }
703

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

710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
    // 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 );

735 736
    // perform generalization
    if ( !p->pPars->fSkipGeneral )
737
    {
738 739 740 741 742 743 744 745 746 747
        // 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 );
        }

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

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

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

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

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

820 821 822 823 824 825 826 827 828 829
            // 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 );
            }

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

835 836
        if ( p->pPars->fTwoRounds )
        for ( j = 0; j < pCubeMin->nLits; j++ )
837
        {
838 839 840 841 842 843 844 845 846
            // 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
847
            Lit = pCubeMin->Lits[i]; pCubeMin->Lits[i] = -1; 
848
            RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, p->pPars->nConfLimit, 0, 1 );
849 850 851 852 853 854 855 856 857 858 859 860 861 862
            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 );

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

    assert( ppCubeMin != NULL );
870 871 872 873
    if ( p->pPars->fVeryVerbose )
    {
        printf("Cube:\n");
        for ( i = 0; i < pCubeMin->nLits; i++)
874
            printf ("%d ", pCubeMin->Lits[i]);
875 876
        printf("\n");
    }
877
    *ppCubeMin = pCubeMin;
878
    p->tGeneral += Abc_Clock() - clk;
879
    if ( keep ) Hash_IntFree( keep );
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
    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;
899
    int kMax = Vec_PtrSize(p->vSolvers)-1;
900
    abctime clk;
901 902
    p->nBlocks++;
    // create first proof obligation
903
//    assert( p->pQueue == NULL );
904 905 906 907 908 909 910
    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 );
911
        if ( pThis->iFrame == 0 || (p->pPars->fUseAbs && Pdr_SetIsInit(pThis->pState, -1)) )
912
            return 0; // SAT
913 914
        if ( pThis->iFrame > kMax ) // finished this level
            return 1;
Alan Mishchenko committed
915 916
        if ( p->nQueLim && p->nQueCur >= p->nQueLim )
        {
Alan Mishchenko committed
917
            p->nQueLim = p->nQueLim * 3 / 2;
Alan Mishchenko committed
918 919 920
            Pdr_QueueStop( p );
            return 1; // restart
        }
921 922 923
        pThis = Pdr_QueuePop( p );
        assert( pThis->iFrame > 0 );
        assert( !Pdr_SetIsInit(pThis->pState, -1) );
924
        p->iUseFrame = Abc_MinInt( p->iUseFrame, pThis->iFrame );
925
        clk = Abc_Clock();
926 927
        if ( Pdr_ManCheckContainment( p, pThis->iFrame, pThis->pState ) )
        {
928
            p->tContain += Abc_Clock() - clk;
929 930 931
            Pdr_OblDeref( pThis );
            continue;
        }
932
        p->tContain += Abc_Clock() - clk;
933 934

        // check if the cube is already contained
935
        RetValue = Pdr_ManCheckCubeCs( p, pThis->iFrame, pThis->pState );
936
        if ( RetValue == -1 ) // resource limit is reached
937 938 939 940 941
        {
            Pdr_OblDeref( pThis );
            return -1;
        }
        if ( RetValue ) // cube is blocked by clauses in this frame
942 943 944 945 946 947 948 949
        {
            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 );
950
        if ( RetValue == -1 ) // resource limit is reached
951 952 953 954 955 956 957 958 959 960 961 962
        {
            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++ )
963
            {
964
                RetValue = Pdr_ManCheckCube( p, k, pCubeMin, NULL, 0, 0, 1 );
965 966 967 968 969 970
                if ( RetValue == -1 )
                {
                    Pdr_OblDeref( pThis );
                    return -1;
                }
                if ( !RetValue )
971
                    break;
972
            }
973 974 975
            // add new clause
            if ( p->pPars->fVeryVerbose )
            {
Alan Mishchenko committed
976 977 978
                Abc_Print( 1, "Adding cube " );
                Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
                Abc_Print( 1, " to frame %d.\n", k );
979 980 981 982 983 984
            }
            // set priority flops
            for ( i = 0; i < pCubeMin->nLits; i++ )
            {
                assert( pCubeMin->Lits[i] >= 0 );
                assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
985 986
                if ( (Vec_IntEntry(p->vPrio, pCubeMin->Lits[i] / 2) >> p->nPrioShift) == 0 )
                    p->nAbsFlops++;
987
                Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 << p->nPrioShift );
988 989 990 991 992 993 994
            }
            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
995
            if ( (k < kMax || p->pPars->fReuseProofOblig) && !p->pPars->fShortest )
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
            {
                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 );
        }

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

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

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

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

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

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

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


ABC_NAMESPACE_IMPL_END