giaCSat2.c 59.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/**CFile****************************************************************

  FileName    [giaCSat.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Scalable AIG package.]

  Synopsis    [A simple circuit-based solver.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

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

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

#include "gia.h"

ABC_NAMESPACE_IMPL_START


//#define gia_assert(exp)     ((void)0)
//#define gia_assert(exp)     (assert(exp))

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

typedef struct Cbs2_Par_t_ Cbs2_Par_t;
struct Cbs2_Par_t_
{
    // conflict limits
    int           nBTLimit;     // limit on the number of conflicts
    int           nJustLimit;   // limit on the size of justification queue
    // current parameters
    int           nBTThis;      // number of conflicts
    int           nBTThisNc;    // number of conflicts
    int           nJustThis;    // max size of the frontier
    int           nBTTotal;     // total number of conflicts
    int           nJustTotal;   // total size of the frontier
    // decision heuristics
    int           fUseHighest;  // use node with the highest ID
    int           fUseLowest;   // use node with the highest ID
    int           fUseMaxFF;    // use node with the largest fanin fanout
49
    int           fUseFanout;   // use node with the largest fanin fanout
50 51 52 53 54 55 56 57 58 59
    // other
    int           fVerbose;
};

typedef struct Cbs2_Que_t_ Cbs2_Que_t;
struct Cbs2_Que_t_
{
    int           iHead;        // beginning of the queue
    int           iTail;        // end of the queue
    int           nSize;        // allocated size
60
    int *         pData;        // nodes stored in the queue
61 62 63 64 65 66 67 68 69 70 71
};
 
typedef struct Cbs2_Man_t_ Cbs2_Man_t;
struct Cbs2_Man_t_
{
    Cbs2_Par_t    Pars;         // parameters
    Gia_Man_t *   pAig;         // AIG manager
    Cbs2_Que_t    pProp;        // propagation queue
    Cbs2_Que_t    pJust;        // justification queue
    Cbs2_Que_t    pClauses;     // clause queue
    Vec_Int_t *   vModel;       // satisfying assignment
72
    Vec_Int_t *   vTemp;        // temporary storage
73 74
    // internal data
    Vec_Str_t     vAssign;
75
    Vec_Str_t     vMark;
76
    Vec_Int_t     vLevReason;
77
    Vec_Int_t     vWatches;
78
    Vec_Int_t     vWatchUpds;
79 80
    Vec_Int_t     vFanoutN;
    Vec_Int_t     vFanout0;
81 82
    Vec_Int_t     vActivity;
    Vec_Int_t     vActStore;
83
    Vec_Int_t     vJStore;
84 85 86 87 88 89 90 91 92 93
    // SAT calls statistics
    int           nSatUnsat;    // the number of proofs
    int           nSatSat;      // the number of failure
    int           nSatUndec;    // the number of timeouts
    int           nSatTotal;    // the number of calls
    // conflicts
    int           nConfUnsat;   // conflicts in unsat problems
    int           nConfSat;     // conflicts in sat problems
    int           nConfUndec;   // conflicts in undec problems
    // runtime stats
94
    abctime       timeJFront;
95 96 97 98
    abctime       timeSatUnsat; // unsat
    abctime       timeSatSat;   // sat
    abctime       timeSatUndec; // undecided
    abctime       timeTotal;    // total runtime
99 100 101
    // other statistics
    int           nPropCalls[3];
    int           nFails[2];
102
    int           nClauseConf;
103 104
};

105 106
static inline int   Cbs2_VarUnused( Cbs2_Man_t * p, int iVar )                     { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; }
static inline void  Cbs2_VarSetUnused( Cbs2_Man_t * p, int iVar )                  { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1);     } 
107

108 109 110
/*
static inline int   Cbs2_VarMark0( Cbs2_Man_t * p, int iVar )                      { return Vec_StrEntry(&p->vAssign, iVar);            }
static inline void  Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value )        { Vec_StrWriteEntry(&p->vAssign, iVar, (char)Value); } 
111

112 113
static inline int   Cbs2_VarMark1( Cbs2_Man_t * p, int iVar )                      { return Vec_StrEntry(&p->vValue, iVar);             }
static inline void  Cbs2_VarSetMark1( Cbs2_Man_t * p, int iVar, int Value )        { Vec_StrWriteEntry(&p->vValue, iVar, (char)Value);  } 
114

115 116 117 118 119
static inline int   Cbs2_VarIsAssigned( Cbs2_Man_t * p, int iVar )                 { return Cbs2_VarMark0(p, iVar);                                                                  }
static inline void  Cbs2_VarAssign( Cbs2_Man_t * p, int iVar )                     { assert(!Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark0(p, iVar, 1);                             }
static inline void  Cbs2_VarUnassign( Cbs2_Man_t * p, int iVar )                   { assert( Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark0(p, iVar, 0); Cbs2_VarSetUnused(p, iVar); }
static inline int   Cbs2_VarValue( Cbs2_Man_t * p, int iVar )                      { assert( Cbs2_VarIsAssigned(p, iVar)); return Cbs2_VarMark1(p, iVar);                            }
static inline void  Cbs2_VarSetValue( Cbs2_Man_t * p, int iVar, int v )            { assert( Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark1(p, iVar, v);                             }
120

121 122 123
static inline int   Cbs2_VarIsJust( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar )      { return Gia_ObjIsAnd(pVar) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar));  } 
static inline int   Cbs2_VarFanin0Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) ? (Cbs2_VarValue(p, Gia_ObjFaninId0(pVar, iVar)) ^ Gia_ObjFaninC0(pVar)) : 2;   }
static inline int   Cbs2_VarFanin1Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)) ? (Cbs2_VarValue(p, Gia_ObjFaninId1(pVar, iVar)) ^ Gia_ObjFaninC1(pVar)) : 2;   }
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
*/

static inline int   Cbs2_VarMark0( Cbs2_Man_t * p, int iVar )                      { return Vec_StrEntry(&p->vMark, iVar);              }
static inline void  Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value )        { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value);   } 

//static inline int   Cbs2_VarMark0( Cbs2_Man_t * p, int iVar )                      { return Vec_StrEntry(&p->vAssign, iVar) >= 2;       }
//static inline void  Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value )        { Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2^Vec_StrEntry(&p->vAssign, iVar)));   } 

static inline int   Cbs2_VarIsAssigned( Cbs2_Man_t * p, int iVar )                 { return Vec_StrEntry(&p->vAssign, iVar) < 2;        }
static inline void  Cbs2_VarUnassign( Cbs2_Man_t * p, int iVar )                   { assert( Cbs2_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs2_VarSetUnused(p, iVar); }

static inline int   Cbs2_VarValue( Cbs2_Man_t * p, int iVar )                      { return Vec_StrEntry(&p->vAssign, iVar);            }
static inline void  Cbs2_VarSetValue( Cbs2_Man_t * p, int iVar, int v )            { assert( !Cbs2_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v);                                  }

static inline int   Cbs2_VarIsJust( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar )      { return Gia_ObjIsAnd(pVar) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar));  } 
static inline int   Cbs2_VarFanin0Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarValue(p, Gia_ObjFaninId0(pVar, iVar)) ^ Gia_ObjFaninC0(pVar);   }
static inline int   Cbs2_VarFanin1Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarValue(p, Gia_ObjFaninId1(pVar, iVar)) ^ Gia_ObjFaninC1(pVar);   }


static inline int   Cbs2_VarDecLevel( Cbs2_Man_t * p, int iVar )                   { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar);    }
static inline int   Cbs2_VarReason0( Cbs2_Man_t * p, int iVar )                    { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1);  }
static inline int   Cbs2_VarReason1( Cbs2_Man_t * p, int iVar )                    { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2);  }
static inline int * Cbs2_VarReasonP( Cbs2_Man_t * p, int iVar )                    { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); }
//static inline int   Cbs2_ClauseDecLevel( Cbs2_Man_t * p, int hClause )             { return Cbs2_VarDecLevel( p, p->pClauses.pData[hClause] );                           }

