This repository has been archived by the owner on Sep 29, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from fornit1917/20-hashes-indexing-by-vp-tree-…
…begin 20 hashes indexing by vp tree begin
- Loading branch information
Showing
9 changed files
with
473 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Xunit; | ||
|
||
namespace ImageBase.HashBase.UnitTests | ||
{ | ||
public class HashBaseUnitTests | ||
{ | ||
public static IEnumerable<object[]> Strings => | ||
new List<object[]> | ||
{ | ||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ | ||
new HashItem() { ObjectId = 1, Hash = 1 }, | ||
new HashItem() { ObjectId = 2, Hash = 3 }, | ||
new HashItem() { ObjectId = 3, Hash = 7 }, | ||
new HashItem() { ObjectId = 4, Hash = 37 }, | ||
new HashItem() { ObjectId = 5, Hash = 53 }, | ||
new HashItem() { ObjectId = 6, Hash = 63 }, | ||
new HashItem() { ObjectId = 7, Hash = 127 }, | ||
new HashItem() { ObjectId = 8, Hash = 255 }, | ||
new HashItem() { ObjectId = 9, Hash = 511}, | ||
new HashItem() { ObjectId = 10, Hash = 512}, | ||
new HashItem() { ObjectId = 11, Hash = 500}, | ||
}, | ||
37, 2, 10,new List<long>() { 1, 3, 4, 5 } | ||
}, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ | ||
new HashItem() { ObjectId = 1, Hash = 1 }, | ||
new HashItem() { ObjectId = 2, Hash = 3 }, | ||
new HashItem() { ObjectId = 3, Hash = 7 }, | ||
new HashItem() { ObjectId = 4, Hash = 37 }, | ||
new HashItem() { ObjectId = 5, Hash = 53 }, | ||
new HashItem() { ObjectId = 6, Hash = 63 }, | ||
new HashItem() { ObjectId = 7, Hash = 127 }, | ||
new HashItem() { ObjectId = 8, Hash = 255 }, | ||
new HashItem() { ObjectId = 9, Hash = 511}, | ||
new HashItem() { ObjectId = 10, Hash = 512}, | ||
new HashItem() { ObjectId = 11, Hash = 500}, | ||
}, | ||
511, 2, 10,new List<long>() { 7, 8, 9 } }, | ||
|
||
new object[] { | ||
new List<HashItem>() | ||
{ | ||
new HashItem() { ObjectId = 1, Hash = 1 }, | ||
new HashItem() { ObjectId = 2, Hash = 3 }, | ||
new HashItem() { ObjectId = 3, Hash = 7 }, | ||
new HashItem() { ObjectId = 4, Hash = 37 }, | ||
new HashItem() { ObjectId = 5, Hash = 53 }, | ||
new HashItem() { ObjectId = 6, Hash = 63 }, | ||
new HashItem() { ObjectId = 7, Hash = 127 }, | ||
new HashItem() { ObjectId = 8, Hash = 255 }, | ||
new HashItem() { ObjectId = 9, Hash = 511}, | ||
new HashItem() { ObjectId = 10, Hash = 512}, | ||
new HashItem() { ObjectId = 11, Hash = 500}, | ||
}, | ||
31, 3, 10,new List<long>() { 2, 3, 5, 6, 7, 8 } }, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ //Hashes | ||
new HashItem() { ObjectId = 1, Hash = 1 }, //1 | ||
new HashItem() { ObjectId = 2, Hash = 3 }, //11 | ||
new HashItem() { ObjectId = 3, Hash = 7 }, //11 | ||
new HashItem() { ObjectId = 4, Hash = 15 }, //111 | ||
new HashItem() { ObjectId = 5, Hash = 31 }, //1111 | ||
new HashItem() { ObjectId = 6, Hash = 63 }, //11111 | ||
new HashItem() { ObjectId = 7, Hash = 127 }, //111111 | ||
new HashItem() { ObjectId = 8, Hash = 255 }, //1111111 | ||
new HashItem() { ObjectId = 9, Hash = 511}, //11111111 | ||
new HashItem() { ObjectId = 10, Hash = 1023 },//111111111 | ||
new HashItem() { ObjectId = 11, Hash = 2047 },//1111111111 | ||
new HashItem() { ObjectId = 12, Hash = 4095 },//11111111111 | ||
new HashItem() { ObjectId = 13, Hash = 8191 },//111111111111 | ||
}, | ||
511, 1, 100,new List<long>() { 8, 9, 10 }, | ||
}, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ //Hashes | ||
new HashItem() { ObjectId = 1, Hash = 1 }, //1 | ||
new HashItem() { ObjectId = 2, Hash = 3 }, //11 | ||
new HashItem() { ObjectId = 3, Hash = 7 }, //11 | ||
new HashItem() { ObjectId = 4, Hash = 15 }, //111 | ||
new HashItem() { ObjectId = 5, Hash = 31 }, //1111 | ||
new HashItem() { ObjectId = 6, Hash = 63 }, //11111 | ||
new HashItem() { ObjectId = 7, Hash = 127 }, //111111 | ||
new HashItem() { ObjectId = 8, Hash = 255 }, //1111111 | ||
new HashItem() { ObjectId = 9, Hash = 511}, //11111111 | ||
new HashItem() { ObjectId = 10, Hash = 1023 },//111111111 | ||
new HashItem() { ObjectId = 11, Hash = 2047 },//1111111111 | ||
new HashItem() { ObjectId = 12, Hash = 4095 },//11111111111 | ||
new HashItem() { ObjectId = 13, Hash = 8191 },//111111111111 | ||
}, | ||
511, 2, 100,new List<long>() { 7, 8, 9, 10, 11 } | ||
}, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ //Hashes | ||
new HashItem() { ObjectId = 1, Hash = 1 }, //1 | ||
new HashItem() { ObjectId = 2, Hash = 3 }, //11 | ||
new HashItem() { ObjectId = 3, Hash = 7 }, //11 | ||
new HashItem() { ObjectId = 4, Hash = 15 }, //111 | ||
new HashItem() { ObjectId = 5, Hash = 31 }, //1111 | ||
new HashItem() { ObjectId = 6, Hash = 63 }, //11111 | ||
new HashItem() { ObjectId = 7, Hash = 127 }, //111111 | ||
new HashItem() { ObjectId = 8, Hash = 255 }, //1111111 | ||
new HashItem() { ObjectId = 9, Hash = 511}, //11111111 | ||
new HashItem() { ObjectId = 10, Hash = 1023 },//111111111 | ||
new HashItem() { ObjectId = 11, Hash = 2047 },//1111111111 | ||
new HashItem() { ObjectId = 12, Hash = 4095 },//11111111111 | ||
new HashItem() { ObjectId = 13, Hash = 8191 },//111111111111 | ||
}, | ||
31, 4, 100,new List<long>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 } | ||
}, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ //Hashes | ||
new HashItem() { ObjectId = 1, Hash = 1 }, //1 | ||
new HashItem() { ObjectId = 2, Hash = 3 }, //11 | ||
new HashItem() { ObjectId = 3, Hash = 7 }, //11 | ||
new HashItem() { ObjectId = 4, Hash = 15 }, //111 | ||
new HashItem() { ObjectId = 5, Hash = 31 }, //1111 | ||
new HashItem() { ObjectId = 6, Hash = 63 }, //11111 | ||
new HashItem() { ObjectId = 7, Hash = 127 }, //111111 | ||
new HashItem() { ObjectId = 8, Hash = 255 }, //1111111 | ||
new HashItem() { ObjectId = 9, Hash = 511}, //11111111 | ||
new HashItem() { ObjectId = 10, Hash = 1023 },//111111111 | ||
new HashItem() { ObjectId = 11, Hash = 2047 },//1111111111 | ||
new HashItem() { ObjectId = 12, Hash = 4095 },//11111111111 | ||
new HashItem() { ObjectId = 13, Hash = 8191 },//111111111111 | ||
}, | ||
31, 4, 3,new List<long>() { 4, 5, 6 } | ||
}, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ | ||
//Hashes | ||
new HashItem() {ObjectId = 1, Hash = 1}, //1 | ||
new HashItem() {ObjectId = 2, Hash = 3}, //11 | ||
new HashItem() {ObjectId = 3, Hash = 7}, //11 | ||
new HashItem() {ObjectId = 4, Hash = 15}, //111 | ||
new HashItem() {ObjectId = 5, Hash = 31}, //1111 | ||
new HashItem() {ObjectId = 6, Hash = 63}, //11111 | ||
new HashItem() {ObjectId = 7, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 14, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 15, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 16, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 17, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 8, Hash = 255}, //1111111 | ||
new HashItem() {ObjectId = 9, Hash = 511}, //11111111 | ||
new HashItem() {ObjectId = 10, Hash = 1023}, //111111111 | ||
new HashItem() {ObjectId = 11, Hash = 2047}, //1111111111 | ||
new HashItem() {ObjectId = 12, Hash = 4095}, //11111111111 | ||
new HashItem() {ObjectId = 13, Hash = 8191}, //111111111111 | ||
}, | ||
127, 4, 100, new List<long>() {3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17} | ||
}, | ||
|
||
new object[] | ||
{ | ||
new List<HashItem>() | ||
{ | ||
//Hashes | ||
new HashItem() {ObjectId = 1, Hash = 1}, //1 | ||
new HashItem() {ObjectId = 2, Hash = 3}, //11 | ||
new HashItem() {ObjectId = 3, Hash = 7}, //11 | ||
new HashItem() {ObjectId = 4, Hash = 15}, //111 | ||
new HashItem() {ObjectId = 5, Hash = 31}, //1111 | ||
new HashItem() {ObjectId = 6, Hash = 63}, //11111 | ||
new HashItem() {ObjectId = 7, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 14, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 15, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 16, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 17, Hash = 127}, //111111 | ||
new HashItem() {ObjectId = 8, Hash = 255}, //1111111 | ||
new HashItem() {ObjectId = 9, Hash = 511}, //11111111 | ||
new HashItem() {ObjectId = 10, Hash = 1023}, //111111111 | ||
new HashItem() {ObjectId = 11, Hash = 2047}, //1111111111 | ||
new HashItem() {ObjectId = 12, Hash = 4095}, //11111111111 | ||
new HashItem() {ObjectId = 18, Hash = 4095}, //11111111111 | ||
new HashItem() {ObjectId = 13, Hash = 8191}, //111111111111 | ||
}, | ||
8191, 6, 100, new List<long>() {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18} | ||
}, | ||
}; | ||
|
||
[Theory] | ||
[MemberData(nameof(Strings))] | ||
public void CalculatesForSearch(IEnumerable<HashItem> hashesInput, long hashSearch, int searchRadius, int limit, List<long> expectedIDs) | ||
{ | ||
//check 100 times because vantage index can be different | ||
for (int i = 0; i < 100; i++) | ||
{ | ||
VPTreeHashBase vpTreeHashBase = new VPTreeHashBase(); | ||
vpTreeHashBase.CreateIndex(hashesInput); | ||
|
||
var result = vpTreeHashBase.Search(hashSearch, searchRadius, limit).OrderBy(x => x); | ||
|
||
Assert.Equal(expectedIDs, result); | ||
} | ||
} | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
ImageBase.HashBase.UnitTests/ImageBase.HashBase.UnitTests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
|
||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> | ||
<PackageReference Include="xunit" Version="2.4.0" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> | ||
<PackageReference Include="coverlet.collector" Version="1.2.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\ImageBase.HashBase\ImageBase.HashBase.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System.Collections.Generic; | ||
using ImageBase.Common; | ||
|
||
namespace ImageBase.HashBase | ||
{ | ||
public class HashComparer : IComparer<HashItem> | ||
{ | ||
private readonly long vantagePointHash; | ||
|
||
public HashComparer(HashItem vantagePoint) | ||
{ | ||
this.vantagePointHash = vantagePoint.Hash; | ||
} | ||
|
||
public int Compare(HashItem x, HashItem y) | ||
{ | ||
var result = HammingDistance.Calculate(x.Hash, vantagePointHash) | ||
.CompareTo(HammingDistance.Calculate(y.Hash, vantagePointHash)); | ||
|
||
return result; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace ImageBase.HashBase | ||
{ | ||
public struct HashItem | ||
{ | ||
/// <summary> | ||
/// id for object in database | ||
/// </summary> | ||
public long ObjectId { get; set; } | ||
|
||
public long Hash { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace ImageBase.HashBase | ||
{ | ||
interface IHashBase | ||
{ | ||
/// <summary> | ||
/// Creates in memory VP-Tree for specified hashes. | ||
/// </summary> | ||
/// <param name="items"></param> | ||
void CreateIndex(IEnumerable<HashItem> items); | ||
|
||
/// <summary> | ||
/// Returns list of objects IDs | ||
/// </summary> | ||
/// <param name="hash"></param> | ||
/// <param name="radius"></param> | ||
/// <param name="limit"></param> | ||
/// <returns></returns> | ||
IReadOnlyList<long> Search(long hash, int radius, int limit); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netstandard2.0</TargetFramework> | ||
<TargetFramework>netstandard2.1</TargetFramework> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\ImageBase.Common\ImageBase.Common.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
Oops, something went wrong.