1 #include "orderencoder.h"
5 #include "ordergraph.h"
9 #include "mutableset.h"
11 OrderGraph *buildOrderGraph(Order *order) {
12 OrderGraph *orderGraph = allocOrderGraph(order);
13 uint constrSize = getSizeVectorBooleanOrder(&order->constraints);
14 for (uint j = 0; j < constrSize; j++) {
15 addOrderConstraintToOrderGraph(orderGraph, getVectorBooleanOrder(&order->constraints, j));
20 void DFS(OrderGraph *graph, VectorOrderNode *finishNodes) {
21 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
22 while (hasNextOrderNode(iterator)) {
23 OrderNode *node = nextOrderNode(iterator);
24 if (node->status == NOTVISITED) {
25 node->status = VISITED;
26 DFSNodeVisit(node, finishNodes, false, 0);
27 node->status = FINISHED;
28 pushVectorOrderNode(finishNodes, node);
31 deleteIterOrderNode(iterator);
34 void DFSReverse(OrderGraph *graph, VectorOrderNode *finishNodes) {
35 uint size = getSizeVectorOrderNode(finishNodes);
37 for (int i = size - 1; i >= 0; i--) {
38 OrderNode *node = getVectorOrderNode(finishNodes, i);
39 if (node->status == NOTVISITED) {
40 node->status = VISITED;
41 DFSNodeVisit(node, NULL, true, sccNum);
42 node->sccNum = sccNum;
43 node->status = FINISHED;
49 void DFSNodeVisit(OrderNode *node, VectorOrderNode *finishNodes, bool isReverse, uint sccNum) {
50 HSIteratorOrderEdge *iterator = isReverse ? iteratorOrderEdge(node->inEdges) : iteratorOrderEdge(node->outEdges);
51 while (hasNextOrderEdge(iterator)) {
52 OrderEdge *edge = nextOrderEdge(iterator);
53 if (!edge->polPos && !edge->pseudoPos)//Ignore edges that do not have positive polarity
56 OrderNode *child = isReverse ? edge->source : edge->sink;
58 if (child->status == NOTVISITED) {
59 child->status = VISITED;
60 DFSNodeVisit(child, finishNodes, isReverse, sccNum);
61 child->status = FINISHED;
63 pushVectorOrderNode(finishNodes, child);
65 child->sccNum = sccNum;
68 deleteIterOrderEdge(iterator);
71 void resetNodeInfoStatusSCC(OrderGraph *graph) {
72 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
73 while (hasNextOrderNode(iterator)) {
74 nextOrderNode(iterator)->status = NOTVISITED;
76 deleteIterOrderNode(iterator);
79 void computeStronglyConnectedComponentGraph(OrderGraph *graph) {
80 VectorOrderNode finishNodes;
81 initDefVectorOrderNode(&finishNodes);
82 DFS(graph, &finishNodes);
83 resetNodeInfoStatusSCC(graph);
84 DFSReverse(graph, &finishNodes);
85 resetNodeInfoStatusSCC(graph);
86 deleteVectorArrayOrderNode(&finishNodes);
89 void removeMustBeTrueNodes(OrderGraph *graph) {
90 //TODO: Nodes that all the incoming/outgoing edges are MUST_BE_TRUE
93 void DFSPseudoNodeVisit(OrderGraph *graph, OrderNode *node) {
94 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
95 while (hasNextOrderEdge(iterator)) {
96 OrderEdge *inEdge = nextOrderEdge(iterator);
98 OrderNode *src = inEdge->source;
99 if (src->status == VISITED) {
100 //Make a pseudoEdge to point backwards
101 OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, inEdge->sink, inEdge->source);
102 newedge->pseudoPos = true;
106 deleteIterOrderEdge(iterator);
107 iterator = iteratorOrderEdge(node->outEdges);
108 while (hasNextOrderEdge(iterator)) {
109 OrderEdge *edge = nextOrderEdge(iterator);
110 if (!edge->polPos)//Ignore edges that do not have positive polarity
113 OrderNode *child = edge->sink;
114 if (child->status == NOTVISITED) {
115 child->status = VISITED;
116 DFSPseudoNodeVisit(graph, child);
117 child->status = FINISHED;
120 deleteIterOrderEdge(iterator);
123 void completePartialOrderGraph(OrderGraph *graph) {
124 VectorOrderNode finishNodes;
125 initDefVectorOrderNode(&finishNodes);
126 DFS(graph, &finishNodes);
127 resetNodeInfoStatusSCC(graph);
129 uint size = getSizeVectorOrderNode(&finishNodes);
130 for (int i = size - 1; i >= 0; i--) {
131 OrderNode *node = getVectorOrderNode(&finishNodes, i);
132 if (node->status == NOTVISITED) {
133 node->status = VISITED;
134 DFSPseudoNodeVisit(graph, node);
135 node->status = FINISHED;
139 resetNodeInfoStatusSCC(graph);
140 deleteVectorArrayOrderNode(&finishNodes);
143 void DFSMust(OrderGraph *graph, VectorOrderNode *finishNodes) {
144 HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes);
145 while (hasNextOrderNode(iterator)) {
146 OrderNode *node = nextOrderNode(iterator);
147 if (node->status == NOTVISITED) {
148 node->status = VISITED;
149 DFSMustNodeVisit(node, finishNodes);
150 node->status = FINISHED;
151 pushVectorOrderNode(finishNodes, node);
154 deleteIterOrderNode(iterator);
157 void DFSMustNodeVisit(OrderNode *node, VectorOrderNode *finishNodes) {
158 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges);
159 while (hasNextOrderEdge(iterator)) {
160 OrderEdge *edge = nextOrderEdge(iterator);
161 OrderNode *child = edge->sink;
163 if (!edge->mustPos) //Ignore edges that are not must Positive edges
166 if (child->status == NOTVISITED) {
167 child->status = VISITED;
168 DFSMustNodeVisit(child, finishNodes);
169 child->status = FINISHED;
170 pushVectorOrderNode(finishNodes, child);
173 deleteIterOrderEdge(iterator);
177 void DFSClearContradictions(CSolver *solver, OrderGraph *graph, VectorOrderNode *finishNodes, bool computeTransitiveClosure) {
178 uint size = getSizeVectorOrderNode(finishNodes);
179 HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25);
181 for (int i = size - 1; i >= 0; i--) {
182 OrderNode *node = getVectorOrderNode(finishNodes, i);
183 HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25);
184 putNodeToNodeSet(table, node, sources);
187 //Compute source sets
188 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
189 while (hasNextOrderEdge(iterator)) {
190 OrderEdge *edge = nextOrderEdge(iterator);
191 OrderNode *parent = edge->source;
193 addHashSetOrderNode(sources, parent);
194 HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent);
195 addAllHashSetOrderNode(sources, parent_srcs);
198 deleteIterOrderEdge(iterator);
200 if (computeTransitiveClosure) {
201 //Compute full transitive closure for nodes
202 HSIteratorOrderNode *srciterator = iteratorOrderNode(sources);
203 while (hasNextOrderNode(srciterator)) {
204 OrderNode *srcnode = nextOrderNode(srciterator);
205 OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, srcnode, node);
206 newedge->mustPos = true;
207 newedge->polPos = true;
208 if (newedge->mustNeg)
209 solver->unsat = true;
210 addHashSetOrderEdge(srcnode->outEdges,newedge);
211 addHashSetOrderEdge(node->inEdges,newedge);
213 deleteIterOrderNode(srciterator);
216 //Use source sets to compute mustPos edges
217 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges);
218 while (hasNextOrderEdge(iterator)) {
219 OrderEdge *edge = nextOrderEdge(iterator);
220 OrderNode *parent = edge->source;
221 if (!edge->mustPos && containsHashSetOrderNode(sources, parent)) {
222 edge->mustPos = true;
225 solver->unsat = true;
228 deleteIterOrderEdge(iterator);
231 //Use source sets to compute mustNeg for edges that would introduce cycle if true
232 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges);
233 while (hasNextOrderEdge(iterator)) {
234 OrderEdge *edge = nextOrderEdge(iterator);
235 OrderNode *child = edge->sink;
236 if (!edge->mustNeg && containsHashSetOrderNode(sources, child)) {
237 edge->mustNeg = true;
240 solver->unsat = true;
243 deleteIterOrderEdge(iterator);
247 resetAndDeleteHashTableNodeToNodeSet(table);
250 /* This function finds edges that would form a cycle with must edges
251 and forces them to be mustNeg. It also decides whether an edge
252 must be true because of transitivity from other must be true
255 void reachMustAnalysis(CSolver * solver, OrderGraph *graph, bool computeTransitiveClosure) {
256 VectorOrderNode finishNodes;
257 initDefVectorOrderNode(&finishNodes);
258 //Topologically sort the mustPos edge graph
259 DFSMust(graph, &finishNodes);
260 resetNodeInfoStatusSCC(graph);
262 //Find any backwards edges that complete cycles and force them to be mustNeg
263 DFSClearContradictions(solver, graph, &finishNodes, computeTransitiveClosure);
264 deleteVectorArrayOrderNode(&finishNodes);
265 resetNodeInfoStatusSCC(graph);
268 /* This function finds edges that must be positive and forces the
269 inverse edge to be negative (and clears its positive polarity if it
272 void localMustAnalysisTotal(CSolver *solver, OrderGraph *graph) {
273 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
274 while (hasNextOrderEdge(iterator)) {
275 OrderEdge *edge = nextOrderEdge(iterator);
277 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
278 if (invEdge != NULL) {
279 if (!invEdge->mustPos) {
280 invEdge->polPos = false;
282 solver->unsat = true;
284 invEdge->mustNeg = true;
285 invEdge->polNeg = true;
289 deleteIterOrderEdge(iterator);
292 /** This finds edges that must be positive and forces the inverse edge
293 to be negative. It also clears the negative flag of this edge.
294 It also finds edges that must be negative and clears the positive
297 void localMustAnalysisPartial(CSolver *solver, OrderGraph *graph) {
298 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
299 while (hasNextOrderEdge(iterator)) {
300 OrderEdge *edge = nextOrderEdge(iterator);
302 if (!edge->mustNeg) {
303 edge->polNeg = false;
305 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
306 if (invEdge != NULL) {
307 if (!invEdge->mustPos)
308 invEdge->polPos = false;
310 solver->unsat = true;
311 invEdge->mustNeg = true;
312 invEdge->polNeg = true;
315 if (edge->mustNeg && !edge->mustPos) {
316 edge->polPos = false;
319 deleteIterOrderEdge(iterator);
322 void decomposeOrder(CSolver *This, Order *order, OrderGraph *graph) {
323 VectorOrder ordervec;
324 initDefVectorOrder(&ordervec);
325 uint size = getSizeVectorBooleanOrder(&order->constraints);
326 for (uint i = 0; i < size; i++) {
327 BooleanOrder *orderconstraint = getVectorBooleanOrder(&order->constraints, i);
328 OrderNode *from = getOrderNodeFromOrderGraph(graph, orderconstraint->first);
329 OrderNode *to = getOrderNodeFromOrderGraph(graph, orderconstraint->second);
330 if (from->sccNum != to->sccNum) {
331 OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to);
333 replaceBooleanWithTrue(This, (Boolean *)orderconstraint);
334 } else if (edge->polNeg) {
335 replaceBooleanWithFalse(This, (Boolean *)orderconstraint);
337 //This case should only be possible if constraint isn't in AST
341 //Build new order and change constraint's order
342 Order *neworder = NULL;
343 if (getSizeVectorOrder(&ordervec) > from->sccNum)
344 neworder = getVectorOrder(&ordervec, from->sccNum);
345 if (neworder == NULL) {
346 Set *set = (Set *) allocMutableSet(order->set->type);
347 neworder = allocOrder(order->type, set);
348 pushVectorOrder(This->allOrders, neworder);
349 setExpandVectorOrder(&ordervec, from->sccNum, neworder);
351 if (from->status != ADDEDTOSET) {
352 from->status = ADDEDTOSET;
353 addElementMSet((MutableSet *)neworder->set, from->id);
355 if (to->status != ADDEDTOSET) {
356 to->status = ADDEDTOSET;
357 addElementMSet((MutableSet *)neworder->set, to->id);
359 orderconstraint->order = neworder;
360 addOrderConstraint(neworder, orderconstraint);
363 deleteVectorArrayOrder(&ordervec);
366 void orderAnalysis(CSolver *This) {
367 uint size = getSizeVectorOrder(This->allOrders);
368 for (uint i = 0; i < size; i++) {
369 Order *order = getVectorOrder(This->allOrders, i);
370 OrderGraph *graph = buildOrderGraph(order);
371 if (order->type == PARTIAL) {
372 //Required to do SCC analysis for partial order graphs. It
373 //makes sure we don't incorrectly optimize graphs with negative
375 completePartialOrderGraph(graph);
378 //This analysis is completely optional
379 reachMustAnalysis(This, graph, false);
381 //This pair of analysis is also optional
382 if (order->type == PARTIAL) {
383 localMustAnalysisPartial(This, graph);
385 localMustAnalysisTotal(This, graph);
388 //This optimization is completely optional
389 removeMustBeTrueNodes(graph);
391 //This is needed for splitorder
392 computeStronglyConnectedComponentGraph(graph);
394 decomposeOrder(This, order, graph);
396 deleteOrderGraph(graph);