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);
182 Constraint * encodeTotalOrderSATEncoder(SATEncoder *This, BooleanOrder * boolOrder){
183 ASSERT(boolOrder->order->type == TOTAL);
184 HashTableBoolConst* boolToConsts = boolOrder->order->boolsToConstraints;
185 OrderPair* pair = allocOrderPair(boolOrder->first, boolOrder->second);
186 if( !containsBoolConst(boolToConsts, pair) ){
187 createAllTotalOrderConstraintsSATEncoder(This, boolOrder->order);
189 Constraint* constraint = getOrderConstraint(boolToConsts, pair);
190 deleteOrderPair(pair);
194 void createAllTotalOrderConstraintsSATEncoder(SATEncoder* This, Order* order){
195 ASSERT(order->type == TOTAL);
196 VectorInt* mems = order->set->members;
197 HashTableBoolConst* table = order->boolsToConstraints;
198 uint size = getSizeVectorInt(mems);
199 for(uint i=0; i<size; i++){
200 uint64_t valueI = getVectorInt(mems, i);
201 for(uint j=i+1; j<size;j++){
202 uint64_t valueJ = getVectorInt(mems, j);
203 OrderPair* pairIJ = allocOrderPair(valueI, valueJ);
204 ASSERT(!containsBoolConst(table, pairIJ));
205 Constraint* constIJ = getNewVarSATEncoder(This);
206 putBoolConst(table, pairIJ, constIJ);
207 for(uint k=j+1; k<size; k++){
208 uint64_t valueK = getVectorInt(mems, k);
209 OrderPair* pairJK = allocOrderPair(valueJ, valueK);
210 OrderPair* pairIK = allocOrderPair(valueI, valueK);
211 Constraint* constJK, *constIK;
212 if(!containsBoolConst(table, pairJK)){
213 constJK = getNewVarSATEncoder(This);
214 putBoolConst(table, pairJK, constJK);
216 if(!containsBoolConst(table, pairIK)){
217 constIK = getNewVarSATEncoder(This);
218 putBoolConst(table, pairIK, constIK);
220 generateTransOrderConstraintSATEncoder(This, constIJ, constJK, constIK);
226 Constraint* getOrderConstraint(HashTableBoolConst *table, OrderPair *pair){
227 ASSERT(pair->first!= pair->second);
228 Constraint* constraint= getBoolConst(table, pair);
229 ASSERT(constraint!= NULL);
230 if(pair->first > pair->second)
233 return negateConstraint(constraint);
236 Constraint * generateTransOrderConstraintSATEncoder(SATEncoder *This, Constraint *constIJ,Constraint *constJK,Constraint *constIK){
237 //FIXME: first we should add the the constraint to the satsolver!
238 Constraint *carray[] = {constIJ, constJK, negateConstraint(constIK)};
239 Constraint * loop1= allocArrayConstraint(OR, 3, carray);
240 Constraint * carray2[] = {negateConstraint(constIJ), negateConstraint(constJK), constIK};
241 Constraint * loop2= allocArrayConstraint(OR, 3,carray2 );
242 return allocConstraint(AND, loop1, loop2);
245 Constraint * encodePartialOrderSATEncoder(SATEncoder *This, BooleanOrder * constraint){
246 // FIXME: we can have this implementation for partial order. Basically,
247 // we compute the transitivity between two order constraints specified by the client! (also can be used
248 // when client specify sparse constraints for the total order!)
249 ASSERT(boolOrder->order->type == PARTIAL);
251 HashTableBoolConst* boolToConsts = boolOrder->order->boolsToConstraints;
252 if( containsBoolConst(boolToConsts, boolOrder) ){
253 return getBoolConst(boolToConsts, boolOrder);
255 Constraint* constraint = getNewVarSATEncoder(This);
256 putBoolConst(boolToConsts,boolOrder, constraint);
257 VectorBoolean* orderConstrs = &boolOrder->order->constraints;
258 uint size= getSizeVectorBoolean(orderConstrs);
259 for(uint i=0; i<size; i++){
260 ASSERT(GETBOOLEANTYPE( getVectorBoolean(orderConstrs, i)) == ORDERCONST );
261 BooleanOrder* tmp = (BooleanOrder*)getVectorBoolean(orderConstrs, i);
262 BooleanOrder* newBool;
263 Constraint* first, *second;
264 if(tmp->second==boolOrder->first){
265 newBool = (BooleanOrder*)allocBooleanOrder(tmp->order,tmp->first,boolOrder->second);
266 first = encodeTotalOrderSATEncoder(This, tmp);
269 }else if (boolOrder->second == tmp->first){
270 newBool = (BooleanOrder*)allocBooleanOrder(tmp->order,boolOrder->first,tmp->second);
272 second = encodeTotalOrderSATEncoder(This, tmp);
275 Constraint* transConstr= encodeTotalOrderSATEncoder(This, newBool);
276 generateTransOrderConstraintSATEncoder(This, first, second, transConstr );
284 Constraint * encodePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint) {
285 switch(GETPREDICATETYPE(constraint->predicate) ){
287 return encodeTablePredicateSATEncoder(This, constraint);
289 return encodeOperatorPredicateSATEncoder(This, constraint);
296 Constraint * encodeTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
297 switch(constraint->encoding.type){
298 case ENUMERATEIMPLICATIONS:
299 case ENUMERATEIMPLICATIONSNEGATE:
300 return encodeEnumTablePredicateSATEncoder(This, constraint);
310 Constraint * encodeEnumTablePredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
311 VectorTableEntry* entries = &(((PredicateTable*)constraint->predicate)->table->entries);
312 FunctionEncodingType encType = constraint->encoding.type;
313 uint size = getSizeVectorTableEntry(entries);
314 Constraint* constraints[size];
315 for(uint i=0; i<size; i++){
316 TableEntry* entry = getVectorTableEntry(entries, i);
317 if(encType==ENUMERATEIMPLICATIONS && entry->output!= true)
319 else if(encType==ENUMERATEIMPLICATIONSNEGATE && entry->output !=false)
321 ArrayElement* inputs = &constraint->inputs;
322 uint inputNum =getSizeArrayElement(inputs);
323 Constraint* carray[inputNum];
324 Element* el = getArrayElement(inputs, i);
325 for(uint j=0; j<inputNum; j++){
326 carray[j] = getElementValueConstraint(el, entry->inputs[j]);
328 constraints[i]=allocArrayConstraint(AND, inputNum, carray);
330 Constraint* result= allocArrayConstraint(OR, size, constraints);
331 //FIXME: if it didn't match with any entry
332 return encType==ENUMERATEIMPLICATIONS? result: negateConstraint(result);
335 Constraint * encodeOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
336 switch(constraint->encoding.type){
337 case ENUMERATEIMPLICATIONS:
338 return encodeEnumOperatorPredicateSATEncoder(This, constraint);
348 Constraint * encodeEnumOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
349 ASSERT(GETPREDICATETYPE(constraint)==OPERATORPRED);
350 PredicateOperator* predicate = (PredicateOperator*)constraint->predicate;
351 ASSERT(predicate->op == EQUALS); //For now, we just only support equals
352 //getting maximum size of in common elements between two sets!
353 uint size=getSizeVectorInt( getArraySet( &predicate->domains, 0)->members);
354 uint64_t commonElements [size];
355 getEqualitySetIntersection(predicate, &size, commonElements);
356 Constraint* carray[size];
357 Element* elem1 = getArrayElement( &constraint->inputs, 0);
358 Element* elem2 = getArrayElement( &constraint->inputs, 1);
359 for(uint i=0; i<size; i++){
361 carray[i] = allocConstraint(AND, getElementValueConstraint(elem1, commonElements[i]),
362 getElementValueConstraint(elem2, commonElements[i]) );
364 //FIXME: the case when there is no intersection ....
365 return allocArrayConstraint(OR, size, carray);
368 Constraint* encodeFunctionElementSATEncoder(SATEncoder* encoder, ElementFunction *This){
369 switch(GETFUNCTIONTYPE(This->function)){
371 return encodeTableElementFunctionSATEncoder(encoder, This);
373 return encodeOperatorElementFunctionSATEncoder(encoder, This);
380 Constraint* encodeTableElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
381 switch(getElementFunctionEncoding(This)->type){
382 case ENUMERATEIMPLICATIONS:
383 return encodeEnumTableElemFunctionSATEncoder(encoder, This);
394 Constraint* encodeOperatorElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
395 //FIXME: for now it just adds/substracts inputs exhustively
399 Constraint* encodeEnumTableElemFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
400 ASSERT(GETFUNCTIONTYPE(This->function)==TABLEFUNC);
401 ArrayElement* elements= &This->inputs;
402 Table* table = ((FunctionTable*) (This->function))->table;
403 uint size = getSizeVectorTableEntry(&table->entries);
404 Constraint* constraints[size]; //FIXME: should add a space for the case that didn't match any entries
405 for(uint i=0; i<size; i++){
406 TableEntry* entry = getVectorTableEntry(&table->entries, i);
407 uint inputNum =getSizeArrayElement(elements);
408 Element* el= getArrayElement(elements, i);
409 Constraint* carray[inputNum];
410 for(uint j=0; j<inputNum; j++){
411 carray[inputNum] = getElementValueConstraint(el, entry->inputs[j]);
413 Constraint* row= allocConstraint(IMPLIES, allocArrayConstraint(AND, inputNum, carray),
414 getElementValueBinaryIndexConstraint((Element*)This, entry->output));
417 Constraint* result = allocArrayConstraint(OR, size, constraints);