Skip to content

Commit f8dfddb

Browse files
Merge pull request #9662 from IoannisPanagiotas/pcst-code-1
Pcst code 1
2 parents 37afa78 + e291bb2 commit f8dfddb

19 files changed

+2254
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.pricesteiner;
21+
22+
import com.carrotsearch.hppc.BitSet;
23+
import org.neo4j.gds.collections.ha.HugeDoubleArray;
24+
25+
import java.util.function.LongPredicate;
26+
27+
class ClusterActivity {
28+
29+
private final BitSet activeClusters;
30+
private final HugeDoubleArray relevantTime;
31+
32+
private long numberOfActiveClusters;
33+
34+
ClusterActivity(long nodeCount) {
35+
this.activeClusters = new BitSet(2 * nodeCount);
36+
this.relevantTime = HugeDoubleArray.newArray(2 * nodeCount);
37+
38+
this.numberOfActiveClusters = nodeCount;
39+
40+
relevantTime.fill(0);
41+
activeClusters.set(0, nodeCount);
42+
}
43+
44+
void deactivateCluster(long clusterId, double moat) {
45+
activeClusters.clear(clusterId);
46+
relevantTime.set(clusterId, moat);
47+
this.numberOfActiveClusters--;
48+
}
49+
50+
void activateCluster(long clusterId, double moat) {
51+
activeClusters.set(clusterId);
52+
relevantTime.set(clusterId,moat);
53+
this.numberOfActiveClusters++;
54+
}
55+
56+
long numberOfActiveClusters() {
57+
return numberOfActiveClusters;
58+
}
59+
60+
double relevantTime(long clusterId) {
61+
return relevantTime.get(clusterId);
62+
}
63+
64+
65+
LongPredicate active() {
66+
return activeClusters::get;
67+
}
68+
69+
boolean active(long clusterId) {
70+
return activeClusters.get(clusterId);
71+
}
72+
73+
long firstActiveCluster() {
74+
return activeClusters.nextSetBit(0);
75+
}
76+
77+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.pricesteiner;
21+
22+
import org.neo4j.gds.core.utils.queue.HugeLongPriorityQueue;
23+
24+
import java.util.function.LongPredicate;
25+
26+
public class ClusterEventsPriorityQueue {
27+
28+
private final HugeLongPriorityQueue queue;
29+
30+
public ClusterEventsPriorityQueue(long nodeCount) {
31+
this.queue = HugeLongPriorityQueue.min(nodeCount*2);
32+
}
33+
34+
double closestEvent(LongPredicate allowed){
35+
var top=queue.top();
36+
while (!allowed.test(top)){
37+
queue.pop();
38+
top=queue.top();
39+
}
40+
return queue.cost(top);
41+
}
42+
43+
long topCluster(){
44+
return queue.top();
45+
}
46+
47+
void pop(){
48+
queue.pop();
49+
}
50+
51+
void add(long cluster, double sumOfPrizes){
52+
queue.add(cluster, sumOfPrizes);
53+
}
54+
55+
}
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
* Copyright (c) "Neo4j"
3+
* Neo4j Sweden AB [http://neo4j.com]
4+
*
5+
* This file is part of Neo4j.
6+
*
7+
* Neo4j is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
package org.neo4j.gds.pricesteiner;
21+
22+
import com.carrotsearch.hppc.BitSet;
23+
import org.neo4j.gds.collections.ha.HugeDoubleArray;
24+
import org.neo4j.gds.collections.ha.HugeLongArray;
25+
import org.neo4j.gds.core.utils.paged.HugeLongArrayStack;
26+
27+
import java.util.function.LongPredicate;
28+
29+
public class ClusterStructure {
30+
31+
private final HugeDoubleArray skippedParentSum;
32+
private final HugeLongArray parent;
33+
private final HugeDoubleArray clusterPrizes;
34+
private final HugeLongArray left;
35+
private final HugeLongArray right;
36+
private final HugeDoubleArray moat;
37+
private final HugeDoubleArray subTotalMoat;
38+
private final long originalNodeCount;
39+
private final ClusterActivity clusterActivity;
40+
private long maxNumberOfClusters;
41+
42+
ClusterStructure(long nodeCount){
43+
44+
this.parent = HugeLongArray.newArray(2*nodeCount);
45+
this.clusterPrizes = HugeDoubleArray.newArray(2*nodeCount);
46+
this.parent.fill(-1L);
47+
this.maxNumberOfClusters = nodeCount;
48+
this.subTotalMoat = HugeDoubleArray.newArray(nodeCount);
49+
this.skippedParentSum = HugeDoubleArray.newArray(2*nodeCount);
50+
this.moat = HugeDoubleArray.newArray(2*nodeCount);
51+
this.left = HugeLongArray.newArray(nodeCount);
52+
this.right = HugeLongArray.newArray(nodeCount);
53+
this.originalNodeCount = nodeCount;
54+
this.clusterActivity = new ClusterActivity(nodeCount);
55+
}
56+
57+
long merge(long cluster1,long cluster2,double moat){
58+
var newCluster = maxNumberOfClusters++;
59+
parent.set(cluster1,newCluster);
60+
parent.set(cluster2,newCluster);
61+
clusterPrizes.set(newCluster, clusterPrizes.get(cluster1)+ clusterPrizes.get(cluster2));
62+
var moat1 = moatAt(cluster1,moat);
63+
var moat2 = moatAt(cluster2,moat);
64+
65+
long newClusterAdaptedIndex = newCluster - originalNodeCount;
66+
67+
subTotalMoat.set(newClusterAdaptedIndex, subTotalMoat(cluster1)+ subTotalMoat(cluster2) + moat1+ moat2);
68+
deactivateCluster(cluster1,moat);
69+
deactivateCluster(cluster2,moat);
70+
71+
clusterActivity.activateCluster(newCluster,moat);
72+
left.set(newClusterAdaptedIndex, cluster1);
73+
right.set(newClusterAdaptedIndex, cluster2);
74+
return newCluster;
75+
}
76+
void deactivateCluster(long clusterId, double moat){
77+
if (clusterActivity.active(clusterId)) {
78+
this.moat.set(clusterId,moatAt(clusterId,moat));
79+
clusterActivity.deactivateCluster(clusterId, moat);
80+
}
81+
}
82+
83+
void setClusterPrize(long clusterId, double prize){
84+
clusterPrizes.set(clusterId, prize);
85+
}
86+
87+
double clusterPrize(long clusterId){
88+
return clusterPrizes.get(clusterId);
89+
}
90+
91+
double tightnessTime(long clusterId, double currentMoat){
92+
double slack = clusterPrizes.get(clusterId) - subTotalMoat(clusterId) - moatAt(clusterId,currentMoat);
93+
return currentMoat + slack;
94+
}
95+
96+
ClusterMoatPair sumOnEdgePart(long node, double currentMoat){
97+
double sum = 0;
98+
long currentNode =node;
99+
100+
while (true){
101+
102+
var parentNode = parent.get(currentNode);
103+
double currentValue = moatAt(currentNode,currentMoat);
104+
105+
sum+= currentValue;
106+
if (parentNode== -1){
107+
break;
108+
}else{
109+
var nextNextParent = parent.get(parentNode);
110+
double parentValue = moatAt(parentNode, currentMoat);
111+
var nextParent = parentNode;
112+
if (nextNextParent !=-1){
113+
parent.set(currentNode, nextNextParent);
114+
skippedParentSum.addTo(currentNode, parentValue + skippedParentSum.get(parentNode));
115+
nextParent= nextNextParent;
116+
}
117+
sum += skippedParentSum.get(currentNode);
118+
currentNode = nextParent;
119+
120+
121+
}
122+
123+
}
124+
125+
return new ClusterMoatPair(currentNode,sum);
126+
}
127+
128+
BitSet activeOriginalNodesOfCluster(long clusterId){
129+
BitSet bitSet=new BitSet(originalNodeCount);
130+
131+
if (clusterId < originalNodeCount){
132+
bitSet.set(clusterId);
133+
return bitSet;
134+
}
135+
136+
HugeLongArrayStack stack= HugeLongArrayStack.newStack(originalNodeCount);
137+
stack.push(clusterId);
138+
139+
while (!stack.isEmpty()){
140+
var stackCluster = stack.pop();
141+
var adaptedIndex = stackCluster - originalNodeCount;
142+
var leftChild = left.get(adaptedIndex);
143+
var rightChild = right.get(adaptedIndex);
144+
if (leftChild < originalNodeCount) {
145+
bitSet.set(leftChild);
146+
}else{
147+
stack.push(leftChild);
148+
}
149+
if (rightChild < originalNodeCount) {
150+
bitSet.set(rightChild);
151+
}else{
152+
stack.push(rightChild);
153+
}
154+
155+
}
156+
return bitSet;
157+
}
158+
159+
double moatAt(long clusterId, double moat){
160+
if (!clusterActivity.active(clusterId)) {
161+
return this.moat.get(clusterId);
162+
}
163+
return moat - clusterActivity.relevantTime(clusterId);
164+
}
165+
166+
long numberOfActiveClusters(){
167+
return clusterActivity.numberOfActiveClusters();
168+
}
169+
170+
LongPredicate active(){
171+
return clusterActivity.active();
172+
}
173+
174+
boolean active(long clusterId){
175+
return clusterActivity.active(clusterId);
176+
}
177+
178+
long singleActiveCluster(){
179+
return clusterActivity.firstActiveCluster();
180+
}
181+
182+
double inactiveSince(long clusterId){
183+
return clusterActivity.relevantTime(clusterId);
184+
}
185+
186+
private double subTotalMoat(long clusterId){
187+
if (clusterId < originalNodeCount) return 0;
188+
return subTotalMoat.get(clusterId - originalNodeCount);
189+
}
190+
191+
}
192+
record ClusterMoatPair(long cluster, double totalMoat){}
193+
194+
195+

0 commit comments

Comments
 (0)