Skip to content
Snippets Groups Projects
Verified Commit 45350d07 authored by David Procházka's avatar David Procházka
Browse files

DEL: unused classes

parent 7f002a6a
No related branches found
No related tags found
No related merge requests found
package mhtree;
import cz.muni.fi.disa.similarityoperators.cover.AbstractRepresentation.PrecomputedDistances;
import messif.buckets.BucketDispatcher;
import messif.buckets.BucketStorageException;
import messif.objects.LocalAbstractObject;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
class BuildTree {
private final int arity;
private final int leafCapacity;
private final InsertType insertType;
private final ObjectToNodeDistance objectToNodeDistance;
private final NodeToNodeDistance nodeToNodeDistance;
private final BucketDispatcher bucketDispatcher;
private final PrecomputedDistances objectDistances;
private final float[][] nodeDistances;
private final Node[] nodes;
private final BitSet validNodeIndices;
private final Node root;
BuildTree(List<LocalAbstractObject> objects, int leafCapacity, int arity, InsertType insertType, ObjectToNodeDistance objectToNodeDistance, NodeToNodeDistance nodeToNodeDistance, BucketDispatcher bucketDispatcher) throws BucketStorageException {
this.leafCapacity = leafCapacity;
this.arity = arity;
this.insertType = insertType;
this.objectToNodeDistance = objectToNodeDistance;
this.nodeToNodeDistance = nodeToNodeDistance;
this.bucketDispatcher = bucketDispatcher;
nodes = new Node[objects.size() / leafCapacity];
validNodeIndices = new BitSet(nodes.length);
validNodeIndices.set(0, nodes.length);
objectDistances = new PrecomputedDistances(objects);
nodeDistances = new float[nodes.length][nodes.length];
// Every object is stored in the root in the case of small number of objects
if (objectDistances.getObjectCount() <= leafCapacity) {
root = new LeafNode(objectDistances, bucketDispatcher.createBucket(), insertType, objectToNodeDistance);
return;
}
createLeafNodes();
root = createRoot();
}
public Node getRoot() {
return root;
}
private Node createRoot() {
while (validNodeIndices.cardinality() != 1) {
BitSet notProcessedNodeIndices = (BitSet) validNodeIndices.clone();
while (!notProcessedNodeIndices.isEmpty()) {
if (notProcessedNodeIndices.cardinality() <= arity) {
mergeNodes(notProcessedNodeIndices.stream().boxed().collect(Collectors.toList()));
break;
}
int furthestNodeIndex = getFurthestIndex(nodeDistances, notProcessedNodeIndices);
notProcessedNodeIndices.clear(furthestNodeIndex);
mergeNodes(furthestNodeIndex, findClosestItems(this::findClosestNodeIndex, furthestNodeIndex, arity - 1, notProcessedNodeIndices));
}
}
return nodes[validNodeIndices.nextSetBit(0)];
}
private void createLeafNodes() throws BucketStorageException {
BitSet notProcessedObjectIndices = new BitSet(objectDistances.getObjectCount());
notProcessedObjectIndices.set(0, objectDistances.getObjectCount());
for (int nodeIndex = 0; !notProcessedObjectIndices.isEmpty(); nodeIndex++) {
if (notProcessedObjectIndices.cardinality() < leafCapacity) {
for (int i = notProcessedObjectIndices.nextSetBit(0); i >= 0; i = notProcessedObjectIndices.nextSetBit(i + 1)) {
LocalAbstractObject object = objectDistances.getObject(i);
nodes[getClosestNodeIndex(object)].addObject(object);
}
return;
}
List<Integer> objectIndices = new ArrayList<>(leafCapacity);
// Select a base object
int furthestIndex = getFurthestIndex(objectDistances.getDistances(), notProcessedObjectIndices);
notProcessedObjectIndices.clear(furthestIndex);
objectIndices.add(furthestIndex);
// Select the rest of the objects up to the total of leafCapacity
objectIndices.addAll(findClosestItems(this::findClosestObjectIndex, furthestIndex, leafCapacity - 1, notProcessedObjectIndices));
List<LocalAbstractObject> objects = objectIndices.stream().map(objectDistances::getObject).collect(Collectors.toList());
nodes[nodeIndex] = new LeafNode(objectDistances.getSubset(objects), bucketDispatcher.createBucket(), insertType, objectToNodeDistance);
}
}
private int getClosestNodeIndex(LocalAbstractObject object) {
double minDistance = Double.MAX_VALUE;
int closestNodeIndex = -1;
for (int candidateIndex = 0; candidateIndex < nodes.length; candidateIndex++) {
double distance = nodes[candidateIndex].getDistance(object);
if (distance < minDistance) {
minDistance = distance;
closestNodeIndex = candidateIndex;
}
}
return closestNodeIndex;
}
private int getFurthestIndex(float[][] distanceMatrix, BitSet validIndices) {
float maxDistance = Float.MIN_VALUE;
int furthestIndex = validIndices.nextSetBit(0);
while (true) {
float[] distances = distanceMatrix[furthestIndex];
int candidateIndex = this.objectDistances.maxDistInArray(distances, validIndices);
if (!(distances[candidateIndex] > maxDistance)) {
return furthestIndex;
}
maxDistance = distances[candidateIndex];
furthestIndex = candidateIndex;
}
}
private List<Integer> findClosestItems(BiFunction<List<Integer>, BitSet, Integer> findClosestItemIndex, int itemIndex, int numberOfItems, BitSet notProcessedItemIndices) {
List<Integer> itemIndices = new ArrayList<>(1 + numberOfItems);
itemIndices.add(itemIndex);
List<Integer> resultItemsIndices = new ArrayList<>();
while (resultItemsIndices.size() != numberOfItems) {
int index = findClosestItemIndex.apply(itemIndices, notProcessedItemIndices);
itemIndices.add(index);
notProcessedItemIndices.clear(index);
resultItemsIndices.add(index);
}
return resultItemsIndices;
}
private int findClosestNodeIndex(List<Integer> indices, BitSet validNodeIndices) {
double minDistance = Double.MAX_VALUE;
int closestNodeIndex = -1;
for (int candidateIndex = validNodeIndices.nextSetBit(0); candidateIndex >= 0; candidateIndex = validNodeIndices.nextSetBit(candidateIndex + 1)) {
double sum = 0;
for (int index : indices)
sum += nodeDistances[index][candidateIndex];
if (sum < minDistance) {
minDistance = sum;
closestNodeIndex = candidateIndex;
}
}
return closestNodeIndex;
}
private int findClosestObjectIndex(List<Integer> indices, BitSet validObjectIndices) {
double minDistance = Double.MAX_VALUE;
int closestObjectIndex = -1;
for (int index : indices) {
int candidateIndex = objectDistances.minDistInArray(objectDistances.getDistances(index), validObjectIndices);
double distance = indices.stream().mapToDouble(i -> objectDistances.getDistance(i, candidateIndex)).sum();
if (distance < minDistance) {
minDistance = distance;
closestObjectIndex = candidateIndex;
}
}
return closestObjectIndex;
}
private void mergeNodes(List<Integer> nodeIndices) {
int parentNodeIndex = nodeIndices.remove(0);
mergeNodes(parentNodeIndex, nodeIndices);
}
private void mergeNodes(int parentNodeIndex, List<Integer> nodeIndices) {
if (nodeIndices.size() == 0) return;
nodeIndices.add(parentNodeIndex);
List<Node> nodes = nodeIndices.stream().map(i -> this.nodes[i]).collect(Collectors.toList());
InternalNode parent = Node.createParent(nodes, objectDistances, insertType, objectToNodeDistance);
nodes.forEach(node -> node.setParent(parent));
parent.addChildren(nodes);
nodeIndices.forEach(index -> {
validNodeIndices.clear(index);
this.nodes[index] = null;
});
this.nodes[parentNodeIndex] = parent;
validNodeIndices.set(parentNodeIndex);
// Update node distances
validNodeIndices.stream().forEach(index -> computeNodeDistances(parentNodeIndex, index));
}
private void computeNodeDistances(int i, int j) {
float distance = nodeToNodeDistance.getDistance(nodes[i], nodes[j], objectDistances::getDistance);
nodeDistances[i][j] = distance;
nodeDistances[j][i] = distance;
}
}
package mhtree;
import messif.objects.LocalAbstractObject;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class Histogram {
private final HashMap<Integer, HashMap<Long, Integer>> levelToHullsCoveredToObjectCount = new HashMap<>();
Histogram() {
}
public static Histogram generate(Node x) {
Histogram histogram = new Histogram();
for (int level = 1; level <= x.getHeight() + 1; level++) {
List<Node> levelNodes = x.getNodesOnLevel(level);
for (LocalAbstractObject object : x.getObjects()) {
long coveredObjectCount = levelNodes.stream()
.filter(node -> node.isCovered(object))
.count();
histogram.addCoveredCount(level, coveredObjectCount);
}
}
return histogram;
}
public void addCoveredCount(int level, long count) {
levelToHullsCoveredToObjectCount.merge(
level,
new HashMap<>(Collections.singletonMap(count, 1)),
(hullsCoveredToObjectCount, x) -> {
hullsCoveredToObjectCount.merge(count, 1, (objectCount, y) -> objectCount + 1);
return hullsCoveredToObjectCount;
});
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
levelToHullsCoveredToObjectCount.forEach((level, hullsCoveredToObjectCount) -> {
stringBuilder.append("Level ");
stringBuilder.append(level);
stringBuilder.append('\n');
hullsCoveredToObjectCount.forEach((hullsCovered, objectCount) -> {
stringBuilder.append(objectCount);
stringBuilder.append(" object");
if (objectCount != 1) stringBuilder.append('s');
if (hullsCovered == 0) {
stringBuilder.append(" not covered");
} else {
stringBuilder.append(" is covered by ");
stringBuilder.append(hullsCovered);
stringBuilder.append(" hull");
if (hullsCovered != 1) stringBuilder.append('s');
}
stringBuilder.append('\n');
});
});
return stringBuilder.toString();
}
}
package mhtree;
import messif.objects.LocalAbstractObject;
import java.util.function.BiFunction;
public enum NodeToNodeDistance {
NEAREST_HULL_OBJECTS(Math::min, Float.MAX_VALUE),
FURTHEST_HULL_OBJECTS(Math::max, Float.MIN_VALUE);
private final BiFunction<Float, Float, Float> compareFunction;
private final float defaultValue;
NodeToNodeDistance(final BiFunction<Float, Float, Float> compareFunction, final float defaultValue) {
this.compareFunction = compareFunction;
this.defaultValue = defaultValue;
}
public float getDistance(Node node1, Node node2, BiFunction<LocalAbstractObject, LocalAbstractObject, Float> getDistance) {
float distance = defaultValue;
for (LocalAbstractObject firstHullObject : node1.getHullObjects())
for (LocalAbstractObject secondHullObject : node2.getHullObjects())
distance = compareFunction.apply(distance, getDistance.apply(firstHullObject, secondHullObject));
return distance;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment