/* This is the learning function that moves all non-decision literals directly to the clause array, without unnecessarily routing them through the stack first. */ void learn(satinstance sati,int dlevel,int *CCdliteral,PTRINT *CCreason,int *maxnondecisionlevel) { int ptr; /* Index to the last literal in the conflict clause */ int top; /* Index to the top of the stack */ int CCwatch1; int CCwatch2; int *newClause; int len,l,rl,i,j; PTRINT r; int *c; int *stck,*cc; #ifdef MULTICORE stck = threads[sati->thread].stck; cc = threads[sati->thread].cc; #else stck = sati->stck; cc = sati->cc; #endif #ifdef LBD int lbd; #endif /* This counter is used for eliminating multiple occurrences of a literal from the derivation of the conflict clause. If the literal is associated with the current round, it has been seen already and will be ignored. */ nextround(sati); ptr = -1; /* The clause we will learn is still empty. */ top = -1; /* All literals in the clause are in the stack. */ *maxnondecisionlevel = -1; /* Highest non-decision level. */ if(sati->conflicttype2lit) { /* A 2-literal clause was falsified. */ stck[0] = sati->conflictl1; /* Push both literals into the stack. */ stck[1] = sati->conflictl2; top = 1; #ifdef MULTICORE threads[sati->thread].wasseen[sati->conflictl1] = threads[sati->thread].cround; threads[sati->thread].wasseen[sati->conflictl2] = threads[sati->thread].cround; #else wasseen[sati->conflictl1] = cround; wasseen[sati->conflictl2] = cround; #endif #ifdef HARDDEBUG printf("Violated binary clause "); printTlit(sati,sati->conflictl1); printf(" "); printTlit(sati,sati->conflictl2); printf("\n"); #endif #ifdef ASSERTS assert(isliteral(sati,sati->conflictl1)); assert(isliteral(sati,sati->conflictl2)); #endif } else { /* A clause of >= 3 literals was falsified. */ len = sati->conflictclause[PREFIX_CLAUSELEN]; #ifdef DEBUG printf("Violated clause %i (len %i):\n",(int)(sati->conflictclause),len); for(i=0;iconflictclause[i]); } // for(i=0;iconflictclause[i]); } printf("\n"); #endif #ifdef ASSERTS for(i=0;iconflictclause[i]))); #endif /* Push all literals in the clause into the stack or in the cc array. */ for(i=0;ithread].wasseen[NEG(sati->conflictclause[i])] = threads[sati->thread].cround; #else wasseen[NEG(sati->conflictclause[i])] = cround; #endif if(LITDLEVEL(sati->conflictclause[i]) == dlevel) { stck[++top] = NEG(sati->conflictclause[i]); } else { int l = sati->conflictclause[i]; if(LITREASON(l) != REASON_INPUT) { *maxnondecisionlevel = max(LITDLEVEL(l),*maxnondecisionlevel); cc[++ptr] = l; } } } } // printf("FALSIFIED A %i-LITERAL CLAUSE.\n",len); // for(i=0;i<=top;i++) printf("{%i}",sati->variabledlevel[VAR(stck[i])]); // for(i=0;i<=top;i++) printTlit(sati,stck[i]); // printf("\n"); CCwatch1 = -1; CCwatch2 = -1; #ifdef ASSERTS assert(ptr=-1); assert(top>=0); /* Necessarily at least one literal at the decision level. */ #endif while(top >= 0) { l = stck[top--]; /* Pop literal from the stack. */ #ifdef ASSERTS assert(ptr=-1); #endif r = LITREASON(l); /* Infer (learn) a new clause from the falsified clause, one literal at a time. */ if(r == REASON_DECISION) { /* It is the decision literal. */ cc[++ptr] = NEG(l); CCwatch1 = NEG(l); *CCdliteral = NEG(l); } else if(r&1) { /* Reason is a literal (2 lit clause) */ #ifdef WEIGHTS increase_score(sati,l); /* Increase score */ #endif if(!seenp(sati,r >> 1)) { stck[++top] = (r >> 1); #ifdef ASSERTS assert(isliteral(sati,r >> 1)); #endif } } else { /* Reason is a clause */ #ifdef WEIGHTS increase_score(sati,l); /* Increase score */ #endif c = (int *)r; while(*c != -1) { /* Literals except l into the stack or into the CC. */ if(VAR(*c) != VAR(l) && !seenp(sati,NEG(*c))) { if(LITDLEVEL(*c) == dlevel) { stck[++top] = NEG(*c); } else { *maxnondecisionlevel = max(LITDLEVEL(*c),*maxnondecisionlevel); cc[++ptr] = *c; } } c += 1; } } } #ifdef ASSERTS assert(ptr=-1); #endif #ifdef DEBUG printf("Learned clause %i (%i lits):",clausecount,ptr+1); for(i=0;i<=ptr;i++) { printf(" %i:",VAR(cc[i])); printTlit(sati,cc[i]); } printf("\n"); #endif #ifdef ASSERTS /* See that the learned clause is false in the current valuation. */ for(i=0;i<=ptr;i++) { assert(!littruep(sati,cc[i])); assert(!litunsetp(sati,cc[i])); } #endif /* Minimize the size of the learned clause: 1. Mark all literals in the clause. 2. Remove literals whose parent is marked. */ #define noMINIMIZE #ifdef MINIMIZE { PTRINT rr; cround += 1; for(i=0;i<=ptr;i++) wasseen[NEG(cc[i])] = cround; i = 0; while(i<=ptr) { rr = LITREASON(cc[i]); if(rr != REASON_DECISION && (((int)rr)&1) && (wasseen[((int)rr) >> 1] == cround)) { /* Remove. */ // printf("*"); cc[i] = cc[ptr--]; } else { if(LITDLEVEL(cc[i]) == *maxnondecisionlevel) CCwatch2 = cc[i]; i = i + 1; } } } #else for(i=0;i<=ptr;i++) { if(LITDLEVEL(cc[i]) == *maxnondecisionlevel) { CCwatch2 = cc[i]; break; } } #endif #ifdef LBD /* Calculate the Literal Block Distance LBD of Laurent & Simon IJCAI'09. */ lbd = 0; sati->LBDcounter += 1; for(i=0;i<=ptr;i++) { if(sati->LBDflag[LITDLEVEL(cc[i])] != sati->LBDcounter) { lbd += 1; sati->LBDflag[LITDLEVEL(cc[i])] = sati->LBDcounter; } } #endif //printf("LEARNED A %i-LITERAL CLAUSE.\n",ptr+1); //if(ptr+1 > 20000) printf("QZ(%i,%i)",ptr+1,dlevel); // printf("ADDING NEW CLAUSE, ptr == %i\n",ptr); /* Add the new clause to the clause set. */ if(ptr+1 > stats_longest_learned) stats_longest_learned = ptr+1; if(ptr >= 2) { /* Clause with at least 3 literals */ #ifdef ASSERTS assert(isliteral(sati,CCwatch1)); assert(isliteral(sati,CCwatch2)); assert(CCwatch1 != CCwatch2); #endif newClause = allocclause(sati->id,ptr+1); // updateactivity(newClause,sati->conflicts); newClause[PREFIX_ACTIVITY] = sati->conflicts; #ifdef LBD // printf("/%i/",lbd); setLBD(newClause,lbd); #endif /* The watched literals are the ones with the highest levels, that is, the one at the decision level and one on the next highest level. */ newClause[0] = CCwatch1; newClause[1] = CCwatch2; #ifdef WEIGHTS increase_score(sati,newClause[0]); increase_score(sati,newClause[1]); #endif // Sort the learned clause. Impact on total runtime??????? qsort(cc,ptr+1,sizeof(int),litCmp); j = 2; for(i=0;i<=ptr;i++) { #ifdef ASSERTS assert(isliteral(sati,cc[i])); // assert(cc[i] != cc[i+1]); #endif if(cc[i] != CCwatch1 && cc[i] != CCwatch2) { newClause[j++] = cc[i]; #ifdef WEIGHTS increase_score(sati,newClause[j-1]); #endif } } #ifdef ASSERTS assert(j == ptr+1); assert(newClause[ptr+1] == -1); #endif *CCreason = (PTRINT)newClause; setwatch(sati,CCwatch1,(int *)(*CCreason),0); setwatch(sati,CCwatch2,(int *)(*CCreason),1); } else if(ptr == 1) { /* Clause with 2 literals */ #ifdef DEBUG printf("LEARNED A 2-LITERAL CLAUSE (horizon %i)\n",sati->nOfTPoints); #endif add2clause(sati,cc[0],cc[1],InitC); if(cc[0] == *CCdliteral) rl = cc[1]; else rl = cc[0]; *CCreason = ((NEG(rl))<< 1)|1; } else { /* Unit clause */ #ifdef DEBUG printf("LEARNED A 1-LITERAL CLAUSE! (horizon %i)\n",sati->nOfTPoints); #endif #ifdef UCC addUCC(sati,cc[0]); #endif *CCreason = REASON_INPUT; *maxnondecisionlevel = 0; } }