From 27435a92a5629d1e0a36351f27220679308ba488 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20Proch=C3=A1zka?= <david@prochazka.dev>
Date: Thu, 8 Apr 2021 14:28:07 +0200
Subject: [PATCH] FIX: removed DC, fixed node gathering, unified knn and
 approxknn, removed search state

---
 src/mhtree/ApproxState.java  | 32 +++-------------------
 src/mhtree/InternalNode.java |  2 +-
 src/mhtree/MHTree.java       | 51 ++++++++++++------------------------
 src/mhtree/SearchState.java  | 15 -----------
 4 files changed, 21 insertions(+), 79 deletions(-)
 delete mode 100644 src/mhtree/SearchState.java

diff --git a/src/mhtree/ApproxState.java b/src/mhtree/ApproxState.java
index 2e42c97..9872dc2 100644
--- a/src/mhtree/ApproxState.java
+++ b/src/mhtree/ApproxState.java
@@ -6,10 +6,6 @@ public class ApproxState {
     protected int limit;
     protected int objectsChecked;
     protected int bucketsVisited;
-    protected long computedDistances;
-
-    protected ApproxState() {
-    }
 
     protected ApproxState(int limit) {
         this.limit = limit;
@@ -23,21 +19,18 @@ public class ApproxState {
                 return new ApproxStateObjects(limits.getLocalSearchParam());
             case DATA_PARTITIONS:
                 return new ApproxStateBuckets(limits.getLocalSearchParam());
-            case ABS_DC_COUNT:
-                return new ApproxStateDistanceComputations(limits.getLocalSearchParam());
             default:
-                return new ApproxState();
+                throw new IllegalArgumentException("Unsupported approximation type: " + limits.getLocalSearchType());
         }
     }
 
-    public void update(LeafNode node, long distanceComputations) {
+    public void update(LeafNode node) {
         objectsChecked += node.getObjectCount();
         bucketsVisited++;
-        computedDistances = distanceComputations;
     }
 
     public boolean stop() {
-        return false;
+        throw new IllegalStateException("ApproxState.stop must be implemented and must not be called!");
     }
 
     private static class ApproxStateBuckets extends ApproxState {
@@ -61,23 +54,4 @@ public class ApproxState {
             return objectsChecked >= limit;
         }
     }
-
-    private static class ApproxStateDistanceComputations extends ApproxState {
-        protected ApproxStateDistanceComputations(int limit) {
-            super(limit);
-        }
-
-        @Override
-        public boolean stop() {
-            return computedDistances >= limit;
-        }
-    }
-
-    public long getComputedDistances() {
-        return computedDistances;
-    }
-
-    public void setComputedDistances(long computedDistances) {
-        this.computedDistances = computedDistances;
-    }
 }
diff --git a/src/mhtree/InternalNode.java b/src/mhtree/InternalNode.java
index 6850bfc..ac0897a 100644
--- a/src/mhtree/InternalNode.java
+++ b/src/mhtree/InternalNode.java
@@ -99,7 +99,7 @@ class InternalNode extends Node implements Serializable {
      */
     protected void gatherNodes(List<Node> nodes) {
         nodes.add(this);
-        nodes.addAll(children);
+        children.forEach(child -> child.gatherNodes(nodes));
     }
 
     /**
diff --git a/src/mhtree/MHTree.java b/src/mhtree/MHTree.java
index d02841a..080cdef 100644
--- a/src/mhtree/MHTree.java
+++ b/src/mhtree/MHTree.java
@@ -10,7 +10,6 @@ import messif.objects.LocalAbstractObject;
 import messif.operations.data.InsertOperation;
 import messif.operations.query.ApproxKNNQueryOperation;
 import messif.operations.query.KNNQueryOperation;
-import messif.statistics.Statistics;
 
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -59,34 +58,26 @@ public class MHTree extends Algorithm implements Serializable {
         root = builder.root;
     }
 
-    public void approxKNN(ApproxKNNQueryOperation operation) {
-        SearchState state = (SearchState) operation.suppData;
-
-        if (state.done) {
-            return;
-        }
+    public void kNN(KNNQueryOperation operation) {
+        kNNSearch(operation, null);
+    }
 
-        long distanceComputations = (long) Statistics.getStatistics("DistanceComputations").getValue();
+    public void approxKNN(ApproxKNNQueryOperation operation) {
+        kNNSearch(operation, ApproxState.create(operation, this));
+    }
 
+    public void kNNSearch(KNNQueryOperation operation, ApproxState approxState) {
         LocalAbstractObject queryObject = operation.getQueryObject();
 
-        long toThisIterationDistanceComputations = 0;
+        PriorityQueue<ObjectToNodeDistanceRank> queue = new PriorityQueue<>();
+        queue.add(new ObjectToNodeDistanceRank(queryObject, root));
 
-        if (state.queue == null || state.approxState == null) {
-            state.queue = new PriorityQueue<>();
-            state.queue.add(new ObjectToNodeDistanceRank(queryObject, root));
-            state.approxState = ApproxState.create(operation, this);
-        } else {
-            toThisIterationDistanceComputations = state.approxState.getComputedDistances() - 1000;
-            state.approxState.setComputedDistances(0);
-        }
-
-        while (!state.queue.isEmpty()) {
-            if (state.approxState.stop()) {
-                return;
+        while (!queue.isEmpty()) {
+            if (approxState != null && approxState.stop()) {
+                break;
             }
 
-            Node node = state.queue.remove().getNode();
+            Node node = queue.remove().getNode();
 
             if (node.isLeaf()) {
                 for (LocalAbstractObject object : node.getObjects()) {
@@ -95,24 +86,16 @@ public class MHTree extends Algorithm implements Serializable {
                     }
                 }
 
-                long changeInDistanceComputations = (long) Statistics.getStatistics("DistanceComputations").getValue() - distanceComputations;
-
-                state.approxState.update(
-                        (LeafNode) node,
-                        toThisIterationDistanceComputations + changeInDistanceComputations);
+                if (approxState != null) {
+                    approxState.update((LeafNode) node);
+                }
             } else {
                 for (Node child : ((InternalNode) node).getChildren()) {
-                    state.queue.add(new ObjectToNodeDistanceRank(queryObject, child));
+                    queue.add(new ObjectToNodeDistanceRank(queryObject, child));
                 }
             }
         }
 
-        state.done = true;
-        operation.endOperation();
-    }
-
-    public void kNN(KNNQueryOperation operation) {
-        root.getObjects().forEach(operation::addToAnswer);
         operation.endOperation();
     }
 
diff --git a/src/mhtree/SearchState.java b/src/mhtree/SearchState.java
deleted file mode 100644
index 1377cc9..0000000
--- a/src/mhtree/SearchState.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package mhtree;
-
-import java.util.PriorityQueue;
-
-public class SearchState {
-    public PriorityQueue<ObjectToNodeDistanceRank> queue;
-    public ApproxState approxState;
-    public boolean done;
-
-    public SearchState(PriorityQueue<ObjectToNodeDistanceRank> queue, ApproxState approxState, boolean done) {
-        this.queue = queue;
-        this.approxState = approxState;
-        this.done = done;
-    }
-}
-- 
GitLab