Adding OrderPairResolver
[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 "transformer.h"
15 #include "autotuner.h"
16 #include "astops.h"
17 #include "structs.h"
18 #include "orderresolver.h"
19
20 CSolver::CSolver() :
21         boolTrue(new BooleanConst(true)),
22         boolFalse(new BooleanConst(false)),
23         unsat(false),
24         tuner(NULL),
25         elapsedTime(0)
26 {
27         satEncoder = new SATEncoder(this);
28         transformer = new Transformer(this);
29 }
30
31 /** This function tears down the solver and the entire AST */
32
33 CSolver::~CSolver() {
34         uint size = allBooleans.getSize();
35         for (uint i = 0; i < size; i++) {
36                 delete allBooleans.get(i);
37         }
38
39         size = allSets.getSize();
40         for (uint i = 0; i < size; i++) {
41                 delete allSets.get(i);
42         }
43
44         size = allElements.getSize();
45         for (uint i = 0; i < size; i++) {
46                 delete allElements.get(i);
47         }
48
49         size = allTables.getSize();
50         for (uint i = 0; i < size; i++) {
51                 delete allTables.get(i);
52         }
53
54         size = allPredicates.getSize();
55         for (uint i = 0; i < size; i++) {
56                 delete allPredicates.get(i);
57         }
58
59         size = allOrders.getSize();
60         for (uint i = 0; i < size; i++) {
61                 delete allOrders.get(i);
62         }
63
64         size = allFunctions.getSize();
65         for (uint i = 0; i < size; i++) {
66                 delete allFunctions.get(i);
67         }
68
69         delete boolTrue;
70         delete boolFalse;
71         delete satEncoder;
72         delete transformer;
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
244 Boolean *CSolver::applyLogicalOperation(LogicOp op, Boolean **array, uint asize) {
245         Boolean * newarray[asize];
246         switch(op) {
247         case SATC_NOT: {
248                 if (array[0]->type == LOGICOP && ((BooleanLogic *)array[0])->op==SATC_NOT) {
249                         return ((BooleanLogic *) array[0])->inputs.get(0);
250                 } else if (array[0]->type == BOOLCONST) {
251                         return array[0]->isTrue() ? boolFalse : boolTrue;
252                 }
253                 break;
254         }
255         case SATC_IFF: {
256                 for(uint i=0;i<2;i++) {
257                         if (array[i]->type == BOOLCONST) {
258                                 if (array[i]->isTrue()) {
259                                         return array[1-i];
260                                 } else {
261                                         newarray[0]=array[1-i];
262                                         return applyLogicalOperation(SATC_NOT, newarray, 1);
263                                 }
264                         }
265                 }
266                 break;
267         }
268         case SATC_XOR: {
269                 for(uint i=0;i<2;i++) {
270                         if (array[i]->type == BOOLCONST) {
271                                 if (array[i]->isTrue()) {
272                                         newarray[0]=array[1-i];
273                                         return applyLogicalOperation(SATC_NOT, newarray, 1);
274                                 } else
275                                         return array[1-i];
276                         }
277                 }
278                 break;
279         }
280         case SATC_OR: {
281                 uint newindex=0;
282                 for(uint i=0;i<asize;i++) {
283                         Boolean *b=array[i];
284                         if (b->type == BOOLCONST) {
285                                 if (b->isTrue())
286                                         return boolTrue;
287                                 else
288                                         continue;
289                         } else
290                                 newarray[newindex++]=b;
291                 }
292                 if (newindex==0) {
293                         return boolFalse;
294                 } else if (newindex==1)
295                         return newarray[0];
296                 else if (newindex == 2) {
297                         bool isNot0 = (newarray[0]->type==BOOLCONST) && ((BooleanLogic *)newarray[0])->op == SATC_NOT;
298                         bool isNot1 = (newarray[1]->type==BOOLCONST) && ((BooleanLogic *)newarray[1])->op == SATC_NOT;
299
300                         if (isNot0 != isNot1) {
301                                 if (isNot0) {
302                                         newarray[0] = ((BooleanLogic *) newarray[0])->inputs.get(0);
303                                 } else {
304                                         Boolean *tmp =  ((BooleanLogic *) array[1])->inputs.get(0);
305                                         array[1] = array[0];
306                                         array[0] = tmp;
307                                 }
308                                 return applyLogicalOperation(SATC_IMPLIES, newarray, 2);
309                         }
310                 } else {
311                         array = newarray;
312                         asize = newindex;
313                 }
314                 break;
315         }
316         case SATC_AND: {
317                 uint newindex=0;
318                 for(uint i=0;i<asize;i++) {
319                         Boolean *b=array[i];
320                         if (b->type == BOOLCONST) {
321                                 if (b->isTrue())
322                                         continue;
323                                 else
324                                         return boolFalse;
325                         } else
326                                 newarray[newindex++]=b;
327                 }
328                 if (newindex==0) {
329                         return boolTrue;
330                 } else if(newindex==1) {
331                         return newarray[0];
332                 } else {
333                         array = newarray;
334                         asize = newindex;
335                 }
336                 break;
337         }
338         case SATC_IMPLIES: {
339                 if (array[0]->type == BOOLCONST) {
340                         if (array[0]->isTrue()) {
341                                 return array[1];
342                         } else {
343                                 return boolTrue;
344                         }
345                 } else if (array[1]->type == BOOLCONST) {
346                         if (array[1]->isTrue()) {
347                                 return array[1];
348                         } else {
349                                 return applyLogicalOperation(SATC_NOT, array, 1);
350                         }
351                 }
352                 break;
353         }
354         }
355         
356         ASSERT(asize != 0);
357         Boolean *boolean = new BooleanLogic(this, op, array, asize);
358         Boolean *b = boolMap.get(boolean);
359         if (b == NULL) {
360                 boolMap.put(boolean, boolean);
361                 allBooleans.push(boolean);
362                 return boolean;         
363         } else {
364                 delete boolean;
365                 return b;
366         }
367 }
368
369 Boolean *CSolver::orderConstraint(Order *order, uint64_t first, uint64_t second) {
370         Boolean *constraint = new BooleanOrder(order, first, second);
371         allBooleans.push(constraint);
372         return constraint;
373 }
374
375 void CSolver::addConstraint(Boolean *constraint) {
376         if (constraint == boolTrue)
377                 return;
378         else if (constraint == boolFalse)
379                 setUnSAT();
380         else
381                 constraints.add(constraint);
382 }
383
384 Order *CSolver::createOrder(OrderType type, Set *set) {
385         Order *order = new Order(type, set);
386         allOrders.push(order);
387         return order;
388 }
389
390 int CSolver::solve() {
391         bool deleteTuner = false;
392         if (tuner == NULL) {
393                 tuner = new DefaultTuner();
394                 deleteTuner = true;
395         }
396                 
397         long long startTime = getTimeNano();
398         computePolarities(this);
399         transformer->orderAnalysis();
400         naiveEncodingDecision(this);
401         satEncoder->encodeAllSATEncoder(this);
402         int result = unsat ? IS_UNSAT : satEncoder->solve();
403         long long finishTime = getTimeNano();
404         elapsedTime = finishTime - startTime;
405         if (deleteTuner) {
406                 delete tuner;
407                 tuner = NULL;
408         }
409         return result;
410 }
411
412 uint64_t CSolver::getElementValue(Element *element) {
413         switch (element->type) {
414         case ELEMSET:
415         case ELEMCONST:
416         case ELEMFUNCRETURN:
417                 return getElementValueSATTranslator(this, element);
418         default:
419                 ASSERT(0);
420         }
421         exit(-1);
422 }
423
424 bool CSolver::getBooleanValue(Boolean *boolean) {
425         switch (boolean->type) {
426         case BOOLEANVAR:
427                 return getBooleanVariableValueSATTranslator(this, boolean);
428         default:
429                 ASSERT(0);
430         }
431         exit(-1);
432 }
433
434 HappenedBefore CSolver::getOrderConstraintValue(Order *order, uint64_t first, uint64_t second) {
435         return  order->encoding.resolver->resolveOrder(first, second);
436 }
437
438 long long CSolver::getEncodeTime() { return satEncoder->getEncodeTime(); }
439
440 long long CSolver::getSolveTime() { return satEncoder->getSolveTime(); }
441
442 void CSolver::autoTune(uint budget) {
443         AutoTuner * autotuner=new AutoTuner(budget);
444         autotuner->addProblem(this);
445         autotuner->tune();
446         delete autotuner;
447 }