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