c3208b91ec5fdd2747ffc763fa3e3b52dd60291a
[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 <stdlib.h>
21
22 CSolver::CSolver() :
23         boolTrue(new BooleanConst(true)),
24         boolFalse(new BooleanConst(false)),
25         unsat(false),
26         tuner(NULL),
27         elapsedTime(0)
28 {
29         satEncoder = new SATEncoder(this);
30 }
31
32 /** This function tears down the solver and the entire AST */
33
34 CSolver::~CSolver() {
35         uint size = allBooleans.getSize();
36         for (uint i = 0; i < size; i++) {
37                 delete allBooleans.get(i);
38         }
39
40         size = allSets.getSize();
41         for (uint i = 0; i < size; i++) {
42                 delete allSets.get(i);
43         }
44
45         size = allElements.getSize();
46         for (uint i = 0; i < size; i++) {
47                 delete allElements.get(i);
48         }
49
50         size = allTables.getSize();
51         for (uint i = 0; i < size; i++) {
52                 delete allTables.get(i);
53         }
54
55         size = allPredicates.getSize();
56         for (uint i = 0; i < size; i++) {
57                 delete allPredicates.get(i);
58         }
59
60         size = allOrders.getSize();
61         for (uint i = 0; i < size; i++) {
62                 delete allOrders.get(i);
63         }
64
65         size = allFunctions.getSize();
66         for (uint i = 0; i < size; i++) {
67                 delete allFunctions.get(i);
68         }
69
70         delete boolTrue;
71         delete boolFalse;
72         delete satEncoder;
73 }
74
75 CSolver *CSolver::clone() {
76         CSolver *copy = new CSolver();
77         CloneMap map;
78         SetIteratorBoolean *it = getConstraints();
79         while (it->hasNext()) {
80                 Boolean *b = it->next();
81                 copy->addConstraint(b->clone(copy, &map));
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, type, 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, Boolean *overflowstatus) {
144         Element *element = new ElementFunction(function,array,numArrays,overflowstatus);
145         Element *e = elemMap.get(element);
146         if (e == NULL) {
147                 allElements.push(element);
148                 elemMap.put(element, element);
149                 return element;
150         } else {
151                 delete element;
152                 return e;
153         }
154 }
155
156 Function *CSolver::createFunctionOperator(ArithOp op, Set **domain, uint numDomain, Set *range,OverFlowBehavior overflowbehavior) {
157         Function *function = new FunctionOperator(op, domain, numDomain, range, overflowbehavior);
158         allFunctions.push(function);
159         return function;
160 }
161
162 Predicate *CSolver::createPredicateOperator(CompOp op, Set **domain, uint numDomain) {
163         Predicate *predicate = new PredicateOperator(op, domain,numDomain);
164         allPredicates.push(predicate);
165         return predicate;
166 }
167
168 Predicate *CSolver::createPredicateTable(Table *table, UndefinedBehavior behavior) {
169         Predicate *predicate = new PredicateTable(table, behavior);
170         allPredicates.push(predicate);
171         return predicate;
172 }
173
174 Table *CSolver::createTable(Set **domains, uint numDomain, Set *range) {
175         Table *table = new Table(domains,numDomain,range);
176         allTables.push(table);
177         return table;
178 }
179
180 Table *CSolver::createTableForPredicate(Set **domains, uint numDomain) {
181         return createTable(domains, numDomain, NULL);
182 }
183
184 void CSolver::addTableEntry(Table *table, uint64_t *inputs, uint inputSize, uint64_t result) {
185         table->addNewTableEntry(inputs, inputSize, result);
186 }
187
188 Function *CSolver::completeTable(Table *table, UndefinedBehavior behavior) {
189         Function *function = new FunctionTable(table, behavior);
190         allFunctions.push(function);
191         return function;
192 }
193
194 Boolean *CSolver::getBooleanVar(VarType type) {
195         Boolean *boolean = new BooleanVar(type);
196         allBooleans.push(boolean);
197         return boolean;
198 }
199
200 Boolean *CSolver::getBooleanTrue() {
201         return boolTrue;
202 }
203
204 Boolean *CSolver::getBooleanFalse() {
205         return boolFalse;
206 }
207
208 Boolean *CSolver::applyPredicate(Predicate *predicate, Element **inputs, uint numInputs) {
209         return applyPredicateTable(predicate, inputs, numInputs, NULL);
210 }
211
212 Boolean *CSolver::applyPredicateTable(Predicate *predicate, Element **inputs, uint numInputs, Boolean *undefinedStatus) {
213         BooleanPredicate *boolean = new BooleanPredicate(predicate, inputs, numInputs, undefinedStatus);
214         Boolean *b = boolMap.get(boolean);
215         if (b == NULL) {
216                 boolMap.put(boolean, boolean);
217                 allBooleans.push(boolean);
218                 return boolean;
219         } else {
220                 delete boolean;
221                 return b;
222         }
223 }
224
225 bool CSolver::isTrue(Boolean *b) {
226         return b->isTrue();
227 }
228
229 bool CSolver::isFalse(Boolean *b) {
230         return b->isFalse();
231 }
232
233 Boolean *CSolver::applyLogicalOperation(LogicOp op, Boolean *arg1, Boolean *arg2) {
234         Boolean *array[] = {arg1, arg2};
235         return applyLogicalOperation(op, array, 2);
236 }
237
238 Boolean *CSolver::applyLogicalOperation(LogicOp op, Boolean *arg) {
239         Boolean *array[] = {arg};
240         return applyLogicalOperation(op, array, 1);
241 }
242
243 static int ptrcompares(const void *p1, const void *p2) {
244         uintptr_t b1 = *(uintptr_t const *) p1;
245   uintptr_t b2 = *(uintptr_t const *) p2;
246         if (b1 < b2)
247                 return -1;
248         else if (b1 == b2)
249                 return 0;
250         else
251                 return 1;
252 }
253
254 Boolean *CSolver::applyLogicalOperation(LogicOp op, Boolean **array, uint asize) {
255         Boolean *newarray[asize];
256         switch (op) {
257         case SATC_NOT: {
258                 if (array[0]->type == LOGICOP && ((BooleanLogic *)array[0])->op == SATC_NOT) {
259                         return ((BooleanLogic *) array[0])->inputs.get(0);
260                 } else if (array[0]->type == BOOLCONST) {
261                         return array[0]->isTrue() ? boolFalse : boolTrue;
262                 }
263                 break;
264         }
265         case SATC_IFF: {
266                 for (uint i = 0; i < 2; i++) {
267                         if (array[i]->type == BOOLCONST) {
268                                 if (array[i]->isTrue()) {
269                                         return array[1 - i];
270                                 } else {
271                                         newarray[0] = array[1 - i];
272                                         return applyLogicalOperation(SATC_NOT, newarray, 1);
273                                 }
274                         }
275                 }
276                 break;
277         }
278         case SATC_OR: {
279                 for (uint i =0; i <asize; i++) {
280                         newarray[i] = applyLogicalOperation(SATC_NOT, array[i]);
281                 }
282                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_AND, newarray, asize));
283         }
284         case SATC_AND: {
285                 uint newindex = 0;
286                 for (uint i = 0; i < asize; i++) {
287                         Boolean *b = array[i];
288                         if (b->type == BOOLCONST) {
289                                 if (b->isTrue())
290                                         continue;
291                                 else
292                                         return boolFalse;
293                         } else
294                                 newarray[newindex++] = b;
295                 }
296                 if (newindex == 0) {
297                         return boolTrue;
298                 } else if (newindex == 1) {
299                         return newarray[0];
300                 } else {
301                         qsort(newarray, asize, sizeof(Boolean *), ptrcompares);
302                         array = newarray;
303                         asize = newindex;
304                 }
305                 break;
306         }
307         case SATC_XOR: {
308                 //handle by translation
309                 return applyLogicalOperation(SATC_NOT, applyLogicalOperation(SATC_IFF, array, asize));
310         }
311         case SATC_IMPLIES: {
312                 //handle by translation
313                 return applyLogicalOperation(SATC_OR, applyLogicalOperation(SATC_NOT, array[0]), array[1]);
314         }
315         }
316
317         ASSERT(asize != 0);
318         Boolean *boolean = new BooleanLogic(this, op, array, asize);
319         Boolean *b = boolMap.get(boolean);
320         if (b == NULL) {
321                 boolMap.put(boolean, boolean);
322                 allBooleans.push(boolean);
323                 return boolean;
324         } else {
325                 delete boolean;
326                 return b;
327         }
328 }
329
330 Boolean *CSolver::orderConstraint(Order *order, uint64_t first, uint64_t second) {
331         Boolean *constraint = new BooleanOrder(order, first, second);
332         allBooleans.push(constraint);
333         return constraint;
334 }
335
336 void CSolver::addConstraint(Boolean *constraint) {
337         if (constraint == boolTrue)
338                 return;
339         else if (constraint == boolFalse)
340                 setUnSAT();
341         else {
342                 if (constraint->type == LOGICOP) {
343                         BooleanLogic *b=(BooleanLogic *) constraint;
344                         if (b->op==SATC_AND) {
345                                 for(uint i=0;i<b->inputs.getSize();i++) {
346                                         addConstraint(b->inputs.get(i));
347                                 }
348                                 return;
349                         }
350                 }
351
352                 constraints.add(constraint);
353         }
354 }
355
356 Order *CSolver::createOrder(OrderType type, Set *set) {
357         Order *order = new Order(type, set);
358         allOrders.push(order);
359         activeOrders.add(order);
360         return order;
361 }
362
363 int CSolver::solve() {
364         bool deleteTuner = false;
365         if (tuner == NULL) {
366                 tuner = new DefaultTuner();
367                 deleteTuner = true;
368         }
369
370         long long startTime = getTimeNano();
371         computePolarities(this);
372
373         DecomposeOrderTransform dot(this);
374         dot.doTransform();
375
376         //This leaks like crazy
377         //      IntegerEncodingTransform iet(this);
378         //iet.doTransform();
379
380         naiveEncodingDecision(this);
381         satEncoder->encodeAllSATEncoder(this);
382         int result = unsat ? IS_UNSAT : satEncoder->solve();
383         long long finishTime = getTimeNano();
384         elapsedTime = finishTime - startTime;
385         if (deleteTuner) {
386                 delete tuner;
387                 tuner = NULL;
388         }
389         return result;
390 }
391
392 uint64_t CSolver::getElementValue(Element *element) {
393         switch (element->type) {
394         case ELEMSET:
395         case ELEMCONST:
396         case ELEMFUNCRETURN:
397                 return getElementValueSATTranslator(this, element);
398         default:
399                 ASSERT(0);
400         }
401         exit(-1);
402 }
403
404 bool CSolver::getBooleanValue(Boolean *boolean) {
405         switch (boolean->type) {
406         case BOOLEANVAR:
407                 return getBooleanVariableValueSATTranslator(this, boolean);
408         default:
409                 ASSERT(0);
410         }
411         exit(-1);
412 }
413
414 bool CSolver::getOrderConstraintValue(Order *order, uint64_t first, uint64_t second) {
415         return order->encoding.resolver->resolveOrder(first, second);
416 }
417
418 long long CSolver::getEncodeTime() { return satEncoder->getEncodeTime(); }
419
420 long long CSolver::getSolveTime() { return satEncoder->getSolveTime(); }
421
422 void CSolver::autoTune(uint budget) {
423         AutoTuner *autotuner = new AutoTuner(budget);
424         autotuner->addProblem(this);
425         autotuner->tune();
426         delete autotuner;
427 }