public void MTreeAddTest() { MTree <IPoint> tree = new MTree <IPoint>(2, 3, (x, y) => GeometryDistanceAlgorithm.Distance(x, y)); tree.Add(this.geometries[0]); tree.NumberOfDataItems.ShouldBe(1); tree.Add(this.geometries[1]); tree.NumberOfDataItems.ShouldBe(2); tree.Add(this.geometries[2]); tree.NumberOfDataItems.ShouldBe(3); tree.Add(this.geometries[3]); tree.NumberOfDataItems.ShouldBe(4); for (int i = 4; i < this.geometries.Count; i++) { tree.Add(this.geometries[i]); } tree.NumberOfDataItems.ShouldBe(this.geometries.Count); tree = new MTree <IPoint>(2, 3, (x, y) => GeometryDistanceAlgorithm.Distance(x, y)); tree.Add(this.geometries); tree.NumberOfDataItems.ShouldBe(this.geometries.Count); Should.Throw <ArgumentNullException>(() => tree.Add((IPoint)null)); Should.Throw <ArgumentNullException>(() => tree.Add((IEnumerable <IPoint>)null)); // try to insert item already in the tree Should.Throw <ArgumentException>(() => tree.Add(this.geometries[0])); }
private void PopulateTree <T>(MTree <T> tree, List <T> points) { foreach (T point in points) { tree.Add(point); } }
public void RangeSearchTest() { int maxItems = 10000; int maxNodes = 25; double distThreshold = 1000; Random rand = new Random(); CartesianPoint testPoint = new CartesianPoint(0, 0); MTree <CartesianPoint> tree = new MTree <CartesianPoint>(CartesianPoint.PythagoreanTheorem, maxNodes); List <CartesianPoint> itemsInThreshold = new List <CartesianPoint>(); CartesianPoint newPoint; for (int i = 0; i < maxItems; i++) { int xMultiplier = rand.Next(-2, 1); while (xMultiplier == 0) { xMultiplier = rand.Next(-2, 1); } int yMultiplier = rand.Next(-2, 1); while (yMultiplier == 0) { yMultiplier = rand.Next(-2, 1); } double x = maxItems * xMultiplier * rand.NextDouble() * 0.05; double y = maxItems * yMultiplier * rand.NextDouble() * 0.05; newPoint = new CartesianPoint(x, y); tree.Add(newPoint); double dist = tree.GetDistance(newPoint, testPoint); if (dist <= distThreshold) { itemsInThreshold.Add(newPoint); } } List <CartesianPoint> neighbors = tree.RangeSearch(testPoint, distThreshold); Assert.AreEqual(itemsInThreshold.Count, neighbors.Count, "RangeSearch did not return the correct number of elements."); foreach (var neighbor in neighbors) { double dist = tree.GetDistance(neighbor, testPoint); Assert.IsTrue(dist <= distThreshold, "RangeSearch returned an item outside of the search radius."); Assert.IsTrue(itemsInThreshold.Contains(neighbor), "RangeSearch returned an invalid item"); } foreach (var closeItem in itemsInThreshold) { Assert.IsTrue(neighbors.Contains(closeItem), "RangeSearch did not return an item within the search radius."); } }
public void KNearestNeighborsTest() { int maxItems = 10000; int k = 100; Random rand = new Random(); CartesianPoint testPoint = new CartesianPoint(0, 0); MTree <CartesianPoint> tree = new MTree <CartesianPoint>(CartesianPoint.PythagoreanTheorem); PriorityQueue <CartesianPoint> kNeighbors = new PriorityQueue <CartesianPoint>(k); CartesianPoint newPoint; for (int i = 0; i < maxItems; i++) { int xMultiplier = rand.Next(-2, 1); while (xMultiplier == 0) { xMultiplier = rand.Next(-2, 1); } int yMultiplier = rand.Next(-2, 1); while (yMultiplier == 0) { yMultiplier = rand.Next(-2, 1); } double x = maxItems * xMultiplier * rand.NextDouble() * 0.05; double y = maxItems * yMultiplier * rand.NextDouble() * 0.05; newPoint = new CartesianPoint(x, y); tree.Add(newPoint); double dist = tree.GetDistance(newPoint, testPoint); kNeighbors.Enqueue(newPoint, dist); } PriorityQueue <CartesianPoint> queryReturns = tree.KNearestNeighborSearch(testPoint, k); Assert.AreEqual(k, queryReturns.Count, "K neighor search did not return the correct number of items."); while (kNeighbors.HasNext) { var neighbor = kNeighbors.Dequeue(); var result = queryReturns.Dequeue(); Assert.AreEqual(neighbor.Value, result.Value, "K neighbor search returned wrong item."); Assert.AreEqual(neighbor.Key, result.Key, "K neighbor search returned correct item with wrong distance."); } Assert.IsFalse(queryReturns.HasNext, "K neighbor search returned too many items."); }
public void MTreeSearchTest() { MTree <IPoint> tree = new MTree <IPoint>(2, 3, (x, y) => GeometryDistanceAlgorithm.Distance(x, y)); tree.Search(this.geometries[0]).ShouldBeEmpty(); IPoint[] points = new IPoint[9]; for (Int32 i = 0; i < 9; i++) { points[i] = this.factory.CreatePoint(i, 0); tree.Add(points[i]); } // search without limits should return all items in the tree tree.Search(this.factory.CreatePoint(2, 0)).Count().ShouldBe(9); // search returns the correct data items in the correct order with correct distance information List <ResultItem <IPoint> > results = new List <ResultItem <IPoint> >(tree.Search(this.factory.CreatePoint(8, 0))); List <IPoint> expectedResults = new List <IPoint>(points.Reverse()); for (Int32 i = 0; i < points.Length; i++) { results[i].Item.ShouldBe(expectedResults[i]); results[i].Distance.ShouldBe(i); } // search with a given radius should return only the elements within that radius tree.Search(this.factory.CreatePoint(8, 0), 1.0D).Count().ShouldBe(2); tree.Search(this.factory.CreatePoint(7, 0), 1.0D).Count().ShouldBe(3); tree.Search(this.factory.CreatePoint(9, 0), 1.0D).Count().ShouldBe(1); tree.Search(this.factory.CreatePoint(10, 0), 1.0D).Count().ShouldBe(0); // search with a given limit should return only that amount of elements tree.Search(this.factory.CreatePoint(2, 0), 0).Count().ShouldBe(0); tree.Search(this.factory.CreatePoint(2, 0), 1).Count().ShouldBe(1); tree.Search(this.factory.CreatePoint(2, 0), 5).Count().ShouldBe(5); tree.Search(this.factory.CreatePoint(2, 0), 10).Count().ShouldBe(9); // search with both radius and limit where radius contains less elements than limit tree.Search(this.factory.CreatePoint(2, 0), 1.1D, 5).Count().ShouldBe(3); // search with both radius and limit where radius contains more elements than limit tree.Search(this.factory.CreatePoint(2, 0), 1.1D, 2).Count().ShouldBe(2); // errors Should.Throw <ArgumentNullException>(() => tree.Search(null)); }
public void ContainsTest() { int maxNodeSize = 25; int numItems = 10000; MTree <int> tree = new MTree <int>((x, y) => Math.Abs(x - y), maxNodeSize); for (int i = 0; i < numItems; i++) { tree.Add(i); Assert.AreEqual(i + 1, tree.Count, "Count is not returning the correct value."); } for (int i = 0; i < numItems; i++) { Assert.IsTrue(tree.Contains(i), "Contains is returning false for a value that has been inserted in the MTree."); } }
public static void Function() { MTree <int> mTree = new MTree <int>(); mTree.Add(123); mTree.Add(324); mTree.Add(45); mTree.Add(78); mTree.Add(126653); mTree.Add(144523); mTree.Add(1624444443); mTree.Add(12 + 73); mTree.MidOrder(); WriteLine("--------------------------------------------------"); mTree.PreOrder(); WriteLine("--------------------------------------------------"); mTree.PostOrder(); WriteLine("--------------------------------------------------"); WriteLine(mTree.Max()); }
public void ItemInsertVerification() { int maxItems = 1000; int maxNodes = 25; Random rand = new Random(); MTree <CartesianPoint> tree = new MTree <CartesianPoint>(CartesianPoint.PythagoreanTheorem, maxNodes); CartesianPoint newPoint; for (int i = 1; i <= maxItems; i++) { int xMultiplier = rand.Next(-2, 1); while (xMultiplier == 0) { xMultiplier = rand.Next(-2, 1); } int yMultiplier = rand.Next(-2, 1); while (yMultiplier == 0) { yMultiplier = rand.Next(-2, 1); } double x = maxItems * xMultiplier * rand.NextDouble() * 0.05; double y = maxItems * yMultiplier * rand.NextDouble() * 0.05; newPoint = new CartesianPoint(x, y); tree.Add(newPoint); Assert.AreEqual(i, tree.Count, "MTree does not give correct Count after adding a new element."); Assert.IsTrue(tree.Contains(newPoint), "MTree does not say it Contains new item that has been added."); NodeDescentAssert(tree.Root, 1, maxNodes); } }
static void Main(string[] args) { var mtreeStopwatch = new Stopwatch(); var fastMtreeStopWatch = new Stopwatch(); var originalTimes = new List <long>(); var fastTimes = new List <long>(); var dataSize = 100000; var testDataSize = 50; var range = 1000000; var neighbors = 10; var dimensions = 1000; Console.WriteLine($"{nameof(dataSize)}: {dataSize}"); Console.WriteLine($"{nameof(dimensions)}: {dimensions}"); Console.WriteLine($"{nameof(neighbors)}: {neighbors}"); Console.WriteLine(); var testData = Supercluster.Tests.Utilities.GenerateDoubles(testDataSize, range, dimensions); for (int index = 0; index < testData.Length; index++) { var treeData = Supercluster.Tests.Utilities.GenerateDoubles(dataSize, range, dimensions); var target = testData[index]; // 1. Build Trees var fastMtree = new FastMTree <double[]> { Capacity = 3, Metric = Metrics.L2Norm_Double }; foreach (var point in treeData) { fastMtree.Add(point); } var mtree = new MTree <double[]> { Capacity = 3, Metric = Metrics.L2Norm_Double }; foreach (var point in treeData) { mtree.Add(point); } GC.Collect(); GCLatencyMode oldMode = GCSettings.LatencyMode; // Make sure we can always go to the catch block, // so we can set the latency mode back to `oldMode` RuntimeHelpers.PrepareConstrainedRegions(); try { GCSettings.LatencyMode = GCLatencyMode.LowLatency; // Measure Trees mtreeStopwatch.Start(); var resultsList = mtree.NearestNeighbors(target, neighbors).ToArray(); mtreeStopwatch.Stop(); fastMtreeStopWatch.Start(); var fastResults = fastMtree.NearestNeighbors(target, neighbors).ToArray(); fastMtreeStopWatch.Stop(); // Generation 2 garbage collection is now // deferred, except in extremely low-memory situations } finally { // ALWAYS set the latency mode back GCSettings.LatencyMode = oldMode; } // Print times if (index != 0) // We skip first run because of jitting { // Record Times originalTimes.Add(mtreeStopwatch.ElapsedTicks); fastTimes.Add(fastMtreeStopWatch.ElapsedTicks); Console.WriteLine(mtreeStopwatch.ElapsedTicks + " " + fastMtreeStopWatch.ElapsedTicks); } // reset stopwatches mtreeStopwatch.Reset(); fastMtreeStopWatch.Reset(); } Console.WriteLine("Average: " + originalTimes.Average() + " " + fastTimes.Average()); Console.Read(); }