1 #include "satencoder.h"
5 #include "constraint.h"
9 #include "tableentry.h"
12 #include "predicate.h"
13 #include "orderpair.h"
16 SATEncoder * allocSATEncoder() {
17 SATEncoder *This=ourmalloc(sizeof (SATEncoder));
19 This->satSolver = allocIncrementalSolver();
23 void deleteSATEncoder(SATEncoder *This) {
24 deleteIncrementalSolver(This->satSolver);
28 Constraint * getElementValueConstraint(SATEncoder* encoder,Element* This, uint64_t value) {
29 generateElementEncodingVariables(encoder, getElementEncoding(This));
30 switch(getElementEncoding(This)->type){
39 return getElementValueBinaryIndexConstraint(This, value);
53 Constraint * getElementValueBinaryIndexConstraint(Element* This, uint64_t value) {
54 ASTNodeType type = GETELEMENTTYPE(This);
55 ASSERT(type == ELEMSET || type == ELEMFUNCRETURN);
56 ElementEncoding* elemEnc = getElementEncoding(This);
57 for(uint i=0; i<elemEnc->encArraySize; i++){
58 if( isinUseElement(elemEnc, i) && elemEnc->encodingArray[i]==value){
59 return generateBinaryConstraint(elemEnc->numVars,
60 elemEnc->variables, i);
66 void addConstraintToSATSolver(Constraint *c, IncrementalSolver* satSolver) {
67 VectorConstraint* simplified = simplifyConstraint(c);
68 uint size = getSizeVectorConstraint(simplified);
69 for(uint i=0; i<size; i++) {
70 Constraint *simp=getVectorConstraint(simplified, i);
73 ASSERT(simp->type!=FALSE);
74 dumpConstraint(simp, satSolver);
75 freerecConstraint(simp);
77 deleteVectorConstraint(simplified);
80 void encodeAllSATEncoder(CSolver *csolver, SATEncoder * This) {
81 VectorBoolean *constraints=csolver->constraints;
82 uint size=getSizeVectorBoolean(constraints);
83 for(uint i=0;i<size;i++) {
84 Boolean *constraint=getVectorBoolean(constraints, i);
85 Constraint* c= encodeConstraintSATEncoder(This, constraint);
88 addConstraintToSATSolver(c, This->satSolver);
92 Constraint * encodeConstraintSATEncoder(SATEncoder *This, Boolean *constraint) {
93 switch(GETBOOLEANTYPE(constraint)) {
95 return encodeOrderSATEncoder(This, (BooleanOrder *) constraint);
97 return encodeVarSATEncoder(This, (BooleanVar *) constraint);
99 return encodeLogicSATEncoder(This, (BooleanLogic *) constraint);
101 return encodePredicateSATEncoder(This, (BooleanPredicate *) constraint);
103 model_print("Unhandled case in encodeConstraintSATEncoder %u", GETBOOLEANTYPE(constraint));
108 void getArrayNewVarsSATEncoder(SATEncoder* encoder, uint num, Constraint **carray) {
109 for(uint i=0;i<num;i++)
110 carray[i]=getNewVarSATEncoder(encoder);
113 Constraint * getNewVarSATEncoder(SATEncoder *This) {
114 Constraint * var=allocVarConstraint(VAR, This->varcount);
115 Constraint * varneg=allocVarConstraint(NOTVAR, This->varcount++);
116 setNegConstraint(var, varneg);
117 setNegConstraint(varneg, var);
121 Constraint * encodeVarSATEncoder(SATEncoder *This, BooleanVar * constraint) {
122 if (constraint->var == NULL) {
123 constraint->var=getNewVarSATEncoder(This);
125 return constraint->var;
128 Constraint * encodeLogicSATEncoder(SATEncoder *This, BooleanLogic * constraint) {
129 Constraint * array[getSizeArrayBoolean(&constraint->inputs)];
130 for(uint i=0;i<getSizeArrayBoolean(&constraint->inputs);i++)
131 array[i]=encodeConstraintSATEncoder(This, getArrayBoolean(&constraint->inputs, i));
133 switch(constraint->op) {
135 return allocArrayConstraint(AND, getSizeArrayBoolean(&constraint->inputs), array);
137 return allocArrayConstraint(OR, getSizeArrayBoolean(&constraint->inputs), array);
139 ASSERT( getSizeArrayBoolean(&constraint->inputs)==1);
140 return negateConstraint(array[0]);
142 ASSERT( getSizeArrayBoolean(&constraint->inputs)==2);
143 Constraint * nleft=negateConstraint(cloneConstraint(array[0]));
144 Constraint * nright=negateConstraint(cloneConstraint(array[1]));
145 return allocConstraint(OR,
146 allocConstraint(AND, array[0], nright),
147 allocConstraint(AND, nleft, array[1]));
150 ASSERT( getSizeArrayBoolean( &constraint->inputs)==2);
151 return allocConstraint(IMPLIES, array[0], array[1]);
153 model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op);
159 Constraint * encodeOrderSATEncoder(SATEncoder *This, BooleanOrder * constraint) {
160 switch( constraint->order->type){
162 return encodePartialOrderSATEncoder(This, constraint);
164 return encodeTotalOrderSATEncoder(This, constraint);
171 Constraint * getPairConstraint(SATEncoder *This, HashTableBoolConst * table, OrderPair * pair) {
174 if (pair->first > pair->second) {
176 flipped.first=pair->second;
177 flipped.second=pair->first;
178 pair = &flipped; //FIXME: accessing a local variable from outside of the function?
180 Constraint * constraint;
181 if (!containsBoolConst(table, pair)) {
182 constraint = getNewVarSATEncoder(This);
183 OrderPair * paircopy = allocOrderPair(pair->first, pair->second, constraint);
184 putBoolConst(table, paircopy, paircopy);
186 constraint = getBoolConst(table, pair)->constraint;
188 return negateConstraint(constraint);
194 Constraint * encodeTotalOrderSATEncoder(SATEncoder *This, BooleanOrder * boolOrder){
195 ASSERT(boolOrder->order->type == TOTAL);
196 if(boolOrder->order->boolsToConstraints == NULL){
197 initializeOrderHashTable(boolOrder->order);
198 return createAllTotalOrderConstraintsSATEncoder(This, boolOrder->order);
200 HashTableBoolConst* boolToConsts = boolOrder->order->boolsToConstraints;
201 OrderPair pair={boolOrder->first, boolOrder->second, NULL};
202 Constraint *constraint = getPairConstraint(This, boolToConsts, & pair);
206 Constraint* createAllTotalOrderConstraintsSATEncoder(SATEncoder* This, Order* order){
207 ASSERT(order->type == TOTAL);
208 VectorInt* mems = order->set->members;
209 HashTableBoolConst* table = order->boolsToConstraints;
210 uint size = getSizeVectorInt(mems);
211 Constraint* constraints [size*size];
213 for(uint i=0; i<size; i++){
214 uint64_t valueI = getVectorInt(mems, i);
215 for(uint j=i+1; j<size;j++){
216 uint64_t valueJ = getVectorInt(mems, j);
217 OrderPair pairIJ = {valueI, valueJ};
218 Constraint* constIJ=getPairConstraint(This, table, & pairIJ);
219 for(uint k=j+1; k<size; k++){
220 uint64_t valueK = getVectorInt(mems, k);
221 OrderPair pairJK = {valueJ, valueK};
222 OrderPair pairIK = {valueI, valueK};
223 Constraint* constIK = getPairConstraint(This, table, & pairIK);
224 Constraint* constJK = getPairConstraint(This, table, & pairJK);
225 constraints[csize++] = generateTransOrderConstraintSATEncoder(This, constIJ, constJK, constIK);
226 ASSERT(csize < size*size);
230 return allocArrayConstraint(AND, csize, constraints);
233 Constraint* getOrderConstraint(HashTableBoolConst *table, OrderPair *pair){
234 ASSERT(pair->first!= pair->second);
235 Constraint* constraint= getBoolConst(table, pair)->constraint;
236 if(pair->first > pair->second)
239 return negateConstraint(constraint);
242 Constraint * generateTransOrderConstraintSATEncoder(SATEncoder *This, Constraint *constIJ,Constraint *constJK,Constraint *constIK){
243 //FIXME: first we should add the the constraint to the satsolver!
244 ASSERT(constIJ!= NULL && constJK != NULL && constIK != NULL);
245 Constraint *carray[] = {constIJ, constJK, negateConstraint(constIK)};
246 Constraint * loop1= allocArrayConstraint(OR, 3, carray);
247 Constraint * carray2[] = {negateConstraint(constIJ), negateConstraint(constJK), constIK};
248 Constraint * loop2= allocArrayConstraint(OR, 3,carray2 );
249 return allocConstraint(AND, loop1, loop2);
252 Constraint * encodePartialOrderSATEncoder(SATEncoder *This, BooleanOrder * constraint){
253 // FIXME: we can have this implementation for partial order. Basically,
254 // we compute the transitivity between two order constraints specified by the client! (also can be used
255 // when client specify sparse constraints for the total order!)
256 ASSERT(constraint->order->type == PARTIAL);
258 HashTableBoolConst* boolToConsts = boolOrder->order->boolsToConstraints;
259 if( containsBoolConst(boolToConsts, boolOrder) ){
260 return getBoolConst(boolToConsts, boolOrder);
262 Constraint* constraint = getNewVarSATEncoder(This);
263 putBoolConst(boolToConsts,boolOrder, constraint);
264 VectorBoolean* orderConstrs = &boolOrder->order->constraints;
265 uint size= getSizeVectorBoolean(orderConstrs);
266 for(uint i=0; i<size; i++){
267 ASSERT(GETBOOLEANTYPE( getVectorBoolean(orderConstrs, i)) == ORDERCONST );
268 BooleanOrder* tmp = (BooleanOrder*)getVectorBoolean(orderConstrs, i);
269 BooleanOrder* newBool;
270 Constraint* first, *second;
271 if(tmp->second==boolOrder->first){
272 newBool = (BooleanOrder*)allocBooleanOrder(tmp->order,tmp->first,boolOrder->second);
273 first = encodeTotalOrderSATEncoder(This, tmp);
276 }else if (boolOrder->second == tmp->first){
277 newBool = (BooleanOrder*)allocBooleanOrder(tmp->order,boolOrder->first,tmp->second);
279 second = encodeTotalOrderSATEncoder(This, tmp);
282 Constraint* transConstr= encodeTotalOrderSATEncoder(This, newBool);
283 generateTransOrderConstraintSATEncoder(This, first, second, transConstr );
291 Constraint * encodePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint) {
292 switch(GETPREDICATETYPE(constraint->predicate) ){
294 return encodeTablePredicateSATEncoder(This, constraint);
296 return encodeOperatorPredicateSATEncoder(This, constraint);
303 Constraint * encodeTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
304 switch(constraint->encoding.type){
305 case ENUMERATEIMPLICATIONS:
306 case ENUMERATEIMPLICATIONSNEGATE:
307 return encodeEnumTablePredicateSATEncoder(This, constraint);
317 Constraint * encodeEnumTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
318 VectorTableEntry* entries = &(((PredicateTable*)constraint->predicate)->table->entries);
319 FunctionEncodingType encType = constraint->encoding.type;
320 uint size = getSizeVectorTableEntry(entries);
321 Constraint* constraints[size];
322 for(uint i=0; i<size; i++){
323 TableEntry* entry = getVectorTableEntry(entries, i);
324 if(encType==ENUMERATEIMPLICATIONS && entry->output!= true)
326 else if(encType==ENUMERATEIMPLICATIONSNEGATE && entry->output !=false)
328 ArrayElement* inputs = &constraint->inputs;
329 uint inputNum =getSizeArrayElement(inputs);
330 Constraint* carray[inputNum];
331 for(uint j=0; j<inputNum; j++){
332 Element* el = getArrayElement(inputs, j);
333 Constraint* tmpc = getElementValueConstraint(This,el, entry->inputs[j]);
335 if( GETELEMENTTYPE(el) == ELEMFUNCRETURN){
336 Constraint* func =encodeFunctionElementSATEncoder(This, (ElementFunction*) el);
338 carray[j] = allocConstraint(AND, func, tmpc);
342 ASSERT(carray[j]!= NULL);
344 constraints[i]=allocArrayConstraint(AND, inputNum, carray);
346 Constraint* result= allocArrayConstraint(OR, size, constraints);
347 //FIXME: if it didn't match with any entry
348 return encType==ENUMERATEIMPLICATIONS? result: negateConstraint(result);
351 Constraint * encodeOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
352 switch(constraint->encoding.type){
353 case ENUMERATEIMPLICATIONS:
354 return encodeEnumOperatorPredicateSATEncoder(This, constraint);
364 Constraint * encodeEnumOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
365 ASSERT(GETPREDICATETYPE(constraint->predicate)==OPERATORPRED);
366 PredicateOperator* predicate = (PredicateOperator*)constraint->predicate;
367 ASSERT(predicate->op == EQUALS); //For now, we just only support equals
368 //getting maximum size of in common elements between two sets!
369 uint size=getSizeVectorInt( getArraySet( &predicate->domains, 0)->members);
370 uint64_t commonElements [size];
371 getEqualitySetIntersection(predicate, &size, commonElements);
372 Constraint* carray[size];
373 Element* elem1 = getArrayElement( &constraint->inputs, 0);
374 Constraint *elemc1 = NULL, *elemc2 = NULL;
375 if( GETELEMENTTYPE(elem1) == ELEMFUNCRETURN)
376 elemc1 = encodeFunctionElementSATEncoder(This, (ElementFunction*) elem1);
377 Element* elem2 = getArrayElement( &constraint->inputs, 1);
378 if( GETELEMENTTYPE(elem2) == ELEMFUNCRETURN)
379 elemc2 = encodeFunctionElementSATEncoder(This, (ElementFunction*) elem2);
380 for(uint i=0; i<size; i++){
381 Constraint* arg1 = getElementValueConstraint(This, elem1, commonElements[i]);
383 Constraint* arg2 = getElementValueConstraint(This, elem2, commonElements[i]);
384 ASSERT(arg2 != NULL);
385 carray[i] = allocConstraint(AND, arg1, arg2);
387 //FIXME: the case when there is no intersection ....
388 Constraint* result = allocArrayConstraint(OR, size, carray);
389 ASSERT(result!= NULL);
391 result = allocConstraint(AND, result, elemc1);
393 result = allocConstraint (AND, result, elemc2);
397 Constraint* encodeFunctionElementSATEncoder(SATEncoder* encoder, ElementFunction *This){
398 switch(GETFUNCTIONTYPE(This->function)){
400 return encodeTableElementFunctionSATEncoder(encoder, This);
402 return encodeOperatorElementFunctionSATEncoder(encoder, This);
409 Constraint* encodeTableElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
410 switch(getElementFunctionEncoding(This)->type){
411 case ENUMERATEIMPLICATIONS:
412 return encodeEnumTableElemFunctionSATEncoder(encoder, This);
423 Constraint* encodeOperatorElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
424 ASSERT(GETFUNCTIONTYPE(This->function) == OPERATORFUNC);
425 ASSERT(getSizeArrayElement(&This->inputs)==2 );
426 Constraint *elemc1=NULL, *elemc2 = NULL;
427 Element* elem1 = getArrayElement(&This->inputs,0);
428 Element* elem2 = getArrayElement(&This->inputs,1);
429 if( GETELEMENTTYPE(elem1) == ELEMFUNCRETURN)
430 elemc1 = encodeFunctionElementSATEncoder(encoder, (ElementFunction*) elem1);
431 if( GETELEMENTTYPE(elem2) == ELEMFUNCRETURN)
432 elemc2 = encodeFunctionElementSATEncoder(encoder , (ElementFunction*) elem2);
434 ElementEncoding* elemEnc1 = getElementEncoding( elem1 );
435 ElementEncoding* elemEnc2 = getElementEncoding( elem2 );
436 Constraint* carray[elemEnc1->encArraySize*elemEnc2->encArraySize];
438 Constraint* overFlowConstraint = ((BooleanVar*) This->overflowstatus)->var;
439 for(uint i=0; i<elemEnc1->encArraySize; i++){
440 if(isinUseElement(elemEnc1, i)){
441 for( uint j=0; j<elemEnc2->encArraySize; j++){
442 if(isinUseElement(elemEnc2, j)){
443 bool isInRange = false;
444 uint64_t result= applyFunctionOperator((FunctionOperator*)This->function,elemEnc1->encodingArray[i],
445 elemEnc2->encodingArray[j], &isInRange);
446 //FIXME: instead of getElementValueConstraint, it might be useful to have another function
447 // that doesn't iterate over encodingArray and treats more efficient ...
448 Constraint* valConstrIn1 = getElementValueConstraint(encoder, elemEnc1->element, elemEnc1->encodingArray[i]);
449 ASSERT(valConstrIn1 != NULL);
450 Constraint* valConstrIn2 = getElementValueConstraint(encoder, elemEnc2->element, elemEnc2->encodingArray[j]);
451 ASSERT(valConstrIn2 != NULL);
452 Constraint* valConstrOut = getElementValueConstraint(encoder, (Element*) This, result);
453 if(valConstrOut == NULL)
454 continue; //FIXME:Should talk to brian about it!
455 Constraint* OpConstraint = allocConstraint(IMPLIES,
456 allocConstraint(AND, valConstrIn1, valConstrIn2) , valConstrOut);
457 switch( ((FunctionOperator*)This->function)->overflowbehavior ){
460 carray[size++] = OpConstraint;
464 carray[size++] = OpConstraint;
466 case FLAGFORCESOVERFLOW:
468 Constraint* const1 = allocConstraint(IMPLIES,
469 allocConstraint(AND, valConstrIn1, valConstrIn2),
470 negateConstraint(overFlowConstraint));
471 carray[size++] = allocConstraint(AND, const1, OpConstraint);
474 case OVERFLOWSETSFLAG:
476 carray[size++] = OpConstraint;
478 carray[size++] = allocConstraint(IMPLIES,
479 allocConstraint(AND, valConstrIn1, valConstrIn2),
483 case FLAGIFFOVERFLOW:
485 Constraint* const1 = allocConstraint(IMPLIES,
486 allocConstraint(AND, valConstrIn1, valConstrIn2),
487 negateConstraint(overFlowConstraint));
488 carray[size++] = allocConstraint(AND, const1, OpConstraint);
490 carray[size++] = allocConstraint(IMPLIES,
491 allocConstraint(AND, valConstrIn1, valConstrIn2),
499 carray[size++] = OpConstraint;
509 Constraint* result = allocArrayConstraint(OR, size, carray);
511 result = allocConstraint(AND, result, elemc1);
513 result = allocConstraint(AND, result, elemc2);
517 Constraint* encodeEnumTableElemFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
518 ASSERT(GETFUNCTIONTYPE(This->function)==TABLEFUNC);
519 ArrayElement* elements= &This->inputs;
520 Table* table = ((FunctionTable*) (This->function))->table;
521 uint size = getSizeVectorTableEntry(&table->entries);
522 Constraint* constraints[size]; //FIXME: should add a space for the case that didn't match any entries
523 for(uint i=0; i<size; i++){
524 TableEntry* entry = getVectorTableEntry(&table->entries, i);
525 uint inputNum =getSizeArrayElement(elements);
526 Constraint* carray[inputNum];
527 for(uint j=0; j<inputNum; j++){
528 Element* el= getArrayElement(elements, j);
529 carray[j] = getElementValueConstraint(encoder, el, entry->inputs[j]);
530 ASSERT(carray[j]!= NULL);
532 Constraint* output = getElementValueConstraint(encoder, (Element*)This, entry->output);
533 ASSERT(output!= NULL);
534 Constraint* row= allocConstraint(IMPLIES, allocArrayConstraint(AND, inputNum, carray), output);
537 Constraint* result = allocArrayConstraint(OR, size, constraints);