static inline int   Cbs2_ClauseSize( Cbs2_Man_t * p, int hClause )                 { return p->pClauses.pData[hClause];                                                  }
static inline int * Cbs2_ClauseLits( Cbs2_Man_t * p, int hClause )                 { return p->pClauses.pData+hClause+1;                                                 }
static inline int   Cbs2_ClauseLit( Cbs2_Man_t * p, int hClause, int i )           { return p->pClauses.pData[hClause+1+i];                                              }
static inline int * Cbs2_ClauseNext1p( Cbs2_Man_t * p, int hClause )               { return p->pClauses.pData+hClause+Cbs2_ClauseSize(p, hClause)+2;                     }

static inline void  Cbs2_ClauseSetSize( Cbs2_Man_t * p, int hClause, int x )       { p->pClauses.pData[hClause] = x;                                                     }
static inline void  Cbs2_ClauseSetLit( Cbs2_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x;                                                 }
static inline void  Cbs2_ClauseSetNext( Cbs2_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs2_ClauseSize(p, hClause)+1+n] = x;                     }
157 158


159 160 161
#define Cbs2_QueForEachEntry( Que, iObj, i )                         \
    for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ )

162 163 164 165 166 167 168
#define Cbs2_ClauseForEachEntry( p, hClause, iObj, i )               \
    for ( i = 1; i <= Cbs2_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ )
#define Cbs2_ClauseForEachEntry1( p, hClause, iObj, i )                   \
    for ( i = 2; i <= Cbs2_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ )

