From 99bf0b1b6f2812ada94bf7ad8ecf12bda033de94 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 13:45:31 -0700 Subject: [PATCH 01/13] Performance: some improvements to hit counting --- build.sbt | 9 +- .../jmhbenchmarks/HitCounterBenchmarks.scala | 2 +- .../elastiknn/search/ArrayHitCounter.java | 7 + .../elastiknn/search/EmptyHitCounter.java | 7 + .../elastiknn/search/HashMapHitCounter.java | 164 ++++++++++++++++++ .../klibisz/elastiknn/search/HitCounter.java | 4 + .../search/MatchHashesAndScoreQuery.java | 149 ++++++++-------- .../search/ArrayHitCounterSpec.scala | 3 + .../MatchHashesAndScoreQuerySuite.scala | 7 +- .../klibisz/elastiknn/models/ExactModel.java | 2 - 10 files changed, 273 insertions(+), 81 deletions(-) create mode 100644 elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java diff --git a/build.sbt b/build.sbt index 658908be3..f5108d6b4 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,5 @@ import ElasticsearchPluginPlugin.autoImport.* +import org.typelevel.sbt.tpolecat.{CiMode, DevMode} import org.typelevel.scalacoptions.* Global / scalaVersion := "3.3.3" @@ -9,7 +10,13 @@ lazy val CirceVersion = "0.14.9" lazy val ElasticsearchVersion = "8.15.0" lazy val Elastic4sVersion = "8.14.1" lazy val ElastiknnVersion = IO.read(file("version")).strip() -lazy val LuceneVersion = "9.10.0" +lazy val LuceneVersion = "9.11.1" + +// Setting this to simplify local development. +// https://github.com/typelevel/sbt-tpolecat/tree/v0.5.1?tab=readme-ov-file#modes +ThisBuild / tpolecatOptionsMode := { + if (sys.env.get("CI").contains("true")) CiMode else DevMode +} lazy val TestSettings = Seq( Test / parallelExecution := false, diff --git a/elastiknn-jmh-benchmarks/src/main/scala/com/klibisz/elastiknn/jmhbenchmarks/HitCounterBenchmarks.scala b/elastiknn-jmh-benchmarks/src/main/scala/com/klibisz/elastiknn/jmhbenchmarks/HitCounterBenchmarks.scala index 60e5b6eb2..eae02df29 100644 --- a/elastiknn-jmh-benchmarks/src/main/scala/com/klibisz/elastiknn/jmhbenchmarks/HitCounterBenchmarks.scala +++ b/elastiknn-jmh-benchmarks/src/main/scala/com/klibisz/elastiknn/jmhbenchmarks/HitCounterBenchmarks.scala @@ -1,7 +1,7 @@ package com.klibisz.elastiknn.jmhbenchmarks import org.openjdk.jmh.annotations._ -import org.apache.lucene.util.hppc.IntIntHashMap +import org.apache.lucene.internal.hppc.IntIntHashMap import org.eclipse.collections.impl.map.mutable.primitive.IntShortHashMap import scala.util.Random diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index f3355f7ee..866c963f3 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -1,5 +1,7 @@ package com.klibisz.elastiknn.search; +import org.apache.lucene.search.DocIdSetIterator; + /** * Use an array of counts to count hits. The index of the array is the doc id. * Hopefully there's a way to do this that doesn't require O(num docs in segment) time and memory, @@ -105,4 +107,9 @@ public KthGreatestResult kthGreatest(int k) { if (kthGreatest == 0) numGreater = numHits; return new KthGreatestResult(kthGreatest, numGreater, numHits); } + + @Override + public DocIdSetIterator docIdSetIterator(int k) { + return DocIdSetIterator.empty(); + } } diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java index efa3f081c..59ce98447 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java @@ -1,5 +1,7 @@ package com.klibisz.elastiknn.search; +import org.apache.lucene.search.DocIdSetIterator; + public final class EmptyHitCounter implements HitCounter { @Override @@ -42,4 +44,9 @@ public int maxKey() { public KthGreatestResult kthGreatest(int k) { return new KthGreatestResult((short) 0, 0, 0); } + + @Override + public DocIdSetIterator docIdSetIterator(int k) { + return DocIdSetIterator.empty(); + } } diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java new file mode 100644 index 000000000..a952b093d --- /dev/null +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java @@ -0,0 +1,164 @@ +package com.klibisz.elastiknn.search; + +import org.apache.lucene.search.DocIdSetIterator; +import org.apache.lucene.internal.hppc.IntIntHashMap; + + +public final class HashMapHitCounter implements HitCounter { + + private final IntIntHashMap docIdToCount; + private final int[] countToFrequency; + private final int[] countToMinDocId; + private final int[] countToMaxDocId; + private int minKey; + private int maxKey; + private int maxCount; + + + public HashMapHitCounter(int expectedDocIdCount, int maxExpectedCount) { + this.docIdToCount = new IntIntHashMap(expectedDocIdCount); + this.countToFrequency = new int[maxExpectedCount + 1]; + this.countToMinDocId = new int[maxExpectedCount + 1]; + this.countToMaxDocId = new int[maxExpectedCount + 1]; + this.minKey = Integer.MAX_VALUE; + this.maxKey = Integer.MIN_VALUE; + this.maxCount = 0; + } + + private void incrementKeyByCount(int key, int count) { + int newCount = docIdToCount.putOrAdd(key, count, count); + if (newCount > maxCount) maxCount = newCount; + + // Updates for the old count. + int oldCount = newCount - count; + if (oldCount > 0) { + countToFrequency[oldCount] -= 1; + if (key < countToMinDocId[oldCount] || countToMinDocId[oldCount] == 0) countToMinDocId[oldCount] = key; + else if (key > countToMaxDocId[oldCount]) countToMaxDocId[oldCount] = key; + } + + // Updates for the new count. + countToFrequency[newCount] += 1; + if (key < countToMinDocId[newCount] || countToMinDocId[newCount] == 0) countToMinDocId[newCount] = key; + else if (key > countToMinDocId[newCount]) countToMinDocId[newCount] = key; + } + + @Override + public void increment(int key) { + incrementKeyByCount(key, 1); + } + + @Override + public void increment(int key, short count) { + incrementKeyByCount(key, count); + } + + @Override + public boolean isEmpty() { + return docIdToCount.isEmpty(); + } + + @Override + public short get(int key) { + return (short) docIdToCount.get(key); + } + + @Override + public int numHits() { + return docIdToCount.size(); + } + + @Override + public int capacity() { + return docIdToCount.size(); + } + + @Override + public int minKey() { + return minKey; + } + + @Override + public int maxKey() { + return maxKey; + } + + @Override + public KthGreatestResult kthGreatest(int k) { + return null; + } + + @Override + public DocIdSetIterator docIdSetIterator(int candidates) { + if (isEmpty()) return DocIdSetIterator.empty(); + else { + // Look backwards through the countToFrequency array to figure out a few things needed for the iterator: + // 1. the minimum count that's required for a document to be a candidate + // 2. the minimum doc ID that we should start iterating at + // 3. and the maximum doc ID that we should iterate to + int minCount = maxCount; + int minDocId = Integer.MAX_VALUE; + int maxDocId = Integer.MIN_VALUE; + int accumulated = 0; + while (accumulated < candidates && minCount > 0) { + int count = countToFrequency[minCount]; + if (count > 0) { + accumulated += count; + if (countToMinDocId[minCount] < minDocId) minDocId = countToMinDocId[minCount]; + if (countToMaxDocId[minCount] > maxDocId) maxDocId = countToMaxDocId[minCount]; + } + minCount -= 1; + } + return new HashMapIntCounterDocIdSetIterator(minDocId, maxDocId, minCount, docIdToCount); + } + } + + private static final class HashMapIntCounterDocIdSetIterator extends DocIdSetIterator { + + private final int minDocId; + private final int maxDocId; + + private final int minCount; + + private final IntIntHashMap docIdToCount; + + private int currentDocId; + + public HashMapIntCounterDocIdSetIterator(int minDocId, int maxDocId, int minCount, IntIntHashMap docIdToCount) { + this.minDocId = minDocId; + this.maxDocId = maxDocId; + this.minCount = Math.max(1, minCount); + this.docIdToCount = docIdToCount; + this.currentDocId = minDocId - 1; + } + + @Override + public int docID() { + return currentDocId; + } + + @Override + public int nextDoc() { + while (true) { + currentDocId++; + if (docIdToCount.getOrDefault(currentDocId, 0) >= minCount) { + return currentDocId; + } else if (currentDocId > maxDocId) { + currentDocId = DocIdSetIterator.NO_MORE_DOCS; + return currentDocId; + } + } + } + + @Override + public int advance(int target) { + while (currentDocId < target) nextDoc(); + return currentDocId; + } + + @Override + public long cost() { + return maxDocId - minDocId; + } + } +} diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java index c2b3aa38b..f9cf102b4 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java @@ -1,5 +1,7 @@ package com.klibisz.elastiknn.search; +import org.apache.lucene.search.DocIdSetIterator; + /** * Abstraction for counting hits for a particular query. */ @@ -23,4 +25,6 @@ public interface HitCounter { KthGreatestResult kthGreatest(int k); + DocIdSetIterator docIdSetIterator(int k); + } diff --git a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java index 448a1df9e..342175273 100644 --- a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java +++ b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java @@ -1,10 +1,7 @@ package org.apache.lucene.search; import com.klibisz.elastiknn.models.HashAndFreq; -import com.klibisz.elastiknn.search.ArrayHitCounter; -import com.klibisz.elastiknn.search.EmptyHitCounter; -import com.klibisz.elastiknn.search.HitCounter; -import com.klibisz.elastiknn.search.KthGreatestResult; +import com.klibisz.elastiknn.search.*; import org.apache.lucene.index.*; import org.apache.lucene.util.BytesRef; @@ -48,6 +45,8 @@ public MatchHashesAndScoreQuery(final String field, this.scoreFunctionBuilder = scoreFunctionBuilder; } + private static int expectedNumberOfMatches = 1024; + @Override public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) { @@ -64,9 +63,7 @@ private HitCounter countHits(LeafReader reader) throws IOException { } else { TermsEnum termsEnum = terms.iterator(); PostingsEnum docs = null; - HitCounter counter = new ArrayHitCounter(reader.maxDoc()); - // TODO: Is this the right place to use the live docs bitset to check for deleted docs? - // Bits liveDocs = reader.getLiveDocs(); + HitCounter counter = new HashMapHitCounter(expectedNumberOfMatches, hashAndFrequencies.length); for (HashAndFreq hf : hashAndFrequencies) { // We take two different paths here, depending on the frequency of the current hash. // If the frequency is one, we avoid checking the frequency of matching docs when @@ -92,75 +89,75 @@ private HitCounter countHits(LeafReader reader) throws IOException { } } - private DocIdSetIterator buildDocIdSetIterator(HitCounter counter) { - // TODO: Add back this logging once log4j mess has settled. -// if (counter.numHits() < candidates) { -// logger.warn(String.format( -// "Found fewer approximate matches [%d] than the requested number of candidates [%d]", -// counter.numHits(), candidates)); +// private DocIdSetIterator buildDocIdSetIterator(HitCounter counter) { +// // TODO: Add back this logging once log4j mess has settled. +//// if (counter.numHits() < candidates) { +//// logger.warn(String.format( +//// "Found fewer approximate matches [%d] than the requested number of candidates [%d]", +//// counter.numHits(), candidates)); +//// } +// if (counter.isEmpty()) return DocIdSetIterator.empty(); +// else { +// +// KthGreatestResult kgr = counter.kthGreatest(candidates); +// +// // Return an iterator over the doc ids >= the min candidate count. +// return new DocIdSetIterator() { +// +// // Important that this starts at -1. Need a boolean to denote that it has started iterating. +// private int docID = -1; +// private boolean started = false; +// +// // Track the number of ids emitted, and the number of ids with count = kgr.kthGreatest emitted. +// private int numEmitted = 0; +// private int numEq = 0; +// +// @Override +// public int docID() { +// return docID; +// } +// +// @Override +// public int nextDoc() { +// +// if (!started) { +// started = true; +// docID = counter.minKey() - 1; +// } +// +// // Ensure that docs with count = kgr.kthGreatest are only emitted when there are fewer +// // than `candidates` docs with count > kgr.kthGreatest. +// while (true) { +// if (numEmitted == candidates || docID + 1 > counter.maxKey()) { +// docID = DocIdSetIterator.NO_MORE_DOCS; +// return docID(); +// } else { +// docID++; +// if (counter.get(docID) > kgr.kthGreatest) { +// numEmitted++; +// return docID(); +// } else if (counter.get(docID) == kgr.kthGreatest && numEq < candidates - kgr.numGreaterThan) { +// numEq++; +// numEmitted++; +// return docID(); +// } +// } +// } +// } +// +// @Override +// public int advance(int target) { +// while (docID < target) nextDoc(); +// return docID(); +// } +// +// @Override +// public long cost() { +// return counter.numHits(); +// } +// }; // } - if (counter.isEmpty()) return DocIdSetIterator.empty(); - else { - - KthGreatestResult kgr = counter.kthGreatest(candidates); - - // Return an iterator over the doc ids >= the min candidate count. - return new DocIdSetIterator() { - - // Important that this starts at -1. Need a boolean to denote that it has started iterating. - private int docID = -1; - private boolean started = false; - - // Track the number of ids emitted, and the number of ids with count = kgr.kthGreatest emitted. - private int numEmitted = 0; - private int numEq = 0; - - @Override - public int docID() { - return docID; - } - - @Override - public int nextDoc() { - - if (!started) { - started = true; - docID = counter.minKey() - 1; - } - - // Ensure that docs with count = kgr.kthGreatest are only emitted when there are fewer - // than `candidates` docs with count > kgr.kthGreatest. - while (true) { - if (numEmitted == candidates || docID + 1 > counter.maxKey()) { - docID = DocIdSetIterator.NO_MORE_DOCS; - return docID(); - } else { - docID++; - if (counter.get(docID) > kgr.kthGreatest) { - numEmitted++; - return docID(); - } else if (counter.get(docID) == kgr.kthGreatest && numEq < candidates - kgr.numGreaterThan) { - numEq++; - numEmitted++; - return docID(); - } - } - } - } - - @Override - public int advance(int target) { - while (docID < target) nextDoc(); - return docID(); - } - - @Override - public long cost() { - return counter.numHits(); - } - }; - } - } +// } @Override public Explanation explain(LeafReaderContext context, int doc) throws IOException { @@ -179,7 +176,7 @@ public Scorer scorer(LeafReaderContext context) throws IOException { ScoreFunction scoreFunction = scoreFunctionBuilder.apply(context); LeafReader reader = context.reader(); HitCounter counter = countHits(reader); - DocIdSetIterator disi = buildDocIdSetIterator(counter); + DocIdSetIterator disi = counter.docIdSetIterator(candidates); return new Scorer(this) { @Override diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 2cf32ff6d..112237961 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -1,5 +1,6 @@ package com.klibisz.elastiknn.search +import org.apache.lucene.search.DocIdSetIterator import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers @@ -34,6 +35,8 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { val numNonZero = values.count(_ != 0) new KthGreatestResult(values(k), numGreaterThan, numNonZero) } + + override def docIdSetIterator(k: Int): DocIdSetIterator = DocIdSetIterator.empty() } "reference examples" - { diff --git a/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala b/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala index 9a402e767..643513c2e 100644 --- a/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala +++ b/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala @@ -108,7 +108,12 @@ class MatchHashesAndScoreQuerySuite extends AnyFunSuite with Matchers with Lucen } } - test("returns no more than `candidates` doc IDs") { + ignore("returns no candidates with zero hash matches") { + // TODO! + succeed + } + + ignore("returns no more than `candidates` doc IDs") { val query = Array(6, 7).map(i => HashAndFreq.once(writeInt(i))) val candidates = 5 diff --git a/elastiknn-models/src/main/java/com/klibisz/elastiknn/models/ExactModel.java b/elastiknn-models/src/main/java/com/klibisz/elastiknn/models/ExactModel.java index fb23f7d2d..cfaead674 100644 --- a/elastiknn-models/src/main/java/com/klibisz/elastiknn/models/ExactModel.java +++ b/elastiknn-models/src/main/java/com/klibisz/elastiknn/models/ExactModel.java @@ -4,8 +4,6 @@ import com.klibisz.elastiknn.vectors.FloatVectorOps; import jdk.internal.vm.annotation.ForceInline; -import java.util.Arrays; - public class ExactModel { @ForceInline From f1a58fc24321311aa17fda5be540eef4fbf12ef1 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 14:05:20 -0700 Subject: [PATCH 02/13] WIP --- .../elastiknn/search/ArrayHitCounter.java | 175 +++++++++++------- .../elastiknn/search/EmptyHitCounter.java | 10 - .../elastiknn/search/HashMapHitCounter.java | 164 ---------------- .../klibisz/elastiknn/search/HitCounter.java | 4 - .../search/MatchHashesAndScoreQuery.java | 3 +- .../search/ArrayHitCounterSpec.scala | 7 +- 6 files changed, 109 insertions(+), 254 deletions(-) delete mode 100644 elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 866c963f3..6c41b61af 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -1,69 +1,71 @@ package com.klibisz.elastiknn.search; import org.apache.lucene.search.DocIdSetIterator; +import org.apache.lucene.internal.hppc.IntIntHashMap; -/** - * Use an array of counts to count hits. The index of the array is the doc id. - * Hopefully there's a way to do this that doesn't require O(num docs in segment) time and memory, - * but so far I haven't found anything on the JVM that's faster than simple arrays of primitives. - */ -public class ArrayHitCounter implements HitCounter { - private final short[] counts; - private int numHits; +public final class ArrayHitCounter implements HitCounter { + + private final short[] docIdToCount; + private final short[] countToFrequency; + private final int[] countToMinDocId; + private final int[] countToMaxDocId; private int minKey; private int maxKey; + private int maxCount; - private short maxValue; - public ArrayHitCounter(int capacity) { - counts = new short[capacity]; - numHits = 0; - minKey = capacity; - maxKey = 0; - maxValue = 0; + public ArrayHitCounter(int capacity, int maxExpectedCount) { + this.docIdToCount = new short[capacity]; + this.countToFrequency = new short[maxExpectedCount + 1]; + this.countToMinDocId = new int[maxExpectedCount + 1]; + this.countToMaxDocId = new int[maxExpectedCount + 1]; + this.minKey = Integer.MAX_VALUE; + this.maxKey = Integer.MIN_VALUE; + this.maxCount = 0; + } + + private void incrementKeyByCount(int key, short count) { + int newCount = (docIdToCount[key] += count); + if (newCount > maxCount) maxCount = newCount; + + // Updates for the old count. + int oldCount = newCount - count; + if (oldCount > 0) { + countToFrequency[oldCount] -= 1; + if (key < countToMinDocId[oldCount] || countToMinDocId[oldCount] == 0) countToMinDocId[oldCount] = key; + else if (key > countToMaxDocId[oldCount]) countToMaxDocId[oldCount] = key; + } + + // Updates for the new count. + countToFrequency[newCount] += 1; + if (key < countToMinDocId[newCount] || countToMinDocId[newCount] == 0) countToMinDocId[newCount] = key; + else if (key > countToMinDocId[newCount]) countToMinDocId[newCount] = key; } @Override public void increment(int key) { - short after = ++counts[key]; - if (after == 1) { - numHits++; - minKey = Math.min(key, minKey); - maxKey = Math.max(key, maxKey); - } - if (after > maxValue) maxValue = after; + incrementKeyByCount(key, (short) 1); } @Override public void increment(int key, short count) { - short after = (counts[key] += count); - if (after == count) { - numHits++; - minKey = Math.min(key, minKey); - maxKey = Math.max(key, maxKey); - } - if (after > maxValue) maxValue = after; + incrementKeyByCount(key, count); } @Override public boolean isEmpty() { - return numHits == 0; + return maxCount != 0; } @Override public short get(int key) { - return counts[key]; - } - - @Override - public int numHits() { - return numHits; + return docIdToCount[key]; } @Override public int capacity() { - return counts.length; + return docIdToCount.length; } @Override @@ -77,39 +79,76 @@ public int maxKey() { } @Override - public KthGreatestResult kthGreatest(int k) { - // Find the kth greatest document hit count in O(n) time and O(n) space. - // Though the space is typically negligibly small in practice. - // This implementation exploits the fact that we're specifically counting document hit counts. - // Counts are integers, and they're likely to be pretty small, since we're unlikely to match - // the same document many times. - - // Start by building a histogram of all counts. - // e.g., if the counts are [0, 4, 1, 1, 2], - // then the histogram is [1, 2, 1, 0, 1], - // because 0 occurs once, 1 occurs twice, 2 occurs once, 3 occurs zero times, and 4 occurs once. - short[] hist = new short[maxValue + 1]; - for (short c: counts) hist[c]++; - - // Now we start at the max value and iterate backwards through the histogram, - // accumulating counts of counts until we've exceeded k. - int numGreaterEqual = 0; - short kthGreatest = maxValue; - while (kthGreatest > 0) { - numGreaterEqual += hist[kthGreatest]; - if (numGreaterEqual > k) break; - else kthGreatest--; + public DocIdSetIterator docIdSetIterator(int candidates) { + if (isEmpty()) return DocIdSetIterator.empty(); + else { + // Look backwards through the countToFrequency array to figure out a few things needed for the iterator: + // 1. the minimum count that's required for a document to be a candidate + // 2. the minimum doc ID that we should start iterating at + // 3. and the maximum doc ID that we should iterate to + int minCount = maxCount; + int minDocId = Integer.MAX_VALUE; + int maxDocId = Integer.MIN_VALUE; + int accumulated = 0; + while (accumulated < candidates && minCount > 0) { + int count = countToFrequency[minCount]; + if (count > 0) { + accumulated += count; + if (countToMinDocId[minCount] < minDocId) minDocId = countToMinDocId[minCount]; + if (countToMaxDocId[minCount] > maxDocId) maxDocId = countToMaxDocId[minCount]; + } + minCount -= 1; + } + return new HashMapIntCounterDocIdSetIterator(minDocId, maxDocId, minCount, docIdToCount); } - - // Finally we find the number that were greater than the kth greatest count. - // There's a special case if kthGreatest is zero, then the number that were greater is the number of hits. - int numGreater = numGreaterEqual - hist[kthGreatest]; - if (kthGreatest == 0) numGreater = numHits; - return new KthGreatestResult(kthGreatest, numGreater, numHits); } - @Override - public DocIdSetIterator docIdSetIterator(int k) { - return DocIdSetIterator.empty(); + private static final class HashMapIntCounterDocIdSetIterator extends DocIdSetIterator { + + private final int minDocId; + private final int maxDocId; + + private final int minCount; + + private final short[] docIdToCount; + + private int currentDocId; + + public HashMapIntCounterDocIdSetIterator(int minDocId, int maxDocId, int minCount, short[] docIdToCount) { + this.minDocId = minDocId; + this.maxDocId = maxDocId; + this.minCount = Math.max(1, minCount); + this.docIdToCount = docIdToCount; + this.currentDocId = minDocId - 1; + } + + @Override + public int docID() { + return currentDocId; + } + + @Override + public int nextDoc() { + while (true) { + currentDocId++; + if (docIdToCount[currentDocId] >= minCount) { + return currentDocId; + } else if (currentDocId > maxDocId) { + currentDocId = DocIdSetIterator.NO_MORE_DOCS; + return currentDocId; + } + } + } + + @Override + public int advance(int target) { + while (currentDocId < target) nextDoc(); + return currentDocId; + } + + @Override + public long cost() { + return maxDocId - minDocId; + } } } diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java index 59ce98447..5dd86b647 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java @@ -20,11 +20,6 @@ public short get(int key) { return 0; } - @Override - public int numHits() { - return 0; - } - @Override public int capacity() { return 0; @@ -40,11 +35,6 @@ public int maxKey() { return 0; } - @Override - public KthGreatestResult kthGreatest(int k) { - return new KthGreatestResult((short) 0, 0, 0); - } - @Override public DocIdSetIterator docIdSetIterator(int k) { return DocIdSetIterator.empty(); diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java deleted file mode 100644 index a952b093d..000000000 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HashMapHitCounter.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.klibisz.elastiknn.search; - -import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.internal.hppc.IntIntHashMap; - - -public final class HashMapHitCounter implements HitCounter { - - private final IntIntHashMap docIdToCount; - private final int[] countToFrequency; - private final int[] countToMinDocId; - private final int[] countToMaxDocId; - private int minKey; - private int maxKey; - private int maxCount; - - - public HashMapHitCounter(int expectedDocIdCount, int maxExpectedCount) { - this.docIdToCount = new IntIntHashMap(expectedDocIdCount); - this.countToFrequency = new int[maxExpectedCount + 1]; - this.countToMinDocId = new int[maxExpectedCount + 1]; - this.countToMaxDocId = new int[maxExpectedCount + 1]; - this.minKey = Integer.MAX_VALUE; - this.maxKey = Integer.MIN_VALUE; - this.maxCount = 0; - } - - private void incrementKeyByCount(int key, int count) { - int newCount = docIdToCount.putOrAdd(key, count, count); - if (newCount > maxCount) maxCount = newCount; - - // Updates for the old count. - int oldCount = newCount - count; - if (oldCount > 0) { - countToFrequency[oldCount] -= 1; - if (key < countToMinDocId[oldCount] || countToMinDocId[oldCount] == 0) countToMinDocId[oldCount] = key; - else if (key > countToMaxDocId[oldCount]) countToMaxDocId[oldCount] = key; - } - - // Updates for the new count. - countToFrequency[newCount] += 1; - if (key < countToMinDocId[newCount] || countToMinDocId[newCount] == 0) countToMinDocId[newCount] = key; - else if (key > countToMinDocId[newCount]) countToMinDocId[newCount] = key; - } - - @Override - public void increment(int key) { - incrementKeyByCount(key, 1); - } - - @Override - public void increment(int key, short count) { - incrementKeyByCount(key, count); - } - - @Override - public boolean isEmpty() { - return docIdToCount.isEmpty(); - } - - @Override - public short get(int key) { - return (short) docIdToCount.get(key); - } - - @Override - public int numHits() { - return docIdToCount.size(); - } - - @Override - public int capacity() { - return docIdToCount.size(); - } - - @Override - public int minKey() { - return minKey; - } - - @Override - public int maxKey() { - return maxKey; - } - - @Override - public KthGreatestResult kthGreatest(int k) { - return null; - } - - @Override - public DocIdSetIterator docIdSetIterator(int candidates) { - if (isEmpty()) return DocIdSetIterator.empty(); - else { - // Look backwards through the countToFrequency array to figure out a few things needed for the iterator: - // 1. the minimum count that's required for a document to be a candidate - // 2. the minimum doc ID that we should start iterating at - // 3. and the maximum doc ID that we should iterate to - int minCount = maxCount; - int minDocId = Integer.MAX_VALUE; - int maxDocId = Integer.MIN_VALUE; - int accumulated = 0; - while (accumulated < candidates && minCount > 0) { - int count = countToFrequency[minCount]; - if (count > 0) { - accumulated += count; - if (countToMinDocId[minCount] < minDocId) minDocId = countToMinDocId[minCount]; - if (countToMaxDocId[minCount] > maxDocId) maxDocId = countToMaxDocId[minCount]; - } - minCount -= 1; - } - return new HashMapIntCounterDocIdSetIterator(minDocId, maxDocId, minCount, docIdToCount); - } - } - - private static final class HashMapIntCounterDocIdSetIterator extends DocIdSetIterator { - - private final int minDocId; - private final int maxDocId; - - private final int minCount; - - private final IntIntHashMap docIdToCount; - - private int currentDocId; - - public HashMapIntCounterDocIdSetIterator(int minDocId, int maxDocId, int minCount, IntIntHashMap docIdToCount) { - this.minDocId = minDocId; - this.maxDocId = maxDocId; - this.minCount = Math.max(1, minCount); - this.docIdToCount = docIdToCount; - this.currentDocId = minDocId - 1; - } - - @Override - public int docID() { - return currentDocId; - } - - @Override - public int nextDoc() { - while (true) { - currentDocId++; - if (docIdToCount.getOrDefault(currentDocId, 0) >= minCount) { - return currentDocId; - } else if (currentDocId > maxDocId) { - currentDocId = DocIdSetIterator.NO_MORE_DOCS; - return currentDocId; - } - } - } - - @Override - public int advance(int target) { - while (currentDocId < target) nextDoc(); - return currentDocId; - } - - @Override - public long cost() { - return maxDocId - minDocId; - } - } -} diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java index f9cf102b4..1c73ca8b6 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java @@ -15,16 +15,12 @@ public interface HitCounter { short get(int key); - int numHits(); - int capacity(); int minKey(); int maxKey(); - KthGreatestResult kthGreatest(int k); - DocIdSetIterator docIdSetIterator(int k); } diff --git a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java index 342175273..872c4859f 100644 --- a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java +++ b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java @@ -8,7 +8,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.Objects; -import java.util.Set; import java.util.function.Function; import static java.lang.Math.min; @@ -63,7 +62,7 @@ private HitCounter countHits(LeafReader reader) throws IOException { } else { TermsEnum termsEnum = terms.iterator(); PostingsEnum docs = null; - HitCounter counter = new HashMapHitCounter(expectedNumberOfMatches, hashAndFrequencies.length); + HitCounter counter = new ArrayHitCounter(expectedNumberOfMatches, hashAndFrequencies.length); for (HashAndFreq hf : hashAndFrequencies) { // We take two different paths here, depending on the frequency of the current hash. // If the frequency is one, we avoid checking the frequency of matching docs when diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 112237961..58946f06b 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -21,8 +21,6 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { override def get(key: Int): Short = counts(key) - override def numHits(): Int = counts.values.count(_ > 0) - override def capacity(): Int = this.referenceCapacity override def minKey(): Int = counts.filter(_._2 > 0).keys.min @@ -48,14 +46,12 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { c.get(0) shouldBe 0 c.increment(0) c.get(0) shouldBe 1 - c.numHits() shouldBe 1 c.minKey() shouldBe 0 c.maxKey() shouldBe 0 c.get(5) shouldBe 0 c.increment(5, 5) c.get(5) shouldBe 5 - c.numHits() shouldBe 2 c.minKey() shouldBe 0 c.maxKey() shouldBe 5 @@ -64,7 +60,6 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { c.get(9) shouldBe 1 c.increment(9) c.get(9) shouldBe 2 - c.numHits() shouldBe 3 c.minKey() shouldBe 0 c.maxKey() shouldBe 9 @@ -84,7 +79,7 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { for (_ <- 0 until 99) { val matches = (0 until numMatches).map(_ => rng.nextInt(numDocs)) val ref = new Reference(numDocs) - val ahc = new ArrayHitCounter(numDocs) + val ahc = new ArrayHitCounter(numDocs, ???) matches.foreach { doc => ref.increment(doc) ahc.increment(doc) From 684f8af29183e8273799793f1d11cd15b6e6fa64 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 14:07:53 -0700 Subject: [PATCH 03/13] WIP --- .../search/ArrayHitCounterSpec.scala | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 58946f06b..619a2d9a0 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -27,13 +27,6 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { override def maxKey(): Int = counts.filter(_._2 > 0).keys.max - override def kthGreatest(k: Int): KthGreatestResult = { - val values = counts.values.toArray.sorted.reverse - val numGreaterThan = values.count(_ > values(k)) - val numNonZero = values.count(_ != 0) - new KthGreatestResult(values(k), numGreaterThan, numNonZero) - } - override def docIdSetIterator(k: Int): DocIdSetIterator = DocIdSetIterator.empty() } @@ -63,10 +56,10 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { c.minKey() shouldBe 0 c.maxKey() shouldBe 9 - val kgr = c.kthGreatest(2) - kgr.kthGreatest shouldBe 1 - kgr.numGreaterThan shouldBe 2 - kgr.numNonZero shouldBe 3 +// val kgr = c.kthGreatest(2) +// kgr.kthGreatest shouldBe 1 +// kgr.numGreaterThan shouldBe 2 +// kgr.numNonZero shouldBe 3 } } @@ -79,7 +72,7 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { for (_ <- 0 until 99) { val matches = (0 until numMatches).map(_ => rng.nextInt(numDocs)) val ref = new Reference(numDocs) - val ahc = new ArrayHitCounter(numDocs, ???) + val ahc = new ArrayHitCounter(numDocs, matches.length) matches.foreach { doc => ref.increment(doc) ahc.increment(doc) @@ -91,11 +84,10 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { } ahc.minKey() shouldBe ref.minKey() ahc.maxKey() shouldBe ref.maxKey() - ahc.numHits() shouldBe ref.numHits() - val k = rng.nextInt(numDocs) - val ahcKgr = ahc.kthGreatest(k) - val refKgr = ref.kthGreatest(k) - ahcKgr shouldBe refKgr +// val k = rng.nextInt(numDocs) +// val ahcKgr = ahc.kthGreatest(k) +// val refKgr = ref.kthGreatest(k) +// ahcKgr shouldBe refKgr } } } From e7ac3a676e70189285a24284490917303facb465 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 16:08:50 -0700 Subject: [PATCH 04/13] Unit tests pass but integration tests still failing --- .../elastiknn/search/ArrayHitCounter.java | 80 ++++++++++--------- .../elastiknn/search/EmptyHitCounter.java | 15 ---- .../klibisz/elastiknn/search/HitCounter.java | 5 -- .../search/MatchHashesAndScoreQuery.java | 4 +- .../search/ArrayHitCounterSpec.scala | 17 +--- .../MatchHashesAndScoreQuerySuite.scala | 2 +- .../com/klibisz/elastiknn/RecallSuite.scala | 2 +- 7 files changed, 46 insertions(+), 79 deletions(-) diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 6c41b61af..6faf878b8 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -1,7 +1,8 @@ package com.klibisz.elastiknn.search; import org.apache.lucene.search.DocIdSetIterator; -import org.apache.lucene.internal.hppc.IntIntHashMap; + +import java.util.Arrays; public final class ArrayHitCounter implements HitCounter { @@ -10,8 +11,6 @@ public final class ArrayHitCounter implements HitCounter { private final short[] countToFrequency; private final int[] countToMinDocId; private final int[] countToMaxDocId; - private int minKey; - private int maxKey; private int maxCount; @@ -19,28 +18,27 @@ public ArrayHitCounter(int capacity, int maxExpectedCount) { this.docIdToCount = new short[capacity]; this.countToFrequency = new short[maxExpectedCount + 1]; this.countToMinDocId = new int[maxExpectedCount + 1]; + Arrays.fill(countToMinDocId, Integer.MAX_VALUE); this.countToMaxDocId = new int[maxExpectedCount + 1]; - this.minKey = Integer.MAX_VALUE; - this.maxKey = Integer.MIN_VALUE; this.maxCount = 0; } - private void incrementKeyByCount(int key, short count) { - int newCount = (docIdToCount[key] += count); + private void incrementKeyByCount(int docId, short count) { + int newCount = (docIdToCount[docId] += count); if (newCount > maxCount) maxCount = newCount; // Updates for the old count. int oldCount = newCount - count; if (oldCount > 0) { countToFrequency[oldCount] -= 1; - if (key < countToMinDocId[oldCount] || countToMinDocId[oldCount] == 0) countToMinDocId[oldCount] = key; - else if (key > countToMaxDocId[oldCount]) countToMaxDocId[oldCount] = key; + if (docId < countToMinDocId[oldCount]) countToMinDocId[oldCount] = docId; + if (docId > countToMaxDocId[oldCount]) countToMaxDocId[oldCount] = docId; } // Updates for the new count. countToFrequency[newCount] += 1; - if (key < countToMinDocId[newCount] || countToMinDocId[newCount] == 0) countToMinDocId[newCount] = key; - else if (key > countToMinDocId[newCount]) countToMinDocId[newCount] = key; + if (docId < countToMinDocId[newCount]) countToMinDocId[newCount] = docId; + if (docId > countToMaxDocId[newCount]) countToMaxDocId[newCount] = docId; } @Override @@ -53,10 +51,6 @@ public void increment(int key, short count) { incrementKeyByCount(key, count); } - @Override - public boolean isEmpty() { - return maxCount != 0; - } @Override public short get(int key) { @@ -68,21 +62,12 @@ public int capacity() { return docIdToCount.length; } - @Override - public int minKey() { - return minKey; - } - - @Override - public int maxKey() { - return maxKey; - } @Override public DocIdSetIterator docIdSetIterator(int candidates) { - if (isEmpty()) return DocIdSetIterator.empty(); + if (maxCount == 0) return DocIdSetIterator.empty(); else { - // Look backwards through the countToFrequency array to figure out a few things needed for the iterator: + // Loop backwards through the countToFrequency array to figure out a few things needed for the iterator: // 1. the minimum count that's required for a document to be a candidate // 2. the minimum doc ID that we should start iterating at // 3. and the maximum doc ID that we should iterate to @@ -94,32 +79,41 @@ public DocIdSetIterator docIdSetIterator(int candidates) { int count = countToFrequency[minCount]; if (count > 0) { accumulated += count; - if (countToMinDocId[minCount] < minDocId) minDocId = countToMinDocId[minCount]; - if (countToMaxDocId[minCount] > maxDocId) maxDocId = countToMaxDocId[minCount]; + int maybeNewMinDocId = countToMinDocId[minCount]; + if (maybeNewMinDocId < minDocId) minDocId = maybeNewMinDocId; + int maybeNewMaxDocId = countToMaxDocId[minCount]; + if (maybeNewMaxDocId > maxDocId) maxDocId = maybeNewMaxDocId; } minCount -= 1; } - return new HashMapIntCounterDocIdSetIterator(minDocId, maxDocId, minCount, docIdToCount); +// minCount = Math.max(1, minCount); + int numGreaterThanMinCount = accumulated - countToFrequency[minCount]; + return new _DocIdSetIterator(candidates, minDocId, maxDocId, minCount, numGreaterThanMinCount, docIdToCount); } } - private static final class HashMapIntCounterDocIdSetIterator extends DocIdSetIterator { + private static final class _DocIdSetIterator extends DocIdSetIterator { + private final int candidates; private final int minDocId; private final int maxDocId; - private final int minCount; - + private final int numGreaterThanMinCount; private final short[] docIdToCount; - private int currentDocId; + private int numEmitted; + private int numEmittedEqualToMinCount; - public HashMapIntCounterDocIdSetIterator(int minDocId, int maxDocId, int minCount, short[] docIdToCount) { + public _DocIdSetIterator(int candidates, int minDocId, int maxDocId, int minCount, int numGreaterThanMinCount, short[] docIdToCount) { + this.candidates = candidates; this.minDocId = minDocId; this.maxDocId = maxDocId; - this.minCount = Math.max(1, minCount); + this.minCount = minCount; + this.numGreaterThanMinCount = numGreaterThanMinCount; this.docIdToCount = docIdToCount; this.currentDocId = minDocId - 1; + this.numEmitted = 0; + this.numEmittedEqualToMinCount = 0; } @Override @@ -130,12 +124,20 @@ public int docID() { @Override public int nextDoc() { while (true) { - currentDocId++; - if (docIdToCount[currentDocId] >= minCount) { - return currentDocId; - } else if (currentDocId > maxDocId) { + if (numEmitted == candidates || currentDocId + 1 > maxDocId) { currentDocId = DocIdSetIterator.NO_MORE_DOCS; return currentDocId; + } else { + currentDocId++; + int count = docIdToCount[currentDocId]; + if (count > minCount) { + numEmitted++; + return currentDocId; + } else if (count == minCount && numEmittedEqualToMinCount < candidates - numGreaterThanMinCount) { + numEmitted++; + numEmittedEqualToMinCount++; + return currentDocId; + } } } } diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java index 5dd86b647..2786b89b4 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/EmptyHitCounter.java @@ -10,11 +10,6 @@ public void increment(int key) {} @Override public void increment(int key, short count) {} - @Override - public boolean isEmpty() { - return true; - } - @Override public short get(int key) { return 0; @@ -25,16 +20,6 @@ public int capacity() { return 0; } - @Override - public int minKey() { - return 0; - } - - @Override - public int maxKey() { - return 0; - } - @Override public DocIdSetIterator docIdSetIterator(int k) { return DocIdSetIterator.empty(); diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java index 1c73ca8b6..75f2eb1ce 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/HitCounter.java @@ -11,16 +11,11 @@ public interface HitCounter { void increment(int key, short count); - boolean isEmpty(); short get(int key); int capacity(); - int minKey(); - - int maxKey(); - DocIdSetIterator docIdSetIterator(int k); } diff --git a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java index 872c4859f..b2bf8dbb6 100644 --- a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java +++ b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java @@ -44,8 +44,6 @@ public MatchHashesAndScoreQuery(final String field, this.scoreFunctionBuilder = scoreFunctionBuilder; } - private static int expectedNumberOfMatches = 1024; - @Override public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) { @@ -62,7 +60,7 @@ private HitCounter countHits(LeafReader reader) throws IOException { } else { TermsEnum termsEnum = terms.iterator(); PostingsEnum docs = null; - HitCounter counter = new ArrayHitCounter(expectedNumberOfMatches, hashAndFrequencies.length); + HitCounter counter = new ArrayHitCounter(reader.maxDoc(), hashAndFrequencies.length); for (HashAndFreq hf : hashAndFrequencies) { // We take two different paths here, depending on the frequency of the current hash. // If the frequency is one, we avoid checking the frequency of matching docs when diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 619a2d9a0..d26fed401 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -17,44 +17,31 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { override def increment(key: Int, count: Short): Unit = counts.update(key, (counts(key) + count).toShort) - override def isEmpty: Boolean = !counts.values.exists(_ > 0) - override def get(key: Int): Short = counts(key) override def capacity(): Int = this.referenceCapacity - override def minKey(): Int = counts.filter(_._2 > 0).keys.min - - override def maxKey(): Int = counts.filter(_._2 > 0).keys.max - override def docIdSetIterator(k: Int): DocIdSetIterator = DocIdSetIterator.empty() } "reference examples" - { "example 1" in { val c = new Reference(10) - c.isEmpty shouldBe true c.capacity() shouldBe 10 c.get(0) shouldBe 0 c.increment(0) c.get(0) shouldBe 1 - c.minKey() shouldBe 0 - c.maxKey() shouldBe 0 c.get(5) shouldBe 0 c.increment(5, 5) c.get(5) shouldBe 5 - c.minKey() shouldBe 0 - c.maxKey() shouldBe 5 c.get(9) shouldBe 0 c.increment(9) c.get(9) shouldBe 1 c.increment(9) c.get(9) shouldBe 2 - c.minKey() shouldBe 0 - c.maxKey() shouldBe 9 // val kgr = c.kthGreatest(2) // kgr.kthGreatest shouldBe 1 @@ -82,8 +69,8 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { ahc.increment(doc, count) ahc.get(doc) shouldBe ref.get(doc) } - ahc.minKey() shouldBe ref.minKey() - ahc.maxKey() shouldBe ref.maxKey() +// ahc.minKey() shouldBe ref.minKey() +// ahc.maxKey() shouldBe ref.maxKey() // val k = rng.nextInt(numDocs) // val ahcKgr = ahc.kthGreatest(k) // val refKgr = ref.kthGreatest(k) diff --git a/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala b/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala index 643513c2e..ca268ec7c 100644 --- a/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala +++ b/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala @@ -113,7 +113,7 @@ class MatchHashesAndScoreQuerySuite extends AnyFunSuite with Matchers with Lucen succeed } - ignore("returns no more than `candidates` doc IDs") { + test("returns no more than `candidates` doc IDs") { val query = Array(6, 7).map(i => HashAndFreq.once(writeInt(i))) val candidates = 5 diff --git a/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala b/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala index 123905234..c60bda022 100644 --- a/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala +++ b/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala @@ -22,7 +22,7 @@ import scala.util.hashing.MurmurHash3.orderedHash * have seen different results at times. This seems to be an effect at the Elasticsearch level. I've tested at the Lucene (sans ES) * level and that seems to be reliably deterministic. */ -class RecallSuite extends AsyncFunSuite with Matchers with ElasticAsyncClient with AsyncCancelAfterFailure { +class RecallSuite extends AsyncFunSuite with Matchers with ElasticAsyncClient { // Each test case consists of setting up one Mapping and then running several queries against that mapping. // Each query has an expected recall that will be checked. From c30fe3626045d32cb55dbf42fe051c23ee7da9a7 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 16:44:57 -0700 Subject: [PATCH 05/13] Better but still some tests failing --- .../elastiknn/search/ArrayHitCounter.java | 43 ++++++------------- .../search/MatchHashesAndScoreQuery.java | 7 ++- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 6faf878b8..6b78977f7 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -2,43 +2,30 @@ import org.apache.lucene.search.DocIdSetIterator; -import java.util.Arrays; - public final class ArrayHitCounter implements HitCounter { private final short[] docIdToCount; private final short[] countToFrequency; - private final int[] countToMinDocId; - private final int[] countToMaxDocId; + private int minDocId = Integer.MAX_VALUE; + private int maxDocId = Integer.MIN_VALUE; private int maxCount; - public ArrayHitCounter(int capacity, int maxExpectedCount) { + public ArrayHitCounter(int capacity, int maxPossibleCount) { this.docIdToCount = new short[capacity]; - this.countToFrequency = new short[maxExpectedCount + 1]; - this.countToMinDocId = new int[maxExpectedCount + 1]; - Arrays.fill(countToMinDocId, Integer.MAX_VALUE); - this.countToMaxDocId = new int[maxExpectedCount + 1]; + this.countToFrequency = new short[maxPossibleCount + 1]; this.maxCount = 0; } private void incrementKeyByCount(int docId, short count) { int newCount = (docIdToCount[docId] += count); if (newCount > maxCount) maxCount = newCount; - - // Updates for the old count. - int oldCount = newCount - count; - if (oldCount > 0) { - countToFrequency[oldCount] -= 1; - if (docId < countToMinDocId[oldCount]) countToMinDocId[oldCount] = docId; - if (docId > countToMaxDocId[oldCount]) countToMaxDocId[oldCount] = docId; - } - - // Updates for the new count. countToFrequency[newCount] += 1; - if (docId < countToMinDocId[newCount]) countToMinDocId[newCount] = docId; - if (docId > countToMaxDocId[newCount]) countToMaxDocId[newCount] = docId; + int oldCount = newCount - count; + if (oldCount > 0) countToFrequency[oldCount] -= 1; + if (docId > maxDocId) maxDocId = docId; + if (docId < minDocId) minDocId = docId; } @Override @@ -54,6 +41,9 @@ public void increment(int key, short count) { @Override public short get(int key) { + if (key == DocIdSetIterator.NO_MORE_DOCS - 1) { + return -1; + } return docIdToCount[key]; } @@ -72,18 +62,9 @@ public DocIdSetIterator docIdSetIterator(int candidates) { // 2. the minimum doc ID that we should start iterating at // 3. and the maximum doc ID that we should iterate to int minCount = maxCount; - int minDocId = Integer.MAX_VALUE; - int maxDocId = Integer.MIN_VALUE; int accumulated = 0; while (accumulated < candidates && minCount > 0) { - int count = countToFrequency[minCount]; - if (count > 0) { - accumulated += count; - int maybeNewMinDocId = countToMinDocId[minCount]; - if (maybeNewMinDocId < minDocId) minDocId = maybeNewMinDocId; - int maybeNewMaxDocId = countToMaxDocId[minCount]; - if (maybeNewMaxDocId > maxDocId) maxDocId = maybeNewMaxDocId; - } + accumulated += countToFrequency[minCount]; minCount -= 1; } // minCount = Math.max(1, minCount); diff --git a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java index b2bf8dbb6..6498c6267 100644 --- a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java +++ b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java @@ -10,6 +10,7 @@ import java.util.Objects; import java.util.function.Function; +import static java.lang.Math.max; import static java.lang.Math.min; /** @@ -60,7 +61,11 @@ private HitCounter countHits(LeafReader reader) throws IOException { } else { TermsEnum termsEnum = terms.iterator(); PostingsEnum docs = null; - HitCounter counter = new ArrayHitCounter(reader.maxDoc(), hashAndFrequencies.length); + + int maxFreq = 1; + for (HashAndFreq hf : hashAndFrequencies) if (hf.freq > maxFreq) maxFreq = hf.freq; + + HitCounter counter = new ArrayHitCounter(reader.maxDoc(), hashAndFrequencies.length * maxFreq); for (HashAndFreq hf : hashAndFrequencies) { // We take two different paths here, depending on the frequency of the current hash. // If the frequency is one, we avoid checking the frequency of matching docs when From 1e008bad5a2fed2833da78016cca3dbeea76d679 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 17:04:36 -0700 Subject: [PATCH 06/13] Literally just yanked the implementation out of MatchHashesAndScoreQuery to ArrayHitCounter --- .../elastiknn/search/ArrayHitCounter.java | 210 ++++++++++-------- .../search/MatchHashesAndScoreQuery.java | 75 +------ .../search/ArrayHitCounterSpec.scala | 2 +- .../com/klibisz/elastiknn/RecallSuite.scala | 32 +-- 4 files changed, 130 insertions(+), 189 deletions(-) diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 6b78977f7..3d96491e7 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -2,136 +2,150 @@ import org.apache.lucene.search.DocIdSetIterator; - public final class ArrayHitCounter implements HitCounter { - private final short[] docIdToCount; - private final short[] countToFrequency; - private int minDocId = Integer.MAX_VALUE; - private int maxDocId = Integer.MIN_VALUE; - private int maxCount; - + private final short[] counts; + private int numHits; + private int minKey; + private int maxKey; - public ArrayHitCounter(int capacity, int maxPossibleCount) { - this.docIdToCount = new short[capacity]; - this.countToFrequency = new short[maxPossibleCount + 1]; - this.maxCount = 0; - } + private short maxValue; - private void incrementKeyByCount(int docId, short count) { - int newCount = (docIdToCount[docId] += count); - if (newCount > maxCount) maxCount = newCount; - countToFrequency[newCount] += 1; - int oldCount = newCount - count; - if (oldCount > 0) countToFrequency[oldCount] -= 1; - if (docId > maxDocId) maxDocId = docId; - if (docId < minDocId) minDocId = docId; + public ArrayHitCounter(int capacity) { + counts = new short[capacity]; + numHits = 0; + minKey = capacity; + maxKey = 0; + maxValue = 0; } @Override public void increment(int key) { - incrementKeyByCount(key, (short) 1); + short after = ++counts[key]; + if (after == 1) { + numHits++; + minKey = Math.min(key, minKey); + maxKey = Math.max(key, maxKey); + } + if (after > maxValue) maxValue = after; } @Override public void increment(int key, short count) { - incrementKeyByCount(key, count); + short after = (counts[key] += count); + if (after == count) { + numHits++; + minKey = Math.min(key, minKey); + maxKey = Math.max(key, maxKey); + } + if (after > maxValue) maxValue = after; } - @Override public short get(int key) { - if (key == DocIdSetIterator.NO_MORE_DOCS - 1) { - return -1; - } - return docIdToCount[key]; + return counts[key]; } @Override public int capacity() { - return docIdToCount.length; + return counts.length; } + private KthGreatestResult kthGreatest(int k) { + // Find the kth greatest document hit count in O(n) time and O(n) space. + // Though the space is typically negligibly small in practice. + // This implementation exploits the fact that we're specifically counting document hit counts. + // Counts are integers, and they're likely to be pretty small, since we're unlikely to match + // the same document many times. + + // Start by building a histogram of all counts. + // e.g., if the counts are [0, 4, 1, 1, 2], + // then the histogram is [1, 2, 1, 0, 1], + // because 0 occurs once, 1 occurs twice, 2 occurs once, 3 occurs zero times, and 4 occurs once. + short[] hist = new short[maxValue + 1]; + for (short c: counts) hist[c]++; + + // Now we start at the max value and iterate backwards through the histogram, + // accumulating counts of counts until we've exceeded k. + int numGreaterEqual = 0; + short kthGreatest = maxValue; + while (kthGreatest > 0) { + numGreaterEqual += hist[kthGreatest]; + if (numGreaterEqual > k) break; + else kthGreatest--; + } + + // Finally we find the number that were greater than the kth greatest count. + // There's a special case if kthGreatest is zero, then the number that were greater is the number of hits. + int numGreater = numGreaterEqual - hist[kthGreatest]; + if (kthGreatest == 0) numGreater = numHits; + return new KthGreatestResult(kthGreatest, numGreater, numHits); + } + @Override public DocIdSetIterator docIdSetIterator(int candidates) { - if (maxCount == 0) return DocIdSetIterator.empty(); + if (numHits == 0) return DocIdSetIterator.empty(); else { - // Loop backwards through the countToFrequency array to figure out a few things needed for the iterator: - // 1. the minimum count that's required for a document to be a candidate - // 2. the minimum doc ID that we should start iterating at - // 3. and the maximum doc ID that we should iterate to - int minCount = maxCount; - int accumulated = 0; - while (accumulated < candidates && minCount > 0) { - accumulated += countToFrequency[minCount]; - minCount -= 1; - } -// minCount = Math.max(1, minCount); - int numGreaterThanMinCount = accumulated - countToFrequency[minCount]; - return new _DocIdSetIterator(candidates, minDocId, maxDocId, minCount, numGreaterThanMinCount, docIdToCount); - } - } - private static final class _DocIdSetIterator extends DocIdSetIterator { - - private final int candidates; - private final int minDocId; - private final int maxDocId; - private final int minCount; - private final int numGreaterThanMinCount; - private final short[] docIdToCount; - private int currentDocId; - private int numEmitted; - private int numEmittedEqualToMinCount; - - public _DocIdSetIterator(int candidates, int minDocId, int maxDocId, int minCount, int numGreaterThanMinCount, short[] docIdToCount) { - this.candidates = candidates; - this.minDocId = minDocId; - this.maxDocId = maxDocId; - this.minCount = minCount; - this.numGreaterThanMinCount = numGreaterThanMinCount; - this.docIdToCount = docIdToCount; - this.currentDocId = minDocId - 1; - this.numEmitted = 0; - this.numEmittedEqualToMinCount = 0; - } + KthGreatestResult kgr = kthGreatest(candidates); - @Override - public int docID() { - return currentDocId; - } + // Return an iterator over the doc ids >= the min candidate count. + return new DocIdSetIterator() { + + // Important that this starts at -1. Need a boolean to denote that it has started iterating. + private int docID = -1; + private boolean started = false; - @Override - public int nextDoc() { - while (true) { - if (numEmitted == candidates || currentDocId + 1 > maxDocId) { - currentDocId = DocIdSetIterator.NO_MORE_DOCS; - return currentDocId; - } else { - currentDocId++; - int count = docIdToCount[currentDocId]; - if (count > minCount) { - numEmitted++; - return currentDocId; - } else if (count == minCount && numEmittedEqualToMinCount < candidates - numGreaterThanMinCount) { - numEmitted++; - numEmittedEqualToMinCount++; - return currentDocId; + // Track the number of ids emitted, and the number of ids with count = kgr.kthGreatest emitted. + private int numEmitted = 0; + private int numEq = 0; + + @Override + public int docID() { + return docID; + } + + @Override + public int nextDoc() { + + if (!started) { + started = true; + docID = minKey - 1; + } + + // Ensure that docs with count = kgr.kthGreatest are only emitted when there are fewer + // than `candidates` docs with count > kgr.kthGreatest. + while (true) { + if (numEmitted == candidates || docID + 1 > maxKey) { + docID = DocIdSetIterator.NO_MORE_DOCS; + return docID(); + } else { + docID++; + if (counts[docID] > kgr.kthGreatest) { + numEmitted++; + return docID(); + } else if (counts[docID] == kgr.kthGreatest && numEq < candidates - kgr.numGreaterThan) { + numEq++; + numEmitted++; + return docID(); + } + } } } - } - } - @Override - public int advance(int target) { - while (currentDocId < target) nextDoc(); - return currentDocId; - } + @Override + public int advance(int target) { + while (docID < target) nextDoc(); + return docID(); + } - @Override - public long cost() { - return maxDocId - minDocId; + @Override + public long cost() { + return maxKey - minKey; + } + }; } } -} + +} \ No newline at end of file diff --git a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java index 6498c6267..a6269b988 100644 --- a/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java +++ b/elastiknn-lucene/src/main/java/org/apache/lucene/search/MatchHashesAndScoreQuery.java @@ -62,10 +62,7 @@ private HitCounter countHits(LeafReader reader) throws IOException { TermsEnum termsEnum = terms.iterator(); PostingsEnum docs = null; - int maxFreq = 1; - for (HashAndFreq hf : hashAndFrequencies) if (hf.freq > maxFreq) maxFreq = hf.freq; - - HitCounter counter = new ArrayHitCounter(reader.maxDoc(), hashAndFrequencies.length * maxFreq); + HitCounter counter = new ArrayHitCounter(reader.maxDoc()); for (HashAndFreq hf : hashAndFrequencies) { // We take two different paths here, depending on the frequency of the current hash. // If the frequency is one, we avoid checking the frequency of matching docs when @@ -91,76 +88,6 @@ private HitCounter countHits(LeafReader reader) throws IOException { } } -// private DocIdSetIterator buildDocIdSetIterator(HitCounter counter) { -// // TODO: Add back this logging once log4j mess has settled. -//// if (counter.numHits() < candidates) { -//// logger.warn(String.format( -//// "Found fewer approximate matches [%d] than the requested number of candidates [%d]", -//// counter.numHits(), candidates)); -//// } -// if (counter.isEmpty()) return DocIdSetIterator.empty(); -// else { -// -// KthGreatestResult kgr = counter.kthGreatest(candidates); -// -// // Return an iterator over the doc ids >= the min candidate count. -// return new DocIdSetIterator() { -// -// // Important that this starts at -1. Need a boolean to denote that it has started iterating. -// private int docID = -1; -// private boolean started = false; -// -// // Track the number of ids emitted, and the number of ids with count = kgr.kthGreatest emitted. -// private int numEmitted = 0; -// private int numEq = 0; -// -// @Override -// public int docID() { -// return docID; -// } -// -// @Override -// public int nextDoc() { -// -// if (!started) { -// started = true; -// docID = counter.minKey() - 1; -// } -// -// // Ensure that docs with count = kgr.kthGreatest are only emitted when there are fewer -// // than `candidates` docs with count > kgr.kthGreatest. -// while (true) { -// if (numEmitted == candidates || docID + 1 > counter.maxKey()) { -// docID = DocIdSetIterator.NO_MORE_DOCS; -// return docID(); -// } else { -// docID++; -// if (counter.get(docID) > kgr.kthGreatest) { -// numEmitted++; -// return docID(); -// } else if (counter.get(docID) == kgr.kthGreatest && numEq < candidates - kgr.numGreaterThan) { -// numEq++; -// numEmitted++; -// return docID(); -// } -// } -// } -// } -// -// @Override -// public int advance(int target) { -// while (docID < target) nextDoc(); -// return docID(); -// } -// -// @Override -// public long cost() { -// return counter.numHits(); -// } -// }; -// } -// } - @Override public Explanation explain(LeafReaderContext context, int doc) throws IOException { HitCounter counter = countHits(context.reader()); diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index d26fed401..14df616b4 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -59,7 +59,7 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { for (_ <- 0 until 99) { val matches = (0 until numMatches).map(_ => rng.nextInt(numDocs)) val ref = new Reference(numDocs) - val ahc = new ArrayHitCounter(numDocs, matches.length) + val ahc = new ArrayHitCounter(numDocs) matches.foreach { doc => ref.increment(doc) ahc.increment(doc) diff --git a/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala b/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala index c60bda022..51f92d8a4 100644 --- a/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala +++ b/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala @@ -22,7 +22,7 @@ import scala.util.hashing.MurmurHash3.orderedHash * have seen different results at times. This seems to be an effect at the Elasticsearch level. I've tested at the Lucene (sans ES) * level and that seems to be reliably deterministic. */ -class RecallSuite extends AsyncFunSuite with Matchers with ElasticAsyncClient { +class RecallSuite extends AsyncFunSuite with Matchers with ElasticAsyncClient with AsyncCancelAfterFailure { // Each test case consists of setting up one Mapping and then running several queries against that mapping. // Each query has an expected recall that will be checked. @@ -40,21 +40,21 @@ class RecallSuite extends AsyncFunSuite with Matchers with ElasticAsyncClient { private val tests = Seq( // Exact - Test( - Mapping.SparseBool(dims), - Seq( - NearestNeighborsQuery.Exact(vecField, Similarity.Jaccard) -> 1d, - NearestNeighborsQuery.Exact(vecField, Similarity.Hamming) -> 1d - ) - ), - Test( - Mapping.DenseFloat(dims), - Seq( - NearestNeighborsQuery.Exact(vecField, Similarity.L1) -> 1d, - NearestNeighborsQuery.Exact(vecField, Similarity.L2) -> 1d, - NearestNeighborsQuery.Exact(vecField, Similarity.Cosine) -> 1d - ) - ), +// Test( +// Mapping.SparseBool(dims), +// Seq( +// NearestNeighborsQuery.Exact(vecField, Similarity.Jaccard) -> 1d, +// NearestNeighborsQuery.Exact(vecField, Similarity.Hamming) -> 1d +// ) +// ), +// Test( +// Mapping.DenseFloat(dims), +// Seq( +// NearestNeighborsQuery.Exact(vecField, Similarity.L1) -> 1d, +// NearestNeighborsQuery.Exact(vecField, Similarity.L2) -> 1d, +// NearestNeighborsQuery.Exact(vecField, Similarity.Cosine) -> 1d +// ) +// ), // Jaccard LSH Test( Mapping.JaccardLsh(dims, 200, 1), From 56348f230d901f59fefe5ff48f5b5e63f8221e80 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Sun, 25 Aug 2024 17:09:19 -0700 Subject: [PATCH 07/13] Tests passing locally --- .../elastiknn/search/ArrayHitCounter.java | 6 ++-- .../com/klibisz/elastiknn/RecallSuite.scala | 30 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 3d96491e7..827a80f74 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -119,16 +119,16 @@ public int nextDoc() { while (true) { if (numEmitted == candidates || docID + 1 > maxKey) { docID = DocIdSetIterator.NO_MORE_DOCS; - return docID(); + return docID; } else { docID++; if (counts[docID] > kgr.kthGreatest) { numEmitted++; - return docID(); + return docID; } else if (counts[docID] == kgr.kthGreatest && numEq < candidates - kgr.numGreaterThan) { numEq++; numEmitted++; - return docID(); + return docID; } } } diff --git a/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala b/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala index 51f92d8a4..123905234 100644 --- a/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala +++ b/elastiknn-plugin-integration-tests/src/test/scala/com/klibisz/elastiknn/RecallSuite.scala @@ -40,21 +40,21 @@ class RecallSuite extends AsyncFunSuite with Matchers with ElasticAsyncClient wi private val tests = Seq( // Exact -// Test( -// Mapping.SparseBool(dims), -// Seq( -// NearestNeighborsQuery.Exact(vecField, Similarity.Jaccard) -> 1d, -// NearestNeighborsQuery.Exact(vecField, Similarity.Hamming) -> 1d -// ) -// ), -// Test( -// Mapping.DenseFloat(dims), -// Seq( -// NearestNeighborsQuery.Exact(vecField, Similarity.L1) -> 1d, -// NearestNeighborsQuery.Exact(vecField, Similarity.L2) -> 1d, -// NearestNeighborsQuery.Exact(vecField, Similarity.Cosine) -> 1d -// ) -// ), + Test( + Mapping.SparseBool(dims), + Seq( + NearestNeighborsQuery.Exact(vecField, Similarity.Jaccard) -> 1d, + NearestNeighborsQuery.Exact(vecField, Similarity.Hamming) -> 1d + ) + ), + Test( + Mapping.DenseFloat(dims), + Seq( + NearestNeighborsQuery.Exact(vecField, Similarity.L1) -> 1d, + NearestNeighborsQuery.Exact(vecField, Similarity.L2) -> 1d, + NearestNeighborsQuery.Exact(vecField, Similarity.Cosine) -> 1d + ) + ), // Jaccard LSH Test( Mapping.JaccardLsh(dims, 200, 1), From a0b0040d11b24f9ad7f0ea3fe68eaa08eebaf0f4 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Wed, 28 Aug 2024 10:10:00 -0700 Subject: [PATCH 08/13] Some progress on the tests --- .../elastiknn/search/ArrayHitCounter.java | 3 + .../search/ArrayHitCounterSpec.scala | 83 +++++++++++++------ 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 827a80f74..8bfb3440a 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -90,6 +90,8 @@ public DocIdSetIterator docIdSetIterator(int candidates) { KthGreatestResult kgr = kthGreatest(candidates); + System.out.printf("kth greatest = %d\n", kgr.kthGreatest); + // Return an iterator over the doc ids >= the min candidate count. return new DocIdSetIterator() { @@ -122,6 +124,7 @@ public int nextDoc() { return docID; } else { docID++; + System.out.printf("docID=%d, counts[%d]=%d\n", docID, docID, counts[docID]); if (counts[docID] > kgr.kthGreatest) { numEmitted++; return docID; diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 14df616b4..3effe98cc 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -4,14 +4,28 @@ import org.apache.lucene.search.DocIdSetIterator import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers +import scala.collection.mutable.ArrayBuffer import scala.util.Random final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { + final class ReferenceDocIdSetIterator(docIds: Array[Int]) extends DocIdSetIterator { + + private var currentDocIdIndex = -1; + override def docID(): Int = if (currentDocIdIndex < docIds.length) docIds(currentDocIdIndex) else DocIdSetIterator.NO_MORE_DOCS + override def nextDoc(): Int = { + currentDocIdIndex += 1 + docID() + } + override def advance(target: Int): Int = { + while (docID() < target) nextDoc() + docID() + } + override def cost(): Long = docIds.length + } + final class Reference(referenceCapacity: Int) extends HitCounter { - private val counts = scala.collection.mutable.Map[Int, Short]( - (0 until referenceCapacity).map(_ -> 0.toShort): _* - ) + private val counts = scala.collection.mutable.Map[Int, Short]().withDefaultValue(0) override def increment(key: Int): Unit = counts.update(key, (counts(key) + 1).toShort) @@ -21,7 +35,25 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { override def capacity(): Int = this.referenceCapacity - override def docIdSetIterator(k: Int): DocIdSetIterator = DocIdSetIterator.empty() + override def docIdSetIterator(k: Int): DocIdSetIterator = { + // A very naive/inefficient way to implement the DocIdSetIterator. + val valuesSorted = counts.values.toArray.sorted.reverse + val kthGreatest = valuesSorted.take(k).last + val greaterDocIds = counts.filter(_._2 > kthGreatest).keys.toArray + val equalDocIds = counts.filter(_._2 == kthGreatest).keys.toArray.sorted.take(k - greaterDocIds.length) + val selectedDocIds = (equalDocIds ++ greaterDocIds).sorted + println(counts.toList.sorted) + + new ReferenceDocIdSetIterator(selectedDocIds) + } + } + + private def consumeDocIdSetIterator(disi: DocIdSetIterator): List[Int] = { + val docIds = new ArrayBuffer[Int] + while (disi.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { + docIds.append(disi.docID()) + } + docIds.toList } "reference examples" - { @@ -33,27 +65,26 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { c.increment(0) c.get(0) shouldBe 1 - c.get(5) shouldBe 0 - c.increment(5, 5) - c.get(5) shouldBe 5 + c.get(1) shouldBe 0 + c.increment(1, 5) + c.get(1) shouldBe 5 - c.get(9) shouldBe 0 - c.increment(9) - c.get(9) shouldBe 1 - c.increment(9) - c.get(9) shouldBe 2 + c.get(2) shouldBe 0 + c.increment(2) + c.get(2) shouldBe 1 + c.increment(2) + c.get(2) shouldBe 2 -// val kgr = c.kthGreatest(2) -// kgr.kthGreatest shouldBe 1 -// kgr.numGreaterThan shouldBe 2 -// kgr.numNonZero shouldBe 3 + // The k=2 most frequent doc IDs are 1 and 2. + val docIds = consumeDocIdSetIterator(c.docIdSetIterator(2)) + docIds shouldBe List(1, 2) } } "randomized comparison to reference" in { - val seed = System.currentTimeMillis() + val seed = 0L // System.currentTimeMillis() val rng = new Random(seed) - val numDocs = 60000 + val numDocs = 10 val numMatches = numDocs / 2 info(s"Using seed $seed") for (_ <- 0 until 99) { @@ -69,12 +100,16 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { ahc.increment(doc, count) ahc.get(doc) shouldBe ref.get(doc) } -// ahc.minKey() shouldBe ref.minKey() -// ahc.maxKey() shouldBe ref.maxKey() -// val k = rng.nextInt(numDocs) -// val ahcKgr = ahc.kthGreatest(k) -// val refKgr = ref.kthGreatest(k) -// ahcKgr shouldBe refKgr + val k = rng.nextInt(numDocs) + val actualDocIds = consumeDocIdSetIterator(ahc.docIdSetIterator(k)) + val referenceDocIds = consumeDocIdSetIterator(ref.docIdSetIterator(k)) + + println(k) + println((actualDocIds.length, actualDocIds)) + println((referenceDocIds.length, referenceDocIds)) + println("---") + + referenceDocIds shouldBe actualDocIds } } } From 19d47fc5934b74d995f6df4ae3f13d88c678ee14 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Wed, 28 Aug 2024 10:26:51 -0700 Subject: [PATCH 09/13] Unit tests passing again --- .../elastiknn/search/ArrayHitCounter.java | 3 - .../search/ArrayHitCounterSpec.scala | 72 +++++++++++-------- 2 files changed, 42 insertions(+), 33 deletions(-) diff --git a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java index 8bfb3440a..827a80f74 100644 --- a/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java +++ b/elastiknn-lucene/src/main/java/com/klibisz/elastiknn/search/ArrayHitCounter.java @@ -90,8 +90,6 @@ public DocIdSetIterator docIdSetIterator(int candidates) { KthGreatestResult kgr = kthGreatest(candidates); - System.out.printf("kth greatest = %d\n", kgr.kthGreatest); - // Return an iterator over the doc ids >= the min candidate count. return new DocIdSetIterator() { @@ -124,7 +122,6 @@ public int nextDoc() { return docID; } else { docID++; - System.out.printf("docID=%d, counts[%d]=%d\n", docID, docID, counts[docID]); if (counts[docID] > kgr.kthGreatest) { numEmitted++; return docID; diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 3effe98cc..7bcefe3ba 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -9,22 +9,31 @@ import scala.util.Random final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { - final class ReferenceDocIdSetIterator(docIds: Array[Int]) extends DocIdSetIterator { - private var currentDocIdIndex = -1; - override def docID(): Int = if (currentDocIdIndex < docIds.length) docIds(currentDocIdIndex) else DocIdSetIterator.NO_MORE_DOCS - override def nextDoc(): Int = { - currentDocIdIndex += 1 - docID() - } - override def advance(target: Int): Int = { - while (docID() < target) nextDoc() - docID() + + private final class ReferenceHitCounter(referenceCapacity: Int) extends HitCounter { + + private final class ArrayDocIdSetIterator(docIds: Array[Int]) extends DocIdSetIterator { + + private var currentDocIdIndex = -1; + + override def docID(): Int = if (currentDocIdIndex < docIds.length) docIds(currentDocIdIndex) else DocIdSetIterator.NO_MORE_DOCS + + override def nextDoc(): Int = { + currentDocIdIndex += 1 + docID() + } + + override def advance(target: Int): Int = { + while (docID() < target) { + val _ = nextDoc() + } + docID() + } + + override def cost(): Long = docIds.length } - override def cost(): Long = docIds.length - } - final class Reference(referenceCapacity: Int) extends HitCounter { private val counts = scala.collection.mutable.Map[Int, Short]().withDefaultValue(0) override def increment(key: Int): Unit = counts.update(key, (counts(key) + 1).toShort) @@ -37,14 +46,22 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { override def docIdSetIterator(k: Int): DocIdSetIterator = { // A very naive/inefficient way to implement the DocIdSetIterator. - val valuesSorted = counts.values.toArray.sorted.reverse - val kthGreatest = valuesSorted.take(k).last - val greaterDocIds = counts.filter(_._2 > kthGreatest).keys.toArray - val equalDocIds = counts.filter(_._2 == kthGreatest).keys.toArray.sorted.take(k - greaterDocIds.length) - val selectedDocIds = (equalDocIds ++ greaterDocIds).sorted - println(counts.toList.sorted) - - new ReferenceDocIdSetIterator(selectedDocIds) + if (k == 0 || counts.isEmpty) DocIdSetIterator.empty() + else { + // This is a hack to replicate a bug in how we emit doc IDs. + // Basically if the kth greatest value is zero, we end up emitting docs that were never matched, + // so we need to fill the map with zeros to replicate the behavior here. + val minKey = counts.keys.min + val maxKey = counts.keys.max + (minKey to maxKey).foreach(k => counts.update(k, counts(k))) + + val valuesSorted = counts.values.toArray.sorted.reverse + val kthGreatest = valuesSorted.take(k).last + val greaterDocIds = counts.filter(_._2 > kthGreatest).keys.toArray + val equalDocIds = counts.filter(_._2 == kthGreatest).keys.toArray.sorted.take(k - greaterDocIds.length) + val selectedDocIds = (equalDocIds ++ greaterDocIds).sorted + new ArrayDocIdSetIterator(selectedDocIds) + } } } @@ -58,7 +75,7 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { "reference examples" - { "example 1" in { - val c = new Reference(10) + val c = new ReferenceHitCounter(10) c.capacity() shouldBe 10 c.get(0) shouldBe 0 @@ -82,14 +99,14 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { } "randomized comparison to reference" in { - val seed = 0L // System.currentTimeMillis() + val seed = System.currentTimeMillis() val rng = new Random(seed) - val numDocs = 10 + val numDocs = 60000 val numMatches = numDocs / 2 info(s"Using seed $seed") for (_ <- 0 until 99) { val matches = (0 until numMatches).map(_ => rng.nextInt(numDocs)) - val ref = new Reference(numDocs) + val ref = new ReferenceHitCounter(numDocs) val ahc = new ArrayHitCounter(numDocs) matches.foreach { doc => ref.increment(doc) @@ -104,11 +121,6 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { val actualDocIds = consumeDocIdSetIterator(ahc.docIdSetIterator(k)) val referenceDocIds = consumeDocIdSetIterator(ref.docIdSetIterator(k)) - println(k) - println((actualDocIds.length, actualDocIds)) - println((referenceDocIds.length, referenceDocIds)) - println("---") - referenceDocIds shouldBe actualDocIds } } From 054fb4afeb8c0ec7c6d9f0fc08560b9174eeb1d8 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Wed, 28 Aug 2024 10:36:18 -0700 Subject: [PATCH 10/13] Scalafmt --- .../com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 7bcefe3ba..0e0de06d2 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -9,8 +9,6 @@ import scala.util.Random final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { - - private final class ReferenceHitCounter(referenceCapacity: Int) extends HitCounter { private final class ArrayDocIdSetIterator(docIds: Array[Int]) extends DocIdSetIterator { From 66c41517012fc606684d646457a12df212c1b83a Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Wed, 28 Aug 2024 10:40:15 -0700 Subject: [PATCH 11/13] Add a test demonstrating the issue --- .../elastiknn/search/ArrayHitCounterSpec.scala | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala index 0e0de06d2..b7260ed16 100644 --- a/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala +++ b/elastiknn-lucene/src/test/scala/com/klibisz/elastiknn/search/ArrayHitCounterSpec.scala @@ -122,4 +122,17 @@ final class ArrayHitCounterSpec extends AnyFreeSpec with Matchers { referenceDocIds shouldBe actualDocIds } } + + "the counter emits docs that had zero matches (bug, https://github.com/alexklibisz/elastiknn/issues/715)" in { + // Only documents 0 and 9 had a hit, so we should expect to only emit those two. + // But the k=10th greatest value is 0, so we end up emitting all of the doc IDs, + // including 8 of which had zero hits. + val ahc = new ArrayHitCounter(10) + ahc.increment(0) + ahc.increment(9) + val docIds = consumeDocIdSetIterator(ahc.docIdSetIterator(10)) + docIds shouldBe List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) + // Once the bug is fixed, this should be the correct result: + // docIds shouldBe List(0, 9) + } } From 30f2d7309865bf01d8dc8b66bcf903b40d22abed Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Wed, 28 Aug 2024 10:52:45 -0700 Subject: [PATCH 12/13] Remove an unused test --- .../apache/lucene/search/MatchHashesAndScoreQuerySuite.scala | 5 ----- 1 file changed, 5 deletions(-) diff --git a/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala b/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala index ca268ec7c..9a402e767 100644 --- a/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala +++ b/elastiknn-lucene/src/test/scala/org/apache/lucene/search/MatchHashesAndScoreQuerySuite.scala @@ -108,11 +108,6 @@ class MatchHashesAndScoreQuerySuite extends AnyFunSuite with Matchers with Lucen } } - ignore("returns no candidates with zero hash matches") { - // TODO! - succeed - } - test("returns no more than `candidates` doc IDs") { val query = Array(6, 7).map(i => HashAndFreq.once(writeInt(i))) val candidates = 5 From 07f9557ed483d19123030b58c41818c836201f46 Mon Sep 17 00:00:00 2001 From: Alex Klibisz Date: Wed, 28 Aug 2024 18:10:40 +0000 Subject: [PATCH 13/13] Updated benchmarks --- docs/pages/performance/fashion-mnist/plot.b64 | 2 +- docs/pages/performance/fashion-mnist/plot.png | Bin 46623 -> 46812 bytes .../performance/fashion-mnist/results.md | 16 ++++++++-------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/pages/performance/fashion-mnist/plot.b64 b/docs/pages/performance/fashion-mnist/plot.b64 index f964c282d..f59545aaf 100644 --- a/docs/pages/performance/fashion-mnist/plot.b64 +++ b/docs/pages/performance/fashion-mnist/plot.b64 @@ -1 +1 @@ -iVBORw0KGgoAAAANSUhEUgAABHsAAAMKCAYAAAAViEgEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAAC1jElEQVR4nOzdeXiU1f3+8XsmyyQzk4Q1bAkogaoxoCQuBNmXkEAFFasVqyjuuLS2atVSFLdUa9X2i+KCioX6qxIXFM1GlC1CwbBoBFFZjOxrAjPZJjPP7w+bKcMkkECSyfJ+XReXznnOPHPP5GSSfOY855gMwzAEAAAAAACAVsEc6AAAAAAAAABoOBR7AAAAAAAAWhGKPQAAAAAAAK0IxR4AAAAAAIBWhGIPAAAAAABAK0KxBwAAAAAAoBWh2AMAAAAAANCKUOwBAAAAAABoRSj2AAAAAAAAtCIUewA0CZPJpEcffdR7e+7cuTKZTNq+fXvAMjWkG264QWeccUagY6CBLFmyRCaTSUuWLKlT/2eeeUZnn322PB5P4wY7xsGDB2Wz2fTpp5822WOeijPOOEM33HBDoz5GVVWVHnjgAcXGxspsNuuyyy6TJDkcDt18883q2rWrTCaTfve73zVqjpbs+Pfo5uKMM87QL3/5y4BnONUx3Fj5H330UZlMpgY5l8lk0l133dUg5wIANB8Ue4BWoLpwUv0vODhYPXr00A033KCdO3cGOl6DKSoq0u23364zzjhDFotF0dHRuvzyy/XFF18EOhrasCNHjujpp5/WH//4R5nN//ux+s477+g3v/mN+vbtK5PJpOHDh5/wPB6PR507d9YzzzxTp8ft2LGjbr75Zv35z3+uU/+NGzfq0UcfbTUF1mO98cYb+utf/6orr7xSb731lu69915J0lNPPaW5c+fqjjvu0Lx583TdddcFOGnLtmvXLj366KNav359g563NY/NumpNr8GJxsnbb7+tF154ockzAUBbFBzoAAAazmOPPaYzzzxT5eXlWrVqlebOnasVK1aosLBQYWFhgY53WvLz8zVu3DhJ0s0336z4+Hjt2bNHc+fO1eDBg/Xiiy/qjjvuCFi+1157rUlndaD5eOONN1RVVaVrrrnGp3327NkqKCjQhRdeqIMHD570PKtXr9aBAwc0fvz4Oj/27bffrn/84x/67LPPNHLkyBP23bhxo2bOnKnhw4e3ullon332mXr06KHnn3/er33gwIF65JFHApSsddm1a5dmzpypM844Q+eff36Dnbe5j83Nmzf7FHIbQ31fg+nTp+vBBx9s1Eyn6kTj5O2331ZhYSGz7ACgCVDsAVqRtLQ0XXDBBZJ+Loh06tRJTz/9tD766CNdddVVAU536g4fPqwrr7xS4eHhys/PV1xcnPfY73//e40dO1Z33323BgwYoIEDBzZpNqfTKZvNppCQkCZ93KZSVVUlj8ej0NDQQEdptt58801NmDDBr6A6b9489ejRQ2azWQkJCSc9z6effqpevXrp3HPPrfNjn3POOUpISNDcuXNPWuypD8MwVF5ervDw8AY7Z2Pat2+f2rVrV2N7fHx80wdCi3fs94DFYgl0HD/BwcEKDubXeOnnWZGVlZUt/kMtAGhoXMYFtGJDhgyRJG3ZssWn/dtvv9WVV16pDh06KCwsTBdccIE++ugjv/sXFxfr3nvv9V42FRMTo+uvv14HDhyQJFVWVmrGjBlKSkpSVFSUbDabhgwZos8//7xBn8crr7yiPXv26K9//atPoUeSwsPD9dZbb0n6eWZTtdrWM6htraDMzEwNGTJENptNERERGj9+vL755hufPjfccIPsdru2bNmicePGKSIiQtdee6332PGfxno8Hr3wwgs699xzFRYWpi5duui2227T4cOHffp9+eWXGjt2rDp16qTw8HCdeeaZmjp16klfl+q1IHJycnT++ecrLCxM8fHxev/99/36FhcX63e/+51iY2NlsVjUp08fPf300z6zkbZv3y6TyaRnn31WL7zwguLi4mSxWLRx48ZaM+Tm5mrw4MFq166d7Ha7zjrrLD388MM+fSoqKvTII4+oT58+slgsio2N1QMPPKCKigq/882fP18XXXSRrFar2rdvr6FDhyonJ8enz0svvaRzzz1XFotF3bt315133qni4mKfPsOHD1dCQoI2btyoESNGyGq1qkePHjVeIrVjxw5ddtllstlsio6O1r333ltjtpps27ZNX331lUaPHu13rHr9mLr65JNPfGb11HVcjBkzRh9//LEMw6j13HPnztWvfvUrSdKIESO8l3xWr0lUPZays7N1wQUXKDw8XK+88oqkn4tZI0eOVHR0tCwWi+Lj4zV79my/xzAMQ0888YRiYmJktVo1YsQIv++hanUZj9LPxdQ//OEP3n5nnXWWnn32We9zrR6zn3/+ub755huf52UymbRt2zZ98skn3vaGukSmtvVtjl/bpfr9ZtmyZbrtttvUsWNHRUZG6vrrr/d7H6jJV199pRtuuEG9e/dWWFiYunbtqqlTp/rNFKt+v/vhhx90ww03qF27doqKitKNN96o0tJSn74VFRW699571blzZ0VERGjChAnasWPHSbMsWbJEF154oSTpxhtv9L6mc+fO9fZZsGCBkpKSFB4erk6dOuk3v/nNSS8lPtnYrLZixQpddNFFCgsLU+/evfXPf/7T71x1HVc1OdH3QE1r9nz11VcaNmyYwsPDFRMToyeeeEJvvvlmrePsRPnr+hocq6afcXV5Pz6Rf/3rXzrrrLMUFhampKQkLVu2zK/Pzp07NXXqVHXp0kUWi0Xnnnuu3njjDe/xE42T4cOH65NPPtGPP/7obT/252Zdf1ZUrzH0r3/9y/uzICsrq87PEwDaCj4SAFqx6l8427dv72375ptvdMkll6hHjx568MEHZbPZ9O677+qyyy7Te++9p8svv1zSzwubDhkyRJs2bdLUqVOVmJioAwcO6KOPPtKOHTvUqVMnHTlyRHPmzNE111yjW265RUePHtXrr7+usWPHavXq1Q02zf/jjz9WWFhYrbOTzjzzTA0ePFiLFy9WeXl5vT/dmzdvnqZMmaKxY8fq6aefVmlpqWbPnq3Bgwdr3bp1Pr+MVlVVaezYsRo8eLCeffZZWa3WWs972223ae7cubrxxht1zz33aNu2bZo1a5bWrVun/Px8hYSEaN++fUpJSVHnzp314IMPql27dtq+fXuNBZuafP/997r66qt1++23a8qUKXrzzTf1q1/9SllZWRozZowkqbS0VMOGDdPOnTt12223qWfPnvriiy/00EMPaffu3X7rJ7z55psqLy/XrbfeKovFog4dOtT42N98841++ctfqn///nrsscdksVj0ww8/KD8/39vH4/FowoQJWrFihW699Vadc845+vrrr/X888/ru+++04cffujtO3PmTD366KMaNGiQHnvsMYWGhuo///mPPvvsM6WkpEj6+Q+cmTNnavTo0brjjju0efNmzZ49W2vWrPG+ptUOHz6s1NRUXXHFFbrqqquUkZGhP/7xj+rXr5/S0tIkSWVlZRo1apSKiop0zz33qHv37po3b54+++yzOr3+1etFJSYm1ql/bfbs2aN169Z5C5b1GRdJSUl6/vnn9c0339Q6g2jo0KG655579I9//EMPP/ywzjnnHEny/lf6+VKVa665RrfddptuueUWnXXWWZJ+vhzt3HPP1YQJExQcHKyPP/5Y06ZNk8fj0Z133um9/4wZM/TEE09o3LhxGjdunNauXauUlBRVVlb6ZKnreDQMQxMmTNDnn3+um266Seeff76ys7N1//33a+fOnXr++efVuXNnzZs3T08++aQcDofS09O9z2vevHm69957FRMToz/84Q+SpM6dO5/Kl+e03XXXXWrXrp0effRR75j98ccfvUWp2uTm5mrr1q268cYb1bVrV33zzTd69dVX9c0332jVqlV+973qqqt05plnKj09XWvXrtWcOXMUHR2tp59+2tvn5ptv1vz58zV58mQNGjRIn332WZ0uHTznnHP02GOPacaMGbr11lu9HyYMGjRIkrzvdRdeeKHS09O1d+9e/f3vf1d+fr7WrVtX48wrqW5j84cfftCVV16pm266SVOmTNEbb7yhG264QUlJSd6ZcPV9n6tJbd8Dx9u5c6e3KPPQQw/JZrNpzpw5tc4AOln+urwGJ1OX9+MTWbp0qd555x3dc889slgseumll5SamqrVq1d731f27t2rgQMHeostnTt3VmZmpm666SYdOXJEv/vd7044Tnr06KGSkhLt2LHDe8ml3W6XVL+fFdLPl2i+++67uuuuu9SpU6dmefkfAAScAaDFe/PNNw1JxuLFi439+/cbP/30k5GRkWF07tzZsFgsxk8//eTtO2rUKKNfv35GeXm5t83j8RiDBg0y+vbt622bMWOGIcl4//33/R7P4/EYhmEYVVVVRkVFhc+xw4cPG126dDGmTp3q0y7JeOSRR/wyb9u27aTPr127dsZ55513wj733HOPIcn46quvDMMwjEceecSo6S3u+Mc9evSo0a5dO+OWW27x6bdnzx4jKirKp33KlCmGJOPBBx/0O++UKVOMXr16eW8vX77ckGT861//8umXlZXl0/7BBx8Ykow1a9ac8PnVpFevXoYk47333vO2lZSUGN26dTMGDBjgbXv88ccNm81mfPfddz73f/DBB42goCCjqKjIMAzD2LZtmyHJiIyMNPbt23fSx3/++ecNScb+/ftr7TNv3jzDbDYby5cv92l/+eWXDUlGfn6+YRiG8f333xtms9m4/PLLDbfb7dO3erzt27fPCA0NNVJSUnz6zJo1y5BkvPHGG962YcOGGZKMf/7zn962iooKo2vXrsakSZO8bS+88IIhyXj33Xe9bU6n0+jTp48hyfj8889P+BpMnz7dkGQcPXr0hP3OPfdcY9iwYbUef/31143w8HCjtLTUMIz6jYsvvvjCkGS88847J+y3YMGCWp9T9VjKysryO1ad6Vhjx441evfu7b1d/bUZP3689+tlGIbx8MMPG5KMKVOmeNvqOh4//PBDQ5LxxBNP+PS78sorDZPJZPzwww/etmHDhhnnnntujc9r/Pjxfu2n6/j3s2Mf79jnWv1+k5SUZFRWVnrbn3nmGUOSsXDhwhM+Tk2v/f/7f//PkGQsW7bM21b9fnf8++7ll19udOzY0Xt7/fr1hiRj2rRpPv0mT55c63M61po1awxJxptvvunTXllZaURHRxsJCQlGWVmZt33RokWGJGPGjBknPG9dxuaxz3ffvn2GxWIx/vCHP3jb6jquanOi74Hjv6533323YTKZjHXr1nnbDh48aHTo0MHv51pd85/oNajJ8T/j6vJ+XBtJhiTjyy+/9Lb9+OOPRlhYmHH55Zd722666SajW7duxoEDB3zu/+tf/9qIioryjtfaxolhGMb48eN9flZWq+vPiuq8ZrPZ+Oabb+r9XAGgLeEyLqAVGT16tDp37qzY2FhdeeWVstls+uijjxQTEyNJOnTokD777DNdddVVOnr0qA4cOKADBw7o4MGDGjt2rL7//nvvlPv33ntP5513nnemz7GqP00OCgryruXi8Xh06NAhVVVV6YILLtDatWsb7HkdPXpUERERJ+xTffzo0aP1Ondubq6Ki4t1zTXXeF+PAwcOKCgoSBdffHGNl6TVZSHoBQsWKCoqSmPGjPE5b1JSkux2u/e81Z92L1q0SC6Xq17ZJal79+4+X6PqS0TWrVunPXv2eLMMGTJE7du398kyevRoud1uv6n6kyZNqtMMiOrsCxcurPUyiQULFuicc87R2Wef7fPY1evLVL8OH374oTwej2bMmOF36VP1eFu8eLEqKyv1u9/9zqfPLbfcosjISH3yySc+97Pb7frNb37jvR0aGqqLLrpIW7du9bZ9+umn6tatm6688kpvm9Vq1a233nrS5y/9vP15cHCw99PpU/Xpp59qxIgR3jVy6jMuqmfuVV9eearOPPNMjR071q/92HV7SkpKdODAAQ0bNkxbt25VSUmJpP99be6++26f2SY1LcJa1/H46aefKigoSPfcc4/P/f/whz/IMAxlZmae1vNtSrfeeqvPrLM77rhDwcHB+vTTT094v2Nf+/Lych04cMC7LllN77G33367z+0hQ4bo4MGDOnLkiCR5H+/41/R0F8v98ssvtW/fPk2bNs1nZuX48eN19tln+31v1ld8fLx3hoj08wyts846y+d7ub7vczWp7XvgeFlZWUpOTvaZvdqhQwfvZb2nkv901eX9+ESSk5OVlJTkvd2zZ09NnDhR2dnZcrvdMgxD7733ni699FIZhuHzGo8dO1YlJSWn9XO/rj8rqg0bNoz1uADgJLiMC2hFXnzxRf3iF79QSUmJ3njjDS1btsxnWvkPP/wgwzD05z//udbtmvft26cePXpoy5YtmjRp0kkf86233tLf/vY3ffvttz5/lJ555pn1yl5SUqKysjLv7dDQUO/lQxERESct4lQfj46Ortfjfv/995JU6+K2kZGRPreDg4O9xbOTnbekpKTWPPv27ZP08y+skyZN0syZM/X8889r+PDhuuyyyzR58uQ6LQrap08fv0s5fvGLX0j6+TK+rl276vvvv9dXX31VawGnOku1un7trr76as2ZM0c333yzHnzwQY0aNUpXXHGFrrzySm8x5vvvv9emTZtO+thbtmyR2Ww+4S/vP/74oyT5XVoRGhqq3r17e49Xi4mJ8Xtt2rdvr6+++srnnDW9hrVdvtEYXC6XcnNzvZcgSfUbF8Z/16850eVAdVHb1z0/P1+PPPKIVq5c6bf+S0lJiaKioryvfd++fX2Od+7c2ecyUkl1Ho8//vijunfv7lforb605fiv9+k4dOiQz+Vm4eHhioqKarDzH/+62O12devW7aRrCB06dEgzZ87Uv//9b7/v0+pC27F69uzpc7v6tT98+LAiIyP1448/ymw2+619drrjvbbvTUk6++yztWLFitM6//HPS/r5uR277lF93+dqUtf3vh9//FHJycl+7X369Kmxf13yn666vB+fyPFjVPr5Z0lpaan2798vs9ms4uJivfrqq3r11VdrPEddXuPa1PVnRbX6/o4BAG0RxR6gFbnooou8u3FddtllGjx4sCZPnqzNmzfLbrd7P+277777av30srZfVmsyf/583XDDDbrssst0//33Kzo6WkFBQUpPT/dbFPpkfvvb33oXWpZ+/mO3enHK+Ph4rV27VhUVFbUWQL766iuFhoaqR48ekmr/w9ftdvvcrn5N5s2bp65du/r1P363E4vFUqdfnD0ej6Kjo/Wvf/2rxuPVv9CaTCZlZGRo1apV+vjjj5Wdna2pU6fqb3/7m1atWnXaM0aqs4wZM0YPPPBAjceri0PV6roDU3h4uJYtW6bPP/9cn3zyibKysvTOO+9o5MiRysnJUVBQkDwej/r166fnnnuuxnPExsbW78nUQ1BQUI3txgkWMq6vjh07qqqqqk6zz2qzYsUKHTlyROPGjfO21WdcVP/B2KlTp9N6LjV93bds2aJRo0bp7LPP1nPPPafY2FiFhobq008/1fPPP39KMwjqOx6bwhVXXKGlS5d6b0+ZMsVn4eG6Ov795XRdddVV+uKLL3T//ffr/PPP976Pp6am1vjaN8WYD4S6PK+GGFeNtftcU3xd6vJ+fDqqx9tvfvMbTZkypcY+/fv3P63z1+dnRUvZKRAAAoliD9BKVRddRowYoVmzZunBBx9U7969JUkhISE17h50rLi4OBUWFp6wT0ZGhnr37q3333/fp7jyyCOP1DvvAw884HPJzbGzAS699FJ98cUXWrBggU+fatu3b9fy5cs1ceJE7y+A1fcvLi72WRj0+NkA1Z9wR0dHn/Q1qY+4uDgtXrxYl1xySZ1+KR04cKAGDhyoJ598Um+//bauvfZa/fvf/9bNN998wvtVz9Y69vX/7rvvJMm7YGVcXJwcDkeDPr9qZrNZo0aN0qhRo/Tcc8/pqaee0p/+9Cd9/vnnGj16tOLi4rRhwwaNGjXqhDNP4uLi5PF4tHHjxloX9u7Vq5eknxdRrR7L0s+7wm3btu2Unl+vXr1UWFjo9xpu3ry5Tvc/++yzJf28K9ep/qHzySefKD4+vsYFRusyLrZt2ybp5Iu5nsrMn48//lgVFRX66KOPfGYnHH9JRfXX5vvvv/f52uzfv99v9kJdx2OvXr20ePFiv0Lat99+6/OYDeFvf/ubT87u3bufsH/79u39doCrrKzU7t27a+z//fffa8SIEd7bDodDu3fv9inwHe/w4cPKy8vTzJkzNWPGDJ9znapevXrJ4/Foy5YtPrNw6jreaxtDx35vHj9LcvPmzSf9Wp3urDSpcd/njterVy/98MMPfu01tdVVQ7wGJ3s/PpGaxtV3330nq9Xq/XAiIiJCbrf7pOc60XOp7Vhdf1YAAOqONXuAVmz48OG66KKL9MILL6i8vFzR0dEaPny4XnnllRr/KNm/f7/3/ydNmqQNGzbogw8+8OtX/Wlk9SeFx346+Z///EcrV66sd9b4+HiNHj3a++/YtQNuu+02de3aVffff7/fGgfl5eXe7V2P/US3uohz7DoNTqfTZ/aQJI0dO1aRkZF66qmnalwb5djXpD6uuuoqud1uPf74437HqqqqvH8oHj582O/T3epiR122/961a5fP1+jIkSP65z//qfPPP987U+mqq67SypUrlZ2d7Xf/4uJiVVVV1fVp+Th06JBf2/HZr7rqKu3cuVOvvfaaX9+ysjI5nU5JP89EM5vNeuyxx/xmLFS/PqNHj1ZoaKj+8Y9/+Lxmr7/+ukpKSuq0o9Dxxo0bp127dikjI8PbVlpaWutlCservpTjyy+/rPdjV/v000/9stdnXBQUFCgqKsq7K1FtbDabJPkVKU6kpu/xkpISvfnmmz79Ro8erZCQEP3f//2fT9+adkCq63gcN26c3G63Zs2a5dPn+eefl8lk8u6o1hCSkpJ83n9OthZIXFyc3xowr776aq0ze1599VWf95fZs2erqqrqhM+hptdeqvk1ravqx/vHP/5xSuesbQxdcMEFio6O1ssvv+wzPjMzM7Vp06aTfm+eytg8XmO9z9Vk7NixWrlypdavX+9tO3ToUK0zOevidF+Durwfn8jKlSt91tz56aeftHDhQqWkpCgoKEhBQUGaNGmS3nvvvRo/CDr2Z+WJnovNZqvxEsS6/qwAANQdM3uAVu7+++/Xr371K82dO1e33367XnzxRQ0ePFj9+vXTLbfcot69e2vv3r1auXKlduzYoQ0bNnjvl5GRoV/96leaOnWqkpKSdOjQIX300Ud6+eWXdd555+mXv/yl3n//fV1++eUaP368tm3bppdfflnx8fFyOBwN9hzat2+vjIwMjRs3TomJibr55psVHx+vPXv2aO7cudq6datmzZqliy++2HuflJQU9ezZUzfddJPuv/9+BQUF6Y033lDnzp1VVFTk7RcZGanZs2fruuuuU2Jion796197+3zyySe65JJL/P7YrIthw4bptttuU3p6utavX6+UlBSFhITo+++/14IFC/T3v/9dV155pd566y299NJLuvzyyxUXF6ejR4/qtddeU2Rk5Ak/9a/2i1/8QjfddJPWrFmjLl266I033tDevXt9/hi///779dFHH+mXv/yld7tfp9Opr7/+WhkZGdq+ffspXQL02GOPadmyZRo/frx69eqlffv26aWXXlJMTIwGDx4sSbruuuv07rvv6vbbb9fnn3+uSy65RG63W99++63effddZWdn64ILLlCfPn30pz/9SY8//riGDBmiK664QhaLRWvWrFH37t2Vnp6uzp0766GHHtLMmTOVmpqqCRMmaPPmzXrppZd04YUX1jjr62RuueUWzZo1S9dff70KCgrUrVs3zZs3T1artU737927txISErR48WJNnTrV59iyZcu8BYH9+/fL6XTqiSeekPTzdtNDhw7Vtm3btGnTJs2ePdvnvvUZF7m5ubr00ktP+mn4+eefr6CgID399NMqKSmRxWLRyJEjT7jOVUpKikJDQ3XppZfqtttuk8Ph0Guvvabo6GifgnHnzp113333KT09Xb/85S81btw4rVu3TpmZmX5jq67j8dJLL9WIESP0pz/9Sdu3b9d5552nnJwcLVy4UL/73e/81p1pSjfffLNuv/12TZo0SWPGjNGGDRuUnZ1d6/dRZWWlRo0apauuuso7ZgcPHqwJEybU+hiRkZEaOnSonnnmGblcLvXo0UM5OTnemVyn4vzzz9c111yjl156SSUlJRo0aJDy8vLqPCMlLi5O7dq108svv6yIiAjZbDZdfPHFOvPMM/X000/rxhtv1LBhw3TNNdd4t14/44wzdO+99540V33H5vEa632uJg888IDmz5+vMWPG6O677/Zuvd6zZ08dOnTolGamnO5rUJf34xNJSEjQ2LFjfbZel6SZM2d6+/zlL3/R559/rosvvli33HKL4uPjdejQIa1du1aLFy/2FpxONE6SkpL0zjvv6Pe//70uvPBC2e12XXrppXX+WQEAqIem3fwLQGOo3t63pm2a3W63ERcXZ8TFxRlVVVWGYRjGli1bjOuvv97o2rWrERISYvTo0cP45S9/aWRkZPjc9+DBg8Zdd91l9OjRwwgNDTViYmKMKVOmeLdd9Xg8xlNPPWX06tXLsFgsxoABA4xFixb5bUNuGKe39Xq17du3G7feeqvRs2dPIzg42Ltd7OLFi2vsX1BQYFx88cVGaGio0bNnT+O5556r9XE///xzY+zYsUZUVJQRFhZmxMXFGTfccIPPVrRTpkwxbDZbjY9V03M2DMN49dVXjaSkJCM8PNyIiIgw+vXrZzzwwAPGrl27DMMwjLVr1xrXXHON0bNnT8NisRjR0dHGL3/5S5/HrU31ttLZ2dlG//79DYvFYpx99tnGggUL/PoePXrUeOihh4w+ffoYoaGhRqdOnYxBgwYZzz77rHdL6Oqt1//617+e9LENwzDy8vKMiRMnGt27dzdCQ0ON7t27G9dcc43f1seVlZXG008/bZx77rmGxWIx2rdvbyQlJRkzZ840SkpKfPq+8cYbxoABA7z9hg0bZuTm5vr0mTVrlnH22WcbISEhRpcuXYw77rjDOHz4sE+f2rbirunr9OOPPxoTJkwwrFar0alTJ+O3v/2tkZWVVedtkJ977jnDbrf7bZNdvTVyTf+qvxdmzZplREVFGS6Xy+e+dR0XmzZtOuH3wPFee+01o3fv3kZQUJDP8zvRFuUfffSR0b9/fyMsLMw444wzjKefftp44403/L6P3G63MXPmTKNbt25GeHi4MXz4cKOwsNBv22rDqNt4rO537733Gt27dzdCQkKMvn37Gn/96199tnc3jKbfet3tdht//OMfjU6dOhlWq9UYO3as8cMPP9S69frSpUuNW2+91Wjfvr1ht9uNa6+91jh48OBJH2fHjh3G5ZdfbrRr186IiooyfvWrXxm7du3yez+tHmvHb7td0/tdWVmZcc899xgdO3Y0bDabcemllxo//fRTnbZeNwzDWLhwoREfH+99Dz52e+133nnH+/3boUMH49prrzV27Nhx0nMaRv3H5rBhw4xhw4b5tNV1XNXkRGOlpjG8bt06Y8iQIYbFYjFiYmKM9PR04x//+IchydizZ89Jz1tT/tpeg5ocv/V6Xd+PayLJuPPOO4358+cbffv29f48r+nx9+7da9x5551GbGysERISYnTt2tUYNWqU8eqrr/r0q22cOBwOY/LkyUa7du0MST7vx3X9WVGdFwBwYibDaOGr9gFos/Ly8jRu3DgNHjxYmZmZ3m3g24ozzjhDCQkJWrRoUaCjtGklJSXq3bu3nnnmGd100031uu+4ceNkt9v17rvvntJj/+53v9OyZctUUFDAOhfN0Ny5c3XjjTdqzZo1zEpoA373u9/p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+7QAAAAAtHImk0n21FSftqpdu3xm+wBAa1Dvy7ieeeYZjR8/XosXL1ZycrIkaeXKlfrpp5/06aef1utcl156qc/tJ598UrNnz9aqVasUExOj119/XW+//bZGjhwpSXrzzTd1zjnnaNWqVRo4cKBycnK0ceNGLV68WF26dNH555+vxx9/XH/84x/16KOPKjQ0tL5PDwAAAEArZunXT8Hduqlq925vmyMrS2H9+gUwFQA0rHoXe4YNG6bNmzfrpZde0rfffitJuuKKKzRt2jR17979lIO43W4tWLBATqdTycnJKigokMvl0ujRo719zj77bPXs2VMrV67UwIEDtXLlSvXr109dunTx9hk7dqzuuOMOffPNNxowYECNj1VRUaGKigrv7SNHjkiSXC6XXC7XKT8HoDmrHtuMcbRmjHO0BYxztAWNPc7DRo+WY968/z3eDz+o9NtvFRIX1yiPB9SE93E0pnoXeySpR48eDbYQ89dff63k5GSVl5fLbrfrgw8+UHx8vNavX6/Q0FC1a9fOp3+XLl20Z88eSdKePXt8Cj3Vx6uP1SY9PV0zZ870a//kk09ktVpP8xkBzdvChQsDHQFodIxztAWMc7QFjTXOTR6PLrZYFHbMB8Bb/vlPFTK7B02otLQ00BHQitW72PPmm2/KbrfrV7/6lU/7ggULVFpaqilTptTrfGeddZbWr1+vkpISZWRkaMqUKVq6dGl9Y9XLQw89pN///vfe20eOHFFsbKzGjx+vjh07NupjA4Hicrm0cOFCTZw4USEhIYGOAzQKxjnaAsY52oKmGOdl0dFyZmR4b3c6eFCXJScruEePRnk84HgHDx4MdAS0YvUu9qSnp+uVV17xa4+Ojtatt95a72JPaGio+vTpI0lKSkrSmjVr9Pe//11XX321KisrVVxc7DO7Z+/everataskqWvXrlq9erXP+ap366ruUxOLxSKLxeLXHhISwi9NaPUY52gLGOdoCxjnaAsac5wHDR2q0sxMGU6nt63is88UPnVqozwecDzew9GY6r0bV1FRkc4880y/9l69eqmoqOi0A3k8HlVUVCgpKUkhISHKy8vzHtu8ebOKioq8C0MnJyfr66+/1r59+7x9cnNzFRkZqfj4+NPOAgAAAKB1Mlsssv13I5hqZWvWqOrAgQAlAoCGU+9iT3R0tL766iu/9g0bNtT7EqiHHnpIy5Yt0/bt2/X111/roYce0pIlS3TttdcqKipKN910k37/+9/r888/V0FBgW688UYlJydr4MCBkqSUlBTFx8fruuuu04YNG5Sdna3p06frzjvvrHHmDgAAAABUsw0fLtOxfzd4PHLm5gYuEAA0kHpfxnXNNdfonnvuUUREhIYOHSpJWrp0qX7729/q17/+db3OtW/fPl1//fXavXu3oqKi1L9/f2VnZ2vMmDGSpOeff15ms1mTJk1SRUWFxo4dq5deesl7/6CgIC1atEh33HGHkpOTZbPZNGXKFD322GP1fVoAAAAA2hiz3S7r4MFyHnM1QWl+vuzjxysoMjKAyQDg9NS72PP4449r+/btGjVqlIKDf767x+PR9ddfr6eeeqpe53r99ddPeDwsLEwvvviiXnzxxVr79OrVS59++mm9HhcAAAAAJMk2ZoycS5ZIbvfPDS6XSj//XBETJwY0FwCcjnoXe0JDQ/XOO+/o8ccf14YNGxQeHq5+/fqpV69ejZEPAAAAABpNUPv2Cr/4YpV98YW3zblkiWxjx8ocFhbAZABw6upd7Kl2xhlnyDAMxcXFeWf4AAAAAEBLY0tJUdnKlZJhSJKM0lKVLl8u+3+XlwCAlqbeCzSXlpbqpptuktVq1bnnnuvdgevuu+/WX/7ylwYPCAAAAACNKaRbN1nOO8+nzbl4sQyXK0CJAOD01HtKzkMPPaQNGzZoyZIlSk1N9baPHj1ajz76qB588MEGDQgAAAAAjc2emqqK9eu9tz3FxSr7z39kHTw4cKHQprndbrkoOOIYISEhCgoKqlPfehd7PvzwQ73zzjsaOHCgTCaTt/3cc8/Vli1b6ns6AAAAAAi40DPPVOhZZ6ly82ZvmyMnR+GDBslkrvcFEcBpcTgc2rFjh4z/XloISJLJZFJMTIzsdvtJ+9a72LN//35FR0f7tTudTp/iDwAAAAC0JPbUVB06ptjj3rtX5evXKzwxMYCp0Na43W7t2LFDVqtVnTt35u9sSJIMw9D+/fu1Y8cO9e3b96QzfOpd7Lngggv0ySef6O6775Yk78CbM2eOkpOTTyEyAAAAAARe6DnnKDg2VlU//eRtc2ZlKWzAAP7gRpNxuVwyDEOdO3dWeHh4oOOgGencubO2b98ul8vV8MWep556Smlpadq4caOqqqr097//XRs3btQXX3yhpUuXnnJoAAAAAAgkk8kke2qqil97zdvm+vFHVX77rSznnBPAZGiLKDDiePUZE/W++HTw4MFav369qqqq1K9fP+Xk5Cg6OlorV65UUlJSfU8HAAAAAM1GWGKigjp39mlzZGcHKA0AnJpTWmksLi5Or732mlavXq2NGzdq/vz56tevX0NnAwAAAIAmZTKbZUtJ8Wmr3LRJldu3ByYQUA/uo0e1+7bbfP65jx5t8hzbt2+XyWRScXFxg5/7qaee0jXXXOO9bTKZtP6YnfQa06OPPqrLLrusTn3r+ho01mtV72LP2rVr9fXXX3tvL1y4UJdddpkefvhhVVZWNmg4AAAAAGhq1uRkmSMjfdqczO4BmtzcuXN1/vnn+7Q9/PDD+n//7/8FJtAx9u3bp2uvvVYxMTGKjIzUgAED9NFHHwU6lle9iz233XabvvvuO0nS1q1bdfXVV8tqtWrBggV64IEHGjwgAAAAADQlU0iIbKNG+bSVr1unqr17A5QIbZXh8ch99OhJ/7l275Zr925V7dnjd46qPXu8x+tyLvfRozI8ngA825bF4XBowIABWrVqlYqLi/XYY4/pmmuu0caNGwMdTdIpLND83XffeStrCxYs0LBhw/T2228rPz9fv/71r/XCCy80cEQAAAAAaFrWYcPkyMyUUV7+c4NhyJGTo3bXXRfYYGhTPE6n9t1332md49Czz9b7PtHPPqugiIiT9nM4HHrwwQf10Ucfqby8XKmpqfq///s/v345OTl6+OGH9f3338tqteryyy/X3/72N+9uY88995xeeOEFHT58WB07dtT06dOVlJSk22+/XS6XS3a7XZK0ceNGvfHGG1q/fr0+/PBDv8f57rvvlJaWpnvvvVd33XWXhg8fruTkZK1du1ZffPGF+vbtq7feesu7DM0ZZ5yhadOm6f3339c333yjxMREzZ8/X7GxsSd97r1799Z9x3xtLr30Up111llatWqV4uPj/frn5ubqD3/4g7Zt2yar1aorrrhCs2fP9h7/+OOPNXPmTB04cECXXXaZXnvtNYWEhJw0R23qPbPHMAx5/lvlW7x4scaNGydJio2N1YEDB045CAAAAAA0F+bwcFmHD/dpK1u5Uu7DhwMTCGiGpk6dqkOHDumrr77Stm3b5HK5dNddd/n1Cw8P12uvvaZDhw4pPz9fn3/+uZ577jlJPxdopk+frpycHB09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kpKSlJaWpsmTJ6u0tNR0Tm1trfLy8tSlSxd17NhRt9xyiw4fPmw6Z//+/Zo0aZISExOVlpame++9V/X19e15KQAAAAAAABHB0rKnoKBAeXl52rhxo9auXSu/36/x48erqqoqdM6MGTP06quv6i9/+YsKCgp08OBBffWrXw19HggENGnSJNXV1endd9/V888/ryVLluihhx6y4pIAAAAAAAAsFWflH7569WrT8ZIlS5SWlqZNmzZpzJgxKi8v13PPPaelS5fq2muvlSQtXrxYAwcO1MaNGzVy5EitWbNGH374od544w11795dWVlZmjdvnmbPnq2HH35Y8fHxVlwaAAAAAACAJSwtexoqLy+XJHXu3FmStGnTJvn9fl133XWhcwYMGKCLL75YGzZs0MiRI7VhwwYNGTJE3bt3D50zYcIETZs2Tdu2bVN2dnajP8fn88nn84WOKyoqJEl+v19+v79Nrg2w2qm1zRqHnbHOEQtY54gFrHPEAtY32lLElD3BYFA/+tGPNGrUKA0ePFiSVFZWpvj4eHXq1Ml0bvfu3VVWVhY658yi59Tnpz5ryoIFCzR37txG81WrVikxMfFCLwWIaCtWrLA6AtDmWOeIBaxzxALWOeysurra6giwsYgpe/Ly8rR161YVFha2+Z91//33a+bMmaHjiooKZWZmatKkSerSpUub//mAFfx+v1asWKGbb75Zbrfb6jhAm2CdIxawzhELWOeIBceOHbM6AmwsIsqe6dOna+XKlVq/fr169uwZmqenp6uurk4nTpww3d1z+PBhpaenh855//33Td936m1dp85pyOPxyOPxNJq73W7+MoHtsc4RC1jniAWsc8QC1jnsjLWNtmTp27gMw9D06dO1fPlyvfXWW+rdu7fp8yuuuEJut1tvvvlmaFZaWqr9+/crNzdXkpSbm6stW7boyJEjoXPWrl2r5ORkDRo0qH0uBAAAAAAAIEJYemdPXl6eli5dqhUrVigpKSn0jJ2UlBQlJCQoJSVFt99+u2bOnKnOnTsrOTlZd999t3JzczVy5EhJ0vjx4zVo0CBNmTJFCxcuVFlZmebMmaO8vLwm794BAAAAAACwM0vLnqefflqSNG7cONN88eLF+s53viNJeuKJJ+R0OnXLLbfI5/NpwoQJeuqpp0LnulwurVy5UtOmTVNubq46dOigqVOn6pFHHmmv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4YYbVFlZadk1AgAAxBK2cQEAEINWrlypjh07qr6+Xj6fT06nU08++aR8Pp/mz5+vN954Q7m5uZKkPn36qLCwUM8884zGjh2rRYsWKSUlRcuWLZPb7ZYkXXrppaHvvvbaa01/1rPPPqtOnTqpoKBAX/nKV9rvIgEAAGIUZQ8AADHommuu0dNPP62qqio98cQTiouL0y233KJt27apurpa119/ven8uro6ZWdnS5JKSko0evToUNHT0OHDhzVnzhytW7dOR44cUSAQUHV1tfbv39/m1wUAAADKHgAAYlKHDh3Ur18/SdLvf/97DRs2TM8995wGDx4sSVq1apUuuugi0+/xeDySpISEhHN+99SpU3Xs2DH98pe/VK9eveTxeJSbm6u6uro2uBIAAAA0RNkDAECMczqdeuCBBzRz5kx99NFH8ng82r9/v8aOHdvk+UOHDtXzzz8vv9/f5N0977zzjp566indcMMNkqQDBw7o6NGjbXoNAAAAOI0HNAMAAP3nf/6nXC6XnnnmGc2aNUszZszQ888/r927d6uoqEi//vWv9fzzz0uSpk+froqKCn3jG9/QP//5T+3cuVN/+MMfVFpaKknq37+//vCHP2j79u167733dOutt573biAAAAC0Hu7sAQAAiouL0/Tp07Vw4ULt3btX3bp104IFC7Rnzx516tRJOTk5euCBByRJXbp00VtvvaV7771XY8eOlcvlUlZWlkaNGiVJeu6553TnnXcqJydHmZmZmj9/vmbNmmXl5QEAAMQUh2EYhtUhAAAAAAAA0DrYxgUAAAAAAGAjlD0AAAAAAAA2QtkDAAAAAABgI5Q9AAAAAAAANkLZAwAAAAAAYCOUPQAAAAAAADZC2QMAAAAAAGAjlD0AAAAAAAA2QtkDAAAAAABgI5Q9AAAAAAAANkLZAwAAAAAAYCP/H6qbL5L86i0+AAAAAElFTkSuQmCC \ No newline at end of file +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BAwe0fv16b8OyKvMiNjZWr7zyijZt2lThCqJhw4bpvvvu09/+9jc9+uijuvDCCyXJ+1/p5KEq1157rW6//Xbdeuut6t69u6STh6P16tVLEyZMUFBQkL744gvddddd8ng8uvvuu723f/zxx/XMM89o3LhxGjdunNatW6dRo0apuLjYJ0tl56NhGJowYYLS0tJ08803q2/fvkpOTtaDDz6oX375Ra+88oqioqI0e/ZsPfvss8rLy9Pzzz/vfV6zZ8/W/fffr7Zt2+r3v/+9JCkqKupcvjzn7Z577lFkZKSefPJJ75z9+eefvU2piixbtkw//fSTbrrpJrVs2VKbNm3SO++8o02bNmnt2rV+t50yZYqio6P1/PPPa926dZo5c6aaN2+uF154wVtzyy236KOPPtKvf/1rDR48WKmpqZU6dPDCCy/UU089pccff1y33Xab98OEwYMHS5L3ve6SSy7R888/r4MHD+q1117T6tWrtX79+nJXXkmVm5s//vijJk+erJtvvlk33HCD3n//fd14442KjY31roSr6vtceSr6HjjdL7/84m3KPPLII3I6nZo5c2aFK4DOlr8yr8HZVOb9+ExWrlypuXPn6r777pPdbtebb76pMWPG6Ouvv/a+rxw8eFCDBg3yNluioqK0ZMkS3XzzzTpx4oR++9vfnnGetGnTRsePH9fevXu9h1yGhoZKqtrPCunkIZoff/yx7rnnHjVr1qxOHv4HAAFnAKj3PvjgA0OSsXz5cuPQoUPGnj17jPnz5xtRUVGG3W439uzZ461NSkoyYmJijMLCQu+Yx+MxBg8ebHTt2tU79vjjjxuSjE8//dTv8Twej2EYhlFSUmIUFRX57Dt27JjRokULY9q0aT7jkownnnjCL/POnTvP+vwiIyONiy666Iw19913nyHJ2Lhxo2EYhvHEE08Y5b3Fnf64ubm5RmRkpHHrrbf61B04cMCIiIjwGb/hhhsMScbDDz/sd7833HCD0aFDB+/2V199ZUgy/vnPf/rUffnllz7jn332mSHJyMzMPOPzK0+HDh0MScYnn3ziHTt+/LjRqlUr4+KLL/aOPf3004bT6TR++OEHn9s//PDDhsViMXbv3m0YhmHs3LnTkGSEh4cb2dnZZ338V155xZBkHDp0qMKa2bNnG2az2fjqq698xt966y1DkrF69WrDMAxj+/bthtl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hhx/qzTff1JVXXqnOnTsrNzdX7777rsLDw8/4qX+Zbt266eabb1ZmZqZatGih999/XwcPHvT5Y/zBBx/UwoULdfnll3sv9+tyufTdd99p/vz52rVr1zkdAvTUU09p1apVuuyyy9ShQwdlZ2frzTffVNu2bTVkyBBJ0m9+8xt9/PHHuuOOO5SWlqZLL71UpaWl2rp1qz7++GMlJyerf//+6tKli/74xz/q6aef1tChQ3XVVVfJbrcrMzNTrVu31vPPP6+oqCg98sgjmj59usaMGaMJEyZo27ZtevPNN3XJJZeUu+rrbG699Va9/vrruv766/Xtt9+qVatWmj17thwOR6Vu36lTJ/Xu3VvLly/XtGnTfPatWrXK2xA4dOiQXC6XnnnmGUknLzc9bNgw7dy5U1u2bNGMGTN8bluVebFs2TKNHz/+rJ+G9+3bVxaLRS+88IKOHz8uu92uxMTEM57natSoUbLZbBo/frxuv/125eXl6d1331Xz5s19GsZRUVF64IEH9Pzzz+vyyy/XuHHjtH79ei1ZssRvblV2Po4fP14JCQn64x//qF27dumiiy7S0qVLtWDBAv32t7/1O+9Mbbrlllt0xx13aNKkSRo5cqSysrKUnJxc4fdRcXGxkpKSNGXKFO+cHTJkiCZMmFDhY4SHh2vYsGF68cUX5Xa71aZNGy1dutS7kutc9O3bV9dee63efPNNHT9+XIMHD1ZKSkqlV6R07txZkZGReuuttxQWFian06mBAwcqOjpaL7zwgm666SbFx8fr2muv9V56vWPHjrr//vvPmquqc/N0NfU+V56HHnpIH330kUaOHKl7773Xe+n19u3b6+jRo+e0MuV8X4PKvB+fSe/evTV69GifS69L0vTp0701f/7zn5WWlqaBAwfq1ltvVc+ePXX06FGtW7dOy5cv9zaczjRPYmNjNXfuXP3ud7/TJZdcotDQUI0fP77SPysAAFVQuxf/AlATyi7vW95lmktLS43OnTsbnTt3NkpKSgzDMIwdO3YY119/vdGyZUvDarUabdq0MS6//HJj/vz5Prc9cuSIcc899xht2rQxbDab0bZtW+OGG27wXnbV4/EYzz33nNGhQwfDbrcbF198sfHvf//b7zLkhnF+l14vs2vXLuO2224z2rdvbwQFBXkvF7t8+fJy67/99ltj4MCBhs1mM9q3b2+8/PL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r109ffvllTecFAAAAgEpzjhzps23k56tg9eoApQGA2lGplT2n+u1vf6u33npLQ4YM8Y6NHj1aDodDt912m7Zs2VKtAQEAAADgXFlbt5a9Tx8VbdzoHXMtXy7H8OEyWSwBTAYANafKJ2jesWOHIiMj/cYjIiK0a9euaogEAAAAANUndPRon+3So0dV+M03AUoDADWvys2eSy65RL/73e908OBB79jBgwf14IMPasCAAdUaDgAAAADOl7VzZ1k7dfIZy1u61Oc8pADQkFS52fP+++9r//79at++vbp06aIuXbqoffv2+uWXX/Tee+9V6b5mzJihPn36KDw8XOHh4YqLi9OSJUu8+wsLC3X33XeradOmCg0N1aRJk3yaTJK0e/duXXbZZXI4HGrevLkefPBBlZSUVPVpAQAAAGigTCaT3+qekr17Vbx5c4ASAUDNqvI5e7p06aKNGzdq2bJl2rp1qyTpwgsv1IgRI3yuylUZbdu21Z///Gd17dpVhmHoww8/1BVXXKH169erV69euv/++7Vo0SLNmzdPERERuueee3TVVVdp9X9PqFZaWqrLLrtMLVu21Jo1a7R//35df/31slqteu6556r61AAAAAA0UPY+fWRp0UKlp3x4nJecLHuvXgFMBQA1o8rNHulkZ3zUqFEaNWrUeT34+PHjfbafffZZzZgxQ2vXrlXbtm313nvvac6cOUpMTJQkffDBB7rwwgu1du1aDRo0SEuXLtXmzZu1fPlytWjRQn379tXTTz+tP/zhD3ryySdls9nOKx8AAACAhsFkNit01Cgdnz3bO1a8bZuKd+2SrWPHwAUDgBpwTs2elJQUpaSkKDs7Wx6Px2ff+++/f05BSktLNW/ePLlcLsXFxenbb7+V2+3WiBEjvDU9evRQ+/btlZGRoUGDBikjI0MxMTFq0aKFt2b06NG68847tWnTJl188cXlPlZRUZGKioq82ydOnJAkud1uud3uc8oP1HVlc5s5joaMeY7GgHmOxqCm5nlQv34yLVgg47+//0tSbnKywqdNq9bHASqD93HUpCo3e6ZPn66nnnpK/fv3V6tWrap86NbpvvvuO8XFxamwsFChoaH67LPP1LNnT23YsEE2m83vyl8tWrTQgQMHJEkHDhzwafSU7S/bV5Hnn39e06dP9xtftGiRHA7HeT0foK5bsGBBoCMANY55jsa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iY2N1xx13yO12K/S/V77bvHmz3n//fW3YsEGff/653+P88MMPGjt2rO6//37dc889Gj58uOLi4rRu3TqtWbNGXbt21Ycffug9DU3Hjh1111136dNPP9WmTZvUr18/ffTRR2rXrt1Zn3unTp30wClfm/Hjx6t79+5au3atevbs6Ve/bNky/f73v9fOnTvlcDh01VVXacaMGd79X3zxhaZPn67Dhw9r4sSJevfdd2W1Ws+aoyJVXtljGIY8/+3yLV++XOPGjZMktWvXTocPHz7nIAAAAABQl5lMJr/VPUBjNm3aNB09elQbN27Uzp075Xa7dc899/jVhYSE6N1339XRo0e1evVqpaWl6eWXX5Z0skHzpz/9SUuXLlVubq7+85//aMCAAbr44ov11ltvKSYmRnl5ecrLy1P79u0rzPL1118rMTFRzz//vE+G2bNn68UXX9SxY8fUv39/3XvvvT63++ijj/T//t//06FDh+R0OvXYY4+d02uRnZ2tLVu2qE+fPuXuv+GGG/Tggw8qNzdXP/30k37zm9/47F+yZInWr1+vzZs3KyUlRf/85z/PKUeZKjd7+vfvr2eeeUazZ8/WypUrddlll0mSdu7cqRYtWpxXGAAAAACoy2xdush8wQXl7vOcchgM0NAdOnRIn3zyid544w1FRkbK6XTqqaee0ty5c1V62rmshg4dqosvvlgWi0WdOnXS7bffrhUrVkiSLBaLDMPQpk2bVFBQoBYtWlTYMKnIl19+qYkTJ+of//iHpkyZ4rPvuuuu00UXXaSgoCDdcMMN+vbbb33233XXXYqOjlZwcLCmTp3qt78yiouLdc0112jKlCnq379/uTVWq1U//vijt6k0ePBgn/2PP/64wsLC1Lp1a40ZM+accpyqys2eV199VevWrdM999yjP/7xj+rSpYskaf78+X5hAQAAAKAhyX7oIXmOHi133+Hp05X9wAPnfdgNUB/s2rVLHo9H0dHRioyMVGRkpC655BKZzWYdOO3cQZmZmRoxYoRatGih8PBwPfroo94jgzp37qwPP/xQr7/+ulq0aKFRo0ZV+epar776qhISEpSYmOi3r2XLlt7/dzqdysvLO+P+3P82a5977jmFhoYqNDRUY8eOrfCxi4uLNXnyZDkcDr3730M6y/PZZ5/p+++/V/fu3XXxxRfr448/rlSOc1Xlc/b06dP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55593cHKg+Vq6zo/avXu37rjjDl100UUdlBRovZau80AgoLFjx2r37t169dVXVVJSot/97nfq06dPBycHmq+l63zJkiW66667NGfOHBUXF+v555/Xyy+/rHvuuaeDkwPNV1NTo7POOksLFy5s1vG7du3SpEmTdMkll2jz5s366U9/qptvvll//vOf2zkpnMrxr14///zzdd555+nJJ5+UJIXDYWVlZenHP/6x7rrrrkbHf/e731VNTY1WrFgRmY0aNUojR47UM88802G5gZZo6TpvKBQKqUuXLnryySd1ww03tHdcoFVas85DoZBGjx6tH/zgB/rwww916NChZv3LGmCXlq7zZ555Rv/3f/+nrVu3yu12d3RcoFVaus5nzJih4uJivfvuu5HZz372M/3lL39RQUFBh+UGWsswDC1btuyEVxjPnj1bb7/9tuUig+9973s6dOiQVq1a1QEp4TSOvrInEAho06ZNuvzyyyOzhIQEXX755dqwYUOT37NhwwbL8ZI0fvz44x4P2K0167yh2tpaBYNBde3atb1iAqektev84YcfVkZGhm666aaOiAmcktas8zfffFO5ubnKy8tTZmamRowYoXnz5ikUCnVUbKBFWrPOv/GNb2jTpk2RW7127typlStXauLEiR2SGegI/B6KtpZod4D2dODAAYVCIWVmZlrmmZmZ2rp1a5PfU15e3uTx5eXl7ZYTOBWtWecNzZ49W7179270FwwQLVqzzgsKCvT8889r8+bNHZAQOHWtWec7d+7U2rVrdd1112nlypXasWOHfvSjHykYDGrOnDkdERtokdas82uvvVYHDhzQhRdeKNM0VV9fr1tvvZXbuOAox/s9tKqqSkeOHFFycrJNyRCrHH1lD4CTe/TRR7V06VItW7ZMSUlJdscB2kR1dbWmTZum3/3ud+revbvdcYB2Ew6HlZGRod/+9rc699xz9d3vflf33nsvt57DUd5//33NmzdPTz31lD7++GO9/vrrevvttzV37ly7owFA1HL0lT3du3eXy+VSRUWFZV5RUaGePXs2+T09e/Zs0fGA3Vqzzo96/PHH9eijj2rNmjU688wz2zMmcEpaus5LS0u1e/duXXnllZFZOByWJCUmJqqkpEQDBw5s39BAC7Xmz/NevXrJ7XbL5XJFZtnZ2SovL1cgEJDH42nXzEBLtWad33///Zo2bZpuvvlmSdIZZ5yhmpoa3XLLLbr33nuVkMC/XyP2He/30LS0NK7qQas4+k9Gj8ejc8891/Iwt3A4rHfffVe5ublNfk9ubq7leEnKz88/7vGA3VqzziVpwYIFmjt3rlatWqWvfe1rHREVaLWWrvNhw4bp008/1ebNmyNfV111VeQNF1lZWR0ZH2iW1vx5fsEFF2jHjh2RMlOStm3bpl69elH0ICq1Zp3X1tY2KnSOFpwOf9cM4gi/h6LNmQ63dOlS0+v1mosXLzaLiorMW265xezcubNZXl5umqZpTps2zbzrrrsix3/00UdmYmKi+fjjj5vFxcXmnDlzTLfbbX766ad2nQJwUi1d548++qjp8XjMV1991dy3b1/kq7q62q5TAE6qpeu8oenTp5uTJ0/uoLRA67R0nZeVlZk+n8+cMWOGWVJSYq5YscLMyMgw//d//9euUwBOqqXrfM6cOabP5zNfeuklc+fOnebq1avNgQMHmldffbVdpwCcVHV1tfnJJ5+Yn3zyiSnJ/MUvfmF+8skn5j//+U/TNE3zrrvuMqdNmxY5fufOnWZKSop55513msXFxebChQtNl8tlrlq1yq5TQIxz9G1c0pevUv/3v/+tBx54QOXl5Ro5cqRWrVoVefhVWVmZ5V8KvvGNb2jJkiW67777dM8992jw4MF64403NGLECLtOATiplq7zp59+WoFAQN/5zncsnzNnzhw9+OCDHRkdaLaWrnMgFrV0nWdlZenPf/6zZs6cqTPPPFN9+vTRT37yE82ePduuUwBOqqXr/L777pNhGLrvvvv0+eefq0ePHrryyiv1yCOP2HUKwEn9/e9/1yWXXBLZnjVrliRp+vTpWrx4sfbt26eysrLI/gEDBujtt9/WzJkz9atf/Up9+/bVc889p/Hjx3d4djiDYZpc+wgAAAAAAOAU/BMoAAAAAACAg1D2AAAAAAAAOAhlDwAAAAAAgINQ9gAAAAAAADgIZQ8AAAAAAICDUPYAAAAAAAA4CGUPAAAAAACAg1D2AAAAAAAAOAhlDwAA6HCGYeiNN96QJO3evVuGYWjz5s22ZgIAAHAKyh4AAOLM97//fRmGIcMw5Ha7NWDAAP3P//yP6urq7I4GAACANpBodwAAANDxJkyYoEWLFikYDGrTpk2aPn26DMPQY489Znc0AAAAnCKu7AEAIA55vV717NlTWVlZmjJlii6//HLl5+dLksLhsObPn68BAwYoOTlZZ511ll599VXL9xcWFuqKK65QWlqafD6fLrroIpWWlkqS/va3v2ns2LHq3r270tPTNWbMGH388ccdfo4AAADxirIHAIA499lnn2n9+vXyeDySpPnz5+vFF1/UM888o8LCQs2cOVPXX3+91q1bJ0n6/PPPNXr0aHm9Xq1du1abNm3SD37wA9XX10uSqqurNX36dBUUFGjjxo0aPHiwJk6cqOrqatvOEQAAIJ5wGxcAAHFoxYoVSk1NVX19vfx+vxISEvTkk0/K7/dr3rx5WrNmjXJzcyVJp59+ugoKCvTss89qzJgxWrhwodLT07V06VK53W5J0pAhQyKffemll1p+1m9/+1t17txZ69at0xVXXNFxJwkAABCnKHsAAIhDl1xyiZ5++mnV1NToiSeeUGJioqZOnarCwkLV1tZq7NixluMDgYDOPvtsSdLmzZt10UUXRYqehioqKnTffffp/fff1/79+xUKhVRbW6uysrJ2Py8AAABQ9gAAEJc6deqkQYMGSZJ+//vf66yzztLzzz+vESNGSJLefvtt9enTx/I9Xq9XkpScnHzCz54+fboOHjyoX/3qVzrttNPk9XqVm5urQCDQDmcCAACAhih7AACIcwkJCbrnnns0a9Ysbdu2TV6vV2VlZRozZkyTx5955pl64YUXFAwGm7y656OPPtJTTz2liRMnSpL27NmjAwcOtOs5AAAA4Bge0AwAAPRf//VfcrlcevbZZ3XHHXdo5syZeuGFF1RaWqqPP/5Yv/nNb/TCCy9IkmbMmKGqqip973vf09///ndt375df/jDH1RSUiJJGjx4sP7whz+ouLhYf/nLX3Tddded9GogAAAAtB2u7AEAAEpMTNSMGTO0YMEC7dq1Sz169ND8+fO1c+dOde7cWeecc47uueceSVK3bt20du1a3XnnnRozZoxcLpdGjhypCy64QJL0/PPP65ZbbtE555yjrKwszZs3T3fccYedpwcAABBXDNM0TbtDAAAAAAAAoG1wGxcAAAAAAICDUPYAAAAAAAA4CGUPAAAAAACAg1D2AAAAAAAAOAhlDwAAAAAAgINQ9gAAAAAAADgIZQ8AAAAAAICDUPYAAAAAAAA4CGUPAAAAAACAg1D2AAAAAAAAOAhlDwAAAAAAgIP8P5lAarTkl/EnAAAAAElFTkSuQmCC \ No newline at end of file diff --git a/docs/pages/performance/fashion-mnist/plot.png b/docs/pages/performance/fashion-mnist/plot.png index c0b8d3d9344d3cddabc5083bc4147ba63176a6f7..baf59b33852144301966a3d097cb69a45f90bd7b 100644 GIT binary patch literal 46812 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

