Add IFF support
[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
15 SATEncoder::SATEncoder(CSolver * _solver) :
16         cnf(createCNF()),
17         solver(_solver) {
18 }
19
20 SATEncoder::~SATEncoder() {
21         deleteCNF(cnf);
22 }
23
24 int SATEncoder::solve() {
25         return solveCNF(cnf);
26 }
27
28 void SATEncoder::encodeAllSATEncoder(CSolver *csolver) {
29         SetIteratorBoolean *iterator = csolver->getConstraints();
30         while (iterator->hasNext()) {
31                 Boolean *constraint = iterator->next();
32                 Edge c = encodeConstraintSATEncoder(constraint);
33                 addConstraintCNF(cnf, c);
34         }
35         delete iterator;
36 }
37
38 Edge SATEncoder::encodeConstraintSATEncoder(Boolean *constraint) {
39         Edge result;
40         if (booledgeMap.contains(constraint)) {
41                 Edge e={(Node *) booledgeMap.get(constraint)};
42                 return e;
43         }
44         
45         switch (constraint->type) {
46         case ORDERCONST:
47                 result=encodeOrderSATEncoder((BooleanOrder *) constraint);
48                 break;
49         case BOOLEANVAR:
50                 result=encodeVarSATEncoder((BooleanVar *) constraint);
51                 break;
52         case LOGICOP:
53                 result=encodeLogicSATEncoder((BooleanLogic *) constraint);
54                 break;
55         case PREDICATEOP:
56                 result=encodePredicateSATEncoder((BooleanPredicate *) constraint);
57                 break;
58         default:
59                 model_print("Unhandled case in encodeConstraintSATEncoder %u", constraint->type);
60                 exit(-1);
61         }
62         booledgeMap.put(constraint, result.node_ptr);
63         return result;
64 }
65
66 void SATEncoder::getArrayNewVarsSATEncoder(uint num, Edge *carray) {
67         for (uint i = 0; i < num; i++)
68                 carray[i] = getNewVarSATEncoder();
69 }
70
71 Edge SATEncoder::getNewVarSATEncoder() {
72         return constraintNewVar(cnf);
73 }
74
75 Edge SATEncoder::encodeVarSATEncoder(BooleanVar *constraint) {
76         if (edgeIsNull(constraint->var)) {
77                 constraint->var = getNewVarSATEncoder();
78         }
79         return constraint->var;
80 }
81
82 Edge SATEncoder::encodeLogicSATEncoder(BooleanLogic *constraint) {
83         Edge array[constraint->inputs.getSize()];
84         for (uint i = 0; i < constraint->inputs.getSize(); i++)
85                 array[i] = encodeConstraintSATEncoder(constraint->inputs.get(i));
86
87         switch (constraint->op) {
88         case SATC_AND:
89                 return constraintAND(cnf, constraint->inputs.getSize(), array);
90         case SATC_OR:
91                 return constraintOR(cnf, constraint->inputs.getSize(), array);
92         case SATC_NOT:
93                 return constraintNegate(array[0]);
94         case SATC_XOR:
95                 return constraintXOR(cnf, array[0], array[1]);
96         case SATC_IFF:
97                 return constraintIFF(cnf, array[0], array[1]);
98         case SATC_IMPLIES:
99                 return constraintIMPLIES(cnf, array[0], array[1]);
100         default:
101                 model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op);
102                 exit(-1);
103         }
104 }
105
106 Edge SATEncoder::encodePredicateSATEncoder(BooleanPredicate *constraint) {
107         switch (constraint->predicate->type) {
108         case TABLEPRED:
109                 return encodeTablePredicateSATEncoder(constraint);
110         case OPERATORPRED:
111                 return encodeOperatorPredicateSATEncoder(constraint);
112         default:
113                 ASSERT(0);
114         }
115         return E_BOGUS;
116 }
117
118 Edge SATEncoder::encodeTablePredicateSATEncoder(BooleanPredicate *constraint) {
119         switch (constraint->encoding.type) {
120         case ENUMERATEIMPLICATIONS:
121         case ENUMERATEIMPLICATIONSNEGATE:
122                 return encodeEnumTablePredicateSATEncoder(constraint);
123         case CIRCUIT:
124                 ASSERT(0);
125                 break;
126         default:
127                 ASSERT(0);
128         }
129         return E_BOGUS;
130 }
131
132 void SATEncoder::encodeElementSATEncoder(Element *element) {
133         /* Check to see if we have already encoded this element. */
134         if (getElementEncoding(element)->variables != NULL)
135                 return;
136         
137         /* Need to encode. */
138         switch ( element->type) {
139         case ELEMFUNCRETURN:
140                 generateElementEncoding(element);
141                 encodeElementFunctionSATEncoder((ElementFunction *) element);
142                 break;
143         case ELEMSET:
144                 generateElementEncoding(element);
145                 return;
146         case ELEMCONST:
147                 return;
148         default:
149                 ASSERT(0);
150         }
151 }
152
153 void SATEncoder::encodeElementFunctionSATEncoder(ElementFunction *function) {
154         switch (function->function->type) {
155         case TABLEFUNC:
156                 encodeTableElementFunctionSATEncoder(function);
157                 break;
158         case OPERATORFUNC:
159                 encodeOperatorElementFunctionSATEncoder(function);
160                 break;
161         default:
162                 ASSERT(0);
163         }
164 }
165
166 void SATEncoder::encodeTableElementFunctionSATEncoder(ElementFunction *function) {
167         switch (getElementFunctionEncoding(function)->type) {
168         case ENUMERATEIMPLICATIONS:
169                 encodeEnumTableElemFunctionSATEncoder(function);
170                 break;
171         case CIRCUIT:
172                 ASSERT(0);
173                 break;
174         default:
175                 ASSERT(0);
176         }
177 }