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, false);
150 node->status = FINISHED;
151 pushVectorOrderNode(finishNodes, node);
154 deleteIterOrderNode(iterator);
157 void DFSMustNodeVisit(OrderNode *node, VectorOrderNode *finishNodes, bool clearBackEdges) {
158 //First compute implication of transitive closure on must pos edges
159 HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges);
160 while (hasNextOrderEdge(iterator)) {
161 OrderEdge *edge = nextOrderEdge(iterator);
162 OrderNode *parent = edge->source;
163 if (parent->status == VISITED) {
164 edge->mustPos = true;
167 deleteIterOrderEdge(iterator);
169 //Next compute implication of transitive closure on must neg edges
170 iterator = iteratorOrderEdge(node->outEdges);
171 while (hasNextOrderEdge(iterator)) {
172 OrderEdge *edge = nextOrderEdge(iterator);
173 OrderNode *child = edge->sink;
175 if (clearBackEdges && child->status == VISITED) {
176 //We have a backedge, so note that this edge must be negative
177 edge->mustNeg = true;
180 if (!edge->mustPos) //Ignore edges that are not must Positive edges
183 if (child->status == NOTVISITED) {
184 child->status = VISITED;
185 DFSMustNodeVisit(child, finishNodes, clearBackEdges);
186 child->status = FINISHED;
187 pushVectorOrderNode(finishNodes, child);
190 deleteIterOrderEdge(iterator);
193 void DFSClearContradictions(OrderGraph *graph, VectorOrderNode *finishNodes) {
194 uint size = getSizeVectorOrderNode(finishNodes);
195 for (int i = size - 1; i >= 0; i--) {
196 OrderNode *node = getVectorOrderNode(finishNodes, i);
197 if (node->status == NOTVISITED) {
198 node->status = VISITED;
199 DFSMustNodeVisit(node, NULL, true);
200 node->status = FINISHED;
205 /* This function finds edges that would form a cycle with must edges
206 and forces them to be mustNeg. It also decides whether an edge
207 must be true because of transitivity from other must be true
210 void reachMustAnalysis(OrderGraph *graph) {
211 VectorOrderNode finishNodes;
212 initDefVectorOrderNode(&finishNodes);
213 //Topologically sort the mustPos edge graph
214 DFSMust(graph, &finishNodes);
215 resetNodeInfoStatusSCC(graph);
217 //Find any backwards edges that complete cycles and force them to be mustNeg
218 DFSClearContradictions(graph, &finishNodes);
219 deleteVectorArrayOrderNode(&finishNodes);
220 resetNodeInfoStatusSCC(graph);
223 /* This function finds edges that must be positive and forces the
224 inverse edge to be negative (and clears its positive polarity if it
227 void localMustAnalysisTotal(OrderGraph *graph) {
228 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
229 while (hasNextOrderEdge(iterator)) {
230 OrderEdge *edge = nextOrderEdge(iterator);
232 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
233 if (invEdge != NULL && !invEdge->mustPos && invEdge->polPos) {
234 invEdge->polPos = false;
236 invEdge->mustNeg = true;
239 deleteIterOrderEdge(iterator);
242 /** This finds edges that must be positive and forces the inverse edge
243 to be negative. It also clears the negative flag of this edge.
244 It also finds edges that must be negative and clears the positive
247 void localMustAnalysisPartial(OrderGraph *graph) {
248 HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges);
249 while (hasNextOrderEdge(iterator)) {
250 OrderEdge *edge = nextOrderEdge(iterator);
252 if (edge->polNeg && !edge->mustNeg) {
253 edge->polNeg = false;
255 OrderEdge *invEdge = getInverseOrderEdge(graph, edge);
256 if (invEdge != NULL && !invEdge->mustPos) {
257 invEdge->polPos = false;
259 invEdge->mustNeg = true;
261 if (edge->mustNeg && !edge->mustPos) {
262 edge->polPos = false;
265 deleteIterOrderEdge(iterator);
268 void decomposeOrder(CSolver *This, Order *order, OrderGraph *graph) {
269 VectorOrder ordervec;
270 initDefVectorOrder(&ordervec);
271 uint size = getSizeVectorBooleanOrder(&order->constraints);
272 for (uint i = 0; i < size; i++) {
273 BooleanOrder *orderconstraint = getVectorBooleanOrder(&order->constraints, i);
274 OrderNode *from = getOrderNodeFromOrderGraph(graph, orderconstraint->first);
275 OrderNode *to = getOrderNodeFromOrderGraph(graph, orderconstraint->second);
276 OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to);
277 if (from->sccNum < to->sccNum) {
279 replaceBooleanWithTrue((Boolean *)orderconstraint);
280 } else if (to->sccNum < from->sccNum) {
282 replaceBooleanWithFalse((Boolean *)orderconstraint);
284 //Build new order and change constraint's order
285 Order * neworder = NULL;
286 if (getSizeVectorOrder(&ordervec) > from->sccNum)
287 neworder = getVectorOrder(&ordervec, from->sccNum);
288 if (neworder == NULL) {
289 Set * set = (Set *) allocMutableSet(order->set->type);
290 neworder = allocOrder(order->type, set);
291 pushVectorOrder(This->allOrders, neworder);
292 setExpandVectorOrder(&ordervec, from->sccNum, neworder);
294 if (from->status != ADDEDTOSET) {
295 from->status = ADDEDTOSET;
296 addElementMSet((MutableSet *)neworder->set, from->id);
298 if (to->status != ADDEDTOSET) {
299 to->status = ADDEDTOSET;
300 addElementMSet((MutableSet *)neworder->set, to->id);
302 orderconstraint->order = neworder;
303 addOrderConstraint(neworder, orderconstraint);
306 deleteVectorArrayOrder(&ordervec);
309 void orderAnalysis(CSolver *This) {
310 uint size = getSizeVectorOrder(This->allOrders);
311 for (uint i = 0; i < size; i++) {
312 Order *order = getVectorOrder(This->allOrders, i);
313 OrderGraph *graph = buildOrderGraph(order);
314 if (order->type == PARTIAL) {
315 //Required to do SCC analysis for partial order graphs. It
316 //makes sure we don't incorrectly optimize graphs with negative
318 completePartialOrderGraph(graph);
321 //This analysis is completely optional
322 reachMustAnalysis(graph);
324 //This pair of analysis is also optional
325 if (order->type == PARTIAL) {
326 localMustAnalysisPartial(graph);
328 localMustAnalysisTotal(graph);
331 //This optimization is completely optional
332 removeMustBeTrueNodes(graph);
334 //This is needed for splitorder
335 computeStronglyConnectedComponentGraph(graph);
337 decomposeOrder(This, order, graph);
339 deleteOrderGraph(graph);