#define Cbs2_ObjForEachFanout( p, iObj, iFanLit )                      \
    for ( iFanLit = Vec_IntEntry(&p->vFanout0, iObj); iFanLit; iFanLit = Vec_IntEntry(&p->vFanoutN, iFanLit) )
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

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

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

  Synopsis    [Sets default values of the parameters.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cbs2_SetDefaultParams( Cbs2_Par_t * pPars )
{
    memset( pPars, 0, sizeof(Cbs2_Par_t) );
    pPars->nBTLimit    =  1000;   // limit on the number of conflicts
189
    pPars->nJustLimit  =   500;   // limit on the size of justification queue
190 191 192
    pPars->fUseHighest =     1;   // use node with the highest ID
    pPars->fUseLowest  =     0;   // use node with the highest ID
    pPars->fUseMaxFF   =     0;   // use node with the largest fanin fanout
193
    pPars->fUseFanout  =     1;
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    pPars->fVerbose    =     1;   // print detailed statistics
}
void Cbs2_ManSetConflictNum( Cbs2_Man_t * p, int Num )
{
    p->Pars.nBTLimit = Num;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Cbs2_Man_t * Cbs2_ManAlloc( Gia_Man_t * pGia )
{
    Cbs2_Man_t * p;
    p = ABC_CALLOC( Cbs2_Man_t, 1 );
    p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000;
217 218 219
    p->pProp.pData = ABC_ALLOC( int, p->pProp.nSize );
    p->pJust.pData = ABC_ALLOC( int, p->pJust.nSize );
    p->pClauses.pData = ABC_ALLOC( int, p->pClauses.nSize );
220 221
    p->pClauses.iHead = p->pClauses.iTail = 1;
    p->vModel   = Vec_IntAlloc( 1000 );
222
    p->vTemp    = Vec_IntAlloc( 1000 );
223 224
    p->pAig     = pGia;
    Cbs2_SetDefaultParams( &p->Pars );
225 226
    Vec_StrFill( &p->vAssign,    Gia_ManObjNum(pGia), 2 );
    Vec_StrFill( &p->vMark,      Gia_ManObjNum(pGia), 0 );
227
    Vec_IntFill( &p->vLevReason, 3*Gia_ManObjNum(pGia), -1 );
228
    Vec_IntFill( &p->vWatches,   2*Gia_ManObjNum(pGia), 0 );
229 230
    Vec_IntFill( &p->vFanout0,   Gia_ManObjNum(pGia),   0 );
    Vec_IntFill( &p->vFanoutN,   2*Gia_ManObjNum(pGia), 0 );
231
    Vec_IntFill( &p->vActivity,  Gia_ManObjNum(pGia), 0 );
232 233 234
    Vec_IntGrow( &p->vActStore,  1000 );
    Vec_IntGrow( &p->vJStore,    1000 );
    Vec_IntGrow( &p->vWatchUpds, 1000 );
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    return p;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cbs2_ManStop( Cbs2_Man_t * p )
{
251
    Vec_StrErase( &p->vAssign );
252
    Vec_StrErase( &p->vMark );
253
    Vec_IntErase( &p->vLevReason );
254
    Vec_IntErase( &p->vWatches );
255 256
    Vec_IntErase( &p->vFanout0 );
    Vec_IntErase( &p->vFanoutN );
257 258
    Vec_IntErase( &p->vActivity );
    Vec_IntErase( &p->vActStore );
259
    Vec_IntErase( &p->vJStore );
260
    Vec_IntErase( &p->vWatchUpds );
261
    Vec_IntFree( p->vModel );
262
    Vec_IntFree( p->vTemp );
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 292 293 294 295 296 297 298 299 300
    ABC_FREE( p->pClauses.pData );
    ABC_FREE( p->pProp.pData );
    ABC_FREE( p->pJust.pData );
    ABC_FREE( p );
}

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

  Synopsis    [Returns satisfying assignment.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Int_t * Cbs2_ReadModel( Cbs2_Man_t * p )
{
    return p->vModel;
}




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

  Synopsis    [Returns 1 if the solver is out of limits.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Cbs2_ManCheckLimits( Cbs2_Man_t * p )
{
301 302
    p->nFails[0] += p->Pars.nJustThis > p->Pars.nJustLimit;
    p->nFails[1] += p->Pars.nBTThis > p->Pars.nBTLimit;
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
    return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit;
}

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

  Synopsis    [Saves the satisfying assignment as an array of literals.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Cbs2_ManSaveModel( Cbs2_Man_t * p, Vec_Int_t * vCex )
{
319
    int i, iLit;
320 321
    Vec_IntClear( vCex );
    p->pProp.iHead = 0;
322 323 324
    Cbs2_QueForEachEntry( p->pProp, iLit, i )
    {
        int iVar = Abc_Lit2Var(iLit);
325 326
        if ( Gia_ObjIsCi(Gia_ManObj(p->pAig, iVar)) )
            Vec_IntPush( vCex, Abc_Var2Lit(Gia_ManIdToCioId(p->pAig, iVar), !Cbs2_VarValue(p, iVar)) );
327
    }
328 329 330
} 
static inline void Cbs2_ManSaveModelAll( Cbs2_Man_t * p, Vec_Int_t * vCex )
{
331
    int i, iLit;
332 333
    Vec_IntClear( vCex );
    p->pProp.iHead = 0;
334 335 336
    Cbs2_QueForEachEntry( p->pProp, iLit, i )
    {
        int iVar = Abc_Lit2Var(iLit);
337
        Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs2_VarValue(p, iVar)) );
338
    }
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
} 

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Cbs2_QueIsEmpty( Cbs2_Que_t * p )
{
    return p->iHead == p->iTail;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
368
static inline void Cbs2_QuePush( Cbs2_Que_t * p, int iObj )
369 370 371 372
{
    if ( p->iTail == p->nSize )
    {
        p->nSize *= 2;
373
        p->pData = ABC_REALLOC( int, p->pData, p->nSize ); 
374
    }
375
    p->pData[p->iTail++] = iObj;
376
}
377 378 379 380 381 382 383 384 385
static inline void Cbs2_QueGrow( Cbs2_Que_t * p, int Plus )
{
    if ( p->iTail + Plus > p->nSize )
    {
        p->nSize *= 2;
        p->pData = ABC_REALLOC( int, p->pData, p->nSize ); 
    }
    assert( p->iTail + Plus <= p->nSize );
}
386 387 388 389 390 391 392 393 394 395 396 397

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

  Synopsis    [Returns 1 if the object in the queue.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
398
static inline int Cbs2_QueHasNode( Cbs2_Que_t * p, int iObj )
399
{
400 401 402
    int i, iTemp;
    Cbs2_QueForEachEntry( *p, iTemp, i )
        if ( iTemp == iObj )
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
            return 1;
    return 0;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Cbs2_QueStore( Cbs2_Que_t * p, int * piHeadOld, int * piTailOld )
{
    int i;
    *piHeadOld = p->iHead;
    *piTailOld = p->iTail;
    for ( i = *piHeadOld; i < *piTailOld; i++ )
        Cbs2_QuePush( p, p->pData[i] );
    p->iHead = *piTailOld;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Cbs2_QueRestore( Cbs2_Que_t * p, int iHeadOld, int iTailOld )
{
    p->iHead = iHeadOld;
    p->iTail = iTailOld;
}


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

  Synopsis    [Max number of fanins fanouts.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Cbs2_VarFaninFanoutMax( Cbs2_Man_t * p, Gia_Obj_t * pObj )
{
    int Count0, Count1;
    assert( !Gia_IsComplement(pObj) );
    assert( Gia_ObjIsAnd(pObj) );
    Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) );
    Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) );
    return Abc_MaxInt( Count0, Count1 );
}

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

  Synopsis    [Find variable with the highest ID.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
478
static inline int Cbs2_ManDecideHighest( Cbs2_Man_t * p )
479
{
480 481 482 483
    int i, iObj, iObjMax = 0;
    Cbs2_QueForEachEntry( p->pJust, iObj, i )
        if ( iObjMax == 0 || iObjMax < iObj )
            iObjMax = iObj;
484
    return iObjMax;
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
}

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

  Synopsis    [Find variable with the lowest ID.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline Gia_Obj_t * Cbs2_ManDecideLowest( Cbs2_Man_t * p )
{
500 501 502 503 504
    int i, iObj, iObjMin = 0;
    Cbs2_QueForEachEntry( p->pJust, iObj, i )
        if ( iObjMin == 0 || iObjMin > iObj )
            iObjMin = iObj;
    return Gia_ManObj(p->pAig, iObjMin);
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
}

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

  Synopsis    [Find variable with the maximum number of fanin fanouts.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline Gia_Obj_t * Cbs2_ManDecideMaxFF( Cbs2_Man_t * p )
{
    Gia_Obj_t * pObj, * pObjMax = NULL;
521
    int i, iMaxFF = 0, iCurFF, iObj;
522
    assert( p->pAig->pRefs != NULL );
523
    Cbs2_QueForEachEntry( p->pJust, iObj, i )
524
    {
525
        pObj = Gia_ManObj(p->pAig, iObj);
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
        iCurFF = Cbs2_VarFaninFanoutMax( p, pObj );
        assert( iCurFF > 0 );
        if ( iMaxFF < iCurFF )
        {
            iMaxFF = iCurFF;
            pObjMax = pObj;
        }
    }
    return pObjMax; 
}


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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Cbs2_ManCancelUntil( Cbs2_Man_t * p, int iBound )
{
551
    int i, iLit;
552 553
    assert( iBound <= p->pProp.iTail );
    p->pProp.iHead = iBound;
554 555
    Cbs2_QueForEachEntry( p->pProp, iLit, i )
        Cbs2_VarUnassign( p, Abc_Lit2Var(iLit) );
556 557 558 559 560 561 562 563 564 565 566 567 568 569
    p->pProp.iTail = iBound;
}

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

  Synopsis    [Assigns the variables a value.]

  Description [Returns 1 if conflict; 0 if no conflict.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
570
static inline void Cbs2_ManAssign( Cbs2_Man_t * p, int iLit, int Level, int iRes0, int iRes1 )
571
{
572
    int iObj = Abc_Lit2Var(iLit);
573
    assert( Cbs2_VarUnused(p, iObj) );
574
    assert( !Cbs2_VarIsAssigned(p, iObj) );
575
    //Cbs2_VarAssign( p, iObj );
576
    Cbs2_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) );
577
    Cbs2_QuePush( &p->pProp, iLit );
578
    Vec_IntWriteEntry( &p->vLevReason, 3*iObj,   Level );
579 580
    Vec_IntWriteEntry( &p->vLevReason, 3*iObj+1, iRes0 );
    Vec_IntWriteEntry( &p->vLevReason, 3*iObj+2, iRes1 );
581 582 583 584 585 586 587
}






588 589


590 591 592 593 594 595 596 597 598 599 600 601 602 603

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

  Synopsis    [Prints conflict clause.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Cbs2_ManPrintClause( Cbs2_Man_t * p, int Level, int hClause )
{
604
    int i, iLit;
605
    assert( Cbs2_QueIsEmpty( &p->pClauses ) );
606
    printf( "Level %2d : ", Level );
607 608 609
    Cbs2_ClauseForEachEntry( p, hClause, iLit, i )
        printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) );
//        printf( "%d=%d(%d) ", iObj, Cbs2_VarValue(p, Abc_Lit2Var(iLit)), Cbs2_VarDecLevel(p, Abc_Lit2Var(iLit)) );
610 611
    printf( "\n" );
}
612
static inline void Cbs2_ManPrintCube( Cbs2_Man_t * p, int Level, int hClause )
613
{
614 615
    int i, iObj;
    assert( Cbs2_QueIsEmpty( &p->pClauses ) );
616
    printf( "Level %2d : ", Level );
617
    Cbs2_ClauseForEachEntry( p, hClause, iObj, i )
618
        printf( "%c%d ", Cbs2_VarValue(p, iObj)? '+':'-', iObj );
619 620
    printf( "\n" );
}
621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
static inline void Cbs2_ManBumpClause( Cbs2_Man_t * p, int hClause )
{
    int i, iObj;
    assert( Cbs2_QueIsEmpty( &p->pClauses ) );
    Cbs2_ClauseForEachEntry( p, hClause, iObj, i )
    {
        //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
        //    Vec_IntPush( &p->vActStore, iObj );
        //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
    }
}
static inline void Cbs2_ManBumpClean( Cbs2_Man_t * p )
{
    int i, iObj;
    Vec_IntForEachEntry( &p->vActStore, iObj, i )
        Vec_IntWriteEntry( &p->vActivity, iObj, 0 );
}

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

  Synopsis    [Finalized the clause.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
650 651 652 653 654 655 656 657 658
static inline void Cbs2_ManCleanWatch( Cbs2_Man_t * p )
{
    int i, iLit;
    Vec_IntForEachEntry( &p->vWatchUpds, iLit, i )
        Vec_IntWriteEntry( &p->vWatches, iLit, 0 );
    Vec_IntClear( &p->vWatchUpds );
    //Vec_IntForEachEntry( &p->vWatches, iLit, i )
    //    assert( iLit == 0 );
}
659 660 661 662
static inline void Cbs2_ManWatchClause( Cbs2_Man_t * p, int hClause, int Lit )
{
    int * pLits = Cbs2_ClauseLits( p, hClause );
    int * pPlace = Vec_IntEntryP( &p->vWatches, Abc_LitNot(Lit) );
663 664
    if ( *pPlace == 0 )
        Vec_IntPush( &p->vWatchUpds, Abc_LitNot(Lit) );
665 666 667 668 669 670 671 672 673 674 675
/*
    if ( pClause->pLits[0] == Lit )
        pClause->pNext0 = p->pWatches[lit_neg(Lit)];  
    else
    {
        assert( pClause->pLits[1] == Lit );
        pClause->pNext1 = p->pWatches[lit_neg(Lit)];  
    }
    p->pWatches[lit_neg(Lit)] = pClause;
*/
    assert( Lit == pLits[0] || Lit == pLits[1] );
676
    Cbs2_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace );
677 678
    *pPlace = hClause;
}
679
static inline int Cbs2_QueFinish( Cbs2_Man_t * p, int Level )
680 681
{
    Cbs2_Que_t * pQue = &(p->pClauses); 
682
    int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1;
683 684
    assert( pQue->iHead+1 < pQue->iTail );
    Cbs2_ClauseSetSize( p, pQue->iHead, Size );
685 686 687 688 689 690 691
    hClauseC = pQue->iHead = pQue->iTail;
    //printf( "Adding cube: " ); Cbs2_ManPrintCube(p, Level, hClause);
    if ( Size == 1 )
        return hClause;
    // create watched clause
    pQue->iHead = hClause;
    Cbs2_QueForEachEntry( p->pClauses, iObj, i )
692
    {
693 694 695 696 697 698
        if ( i == hClauseC )
            break;
        else if ( i == hClause ) // nlits
            Cbs2_QuePush( pQue, iObj );
        else // literals
            Cbs2_QuePush( pQue, Abc_Var2Lit(iObj, Cbs2_VarValue(p, iObj)) ); // complement
699
    }
700 701 702 703 704 705
    Cbs2_QuePush( pQue, 0 ); // next0
    Cbs2_QuePush( pQue, 0 ); // next1
    pQue->iHead = pQue->iTail;
    Cbs2_ManWatchClause( p, hClauseC, Cbs2_ClauseLit(p, hClauseC, 0) );
    Cbs2_ManWatchClause( p, hClauseC, Cbs2_ClauseLit(p, hClauseC, 1) );
    //printf( "Adding clause %d: ", hClauseC ); Cbs2_ManPrintClause(p, Level, hClauseC);
706 707
    return hClause;
}
708 709 710 711 712 713 714 715 716 717 718 719

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

  Synopsis    [Returns conflict clause.]

  Description [Performs conflict analysis.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
720
static inline int Cbs2_ManDeriveReason( Cbs2_Man_t * p, int Level )
721 722
{
    Cbs2_Que_t * pQue = &(p->pClauses);
723
    int i, k, iObj, iLitLevel, * pReason;
724
    assert( pQue->pData[pQue->iHead] == 0 );
725 726 727 728
    assert( pQue->pData[pQue->iHead+1] == 0 );
    assert( pQue->iHead + 2 < pQue->iTail );
    //for ( i = pQue->iHead + 2; i < pQue->iTail; i++ )
    //    assert( !Cbs2_VarMark0(p, pQue->pData[i]) );
729
    // compact literals
730
    Vec_IntClear( p->vTemp );
731
    for ( i = k = pQue->iHead + 2; i < pQue->iTail; i++ )
732
    {
733
        iObj = pQue->pData[i];
734
        if ( Cbs2_VarMark0(p, iObj) ) // unassigned - seen again
735
            continue;
736 737 738
        //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
        //    Vec_IntPush( &p->vActStore, iObj );
        //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
739
        // assigned - seen first time
740
        Cbs2_VarSetMark0(p, iObj, 1);
741
        Vec_IntPush( p->vTemp, iObj );
742
        // check decision level
743
        iLitLevel = Cbs2_VarDecLevel( p, iObj );
744 745
        if ( iLitLevel < Level )
        {
746
            pQue->pData[k++] = iObj;
747 748 749
            continue;
        }
        assert( iLitLevel == Level );
750 751
        pReason = Cbs2_VarReasonP( p, iObj );
        if ( pReason[0] == 0 && pReason[1] == 0 ) // no reason
752
        {
753 754 755 756 757 758 759 760 761 762 763
            assert( pQue->pData[pQue->iHead+1] == 0 );
            pQue->pData[pQue->iHead+1] = iObj;
        }
        else if ( pReason[0] != 0 ) // circuit reason
        {
            Cbs2_QuePush( pQue, pReason[0] );
            if ( pReason[1] )
            Cbs2_QuePush( pQue, pReason[1] );
        }
        else // clause reason
        {
764
            int i, * pLits, nLits = Cbs2_ClauseSize( p, pReason[1] );
765
            assert( pReason[1] );
766 767
            Cbs2_QueGrow( pQue, nLits );
            pLits = Cbs2_ClauseLits( p, pReason[1] );
768 769 770
            assert( iObj == Abc_Lit2Var(pLits[0]) );
            for ( i = 1; i < nLits; i++ )
                Cbs2_QuePush( pQue, Abc_Lit2Var(pLits[i]) );
771 772
        }
    }
773 774
    assert( pQue->pData[pQue->iHead] == 0 );
    assert( pQue->pData[pQue->iHead+1] != 0 );
775 776
    pQue->iTail = k;
    // clear the marks
777
    Vec_IntForEachEntry( p->vTemp, iObj, i )
778
        Cbs2_VarSetMark0(p, iObj, 0);
779
    return Cbs2_QueFinish( p, Level );
780 781 782 783 784 785 786 787
}
static inline int Cbs2_ManAnalyze( Cbs2_Man_t * p, int Level, int iVar, int iFan0, int iFan1 )
{
    Cbs2_Que_t * pQue = &(p->pClauses); 
    assert( Cbs2_VarIsAssigned(p, iVar) );
    assert( Cbs2_QueIsEmpty( pQue ) );
    Cbs2_QuePush( pQue, 0 );
    Cbs2_QuePush( pQue, 0 );
788
    if ( iFan0 ) // circuit conflict
789
    {
790 791 792
        assert( Cbs2_VarIsAssigned(p, iFan0) );
        assert( iFan1 == 0 || Cbs2_VarIsAssigned(p, iFan1) );
        Cbs2_QuePush( pQue, iVar );
793 794 795 796
        Cbs2_QuePush( pQue, iFan0 );
        if ( iFan1 )
        Cbs2_QuePush( pQue, iFan1 );
    }
797
    else // clause conflict
798
    {
799
        int i, * pLits, nLits = Cbs2_ClauseSize( p, iFan1 );
800
        assert( iFan1 );
801 802
        Cbs2_QueGrow( pQue, nLits );
        pLits = Cbs2_ClauseLits( p, iFan1 );
803
        assert( iVar == Abc_Lit2Var(pLits[0]) );
804 805
        assert( Cbs2_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) );
        for ( i = 0; i < nLits; i++ )
806 807 808
            Cbs2_QuePush( pQue, Abc_Lit2Var(pLits[i]) );
    }
    return Cbs2_ManDeriveReason( p, Level );
809 810
}

811

812 813
/**Function*************************************************************

814
  Synopsis    [Propagate one assignment.]
815

816
  Description [Returns handle of the conflict clause, if conflict occurs.]
817 818 819 820 821 822
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
823
static inline int Cbs2_ManPropagateClauses( Cbs2_Man_t * p, int Level, int Lit )
824
{
825 826 827 828 829 830 831
    int i, Value, Cur, LitF = Abc_LitNot(Lit);
    int * pPrev = Vec_IntEntryP( &p->vWatches, Lit );
    //for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
    for ( Cur = *pPrev; Cur; Cur = *pPrev )
    {
        int nLits = Cbs2_ClauseSize( p, Cur );
        int * pLits = Cbs2_ClauseLits( p, Cur );
832 833
        p->nPropCalls[1]++;
//printf( "  Watching literal %c%d on level %d.\n", Abc_LitIsCompl(Lit) ? '-':'+', Abc_Lit2Var(Lit), Level );
834 835 836 837 838 839 840 841 842 843 844
        // make sure the false literal is in the second literal of the clause
        //if ( pCur->pLits[0] == LitF )
        if ( pLits[0] == LitF )
        {
            //pCur->pLits[0] = pCur->pLits[1];
            pLits[0] = pLits[1];
            //pCur->pLits[1] = LitF;
            pLits[1] = LitF;
            //pTemp = pCur->pNext0;
            //pCur->pNext0 = pCur->pNext1;
            //pCur->pNext1 = pTemp;
845
            ABC_SWAP( int, pLits[nLits], pLits[nLits+1] );
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
        }
        //assert( pCur->pLits[1] == LitF );
        assert( pLits[1] == LitF );

        // if the first literal is true, the clause is satisfied
        //if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
        if ( Cbs2_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) )
        {
            //ppPrev = &pCur->pNext1;
            pPrev = Cbs2_ClauseNext1p(p, Cur);
            continue;
        }

        // look for a new literal to watch
        for ( i = 2; i < nLits; i++ )
        {
            // skip the case when the literal is false
            //if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
            if ( Cbs2_VarValue(p, Abc_Lit2Var(pLits[i])) == Abc_LitIsCompl(pLits[i]) )
                continue;
            // the literal is either true or unassigned - watch it
            //pCur->pLits[1] = pCur->pLits[i];
            //pCur->pLits[i] = LitF;
            pLits[1] = pLits[i];
            pLits[i] = LitF;
            // remove this clause from the watch list of Lit
            //*ppPrev = pCur->pNext1;
            *pPrev = *Cbs2_ClauseNext1p(p, Cur);
            // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
            //Intb_ManWatchClause( p, pCur, pCur->pLits[1] );
            Cbs2_ManWatchClause( p, Cur, Cbs2_ClauseLit(p, Cur, 1) );
            break;
        }
        if ( i < nLits ) // found new watch
            continue;

        // clause is unit - enqueue new implication
        //if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) )
        //{
        //    ppPrev = &pCur->pNext1;
        //    continue;
        //}

        // clause is unit - enqueue new implication
        Value = Cbs2_VarValue(p, Abc_Lit2Var(pLits[0]));
        if ( Value >= 2 ) // unassigned
        {
            Cbs2_ManAssign( p, pLits[0], Level, 0, Cur );
            pPrev = Cbs2_ClauseNext1p(p, Cur);
            continue;
        }

        // conflict detected - return the conflict clause
        //return pCur;
        if ( Value == Abc_LitIsCompl(pLits[0]) )
901 902
        {
            p->nClauseConf++;
903
            return Cbs2_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur );
904
        }
905 906
    }
    return 0;
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923
}


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

  Synopsis    [Performs resolution of two clauses.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline int Cbs2_ManResolve( Cbs2_Man_t * p, int Level, int hClause0, int hClause1 )
{
    Cbs2_Que_t * pQue = &(p->pClauses);
924
    int i, iObj, LevelMax = -1, LevelCur;
925 926 927 928 929 930
    assert( pQue->pData[hClause0+1] != 0 );
    assert( pQue->pData[hClause0+1] == pQue->pData[hClause1+1] );
    //Cbs2_ClauseForEachEntry1( p, hClause0, iObj, i )
    //    assert( !Cbs2_VarMark0(p, iObj) );
    //Cbs2_ClauseForEachEntry1( p, hClause1, iObj, i )
    //    assert( !Cbs2_VarMark0(p, iObj) );
931
    assert( Cbs2_QueIsEmpty( pQue ) );
932
    Cbs2_QuePush( pQue, 0 );
933 934 935
    Cbs2_QuePush( pQue, 0 );
//    for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ )
    Cbs2_ClauseForEachEntry1( p, hClause0, iObj, i )
936
    {
937
        if ( Cbs2_VarMark0(p, iObj) ) // unassigned - seen again
938
            continue;
939 940 941
        //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
        //    Vec_IntPush( &p->vActStore, iObj );
        //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
942
        // assigned - seen first time
943
        Cbs2_VarSetMark0(p, iObj, 1);
944 945
        Cbs2_QuePush( pQue, iObj );
        LevelCur = Cbs2_VarDecLevel( p, iObj );
946 947 948
        if ( LevelMax < LevelCur )
            LevelMax = LevelCur;
    }
949 950
//    for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ )
    Cbs2_ClauseForEachEntry1( p, hClause1, iObj, i )
951
    {
952
        if ( Cbs2_VarMark0(p, iObj) ) // unassigned - seen again
953
            continue;
954 955 956
        //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
        //    Vec_IntPush( &p->vActStore, iObj );
        //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
957
        // assigned - seen first time
958
        Cbs2_VarSetMark0(p, iObj, 1);
959 960
        Cbs2_QuePush( pQue, iObj );
        LevelCur = Cbs2_VarDecLevel( p, iObj );
961 962 963
        if ( LevelMax < LevelCur )
            LevelMax = LevelCur;
    }
964 965 966
    for ( i = pQue->iHead + 2; i < pQue->iTail; i++ )
        Cbs2_VarSetMark0(p, pQue->pData[i], 0);
    return Cbs2_ManDeriveReason( p, LevelMax );
967 968 969 970 971 972 973 974 975 976 977 978 979
}

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

  Synopsis    [Propagates a variable.]

  Description [Returns clause handle if conflict; 0 if no conflict.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
980
static inline int Cbs2_ManPropagateOne( Cbs2_Man_t * p, int iVar, int Level )
981
{
982
    Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1;
983
    assert( !Gia_IsComplement(pVar) );
984
    assert( Cbs2_VarIsAssigned(p, iVar) );
985 986
    if ( Gia_ObjIsCi(pVar) )
        return 0;
987
    p->nPropCalls[0]++;
988
    assert( Gia_ObjIsAnd(pVar) );
989 990
    Value0 = Cbs2_VarFanin0Value(p, pVar, iVar);
    Value1 = Cbs2_VarFanin1Value(p, pVar, iVar);
991
    if ( Cbs2_VarValue(p, iVar) == 1 )
992 993 994 995
    { // value is 1
        if ( Value0 == 0 || Value1 == 0 ) // one is 0
        {
            if ( Value0 == 0 && Value1 != 0 )
996
                return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), 0 );
997
            if ( Value0 != 0 && Value1 == 0 )
998
                return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId1(pVar, iVar), 0 );
999
            assert( Value0 == 0 && Value1 == 0 );
1000
            return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) );
1001
        }
1002
        if ( Value0 >= 2 ) // first is unassigned
1003
            Cbs2_ManAssign( p, Gia_ObjFaninLit0(pVar, iVar), Level, iVar, 0 );
1004
        if ( Value1 >= 2 ) // first is unassigned
1005
            Cbs2_ManAssign( p, Gia_ObjFaninLit1(pVar, iVar), Level, iVar, 0 );
1006 1007 1008 1009 1010 1011
        return 0;
    }
    // value is 0
    if ( Value0 == 0 || Value1 == 0 ) // one is 0
        return 0;
    if ( Value0 == 1 && Value1 == 1 ) // both are 1
1012
        return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) );
1013 1014
    if ( Value0 == 1 || Value1 == 1 ) // one is 1 
    {
1015
        if ( Value0 >= 2 ) // first is unassigned
1016
            Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)), Level, iVar, Gia_ObjFaninId1(pVar, iVar) );
1017
        if ( Value1 >= 2 ) // second is unassigned
1018
            Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)), Level, iVar, Gia_ObjFaninId0(pVar, iVar) );
1019 1020
        return 0;
    }
1021 1022
    assert( Cbs2_VarIsJust(p, pVar, iVar) );
    //assert( !Cbs2_QueHasNode( &p->pJust, iVar ) );
1023 1024
    if ( !p->Pars.fUseFanout )
        Cbs2_QuePush( &p->pJust, iVar );
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
    return 0;
}

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

  Synopsis    [Propagates a variable.]

  Description [Returns 1 if conflict; 0 if no conflict.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1039
static inline int Cbs2_ManPropagateTwo( Cbs2_Man_t * p, int iVar, int Level )
1040
{
1041
    Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1;
1042 1043
    assert( !Gia_IsComplement(pVar) );
    assert( Gia_ObjIsAnd(pVar) );
1044
    assert( Cbs2_VarIsAssigned(p, iVar) );
1045
    assert( Cbs2_VarValue(p, iVar) == 0 );
1046 1047
    Value0 = Cbs2_VarFanin0Value(p, pVar, iVar);
    Value1 = Cbs2_VarFanin1Value(p, pVar, iVar);
1048
    p->nPropCalls[1]++;
1049 1050 1051 1052
    // value is 0
    if ( Value0 == 0 || Value1 == 0 ) // one is 0
        return 0;
    if ( Value0 == 1 && Value1 == 1 ) // both are 1
1053
        return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) );
1054
    assert( Value0 == 1 || Value1 == 1 );
1055
    if ( Value0 >= 2 ) // first is unassigned
1056
        Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)), Level, iVar, Gia_ObjFaninId1(pVar, iVar) );
1057
    if ( Value1 >= 2 ) // first is unassigned
1058
        Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)), Level, iVar, Gia_ObjFaninId0(pVar, iVar) );
1059 1060 1061 1062 1063
    return 0;
}

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

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
  Synopsis    [Propagates a variable.]

  Description [Returns 1 if conflict; 0 if no conflict.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static inline void Cbs2_ManPropagateUnassigned( Cbs2_Man_t * p, int iVar, int Level )
{
    Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1;
    assert( !Gia_IsComplement(pVar) );
    assert( Gia_ObjIsAnd(pVar) );
    assert( !Cbs2_VarIsAssigned(p, iVar) );
    Value0 = Cbs2_VarFanin0Value(p, pVar, iVar);
    Value1 = Cbs2_VarFanin1Value(p, pVar, iVar);
1081 1082 1083 1084
    p->nPropCalls[2]++;
    if ( Value0 == 0 && Value1 == 0 ) // the output becomes 1
        Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) );
    else if ( Value0 == 0 ) // the output becomes 0
1085
        Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId0(pVar, iVar), 0 );
1086 1087 1088
    else if ( Value1 == 0 ) // the output becomes 0
        Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId1(pVar, iVar), 0 );
    else if ( Value0 == 1 && Value1 == 1 ) // the output becomes 1
1089 1090 1091 1092 1093
        Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 0), Level, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) );
}

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

1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
  Synopsis    [Propagates all variables.]

  Description [Returns 1 if conflict; 0 if no conflict.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Cbs2_ManPropagate( Cbs2_Man_t * p, int Level )
{
    while ( 1 )
    {
1107 1108
        int i, k, iVar, iLit, hClause;
        Cbs2_QueForEachEntry( p->pProp, iLit, i )
1109
        {
1110
            if ( (hClause = Cbs2_ManPropagateOne( p, Abc_Lit2Var(iLit), Level )) )
1111 1112 1113 1114
                return hClause;
        }
        p->pProp.iHead = p->pProp.iTail;
        k = p->pJust.iHead;
1115
        Cbs2_QueForEachEntry( p->pJust, iVar, i )
1116
        {
1117
            if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) )
1118
                p->pJust.pData[k++] = iVar;
1119
            else if ( (hClause = Cbs2_ManPropagateTwo( p, iVar, Level )) )
1120 1121 1122 1123 1124 1125 1126 1127
                return hClause;
        }
        if ( k == p->pJust.iTail )
            break;
        p->pJust.iTail = k;
    }
    return 0;
}
1128 1129 1130


int Cbs2_ManPropagate2( Cbs2_Man_t * p, int Level )
1131
{
1132 1133
    int i, iLit, iFan, hClause;
    Cbs2_QueForEachEntry( p->pProp, iLit, i )
1134
    {
1135 1136
        if ( (hClause = Cbs2_ManPropagateClauses(p, Level, iLit)) )
            return hClause;
1137
        Cbs2_ObjForEachFanout( p, Abc_Lit2Var(iLit), iFan )
1138
        {
1139 1140 1141 1142
            int iFanout = Abc_Lit2Var(iFan);
            if ( !Cbs2_VarIsAssigned(p, iFanout) )
                Cbs2_ManPropagateUnassigned( p, iFanout, Level );
            else if ( (hClause = Cbs2_ManPropagateOne(p, iFanout, Level)) )
1143 1144
                return hClause;
        }
1145
        if ( (hClause = Cbs2_ManPropagateOne( p, Abc_Lit2Var(iLit), Level )) )
1146 1147 1148 1149 1150
            return hClause;
    }
    p->pProp.iHead = p->pProp.iTail;
    return 0;
}
1151

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163

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

  Synopsis    [Updates J-frontier.]

  Description [Returns 1 if found SAT; 0 if continues solving.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
static inline int Cbs2_ManUpdateDecVar2( Cbs2_Man_t * p, int iObj, int iDecLit )
{
    Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan;

    iFan = Gia_ObjFaninId0(pObj, iObj);
    if ( iDecLit == -1 || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjLevelId(p->pAig, iFan) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj));

    iFan = Gia_ObjFaninId1(pObj, iObj);
    if ( iDecLit == -1 || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjLevelId(p->pAig, iFan) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj));

    return iDecLit;
}
static inline int Cbs2_ManUpdateDecVar3( Cbs2_Man_t * p, int iObj, int iDecLit )
{
    Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan;

    iFan = Gia_ObjFaninId0(pObj, iObj);
    if ( iDecLit == -1 || Vec_IntEntry(&p->vActivity, Abc_Lit2Var(iDecLit)) < Vec_IntEntry(&p->vActivity, iFan) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj));

    iFan = Gia_ObjFaninId1(pObj, iObj);
    if ( iDecLit == -1 || Vec_IntEntry(&p->vActivity, Abc_Lit2Var(iDecLit)) < Vec_IntEntry(&p->vActivity, iFan) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj));

    return iDecLit;
}
static inline int Cbs2_ManUpdateDecVar( Cbs2_Man_t * p, int iObj, int iDecLit )
{
    Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan;

    iFan = Gia_ObjFaninId0(pObj, iObj);
    if ( iDecLit == -1 || Gia_ObjRefNumId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjRefNumId(p->pAig, iFan) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj));

    iFan = Gia_ObjFaninId1(pObj, iObj);
    if ( iDecLit == -1 || Gia_ObjRefNumId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjRefNumId(p->pAig, iFan) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj));

    return iDecLit;
}
int Cbs2_ManUpdateFrontier( Cbs2_Man_t * p, int iPropHeadOld, int * piDecLit )
1207
{
1208 1209 1210
    abctime clk = Abc_Clock();
    int i, iVar, iLit, iJustTailOld = p->pJust.iTail;
    *piDecLit = -1;
1211 1212 1213
    assert( Cbs2_QueIsEmpty(&p->pProp) );
    // visit old frontier nodes
    Cbs2_QueForEachEntry( p->pJust, iVar, i )
1214 1215 1216 1217
        if ( i == iJustTailOld )
            break;
        else if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) )
        {
1218
            Cbs2_QuePush( &p->pJust, iVar );
1219 1220
            //*piDecLit = Cbs2_ManUpdateDecVar( p, iVar, *piDecLit );
        }
1221 1222
    // append new nodes
    p->pProp.iHead = iPropHeadOld;
1223 1224 1225
    Cbs2_QueForEachEntry( p->pProp, iLit, i )
    {
        iVar = Abc_Lit2Var(iLit);
1226
        if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) )
1227
        {
1228
            Cbs2_QuePush( &p->pJust, iVar );
1229 1230 1231
            //*piDecLit = Cbs2_ManUpdateDecVar( p, iVar, *piDecLit );
        }
    }
1232 1233 1234 1235
    p->pProp.iHead = p->pProp.iTail;
    // update the head of the frontier
    p->pJust.iHead = iJustTailOld;
    // return 1 if the queue is empty
1236 1237
    p->timeJFront += Abc_Clock() - clk;
//printf( "%d ", p->pJust.iTail - p->pJust.iHead );
1238 1239
    return Cbs2_QueIsEmpty(&p->pJust);
}
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251

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

  Synopsis    [Solve the problem recursively.]

  Description [Returns learnt clause if unsat, NULL if sat or undecided.]
               
  SideEffects []

  SeeAlso     []
 
***********************************************************************/
1252 1253

int Cbs2_ManSolve1_rec( Cbs2_Man_t * p, int Level )
1254
{ 
1255
    Gia_Obj_t * pVar;
1256 1257
    Cbs2_Que_t * pQue = &(p->pClauses);
    int iPropHead, iJustHead, iJustTail;
1258
    int hClause, hLearn0, hLearn1, iVar, iDecLit;
1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
    // propagate assignments
    assert( !Cbs2_QueIsEmpty(&p->pProp) );
    if ( (hClause = Cbs2_ManPropagate( p, Level )) )
        return hClause;
    // check for satisfying assignment
    assert( Cbs2_QueIsEmpty(&p->pProp) );
    if ( Cbs2_QueIsEmpty(&p->pJust) )
        return 0;
    // quit using resource limits
    p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead );
    if ( Cbs2_ManCheckLimits( p ) )
        return 0;
    // remember the state before branching
    iPropHead = p->pProp.iHead;
    Cbs2_QueStore( &p->pJust, &iJustHead, &iJustTail );
    // find the decision variable
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
    assert( p->Pars.fUseHighest );
    iVar = Cbs2_ManDecideHighest( p );
    pVar = Gia_ManObj( p->pAig, iVar );
    assert( Cbs2_VarIsJust(p, pVar, iVar) );
    // chose decision variable using fanout count
    if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) )
        iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar));
    else
        iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar));
    // decide on first fanin
    Cbs2_ManAssign( p, iDecLit, Level+1, 0, 0 );
