memoize timeouts
[satune.git] / src / Backend / satencoder.cc
1 #include "satencoder.h"
2 #include "structs.h"
3 #include "csolver.h"
4 #include "boolean.h"
5 #include "constraint.h"
6 #include "common.h"
7 #include "element.h"
8 #include "function.h"
9 #include "tableentry.h"
10 #include "table.h"
11 #include "order.h"
12 #include "predicate.h"
13 #include "set.h"
14 #include "tunable.h"
15
16 SATEncoder::SATEncoder(CSolver *_solver) :
17         cnf(createCNF()),
18         solver(_solver),
19         vector(allocDefVectorEdge()) {
20 }
21
22 SATEncoder::~SATEncoder() {
23         deleteCNF(cnf);
24         deleteVectorEdge(vector);
25 }
26
27 void SATEncoder::resetSATEncoder() {
28         resetCNF(cnf);
29         booledgeMap.reset();
30 }
31
32 int SATEncoder::solve(long timeout) {
33         cnf->solver->timeout = timeout;
34         return solveCNF(cnf);
35 }
36
37 void SATEncoder::encodeAllSATEncoder(CSolver *csolver) {
38         SetIteratorBooleanEdge *iterator = csolver->getConstraints();
39         while (iterator->hasNext()) {
40                 BooleanEdge constraint = iterator->next();
41                 Edge c = encodeConstraintSATEncoder(constraint);
42                 addConstraintCNF(cnf, c);
43         }
44         delete iterator;
45 }
46
47 Edge SATEncoder::encodeConstraintSATEncoder(BooleanEdge c) {
48         Edge result;
49         Boolean *constraint = c.getBoolean();
50
51         if (booledgeMap.contains(constraint)) {
52                 Edge e = {(Node *) booledgeMap.get(constraint)};
53                 return c.isNegated() ? constraintNegate(e) : e;
54         }
55
56         switch (constraint->type) {
57         case ORDERCONST:
58                 result = encodeOrderSATEncoder((BooleanOrder *) constraint);
59                 break;
60         case BOOLEANVAR:
61                 result = encodeVarSATEncoder((BooleanVar *) constraint);
62                 break;
63         case LOGICOP:
64                 result = encodeLogicSATEncoder((BooleanLogic *) constraint);
65                 break;
66         case PREDICATEOP:
67                 result = encodePredicateSATEncoder((BooleanPredicate *) constraint);
68                 break;
69         case BOOLCONST:
70                 result = ((BooleanConst *) constraint)->isTrue() ? E_True : E_False;
71                 break;
72         default:
73                 model_print("Unhandled case in encodeConstraintSATEncoder %u", constraint->type);
74                 exit(-1);
75         }
76         Polarity p = constraint->polarity;
77         uint pSize = constraint->parents.getSize();
78
79         if ( !edgeIsVarConst(result) && pSize > (uint)solver->getTuner()->getTunable(PROXYVARIABLE, &proxyparameter) ) {
80                 Edge e = getNewVarSATEncoder();
81                 generateProxy(cnf, result, e, p);
82                 booledgeMap.put(constraint, e.node_ptr);
83                 result = e;
84         }
85
86         return c.isNegated() ? constraintNegate(result) : result;
87 }
88
89 void SATEncoder::getArrayNewVarsSATEncoder(uint num, Edge *carray) {
90         for (uint i = 0; i < num; i++)
91                 carray[i] = getNewVarSATEncoder();
92 }
93
94 Edge SATEncoder::getNewVarSATEncoder() {
95         return constraintNewVar(cnf);
96 }
97
98 Edge SATEncoder::encodeVarSATEncoder(BooleanVar *constraint) {
99         if (edgeIsNull(constraint->var)) {
100                 constraint->var = getNewVarSATEncoder();
101         }
102         return constraint->var;
103 }
104
105 Edge SATEncoder::encodeLogicSATEncoder(BooleanLogic *constraint) {
106         Edge array[constraint->inputs.getSize()];
107         for (uint i = 0; i < constraint->inputs.getSize(); i++)
108                 array[i] = encodeConstraintSATEncoder(constraint->inputs.get(i));
109
110         switch (constraint->op) {
111         case SATC_AND:
112                 return constraintAND(cnf, constraint->inputs.getSize(), array);
113         case SATC_NOT:
114                 return constraintNegate(array[0]);
115         case SATC_IFF:
116                 ASSERT(constraint->inputs.getSize() == 2);
117                 return constraintIFF(cnf, array[0], array[1]);
118         case SATC_OR:
119         case SATC_XOR:
120         case SATC_IMPLIES:
121         //Don't handle, translate these away...
122         default:
123                 model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op);
124                 exit(-1);
125         }
126 }
127
128 Edge SATEncoder::encodePredicateSATEncoder(BooleanPredicate *constraint) {
129         switch (constraint->predicate->type) {
130         case TABLEPRED:
131                 return encodeTablePredicateSATEncoder(constraint);
132         case OPERATORPRED:
133                 return encodeOperatorPredicateSATEncoder(constraint);
134         default:
135                 ASSERT(0);
136         }
137         return E_BOGUS;
138 }
139
140 Edge SATEncoder::encodeTablePredicateSATEncoder(BooleanPredicate *constraint) {
141         switch (constraint->encoding.type) {
142         case ENUMERATEIMPLICATIONS:
143         case ENUMERATEIMPLICATIONSNEGATE:
144                 return encodeEnumTablePredicateSATEncoder(constraint);
145         case CIRCUIT:
146                 ASSERT(0);
147                 break;
148         default:
149                 ASSERT(0);
150         }
151         return E_BOGUS;
152 }
153
154 void SATEncoder::encodeElementSATEncoder(Element *element) {
155         /* Check to see if we have already encoded this element. */
156         if (element->getElementEncoding()->variables != NULL)
157                 return;
158
159         /* Need to encode. */
160         switch ( element->type) {
161         case ELEMFUNCRETURN:
162                 generateElementEncoding(element);
163                 encodeElementFunctionSATEncoder((ElementFunction *) element);
164                 break;
165         case ELEMSET:
166                 generateElementEncoding(element);
167                 return;
168         case ELEMCONST:
169                 return;
170         default:
171                 ASSERT(0);
172         }
173 }
174
175 void SATEncoder::encodeElementFunctionSATEncoder(ElementFunction *function) {
176         switch (function->getFunction()->type) {
177         case TABLEFUNC:
178                 encodeTableElementFunctionSATEncoder(function);
179                 break;
180         case OPERATORFUNC:
181                 encodeOperatorElementFunctionSATEncoder(function);
182                 break;
183         default:
184                 ASSERT(0);
185         }
186 }
187
188 void SATEncoder::encodeTableElementFunctionSATEncoder(ElementFunction *function) {
189         switch (function->getElementFunctionEncoding()->type) {
190         case ENUMERATEIMPLICATIONS:
191                 encodeEnumTableElemFunctionSATEncoder(function);
192                 break;
193         case CIRCUIT:
194                 ASSERT(0);
195                 break;
196         default:
197                 ASSERT(0);
198         }
199 }