in Java/core/src/main/java/com/amazon/randomcutforest/tree/RandomCutTree.java [177:280]
public Integer addPoint(Integer pointIndex, long sequenceIndex) {
if (root == Null) {
root = nodeStore.addLeaf(pointIndex, sequenceIndex);
return pointIndex;
} else {
float[] point = pointStoreView.get(pointIndex);
Stack<int[]> pathToRoot = nodeStore.getPath(root, point, false);
int[] first = pathToRoot.pop();
int leafNode = first[0];
int savedParent = (pathToRoot.size() == 0) ? Null : pathToRoot.lastElement()[0];
if (!nodeStore.isLeaf(leafNode)) {
// this corresponds to rebuilding a partial tree
if (savedParent == Null) {
root = pointIndex + numberOfLeaves; // note this capacity is nodestore.capacity + 1
} else {
nodeStore.addToPartialTree(pathToRoot, point, pointIndex);
nodeStore.manageAncestorsAdd(pathToRoot, point, pointStoreView);
nodeStore.addLeaf(pointIndex, sequenceIndex);
}
return pointIndex;
}
int leafSavedSibling = first[1];
int sibling = leafSavedSibling;
int leafPointIndex = nodeStore.getPointIndex(leafNode);
float[] oldPoint = pointStoreView.get(leafPointIndex);
Stack<int[]> parentPath = new Stack<>();
if (Arrays.equals(point, oldPoint)) {
nodeStore.increaseLeafMass(leafNode);
checkArgument(!nodeStore.freeNodeManager.isEmpty(), "incorrect/impossible state");
nodeStore.manageAncestorsAdd(pathToRoot, point, pointStoreView);
nodeStore.addLeaf(leafPointIndex, sequenceIndex);
return leafPointIndex;
} else {
int node = leafNode;
int savedNode = node;
int parent = savedParent;
float savedCutValue = (float) 0.0;
BoundingBox currentBox = new BoundingBox(oldPoint, oldPoint);
BoundingBox savedBox = currentBox.copy();
int savedDim = Integer.MAX_VALUE;
Random rng;
if (testRandom == null) {
rng = new Random(randomSeed);
randomSeed = rng.nextLong();
} else {
rng = testRandom;
}
while (true) {
double factor = rng.nextDouble();
Cut cut = randomCut(factor, point, currentBox);
int dim = cut.getDimension();
float value = (float) cut.getValue();
boolean separation = ((point[dim] <= value && value < currentBox.getMinValue(dim)
|| point[dim] > value && value >= currentBox.getMaxValue(dim)));
if (separation) {
savedCutValue = value;
savedDim = dim;
savedParent = parent;
savedNode = node;
savedBox = currentBox.copy();
parentPath.clear();
} else {
parentPath.push(new int[] { node, sibling });
}
if (savedDim == Integer.MAX_VALUE) {
randomCut(factor, point, currentBox);
throw new IllegalStateException(" cut failed ");
}
if (currentBox.contains(point) || parent == Null) {
break;
} else {
nodeStore.growNodeBox(currentBox, pointStoreView, parent, sibling);
int[] next = pathToRoot.pop();
node = next[0];
sibling = next[1];
if (pathToRoot.size() != 0) {
parent = pathToRoot.lastElement()[0];
} else {
parent = Null;
}
}
}
if (savedParent != Null) {
while (!parentPath.isEmpty()) {
pathToRoot.push(parentPath.pop());
}
assert (pathToRoot.lastElement()[0] == savedParent);
}
int mergedNode = nodeStore.addNode(pathToRoot, point, sequenceIndex, pointIndex, savedNode, savedDim,
savedCutValue, savedBox);
if (savedParent == Null) {
root = mergedNode;
}
}
return pointIndex;
}
}