1286
    if ( !(hLearn0 = Cbs2_ManSolve1_rec( p, Level+1 )) )
1287
        return 0;
1288
    if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) )
1289 1290 1291 1292 1293
        return hLearn0;
    Cbs2_ManCancelUntil( p, iPropHead );
    Cbs2_QueRestore( &p->pJust, iJustHead, iJustTail );
    // decide on second fanin
    Cbs2_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 );
1294
    if ( !(hLearn1 = Cbs2_ManSolve1_rec( p, Level+1 )) )
1295
        return 0;
1296
    if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) )
1297 1298
        return hLearn1;
    hClause = Cbs2_ManResolve( p, Level, hLearn0, hLearn1 );
1299
    Cbs2_ManBumpClause( p, hClause );
1300
//    Cbs2_ManPrintCube( p, Level, hClause );
1301 1302 1303 1304 1305
//    if ( Level > Cbs2_ClauseDecLevel(p, hClause) )
//        p->Pars.nBTThisNc++;
    p->Pars.nBTThis++;
    return hClause;
}
1306 1307

int Cbs2_ManSolve2_rec( Cbs2_Man_t * p, int Level )
1308 1309 1310 1311
{ 
    Gia_Obj_t * pVar;
    Cbs2_Que_t * pQue = &(p->pClauses);
    int iPropHead, iJustHead, iJustTail;
1312
    int hClause, hLearn0, hLearn1, iVar, iDecLit, iDecLit2;
1313 1314 1315
    int iPropHeadOld = p->pProp.iHead;
    // propagate assignments
    assert( !Cbs2_QueIsEmpty(&p->pProp) );
1316
    if ( (hClause = Cbs2_ManPropagate2( p, Level )) )
1317 1318 1319 1320 1321
        return hClause;
    // check for satisfying assignment
    assert( Cbs2_QueIsEmpty(&p->pProp) );
//    if ( Cbs2_QueIsEmpty(&p->pJust) )
//        return 0;
1322
    if ( Cbs2_ManUpdateFrontier(p, iPropHeadOld, &iDecLit2) )
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
        return 0;
    // quit using resource limits
    p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead );
    if ( Cbs2_ManCheckLimits( p ) )
        return 0;
    // remember the state before branching
    iPropHead = p->pProp.iHead;
