1 #include "satencoder.h"
5 #include "constraint.h"
9 #include "tableentry.h"
12 #include "predicate.h"
15 SATEncoder * allocSATEncoder() {
16 SATEncoder *This=ourmalloc(sizeof (SATEncoder));
18 This->cnf=createCNF();
22 void deleteSATEncoder(SATEncoder *This) {
27 void encodeAllSATEncoder(CSolver *csolver, SATEncoder * This) {
28 VectorBoolean *constraints=csolver->constraints;
29 uint size=getSizeVectorBoolean(constraints);
30 for(uint i=0;i<size;i++) {
31 Boolean *constraint=getVectorBoolean(constraints, i);
32 Edge c= encodeConstraintSATEncoder(This, constraint);
35 addConstraintCNF(This->cnf, c);
39 Edge encodeConstraintSATEncoder(SATEncoder *This, Boolean *constraint) {
40 switch(GETBOOLEANTYPE(constraint)) {
42 return encodeOrderSATEncoder(This, (BooleanOrder *) constraint);
44 return encodeVarSATEncoder(This, (BooleanVar *) constraint);
46 return encodeLogicSATEncoder(This, (BooleanLogic *) constraint);
48 return encodePredicateSATEncoder(This, (BooleanPredicate *) constraint);
50 model_print("Unhandled case in encodeConstraintSATEncoder %u", GETBOOLEANTYPE(constraint));
55 void getArrayNewVarsSATEncoder(SATEncoder* encoder, uint num, Edge * carray) {
56 for(uint i=0;i<num;i++)
57 carray[i]=getNewVarSATEncoder(encoder);
60 Edge getNewVarSATEncoder(SATEncoder *This) {
61 return constraintNewVar(This->cnf);
64 Edge encodeVarSATEncoder(SATEncoder *This, BooleanVar * constraint) {
65 if (edgeIsNull(constraint->var)) {
66 constraint->var=getNewVarSATEncoder(This);
68 return constraint->var;
71 Edge encodeLogicSATEncoder(SATEncoder *This, BooleanLogic * constraint) {
72 Edge array[getSizeArrayBoolean(&constraint->inputs)];
73 for(uint i=0;i<getSizeArrayBoolean(&constraint->inputs);i++)
74 array[i]=encodeConstraintSATEncoder(This, getArrayBoolean(&constraint->inputs, i));
76 switch(constraint->op) {
78 return constraintAND(This->cnf, getSizeArrayBoolean(&constraint->inputs), array);
80 return constraintOR(This->cnf, getSizeArrayBoolean(&constraint->inputs), array);
82 ASSERT( getSizeArrayBoolean(&constraint->inputs)==1);
83 return constraintNegate(array[0]);
85 ASSERT( getSizeArrayBoolean(&constraint->inputs)==2);
86 return constraintXOR(This->cnf, array[0], array[1]);
88 ASSERT( getSizeArrayBoolean( &constraint->inputs)==2);
89 return constraintIMPLIES(This->cnf, array[0], array[1]);
91 model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op);
96 Edge encodePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint) {
97 switch(GETPREDICATETYPE(constraint->predicate) ){
99 return encodeTablePredicateSATEncoder(This, constraint);
101 return encodeOperatorPredicateSATEncoder(This, constraint);
108 Edge encodeTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
109 switch(constraint->encoding.type){
110 case ENUMERATEIMPLICATIONS:
111 case ENUMERATEIMPLICATIONSNEGATE:
112 return encodeEnumTablePredicateSATEncoder(This, constraint);
122 Edge encodeEnumTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
123 VectorTableEntry* entries = &(((PredicateTable*)constraint->predicate)->table->entries);
124 FunctionEncodingType encType = constraint->encoding.type;
125 ArrayElement* inputs = &constraint->inputs;
126 uint inputNum =getSizeArrayElement(inputs);
127 //Encode all the inputs first ...
128 for(uint i=0; i<inputNum; i++){
129 encodeElementSATEncoder(This, getArrayElement(inputs, i));
132 //WARNING: THIS ASSUMES PREDICATE TABLE IS COMPLETE...SEEMS UNLIKELY TO BE SAFE IN MANY CASES...
133 //WONDER WHAT BEST WAY TO HANDLE THIS IS...
135 uint size = getSizeVectorTableEntry(entries);
136 bool generateNegation = encType == ENUMERATEIMPLICATIONSNEGATE;
137 Edge constraints[size];
138 for(uint i=0; i<size; i++){
139 TableEntry* entry = getVectorTableEntry(entries, i);
140 if(generateNegation == entry->output) {
141 //Skip the irrelevant entries
144 Edge carray[inputNum];
145 for(uint j=0; j<inputNum; j++){
146 Element* el = getArrayElement(inputs, j);
147 carray[j] = getElementValueConstraint(This, el, entry->inputs[j]);
149 constraints[i]=constraintAND(This->cnf, inputNum, carray);
151 Edge result=constraintOR(This->cnf, size, constraints);
153 return generateNegation ? result: constraintNegate(result);
156 Edge encodeOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint) {
157 switch(constraint->encoding.type){
158 case ENUMERATEIMPLICATIONS:
159 return encodeEnumOperatorPredicateSATEncoder(This, constraint);
169 Edge encodeEnumOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint) {
170 PredicateOperator* predicate = (PredicateOperator*)constraint->predicate;
171 uint numDomains=getSizeArraySet(&predicate->domains);
173 FunctionEncodingType encType = constraint->encoding.type;
174 bool generateNegation = encType == ENUMERATEIMPLICATIONSNEGATE;
176 /* Call base encoders for children */
177 for(uint i=0;i<numDomains;i++) {
178 Element *elem = getArrayElement( &constraint->inputs, i);
179 encodeElementSATEncoder(This, elem);
181 VectorEdge * clauses=allocDefVectorEdge(); // Setup array of clauses
183 uint indices[numDomains]; //setup indices
184 bzero(indices, sizeof(uint)*numDomains);
186 uint64_t vals[numDomains]; //setup value array
187 for(uint i=0;i<numDomains; i++) {
188 Set * set=getArraySet(&predicate->domains, i);
189 vals[i]=getSetElement(set, indices[i]);
192 bool notfinished=true;
194 Edge carray[numDomains];
196 if (evalPredicateOperator(predicate, vals) ^ generateNegation) {
197 //Include this in the set of terms
198 for(uint i=0;i<numDomains;i++) {
199 Element * elem = getArrayElement(&constraint->inputs, i);
200 carray[i] = getElementValueConstraint(This, elem, vals[i]);
202 pushVectorEdge(clauses, constraintAND(This->cnf, numDomains, carray));
206 for(uint i=0;i<numDomains; i++) {
207 uint index=++indices[i];
208 Set * set=getArraySet(&predicate->domains, i);
210 if (index < getSetSize(set)) {
211 vals[i]=getSetElement(set, index);
216 vals[i]=getSetElement(set, 0);
221 Edge cor=constraintOR(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses));
222 deleteVectorEdge(clauses);
223 return generateNegation ? cor : constraintNegate(cor);
226 void encodeElementSATEncoder(SATEncoder* encoder, Element *This){
227 switch( GETELEMENTTYPE(This) ){
229 addConstraintCNF(encoder->cnf, encodeElementFunctionSATEncoder(encoder, (ElementFunction*) This));
238 Edge encodeElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction *This){
239 switch(GETFUNCTIONTYPE(This->function)){
241 return encodeTableElementFunctionSATEncoder(encoder, This);
243 return encodeOperatorElementFunctionSATEncoder(encoder, This);
250 Edge encodeTableElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
251 switch(getElementFunctionEncoding(This)->type){
252 case ENUMERATEIMPLICATIONS:
253 return encodeEnumTableElemFunctionSATEncoder(encoder, This);
264 Edge encodeOperatorElementFunctionSATEncoder(SATEncoder* This, ElementFunction* func) {
265 FunctionOperator * function = (FunctionOperator *) func->function;
266 uint numDomains=getSizeArrayElement(&func->inputs);
268 /* Call base encoders for children */
269 for(uint i=0;i<numDomains;i++) {
270 Element *elem = getArrayElement( &func->inputs, i);
271 encodeElementSATEncoder(This, elem);
274 VectorEdge * clauses=allocDefVectorEdge(); // Setup array of clauses
276 uint indices[numDomains]; //setup indices
277 bzero(indices, sizeof(uint)*numDomains);
279 uint64_t vals[numDomains]; //setup value array
280 for(uint i=0;i<numDomains; i++) {
281 Set * set=getElementSet(getArrayElement(&func->inputs, i));
282 vals[i]=getSetElement(set, indices[i]);
285 Edge overFlowConstraint = ((BooleanVar*) func->overflowstatus)->var;
287 bool notfinished=true;
289 Edge carray[numDomains+2];
291 uint64_t result=applyFunctionOperator(function, numDomains, vals);
292 bool isInRange = isInRangeFunction((FunctionOperator*)func->function, result);
293 bool needClause = isInRange;
294 if (function->overflowbehavior == OVERFLOWSETSFLAG || function->overflowbehavior == FLAGIFFOVERFLOW) {
299 //Include this in the set of terms
300 for(uint i=0;i<numDomains;i++) {
301 Element * elem = getArrayElement(&func->inputs, i);
302 carray[i] = getElementValueConstraint(This, elem, vals[i]);
305 carray[numDomains] = getElementValueConstraint(This, &func->base, result);
309 switch(function->overflowbehavior) {
313 clause=constraintAND(This->cnf, numDomains+1, carray);
316 case FLAGFORCESOVERFLOW: {
317 carray[numDomains+1]=constraintNegate(overFlowConstraint);
318 clause=constraintAND(This->cnf, numDomains+2, carray);
321 case OVERFLOWSETSFLAG: {
323 clause=constraintAND(This->cnf, numDomains+1, carray);
325 carray[numDomains+1]=overFlowConstraint;
326 clause=constraintAND(This->cnf, numDomains+1, carray);
330 case FLAGIFFOVERFLOW: {
332 carray[numDomains+1]=constraintNegate(overFlowConstraint);
333 clause=constraintAND(This->cnf, numDomains+2, carray);
335 carray[numDomains+1]=overFlowConstraint;
336 clause=constraintAND(This->cnf, numDomains+1, carray);
343 pushVectorEdge(clauses, clause);
347 for(uint i=0;i<numDomains; i++) {
348 uint index=++indices[i];
349 Set * set=getElementSet(getArrayElement(&func->inputs, i));
351 if (index < getSetSize(set)) {
352 vals[i]=getSetElement(set, index);
357 vals[i]=getSetElement(set, 0);
362 Edge cor=constraintOR(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses));
363 deleteVectorEdge(clauses);
367 Edge encodeEnumTableElemFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
368 //FIXME: HANDLE UNDEFINED BEHAVIORS
369 ASSERT(GETFUNCTIONTYPE(This->function)==TABLEFUNC);
370 ArrayElement* elements= &This->inputs;
371 Table* table = ((FunctionTable*) (This->function))->table;
372 uint size = getSizeVectorTableEntry(&table->entries);
373 Edge constraints[size]; //FIXME: should add a space for the case that didn't match any entries
374 for(uint i=0; i<size; i++) {
375 TableEntry* entry = getVectorTableEntry(&table->entries, i);
376 uint inputNum = getSizeArrayElement(elements);
377 Edge carray[inputNum];
378 for(uint j=0; j<inputNum; j++){
379 Element* el= getArrayElement(elements, j);
380 carray[j] = getElementValueConstraint(encoder, el, entry->inputs[j]);
382 Edge output = getElementValueConstraint(encoder, (Element*)This, entry->output);
383 Edge row= constraintIMPLIES(encoder->cnf, constraintAND(encoder->cnf, inputNum, carray), output);
386 return constraintOR(encoder->cnf, size, constraints);