Fixing bugs ...
[satune.git] / src / csolver.cc
1 #include "csolver.h"
2 #include "set.h"
3 #include "mutableset.h"
4 #include "element.h"
5 #include "boolean.h"
6 #include "predicate.h"
7 #include "order.h"
8 #include "table.h"
9 #include "function.h"
10 #include "satencoder.h"
11 #include "sattranslator.h"
12 #include "tunable.h"
13 #include "polarityassignment.h"
14 #include "decomposeordertransform.h"
15 #include "autotuner.h"
16 #include "astops.h"
17 #include "structs.h"
18 #include "orderresolver.h"
19 #include "integerencoding.h"
20 #include "qsort.h"
21 #include "preprocess.h"
22 #include "serializer.h"
23 #include "deserializer.h"
24 #include "encodinggraph.h"
25
26 CSolver::CSolver() :
27         boolTrue(BooleanEdge(new BooleanConst(true))),
28         boolFalse(boolTrue.negate()),
29         unsat(false),
30         tuner(NULL),
31         elapsedTime(0)
32 {
33         satEncoder = new SATEncoder(this);
34 }
35
36 /** This function tears down the solver and the entire AST */
37
38 CSolver::~CSolver() {
39         this->serialize();
40         uint size = allBooleans.getSize();
41         for (uint i = 0; i < size; i++) {
42                 delete allBooleans.get(i);
43         }
44
45         size = allSets.getSize();
46         for (uint i = 0; i < size; i++) {
47                 delete allSets.get(i);
48         }
49
50         size = allElements.getSize();
51         for (uint i = 0; i < size; i++) {
52                 Element* el = allElements.get(i);
53                 model_print("deleting ...%u", i);
54                 ASSERT(el != NULL);
55                 delete el;
56         }
57
58         size = allTables.getSize();
59         for (uint i = 0; i < size; i++) {
60                 delete allTables.get(i);
61         }
62
63         size = allPredicates.getSize();
64         for (uint i = 0; i < size; i++) {
65                 delete allPredicates.get(i);
66         }
67
68         size = allOrders.getSize();
69         for (uint i = 0; i < size; i++) {
70                 delete allOrders.get(i);
71         }
72
73         size = allFunctions.getSize();
74         for (uint i = 0; i < size; i++) {
75                 delete allFunctions.get(i);
76         }
77
78         delete boolTrue.getBoolean();
79         delete satEncoder;
80 }
81
82 CSolver *CSolver::clone() {
83         CSolver *copy = new CSolver();
84         CloneMap map;
85         SetIteratorBooleanEdge *it = getConstraints();
86         while (it->hasNext()) {
87                 BooleanEdge b = it->next();
88                 copy->addConstraint(cloneEdge(copy, &map, b));
89         }
90         delete it;
91         return copy;
92 }
93
94 void CSolver::serialize() {
95         model_print("serializing ...\n");
96         {
97                 Serializer serializer("dump");
98                 SetIteratorBooleanEdge *it = getConstraints();
99                 while (it->hasNext()) {
100                         BooleanEdge b = it->next();
101                         serializeBooleanEdge(&serializer, b);
102                 }
103                 delete it;
104         }
105 //      model_print("deserializing ...\n");
106 //      {
107 //              Deserializer deserializer("dump");
108 //              deserializer.deserialize();
109 //      }
110         
111 }
112
113 Set *CSolver::createSet(VarType type, uint64_t *elements, uint numelements) {
114         Set *set = new Set(type, elements, numelements);
115         allSets.push(set);
116         return set;
117 }
118
119 Set *CSolver::createRangeSet(VarType type, uint64_t lowrange, uint64_t highrange) {
120         Set *set = new Set(type, lowrange, highrange);
121         allSets.push(set);
122         return set;
123 }
124
125 VarType CSolver::getSetVarType(Set *set){
126         return set->getType();
127 }
128
129 Element *CSolver::createRangeVar(VarType type, uint64_t lowrange, uint64_t highrange) {
130         Set *s = createRangeSet(type, lowrange, highrange);
131         return getElementVar(s);
132 }
133
134 MutableSet *CSolver::createMutableSet(VarType type) {
135         MutableSet *set = new MutableSet(type);
136         allSets.push(set);
137         return set;
138 }
139
140 void CSolver::addItem(MutableSet *set, uint64_t element) {
141         set->addElementMSet(element);
142 }
143
144 uint64_t CSolver::createUniqueItem(MutableSet *set) {
145         uint64_t element = set->getNewUniqueItem();
146         set->addElementMSet(element);
147         return element;
148 }
149
150 void CSolver::finalizeMutableSet(MutableSet* set){
151         set->finalize();
152 }
153
154 Element *CSolver::getElementVar(Set *set) {
155         Element *element = new ElementSet(set);
156         model_println("%%%%ElementVar:%u", allElements.getSize());
157         allElements.push(element);
158         return element;
159 }
160
161 Set* CSolver::getElementRange (Element* element){
162         return element->getRange();
163 }
164
165
166 Element *CSolver::getElementConst(VarType type, uint64_t value) {
167         uint64_t array[] = {value};
168         Set *set = new Set(type, array, 1);
169         Element *element = new ElementConst(value, set);
170         Element *e = elemMap.get(element);
171         if (e == NULL) {
172                 allSets.push(set);
173                 model_println("%%%%ElementConst:%u", allElements.getSize());
174                 allElements.push(element);
175                 elemMap.put(element, element);
176                 return element;
177         } else {
178                 delete set;
179                 delete element;
180                 return e;
181         }
182 }
183
184 Element *CSolver::applyFunction(Function *function, Element **array, uint numArrays, BooleanEdge overflowstatus) {
185         Element *element = new ElementFunction(function,array,numArrays,overflowstatus);
186         Element *e = elemMap.get(element);
187         if (e == NULL) {
188                 element->updateParents();
189                 model_println("%%%%ElementFunction:%u", allElements.getSize());
190                 allElements.push(element);
191                 elemMap.put(element, element);
192                 return element;
193         } else {
194                 delete element;
195                 return e;
196         }
197 }
198
199 Function *CSolver::createFunctionOperator(ArithOp op, Set **domain, uint numDomain, Set *range,OverFlowBehavior overflowbehavior) {
200         Function *function = new FunctionOperator(op, domain, numDomain, range, overflowbehavior);
201         allFunctions.push(function);
202         return function;
203 }
204
205 Predicate *CSolver::createPredicateOperator(CompOp op, Set **domain, uint numDomain) {
206         Predicate *predicate = new PredicateOperator(op, domain,numDomain);
207         allPredicates.push(predicate);
208         return predicate;
209 }
210
211 Predicate *CSolver::createPredicateTable(Table *table, UndefinedBehavior behavior) {
212         Predicate *predicate = new PredicateTable(table, behavior);
213         allPredicates.push(predicate);
214         return predicate;
215 }
216
217 Table *CSolver::createTable(Set **domains, uint numDomain, Set *range) {
218         Table *table = new Table(domains,numDomain,range);
219         allTables.push(table);
220         return table;
221 }
222
223 Table *CSolver::createTableForPredicate(Set **domains, uint numDomain) {
224         return createTable(domains, numDomain, NULL);
225 }
226
227 void CSolver::addTableEntry(Table *table, uint64_t *inputs, uint inputSize, uint64_t result) {
228         table->addNewTableEntry(inputs, inputSize, result);
229 }
230
231 Function *CSolver::completeTable(Table *table, UndefinedBehavior behavior) {
232         Function *function = new FunctionTable(table, behavior);
233         allFunctions.push(function);
234         return function;
235 }
236
237 BooleanEdge CSolver::getBooleanVar(VarType type) {
238         Boolean *boolean = new BooleanVar(type);
239         allBooleans.push(boolean);
240         return BooleanEdge(boolean);
241 }
242
243 BooleanEdge CSolver::getBooleanTrue() {
244         return boolTrue;
245 }
246
247 BooleanEdge CSolver::getBooleanFalse() {
248         return boolFalse;
249 }
250
251 BooleanEdge CSolver::applyPredicate(Predicate *predicate, Element **inputs, uint numInputs) {
252         return applyPredicateTable(predicate, inputs, numInputs, BooleanEdge(NULL));
253 }
254
255 BooleanEdge CSolver::applyPredicateTable(Predicate *predicate, Element **inputs, uint numInputs, BooleanEdge undefinedStatus) {
256         BooleanPredicate *boolean = new BooleanPredicate(predicate, inputs, numInputs, undefinedStatus);
257         Boolean *b = boolMap.get(boolean);
258         if (b == NULL) {
259                 boolean->updateParents();
260                 boolMap.put(boolean, boolean);
261                 allBooleans.push(boolean);
262                 return BooleanEdge(boolean);
263         } else {
264                 delete boolean;
265                 return BooleanEdge(b);
266         }
267 }
268
269 bool CSolver::isTrue(BooleanEdge b) {
270         return b.isNegated()?b->isFalse():b->isTrue();
271 }
272
273 bool CSolver::isFalse(BooleanEdge b) {
274         return b.isNegated()?b->isTrue():b->isFalse();
275 }
276
277 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge arg1, BooleanEdge arg2) {
278         BooleanEdge array[] = {arg1, arg2};
279         return applyLogicalOperation(op, array, 2);
280 }
281
282 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge arg) {
283         BooleanEdge array[] = {arg};
284         return applyLogicalOperation(op, array, 1);
285 }
286
287 static int ptrcompares(const void *p1, const void *p2) {
288         uintptr_t b1 = *(uintptr_t const *) p1;
289   uintptr_t b2 = *(uintptr_t const *) p2;
290         if (b1 < b2)
291                 return -1;
292         else if (b1 == b2)
293                 return 0;
294         else
295                 return 1;
296 }
297
298 BooleanEdge CSolver::rewriteLogicalOperation(LogicOp op, BooleanEdge * array, uint asize) {
299   return applyLogicalOperation(op, array, asize);
300   /*  BooleanEdge newarray[asize];
301         memcpy(newarray, array, asize * sizeof(BooleanEdge));
302         for(uint i=0; i < asize; i++) {
303                 BooleanEdge b=newarray[i];
304                 if (b->type == LOGICOP) {
305                         if (((BooleanLogic *) b.getBoolean())->replaced) {
306                                 newarray[i] = doRewrite(newarray[i]);
307                                 i--;//Check again
308                         }
309                 }
310         }
311         return applyLogicalOperation(op, newarray, asize);*/
312 }
313
314 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge *array, uint asize) {
315         BooleanEdge newarray[asize];
316         switch (op) {
317         case SATC_NOT: {
318                 return array[0].negate();
319         }
320         case SATC_IFF: {
321                 for (uint i = 0; i < 2; i++) {
322                         if (array[i]->type == BOOLCONST) {
323                                 if (isTrue(array[i])) { // It can be undefined
324                                         return array[1 - i];
325                                 } else if(isFalse(array[i])) {
326                                         newarray[0] = array[1 - i];
327                                         return applyLogicalOperation(SATC_NOT, newarray, 1);
328                                 }
329                         } else if (array[i]->type == LOGICOP) {
330                                 BooleanLogic *b =(BooleanLogic *)array[i].getBoolean();
331                                 if (b->replaced) {
332                                         return rewriteLogicalOperation(op, array, asize);
333                                 }
334                         }
335                 }
336                 break;
337         }
338         case SATC_OR: {
339                 for (uint i =0; i <asize; i++) {
340                         newarray[i] = applyLogicalOperation(SATC_NOT, array[i]);
341                 }
342                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_AND, newarray, asize));
343         }
344         case SATC_AND: {
345                 uint newindex = 0;
346                 for (uint i = 0; i < asize; i++) {
347                         BooleanEdge b = array[i];
348 //                        model_print("And: Argument %u:", i);
349 //                        if(b.isNegated())
350 //                                model_print("!");
351 //                        b->print();
352                         if (b->type == LOGICOP) {
353                                 if (((BooleanLogic *)b.getBoolean())->replaced)
354                                         return rewriteLogicalOperation(op, array, asize);
355                         }
356                         if (b->type == BOOLCONST) {
357                                 if (isTrue(b))
358                                         continue;
359                                 else{
360                                         return boolFalse;
361                                 }
362                         } else
363                                 newarray[newindex++] = b;
364                 }
365                 if (newindex == 0) {
366                         return boolTrue;
367                 } else if (newindex == 1) {
368                         return newarray[0];
369                 } else {
370                         bsdqsort(newarray, newindex, sizeof(BooleanEdge), ptrcompares);
371                         array = newarray;
372                         asize = newindex;
373                 }
374                 break;
375         }
376         case SATC_XOR: {
377                 //handle by translation
378                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_IFF, array, asize));
379         }
380         case SATC_IMPLIES: {
381                 //handle by translation
382 //                model_print("Implies: first:");
383 //                if(array[0].isNegated())
384 //                        model_print("!");
385 //                array[0]->print();
386 //                model_print("Implies: second:");
387 //                if(array[1].isNegated())
388 //                        model_print("!");
389 //                array[1]->print();
390 //                model_println("##### OK let's get the operation done");
391                 return applyLogicalOperation(SATC_OR, applyLogicalOperation(SATC_NOT, array[0]), array[1]);
392         }
393         }
394
395         ASSERT(asize != 0);
396         Boolean *boolean = new BooleanLogic(this, op, array, asize);
397         /*      Boolean *b = boolMap.get(boolean);
398         if (b == NULL) {
399                 boolean->updateParents();
400                 boolMap.put(boolean, boolean);
401                 allBooleans.push(boolean);
402                 return BooleanEdge(boolean);
403         } else {
404         delete boolean;*/
405                 return BooleanEdge(boolean);
406                 /*      }*/
407 }
408
409 BooleanEdge CSolver::orderConstraint(Order *order, uint64_t first, uint64_t second) {
410 #ifdef TRACE_DEBUG
411         model_println("Creating order: From:%lu => To:%lu", first, second);
412 #endif
413         if(first == second)
414                 return boolFalse;
415         Boolean *constraint = new BooleanOrder(order, first, second);
416         allBooleans.push(constraint);
417         return BooleanEdge(constraint);
418 }
419
420 void CSolver::addConstraint(BooleanEdge constraint) {
421 #ifdef TRACE_DEBUG
422         model_println("****New Constraint******");
423 #endif
424         if(constraint.isNegated())
425                 model_print("!");
426         constraint.getBoolean()->print();
427         if (isTrue(constraint))
428                 return;
429         else if (isFalse(constraint)){
430                 int t=0;
431 #ifdef TRACE_DEBUG
432                 model_println("Adding constraint which is false :|");
433 #endif
434                 setUnSAT();
435         }
436         else {
437                 if (constraint->type == LOGICOP) {
438                         BooleanLogic *b=(BooleanLogic *) constraint.getBoolean();
439                         if (!constraint.isNegated()) {
440                                 if (b->op==SATC_AND) {
441                                         for(uint i=0;i<b->inputs.getSize();i++) {
442 #ifdef TRACE_DEBUG
443                                                 model_println("In loop");
444 #endif
445                                                 addConstraint(b->inputs.get(i));
446                                         }
447                                         return;
448                                 }
449                         }
450                         if (b->replaced) {
451 #ifdef TRACE_DEBUG
452                                 model_println("While rewriting");
453 #endif
454                                 addConstraint(doRewrite(constraint));
455                                 return;
456                         }
457                 }
458                 constraints.add(constraint);
459                 Boolean *ptr=constraint.getBoolean();
460                 
461                 if (ptr->boolVal == BV_UNSAT){
462 #ifdef TRACE_DEBUG
463                         model_println("BooleanValue is Set to UnSAT");
464 #endif
465                         setUnSAT();
466                 }
467                 
468                 replaceBooleanWithTrueNoRemove(constraint);
469                 constraint->parents.clear();
470         }
471 }
472
473 Order *CSolver::createOrder(OrderType type, Set *set) {
474         Order *order = new Order(type, set);
475         allOrders.push(order);
476         activeOrders.add(order);
477         return order;
478 }
479
480 int CSolver::solve() {
481         bool deleteTuner = false;
482         if (tuner == NULL) {
483                 tuner = new DefaultTuner();
484                 deleteTuner = true;
485         }
486
487         long long startTime = getTimeNano();
488         computePolarities(this);
489
490 //      Preprocess pp(this);
491 //      pp.doTransform();
492         
493 //      DecomposeOrderTransform dot(this);
494 //      dot.doTransform();
495
496 //      IntegerEncodingTransform iet(this);
497 //      iet.doTransform();
498
499 //      EncodingGraph eg(this);
500 //      eg.buildGraph();
501 //      eg.encode();
502         
503         naiveEncodingDecision(this);
504         satEncoder->encodeAllSATEncoder(this);
505         model_println("Is problem UNSAT after encoding: %d", unsat);
506         int result = unsat ? IS_UNSAT : satEncoder->solve();
507         model_println("Result Computed in CSolver: %d", result);
508         long long finishTime = getTimeNano();
509         elapsedTime = finishTime - startTime;
510         if (deleteTuner) {
511                 delete tuner;
512                 tuner = NULL;
513         }
514         return result;
515 }
516
517 uint64_t CSolver::getElementValue(Element *element) {
518         switch (element->type) {
519         case ELEMSET:
520         case ELEMCONST:
521         case ELEMFUNCRETURN:
522                 return getElementValueSATTranslator(this, element);
523         default:
524                 ASSERT(0);
525         }
526         exit(-1);
527 }
528
529 bool CSolver::getBooleanValue(BooleanEdge bedge) {
530         Boolean *boolean=bedge.getBoolean();
531         switch (boolean->type) {
532         case BOOLEANVAR:
533                 return getBooleanVariableValueSATTranslator(this, boolean);
534         default:
535                 ASSERT(0);
536         }
537         exit(-1);
538 }
539
540 bool CSolver::getOrderConstraintValue(Order *order, uint64_t first, uint64_t second) {
541         return order->encoding.resolver->resolveOrder(first, second);
542 }
543
544 long long CSolver::getEncodeTime() { return satEncoder->getEncodeTime(); }
545
546 long long CSolver::getSolveTime() { return satEncoder->getSolveTime(); }
547
548 void CSolver::autoTune(uint budget) {
549         AutoTuner *autotuner = new AutoTuner(budget);
550         autotuner->addProblem(this);
551         autotuner->tune();
552         delete autotuner;
553 }