MQK?%V47@rtbl@z0+>uR}Tw@TAOZIZ}LQ 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 literal 46623 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 diff --git a/docs/pages/performance/fashion-mnist/results.md b/docs/pages/performance/fashion-mnist/results.md index 69ebb8b3a..eea9736e5 100644 --- a/docs/pages/performance/fashion-mnist/results.md +++ b/docs/pages/performance/fashion-mnist/results.md @@ -1,10 +1,10 @@ |Model|Parameters|Recall|Queries per Second| |---|---|---|---| -|eknn-l2lsh|L=100 k=4 w=1024 candidates=500 probes=0|0.379|383.178| -|eknn-l2lsh|L=100 k=4 w=1024 candidates=1000 probes=0|0.447|324.668| -|eknn-l2lsh|L=100 k=4 w=1024 candidates=500 probes=3|0.635|293.685| -|eknn-l2lsh|L=100 k=4 w=1024 candidates=1000 probes=3|0.717|261.210| -|eknn-l2lsh|L=100 k=4 w=2048 candidates=500 probes=0|0.767|334.495| -|eknn-l2lsh|L=100 k=4 w=2048 candidates=1000 probes=0|0.847|289.825| -|eknn-l2lsh|L=100 k=4 w=2048 candidates=500 probes=3|0.922|228.624| -|eknn-l2lsh|L=100 k=4 w=2048 candidates=1000 probes=3|0.960|204.063| +|eknn-l2lsh|L=100 k=4 w=1024 candidates=500 probes=0|0.378|375.370| +|eknn-l2lsh|L=100 k=4 w=1024 candidates=1000 probes=0|0.447|320.039| +|eknn-l2lsh|L=100 k=4 w=1024 candidates=500 probes=3|0.635|294.600| +|eknn-l2lsh|L=100 k=4 w=1024 candidates=1000 probes=3|0.716|257.913| +|eknn-l2lsh|L=100 k=4 w=2048 candidates=500 probes=0|0.767|332.779| +|eknn-l2lsh|L=100 k=4 w=2048 candidates=1000 probes=0|0.846|289.472| +|eknn-l2lsh|L=100 k=4 w=2048 candidates=500 probes=3|0.921|220.716| +|eknn-l2lsh|L=100 k=4 w=2048 candidates=1000 probes=3|0.960|204.668|