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));
22 void deleteSATEncoder(SATEncoder *This) {
26 void initializeConstraintVars(CSolver* csolver, SATEncoder* This){
27 /** We really should not walk the free list to generate constraint
28 variables...walk the constraint tree instead. Or even better
29 yet, just do this as you need to during the encodeAllSATEncoder
32 // FIXME!!!!(); // Make sure Hamed sees comment above
34 uint size = getSizeVectorElement(csolver->allElements);
35 for(uint i=0; i<size; i++){
36 Element* element = getVectorElement(csolver->allElements, i);
37 generateElementEncodingVariables(This,getElementEncoding(element));
42 Constraint * getElementValueConstraint(Element* This, uint64_t value) {
43 switch(getElementEncoding(This)->type){
54 return getElementValueBinaryIndexConstraint(This, value);
65 Constraint * getElementValueBinaryIndexConstraint(Element* This, uint64_t value) {
66 ASTNodeType type = GETELEMENTTYPE(This);
67 ASSERT(type == ELEMSET || type == ELEMFUNCRETURN);
68 ElementEncoding* elemEnc = getElementEncoding(This);
69 for(uint i=0; i<elemEnc->encArraySize; i++){
70 if( isinUseElement(elemEnc, i) && elemEnc->encodingArray[i]==value){
71 return generateBinaryConstraint(elemEnc->numVars,
72 elemEnc->variables, i);
78 void encodeAllSATEncoder(CSolver *csolver, SATEncoder * This) {
79 VectorBoolean *constraints=csolver->constraints;
80 uint size=getSizeVectorBoolean(constraints);
81 for(uint i=0;i<size;i++) {
82 Boolean *constraint=getVectorBoolean(constraints, i);
83 encodeConstraintSATEncoder(This, constraint);
86 // FIXME: Following line for element!
87 // size = getSizeVectorElement(csolver->allElements);
88 // for(uint i=0; i<size; i++){
89 // Element* element = getVectorElement(csolver->allElements, i);
90 // switch(GETELEMENTTYPE(element)){
91 // case ELEMFUNCRETURN:
92 // encodeFunctionElementSATEncoder(This, (ElementFunction*) element);
96 // //ElementSets that aren't used in any constraints/functions
97 // //will be eliminated.
102 Constraint * encodeConstraintSATEncoder(SATEncoder *This, Boolean *constraint) {
103 switch(GETBOOLEANTYPE(constraint)) {
105 return encodeOrderSATEncoder(This, (BooleanOrder *) constraint);
107 return encodeVarSATEncoder(This, (BooleanVar *) constraint);
109 return encodeLogicSATEncoder(This, (BooleanLogic *) constraint);
111 return encodePredicateSATEncoder(This, (BooleanPredicate *) constraint);
113 model_print("Unhandled case in encodeConstraintSATEncoder %u", GETBOOLEANTYPE(constraint));
118 void getArrayNewVarsSATEncoder(SATEncoder* encoder, uint num, Constraint **carray) {
119 for(uint i=0;i<num;i++)
120 carray[i]=getNewVarSATEncoder(encoder);
123 Constraint * getNewVarSATEncoder(SATEncoder *This) {
124 Constraint * var=allocVarConstraint(VAR, This->varcount);
125 Constraint * varneg=allocVarConstraint(NOTVAR, This->varcount++);
126 setNegConstraint(var, varneg);
127 setNegConstraint(varneg, var);
131 Constraint * encodeVarSATEncoder(SATEncoder *This, BooleanVar * constraint) {
132 if (constraint->var == NULL) {
133 constraint->var=getNewVarSATEncoder(This);
135 return constraint->var;
138 Constraint * encodeLogicSATEncoder(SATEncoder *This, BooleanLogic * constraint) {
139 Constraint * array[getSizeArrayBoolean(&constraint->inputs)];
140 for(uint i=0;i<getSizeArrayBoolean(&constraint->inputs);i++)
141 array[i]=encodeConstraintSATEncoder(This, getArrayBoolean(&constraint->inputs, i));
143 switch(constraint->op) {
145 return allocArrayConstraint(AND, getSizeArrayBoolean(&constraint->inputs), array);
147 return allocArrayConstraint(OR, getSizeArrayBoolean(&constraint->inputs), array);
149 ASSERT(constraint->numArray==1);
150 return negateConstraint(array[0]);
152 ASSERT(constraint->numArray==2);
153 Constraint * nleft=negateConstraint(cloneConstraint(array[0]));
154 Constraint * nright=negateConstraint(cloneConstraint(array[1]));
155 return allocConstraint(OR,
156 allocConstraint(AND, array[0], nright),
157 allocConstraint(AND, nleft, array[1]));
160 ASSERT(constraint->numArray==2);
161 return allocConstraint(IMPLIES, array[0], array[1]);
163 model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op);
169 Constraint * encodeOrderSATEncoder(SATEncoder *This, BooleanOrder * constraint) {
170 switch( constraint->order->type){
172 return encodePartialOrderSATEncoder(This, constraint);
174 return encodeTotalOrderSATEncoder(This, constraint);
181 Constraint * getPairConstraint(SATEncoder *This, HashTableBoolConst * table, OrderPair * pair) {
184 if (pair->first > pair->second) {
186 flipped.first=pair->second;
187 flipped.second=pair->first;
190 Constraint * constraint;
191 if (!containsBoolConst(table, pair)) {
192 constraint = getNewVarSATEncoder(This);
193 OrderPair * paircopy = allocOrderPair(pair->first, pair->second);
194 putBoolConst(table, paircopy, constraint);
196 constraint = getBoolConst(table, pair);
198 return negateConstraint(constraint);
204 Constraint * encodeTotalOrderSATEncoder(SATEncoder *This, BooleanOrder * boolOrder){
205 ASSERT(boolOrder->order->type == TOTAL);
206 HashTableBoolConst* boolToConsts = boolOrder->order->boolsToConstraints;
207 OrderPair pair={boolOrder->first, boolOrder->second};
208 Constraint* constraint = getPairConstraint(This, boolToConsts, & pair);
212 void createAllTotalOrderConstraintsSATEncoder(SATEncoder* This, Order* order){
213 ASSERT(order->type == TOTAL);
214 VectorInt* mems = order->set->members;
215 HashTableBoolConst* table = order->boolsToConstraints;
216 uint size = getSizeVectorInt(mems);
217 for(uint i=0; i<size; i++){
218 uint64_t valueI = getVectorInt(mems, i);
219 for(uint j=i+1; j<size;j++){
220 uint64_t valueJ = getVectorInt(mems, j);
221 OrderPair pairIJ = {valueI, valueJ};
222 Constraint* constIJ=getPairConstraint(This, table, & pairIJ);
223 for(uint k=j+1; k<size; k++){
224 uint64_t valueK = getVectorInt(mems, k);
225 OrderPair pairJK = {valueJ, valueK};
226 OrderPair pairIK = {valueI, valueK};
227 Constraint* constIK = getPairConstraint(This, table, & pairIK);
228 Constraint* constJK = getPairConstraint(This, table, & pairJK);
229 generateTransOrderConstraintSATEncoder(This, constIJ, constJK, constIK);
235 Constraint* getOrderConstraint(HashTableBoolConst *table, OrderPair *pair){
236 ASSERT(pair->first!= pair->second);
237 Constraint* constraint= getBoolConst(table, pair);
238 ASSERT(constraint!= NULL);
239 if(pair->first > pair->second)
242 return negateConstraint(constraint);
245 Constraint * generateTransOrderConstraintSATEncoder(SATEncoder *This, Constraint *constIJ,Constraint *constJK,Constraint *constIK){
246 //FIXME: first we should add the the constraint to the satsolver!
247 Constraint *carray[] = {constIJ, constJK, negateConstraint(constIK)};
248 Constraint * loop1= allocArrayConstraint(OR, 3, carray);
249 Constraint * carray2[] = {negateConstraint(constIJ), negateConstraint(constJK), constIK};
250 Constraint * loop2= allocArrayConstraint(OR, 3,carray2 );
251 return allocConstraint(AND, loop1, loop2);
254 Constraint * encodePartialOrderSATEncoder(SATEncoder *This, BooleanOrder * constraint){
255 // FIXME: we can have this implementation for partial order. Basically,
256 // we compute the transitivity between two order constraints specified by the client! (also can be used
257 // when client specify sparse constraints for the total order!)
258 ASSERT(boolOrder->order->type == PARTIAL);
260 HashTableBoolConst* boolToConsts = boolOrder->order->boolsToConstraints;
261 if( containsBoolConst(boolToConsts, boolOrder) ){
262 return getBoolConst(boolToConsts, boolOrder);
264 Constraint* constraint = getNewVarSATEncoder(This);
265 putBoolConst(boolToConsts,boolOrder, constraint);
266 VectorBoolean* orderConstrs = &boolOrder->order->constraints;
267 uint size= getSizeVectorBoolean(orderConstrs);
268 for(uint i=0; i<size; i++){
269 ASSERT(GETBOOLEANTYPE( getVectorBoolean(orderConstrs, i)) == ORDERCONST );
270 BooleanOrder* tmp = (BooleanOrder*)getVectorBoolean(orderConstrs, i);
271 BooleanOrder* newBool;
272 Constraint* first, *second;
273 if(tmp->second==boolOrder->first){
274 newBool = (BooleanOrder*)allocBooleanOrder(tmp->order,tmp->first,boolOrder->second);
275 first = encodeTotalOrderSATEncoder(This, tmp);
278 }else if (boolOrder->second == tmp->first){
279 newBool = (BooleanOrder*)allocBooleanOrder(tmp->order,boolOrder->first,tmp->second);
281 second = encodeTotalOrderSATEncoder(This, tmp);
284 Constraint* transConstr= encodeTotalOrderSATEncoder(This, newBool);
285 generateTransOrderConstraintSATEncoder(This, first, second, transConstr );
293 Constraint * encodePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint) {
294 switch(GETPREDICATETYPE(constraint->predicate) ){
296 return encodeTablePredicateSATEncoder(This, constraint);
298 return encodeOperatorPredicateSATEncoder(This, constraint);
305 Constraint * encodeTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
306 switch(constraint->encoding.type){
307 case ENUMERATEIMPLICATIONS:
308 case ENUMERATEIMPLICATIONSNEGATE:
309 return encodeEnumTablePredicateSATEncoder(This, constraint);
319 Constraint * encodeEnumTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
320 VectorTableEntry* entries = &(((PredicateTable*)constraint->predicate)->table->entries);
321 FunctionEncodingType encType = constraint->encoding.type;
322 uint size = getSizeVectorTableEntry(entries);
323 Constraint* constraints[size];
324 for(uint i=0; i<size; i++){
325 TableEntry* entry = getVectorTableEntry(entries, i);
326 if(encType==ENUMERATEIMPLICATIONS && entry->output!= true)
328 else if(encType==ENUMERATEIMPLICATIONSNEGATE && entry->output !=false)
330 ArrayElement* inputs = &constraint->inputs;
331 uint inputNum =getSizeArrayElement(inputs);
332 Constraint* carray[inputNum];
333 Element* el = getArrayElement(inputs, i);
334 for(uint j=0; j<inputNum; j++){
335 carray[j] = getElementValueConstraint(el, entry->inputs[j]);
337 constraints[i]=allocArrayConstraint(AND, inputNum, carray);
339 Constraint* result= allocArrayConstraint(OR, size, constraints);
340 //FIXME: if it didn't match with any entry
341 return encType==ENUMERATEIMPLICATIONS? result: negateConstraint(result);
344 Constraint * encodeOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
345 switch(constraint->encoding.type){
346 case ENUMERATEIMPLICATIONS:
347 return encodeEnumOperatorPredicateSATEncoder(This, constraint);
357 Constraint * encodeEnumOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
358 ASSERT(GETPREDICATETYPE(constraint)==OPERATORPRED);
359 PredicateOperator* predicate = (PredicateOperator*)constraint->predicate;
360 ASSERT(predicate->op == EQUALS); //For now, we just only support equals
361 //getting maximum size of in common elements between two sets!
362 uint size=getSizeVectorInt( getArraySet( &predicate->domains, 0)->members);
363 uint64_t commonElements [size];
364 getEqualitySetIntersection(predicate, &size, commonElements);
365 Constraint* carray[size];
366 Element* elem1 = getArrayElement( &constraint->inputs, 0);
367 Element* elem2 = getArrayElement( &constraint->inputs, 1);
368 for(uint i=0; i<size; i++){
370 carray[i] = allocConstraint(AND, getElementValueConstraint(elem1, commonElements[i]),
371 getElementValueConstraint(elem2, commonElements[i]) );
373 //FIXME: the case when there is no intersection ....
374 return allocArrayConstraint(OR, size, carray);
377 Constraint* encodeFunctionElementSATEncoder(SATEncoder* encoder, ElementFunction *This){
378 switch(GETFUNCTIONTYPE(This->function)){
380 return encodeTableElementFunctionSATEncoder(encoder, This);
382 return encodeOperatorElementFunctionSATEncoder(encoder, This);
389 Constraint* encodeTableElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
390 switch(getElementFunctionEncoding(This)->type){
391 case ENUMERATEIMPLICATIONS:
392 return encodeEnumTableElemFunctionSATEncoder(encoder, This);
403 Constraint* encodeOperatorElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
404 //FIXME: for now it just adds/substracts inputs exhustively
408 Constraint* encodeEnumTableElemFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
409 ASSERT(GETFUNCTIONTYPE(This->function)==TABLEFUNC);
410 ArrayElement* elements= &This->inputs;
411 Table* table = ((FunctionTable*) (This->function))->table;
412 uint size = getSizeVectorTableEntry(&table->entries);
413 Constraint* constraints[size]; //FIXME: should add a space for the case that didn't match any entries
414 for(uint i=0; i<size; i++){
415 TableEntry* entry = getVectorTableEntry(&table->entries, i);
416 uint inputNum =getSizeArrayElement(elements);
417 Element* el= getArrayElement(elements, i);
418 Constraint* carray[inputNum];
419 for(uint j=0; j<inputNum; j++){
420 carray[inputNum] = getElementValueConstraint(el, entry->inputs[j]);
422 Constraint* row= allocConstraint(IMPLIES, allocArrayConstraint(AND, inputNum, carray),
423 getElementValueBinaryIndexConstraint((Element*)This, entry->output));
426 Constraint* result = allocArrayConstraint(OR, size, constraints);