From 59348e227c7ec2bc7ea9b814d9a963098b1df9ef Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Fri, 3 Mar 2017 15:16:05 -0800 Subject: Clone of the main SAT solver to eneable independent work. --- src/sat/bsat/satSolver3.c | 2299 +++++++++++++++++++++++++++++++++++++++++++++ src/sat/bsat/satSolver3.h | 622 ++++++++++++ 2 files changed, 2921 insertions(+) create mode 100644 src/sat/bsat/satSolver3.c create mode 100644 src/sat/bsat/satSolver3.h (limited to 'src/sat') diff --git a/src/sat/bsat/satSolver3.c b/src/sat/bsat/satSolver3.c new file mode 100644 index 00000000..b61ce96c --- /dev/null +++ b/src/sat/bsat/satSolver3.c @@ -0,0 +1,2299 @@ +/************************************************************************************************** +MiniSat -- Copyright (c) 2005, Niklas Sorensson +http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ +// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko + +#include +#include +#include +#include + +#include "satSolver3.h" + +ABC_NAMESPACE_IMPL_START + +#define SAT_USE_ANALYZE_FINAL + +//================================================================================================= +// Debug: + +//#define VERBOSEDEBUG + +// For derivation output (verbosity level 2) +#define L_IND "%-*d" +#define L_ind sat_solver3_dl(s)*2+2,sat_solver3_dl(s) +#define L_LIT "%sx%d" +#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p)) + +// Just like 'assert()' but expression will be evaluated in the release version as well. +static inline void check(int expr) { assert(expr); } + +static void printlits(lit* begin, lit* end) +{ + int i; + for (i = 0; i < end - begin; i++) + printf(L_LIT" ",L_lit(begin[i])); +} + +//================================================================================================= +// Random numbers: + + +// Returns a random float 0 <= x < 1. Seed must never be 0. +static inline double drand(double* seed) { + int q; + *seed *= 1389796; + q = (int)(*seed / 2147483647); + *seed -= (double)q * 2147483647; + return *seed / 2147483647; } + + +// Returns a random integer 0 <= x < size. Seed must never be 0. +static inline int irand(double* seed, int size) { + return (int)(drand(seed) * size); } + + +//================================================================================================= +// Variable datatype + minor functions: + +static const int var0 = 1; +static const int var1 = 0; +static const int varX = 3; + +struct varinfo_t +{ + unsigned val : 2; // variable value + unsigned pol : 1; // last polarity + unsigned tag : 1; // conflict analysis tag + unsigned lev : 28; // variable level +}; + +static inline int var_level (sat_solver3* s, int v) { return s->levels[v]; } +static inline int var_value (sat_solver3* s, int v) { return s->assigns[v]; } +static inline int var_polar (sat_solver3* s, int v) { return s->polarity[v]; } + +static inline void var_set_level (sat_solver3* s, int v, int lev) { s->levels[v] = lev; } +static inline void var_set_value (sat_solver3* s, int v, int val) { s->assigns[v] = val; } +static inline void var_set_polar (sat_solver3* s, int v, int pol) { s->polarity[v] = pol; } + +// variable tags +static inline int var_tag (sat_solver3* s, int v) { return s->tags[v]; } +static inline void var_set_tag (sat_solver3* s, int v, int tag) { + assert( tag > 0 && tag < 16 ); + if ( s->tags[v] == 0 ) + veci_push( &s->tagged, v ); + s->tags[v] = tag; +} +static inline void var_add_tag (sat_solver3* s, int v, int tag) { + assert( tag > 0 && tag < 16 ); + if ( s->tags[v] == 0 ) + veci_push( &s->tagged, v ); + s->tags[v] |= tag; +} +static inline void solver2_clear_tags(sat_solver3* s, int start) { + int i, * tagged = veci_begin(&s->tagged); + for (i = start; i < veci_size(&s->tagged); i++) + s->tags[tagged[i]] = 0; + veci_resize(&s->tagged,start); +} + +int sat_solver3_get_var_value(sat_solver3* s, int v) +{ + if ( var_value(s, v) == var0 ) + return l_False; + if ( var_value(s, v) == var1 ) + return l_True; + if ( var_value(s, v) == varX ) + return l_Undef; + assert( 0 ); + return 0; +} + +//================================================================================================= +// Simple helpers: + +static inline int sat_solver3_dl(sat_solver3* s) { return veci_size(&s->trail_lim); } +static inline veci* sat_solver3_read_wlist(sat_solver3* s, lit l) { return &s->wlists[l]; } + +//================================================================================================= +// Variable order functions: + +static inline void order_update(sat_solver3* s, int v) // updateorder +{ + int* orderpos = s->orderpos; + int* heap = veci_begin(&s->order); + int i = orderpos[v]; + int x = heap[i]; + int parent = (i - 1) / 2; + + assert(s->orderpos[v] != -1); + + while (i != 0 && s->activity[x] > s->activity[heap[parent]]){ + heap[i] = heap[parent]; + orderpos[heap[i]] = i; + i = parent; + parent = (i - 1) / 2; + } + + heap[i] = x; + orderpos[x] = i; +} + +static inline void order_assigned(sat_solver3* s, int v) +{ +} + +static inline void order_unassigned(sat_solver3* s, int v) // undoorder +{ + int* orderpos = s->orderpos; + if (orderpos[v] == -1){ + orderpos[v] = veci_size(&s->order); + veci_push(&s->order,v); + order_update(s,v); +//printf( "+%d ", v ); + } +} + +static inline int order_select(sat_solver3* s, float random_var_freq) // selectvar +{ + int* heap = veci_begin(&s->order); + int* orderpos = s->orderpos; + // Random decision: + if (drand(&s->random_seed) < random_var_freq){ + int next = irand(&s->random_seed,s->size); + assert(next >= 0 && next < s->size); + if (var_value(s, next) == varX) + return next; + } + // Activity based decision: + while (veci_size(&s->order) > 0){ + int next = heap[0]; + int size = veci_size(&s->order)-1; + int x = heap[size]; + veci_resize(&s->order,size); + orderpos[next] = -1; + if (size > 0){ + int i = 0; + int child = 1; + while (child < size){ + + if (child+1 < size && s->activity[heap[child]] < s->activity[heap[child+1]]) + child++; + assert(child < size); + if (s->activity[x] >= s->activity[heap[child]]) + break; + + heap[i] = heap[child]; + orderpos[heap[i]] = i; + i = child; + child = 2 * child + 1; + } + heap[i] = x; + orderpos[heap[i]] = i; + } + if (var_value(s, next) == varX) + return next; + } + return var_Undef; +} + +void sat_solver3_set_var_activity(sat_solver3* s, int * pVars, int nVars) +{ + int i; + assert( s->VarActType == 1 ); + for (i = 0; i < s->size; i++) + s->activity[i] = 0; + s->var_inc = Abc_Dbl2Word(1); + for ( i = 0; i < nVars; i++ ) + { + int iVar = pVars ? pVars[i] : i; + s->activity[iVar] = Abc_Dbl2Word(nVars-i); + order_update( s, iVar ); + } +} + +//================================================================================================= +// variable activities + +static inline void solver_init_activities(sat_solver3* s) +{ + // variable activities + s->VarActType = 0; + if ( s->VarActType == 0 ) + { + s->var_inc = (1 << 5); + s->var_decay = -1; + } + else if ( s->VarActType == 1 ) + { + s->var_inc = Abc_Dbl2Word(1.0); + s->var_decay = Abc_Dbl2Word(1.0 / 0.95); + } + else if ( s->VarActType == 2 ) + { + s->var_inc = Xdbl_FromDouble(1.0); + s->var_decay = Xdbl_FromDouble(1.0 / 0.950); + } + else assert(0); + + // clause activities + s->ClaActType = 0; + if ( s->ClaActType == 0 ) + { + s->cla_inc = (1 << 11); + s->cla_decay = -1; + } + else + { + s->cla_inc = 1; + s->cla_decay = (float)(1 / 0.999); + } +} + +static inline void act_var_rescale(sat_solver3* s) +{ + if ( s->VarActType == 0 ) + { + word* activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] >>= 19; + s->var_inc >>= 19; + s->var_inc = Abc_MaxInt( (unsigned)s->var_inc, (1<<4) ); + } + else if ( s->VarActType == 1 ) + { + double* activity = (double*)s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] *= 1e-100; + s->var_inc = Abc_Dbl2Word( Abc_Word2Dbl(s->var_inc) * 1e-100 ); + //printf( "Rescaling var activity...\n" ); + } + else if ( s->VarActType == 2 ) + { + xdbl * activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] = Xdbl_Div( activity[i], 200 ); // activity[i] / 2^200 + s->var_inc = Xdbl_Div( s->var_inc, 200 ); + } + else assert(0); +} +static inline void act_var_bump(sat_solver3* s, int v) +{ + if ( s->VarActType == 0 ) + { + s->activity[v] += s->var_inc; + if ((unsigned)s->activity[v] & 0x80000000) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 1 ) + { + double act = Abc_Word2Dbl(s->activity[v]) + Abc_Word2Dbl(s->var_inc); + s->activity[v] = Abc_Dbl2Word(act); + if (act > 1e100) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 2 ) + { + s->activity[v] = Xdbl_Add( s->activity[v], s->var_inc ); + if (s->activity[v] > ABC_CONST(0x014c924d692ca61b)) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else assert(0); +} +static inline void act_var_bump_global(sat_solver3* s, int v) +{ + if ( !s->pGlobalVars || !s->pGlobalVars[v] ) + return; + if ( s->VarActType == 0 ) + { + s->activity[v] += (int)((unsigned)s->var_inc * 3); + if (s->activity[v] & 0x80000000) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 1 ) + { + double act = Abc_Word2Dbl(s->activity[v]) + Abc_Word2Dbl(s->var_inc) * 3.0; + s->activity[v] = Abc_Dbl2Word(act); + if ( act > 1e100) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 2 ) + { + s->activity[v] = Xdbl_Add( s->activity[v], Xdbl_Mul(s->var_inc, Xdbl_FromDouble(3.0)) ); + if (s->activity[v] > ABC_CONST(0x014c924d692ca61b)) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else assert( 0 ); +} +static inline void act_var_bump_factor(sat_solver3* s, int v) +{ + if ( !s->factors ) + return; + if ( s->VarActType == 0 ) + { + s->activity[v] += (int)((unsigned)s->var_inc * (float)s->factors[v]); + if (s->activity[v] & 0x80000000) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 1 ) + { + double act = Abc_Word2Dbl(s->activity[v]) + Abc_Word2Dbl(s->var_inc) * s->factors[v]; + s->activity[v] = Abc_Dbl2Word(act); + if ( act > 1e100) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 2 ) + { + s->activity[v] = Xdbl_Add( s->activity[v], Xdbl_Mul(s->var_inc, Xdbl_FromDouble(s->factors[v])) ); + if (s->activity[v] > ABC_CONST(0x014c924d692ca61b)) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else assert( 0 ); +} + +static inline void act_var_decay(sat_solver3* s) +{ + if ( s->VarActType == 0 ) + s->var_inc += (s->var_inc >> 4); + else if ( s->VarActType == 1 ) + s->var_inc = Abc_Dbl2Word( Abc_Word2Dbl(s->var_inc) * Abc_Word2Dbl(s->var_decay) ); + else if ( s->VarActType == 2 ) + s->var_inc = Xdbl_Mul(s->var_inc, s->var_decay); + else assert(0); +} + +// clause activities +static inline void act_clause_rescale(sat_solver3* s) +{ + if ( s->ClaActType == 0 ) + { + unsigned* activity = (unsigned *)veci_begin(&s->act_clas); + int i; + for (i = 0; i < veci_size(&s->act_clas); i++) + activity[i] >>= 14; + s->cla_inc >>= 14; + s->cla_inc = Abc_MaxInt( s->cla_inc, (1<<10) ); + } + else + { + float* activity = (float *)veci_begin(&s->act_clas); + int i; + for (i = 0; i < veci_size(&s->act_clas); i++) + activity[i] *= (float)1e-20; + s->cla_inc *= (float)1e-20; + } +} +static inline void act_clause_bump(sat_solver3* s, clause *c) +{ + if ( s->ClaActType == 0 ) + { + unsigned* act = (unsigned *)veci_begin(&s->act_clas) + c->lits[c->size]; + *act += s->cla_inc; + if ( *act & 0x80000000 ) + act_clause_rescale(s); + } + else + { + float* act = (float *)veci_begin(&s->act_clas) + c->lits[c->size]; + *act += s->cla_inc; + if (*act > 1e20) + act_clause_rescale(s); + } +} +static inline void act_clause_decay(sat_solver3* s) +{ + if ( s->ClaActType == 0 ) + s->cla_inc += (s->cla_inc >> 10); + else + s->cla_inc *= s->cla_decay; +} + + +//================================================================================================= +// Sorting functions (sigh): + +static inline void selectionsort(void** array, int size, int(*comp)(const void *, const void *)) +{ + int i, j, best_i; + void* tmp; + + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (comp(array[j], array[best_i]) < 0) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} + +static void sortrnd(void** array, int size, int(*comp)(const void *, const void *), double* seed) +{ + if (size <= 15) + selectionsort(array, size, comp); + + else{ + void* pivot = array[irand(seed, size)]; + void* tmp; + int i = -1; + int j = size; + + for(;;){ + do i++; while(comp(array[i], pivot)<0); + do j--; while(comp(pivot, array[j])<0); + + if (i >= j) break; + + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + + sortrnd(array , i , comp, seed); + sortrnd(&array[i], size-i, comp, seed); + } +} + +//================================================================================================= +// Clause functions: + +static inline int sat_clause_compute_lbd( sat_solver3* s, clause* c ) +{ + int i, lev, minl = 0, lbd = 0; + for (i = 0; i < (int)c->size; i++) + { + lev = var_level(s, lit_var(c->lits[i])); + if ( !(minl & (1 << (lev & 31))) ) + { + minl |= 1 << (lev & 31); + lbd++; +// printf( "%d ", lev ); + } + } +// printf( " -> %d\n", lbd ); + return lbd; +} + +/* pre: size > 1 && no variable occurs twice + */ +int sat_solver3_clause_new(sat_solver3* s, lit* begin, lit* end, int learnt) +{ + int fUseBinaryClauses = 1; + int size; + clause* c; + int h; + + assert(end - begin > 1); + assert(learnt >= 0 && learnt < 2); + size = end - begin; + + // do not allocate memory for the two-literal problem clause + if ( fUseBinaryClauses && size == 2 && !learnt ) + { + veci_push(sat_solver3_read_wlist(s,lit_neg(begin[0])),(clause_from_lit(begin[1]))); + veci_push(sat_solver3_read_wlist(s,lit_neg(begin[1])),(clause_from_lit(begin[0]))); + s->stats.clauses++; + s->stats.clauses_literals += size; + return 0; + } + + // create new clause +// h = Vec_SetAppend( &s->Mem, NULL, size + learnt + 1 + 1 ) << 1; + h = Sat_MemAppend( &s->Mem, begin, size, learnt, 0 ); + assert( !(h & 1) ); + if ( s->hLearnts == -1 && learnt ) + s->hLearnts = h; + if (learnt) + { + c = clause_read( s, h ); + c->lbd = sat_clause_compute_lbd( s, c ); + assert( clause_id(c) == veci_size(&s->act_clas) ); +// veci_push(&s->learned, h); +// act_clause_bump(s,clause_read(s, h)); + if ( s->ClaActType == 0 ) + veci_push(&s->act_clas, (1<<10)); + else + veci_push(&s->act_clas, s->cla_inc); + s->stats.learnts++; + s->stats.learnts_literals += size; + } + else + { + s->stats.clauses++; + s->stats.clauses_literals += size; + } + + assert(begin[0] >= 0); + assert(begin[0] < s->size*2); + assert(begin[1] >= 0); + assert(begin[1] < s->size*2); + + assert(lit_neg(begin[0]) < s->size*2); + assert(lit_neg(begin[1]) < s->size*2); + + //veci_push(sat_solver3_read_wlist(s,lit_neg(begin[0])),c); + //veci_push(sat_solver3_read_wlist(s,lit_neg(begin[1])),c); + veci_push(sat_solver3_read_wlist(s,lit_neg(begin[0])),(size > 2 ? h : clause_from_lit(begin[1]))); + veci_push(sat_solver3_read_wlist(s,lit_neg(begin[1])),(size > 2 ? h : clause_from_lit(begin[0]))); + + return h; +} + + +//================================================================================================= +// Minor (solver) functions: + +static inline int sat_solver3_enqueue(sat_solver3* s, lit l, int from) +{ + int v = lit_var(l); + if ( s->pFreqs[v] == 0 ) +// { + s->pFreqs[v] = 1; +// s->nVarUsed++; +// } + +#ifdef VERBOSEDEBUG + printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); +#endif + if (var_value(s, v) != varX) + return var_value(s, v) == lit_sign(l); + else{ +/* + if ( s->pCnfFunc ) + { + if ( lit_sign(l) ) + { + if ( (s->loads[v] & 1) == 0 ) + { + s->loads[v] ^= 1; + s->pCnfFunc( s->pCnfMan, l ); + } + } + else + { + if ( (s->loads[v] & 2) == 0 ) + { + s->loads[v] ^= 2; + s->pCnfFunc( s->pCnfMan, l ); + } + } + } +*/ + // New fact -- store it. +#ifdef VERBOSEDEBUG + printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); +#endif + var_set_value(s, v, lit_sign(l)); + var_set_level(s, v, sat_solver3_dl(s)); + s->reasons[v] = from; + s->trail[s->qtail++] = l; + order_assigned(s, v); + return true; + } +} + + +static inline int sat_solver3_decision(sat_solver3* s, lit l){ + assert(s->qtail == s->qhead); + assert(var_value(s, lit_var(l)) == varX); +#ifdef VERBOSEDEBUG + printf(L_IND"assume("L_LIT") ", L_ind, L_lit(l)); + printf( "act = %.20f\n", s->activity[lit_var(l)] ); +#endif + veci_push(&s->trail_lim,s->qtail); + return sat_solver3_enqueue(s,l,0); +} + + +static void sat_solver3_canceluntil(sat_solver3* s, int level) { + int bound; + int lastLev; + int c; + + if (sat_solver3_dl(s) <= level) + return; + + assert( veci_size(&s->trail_lim) > 0 ); + bound = (veci_begin(&s->trail_lim))[level]; + lastLev = (veci_begin(&s->trail_lim))[veci_size(&s->trail_lim)-1]; + + //////////////////////////////////////// + // added to cancel all assignments +// if ( level == -1 ) +// bound = 0; + //////////////////////////////////////// + + for (c = s->qtail-1; c >= bound; c--) { + int x = lit_var(s->trail[c]); + var_set_value(s, x, varX); + s->reasons[x] = 0; + if ( c < lastLev ) + var_set_polar( s, x, !lit_sign(s->trail[c]) ); + } + //printf( "\n" ); + + for (c = s->qhead-1; c >= bound; c--) + order_unassigned(s,lit_var(s->trail[c])); + + s->qhead = s->qtail = bound; + veci_resize(&s->trail_lim,level); +} + +static void sat_solver3_canceluntil_rollback(sat_solver3* s, int NewBound) { + int c, x; + + assert( sat_solver3_dl(s) == 0 ); + assert( s->qtail == s->qhead ); + assert( s->qtail >= NewBound ); + + for (c = s->qtail-1; c >= NewBound; c--) + { + x = lit_var(s->trail[c]); + var_set_value(s, x, varX); + s->reasons[x] = 0; + } + + for (c = s->qhead-1; c >= NewBound; c--) + order_unassigned(s,lit_var(s->trail[c])); + + s->qhead = s->qtail = NewBound; +} + +static void sat_solver3_record(sat_solver3* s, veci* cls) +{ + lit* begin = veci_begin(cls); + lit* end = begin + veci_size(cls); + int h = (veci_size(cls) > 1) ? sat_solver3_clause_new(s,begin,end,1) : 0; + sat_solver3_enqueue(s,*begin,h); + assert(veci_size(cls) > 0); + if ( h == 0 ) + veci_push( &s->unit_lits, *begin ); + +/* + if (h != 0) { + act_clause_bump(s,clause_read(s, h)); + s->stats.learnts++; + s->stats.learnts_literals += veci_size(cls); + } +*/ +} + +int sat_solver3_count_assigned(sat_solver3* s) +{ + // count top-level assignments + int i, Count = 0; + assert(sat_solver3_dl(s) == 0); + for ( i = 0; i < s->size; i++ ) + if (var_value(s, i) != varX) + Count++; + return Count; +} + +static double sat_solver3_progress(sat_solver3* s) +{ + int i; + double progress = 0; + double F = 1.0 / s->size; + for (i = 0; i < s->size; i++) + if (var_value(s, i) != varX) + progress += pow(F, var_level(s, i)); + return progress / s->size; +} + +//================================================================================================= +// Major methods: + +static int sat_solver3_lit_removable(sat_solver3* s, int x, int minl) +{ + int top = veci_size(&s->tagged); + + assert(s->reasons[x] != 0); + veci_resize(&s->stack,0); + veci_push(&s->stack,x); + + while (veci_size(&s->stack)){ + int v = veci_pop(&s->stack); + assert(s->reasons[v] != 0); + if (clause_is_lit(s->reasons[v])){ + v = lit_var(clause_read_lit(s->reasons[v])); + if (!var_tag(s,v) && var_level(s, v)){ + if (s->reasons[v] != 0 && ((1 << (var_level(s, v) & 31)) & minl)){ + veci_push(&s->stack,v); + var_set_tag(s, v, 1); + }else{ + solver2_clear_tags(s, top); + return 0; + } + } + }else{ + clause* c = clause_read(s, s->reasons[v]); + lit* lits = clause_begin(c); + int i; + for (i = 1; i < clause_size(c); i++){ + int v = lit_var(lits[i]); + if (!var_tag(s,v) && var_level(s, v)){ + if (s->reasons[v] != 0 && ((1 << (var_level(s, v) & 31)) & minl)){ + veci_push(&s->stack,lit_var(lits[i])); + var_set_tag(s, v, 1); + }else{ + solver2_clear_tags(s, top); + return 0; + } + } + } + } + } + return 1; +} + + +/*_________________________________________________________________________________________________ +| +| analyzeFinal : (p : Lit) -> [void] +| +| Description: +| Specialized analysis procedure to express the final conflict in terms of assumptions. +| Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and +| stores the result in 'out_conflict'. +|________________________________________________________________________________________________@*/ +/* +void Solver::analyzeFinal(Clause* confl, bool skip_first) +{ + // -- NOTE! This code is relatively untested. Please report bugs! + conflict.clear(); + if (root_level == 0) return; + + vec& seen = analyze_seen; + for (int i = skip_first ? 1 : 0; i < confl->size(); i++){ + Var x = var((*confl)[i]); + if (level[x] > 0) + seen[x] = 1; + } + + int start = (root_level >= trail_lim.size()) ? trail.size()-1 : trail_lim[root_level]; + for (int i = start; i >= trail_lim[0]; i--){ + Var x = var(trail[i]); + if (seen[x]){ + GClause r = reason[x]; + if (r == GClause_NULL){ + assert(level[x] > 0); + conflict.push(~trail[i]); + }else{ + if (r.isLit()){ + Lit p = r.lit(); + if (level[var(p)] > 0) + seen[var(p)] = 1; + }else{ + Clause& c = *r.clause(); + for (int j = 1; j < c.size(); j++) + if (level[var(c[j])] > 0) + seen[var(c[j])] = 1; + } + } + seen[x] = 0; + } + } +} +*/ + +#ifdef SAT_USE_ANALYZE_FINAL + +static void sat_solver3_analyze_final(sat_solver3* s, int hConf, int skip_first) +{ + clause* conf = clause_read(s, hConf); + int i, j, start; + veci_resize(&s->conf_final,0); + if ( s->root_level == 0 ) + return; + assert( veci_size(&s->tagged) == 0 ); +// assert( s->tags[lit_var(p)] == l_Undef ); +// s->tags[lit_var(p)] = l_True; + for (i = skip_first ? 1 : 0; i < clause_size(conf); i++) + { + int x = lit_var(clause_begin(conf)[i]); + if (var_level(s, x) > 0) + var_set_tag(s, x, 1); + } + + start = (s->root_level >= veci_size(&s->trail_lim))? s->qtail-1 : (veci_begin(&s->trail_lim))[s->root_level]; + for (i = start; i >= (veci_begin(&s->trail_lim))[0]; i--){ + int x = lit_var(s->trail[i]); + if (var_tag(s,x)){ + if (s->reasons[x] == 0){ + assert(var_level(s, x) > 0); + veci_push(&s->conf_final,lit_neg(s->trail[i])); + }else{ + if (clause_is_lit(s->reasons[x])){ + lit q = clause_read_lit(s->reasons[x]); + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (var_level(s, lit_var(q)) > 0) + var_set_tag(s, lit_var(q), 1); + } + else{ + clause* c = clause_read(s, s->reasons[x]); + int* lits = clause_begin(c); + for (j = 1; j < clause_size(c); j++) + if (var_level(s, lit_var(lits[j])) > 0) + var_set_tag(s, lit_var(lits[j]), 1); + } + } + } + } + solver2_clear_tags(s,0); +} + +#endif + +static void sat_solver3_analyze(sat_solver3* s, int h, veci* learnt) +{ + lit* trail = s->trail; + int cnt = 0; + lit p = lit_Undef; + int ind = s->qtail-1; + lit* lits; + int i, j, minl; + veci_push(learnt,lit_Undef); + do{ + assert(h != 0); + if (clause_is_lit(h)){ + int x = lit_var(clause_read_lit(h)); + if (var_tag(s, x) == 0 && var_level(s, x) > 0){ + var_set_tag(s, x, 1); + act_var_bump(s,x); + if (var_level(s, x) == sat_solver3_dl(s)) + cnt++; + else + veci_push(learnt,clause_read_lit(h)); + } + }else{ + clause* c = clause_read(s, h); + + if (clause_learnt(c)) + act_clause_bump(s,c); + lits = clause_begin(c); + //printlits(lits,lits+clause_size(c)); printf("\n"); + for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ + int x = lit_var(lits[j]); + if (var_tag(s, x) == 0 && var_level(s, x) > 0){ + var_set_tag(s, x, 1); + act_var_bump(s,x); + // bump variables propaged by the LBD=2 clause +// if ( s->reasons[x] && clause_read(s, s->reasons[x])->lbd <= 2 ) +// act_var_bump(s,x); + if (var_level(s,x) == sat_solver3_dl(s)) + cnt++; + else + veci_push(learnt,lits[j]); + } + } + } + + while ( !var_tag(s, lit_var(trail[ind--])) ); + + p = trail[ind+1]; + h = s->reasons[lit_var(p)]; + cnt--; + + }while (cnt > 0); + + *veci_begin(learnt) = lit_neg(p); + + lits = veci_begin(learnt); + minl = 0; + for (i = 1; i < veci_size(learnt); i++){ + int lev = var_level(s, lit_var(lits[i])); + minl |= 1 << (lev & 31); + } + + // simplify (full) + for (i = j = 1; i < veci_size(learnt); i++){ + if (s->reasons[lit_var(lits[i])] == 0 || !sat_solver3_lit_removable(s,lit_var(lits[i]),minl)) + lits[j++] = lits[i]; + } + + // update size of learnt + statistics + veci_resize(learnt,j); + s->stats.tot_literals += j; + + + // clear tags + solver2_clear_tags(s,0); + +#ifdef DEBUG + for (i = 0; i < s->size; i++) + assert(!var_tag(s, i)); +#endif + +#ifdef VERBOSEDEBUG + printf(L_IND"Learnt {", L_ind); + for (i = 0; i < veci_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i])); +#endif + if (veci_size(learnt) > 1){ + int max_i = 1; + int max = var_level(s, lit_var(lits[1])); + lit tmp; + + for (i = 2; i < veci_size(learnt); i++) + if (var_level(s, lit_var(lits[i])) > max){ + max = var_level(s, lit_var(lits[i])); + max_i = i; + } + + tmp = lits[1]; + lits[1] = lits[max_i]; + lits[max_i] = tmp; + } +#ifdef VERBOSEDEBUG + { + int lev = veci_size(learnt) > 1 ? var_level(s, lit_var(lits[1])) : 0; + printf(" } at level %d\n", lev); + } +#endif +} + +//#define TEST_CNF_LOAD + +int sat_solver3_propagate(sat_solver3* s) +{ + int hConfl = 0; + lit* lits; + lit false_lit; + + //printf("sat_solver3_propagate\n"); + while (hConfl == 0 && s->qtail - s->qhead > 0){ + lit p = s->trail[s->qhead++]; + +#ifdef TEST_CNF_LOAD + int v = lit_var(p); + if ( s->pCnfFunc ) + { + if ( lit_sign(p) ) + { + if ( (s->loads[v] & 1) == 0 ) + { + s->loads[v] ^= 1; + s->pCnfFunc( s->pCnfMan, p ); + } + } + else + { + if ( (s->loads[v] & 2) == 0 ) + { + s->loads[v] ^= 2; + s->pCnfFunc( s->pCnfMan, p ); + } + } + } + { +#endif + + veci* ws = sat_solver3_read_wlist(s,p); + int* begin = veci_begin(ws); + int* end = begin + veci_size(ws); + int*i, *j; + + s->stats.propagations++; +// s->simpdb_props--; + + //printf("checking lit %d: "L_LIT"\n", veci_size(ws), L_lit(p)); + for (i = j = begin; i < end; ){ + if (clause_is_lit(*i)){ + + int Lit = clause_read_lit(*i); + if (var_value(s, lit_var(Lit)) == lit_sign(Lit)){ + *j++ = *i++; + continue; + } + + *j++ = *i; + if (!sat_solver3_enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ + hConfl = s->hBinary; + (clause_begin(s->binary))[1] = lit_neg(p); + (clause_begin(s->binary))[0] = clause_read_lit(*i++); + // Copy the remaining watches: + while (i < end) + *j++ = *i++; + } + }else{ + + clause* c = clause_read(s,*i); + lits = clause_begin(c); + + // Make sure the false literal is data[1]: + false_lit = lit_neg(p); + if (lits[0] == false_lit){ + lits[0] = lits[1]; + lits[1] = false_lit; + } + assert(lits[1] == false_lit); + + // If 0th watch is true, then clause is already satisfied. + if (var_value(s, lit_var(lits[0])) == lit_sign(lits[0])) + *j++ = *i; + else{ + // Look for new watch: + lit* stop = lits + clause_size(c); + lit* k; + for (k = lits + 2; k < stop; k++){ + if (var_value(s, lit_var(*k)) != !lit_sign(*k)){ + lits[1] = *k; + *k = false_lit; + veci_push(sat_solver3_read_wlist(s,lit_neg(lits[1])),*i); + goto next; } + } + + *j++ = *i; + // Clause is unit under assignment: + if ( c->lrn ) + c->lbd = sat_clause_compute_lbd(s, c); + if (!sat_solver3_enqueue(s,lits[0], *i)){ + hConfl = *i++; + // Copy the remaining watches: + while (i < end) + *j++ = *i++; + } + } + } + next: + i++; + } + + s->stats.inspects += j - veci_begin(ws); + veci_resize(ws,j - veci_begin(ws)); +#ifdef TEST_CNF_LOAD + } +#endif + } + + return hConfl; +} + +//================================================================================================= +// External solver functions: + +sat_solver3* sat_solver3_new(void) +{ + sat_solver3* s = (sat_solver3*)ABC_CALLOC( char, sizeof(sat_solver3)); + +// Vec_SetAlloc_(&s->Mem, 15); + Sat_MemAlloc_(&s->Mem, 17); + s->hLearnts = -1; + s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); + s->binary = clause_read( s, s->hBinary ); + + s->nLearntStart = LEARNT_MAX_START_DEFAULT; // starting learned clause limit + s->nLearntDelta = LEARNT_MAX_INCRE_DEFAULT; // delta of learned clause limit + s->nLearntRatio = LEARNT_MAX_RATIO_DEFAULT; // ratio of learned clause limit + s->nLearntMax = s->nLearntStart; + + // initialize vectors + veci_new(&s->order); + veci_new(&s->trail_lim); + veci_new(&s->tagged); +// veci_new(&s->learned); + veci_new(&s->act_clas); + veci_new(&s->stack); +// veci_new(&s->model); + veci_new(&s->unit_lits); + veci_new(&s->temp_clause); + veci_new(&s->conf_final); + + // initialize arrays + s->wlists = 0; + s->activity = 0; + s->orderpos = 0; + s->reasons = 0; + s->trail = 0; + + // initialize other vars + s->size = 0; + s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + solver_init_activities(s); + veci_new(&s->act_vars); + + s->root_level = 0; +// s->simpdb_assigns = 0; +// s->simpdb_props = 0; + s->random_seed = 91648253; + s->progress_estimate = 0; +// s->binary = (clause*)ABC_ALLOC( char, sizeof(clause) + sizeof(lit)*2); +// s->binary->size_learnt = (2 << 1); + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; + return s; +} + +sat_solver3* zsat_solver3_new_seed(double seed) +{ + sat_solver3* s = (sat_solver3*)ABC_CALLOC( char, sizeof(sat_solver3)); + +// Vec_SetAlloc_(&s->Mem, 15); + Sat_MemAlloc_(&s->Mem, 15); + s->hLearnts = -1; + s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); + s->binary = clause_read( s, s->hBinary ); + + s->nLearntStart = LEARNT_MAX_START_DEFAULT; // starting learned clause limit + s->nLearntDelta = LEARNT_MAX_INCRE_DEFAULT; // delta of learned clause limit + s->nLearntRatio = LEARNT_MAX_RATIO_DEFAULT; // ratio of learned clause limit + s->nLearntMax = s->nLearntStart; + + // initialize vectors + veci_new(&s->order); + veci_new(&s->trail_lim); + veci_new(&s->tagged); +// veci_new(&s->learned); + veci_new(&s->act_clas); + veci_new(&s->stack); +// veci_new(&s->model); + veci_new(&s->unit_lits); + veci_new(&s->temp_clause); + veci_new(&s->conf_final); + + // initialize arrays + s->wlists = 0; + s->activity = 0; + s->orderpos = 0; + s->reasons = 0; + s->trail = 0; + + // initialize other vars + s->size = 0; + s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + solver_init_activities(s); + veci_new(&s->act_vars); + + s->root_level = 0; +// s->simpdb_assigns = 0; +// s->simpdb_props = 0; + s->random_seed = seed; + s->progress_estimate = 0; +// s->binary = (clause*)ABC_ALLOC( char, sizeof(clause) + sizeof(lit)*2); +// s->binary->size_learnt = (2 << 1); + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; + return s; +} + +void sat_solver3_setnvars(sat_solver3* s,int n) +{ + int var; + + if (s->cap < n){ + int old_cap = s->cap; + while (s->cap < n) s->cap = s->cap*2+1; + if ( s->cap < 50000 ) + s->cap = 50000; + + s->wlists = ABC_REALLOC(veci, s->wlists, s->cap*2); +// s->vi = ABC_REALLOC(varinfo,s->vi, s->cap); + s->levels = ABC_REALLOC(int, s->levels, s->cap); + s->assigns = ABC_REALLOC(char, s->assigns, s->cap); + s->polarity = ABC_REALLOC(char, s->polarity, s->cap); + s->tags = ABC_REALLOC(char, s->tags, s->cap); + s->loads = ABC_REALLOC(char, s->loads, s->cap); + s->activity = ABC_REALLOC(word, s->activity, s->cap); + s->activity2 = ABC_REALLOC(word, s->activity2,s->cap); + s->pFreqs = ABC_REALLOC(char, s->pFreqs, s->cap); + + if ( s->factors ) + s->factors = ABC_REALLOC(double, s->factors, s->cap); + s->orderpos = ABC_REALLOC(int, s->orderpos, s->cap); + s->reasons = ABC_REALLOC(int, s->reasons, s->cap); + s->trail = ABC_REALLOC(lit, s->trail, s->cap); + s->model = ABC_REALLOC(int, s->model, s->cap); + memset( s->wlists + 2*old_cap, 0, 2*(s->cap-old_cap)*sizeof(veci) ); + } + + for (var = s->size; var < n; var++){ + assert(!s->wlists[2*var].size); + assert(!s->wlists[2*var+1].size); + if ( s->wlists[2*var].ptr == NULL ) + veci_new(&s->wlists[2*var]); + if ( s->wlists[2*var+1].ptr == NULL ) + veci_new(&s->wlists[2*var+1]); + + if ( s->VarActType == 0 ) + s->activity[var] = (1<<10); + else if ( s->VarActType == 1 ) + s->activity[var] = 0; + else if ( s->VarActType == 2 ) + s->activity[var] = 0; + else assert(0); + + s->pFreqs[var] = 0; + if ( s->factors ) + s->factors [var] = 0; +// *((int*)s->vi + var) = 0; s->vi[var].val = varX; + s->levels [var] = 0; + s->assigns [var] = varX; + s->polarity[var] = 0; + s->tags [var] = 0; + s->loads [var] = 0; + s->orderpos[var] = veci_size(&s->order); + s->reasons [var] = 0; + s->model [var] = 0; + + /* does not hold because variables enqueued at top level will not be reinserted in the heap + assert(veci_size(&s->order) == var); + */ + veci_push(&s->order,var); + order_update(s, var); + } + + s->size = n > s->size ? n : s->size; +} + +void sat_solver3_delete(sat_solver3* s) +{ +// Vec_SetFree_( &s->Mem ); + Sat_MemFree_( &s->Mem ); + + // delete vectors + veci_delete(&s->order); + veci_delete(&s->trail_lim); + veci_delete(&s->tagged); +// veci_delete(&s->learned); + veci_delete(&s->act_clas); + veci_delete(&s->stack); +// veci_delete(&s->model); + veci_delete(&s->act_vars); + veci_delete(&s->unit_lits); + veci_delete(&s->pivot_vars); + veci_delete(&s->temp_clause); + veci_delete(&s->conf_final); + + // delete arrays + if (s->reasons != 0){ + int i; + for (i = 0; i < s->cap*2; i++) + veci_delete(&s->wlists[i]); + ABC_FREE(s->wlists ); +// ABC_FREE(s->vi ); + ABC_FREE(s->levels ); + ABC_FREE(s->assigns ); + ABC_FREE(s->polarity ); + ABC_FREE(s->tags ); + ABC_FREE(s->loads ); + ABC_FREE(s->activity ); + ABC_FREE(s->activity2); + ABC_FREE(s->pFreqs ); + ABC_FREE(s->factors ); + ABC_FREE(s->orderpos ); + ABC_FREE(s->reasons ); + ABC_FREE(s->trail ); + ABC_FREE(s->model ); + } + + ABC_FREE(s); +} + +void sat_solver3_restart( sat_solver3* s ) +{ + int i; + Sat_MemRestart( &s->Mem ); + s->hLearnts = -1; + s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); + s->binary = clause_read( s, s->hBinary ); + + veci_resize(&s->trail_lim, 0); + veci_resize(&s->order, 0); + for ( i = 0; i < s->size*2; i++ ) + s->wlists[i].size = 0; + + s->nDBreduces = 0; + + // initialize other vars + s->size = 0; +// s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + + // variable activities + solver_init_activities(s); + veci_resize(&s->act_clas, 0); + + + s->root_level = 0; +// s->simpdb_assigns = 0; +// s->simpdb_props = 0; + s->random_seed = 91648253; + s->progress_estimate = 0; + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; +} + +void zsat_solver3_restart_seed( sat_solver3* s, double seed ) +{ + int i; + Sat_MemRestart( &s->Mem ); + s->hLearnts = -1; + s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); + s->binary = clause_read( s, s->hBinary ); + + veci_resize(&s->trail_lim, 0); + veci_resize(&s->order, 0); + for ( i = 0; i < s->size*2; i++ ) + s->wlists[i].size = 0; + + s->nDBreduces = 0; + + // initialize other vars + s->size = 0; +// s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + solver_init_activities(s); + veci_resize(&s->act_clas, 0); + + s->root_level = 0; +// s->simpdb_assigns = 0; +// s->simpdb_props = 0; + s->random_seed = seed; + s->progress_estimate = 0; + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; +} + +// returns memory in bytes used by the SAT solver +double sat_solver3_memory( sat_solver3* s ) +{ + int i; + double Mem = sizeof(sat_solver3); + for (i = 0; i < s->cap*2; i++) + Mem += s->wlists[i].cap * sizeof(int); + Mem += s->cap * sizeof(veci); // ABC_FREE(s->wlists ); + Mem += s->cap * sizeof(int); // ABC_FREE(s->levels ); + Mem += s->cap * sizeof(char); // ABC_FREE(s->assigns ); + Mem += s->cap * sizeof(char); // ABC_FREE(s->polarity ); + Mem += s->cap * sizeof(char); // ABC_FREE(s->tags ); + Mem += s->cap * sizeof(char); // ABC_FREE(s->loads ); + Mem += s->cap * sizeof(word); // ABC_FREE(s->activity ); + if ( s->activity2 ) + Mem += s->cap * sizeof(word); // ABC_FREE(s->activity ); + if ( s->factors ) + Mem += s->cap * sizeof(double); // ABC_FREE(s->factors ); + Mem += s->cap * sizeof(int); // ABC_FREE(s->orderpos ); + Mem += s->cap * sizeof(int); // ABC_FREE(s->reasons ); + Mem += s->cap * sizeof(lit); // ABC_FREE(s->trail ); + Mem += s->cap * sizeof(int); // ABC_FREE(s->model ); + + Mem += s->order.cap * sizeof(int); + Mem += s->trail_lim.cap * sizeof(int); + Mem += s->tagged.cap * sizeof(int); +// Mem += s->learned.cap * sizeof(int); + Mem += s->stack.cap * sizeof(int); + Mem += s->act_vars.cap * sizeof(int); + Mem += s->unit_lits.cap * sizeof(int); + Mem += s->act_clas.cap * sizeof(int); + Mem += s->temp_clause.cap * sizeof(int); + Mem += s->conf_final.cap * sizeof(int); + Mem += Sat_MemMemoryAll( &s->Mem ); + return Mem; +} + +int sat_solver3_simplify(sat_solver3* s) +{ + assert(sat_solver3_dl(s) == 0); + if (sat_solver3_propagate(s) != 0) + return false; + return true; +} + +void sat_solver3_reducedb(sat_solver3* s) +{ + static abctime TimeTotal = 0; + abctime clk = Abc_Clock(); + Sat_Mem_t * pMem = &s->Mem; + int nLearnedOld = veci_size(&s->act_clas); + int * act_clas = veci_begin(&s->act_clas); + int * pPerm, * pArray, * pSortValues, nCutoffValue; + int i, k, j, Id, Counter, CounterStart, nSelected; + clause * c; + + assert( s->nLearntMax > 0 ); + assert( nLearnedOld == Sat_MemEntryNum(pMem, 1) ); + assert( nLearnedOld == (int)s->stats.learnts ); + + s->nDBreduces++; + + //printf( "Calling reduceDB with %d learned clause limit.\n", s->nLearntMax ); + s->nLearntMax = s->nLearntStart + s->nLearntDelta * s->nDBreduces; +// return; + + // create sorting values + pSortValues = ABC_ALLOC( int, nLearnedOld ); + Sat_MemForEachLearned( pMem, c, i, k ) + { + Id = clause_id(c); +// pSortValues[Id] = act[Id]; + if ( s->ClaActType == 0 ) + pSortValues[Id] = ((7 - Abc_MinInt(c->lbd, 7)) << 28) | (act_clas[Id] >> 4); + else + pSortValues[Id] = ((7 - Abc_MinInt(c->lbd, 7)) << 28);// | (act_clas[Id] >> 4); + assert( pSortValues[Id] >= 0 ); + } + + // preserve 1/20 of last clauses + CounterStart = nLearnedOld - (s->nLearntMax / 20); + + // preserve 3/4 of most active clauses + nSelected = nLearnedOld*s->nLearntRatio/100; + + // find non-decreasing permutation + pPerm = Abc_MergeSortCost( pSortValues, nLearnedOld ); + assert( pSortValues[pPerm[0]] <= pSortValues[pPerm[nLearnedOld-1]] ); + nCutoffValue = pSortValues[pPerm[nLearnedOld-nSelected]]; + ABC_FREE( pPerm ); +// ActCutOff = ABC_INFINITY; + + // mark learned clauses to remove + Counter = j = 0; + Sat_MemForEachLearned( pMem, c, i, k ) + { + assert( c->mark == 0 ); + if ( Counter++ > CounterStart || clause_size(c) < 3 || pSortValues[clause_id(c)] > nCutoffValue || s->reasons[lit_var(c->lits[0])] == Sat_MemHand(pMem, i, k) ) + act_clas[j++] = act_clas[clause_id(c)]; + else // delete + { + c->mark = 1; + s->stats.learnts_literals -= clause_size(c); + s->stats.learnts--; + } + } + assert( s->stats.learnts == (unsigned)j ); + assert( Counter == nLearnedOld ); + veci_resize(&s->act_clas,j); + ABC_FREE( pSortValues ); + + // update ID of each clause to be its new handle + Counter = Sat_MemCompactLearned( pMem, 0 ); + assert( Counter == (int)s->stats.learnts ); + + // update reasons + for ( i = 0; i < s->size; i++ ) + { + if ( !s->reasons[i] ) // no reason + continue; + if ( clause_is_lit(s->reasons[i]) ) // 2-lit clause + continue; + if ( !clause_learnt_h(pMem, s->reasons[i]) ) // problem clause + continue; + c = clause_read( s, s->reasons[i] ); + assert( c->mark == 0 ); + s->reasons[i] = clause_id(c); // updating handle here!!! + } + + // update watches + for ( i = 0; i < s->size*2; i++ ) + { + pArray = veci_begin(&s->wlists[i]); + for ( j = k = 0; k < veci_size(&s->wlists[i]); k++ ) + { + if ( clause_is_lit(pArray[k]) ) // 2-lit clause + pArray[j++] = pArray[k]; + else if ( !clause_learnt_h(pMem, pArray[k]) ) // problem clause + pArray[j++] = pArray[k]; + else + { + c = clause_read(s, pArray[k]); + if ( !c->mark ) // useful learned clause + pArray[j++] = clause_id(c); // updating handle here!!! + } + } + veci_resize(&s->wlists[i],j); + } + + // perform final move of the clauses + Counter = Sat_MemCompactLearned( pMem, 1 ); + assert( Counter == (int)s->stats.learnts ); + + // report the results + TimeTotal += Abc_Clock() - clk; + if ( s->fVerbose ) + { + Abc_Print(1, "reduceDB: Keeping %7d out of %7d clauses (%5.2f %%) ", + s->stats.learnts, nLearnedOld, 100.0 * s->stats.learnts / nLearnedOld ); + Abc_PrintTime( 1, "Time", TimeTotal ); + } +} + + +// reverses to the previously bookmarked point +void sat_solver3_rollback( sat_solver3* s ) +{ + Sat_Mem_t * pMem = &s->Mem; + int i, k, j; + static int Count = 0; + Count++; + assert( s->iVarPivot >= 0 && s->iVarPivot <= s->size ); + assert( s->iTrailPivot >= 0 && s->iTrailPivot <= s->qtail ); + // reset implication queue + sat_solver3_canceluntil_rollback( s, s->iTrailPivot ); + // update order + if ( s->iVarPivot < s->size ) + { + if ( s->activity2 ) + { + s->var_inc = s->var_inc2; + memcpy( s->activity, s->activity2, sizeof(word) * s->iVarPivot ); + } + veci_resize(&s->order, 0); + for ( i = 0; i < s->iVarPivot; i++ ) + { + if ( var_value(s, i) != varX ) + continue; + s->orderpos[i] = veci_size(&s->order); + veci_push(&s->order,i); + order_update(s, i); + } + } + // compact watches + for ( i = 0; i < s->iVarPivot*2; i++ ) + { + cla* pArray = veci_begin(&s->wlists[i]); + for ( j = k = 0; k < veci_size(&s->wlists[i]); k++ ) + { + if ( clause_is_lit(pArray[k]) ) + { + if ( clause_read_lit(pArray[k]) < s->iVarPivot*2 ) + pArray[j++] = pArray[k]; + } + else if ( Sat_MemClauseUsed(pMem, pArray[k]) ) + pArray[j++] = pArray[k]; + } + veci_resize(&s->wlists[i],j); + } + // reset watcher lists + for ( i = 2*s->iVarPivot; i < 2*s->size; i++ ) + s->wlists[i].size = 0; + + // reset clause counts + s->stats.clauses = pMem->BookMarkE[0]; + s->stats.learnts = pMem->BookMarkE[1]; + // rollback clauses + Sat_MemRollBack( pMem ); + + // resize learned arrays + veci_resize(&s->act_clas, s->stats.learnts); + + // initialize other vars + s->size = s->iVarPivot; + if ( s->size == 0 ) + { + // s->size = 0; + // s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + solver_init_activities(s); + + s->root_level = 0; + s->random_seed = 91648253; + s->progress_estimate = 0; + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; + + // initialize rollback + s->iVarPivot = 0; // the pivot for variables + s->iTrailPivot = 0; // the pivot for trail + s->hProofPivot = 1; // the pivot for proof records + } +} + + +int sat_solver3_addclause(sat_solver3* s, lit* begin, lit* end) +{ + int fVerbose = 0; + lit *i,*j; + int maxvar; + lit last; + assert( begin < end ); + if ( fVerbose ) + { + for ( i = begin; i < end; i++ ) + printf( "%s%d ", (*i)&1 ? "!":"", (*i)>>1 ); + printf( "\n" ); + } + + veci_resize( &s->temp_clause, 0 ); + for ( i = begin; i < end; i++ ) + veci_push( &s->temp_clause, *i ); + begin = veci_begin( &s->temp_clause ); + end = begin + veci_size( &s->temp_clause ); + + // insertion sort + maxvar = lit_var(*begin); + for (i = begin + 1; i < end; i++){ + lit l = *i; + maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; + for (j = i; j > begin && *(j-1) > l; j--) + *j = *(j-1); + *j = l; + } + sat_solver3_setnvars(s,maxvar+1); + + // delete duplicates + last = lit_Undef; + for (i = j = begin; i < end; i++){ + //printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -s->assignss[lit_var(*i)] : s->assignss[lit_var(*i)])); + if (*i == lit_neg(last) || var_value(s, lit_var(*i)) == lit_sign(*i)) + return true; // tautology + else if (*i != last && var_value(s, lit_var(*i)) == varX) + last = *j++ = *i; + } +// j = i; + + if (j == begin) // empty clause + return false; + + if (j - begin == 1) // unit clause + return sat_solver3_enqueue(s,*begin,0); + + // create new clause + sat_solver3_clause_new(s,begin,j,0); + return true; +} + +static double luby(double y, int x) +{ + int size, seq; + for (size = 1, seq = 0; size < x+1; seq++, size = 2*size + 1); + while (size-1 != x){ + size = (size-1) >> 1; + seq--; + x = x % size; + } + return pow(y, (double)seq); +} + +static void luby_test() +{ + int i; + for ( i = 0; i < 20; i++ ) + printf( "%d ", (int)luby(2,i) ); + printf( "\n" ); +} + +static lbool sat_solver3_search(sat_solver3* s, ABC_INT64_T nof_conflicts) +{ +// double var_decay = 0.95; +// double clause_decay = 0.999; + double random_var_freq = s->fNotUseRandom ? 0.0 : 0.02; + ABC_INT64_T conflictC = 0; + veci learnt_clause; + int i; + + assert(s->root_level == sat_solver3_dl(s)); + + s->nRestarts++; + s->stats.starts++; +// s->var_decay = (float)(1 / var_decay ); // move this to sat_solver3_new() +// s->cla_decay = (float)(1 / clause_decay); // move this to sat_solver3_new() +// veci_resize(&s->model,0); + veci_new(&learnt_clause); + + // use activity factors in every even restart + if ( (s->nRestarts & 1) && veci_size(&s->act_vars) > 0 ) +// if ( veci_size(&s->act_vars) > 0 ) + for ( i = 0; i < s->act_vars.size; i++ ) + act_var_bump_factor(s, s->act_vars.ptr[i]); + + // use activity factors in every restart + if ( s->pGlobalVars && veci_size(&s->act_vars) > 0 ) + for ( i = 0; i < s->act_vars.size; i++ ) + act_var_bump_global(s, s->act_vars.ptr[i]); + + for (;;){ + int hConfl = sat_solver3_propagate(s); + if (hConfl != 0){ + // CONFLICT + int blevel; + +#ifdef VERBOSEDEBUG + printf(L_IND"**CONFLICT**\n", L_ind); +#endif + s->stats.conflicts++; conflictC++; + if (sat_solver3_dl(s) == s->root_level){ +#ifdef SAT_USE_ANALYZE_FINAL + sat_solver3_analyze_final(s, hConfl, 0); +#endif + veci_delete(&learnt_clause); + return l_False; + } + + veci_resize(&learnt_clause,0); + sat_solver3_analyze(s, hConfl, &learnt_clause); + blevel = veci_size(&learnt_clause) > 1 ? var_level(s, lit_var(veci_begin(&learnt_clause)[1])) : s->root_level; + blevel = s->root_level > blevel ? s->root_level : blevel; + sat_solver3_canceluntil(s,blevel); + sat_solver3_record(s,&learnt_clause); +#ifdef SAT_USE_ANALYZE_FINAL +// if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0; // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions) + if ( learnt_clause.size == 1 ) + var_set_level(s, lit_var(learnt_clause.ptr[0]), 0); +#endif + act_var_decay(s); + act_clause_decay(s); + + }else{ + // NO CONFLICT + int next; + + // Reached bound on number of conflicts: + if ( (!s->fNoRestarts && nof_conflicts >= 0 && conflictC >= nof_conflicts) || (s->nRuntimeLimit && (s->stats.conflicts & 63) == 0 && Abc_Clock() > s->nRuntimeLimit)){ + s->progress_estimate = sat_solver3_progress(s); + sat_solver3_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + return l_Undef; } + + // Reached bound on number of conflicts: + if ( (s->nConfLimit && s->stats.conflicts > s->nConfLimit) || + (s->nInsLimit && s->stats.propagations > s->nInsLimit) ) + { + s->progress_estimate = sat_solver3_progress(s); + sat_solver3_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + return l_Undef; + } + + // Simplify the set of problem clauses: + if (sat_solver3_dl(s) == 0 && !s->fSkipSimplify) + sat_solver3_simplify(s); + + // Reduce the set of learnt clauses: +// if (s->nLearntMax && veci_size(&s->learned) - s->qtail >= s->nLearntMax) + if (s->nLearntMax && veci_size(&s->act_clas) >= s->nLearntMax) + sat_solver3_reducedb(s); + + // New variable decision: + s->stats.decisions++; + next = order_select(s,(float)random_var_freq); + + if (next == var_Undef){ + // Model found: + int i; + for (i = 0; i < s->size; i++) + s->model[i] = (var_value(s,i)==var1 ? l_True : l_False); + sat_solver3_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + + /* + veci apa; veci_new(&apa); + for (i = 0; i < s->size; i++) + veci_push(&apa,(int)(s->model.ptr[i] == l_True ? toLit(i) : lit_neg(toLit(i)))); + printf("model: "); printlits((lit*)apa.ptr, (lit*)apa.ptr + veci_size(&apa)); printf("\n"); + veci_delete(&apa); + */ + + return l_True; + } + + if ( var_polar(s, next) ) // positive polarity + sat_solver3_decision(s,toLit(next)); + else + sat_solver3_decision(s,lit_neg(toLit(next))); + } + } + + return l_Undef; // cannot happen +} + +// internal call to the SAT solver +int sat_solver3_solve_internal(sat_solver3* s) +{ + lbool status = l_Undef; + int restart_iter = 0; + veci_resize(&s->unit_lits, 0); + s->nCalls++; + + if (s->verbosity >= 1){ + printf("==================================[MINISAT]===================================\n"); + printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); + printf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n"); + printf("==============================================================================\n"); + } + + while (status == l_Undef){ + ABC_INT64_T nof_conflicts; + double Ratio = (s->stats.learnts == 0)? 0.0 : + s->stats.learnts_literals / (double)s->stats.learnts; + if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit ) + break; + if (s->verbosity >= 1) + { + printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n", + (double)s->stats.conflicts, + (double)s->stats.clauses, + (double)s->stats.clauses_literals, + (double)0, + (double)s->stats.learnts, + (double)s->stats.learnts_literals, + Ratio, + s->progress_estimate*100); + fflush(stdout); + } + nof_conflicts = (ABC_INT64_T)( 100 * luby(2, restart_iter++) ); + status = sat_solver3_search(s, nof_conflicts); + // quit the loop if reached an external limit + if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit ) + break; + if ( s->nInsLimit && s->stats.propagations > s->nInsLimit ) + break; + if ( s->nRuntimeLimit && Abc_Clock() > s->nRuntimeLimit ) + break; + } + if (s->verbosity >= 1) + printf("==============================================================================\n"); + + sat_solver3_canceluntil(s,s->root_level); + return status; +} + +// pushing one assumption to the stack of assumptions +int sat_solver3_push(sat_solver3* s, int p) +{ + assert(lit_var(p) < s->size); + veci_push(&s->trail_lim,s->qtail); + s->root_level++; + if (!sat_solver3_enqueue(s,p,0)) + { + int h = s->reasons[lit_var(p)]; + if (h) + { + if (clause_is_lit(h)) + { + (clause_begin(s->binary))[1] = lit_neg(p); + (clause_begin(s->binary))[0] = clause_read_lit(h); + h = s->hBinary; + } + sat_solver3_analyze_final(s, h, 1); + veci_push(&s->conf_final, lit_neg(p)); + } + else + { + veci_resize(&s->conf_final,0); + veci_push(&s->conf_final, lit_neg(p)); + // the two lines below are a bug fix by Siert Wieringa + if (var_level(s, lit_var(p)) > 0) + veci_push(&s->conf_final, p); + } + //sat_solver3_canceluntil(s, 0); + return false; + } + else + { + int fConfl = sat_solver3_propagate(s); + if (fConfl){ + sat_solver3_analyze_final(s, fConfl, 0); + //assert(s->conf_final.size > 0); + //sat_solver3_canceluntil(s, 0); + return false; } + } + return true; +} + +// removing one assumption from the stack of assumptions +void sat_solver3_pop(sat_solver3* s) +{ + assert( sat_solver3_dl(s) > 0 ); + sat_solver3_canceluntil(s, --s->root_level); +} + +void sat_solver3_set_resource_limits(sat_solver3* s, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal) +{ + // set the external limits + s->nRestarts = 0; + s->nConfLimit = 0; + s->nInsLimit = 0; + if ( nConfLimit ) + s->nConfLimit = s->stats.conflicts + nConfLimit; + if ( nInsLimit ) +// s->nInsLimit = s->stats.inspects + nInsLimit; + s->nInsLimit = s->stats.propagations + nInsLimit; + if ( nConfLimitGlobal && (s->nConfLimit == 0 || s->nConfLimit > nConfLimitGlobal) ) + s->nConfLimit = nConfLimitGlobal; + if ( nInsLimitGlobal && (s->nInsLimit == 0 || s->nInsLimit > nInsLimitGlobal) ) + s->nInsLimit = nInsLimitGlobal; +} + +int sat_solver3_solve(sat_solver3* s, lit* begin, lit* end, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal) +{ + lbool status; + lit * i; + if ( s->fSolved ) + return l_False; + + if ( s->fVerbose ) + printf( "Running SAT solver with parameters %d and %d and %d.\n", s->nLearntStart, s->nLearntDelta, s->nLearntRatio ); + + sat_solver3_set_resource_limits( s, nConfLimit, nInsLimit, nConfLimitGlobal, nInsLimitGlobal ); + +#ifdef SAT_USE_ANALYZE_FINAL + // Perform assumptions: + s->root_level = 0; + for ( i = begin; i < end; i++ ) + if ( !sat_solver3_push(s, *i) ) + { + sat_solver3_canceluntil(s,0); + s->root_level = 0; + return l_False; + } + assert(s->root_level == sat_solver3_dl(s)); +#else + //printf("solve: "); printlits(begin, end); printf("\n"); + for (i = begin; i < end; i++){ +// switch (lit_sign(*i) ? -s->assignss[lit_var(*i)] : s->assignss[lit_var(*i)]){ + switch (var_value(s, *i)) { + case var1: // l_True: + break; + case varX: // l_Undef + sat_solver3_decision(s, *i); + if (sat_solver3_propagate(s) == 0) + break; + // fallthrough + case var0: // l_False + sat_solver3_canceluntil(s, 0); + return l_False; + } + } + s->root_level = sat_solver3_dl(s); +#endif + + status = sat_solver3_solve_internal(s); + + sat_solver3_canceluntil(s,0); + s->root_level = 0; + return status; +} + +// This LEXSAT procedure should be called with a set of literals (pLits, nLits), +// which defines both (1) variable order, and (2) assignment to begin search from. +// It retuns the LEXSAT assigment that is the same or larger than the given one. +// (It assumes that there is no smaller assignment than the one given!) +// The resulting assignment is returned in the same set of literals (pLits, nLits). +// It pushes/pops assumptions internally and will undo them before terminating. +int sat_solver3_solve_lexsat( sat_solver3* s, int * pLits, int nLits ) +{ + int i, iLitFail = -1; + lbool status; + assert( nLits > 0 ); + // help the SAT solver by setting desirable polarity + sat_solver3_set_literal_polarity( s, pLits, nLits ); + // check if there exists a satisfying assignment + status = sat_solver3_solve_internal( s ); + if ( status != l_True ) // no assignment + return status; + // there is at least one satisfying assignment + assert( status == l_True ); + // find the first mismatching literal + for ( i = 0; i < nLits; i++ ) + if ( pLits[i] != sat_solver3_var_literal(s, Abc_Lit2Var(pLits[i])) ) + break; + if ( i == nLits ) // no mismatch - the current assignment is the minimum one! + return l_True; + // mismatch happens in literal i + iLitFail = i; + // create assumptions up to this literal (as in pLits) - including this literal! + for ( i = 0; i <= iLitFail; i++ ) + if ( !sat_solver3_push(s, pLits[i]) ) // can become UNSAT while adding the last assumption + break; + if ( i < iLitFail + 1 ) // the solver became UNSAT while adding assumptions + status = l_False; + else // solve under the assumptions + status = sat_solver3_solve_internal( s ); + if ( status == l_True ) + { + // we proved that there is a sat assignment with literal (iLitFail) having polarity as in pLits + // continue solving recursively + if ( iLitFail + 1 < nLits ) + status = sat_solver3_solve_lexsat( s, pLits + iLitFail + 1, nLits - iLitFail - 1 ); + } + else if ( status == l_False ) + { + // we proved that there is no assignment with iLitFail having polarity as in pLits + assert( Abc_LitIsCompl(pLits[iLitFail]) ); // literal is 0 + // (this assert may fail only if there is a sat assignment smaller than one originally given in pLits) + // now we flip this literal (make it 1), change the last assumption + // and contiue looking for the 000...0-assignment of other literals + sat_solver3_pop( s ); + pLits[iLitFail] = Abc_LitNot(pLits[iLitFail]); + if ( !sat_solver3_push(s, pLits[iLitFail]) ) + printf( "sat_solver3_solve_lexsat(): A satisfying assignment should exist.\n" ); // because we know that the problem is satisfiable + // update other literals to be 000...0 + for ( i = iLitFail + 1; i < nLits; i++ ) + pLits[i] = Abc_LitNot( Abc_LitRegular(pLits[i]) ); + // continue solving recursively + if ( iLitFail + 1 < nLits ) + status = sat_solver3_solve_lexsat( s, pLits + iLitFail + 1, nLits - iLitFail - 1 ); + else + status = l_True; + } + // undo the assumptions + for ( i = iLitFail; i >= 0; i-- ) + sat_solver3_pop( s ); + return status; +} + +// This procedure is called on a set of assumptions to minimize their number. +// The procedure relies on the fact that the current set of assumptions is UNSAT. +// It receives and returns SAT solver without assumptions. It returns the number +// of assumptions after minimization. The set of assumptions is returned in pLits. +int sat_solver3_minimize_assumptions( sat_solver3* s, int * pLits, int nLits, int nConfLimit ) +{ + int i, k, nLitsL, nLitsR, nResL, nResR; + if ( nLits == 1 ) + { + // since the problem is UNSAT, we will try to solve it without assuming the last literal + // if the result is UNSAT, the last literal can be dropped; otherwise, it is needed + int status = l_False; + int Temp = s->nConfLimit; + s->nConfLimit = nConfLimit; + status = sat_solver3_solve_internal( s ); + s->nConfLimit = Temp; + return (int)(status != l_False); // return 1 if the problem is not UNSAT + } + assert( nLits >= 2 ); + nLitsL = nLits / 2; + nLitsR = nLits - nLitsL; + // assume the left lits + for ( i = 0; i < nLitsL; i++ ) + if ( !sat_solver3_push(s, pLits[i]) ) + { + for ( k = i; k >= 0; k-- ) + sat_solver3_pop(s); + return sat_solver3_minimize_assumptions( s, pLits, i+1, nConfLimit ); + } + // solve for the right lits + nResL = sat_solver3_minimize_assumptions( s, pLits + nLitsL, nLitsR, nConfLimit ); + for ( i = 0; i < nLitsL; i++ ) + sat_solver3_pop(s); + // swap literals +// assert( nResL <= nLitsL ); +// for ( i = 0; i < nResL; i++ ) +// ABC_SWAP( int, pLits[i], pLits[nLitsL+i] ); + veci_resize( &s->temp_clause, 0 ); + for ( i = 0; i < nLitsL; i++ ) + veci_push( &s->temp_clause, pLits[i] ); + for ( i = 0; i < nResL; i++ ) + pLits[i] = pLits[nLitsL+i]; + for ( i = 0; i < nLitsL; i++ ) + pLits[nResL+i] = veci_begin(&s->temp_clause)[i]; + // assume the right lits + for ( i = 0; i < nResL; i++ ) + if ( !sat_solver3_push(s, pLits[i]) ) + { + for ( k = i; k >= 0; k-- ) + sat_solver3_pop(s); + return sat_solver3_minimize_assumptions( s, pLits, i+1, nConfLimit ); + } + // solve for the left lits + nResR = sat_solver3_minimize_assumptions( s, pLits + nResL, nLitsL, nConfLimit ); + for ( i = 0; i < nResL; i++ ) + sat_solver3_pop(s); + return nResL + nResR; +} + +// This is a specialized version of the above procedure with several custom changes: +// - makes sure that at least one of the marked literals is preserved in the clause +// - sets literals to zero when they do not have to be used +// - sets literals to zero for disproved variables +int sat_solver3_minimize_assumptions2( sat_solver3* s, int * pLits, int nLits, int nConfLimit ) +{ + int i, k, nLitsL, nLitsR, nResL, nResR; + if ( nLits == 1 ) + { + // since the problem is UNSAT, we will try to solve it without assuming the last literal + // if the result is UNSAT, the last literal can be dropped; otherwise, it is needed + int RetValue = 1, LitNot = Abc_LitNot(pLits[0]); + int status = l_False; + int Temp = s->nConfLimit; + s->nConfLimit = nConfLimit; + + RetValue = sat_solver3_push( s, LitNot ); assert( RetValue ); + status = sat_solver3_solve_internal( s ); + sat_solver3_pop( s ); + + // if the problem is UNSAT, add clause + if ( status == l_False ) + { + RetValue = sat_solver3_addclause( s, &LitNot, &LitNot+1 ); + assert( RetValue ); + } + + s->nConfLimit = Temp; + return (int)(status != l_False); // return 1 if the problem is not UNSAT + } + assert( nLits >= 2 ); + nLitsL = nLits / 2; + nLitsR = nLits - nLitsL; + // assume the left lits + for ( i = 0; i < nLitsL; i++ ) + if ( !sat_solver3_push(s, pLits[i]) ) + { + for ( k = i; k >= 0; k-- ) + sat_solver3_pop(s); + + // add clauses for these literal + for ( k = i+1; k > nLitsL; k++ ) + { + int LitNot = Abc_LitNot(pLits[i]); + int RetValue = sat_solver3_addclause( s, &LitNot, &LitNot+1 ); + assert( RetValue ); + } + + return sat_solver3_minimize_assumptions2( s, pLits, i+1, nConfLimit ); + } + // solve for the right lits + nResL = sat_solver3_minimize_assumptions2( s, pLits + nLitsL, nLitsR, nConfLimit ); + for ( i = 0; i < nLitsL; i++ ) + sat_solver3_pop(s); + // swap literals +// assert( nResL <= nLitsL ); + veci_resize( &s->temp_clause, 0 ); + for ( i = 0; i < nLitsL; i++ ) + veci_push( &s->temp_clause, pLits[i] ); + for ( i = 0; i < nResL; i++ ) + pLits[i] = pLits[nLitsL+i]; + for ( i = 0; i < nLitsL; i++ ) + pLits[nResL+i] = veci_begin(&s->temp_clause)[i]; + // assume the right lits + for ( i = 0; i < nResL; i++ ) + if ( !sat_solver3_push(s, pLits[i]) ) + { + for ( k = i; k >= 0; k-- ) + sat_solver3_pop(s); + + // add clauses for these literal + for ( k = i+1; k > nResL; k++ ) + { + int LitNot = Abc_LitNot(pLits[i]); + int RetValue = sat_solver3_addclause( s, &LitNot, &LitNot+1 ); + assert( RetValue ); + } + + return sat_solver3_minimize_assumptions2( s, pLits, i+1, nConfLimit ); + } + // solve for the left lits + nResR = sat_solver3_minimize_assumptions2( s, pLits + nResL, nLitsL, nConfLimit ); + for ( i = 0; i < nResL; i++ ) + sat_solver3_pop(s); + return nResL + nResR; +} + + + +int sat_solver3_nvars(sat_solver3* s) +{ + return s->size; +} + + +int sat_solver3_nclauses(sat_solver3* s) +{ + return s->stats.clauses; +} + + +int sat_solver3_nconflicts(sat_solver3* s) +{ + return (int)s->stats.conflicts; +} + + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/bsat/satSolver3.h b/src/sat/bsat/satSolver3.h new file mode 100644 index 00000000..2d2e7ded --- /dev/null +++ b/src/sat/bsat/satSolver3.h @@ -0,0 +1,622 @@ +/************************************************************************************************** +MiniSat -- Copyright (c) 2005, Niklas Sorensson +http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ +// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko + +#ifndef ABC__sat__bsat__satSolver3_h +#define ABC__sat__bsat__satSolver3_h + + +#include +#include +#include +#include + +#include "satVec.h" +#include "satClause.h" +#include "misc/util/utilDouble.h" + +ABC_NAMESPACE_HEADER_START + +//================================================================================================= +// Public interface: + +struct sat_solver3_t; +typedef struct sat_solver3_t sat_solver3; + +extern sat_solver3* sat_solver3_new(void); +extern sat_solver3* zsat_solver3_new_seed(double seed); +extern void sat_solver3_delete(sat_solver3* s); + +extern int sat_solver3_addclause(sat_solver3* s, lit* begin, lit* end); +extern int sat_solver3_clause_new(sat_solver3* s, lit* begin, lit* end, int learnt); +extern int sat_solver3_simplify(sat_solver3* s); +extern int sat_solver3_solve(sat_solver3* s, lit* begin, lit* end, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal); +extern int sat_solver3_solve_internal(sat_solver3* s); +extern int sat_solver3_solve_lexsat(sat_solver3* s, int * pLits, int nLits); +extern int sat_solver3_minimize_assumptions( sat_solver3* s, int * pLits, int nLits, int nConfLimit ); +extern int sat_solver3_minimize_assumptions2( sat_solver3* s, int * pLits, int nLits, int nConfLimit ); +extern int sat_solver3_push(sat_solver3* s, int p); +extern void sat_solver3_pop(sat_solver3* s); +extern void sat_solver3_set_resource_limits(sat_solver3* s, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal); +extern void sat_solver3_restart( sat_solver3* s ); +extern void zsat_solver3_restart_seed( sat_solver3* s, double seed ); +extern void sat_solver3_rollback( sat_solver3* s ); + +extern int sat_solver3_nvars(sat_solver3* s); +extern int sat_solver3_nclauses(sat_solver3* s); +extern int sat_solver3_nconflicts(sat_solver3* s); +extern double sat_solver3_memory(sat_solver3* s); +extern int sat_solver3_count_assigned(sat_solver3* s); + +extern void sat_solver3_setnvars(sat_solver3* s,int n); +extern int sat_solver3_get_var_value(sat_solver3* s, int v); +extern void sat_solver3_set_var_activity(sat_solver3* s, int * pVars, int nVars); + +extern void sat_solver3WriteDimacs( sat_solver3 * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars ); +extern void sat_solver3PrintStats( FILE * pFile, sat_solver3 * p ); +extern int * sat_solver3GetModel( sat_solver3 * p, int * pVars, int nVars ); +extern void sat_solver3DoubleClauses( sat_solver3 * p, int iVar ); + +// trace recording +extern void sat_solver3TraceStart( sat_solver3 * pSat, char * pName ); +extern void sat_solver3TraceStop( sat_solver3 * pSat ); +extern void sat_solver3TraceWrite( sat_solver3 * pSat, int * pBeg, int * pEnd, int fRoot ); + +// clause storage +extern void sat_solver3_store_alloc( sat_solver3 * s ); +extern void sat_solver3_store_write( sat_solver3 * s, char * pFileName ); +extern void sat_solver3_store_free( sat_solver3 * s ); +extern void sat_solver3_store_mark_roots( sat_solver3 * s ); +extern void sat_solver3_store_mark_clauses_a( sat_solver3 * s ); +extern void * sat_solver3_store_release( sat_solver3 * s ); + +//================================================================================================= +// Solver representation: + +//struct clause_t; +//typedef struct clause_t clause; + +struct varinfo_t; +typedef struct varinfo_t varinfo; + +struct sat_solver3_t +{ + int size; // nof variables + int cap; // size of varmaps + int qhead; // Head index of queue. + int qtail; // Tail index of queue. + + // clauses + Sat_Mem_t Mem; + int hLearnts; // the first learnt clause + int hBinary; // the special binary clause + clause * binary; + veci* wlists; // watcher lists + + // rollback + int iVarPivot; // the pivot for variables + int iTrailPivot; // the pivot for trail + int hProofPivot; // the pivot for proof records + + // activities + int VarActType; + int ClaActType; + word var_inc; // Amount to bump next variable with. + word var_inc2; // Amount to bump next variable with. + word var_decay; // INVERSE decay factor for variable activity: stores 1/decay. + word* activity; // A heuristic measurement of the activity of a variable. + word* activity2; // backup variable activity + unsigned cla_inc; // Amount to bump next clause with. + unsigned cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. + veci act_clas; // contain clause activities + + char * pFreqs; // how many times this variable was assigned a value + int nVarUsed; + +// varinfo * vi; // variable information + int* levels; // + char* assigns; // Current values of variables. + char* polarity; // + char* tags; // + char* loads; // + + int* orderpos; // Index in variable order. + int* reasons; // + lit* trail; + veci tagged; // (contains: var) + veci stack; // (contains: var) + + veci order; // Variable order. (heap) (contains: var) + veci trail_lim; // Separator indices for different decision levels in 'trail'. (contains: int) +// veci model; // If problem is solved, this vector contains the model (contains: lbool). + int * model; // If problem is solved, this vector contains the model (contains: lbool). + veci conf_final; // If problem is unsatisfiable (possibly under assumptions), + // this vector represent the final conflict clause expressed in the assumptions. + + int root_level; // Level of first proper decision. + int simpdb_assigns;// Number of top-level assignments at last 'simplifyDB()'. + int simpdb_props; // Number of propagations before next 'simplifyDB()'. + double random_seed; + double progress_estimate; + int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything + int fVerbose; + + stats_t stats; + int nLearntMax; // max number of learned clauses + int nLearntStart; // starting learned clause limit + int nLearntDelta; // delta of learned clause limit + int nLearntRatio; // ratio percentage of learned clauses + int nDBreduces; // number of DB reductions + + ABC_INT64_T nConfLimit; // external limit on the number of conflicts + ABC_INT64_T nInsLimit; // external limit on the number of implications + abctime nRuntimeLimit; // external limit on runtime + + veci act_vars; // variables whose activity has changed + double* factors; // the activity factors + int nRestarts; // the number of local restarts + int nCalls; // the number of local restarts + int nCalls2; // the number of local restarts + veci unit_lits; // variables whose activity has changed + veci pivot_vars; // pivot variables + + int fSkipSimplify; // set to one to skip simplification of the clause database + int fNotUseRandom; // do not allow random decisions with a fixed probability + int fNoRestarts; // disables periodic restarts + + int * pGlobalVars; // for experiments with global vars during interpolation + // clause store + void * pStore; + int fSolved; + + // trace recording + FILE * pFile; + int nClauses; + int nRoots; + + veci temp_clause; // temporary storage for a CNF clause + + // CNF loading + void * pCnfMan; // external CNF manager + int(*pCnfFunc)(void * p, int); // external callback +}; + +static inline clause * clause_read( sat_solver3 * s, cla h ) +{ + return Sat_MemClauseHand( &s->Mem, h ); +} + +static int sat_solver3_var_value( sat_solver3* s, int v ) +{ + assert( v >= 0 && v < s->size ); + return (int)(s->model[v] == l_True); +} +static int sat_solver3_var_literal( sat_solver3* s, int v ) +{ + assert( v >= 0 && v < s->size ); + return toLitCond( v, s->model[v] != l_True ); +} +static void sat_solver3_act_var_clear(sat_solver3* s) +{ + int i; + if ( s->VarActType == 0 ) + { + for (i = 0; i < s->size; i++) + s->activity[i] = (1 << 10); + s->var_inc = (1 << 5); + } + else if ( s->VarActType == 1 ) + { + for (i = 0; i < s->size; i++) + s->activity[i] = 0; + s->var_inc = 1; + } + else if ( s->VarActType == 2 ) + { + for (i = 0; i < s->size; i++) + s->activity[i] = Xdbl_Const1(); + s->var_inc = Xdbl_Const1(); + } + else assert(0); +} +static void sat_solver3_compress(sat_solver3* s) +{ + if ( s->qtail != s->qhead ) + { + int RetValue = sat_solver3_simplify(s); + assert( RetValue != 0 ); + (void) RetValue; + } +} +static void sat_solver3_delete_p( sat_solver3 ** ps ) +{ + if ( *ps ) + sat_solver3_delete( *ps ); + *ps = NULL; +} +static void sat_solver3_clean_polarity(sat_solver3* s, int * pVars, int nVars ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + s->polarity[pVars[i]] = 0; +} +static void sat_solver3_set_polarity(sat_solver3* s, int * pVars, int nVars ) +{ + int i; + for ( i = 0; i < s->size; i++ ) + s->polarity[i] = 0; + for ( i = 0; i < nVars; i++ ) + s->polarity[pVars[i]] = 1; +} +static void sat_solver3_set_literal_polarity(sat_solver3* s, int * pLits, int nLits ) +{ + int i; + for ( i = 0; i < nLits; i++ ) + s->polarity[Abc_Lit2Var(pLits[i])] = !Abc_LitIsCompl(pLits[i]); +} + +static int sat_solver3_final(sat_solver3* s, int ** ppArray) +{ + *ppArray = s->conf_final.ptr; + return s->conf_final.size; +} + +static abctime sat_solver3_set_runtime_limit(sat_solver3* s, abctime Limit) +{ + abctime nRuntimeLimit = s->nRuntimeLimit; + s->nRuntimeLimit = Limit; + return nRuntimeLimit; +} + +static int sat_solver3_set_random(sat_solver3* s, int fNotUseRandom) +{ + int fNotUseRandomOld = s->fNotUseRandom; + s->fNotUseRandom = fNotUseRandom; + return fNotUseRandomOld; +} + +static inline void sat_solver3_bookmark(sat_solver3* s) +{ + assert( s->qhead == s->qtail ); + s->iVarPivot = s->size; + s->iTrailPivot = s->qhead; + Sat_MemBookMark( &s->Mem ); + if ( s->activity2 ) + { + s->var_inc2 = s->var_inc; + memcpy( s->activity2, s->activity, sizeof(word) * s->iVarPivot ); + } +} +static inline void sat_solver3_set_pivot_variables( sat_solver3* s, int * pPivots, int nPivots ) +{ + s->pivot_vars.cap = nPivots; + s->pivot_vars.size = nPivots; + s->pivot_vars.ptr = pPivots; +} +static inline int sat_solver3_count_usedvars(sat_solver3* s) +{ + int i, nVars = 0; + for ( i = 0; i < s->size; i++ ) + if ( s->pFreqs[i] ) + { + s->pFreqs[i] = 0; + nVars++; + } + return nVars; +} + +static inline int sat_solver3_add_const( sat_solver3 * pSat, int iVar, int fCompl ) +{ + lit Lits[1]; + int Cid; + assert( iVar >= 0 ); + + Lits[0] = toLitCond( iVar, fCompl ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 1 ); + assert( Cid ); + return 1; +} +static inline int sat_solver3_add_buffer( sat_solver3 * pSat, int iVarA, int iVarB, int fCompl ) +{ + lit Lits[2]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 ); + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVarB, !fCompl ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + if ( Cid == 0 ) + return 0; + assert( Cid ); + + Lits[0] = toLitCond( iVarA, 1 ); + Lits[1] = toLitCond( iVarB, fCompl ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + if ( Cid == 0 ) + return 0; + assert( Cid ); + return 2; +} +static inline int sat_solver3_add_buffer_enable( sat_solver3 * pSat, int iVarA, int iVarB, int iVarEn, int fCompl ) +{ + lit Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarEn >= 0 ); + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVarB, !fCompl ); + Lits[2] = toLitCond( iVarEn, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, 1 ); + Lits[1] = toLitCond( iVarB, fCompl ); + Lits[2] = toLitCond( iVarEn, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + return 2; +} +static inline int sat_solver3_add_and( sat_solver3 * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) +{ + lit Lits[3]; + int Cid; + + Lits[0] = toLitCond( iVar, !fCompl ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVar, !fCompl ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVar, fCompl ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + return 3; +} +static inline int sat_solver3_add_xor( sat_solver3 * pSat, int iVarA, int iVarB, int iVarC, int fCompl ) +{ + lit Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = toLitCond( iVarA, !fCompl ); + Lits[1] = toLitCond( iVarB, 1 ); + Lits[2] = toLitCond( iVarC, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, !fCompl ); + Lits[1] = toLitCond( iVarB, 0 ); + Lits[2] = toLitCond( iVarC, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, fCompl ); + Lits[1] = toLitCond( iVarB, 1 ); + Lits[2] = toLitCond( iVarC, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, fCompl ); + Lits[1] = toLitCond( iVarB, 0 ); + Lits[2] = toLitCond( iVarC, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + return 4; +} +static inline int sat_solver3_add_mux( sat_solver3 * pSat, int iVarZ, int iVarC, int iVarT, int iVarE, int iComplC, int iComplT, int iComplE, int iComplZ ) +{ + lit Lits[3]; + int Cid; + assert( iVarC >= 0 && iVarT >= 0 && iVarE >= 0 && iVarZ >= 0 ); + + Lits[0] = toLitCond( iVarC, 1 ^ iComplC ); + Lits[1] = toLitCond( iVarT, 1 ^ iComplT ); + Lits[2] = toLitCond( iVarZ, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarC, 1 ^ iComplC ); + Lits[1] = toLitCond( iVarT, 0 ^ iComplT ); + Lits[2] = toLitCond( iVarZ, 1 ^ iComplZ ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarC, 0 ^ iComplC ); + Lits[1] = toLitCond( iVarE, 1 ^ iComplE ); + Lits[2] = toLitCond( iVarZ, 0 ^ iComplZ ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarC, 0 ^ iComplC ); + Lits[1] = toLitCond( iVarE, 0 ^ iComplE ); + Lits[2] = toLitCond( iVarZ, 1 ^ iComplZ ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + if ( iVarT == iVarE ) + return 4; + + Lits[0] = toLitCond( iVarT, 0 ^ iComplT ); + Lits[1] = toLitCond( iVarE, 0 ^ iComplE ); + Lits[2] = toLitCond( iVarZ, 1 ^ iComplZ ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarT, 1 ^ iComplT ); + Lits[1] = toLitCond( iVarE, 1 ^ iComplE ); + Lits[2] = toLitCond( iVarZ, 0 ^ iComplZ ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + return 6; +} +static inline int sat_solver3_add_mux41( sat_solver3 * pSat, int iVarZ, int iVarC0, int iVarC1, int iVarD0, int iVarD1, int iVarD2, int iVarD3 ) +{ + lit Lits[4]; + int Cid; + assert( iVarC0 >= 0 && iVarC1 >= 0 && iVarD0 >= 0 && iVarD1 >= 0 && iVarD2 >= 0 && iVarD3 >= 0 && iVarZ >= 0 ); + + Lits[0] = toLitCond( iVarD0, 1 ); + Lits[1] = toLitCond( iVarC0, 0 ); + Lits[2] = toLitCond( iVarC1, 0 ); + Lits[3] = toLitCond( iVarZ, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarD1, 1 ); + Lits[1] = toLitCond( iVarC0, 1 ); + Lits[2] = toLitCond( iVarC1, 0 ); + Lits[3] = toLitCond( iVarZ, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarD2, 1 ); + Lits[1] = toLitCond( iVarC0, 0 ); + Lits[2] = toLitCond( iVarC1, 1 ); + Lits[3] = toLitCond( iVarZ, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarD3, 1 ); + Lits[1] = toLitCond( iVarC0, 1 ); + Lits[2] = toLitCond( iVarC1, 1 ); + Lits[3] = toLitCond( iVarZ, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + + Lits[0] = toLitCond( iVarD0, 0 ); + Lits[1] = toLitCond( iVarC0, 0 ); + Lits[2] = toLitCond( iVarC1, 0 ); + Lits[3] = toLitCond( iVarZ, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarD1, 0 ); + Lits[1] = toLitCond( iVarC0, 1 ); + Lits[2] = toLitCond( iVarC1, 0 ); + Lits[3] = toLitCond( iVarZ, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarD2, 0 ); + Lits[1] = toLitCond( iVarC0, 0 ); + Lits[2] = toLitCond( iVarC1, 1 ); + Lits[3] = toLitCond( iVarZ, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarD3, 0 ); + Lits[1] = toLitCond( iVarC0, 1 ); + Lits[2] = toLitCond( iVarC1, 1 ); + Lits[3] = toLitCond( iVarZ, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + return 8; +} +static inline int sat_solver3_add_xor_and( sat_solver3 * pSat, int iVarF, int iVarA, int iVarB, int iVarC ) +{ + // F = (a (+) b) * c + lit Lits[4]; + int Cid; + assert( iVarF >= 0 && iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = toLitCond( iVarF, 1 ); + Lits[1] = toLitCond( iVarA, 1 ); + Lits[2] = toLitCond( iVarB, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarF, 1 ); + Lits[1] = toLitCond( iVarA, 0 ); + Lits[2] = toLitCond( iVarB, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarF, 1 ); + Lits[1] = toLitCond( iVarC, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarF, 0 ); + Lits[1] = toLitCond( iVarA, 1 ); + Lits[2] = toLitCond( iVarB, 0 ); + Lits[3] = toLitCond( iVarC, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarF, 0 ); + Lits[1] = toLitCond( iVarA, 0 ); + Lits[2] = toLitCond( iVarB, 1 ); + Lits[3] = toLitCond( iVarC, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 4 ); + assert( Cid ); + return 5; +} +static inline int sat_solver3_add_constraint( sat_solver3 * pSat, int iVar, int iVar2, int fCompl ) +{ + lit Lits[2]; + int Cid; + assert( iVar >= 0 ); + + Lits[0] = toLitCond( iVar, fCompl ); + Lits[1] = toLitCond( iVar2, 0 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVar, fCompl ); + Lits[1] = toLitCond( iVar2, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + return 2; +} + +static inline int sat_solver3_add_half_sorter( sat_solver3 * pSat, int iVarA, int iVarB, int iVar0, int iVar1 ) +{ + lit Lits[3]; + int Cid; + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVar0, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVar1, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarB, 0 ); + Lits[1] = toLitCond( iVar0, 1 ); + Lits[2] = toLitCond( iVar1, 1 ); + Cid = sat_solver3_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + return 3; +} + + +ABC_NAMESPACE_HEADER_END + +#endif -- cgit v1.2.3