More refactoring
[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
23 CSolver::CSolver() :
24         boolTrue(BooleanEdge(new BooleanConst(true))),
25         boolFalse(boolTrue.negate()),
26         unsat(false),
27         tuner(NULL),
28         elapsedTime(0)
29 {
30         satEncoder = new SATEncoder(this);
31 }
32
33 /** This function tears down the solver and the entire AST */
34
35 CSolver::~CSolver() {
36         uint size = allBooleans.getSize();
37         for (uint i = 0; i < size; i++) {
38                 delete allBooleans.get(i);
39         }
40
41         size = allSets.getSize();
42         for (uint i = 0; i < size; i++) {
43                 delete allSets.get(i);
44         }
45
46         size = allElements.getSize();
47         for (uint i = 0; i < size; i++) {
48                 delete allElements.get(i);
49         }
50
51         size = allTables.getSize();
52         for (uint i = 0; i < size; i++) {
53                 delete allTables.get(i);
54         }
55
56         size = allPredicates.getSize();
57         for (uint i = 0; i < size; i++) {
58                 delete allPredicates.get(i);
59         }
60
61         size = allOrders.getSize();
62         for (uint i = 0; i < size; i++) {
63                 delete allOrders.get(i);
64         }
65
66         size = allFunctions.getSize();
67         for (uint i = 0; i < size; i++) {
68                 delete allFunctions.get(i);
69         }
70
71         delete boolTrue.getBoolean();
72         delete satEncoder;
73 }
74
75 CSolver *CSolver::clone() {
76         CSolver *copy = new CSolver();
77         CloneMap map;
78         SetIteratorBooleanEdge *it = getConstraints();
79         while (it->hasNext()) {
80                 BooleanEdge b = it->next();
81                 copy->addConstraint(cloneEdge(copy, &map, b));
82         }
83         delete it;
84         return copy;
85 }
86
87 Set *CSolver::createSet(VarType type, uint64_t *elements, uint numelements) {
88         Set *set = new Set(type, elements, numelements);
89         allSets.push(set);
90         return set;
91 }
92
93 Set *CSolver::createRangeSet(VarType type, uint64_t lowrange, uint64_t highrange) {
94         Set *set = new Set(type, lowrange, highrange);
95         allSets.push(set);
96         return set;
97 }
98
99 Element *CSolver::createRangeVar(VarType type, uint64_t lowrange, uint64_t highrange) {
100         Set *s = createRangeSet(type, lowrange, highrange);
101         return getElementVar(s);
102 }
103
104 MutableSet *CSolver::createMutableSet(VarType type) {
105         MutableSet *set = new MutableSet(type);
106         allSets.push(set);
107         return set;
108 }
109
110 void CSolver::addItem(MutableSet *set, uint64_t element) {
111         set->addElementMSet(element);
112 }
113
114 uint64_t CSolver::createUniqueItem(MutableSet *set) {
115         uint64_t element = set->getNewUniqueItem();
116         set->addElementMSet(element);
117         return element;
118 }
119
120 Element *CSolver::getElementVar(Set *set) {
121         Element *element = new ElementSet(set);
122         allElements.push(element);
123         return element;
124 }
125
126 Element *CSolver::getElementConst(VarType type, uint64_t value) {
127         uint64_t array[] = {value};
128         Set *set = new Set(type, array, 1);
129         Element *element = new ElementConst(value, set);
130         Element *e = elemMap.get(element);
131         if (e == NULL) {
132                 allSets.push(set);
133                 allElements.push(element);
134                 elemMap.put(element, element);
135                 return element;
136         } else {
137                 delete set;
138                 delete element;
139                 return e;
140         }
141 }
142
143 Element *CSolver::applyFunction(Function *function, Element **array, uint numArrays, BooleanEdge overflowstatus) {
144         Element *element = new ElementFunction(function,array,numArrays,overflowstatus);
145         Element *e = elemMap.get(element);
146         if (e == NULL) {
147                 element->updateParents();
148                 allElements.push(element);
149                 elemMap.put(element, element);
150                 return element;
151         } else {
152                 delete element;
153                 return e;
154         }
155 }
156
157 Function *CSolver::createFunctionOperator(ArithOp op, Set **domain, uint numDomain, Set *range,OverFlowBehavior overflowbehavior) {
158         Function *function = new FunctionOperator(op, domain, numDomain, range, overflowbehavior);
159         allFunctions.push(function);
160         return function;
161 }
162
163 Predicate *CSolver::createPredicateOperator(CompOp op, Set **domain, uint numDomain) {
164         Predicate *predicate = new PredicateOperator(op, domain,numDomain);
165         allPredicates.push(predicate);
166         return predicate;
167 }
168
169 Predicate *CSolver::createPredicateTable(Table *table, UndefinedBehavior behavior) {
170         Predicate *predicate = new PredicateTable(table, behavior);
171         allPredicates.push(predicate);
172         return predicate;
173 }
174
175 Table *CSolver::createTable(Set **domains, uint numDomain, Set *range) {
176         Table *table = new Table(domains,numDomain,range);
177         allTables.push(table);
178         return table;
179 }
180
181 Table *CSolver::createTableForPredicate(Set **domains, uint numDomain) {
182         return createTable(domains, numDomain, NULL);
183 }
184
185 void CSolver::addTableEntry(Table *table, uint64_t *inputs, uint inputSize, uint64_t result) {
186         table->addNewTableEntry(inputs, inputSize, result);
187 }
188
189 Function *CSolver::completeTable(Table *table, UndefinedBehavior behavior) {
190         Function *function = new FunctionTable(table, behavior);
191         allFunctions.push(function);
192         return function;
193 }
194
195 BooleanEdge CSolver::getBooleanVar(VarType type) {
196         Boolean *boolean = new BooleanVar(type);
197         allBooleans.push(boolean);
198         return BooleanEdge(boolean);
199 }
200
201 BooleanEdge CSolver::getBooleanTrue() {
202         return boolTrue;
203 }
204
205 BooleanEdge CSolver::getBooleanFalse() {
206         return boolFalse;
207 }
208
209 BooleanEdge CSolver::applyPredicate(Predicate *predicate, Element **inputs, uint numInputs) {
210         return applyPredicateTable(predicate, inputs, numInputs, NULL);
211 }
212
213 BooleanEdge CSolver::applyPredicateTable(Predicate *predicate, Element **inputs, uint numInputs, BooleanEdge undefinedStatus) {
214         BooleanPredicate *boolean = new BooleanPredicate(predicate, inputs, numInputs, undefinedStatus);
215         Boolean *b = boolMap.get(boolean);
216         if (b == NULL) {
217                 boolean->updateParents();
218                 boolMap.put(boolean, boolean);
219                 allBooleans.push(boolean);
220                 return BooleanEdge(boolean);
221         } else {
222                 delete boolean;
223                 return BooleanEdge(b);
224         }
225 }
226
227 bool CSolver::isTrue(BooleanEdge b) {
228         return b.isNegated()?b->isFalse():b->isTrue();
229 }
230
231 bool CSolver::isFalse(BooleanEdge b) {
232         return b.isNegated()?b->isTrue():b->isFalse();
233 }
234
235 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge arg1, BooleanEdge arg2) {
236         BooleanEdge array[] = {arg1, arg2};
237         return applyLogicalOperation(op, array, 2);
238 }
239
240 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge arg) {
241         BooleanEdge array[] = {arg};
242         return applyLogicalOperation(op, array, 1);
243 }
244
245 static int ptrcompares(const void *p1, const void *p2) {
246         uintptr_t b1 = *(uintptr_t const *) p1;
247   uintptr_t b2 = *(uintptr_t const *) p2;
248         if (b1 < b2)
249                 return -1;
250         else if (b1 == b2)
251                 return 0;
252         else
253                 return 1;
254 }
255
256 BooleanEdge CSolver::rewriteLogicalOperation(LogicOp op, BooleanEdge * array, uint asize) {
257         BooleanEdge newarray[asize];
258         memcpy(newarray, array, asize * sizeof(BooleanEdge));
259         for(uint i=0; i < asize; i++) {
260                 BooleanEdge b=newarray[i];
261                 if (b->type == LOGICOP) {
262                         if (((BooleanLogic *) b.getBoolean())->replaced) {
263                                 newarray[i] = doRewrite(newarray[i]);
264                                 i--;//Check again
265                         }
266                 }
267         }
268         return applyLogicalOperation(op, newarray, asize);
269 }
270
271 BooleanEdge CSolver::applyLogicalOperation(LogicOp op, BooleanEdge *array, uint asize) {
272         BooleanEdge newarray[asize];
273         switch (op) {
274         case SATC_NOT: {
275                 return array[0].negate();
276         }
277         case SATC_IFF: {
278                 for (uint i = 0; i < 2; i++) {
279                         if (array[i]->type == BOOLCONST) {
280                                 if (array[i]->isTrue()) {
281                                         return array[1 - i];
282                                 } else {
283                                         newarray[0] = array[1 - i];
284                                         return applyLogicalOperation(SATC_NOT, newarray, 1);
285                                 }
286                         } else if (array[i]->type == LOGICOP) {
287                                 BooleanLogic *b =(BooleanLogic *)array[i].getBoolean();
288                                 if (b->replaced) {
289                                         return rewriteLogicalOperation(op, array, asize);
290                                 }
291                         }
292                 }
293                 break;
294         }
295         case SATC_OR: {
296                 for (uint i =0; i <asize; i++) {
297                         newarray[i] = applyLogicalOperation(SATC_NOT, array[i]);
298                 }
299                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_AND, newarray, asize));
300         }
301         case SATC_AND: {
302                 uint newindex = 0;
303                 for (uint i = 0; i < asize; i++) {
304                         BooleanEdge b = array[i];
305                         if (b->type == LOGICOP) {
306                                 if (((BooleanLogic *)b.getBoolean())->replaced)
307                                         return rewriteLogicalOperation(op, array, asize);
308                         }
309                         if (b->type == BOOLCONST) {
310                                 if (b->isTrue())
311                                         continue;
312                                 else
313                                         return boolFalse;
314                         } else
315                                 newarray[newindex++] = b;
316                 }
317                 if (newindex == 0) {
318                         return boolTrue;
319                 } else if (newindex == 1) {
320                         return newarray[0];
321                 } else {
322                         bsdqsort(newarray, newindex, sizeof(BooleanEdge), ptrcompares);
323                         array = newarray;
324                         asize = newindex;
325                 }
326                 break;
327         }
328         case SATC_XOR: {
329                 //handle by translation
330                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_IFF, array, asize));
331         }
332         case SATC_IMPLIES: {
333                 //handle by translation
334                 return applyLogicalOperation(SATC_OR, applyLogicalOperation(SATC_NOT, array[0]), array[1]);
335         }
336         }
337
338         ASSERT(asize != 0);
339         Boolean *boolean = new BooleanLogic(this, op, array, asize);
340         Boolean *b = boolMap.get(boolean);
341         if (b == NULL) {
342                 boolean->updateParents();
343                 boolMap.put(boolean, boolean);
344                 allBooleans.push(boolean);
345                 return BooleanEdge(boolean);
346         } else {
347                 delete boolean;
348                 return BooleanEdge(b);
349         }
350 }
351
352 BooleanEdge CSolver::orderConstraint(Order *order, uint64_t first, uint64_t second) {
353         Boolean *constraint = new BooleanOrder(order, first, second);
354         allBooleans.push(constraint);
355         return BooleanEdge(constraint);
356 }
357
358 void CSolver::addConstraint(BooleanEdge constraint) {
359         if (isTrue(constraint))
360                 return;
361         else if (isFalse(constraint))
362                 setUnSAT();
363         else {
364                 if (constraint->type == LOGICOP) {
365                         BooleanLogic *b=(BooleanLogic *) constraint.getBoolean();
366                         if (!constraint.isNegated()) {
367                                 if (b->op==SATC_AND) {
368                                         for(uint i=0;i<b->inputs.getSize();i++) {
369                                                 addConstraint(b->inputs.get(i));
370                                         }
371                                         return;
372                                 }
373                         }
374                         if (b->replaced) {
375                                 addConstraint(doRewrite(constraint));
376                                 return;
377                         }
378                 }
379                 constraints.add(constraint);
380                 Boolean *ptr=constraint.getBoolean();
381                 
382                 if (ptr->boolVal == BV_UNSAT)
383                         setUnSAT();
384                 
385                 replaceBooleanWithTrueNoRemove(constraint);
386                 constraint->parents.clear();
387         }
388 }
389
390 Order *CSolver::createOrder(OrderType type, Set *set) {
391         Order *order = new Order(type, set);
392         allOrders.push(order);
393         activeOrders.add(order);
394         return order;
395 }
396
397 int CSolver::solve() {
398         bool deleteTuner = false;
399         if (tuner == NULL) {
400                 tuner = new DefaultTuner();
401                 deleteTuner = true;
402         }
403
404         long long startTime = getTimeNano();
405         computePolarities(this);
406
407         Preprocess pp(this);
408         pp.doTransform();
409         
410         DecomposeOrderTransform dot(this);
411         dot.doTransform();
412
413         IntegerEncodingTransform iet(this);
414         iet.doTransform();
415
416         naiveEncodingDecision(this);
417         satEncoder->encodeAllSATEncoder(this);
418         int result = unsat ? IS_UNSAT : satEncoder->solve();
419         long long finishTime = getTimeNano();
420         elapsedTime = finishTime - startTime;
421         if (deleteTuner) {
422                 delete tuner;
423                 tuner = NULL;
424         }
425         return result;
426 }
427
428 uint64_t CSolver::getElementValue(Element *element) {
429         switch (element->type) {
430         case ELEMSET:
431         case ELEMCONST:
432         case ELEMFUNCRETURN:
433                 return getElementValueSATTranslator(this, element);
434         default:
435                 ASSERT(0);
436         }
437         exit(-1);
438 }
439
440 bool CSolver::getBooleanValue(BooleanEdge bedge) {
441         Boolean *boolean=bedge.getBoolean();
442         switch (boolean->type) {
443         case BOOLEANVAR:
444                 return getBooleanVariableValueSATTranslator(this, boolean);
445         default:
446                 ASSERT(0);
447         }
448         exit(-1);
449 }
450
451 bool CSolver::getOrderConstraintValue(Order *order, uint64_t first, uint64_t second) {
452         return order->encoding.resolver->resolveOrder(first, second);
453 }
454
455 long long CSolver::getEncodeTime() { return satEncoder->getEncodeTime(); }
456
457 long long CSolver::getSolveTime() { return satEncoder->getSolveTime(); }
458
459 void CSolver::autoTune(uint budget) {
460         AutoTuner *autotuner = new AutoTuner(budget);
461         autotuner->addProblem(this);
462         autotuner->tune();
463         delete autotuner;
464 }