|
20 | 20 | package org.neo4j.gds.impl.spanningtree; |
21 | 21 |
|
22 | 22 | import com.carrotsearch.hppc.BitSet; |
23 | | -import org.apache.commons.lang3.mutable.MutableDouble; |
24 | | -import org.apache.commons.lang3.mutable.MutableLong; |
25 | 23 | import org.jetbrains.annotations.NotNull; |
26 | 24 | import org.neo4j.gds.Algorithm; |
27 | 25 | import org.neo4j.gds.api.Graph; |
@@ -78,7 +76,7 @@ public SpanningTree compute() { |
78 | 76 | prim.setTerminationFlag(getTerminationFlag()); |
79 | 77 | SpanningTree spanningTree = prim.compute(); |
80 | 78 |
|
81 | | - var outputTree = combineApproach(spanningTree); |
| 79 | + var outputTree = growApproach(spanningTree); |
82 | 80 | progressTracker.endSubTask(); |
83 | 81 | return outputTree; |
84 | 82 | } |
@@ -111,97 +109,15 @@ private double init(HugeLongArray parent, HugeDoubleArray costToParent, Spanning |
111 | 109 | return spanningTree.totalWeight(); |
112 | 110 | } |
113 | 111 |
|
114 | | - private SpanningTree cutLeafApproach(SpanningTree spanningTree) { |
115 | | - //this approach cuts a leaf at each step (remaining graph is always corrected) |
116 | | - //so we can just cut the most expensive leaf at each step |
117 | | - var priorityQueue = createPriorityQueue(graph.nodeCount(), true); |
118 | | - HugeLongArray degree = HugeLongArray.newArray(graph.nodeCount()); |
119 | | - long root = startNodeId; |
120 | | - double rootCost = -1.0; |
121 | | - long rootChild = -1; |
122 | | - |
123 | | - HugeLongArray parent = HugeLongArray.newArray(graph.nodeCount()); |
124 | | - HugeDoubleArray costToParent = HugeDoubleArray.newArray(graph.nodeCount()); |
125 | | - |
126 | | - double totalCost = init(parent, costToParent, spanningTree); |
127 | | - long numberOfDeletions = spanningTree.effectiveNodeCount() - k; |
128 | | - |
129 | | - progressTracker.beginSubTask(numberOfDeletions); |
130 | | - //calculate degree of each node in MST |
131 | | - for (long nodeId = 0; nodeId < graph.nodeCount(); ++nodeId) { |
132 | | - var nodeParent = parent.get(nodeId); |
133 | | - if (nodeParent != -1) { |
134 | | - degree.set(nodeParent, degree.get(nodeParent) + 1); |
135 | | - degree.set(nodeId, degree.get(nodeId) + 1); |
136 | | - |
137 | | - if (nodeParent == root) { //root nodes needs special care because parent is -1 |
138 | | - rootChild = nodeId; |
139 | | - rootCost = costToParent.get(nodeId); |
140 | | - } |
141 | | - } |
142 | | - } |
143 | | - //add all leafs in priority queue |
144 | | - for (long nodeId = 0; nodeId < graph.nodeCount(); ++nodeId) { |
145 | | - if (degree.get(nodeId) == 1) { |
146 | | - double relevantCost = (nodeId == root) ? |
147 | | - rootCost : |
148 | | - costToParent.get(nodeId); |
149 | | - priorityQueue.add(nodeId, relevantCost); |
150 | | - } |
151 | | - } |
152 | | - |
153 | | - for (long i = 0; i < numberOfDeletions; ++i) { |
154 | | - var nextNode = priorityQueue.pop(); |
155 | | - long affectedNode; |
156 | | - |
157 | | - if (nextNode == root) { //the affecte node is its single child |
158 | | - affectedNode = rootChild; |
159 | | - totalCost -= rootCost; |
160 | | - clearNode(rootChild, parent, costToParent); |
161 | | - clearNode(root, parent, costToParent); |
162 | | - root = affectedNode; |
163 | | - } else { //the affected node is its paret |
164 | | - affectedNode = parent.get(nextNode); |
165 | | - totalCost -= costToParent.get(nextNode); |
166 | | - clearNode(nextNode, parent, costToParent); |
167 | | - } |
168 | | - |
169 | | - degree.set(affectedNode, degree.get(affectedNode) - 1); |
170 | | - double associatedCost = -1; |
171 | | - if (degree.get(affectedNode) == 1) { //it becomes a leaf |
172 | | - if (affectedNode == root) { |
173 | | - //if it is root, we loop at its neighbors to find its single alive child |
174 | | - MutableDouble mutRootCost = new MutableDouble(); |
175 | | - MutableLong mutRootChild = new MutableLong(); |
176 | | - graph.forEachRelationship(root, (s, t) -> { |
177 | | - if (parent.get(t) == s) { |
178 | | - mutRootChild.setValue(t); |
179 | | - mutRootCost.setValue(costToParent.get(t)); |
180 | | - return false; |
181 | | - } |
182 | | - return true; |
183 | | - }); |
184 | | - rootChild = mutRootChild.longValue(); |
185 | | - rootCost = mutRootCost.doubleValue(); |
186 | | - associatedCost = rootCost; |
187 | | - } else { |
188 | | - //otherwise we just get the info from parent |
189 | | - associatedCost = costToParent.get(affectedNode); |
190 | | - } |
191 | | - priorityQueue.add(affectedNode, associatedCost); |
192 | | - } |
193 | | - progressTracker.logProgress(); |
194 | | - } |
195 | | - progressTracker.endSubTask(); |
196 | | - return new SpanningTree(root, graph.nodeCount(), k, parent, costToParent, totalCost); |
197 | | - } |
198 | 112 |
|
199 | 113 | private SpanningTree growApproach(SpanningTree spanningTree) { |
200 | 114 |
|
201 | 115 | //this approach grows gradually the MST found in the previous step |
202 | 116 | //when it is about to get larger than K, we crop the current worst leaf if the new value to be added |
203 | 117 | // is actually better |
204 | | - |
| 118 | + if (spanningTree.effectiveNodeCount() < k) |
| 119 | + return spanningTree; |
| 120 | + |
205 | 121 | HugeLongArray outDegree = HugeLongArray.newArray(graph.nodeCount()); |
206 | 122 |
|
207 | 123 | HugeLongArray parent = HugeLongArray.newArray(graph.nodeCount()); |
@@ -372,21 +288,6 @@ private boolean moveMakesSense(double cost1, double cost2, DoubleUnaryOperator m |
372 | 288 | } |
373 | 289 | } |
374 | 290 |
|
375 | | - private SpanningTree combineApproach(SpanningTree tree) { |
376 | | - if (tree.effectiveNodeCount() < k) { |
377 | | - return tree; |
378 | | - } |
379 | | - var spanningTree1 = cutLeafApproach(tree); |
380 | | - var spanningTree2 = growApproach(tree); |
381 | | - System.out.println("Prune Leaf: " + spanningTree1.totalWeight() + " Grow Mst:" + spanningTree2.totalWeight()); |
382 | | - if (spanningTree1.totalWeight() > spanningTree2.totalWeight()) { |
383 | | - return (minMax == Prim.MAX_OPERATOR) ? spanningTree1 : spanningTree2; |
384 | | - } else { |
385 | | - return (minMax == Prim.MAX_OPERATOR) ? spanningTree2 : spanningTree1; |
386 | | - |
387 | | - } |
388 | | - |
389 | | - } |
390 | 291 | } |
391 | 292 |
|
392 | 293 |
|
0 commit comments