public void DoProcess(SortedLimitedList<Double> mustBeEqualTo, SortedLimitedList<Double> expectedOutput) { // TODO: make "mustBeEqualTo" list equal to "expectedOutput". // 0. Processor will be created once and then will be used billion times. // 1. Use methods: AddFirst, AddLast, AddBefore, AddAfter, Remove to modify list. // 2. Do not change expectedOutput list. // 3. At any time number of elements in list could not exceed the "Limit". // 4. "Limit" will be passed into Processor's constructor. All "mustBeEqualTo" and "expectedOutput" lists will have the same "Limit" value. // 5. At any time list elements must be in non-descending order. // 6. Implementation must perform minimal possible number of actions (AddFirst, AddLast, AddBefore, AddAfter, Remove). // 7. Implementation must be fast and do not allocate excess memory. }
// Limited Best-Bin-First k-d-tree nearest neighbour search. // // (Using the algorithm described in the paper "Shape indexing using // approximate nearest-neighbour search in high-dimensional spaces", // available at http://www.cs.ubc.ca/spider/lowe/papers/cvpr97-abs.html) // // Find the approximate nearest neighbour to the hyperspace point 'target' // within the kd-tree using 'searchSteps' tail recursions at most (each // recursion deciding about one neighbours' fitness). // // After return 'resDist' contains the absolute distance of the // approximate nearest neighbour from the target point. The approximate // nearest neighbour is returned. public ArrayList NearestNeighbourListBBF(IKDTreeDomain target, int q, int searchSteps) { HyperRectangle hr = HyperRectangle.CreateUniverseRectangle(target.DimensionCount); SortedLimitedList best = new SortedLimitedList(q); SortedLimitedList searchHr = new SortedLimitedList(searchSteps); float dummyDist; IKDTreeDomain nearest = NearestNeighbourListBBFI(best, q, target, hr, float.MaxValue, out dummyDist, searchHr, ref searchSteps); foreach (BestEntry be in best) { be.Distance = Math.Sqrt(be.DistanceSq); } return(best); }
public ArrayList NearestNeighbourList(IKDTreeDomain target, out double resDist, int q) { HyperRectangle hr = HyperRectangle.CreateUniverseRectangle(target.DimensionCount); SortedLimitedList best = new SortedLimitedList(q); IKDTreeDomain nearest = NearestNeighbourListI(best, q, target, hr, Double.PositiveInfinity, out resDist); resDist = Math.Sqrt(resDist); foreach (BestEntry be in best) { be.Distance = Math.Sqrt(be.Distance); } return(best); }
private IKDTreeDomain NearestNeighbourListBBFI(SortedLimitedList best, int q, IKDTreeDomain target, HyperRectangle hr, int maxDistSq, out int resDistSq, SortedLimitedList searchHr, ref int searchSteps) { resDistSq = Int32.MaxValue; IKDTreeDomain pivot = dr; best.Add(new BestEntry(dr, KDTree.DistanceSq(target, dr), true)); HyperRectangle leftHr = hr; HyperRectangle rightHr = leftHr.SplitAt(splitDim, pivot.GetDimensionElement(splitDim)); HyperRectangle nearerHr, furtherHr; KDTree nearerKd, furtherKd; if (target.GetDimensionElement(splitDim) <= pivot.GetDimensionElement(splitDim)) { nearerKd = left; nearerHr = leftHr; furtherKd = right; furtherHr = rightHr; } else { nearerKd = right; nearerHr = rightHr; furtherKd = left; furtherHr = leftHr; } IKDTreeDomain nearest = null; int distSq; searchHr.Add(new HREntry(furtherHr, furtherKd, pivot, furtherHr.Distance(target))); if (nearerKd == null) { distSq = Int32.MaxValue; } else { nearest = nearerKd.NearestNeighbourListBBFI(best, q, target, nearerHr, maxDistSq, out distSq, searchHr, ref searchSteps); } if (best.Count >= q) { maxDistSq = ((BestEntry)best[q - 1]).DistanceSq; } else { maxDistSq = Int32.MaxValue; } if (searchHr.Count > 0) { HREntry hre = (HREntry)searchHr[0]; searchHr.RemoveAt(0); furtherHr = hre.HR; furtherKd = hre.Tree; pivot = hre.Pivot; } searchSteps -= 1; if (searchSteps > 0 && furtherHr.IsInReach(target, Math.Sqrt(maxDistSq))) { int ptDistSq = KDTree.DistanceSq(pivot, target); if (ptDistSq < distSq) { nearest = pivot; distSq = ptDistSq; maxDistSq = distSq; } int tempDistSq; IKDTreeDomain tempNearest = null; if (furtherKd == null) { tempDistSq = Int32.MaxValue; } else { tempNearest = furtherKd.NearestNeighbourListBBFI(best, q, target, furtherHr, maxDistSq, out tempDistSq, searchHr, ref searchSteps); } if (tempDistSq < distSq) { nearest = tempNearest; distSq = tempDistSq; } } resDistSq = distSq; return(nearest); }
private IKDTreeDomain NearestNeighbourListI(SortedLimitedList best, int q, IKDTreeDomain target, HyperRectangle hr, double maxDistSq, out double resDistSq) { resDistSq = Double.PositiveInfinity; IKDTreeDomain pivot = dr; best.Add(new BestEntry(dr, KDTree.DistanceSq(target, dr))); HyperRectangle leftHr = hr; HyperRectangle rightHr = leftHr.SplitAt(splitDim, pivot.GetDimensionElement(splitDim)); HyperRectangle nearerHr, furtherHr; KDTree nearerKd, furtherKd; if (target.GetDimensionElement(splitDim) <= pivot.GetDimensionElement(splitDim)) { nearerKd = left; nearerHr = leftHr; furtherKd = right; furtherHr = rightHr; } else { nearerKd = right; nearerHr = rightHr; furtherKd = left; furtherHr = leftHr; } IKDTreeDomain nearest = null; double distSq; if (nearerKd == null) { distSq = Double.PositiveInfinity; } else { nearest = nearerKd.NearestNeighbourListI(best, q, target, nearerHr, maxDistSq, out distSq); } if (best.Count >= q) { maxDistSq = ((BestEntry)best[q - 1]).Distance; } else { maxDistSq = Double.PositiveInfinity; } if (furtherHr.IsInReach(target, Math.Sqrt(maxDistSq))) { double ptDistSq = KDTree.DistanceSq(pivot, target); if (ptDistSq < distSq) { nearest = pivot; distSq = ptDistSq; maxDistSq = distSq; } double tempDistSq; IKDTreeDomain tempNearest = null; if (furtherKd == null) { tempDistSq = Double.PositiveInfinity; } else { tempNearest = furtherKd.NearestNeighbourListI(best, q, target, furtherHr, maxDistSq, out tempDistSq); } if (tempDistSq < distSq) { nearest = tempNearest; distSq = tempDistSq; } } resDistSq = distSq; return(nearest); }
public void DoProcess(SortedLimitedList<Double> mustBeEqualTo, SortedLimitedList<Double> expectedOutput) { // TODO: make "mustBeEqualTo" list equal to "expectedOutput". // 0. Processor will be created once and then will be used billion times. // 1. Use methods: AddFirst, AddLast, AddBefore, AddAfter, Remove to modify list. // 2. Do not change expectedOutput list. // 3. At any time number of elements in list could not exceed the "Limit". // 4. "Limit" will be passed into Processor's constructor. All "mustBeEqualTo" and "expectedOutput" lists will have the same "Limit" value. // 5. At any time list elements must be in non-descending order. // 6. Implementation must perform minimal possible number of actions (AddFirst, AddLast, AddBefore, AddAfter, Remove). // 7. Implementation must be fast and do not allocate excess memory. oneEOItem = expectedOutput.Last; oneMBETItem = mustBeEqualTo.Last; //Delete in mustBeEqualTo all which greater than last from expectedOutput while(oneMBETItem!=null){ if(oneEOItem !=null && oneMBETItem.Value.CompareTo(oneEOItem.Value)>0){ remMBETItem = oneMBETItem; oneMBETItem = oneMBETItem.Previous; mustBeEqualTo.Remove(remMBETItem); }else if(oneEOItem == null){ remMBETItem = oneMBETItem; oneMBETItem = oneMBETItem.Previous; mustBeEqualTo.Remove(remMBETItem); } else { oneMBETItem = oneMBETItem.Previous; } } //Delete in mustBeEqualTo all which not found in expectedOutput from the beginning oneEOItem = expectedOutput.First; int totalEOItems=0; oneMBETItem = mustBeEqualTo.First; while(oneEOItem != null && oneMBETItem!=null){ twoEOItem = oneEOItem.Next; totalEOItems++; int kolvoEOItems=1; while(twoEOItem!=null && oneEOItem.Value.CompareTo(twoEOItem.Value)==0){ kolvoEOItems++; totalEOItems++; twoEOItem=twoEOItem.Next; } while(oneMBETItem!=null && oneEOItem.Value.CompareTo(oneMBETItem.Value)>=0){ if(oneEOItem.Value.CompareTo(oneMBETItem.Value)>0){ remMBETItem = oneMBETItem; oneMBETItem = oneMBETItem.Next; mustBeEqualTo.Remove(remMBETItem); }else{ twoMBETItem = oneMBETItem.Next; int kolvoMBETItems=1; while(twoMBETItem!=null && oneMBETItem.Value.CompareTo(twoMBETItem.Value)==0){ kolvoMBETItems++; twoMBETItem=twoMBETItem.Next; } while(kolvoMBETItems>kolvoEOItems){ remMBETItem = oneMBETItem; oneMBETItem = oneMBETItem.Next; mustBeEqualTo.Remove(remMBETItem); kolvoMBETItems--; } oneMBETItem = twoMBETItem; } } oneEOItem = twoEOItem; } if(totalEOItems>iLimit){ throw new Exception("Number of elements in 'expectedOutput' exceed the 'Limit'."); } //Insert in mustBeEqualTo all which found in expectedOutput from the beginning oneEOItem = expectedOutput.First; oneMBETItem = mustBeEqualTo.First; while(oneEOItem != null){ twoEOItem = oneEOItem.Next; int kolvoEOItems=1; while(twoEOItem!=null && oneEOItem.Value.CompareTo(twoEOItem.Value)==0){ kolvoEOItems++; twoEOItem=twoEOItem.Next; } if(oneMBETItem == null){ for(int i=0;i<kolvoEOItems;i++){ mustBeEqualTo.AddLast(oneEOItem.Value); } //oneMBETItem = mustBeEqualTo.Last; }else if(oneEOItem.Value.CompareTo(oneMBETItem.Value)<0){ for(int i=0;i<kolvoEOItems;i++){ mustBeEqualTo.AddBefore(oneMBETItem,oneEOItem.Value); } }else if(oneEOItem.Value.CompareTo(oneMBETItem.Value)==0){ twoMBETItem = oneMBETItem.Next; kolvoEOItems--; while(twoMBETItem!=null && oneMBETItem.Value.CompareTo(twoMBETItem.Value)==0){ kolvoEOItems--; twoMBETItem=twoMBETItem.Next; } for(int i=0;i<kolvoEOItems;i++){ mustBeEqualTo.AddAfter(oneMBETItem,oneEOItem.Value); } oneMBETItem = twoMBETItem; } oneEOItem = twoEOItem; } }
private IKDTreeDomain NearestNeighbourListI(SortedLimitedList best, int q, IKDTreeDomain target, HyperRectangle hr, double maxDistSq, out double resDistSq) { resDistSq = Double.PositiveInfinity; IKDTreeDomain pivot = dr; best.Add(new BestEntry(dr, KDTree.DistanceSq(target, dr))); HyperRectangle leftHr = hr; HyperRectangle rightHr = leftHr.SplitAt(splitDim, pivot.GetDimensionElement(splitDim)); HyperRectangle nearerHr, furtherHr; KDTree nearerKd, furtherKd; // step 5-7 if (target.GetDimensionElement(splitDim) <= pivot.GetDimensionElement(splitDim)) { nearerKd = left; nearerHr = leftHr; furtherKd = right; furtherHr = rightHr; } else { nearerKd = right; nearerHr = rightHr; furtherKd = left; furtherHr = leftHr; } // step 8 IKDTreeDomain nearest = null; double distSq; // No child, bottom reached! if (nearerKd == null) { distSq = Double.PositiveInfinity; } else { nearest = nearerKd.NearestNeighbourListI(best, q, target, nearerHr, maxDistSq, out distSq); } // step 9 //maxDistSq = Math.Min (maxDistSq, distSq); if (best.Count >= q) { maxDistSq = ((BestEntry)best[q - 1]).Distance; } else { maxDistSq = Double.PositiveInfinity; } // step 10 if (furtherHr.IsInReach(target, Math.Sqrt(maxDistSq))) { double ptDistSq = KDTree.DistanceSq(pivot, target); if (ptDistSq < distSq) { // steps 10.1.1 to 10.1.3 nearest = pivot; distSq = ptDistSq; // TODO: use k-element list /* * best.Add (new BestEntry (pivot, ptDistSq)); * best.Sort (); */ maxDistSq = distSq; } // step 10.2 double tempDistSq; IKDTreeDomain tempNearest = null; if (furtherKd == null) { tempDistSq = Double.PositiveInfinity; } else { tempNearest = furtherKd.NearestNeighbourListI(best, q, target, furtherHr, maxDistSq, out tempDistSq); } // step 10.3 if (tempDistSq < distSq) { nearest = tempNearest; distSq = tempDistSq; } } resDistSq = distSq; return(nearest); }