//    Cbs2_QueStore( &p->pJust, &iJustHead, &iJustTail );
    iJustHead = p->pJust.iHead;
    iJustTail = p->pJust.iTail;
    // find the decision variable
1334

1335 1336 1337 1338
    assert( p->Pars.fUseHighest );
    iVar = Cbs2_ManDecideHighest( p );
    pVar = Gia_ManObj( p->pAig, iVar );
    assert( Cbs2_VarIsJust(p, pVar, iVar) );
1339 1340
    // chose decision variable using fanout count
    if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) )
1341
//    if ( Vec_IntEntry(&p->vActivity, Gia_ObjFaninId0(pVar, iVar)) > Vec_IntEntry(&p->vActivity, Gia_ObjFaninId1(pVar, iVar)) )
1342
        iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar));
1343
    else
1344
        iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar));
1345 1346 1347

    //iDecLit = iDecLit2;

1348
    // decide on first fanin
1349
    Cbs2_ManAssign( p, iDecLit, Level+1, 0, 0 );
1350
    if ( !(hLearn0 = Cbs2_ManSolve2_rec( p, Level+1 )) )
1351
        return 0;
1352
    if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) )
1353 1354 1355 1356
        return hLearn0;
    Cbs2_ManCancelUntil( p, iPropHead );
    Cbs2_QueRestore( &p->pJust, iJustHead, iJustTail );
    // decide on second fanin
