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) ){
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]; //FIXME: should add a space for the case that didn't match any entries
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[inputNum] = getElementValueConstraint(el, entry->inputs[j]);
328 constraints[i]=allocArrayConstraint(AND, inputNum, carray);
330 Constraint* result= allocArrayConstraint(OR, size, constraints);
331 return encType==ENUMERATEIMPLICATIONS? result: negateConstraint(result);
334 Constraint * encodeOperatorPredicateSATEncoder(SATEncoder * This, BooleanPredicate * constraint){
335 switch(constraint->encoding.type){
336 case ENUMERATEIMPLICATIONS:
346 Constraint* encodeFunctionElementSATEncoder(SATEncoder* encoder, ElementFunction *This){
347 switch(GETFUNCTIONTYPE(This->function)){
349 return encodeTableElementFunctionSATEncoder(encoder, This);
351 return encodeOperatorElementFunctionSATEncoder(encoder, This);
358 Constraint* encodeTableElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
359 switch(getElementFunctionEncoding(This)->type){
360 case ENUMERATEIMPLICATIONS:
361 return encodeEnumTableElemFunctionSATEncoder(encoder, This);
372 Constraint* encodeOperatorElementFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
373 //FIXME: for now it just adds/substracts inputs exhustively
377 Constraint* encodeEnumTableElemFunctionSATEncoder(SATEncoder* encoder, ElementFunction* This){
378 ASSERT(GETFUNCTIONTYPE(This->function)==TABLEFUNC);
379 ArrayElement* elements= &This->inputs;
380 Table* table = ((FunctionTable*) (This->function))->table;
381 uint size = getSizeVectorTableEntry(&table->entries);
382 Constraint* constraints[size]; //FIXME: should add a space for the case that didn't match any entries
383 for(uint i=0; i<size; i++){
384 TableEntry* entry = getVectorTableEntry(&table->entries, i);
385 uint inputNum =getSizeArrayElement(elements);
386 Element* el= getArrayElement(elements, i);
387 Constraint* carray[inputNum];
388 for(uint j=0; j<inputNum; j++){
389 carray[inputNum] = getElementValueConstraint(el, entry->inputs[j]);
391 Constraint* row= allocConstraint(IMPLIES, allocArrayConstraint(AND, inputNum, carray),
392 getElementValueBinaryIndexConstraint((Element*)This, entry->output));
395 Constraint* result = allocArrayConstraint(OR, size, constraints);