Parser for the tuner's log file
[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 #include "ordergraph.h"
26 #include "orderedge.h"
27 #include "orderanalysis.h"
28 #include "elementopt.h"
29 #include <time.h>
30 #include <stdarg.h>
31
32 CSolver::CSolver() :
33         boolTrue(BooleanEdge(new BooleanConst(true))),
34         boolFalse(boolTrue.negate()),
35         unsat(false),
36         tuner(NULL),
37         elapsedTime(0),
38         satsolverTimeout(NOTIMEOUT)
39 {
40         satEncoder = new SATEncoder(this);
41 }
42
43 /** This function tears down the solver and the entire AST */
44
45 CSolver::~CSolver() {
46         //serialize();
47         uint size = allBooleans.getSize();
48         for (uint i = 0; i < size; i++) {
49                 delete allBooleans.get(i);
50         }
51
52         size = allSets.getSize();
53         for (uint i = 0; i < size; i++) {
54                 delete allSets.get(i);
55         }
56
57         size = allElements.getSize();
58         for (uint i = 0; i < size; i++) {
59                 Element *el = allElements.get(i);
60                 delete el;
61         }
62
63         size = allTables.getSize();
64         for (uint i = 0; i < size; i++) {
65                 delete allTables.get(i);
66         }
67
68         size = allPredicates.getSize();
69         for (uint i = 0; i < size; i++) {
70                 delete allPredicates.get(i);
71         }
72
73         size = allOrders.getSize();
74         for (uint i = 0; i < size; i++) {
75                 delete allOrders.get(i);
76         }
77         size = allFunctions.getSize();
78         for (uint i = 0; i < size; i++) {
79                 delete allFunctions.get(i);
80         }
81
82         delete boolTrue.getBoolean();
83         delete satEncoder;
84 }
85
86 void CSolver::resetSolver() {
87         //serialize();
88         uint size = allBooleans.getSize();
89         for (uint i = 0; i < size; i++) {
90                 delete allBooleans.get(i);
91         }
92
93         size = allSets.getSize();
94         for (uint i = 0; i < size; i++) {
95                 delete allSets.get(i);
96         }
97
98         size = allElements.getSize();
99         for (uint i = 0; i < size; i++) {
100                 Element *el = allElements.get(i);
101                 delete el;
102         }
103
104         size = allTables.getSize();
105         for (uint i = 0; i < size; i++) {
106                 delete allTables.get(i);
107         }
108
109         size = allPredicates.getSize();
110         for (uint i = 0; i < size; i++) {
111                 delete allPredicates.get(i);
112         }
113
114         size = allOrders.getSize();
115         for (uint i = 0; i < size; i++) {
116                 delete allOrders.get(i);
117         }
118         size = allFunctions.getSize();
119         for (uint i = 0; i < size; i++) {
120                 delete allFunctions.get(i);
121         }
122         delete boolTrue.getBoolean();
123         allBooleans.clear();
124         allSets.clear();
125         allElements.clear();
126         allTables.clear();
127         allPredicates.clear();
128         allOrders.clear();
129         allFunctions.clear();
130         constraints.reset();
131         activeOrders.reset();
132         boolMap.reset();
133         elemMap.reset();
134
135         boolTrue = BooleanEdge(new BooleanConst(true));
136         boolFalse = boolTrue.negate();
137         unsat = false;
138         elapsedTime = 0;
139         tuner = NULL;
140         satEncoder->resetSATEncoder();
141
142 }
143
144 CSolver *CSolver::clone() {
145         CSolver *copy = new CSolver();
146         CloneMap map;
147         SetIteratorBooleanEdge *it = getConstraints();
148         while (it->hasNext()) {
149                 BooleanEdge b = it->next();
150                 copy->addConstraint(cloneEdge(copy, &map, b));
151         }
152         delete it;
153         return copy;
154 }
155
156 CSolver *CSolver::deserialize(const char *file) {
157         model_print("deserializing %s ...\n", file);
158         Deserializer deserializer(file);
159         return deserializer.deserialize();
160 }
161
162 void CSolver::serialize() {
163         model_print("serializing ...\n");
164         char buffer[255];
165         long long nanotime = getTimeNano();
166         int numchars = sprintf(buffer, "DUMP%llu", nanotime);
167         Serializer serializer(buffer);
168         SetIteratorBooleanEdge *it = getConstraints();
169         while (it->hasNext()) {
170                 BooleanEdge b = it->next();
171                 serializeBooleanEdge(&serializer, b, true);
172         }
173         delete it;
174 }
175
176 Set *CSolver::createSet(VarType type, uint64_t *elements, uint numelements) {
177         Set *set = new Set(type, elements, numelements);
178         allSets.push(set);
179         return set;
180 }
181
182 Set *CSolver::createRangeSet(VarType type, uint64_t lowrange, uint64_t highrange) {
183         Set *set = new Set(type, lowrange, highrange);
184         allSets.push(set);
185         return set;
186 }
187
188 bool CSolver::itemExistInSet(Set *set, uint64_t item) {
189         return set->exists(item);
190 }
191
192 VarType CSolver::getSetVarType(Set *set) {
193         return set->getType();
194 }
195
196 Element *CSolver::createRangeVar(VarType type, uint64_t lowrange, uint64_t highrange) {
197         Set *s = createRangeSet(type, lowrange, highrange);
198         return getElementVar(s);
199 }
200
201 MutableSet *CSolver::createMutableSet(VarType type) {
202         MutableSet *set = new MutableSet(type);
203         allSets.push(set);
204         return set;
205 }
206
207 void CSolver::addItem(MutableSet *set, uint64_t element) {
208         set->addElementMSet(element);
209 }
210
211 uint64_t CSolver::createUniqueItem(MutableSet *set) {
212         uint64_t element = set->getNewUniqueItem();
213         set->addElementMSet(element);
214         return element;
215 }
216
217 void CSolver::finalizeMutableSet(MutableSet *set) {
218         set->finalize();
219 }
220
221 Element *CSolver::getElementVar(Set *set) {
222         Element *element = new ElementSet(set);
223         allElements.push(element);
224         return element;
225 }
226
227 void CSolver::mustHaveValue(Element *element) {
228         element->anyValue = true;
229 }
230
231 Set *CSolver::getElementRange (Element *element) {
232         return element->getRange();
233 }
234
235
236 Element *CSolver::getElementConst(VarType type, uint64_t value) {
237         uint64_t array[] = {value};
238         Set *set = new Set(type, array, 1);
239         Element *element = new ElementConst(value, set);
240         Element *e = elemMap.get(element);
241         if (e == NULL) {
242                 allSets.push(set);
243                 allElements.push(element);
244                 elemMap.put(element, element);
245                 return element;
246         } else {
247                 delete set;
248                 delete element;
249                 return e;
250         }
251 }
252
253
254 Element *CSolver::applyFunction(Function *function, Element **array, uint numArrays, BooleanEdge overflowstatus) {
255         ASSERT(numArrays == 2);
256         Element *element = new ElementFunction(function,array,numArrays,overflowstatus);
257         Element *e = elemMap.get(element);
258         if (e == NULL) {
259                 element->updateParents();
260                 allElements.push(element);
261                 elemMap.put(element, element);
262                 return element;
263         } else {
264                 delete element;
265                 return e;
266         }
267 }
268
269 Function *CSolver::createFunctionOperator(ArithOp op, Set *range, OverFlowBehavior overflowbehavior) {
270         Function *function = new FunctionOperator(op, range, overflowbehavior);
271         allFunctions.push(function);
272         return function;
273 }
274
275 Predicate *CSolver::createPredicateOperator(CompOp op) {
276         Predicate *predicate = new PredicateOperator(op);
277         allPredicates.push(predicate);
278         return predicate;
279 }
280
281 Predicate *CSolver::createPredicateTable(Table *table, UndefinedBehavior behavior) {
282         Predicate *predicate = new PredicateTable(table, behavior);
283         allPredicates.push(predicate);
284         return predicate;
285 }
286
287 Table *CSolver::createTable(Set *range) {
288         Table *table = new Table(range);
289         allTables.push(table);
290         return table;
291 }
292
293 Table *CSolver::createTableForPredicate() {
294         return createTable(NULL);
295 }
296
297 void CSolver::addTableEntry(Table *table, uint64_t *inputs, uint inputSize, uint64_t result) {
298         table->addNewTableEntry(inputs, inputSize, result);
299 }
300
301 Function *CSolver::completeTable(Table *table, UndefinedBehavior behavior) {
302         Function *function = new FunctionTable(table, behavior);
303         allFunctions.push(function);
304         return function;
305 }
306
307 BooleanEdge CSolver::getBooleanVar(VarType type) {
308         Boolean *boolean = new BooleanVar(type);
309         allBooleans.push(boolean);
310         return BooleanEdge(boolean);
311 }
312
313 BooleanEdge CSolver::getBooleanTrue() {
314         return boolTrue;
315 }
316
317 BooleanEdge CSolver::getBooleanFalse() {
318         return boolFalse;
319 }
320
321 BooleanEdge CSolver::applyPredicate(Predicate *predicate, Element **inputs, uint numInputs) {
322         return applyPredicateTable(predicate, inputs, numInputs, BooleanEdge(NULL));
323 }
324
325 BooleanEdge CSolver::applyPredicateTable(Predicate *predicate, Element **inputs, uint numInputs, BooleanEdge undefinedStatus) {
326         BooleanPredicate *boolean = new BooleanPredicate(predicate, inputs, numInputs, undefinedStatus);
327         Boolean *b = boolMap.get(boolean);
328         if (b == NULL) {
329                 boolean->updateParents();
330                 boolMap.put(boolean, boolean);
331                 allBooleans.push(boolean);
332                 return BooleanEdge(boolean);
333         } else {
334                 delete boolean;
335                 return BooleanEdge(b);
336         }
337 }
338
339 bool CSolver::isTrue(BooleanEdge b) {
340         return b.isNegated() ? b->isFalse() : b->isTrue();
341 }
342
343 bool CSolver::isFalse(BooleanEdge b) {
344         return b.isNegated() ? b->isTrue() : b->isFalse();
345 }
346
347 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge arg1, BooleanEdge arg2) {
348         BooleanEdge array[] = {arg1, arg2};
349         return applyLogicalOperation(op, array, 2);
350 }
351
352 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge arg) {
353         BooleanEdge array[] = {arg};
354         return applyLogicalOperation(op, array, 1);
355 }
356
357 static int booleanEdgeCompares(const void *p1, const void *p2) {
358         BooleanEdge be1 = *(BooleanEdge const *) p1;
359         BooleanEdge be2 = *(BooleanEdge const *) p2;
360         uint64_t b1 = be1->id;
361         uint64_t b2 = be2->id;
362         if (b1 < b2)
363                 return -1;
364         else if (b1 == b2)
365                 return 0;
366         else
367                 return 1;
368 }
369
370 BooleanEdge CSolver::rewriteLogicalOperation(LogicOp op, BooleanEdge *array, uint asize) {
371         BooleanEdge newarray[asize];
372         memcpy(newarray, array, asize * sizeof(BooleanEdge));
373         for (uint i = 0; i < asize; i++) {
374                 BooleanEdge b = newarray[i];
375                 if (b->type == LOGICOP) {
376                         if (((BooleanLogic *) b.getBoolean())->replaced) {
377                                 newarray[i] = doRewrite(newarray[i]);
378                                 i--;//Check again
379                         }
380                 }
381         }
382         return applyLogicalOperation(op, newarray, asize);
383 }
384
385 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge *array, uint asize) {
386         BooleanEdge newarray[asize];
387         switch (op) {
388         case SATC_NOT: {
389                 return array[0].negate();
390         }
391         case SATC_IFF: {
392                 for (uint i = 0; i < 2; i++) {
393                         if (isTrue(array[i])) { // It can be undefined
394                                 return array[1 - i];
395                         } else if (isFalse(array[i])) {
396                                 newarray[0] = array[1 - i];
397                                 return applyLogicalOperation(SATC_NOT, newarray, 1);
398                         } else if (array[i]->type == LOGICOP) {
399                                 BooleanLogic *b = (BooleanLogic *)array[i].getBoolean();
400                                 if (b->replaced) {
401                                         return rewriteLogicalOperation(op, array, asize);
402                                 }
403                         }
404                 }
405                 break;
406         }
407         case SATC_OR: {
408                 for (uint i = 0; i < asize; i++) {
409                         newarray[i] = applyLogicalOperation(SATC_NOT, array[i]);
410                 }
411                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_AND, newarray, asize));
412         }
413         case SATC_AND: {
414                 uint newindex = 0;
415                 for (uint i = 0; i < asize; i++) {
416                         BooleanEdge b = array[i];
417                         if (b->type == LOGICOP) {
418                                 if (((BooleanLogic *)b.getBoolean())->replaced)
419                                         return rewriteLogicalOperation(op, array, asize);
420                         }
421                         if (isTrue(b))
422                                 continue;
423                         else if (isFalse(b)) {
424                                 return boolFalse;
425                         } else
426                                 newarray[newindex++] = b;
427                 }
428                 if (newindex == 0) {
429                         return boolTrue;
430                 } else if (newindex == 1) {
431                         return newarray[0];
432                 } else {
433                         bsdqsort(newarray, newindex, sizeof(BooleanEdge), booleanEdgeCompares);
434                         array = newarray;
435                         asize = newindex;
436                 }
437                 break;
438         }
439         case SATC_XOR: {
440                 //handle by translation
441                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_IFF, array, asize));
442         }
443         case SATC_IMPLIES: {
444                 //handle by translation
445                 return applyLogicalOperation(SATC_OR, applyLogicalOperation(SATC_NOT, array[0]), array[1]);
446         }
447         }
448
449         ASSERT(asize != 0);
450         Boolean *boolean = new BooleanLogic(this, op, array, asize);
451         Boolean *b = boolMap.get(boolean);
452         if (b == NULL) {
453                 boolean->updateParents();
454                 boolMap.put(boolean, boolean);
455                 allBooleans.push(boolean);
456                 return BooleanEdge(boolean);
457         } else {
458                 delete boolean;
459                 return BooleanEdge(b);
460         }
461 }
462
463 BooleanEdge CSolver::orderConstraint(Order *order, uint64_t first, uint64_t second) {
464         //      ASSERT(first != second);
465         if (first == second)
466                 return getBooleanFalse();
467
468         bool negate = false;
469         if (order->type == SATC_TOTAL) {
470                 if (first > second) {
471                         uint64_t tmp = first;
472                         first = second;
473                         second = tmp;
474                         negate = true;
475                 }
476         }
477         Boolean *constraint = new BooleanOrder(order, first, second);
478         Boolean *b = boolMap.get(constraint);
479
480         if (b == NULL) {
481                 allBooleans.push(constraint);
482                 boolMap.put(constraint, constraint);
483                 constraint->updateParents();
484                 if (order->graph != NULL) {
485                         OrderGraph *graph = order->graph;
486                         OrderNode *from = graph->lookupOrderNodeFromOrderGraph(first);
487                         if (from != NULL) {
488                                 OrderNode *to = graph->lookupOrderNodeFromOrderGraph(second);
489                                 if (to != NULL) {
490                                         OrderEdge *edge = graph->lookupOrderEdgeFromOrderGraph(from, to);
491                                         OrderEdge *invedge;
492
493                                         if (edge != NULL && edge->mustPos) {
494                                                 replaceBooleanWithTrueNoRemove(constraint);
495                                         } else if (edge != NULL && edge->mustNeg) {
496                                                 replaceBooleanWithFalseNoRemove(constraint);
497                                         } else if ((invedge = graph->lookupOrderEdgeFromOrderGraph(to, from)) != NULL
498                                                                                  && invedge->mustPos) {
499                                                 replaceBooleanWithFalseNoRemove(constraint);
500                                         }
501                                 }
502                         }
503                 }
504         } else {
505                 delete constraint;
506                 constraint = b;
507         }
508
509         BooleanEdge be = BooleanEdge(constraint);
510         return negate ? be.negate() : be;
511 }
512
513 void CSolver::addConstraint(BooleanEdge constraint) {
514         if (isTrue(constraint))
515                 return;
516         else if (isFalse(constraint)) {
517                 setUnSAT();
518         }
519         else {
520                 if (constraint->type == LOGICOP) {
521                         BooleanLogic *b = (BooleanLogic *) constraint.getBoolean();
522                         if (!constraint.isNegated()) {
523                                 if (b->op == SATC_AND) {
524                                         uint size = b->inputs.getSize();
525                                         //Handle potential concurrent modification
526                                         BooleanEdge array[size];
527                                         for (uint i = 0; i < size; i++) {
528                                                 array[i] = b->inputs.get(i);
529                                         }
530                                         for (uint i = 0; i < size; i++) {
531                                                 addConstraint(array[i]);
532                                         }
533                                         return;
534                                 }
535                         }
536                         if (b->replaced) {
537                                 addConstraint(doRewrite(constraint));
538                                 return;
539                         }
540                 }
541                 constraints.add(constraint);
542                 Boolean *ptr = constraint.getBoolean();
543
544                 if (ptr->boolVal == BV_UNSAT) {
545                         setUnSAT();
546                 }
547
548                 replaceBooleanWithTrueNoRemove(constraint);
549                 constraint->parents.clear();
550         }
551 }
552
553 Order *CSolver::createOrder(OrderType type, Set *set) {
554         Order *order = new Order(type, set);
555         allOrders.push(order);
556         activeOrders.add(order);
557         return order;
558 }
559
560 /** Computes static ordering information to allow isTrue/isFalse
561     queries on newly created orders to work. */
562
563 void CSolver::inferFixedOrder(Order *order) {
564         if (order->graph != NULL) {
565                 delete order->graph;
566         }
567         order->graph = buildMustOrderGraph(order);
568         reachMustAnalysis(this, order->graph, true);
569 }
570
571 void CSolver::inferFixedOrders() {
572         SetIteratorOrder *orderit = activeOrders.iterator();
573         while (orderit->hasNext()) {
574                 Order *order = orderit->next();
575                 inferFixedOrder(order);
576         }
577 }
578
579 #define NANOSEC 1000000000.0
580 int CSolver::solve() {
581         long long startTime = getTimeNano();
582         bool deleteTuner = false;
583         if (tuner == NULL) {
584                 tuner = new DefaultTuner();
585                 deleteTuner = true;
586         }
587
588
589         {
590                 SetIteratorOrder *orderit = activeOrders.iterator();
591                 while (orderit->hasNext()) {
592                         Order *order = orderit->next();
593                         if (order->graph != NULL) {
594                                 delete order->graph;
595                                 order->graph = NULL;
596                         }
597                 }
598                 delete orderit;
599         }
600         computePolarities(this);
601         long long time1 = getTimeNano();
602         model_print("Polarity time: %f\n", (time1 - startTime) / NANOSEC);
603         Preprocess pp(this);
604         pp.doTransform();
605         long long time2 = getTimeNano();
606         model_print("Preprocess time: %f\n", (time2 - time1) / NANOSEC);
607
608         DecomposeOrderTransform dot(this);
609         dot.doTransform();
610         time1 = getTimeNano();
611         model_print("Decompose Order: %f\n", (time1 - time2) / NANOSEC);
612
613         IntegerEncodingTransform iet(this);
614         iet.doTransform();
615
616         ElementOpt eop(this);
617         eop.doTransform();
618
619         EncodingGraph eg(this);
620         eg.encode();
621
622         naiveEncodingDecision(this);
623 //      eg.validate();
624
625         time2 = getTimeNano();
626         model_print("Encoding Graph Time: %f\n", (time2 - time1) / NANOSEC);
627
628         satEncoder->encodeAllSATEncoder(this);
629         time1 = getTimeNano();
630
631         model_print("Elapse Encode time: %f\n", (time1 - startTime) / NANOSEC);
632
633         model_print("Is problem UNSAT after encoding: %d\n", unsat);
634         int result = unsat ? IS_UNSAT : satEncoder->solve(satsolverTimeout);
635         model_print("Result Computed in SAT solver:\t%s\n", result == IS_SAT? "SAT" : result == IS_INDETER? "INDETERMINATE" : " UNSAT");
636         time2 = getTimeNano();
637         elapsedTime = time2 - startTime;
638         model_print("CSOLVER solve time: %f\n", elapsedTime / NANOSEC);
639         if (deleteTuner) {
640                 delete tuner;
641                 tuner = NULL;
642         }
643         return result;
644 }
645
646 void CSolver::printConstraints() {
647         SetIteratorBooleanEdge *it = getConstraints();
648         while (it->hasNext()) {
649                 BooleanEdge b = it->next();
650                 b.print();
651         }
652         delete it;
653 }
654
655 void CSolver::printConstraint(BooleanEdge b) {
656         b.print();
657 }
658
659 uint64_t CSolver::getElementValue(Element *element) {
660         switch (element->type) {
661         case ELEMSET:
662         case ELEMCONST:
663         case ELEMFUNCRETURN:
664                 return getElementValueSATTranslator(this, element);
665         default:
666                 ASSERT(0);
667         }
668         exit(-1);
669 }
670
671 bool CSolver::getBooleanValue(BooleanEdge bedge) {
672         Boolean *boolean = bedge.getBoolean();
673         switch (boolean->type) {
674         case BOOLEANVAR:
675                 return getBooleanVariableValueSATTranslator(this, boolean);
676         default:
677                 ASSERT(0);
678         }
679         exit(-1);
680 }
681
682 bool CSolver::getOrderConstraintValue(Order *order, uint64_t first, uint64_t second) {
683         return order->encoding.resolver->resolveOrder(first, second);
684 }
685
686 long long CSolver::getEncodeTime() { return satEncoder->getEncodeTime(); }
687
688 long long CSolver::getSolveTime() { return satEncoder->getSolveTime(); }
689
690 void CSolver::autoTune(uint budget) {
691         AutoTuner *autotuner = new AutoTuner(budget);
692         autotuner->addProblem(this);
693         autotuner->tune();
694         delete autotuner;
695 }
696
697