1357
    Cbs2_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 );
1358
    if ( !(hLearn1 = Cbs2_ManSolve2_rec( p, Level+1 )) )
1359
        return 0;
1360
    if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) )
1361 1362
        return hLearn1;
    hClause = Cbs2_ManResolve( p, Level, hLearn0, hLearn1 );
1363
    Cbs2_ManBumpClause( p, hClause );
1364
    //Cbs2_ManPrintCube( p, Level, hClause );
1365 1366 1367 1368 1369
//    if ( Level > Cbs2_ClauseDecLevel(p, hClause) )
//        p->Pars.nBTThisNc++;
    p->Pars.nBTThis++;
    return hClause;
}
1370 1371 1372 1373 1374

int Cbs2_ManSolve_rec( Cbs2_Man_t * p, int Level )
{ 
    return p->Pars.fUseFanout ? Cbs2_ManSolve2_rec(p, Level) : Cbs2_ManSolve1_rec(p, Level);
}
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388

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

  Synopsis    [Looking for a satisfying assignment of the node.]

  Description [Assumes that each node has flag pObj->fMark0 set to 0.
  Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided.
  The node may be complemented. ]
               
  SideEffects [The two procedures differ in the CEX format.]

  SeeAlso     []

***********************************************************************/
1389
int Cbs2_ManSolve( Cbs2_Man_t * p, int iLit )
1390 1391 1392 1393 1394 1395
{
    int RetValue = 0;
    assert( !p->pProp.iHead && !p->pProp.iTail );
    assert( !p->pJust.iHead && !p->pJust.iTail );
    assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 );
    p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0;
