Skip to content
This repository has been archived by the owner on Sep 29, 2021. It is now read-only.

Commit

Permalink
Merge pull request #23 from fornit1917/20-hashes-indexing-by-vp-tree-…
Browse files Browse the repository at this point in the history
…begin

20 hashes indexing by vp tree begin
  • Loading branch information
fornit1917 authored Dec 1, 2020
2 parents bad9e7c + bf63c33 commit 2970683
Show file tree
Hide file tree
Showing 9 changed files with 473 additions and 3 deletions.
220 changes: 220 additions & 0 deletions ImageBase.HashBase.UnitTests/HashBaseUnitTests.cs
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 ImageBase.HashBase.UnitTests/ImageBase.HashBase.UnitTests.csproj
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>
23 changes: 23 additions & 0 deletions ImageBase.HashBase/HashComparer.cs
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;
}
}
}
16 changes: 16 additions & 0 deletions ImageBase.HashBase/HashItem.cs
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; }
}
}
24 changes: 24 additions & 0 deletions ImageBase.HashBase/IHashBase.cs
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);
}
}
8 changes: 6 additions & 2 deletions ImageBase.HashBase/ImageBase.HashBase.csproj
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>
Loading

0 comments on commit 2970683

Please sign in to comment.