3 #include "orderanalysis.h"
7 #include "ordergraph.h"
11 #include "mutableset.h"
14 void DFS(OrderGraph *graph, Vector<OrderNode *> *finishNodes) {
15 SetIteratorOrderNode *iterator = graph->getNodes();
16 while (iterator->hasNext()) {
17 OrderNode *node = iterator->next();
18 if (node->status == NOTVISITED) {
19 node->status = VISITED;
20 DFSNodeVisit(node, finishNodes, false, false, 0);
21 node->status = FINISHED;
22 finishNodes->push(node);
28 void DFSReverse(OrderGraph *graph, Vector<OrderNode *> *finishNodes) {
29 uint size = finishNodes->getSize();
31 for (int i = size - 1; i >= 0; i--) {
32 OrderNode *node = finishNodes->get(i);
33 if (node->status == NOTVISITED) {
34 node->status = VISITED;
35 DFSNodeVisit(node, NULL, true, false, sccNum);
36 node->sccNum = sccNum;
37 node->status = FINISHED;
43 void DFSNodeVisit(OrderNode *node, Vector<OrderNode *> *finishNodes, bool isReverse, bool mustvisit, uint sccNum) {
44 SetIteratorOrderEdge *iterator = isReverse ? node->inEdges.iterator() : node->outEdges.iterator();
46 model_print("Node:%lu=>", node->id);
48 while (iterator->hasNext()) {
49 OrderEdge *edge = iterator->next();
51 model_print("Edge:%lu=>",(uintptr_t) edge);
57 if (!edge->polPos && !edge->pseudoPos) //Ignore edges that do not have positive polarity
60 OrderNode *child = isReverse ? edge->source : edge->sink;
62 model_println("NodeChild:%lu", child->id);
64 if (child->status == NOTVISITED) {
65 child->status = VISITED;
66 DFSNodeVisit(child, finishNodes, isReverse, mustvisit, sccNum);
67 child->status = FINISHED;
68 if (finishNodes != NULL)
69 finishNodes->push(child);
71 child->sccNum = sccNum;
77 void resetNodeInfoStatusSCC(OrderGraph *graph) {
78 SetIteratorOrderNode *iterator = graph->getNodes();
79 while (iterator->hasNext()) {
80 iterator->next()->status = NOTVISITED;
85 void computeStronglyConnectedComponentGraph(OrderGraph *graph) {
86 Vector<OrderNode *> finishNodes;
87 DFS(graph, &finishNodes);
88 resetNodeInfoStatusSCC(graph);
89 DFSReverse(graph, &finishNodes);
90 resetNodeInfoStatusSCC(graph);
93 bool isMustBeTrueNode(OrderNode *node) {
94 SetIteratorOrderEdge *iterator = node->inEdges.iterator();
95 while (iterator->hasNext()) {
96 OrderEdge *edge = iterator->next();
103 iterator = node->outEdges.iterator();
104 while (iterator->hasNext()) {
105 OrderEdge *edge = iterator->next();
106 if (!edge->mustPos) {
115 void bypassMustBeTrueNode(CSolver *This, OrderGraph *graph, OrderNode *node) {
116 SetIteratorOrderEdge *iterin = node->inEdges.iterator();
117 while (iterin->hasNext()) {
118 OrderEdge *inEdge = iterin->next();
119 OrderNode *srcNode = inEdge->source;
120 srcNode->outEdges.remove(inEdge);
121 SetIteratorOrderEdge *iterout = node->outEdges.iterator();
122 while (iterout->hasNext()) {
123 OrderEdge *outEdge = iterout->next();
124 OrderNode *sinkNode = outEdge->sink;
125 sinkNode->inEdges.remove(outEdge);
126 //Adding new edge to new sink and src nodes ...
127 if(srcNode == sinkNode){
129 model_println("bypassMustBe 1");
136 OrderEdge *newEdge = graph->getOrderEdgeFromOrderGraph(srcNode, sinkNode);
137 newEdge->mustPos = true;
138 newEdge->polPos = true;
139 if (newEdge->mustNeg){
141 model_println("BypassMustBe 2");
145 srcNode->outEdges.add(newEdge);
146 sinkNode->inEdges.add(newEdge);
153 void removeMustBeTrueNodes(CSolver *This, OrderGraph *graph) {
154 SetIteratorOrderNode *iterator = graph->getNodes();
155 while (iterator->hasNext()) {
156 OrderNode *node = iterator->next();
157 if (isMustBeTrueNode(node)) {
158 bypassMustBeTrueNode(This, graph, node);
164 /** This function computes a source set for every nodes, the set of
165 nodes that can reach that node via pospolarity edges. It then
166 looks for negative polarity edges from nodes in the the source set
167 to determine whether we need to generate pseudoPos edges. */
169 void completePartialOrderGraph(OrderGraph *graph) {
170 Vector<OrderNode *> finishNodes;
171 DFS(graph, &finishNodes);
172 resetNodeInfoStatusSCC(graph);
173 HashtableNodeToNodeSet *table = new HashtableNodeToNodeSet(128, 0.25);
175 Vector<OrderNode *> sccNodes;
177 uint size = finishNodes.getSize();
179 for (int i = size - 1; i >= 0; i--) {
180 OrderNode *node = finishNodes.get(i);
181 HashsetOrderNode *sources = new HashsetOrderNode(4, 0.25);
182 table->put(node, sources);
184 if (node->status == NOTVISITED) {
185 //Need to do reverse traversal here...
186 node->status = VISITED;
187 DFSNodeVisit(node, &sccNodes, true, false, sccNum);
188 node->status = FINISHED;
189 node->sccNum = sccNum;
193 //Compute in set for entire SCC
194 uint rSize = sccNodes.getSize();
195 for (uint j = 0; j < rSize; j++) {
196 OrderNode *rnode = sccNodes.get(j);
197 //Compute source sets
198 SetIteratorOrderEdge *iterator = rnode->inEdges.iterator();
199 while (iterator->hasNext()) {
200 OrderEdge *edge = iterator->next();
201 OrderNode *parent = edge->source;
203 sources->add(parent);
204 HashsetOrderNode *parent_srcs = (HashsetOrderNode *)table->get(parent);
205 sources->addAll(parent_srcs);
210 for (uint j = 0; j < rSize; j++) {
211 //Copy in set of entire SCC
212 OrderNode *rnode = sccNodes.get(j);
213 HashsetOrderNode *set = (j == 0) ? sources : sources->copy();
214 table->put(rnode, set);
216 //Use source sets to compute pseudoPos edges
217 SetIteratorOrderEdge *iterator = node->inEdges.iterator();
218 while (iterator->hasNext()) {
219 OrderEdge *edge = iterator->next();
220 OrderNode *parent = edge->source;
221 ASSERT(parent != rnode);
222 if (edge->polNeg && parent->sccNum != rnode->sccNum &&
223 sources->contains(parent)) {
224 OrderEdge *newedge = graph->getOrderEdgeFromOrderGraph(rnode, parent);
225 newedge->pseudoPos = true;
235 table->resetanddelete();
237 resetNodeInfoStatusSCC(graph);
240 void DFSMust(OrderGraph *graph, Vector<OrderNode *> *finishNodes) {
241 SetIteratorOrderNode *iterator = graph->getNodes();
242 while (iterator->hasNext()) {
243 OrderNode *node = iterator->next();
244 if (node->status == NOTVISITED) {
245 node->status = VISITED;
246 DFSNodeVisit(node, finishNodes, false, true, 0);
247 node->status = FINISHED;
248 finishNodes->push(node);
254 void DFSClearContradictions(CSolver *solver, OrderGraph *graph, Vector<OrderNode *> *finishNodes, bool computeTransitiveClosure) {
255 uint size = finishNodes->getSize();
256 HashtableNodeToNodeSet *table = new HashtableNodeToNodeSet(128, 0.25);
258 for (int i = size - 1; i >= 0; i--) {
259 OrderNode *node = finishNodes->get(i);
260 HashsetOrderNode *sources = new HashsetOrderNode(4, 0.25);
261 table->put(node, sources);
264 //Compute source sets
265 SetIteratorOrderEdge *iterator = node->inEdges.iterator();
266 while (iterator->hasNext()) {
267 OrderEdge *edge = iterator->next();
268 OrderNode *parent = edge->source;
270 sources->add(parent);
271 HashsetOrderNode *parent_srcs = (HashsetOrderNode *) table->get(parent);
272 sources->addAll(parent_srcs);
277 if (computeTransitiveClosure) {
278 //Compute full transitive closure for nodes
279 SetIteratorOrderNode *srciterator = sources->iterator();
280 while (srciterator->hasNext()) {
281 OrderNode *srcnode = srciterator->next();
282 OrderEdge *newedge = graph->getOrderEdgeFromOrderGraph(srcnode, node);
283 newedge->mustPos = true;
284 newedge->polPos = true;
285 if (newedge->mustNeg){
287 model_println("DFS clear 1");
291 srcnode->outEdges.add(newedge);
292 node->inEdges.add(newedge);
297 //Use source sets to compute mustPos edges
298 SetIteratorOrderEdge *iterator = node->inEdges.iterator();
299 while (iterator->hasNext()) {
300 OrderEdge *edge = iterator->next();
301 OrderNode *parent = edge->source;
302 if (!edge->mustPos && sources->contains(parent)) {
303 edge->mustPos = true;
307 model_println("DFS clear 2");
316 //Use source sets to compute mustNeg for edges that would introduce cycle if true
317 SetIteratorOrderEdge *iterator = node->outEdges.iterator();
318 while (iterator->hasNext()) {
319 OrderEdge *edge = iterator->next();
320 OrderNode *child = edge->sink;
321 if (!edge->mustNeg && sources->contains(child)) {
322 edge->mustNeg = true;
326 model_println("DFS clear 3: NodeFrom:%lu=>edge%lu=>NodeTo:%lu", node->id, (uintptr_t) edge, child->id);
336 table->resetanddelete();
340 /* This function finds edges that would form a cycle with must edges
341 and forces them to be mustNeg. It also decides whether an edge
342 must be true because of transitivity from other must be true
345 void reachMustAnalysis(CSolver *solver, OrderGraph *graph, bool computeTransitiveClosure) {
346 Vector<OrderNode *> finishNodes;
347 //Topologically sort the mustPos edge graph
348 DFSMust(graph, &finishNodes);
349 resetNodeInfoStatusSCC(graph);
351 //Find any backwards edges that complete cycles and force them to be mustNeg
352 DFSClearContradictions(solver, graph, &finishNodes, computeTransitiveClosure);
355 /* This function finds edges that must be positive and forces the
356 inverse edge to be negative (and clears its positive polarity if it
359 void localMustAnalysisTotal(CSolver *solver, OrderGraph *graph) {
360 SetIteratorOrderEdge *iterator = graph->getEdges();
361 while (iterator->hasNext()) {
362 OrderEdge *edge = iterator->next();
364 OrderEdge *invEdge = graph->getInverseOrderEdge(edge);
365 if (invEdge != NULL) {
366 if (!invEdge->mustPos) {
367 invEdge->polPos = false;
370 model_println("localMustAnalysis Total");
374 invEdge->mustNeg = true;
375 invEdge->polNeg = true;
382 /** This finds edges that must be positive and forces the inverse edge
383 to be negative. It also clears the negative flag of this edge.
384 It also finds edges that must be negative and clears the positive
387 void localMustAnalysisPartial(CSolver *solver, OrderGraph *graph) {
388 SetIteratorOrderEdge *iterator = graph->getEdges();
389 while (iterator->hasNext()) {
390 OrderEdge *edge = iterator->next();
392 if (!edge->mustNeg) {
393 edge->polNeg = false;
396 model_println("Local must analysis partial");
400 OrderEdge *invEdge = graph->getInverseOrderEdge(edge);
401 if (invEdge != NULL) {
402 if (!invEdge->mustPos)
403 invEdge->polPos = false;
406 model_println("Local must analysis partial 2");
410 invEdge->mustNeg = true;
411 invEdge->polNeg = true;
414 if (edge->mustNeg && !edge->mustPos) {
415 edge->polPos = false;