1396
    Cbs2_ManAssign( p, iLit, 0, 0, 0 );
1397 1398 1399 1400 1401
    if ( !Cbs2_ManSolve_rec(p, 0) && !Cbs2_ManCheckLimits(p) )
        Cbs2_ManSaveModel( p, p->vModel );
    else
        RetValue = 1;
    Cbs2_ManCancelUntil( p, 0 );
1402
    Cbs2_ManCleanWatch( p );
1403
    Cbs2_ManBumpClean( p );
1404 1405 1406 1407 1408 1409 1410 1411
    p->pJust.iHead = p->pJust.iTail = 0;
    p->pClauses.iHead = p->pClauses.iTail = 1;
    p->Pars.nBTTotal += p->Pars.nBTThis;
    p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
    if ( Cbs2_ManCheckLimits( p ) )
        RetValue = -1;
    return RetValue;
}
1412
int Cbs2_ManSolve2( Cbs2_Man_t * p, int iLit, int iLit2 )
1413 1414 1415 1416 1417 1418
{
    int RetValue = 0;
    assert( !p->pProp.iHead && !p->pProp.iTail );
    assert( !p->pJust.iHead && !p->pJust.iTail );
    assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 );
    p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0;
1419 1420 1421
    Cbs2_ManAssign( p, iLit, 0, 0, 0 );
    if ( iLit2 ) 
    Cbs2_ManAssign( p, iLit2, 0, 0, 0 );
1422 1423 1424 1425 1426
    if ( !Cbs2_ManSolve_rec(p, 0) && !Cbs2_ManCheckLimits(p) )
        Cbs2_ManSaveModelAll( p, p->vModel );
    else
        RetValue = 1;
    Cbs2_ManCancelUntil( p, 0 );
1427
    Cbs2_ManCleanWatch( p );
