a1fd4c5cb8f26b397e6bfe2c017d6855423970f9
[satune.git] / src / Backend / nodeedge.c
1 #include "nodeedge.h"
2 #include <string.h>
3 #include <stdlib.h>
4
5 CNF * createCNF() {
6         CNF * cnf=ourmalloc(sizeof(CNF));
7         cnf->varcount=1;
8         cnf->capacity=DEFAULT_CNF_ARRAY_SIZE;
9         cnf->mask=cnf->capacity-1;
10         cnf->node_array=ourcalloc(1, sizeof(Node *)*cnf->capacity);
11         cnf->size=0;
12         cnf->maxsize=(uint)(((double)cnf->capacity)*LOAD_FACTOR);
13         return cnf;
14 }
15
16 void deleteCNF(CNF * cnf) {
17         for(uint i=0;i<cnf->capacity;i++) {
18                 Node *n=cnf->node_array[i];
19                 if (n!=NULL)
20                         ourfree(n);
21         }
22         ourfree(cnf->node_array);
23         ourfree(cnf);
24 }
25
26 void resizeCNF(CNF *cnf, uint newCapacity) {
27         Node **old_array=cnf->node_array;
28         Node **new_array=ourcalloc(1, sizeof(Node *)*newCapacity);
29         uint oldCapacity=cnf->capacity;
30         uint newMask=newCapacity-1;
31         for(uint i=0;i<oldCapacity;i++) {
32                 Node *n=old_array[i];
33                 uint hashCode=n->hashCode;
34                 uint newindex=hashCode & newMask;
35                 for(;;newindex=(newindex+1) & newMask) {
36                         if (new_array[newindex] == NULL) {
37                                 new_array[newindex]=n;
38                                 break;
39                         }
40                 }
41         }
42         ourfree(old_array);
43         cnf->node_array=new_array;
44         cnf->capacity=newCapacity;
45         cnf->maxsize=(uint)(((double)cnf->capacity)*LOAD_FACTOR);
46         cnf->mask=newMask;
47 }
48
49 Node * allocNode(NodeType type, uint numEdges, Edge * edges, uint hashcode) {
50         Node *n=(Node *)ourmalloc(sizeof(Node)+sizeof(Edge)*numEdges);
51         memcpy(n->edges, edges, sizeof(Edge)*numEdges);
52         n->numEdges=numEdges;
53         n->flags.type=type;
54         n->hashCode=hashcode;
55         return n;
56 }
57
58 Edge createNode(CNF *cnf, NodeType type, uint numEdges, Edge * edges) {
59         if (cnf->size > cnf->maxsize) {
60                 resizeCNF(cnf, cnf->capacity << 1);
61         }
62         uint hashvalue=hashNode(type, numEdges, edges);
63         uint mask=cnf->mask;
64         uint index=hashvalue & mask;
65         Node **n_ptr;
66         for(;;index=(index+1)&mask) {
67                 n_ptr=&cnf->node_array[index];
68                 if (*n_ptr!=NULL) {
69                         if ((*n_ptr)->hashCode==hashvalue) {
70                                 if (compareNodes(*n_ptr, type, numEdges, edges)) {
71                                         Edge e={*n_ptr};
72                                         return e;
73                                 }
74                         }
75                 } else {
76                         break;
77                 }
78         }
79         *n_ptr=allocNode(type, numEdges, edges, hashvalue);
80         Edge e={*n_ptr};
81         return e;
82 }
83
84 uint hashNode(NodeType type, uint numEdges, Edge * edges) {
85         uint hashvalue=type ^ numEdges;
86         for(uint i=0;i<numEdges;i++) {
87                 hashvalue ^= (uint) edges[i].node_ptr;
88                 hashvalue = (hashvalue << 3) | (hashvalue >> 29); //rotate left by 3 bits
89         }
90         return (uint) hashvalue;
91 }
92
93 bool compareNodes(Node * node, NodeType type, uint numEdges, Edge *edges) {
94         if (node->flags.type!=type || node->numEdges != numEdges)
95                 return false;
96         Edge *nodeedges=node->edges;
97         for(uint i=0;i<numEdges;i++) {
98                 if (nodeedges[i].node_ptr!=edges[i].node_ptr)
99                         return false;
100         }
101         return true;
102 }
103
104 Edge constraintOR(CNF * cnf, uint numEdges, Edge *edges) {
105         Edge edgearray[numEdges];
106         
107         for(uint i=0; i<numEdges; i++) {
108                 edgearray[i]=constraintNegate(edges[i]);
109         }
110         Edge eand=constraintAND(cnf, numEdges, edgearray);
111         return constraintNegate(eand);
112 }
113
114 Edge constraintOR2(CNF * cnf, Edge left, Edge right) {
115         Edge lneg=constraintNegate(left);
116         Edge rneg=constraintNegate(right);
117         Edge eand=constraintAND2(cnf, left, right);
118         return constraintNegate(eand);
119 }
120
121 int comparefunction(const Edge * e1, const Edge * e2) {
122         return ((uintptr_t)e1->node_ptr)-((uintptr_t)e2->node_ptr);
123 }
124
125 Edge constraintAND(CNF * cnf, uint numEdges, Edge * edges) {
126         qsort(edges, numEdges, sizeof(Edge), (int (*)(const void *, const void *)) comparefunction);
127         int initindex=0;
128         while(initindex<numEdges && edges[initindex].node_ptr == E_True.node_ptr)
129                 initindex++;
130
131         uint remainSize=numEdges-initindex;
132
133         if (remainSize == 0)
134                 return E_True;
135         else if (remainSize == 1)
136                 return edges[initindex];
137         else if (edges[initindex].node_ptr==E_False.node_ptr)
138                 return E_False;
139
140         /** De-duplicate array */
141         uint lowindex=0;
142         edges[lowindex++]=edges[initindex++];
143
144         for(;initindex<numEdges;initindex++) {
145                 Edge e1=edges[lowindex];
146                 Edge e2=edges[initindex];
147                 if (sameNodeVarEdge(e1, e2)) {
148                         if (!sameSignEdge(e1, e2)) {
149                                 return E_False;
150                         }
151                 } else
152                         edges[lowindex++]=edges[initindex];
153         }
154         if (lowindex==1)
155                 return edges[0];
156
157         if (enableMatching && lowindex==2 &&
158                         isNegNodeEdge(edges[0]) && isNegNodeEdge(edges[1]) &&
159                         getNodeType(edges[0]) == NodeType_AND &&
160                         getNodeType(edges[1]) == NodeType_AND &&
161                         getNodeSize(edges[0]) == 2 &&
162                         getNodeSize(edges[1]) == 2) {
163                 Edge * e0edges=getEdgeArray(edges[0]);
164                 Edge * e1edges=getEdgeArray(edges[1]);
165                 if (sameNodeOppSign(e0edges[0], e1edges[0])) {
166                         return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[1]));
167                 } else if (sameNodeOppSign(e0edges[0], e1edges[1])) {
168                         return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[0]));
169                 } else if (sameNodeOppSign(e0edges[1], e1edges[0])) {
170                         return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[1]));
171                 } else if (sameNodeOppSign(e0edges[1], e1edges[1])) {
172                         return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[0]));
173                 }
174         }
175         
176         return createNode(cnf, NodeType_AND, numEdges, edges);
177 }
178
179 Edge constraintAND2(CNF * cnf, Edge left, Edge right) {
180         Edge edges[2]={left, right};
181         return constraintAND(cnf, 2, edges);
182 }
183
184 Edge constraintIMPLIES(CNF * cnf, Edge left, Edge right) {
185         Edge array[2];
186         array[0]=left;
187         array[1]=constraintNegate(right);
188         Edge eand=constraintAND(cnf, 2, array);
189         return constraintNegate(eand);
190 }
191
192 Edge constraintIFF(CNF * cnf, Edge left, Edge right) {
193         Edge edges[2];
194         if ((uintptr_t)left.node_ptr < (uintptr_t) right.node_ptr) {
195                 edges[0]=left;
196                 edges[1]=right;
197         } else {
198                 edges[0]=right;
199                 edges[1]=left;
200         }
201         return createNode(cnf, NodeType_IFF, 2, edges);
202 }
203
204 Edge constraintITE(CNF * cnf, Edge cond, Edge thenedge, Edge elseedge) {
205         Edge edges[]={cond, thenedge, elseedge};
206         return createNode(cnf, NodeType_ITE, 3, edges);
207 }
208
209 Edge constraintNewVar(CNF *cnf) {
210         uint varnum=cnf->varcount++;
211         Edge e={(Node *) ((((uintptr_t)varnum) << VAR_SHIFT) | EDGE_IS_VAR_CONSTANT) };
212         return e;
213 }