1428
    Cbs2_ManBumpClean( p );
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469
    p->pJust.iHead = p->pJust.iTail = 0;
    p->pClauses.iHead = p->pClauses.iTail = 1;
    p->Pars.nBTTotal += p->Pars.nBTThis;
    p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
    if ( Cbs2_ManCheckLimits( p ) )
        RetValue = -1;
    return RetValue;
}

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

  Synopsis    [Prints statistics of the manager.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Cbs2_ManSatPrintStats( Cbs2_Man_t * p )
{
    printf( "CO = %8d  ", Gia_ManCoNum(p->pAig) );
    printf( "AND = %8d  ", Gia_ManAndNum(p->pAig) );
    printf( "Conf = %6d  ", p->Pars.nBTLimit );
    printf( "JustMax = %5d  ", p->Pars.nJustLimit );
    printf( "\n" );
    printf( "Unsat calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
        p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
    ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal );
    printf( "Sat   calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
        p->nSatSat,   p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
    ABC_PRTP( "Time", p->timeSatSat,   p->timeTotal );
    printf( "Undef calls %6d  (%6.2f %%)   Ave conf = %8.1f   ", 
        p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
    ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal );
    ABC_PRT( "Total time", p->timeTotal );
}

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

1470 1471 1472 1473 1474 1475 1476 1477 1478
  Synopsis    [Create fanout.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494
void Cbs2_ObjPrintFanouts( Cbs2_Man_t * p, int iObj )
{
    int iFanLit;
    printf( "Fanouts of node %d: ", iObj );
    Cbs2_ObjForEachFanout( p, iObj, iFanLit )
        printf( "%d ", Abc_Lit2Var(iFanLit) );
    printf( "\n" );
}

void Cbs2_ManPrintFanouts( Cbs2_Man_t * p )
{
    Gia_Obj_t * pObj; int iObj;
    Gia_ManForEachObj( p->pAig, pObj, iObj )
        if ( Vec_IntEntry(&p->vFanout0, iObj) )
            Cbs2_ObjPrintFanouts( p, iObj );
}
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
void Cbs2_ObjCreateFanout( Cbs2_Man_t * p, int iObj, int iFan0, int iFan1 )
{
    Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 0), Vec_IntEntry(&p->vFanout0, iFan0) );
    Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 1), Vec_IntEntry(&p->vFanout0, iFan1) );
    Vec_IntWriteEntry( &p->vFanout0, iFan0, Abc_Var2Lit(iObj, 0) );
    Vec_IntWriteEntry( &p->vFanout0, iFan1, Abc_Var2Lit(iObj, 1) );
}
void Cbs2_ObjDeleteFanout( Cbs2_Man_t * p, int iObj )
{
    Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 0), 0 );
    Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 1), 0 );
    Vec_IntWriteEntry( &p->vFanout0, iObj, 0 );
}
void Cbs2_ManCreateFanout_rec( Cbs2_Man_t * p, int iObj )
{
1510 1511 1512 1513 1514
    Gia_Obj_t * pObj; int iFan0, iFan1;
    if ( !iObj || Gia_ObjIsTravIdCurrentId(p->pAig, iObj) )
        return;
    Gia_ObjSetTravIdCurrentId(p->pAig, iObj);
    pObj = Gia_ManObj(p->pAig, iObj);
1515 1516 1517 1518 1519
    if ( Gia_ObjIsCi(pObj) )
        return;
    assert( Gia_ObjIsAnd(pObj) );
    iFan0 = Gia_ObjFaninId0(pObj, iObj);
    iFan1 = Gia_ObjFaninId1(pObj, iObj);
1520 1521
    Cbs2_ManCreateFanout_rec( p, iFan0 );
    Cbs2_ManCreateFanout_rec( p, iFan1 );
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549
    Cbs2_ObjCreateFanout( p, iObj, iFan0, iFan1 ); 
}
void Cbs2_ManDeleteFanout_rec( Cbs2_Man_t * p, int iObj )
{
    Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan0, iFan1;
    Cbs2_ObjDeleteFanout( p, iObj ); 
    if ( Gia_ObjIsCi(pObj) )
        return;
    assert( Gia_ObjIsAnd(pObj) );
    iFan0 = Gia_ObjFaninId0(pObj, iObj);
    iFan1 = Gia_ObjFaninId1(pObj, iObj);
    if ( Vec_IntEntry(&p->vFanout0, iFan0) )  Cbs2_ManDeleteFanout_rec( p, iFan0 );
    if ( Vec_IntEntry(&p->vFanout0, iFan1) )  Cbs2_ManDeleteFanout_rec( p, iFan1 );
}
void Cbs2_ManCheckFanouts( Cbs2_Man_t * p )
{
    Gia_Obj_t * pObj;
    int iObj;
    Gia_ManForEachObj( p->pAig, pObj, iObj )
    {
        assert( Vec_IntEntry(&p->vFanout0, iObj) == 0 );
        assert( Vec_IntEntry(&p->vFanoutN, Abc_Var2Lit(iObj, 0)) == 0 );
        assert( Vec_IntEntry(&p->vFanoutN, Abc_Var2Lit(iObj, 1)) == 0 );
    }
}

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

1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572
  Synopsis    [Procedure to test the new SAT solver.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose )
{
    extern void Gia_ManCollectTest( Gia_Man_t * pAig );
    extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
    Cbs2_Man_t * p; 
    Vec_Int_t * vCex, * vVisit, * vCexStore;
    Vec_Str_t * vStatus;
    Gia_Obj_t * pRoot; 
    int i, status;
    abctime clk, clkTotal = Abc_Clock();
    assert( Gia_ManRegNum(pAig) == 0 );
//    Gia_ManCollectTest( pAig );
    // prepare AIG
    Gia_ManCreateRefs( pAig );
1573
    //Gia_ManLevelNum( pAig );
1574 1575
    //Gia_ManCleanMark0( pAig );
    //Gia_ManCleanMark1( pAig );
1576
    //Gia_ManFillValue( pAig ); // maps nodes into trail ids
1577
    //Gia_ManSetPhase( pAig ); // maps nodes into trail ids
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
    // create logic network
    p = Cbs2_ManAlloc( pAig );
    p->Pars.nBTLimit = nConfs;
    // create resulting data-structures
    vStatus   = Vec_StrAlloc( Gia_ManPoNum(pAig) );
    vCexStore = Vec_IntAlloc( 10000 );
    vVisit    = Vec_IntAlloc( 100 );
    vCex      = Cbs2_ReadModel( p );
    // solve for each output
    Gia_ManForEachCo( pAig, pRoot, i )
    {
1589
        //printf( "\nOutput %d\n", i );
1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609

        Vec_IntClear( vCex );
        if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) )
        {
            if ( Gia_ObjFaninC0(pRoot) )
            {
//                printf( "Constant 1 output of SRM!!!\n" );
                Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example
                Vec_StrPush( vStatus, 0 );
            }
            else
            {
//                printf( "Constant 0 output of SRM!!!\n" );
                Vec_StrPush( vStatus, 1 );
            }
            continue;
        }
        clk = Abc_Clock();
        p->Pars.fUseHighest = 1;
        p->Pars.fUseLowest  = 0;
1610

1611 1612
        Gia_ManIncrementTravId( pAig );
        Cbs2_ManCreateFanout_rec( p, Gia_ObjFaninId0p(pAig, pRoot) );
1613 1614
        //Cbs2_ManPrintFanouts( p );

1615
        status = Cbs2_ManSolve( p, Gia_ObjFaninLit0p(pAig, pRoot) );
1616 1617 1618 1619 1620
        //printf( "\n" );

        Cbs2_ManDeleteFanout_rec( p, Gia_ObjFaninId0p(pAig, pRoot) );
        //Cbs2_ManCheckFanouts( p );

1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
/*
        if ( status == -1 )
        {
            p->Pars.fUseHighest = 0;
            p->Pars.fUseLowest  = 1;
            status = Cbs2_ManSolve( p, Gia_ObjChild0(pRoot) );
        }
*/
        Vec_StrPush( vStatus, (char)status );
        if ( status == -1 )
        {
            p->nSatUndec++;
            p->nConfUndec += p->Pars.nBTThis;
            Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
            p->timeSatUndec += Abc_Clock() - clk;
            continue;
        }
        if ( status == 1 )
        {
            p->nSatUnsat++;
            p->nConfUnsat += p->Pars.nBTThis;
            p->timeSatUnsat += Abc_Clock() - clk;
            continue;
        }
        p->nSatSat++;
        p->nConfSat += p->Pars.nBTThis;
//        Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
        Cec_ManSatAddToStore( vCexStore, vCex, i );
        p->timeSatSat += Abc_Clock() - clk;
    }
    Vec_IntFree( vVisit );
    p->nSatTotal = Gia_ManPoNum(pAig);
    p->timeTotal = Abc_Clock() - clkTotal;
    if ( fVerbose )
        Cbs2_ManSatPrintStats( p );
1656 1657
    if ( fVerbose )
    {
1658
//    printf( "RecCalls = %8d.  RecClause = %8d.  RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro );
1659
    printf( "Prop1 = %d.  Prop2 = %d.  Prop3 = %d.  ClaConf = %d.   FailJ = %d.  FailC = %d.   ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] );
1660
    Abc_PrintTime( 1, "JFront", p->timeJFront );
1661
    }
1662

1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
    Cbs2_ManStop( p );
    *pvStatus = vStatus;

//    printf( "Total number of cex literals = %d. (Ave = %d)\n", 
//         Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, 
//        (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat );
    return vCexStore;
}


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


ABC_NAMESPACE_IMPL_END