internal float?CoreDistance(KdTree kdt, Dictionary <long, float?> coreDistances, IPointIdFloat p, float eps, int minPoints) { float?distance; long id = p.id; if (coreDistances.ContainsKey(id)) { coreDistances.TryGetValue(id, out distance); } else { var nNeighbours = NNearestNeighbours(kdt, p, minPoints); //There will always be at least one element, i.e. p itself float nthDistance = nNeighbours.Last().DistanceTo(p); if (nNeighbours.Count < minPoints || nthDistance > eps) { distance = null; } else { distance = nthDistance; } coreDistances.Add(id, distance); } return(distance); }
public IPointIdFloat NearestNeighbour(IPointIdFloat target, IPointIdFloat nn, ref float nnDist, Func <VBuffer <float>, VBuffer <float>, float> distFunc) { float key = KeyByDepth(point, depth); float targetKey = KeyByDepth(target, depth); float d = distFunc(point.coordinates, target.coordinates); IKdTreeNode closestBranch, fartherBranch; if (d < nnDist) { nnDist = d; nn = point; } if (targetKey <= key) { closestBranch = left; fartherBranch = right; } else { closestBranch = right; fartherBranch = left; } nn = closestBranch.NearestNeighbour(target, nn, ref nnDist, distFunc); if (Math.Abs(targetKey - key) <= nnDist) { nn = fartherBranch.NearestNeighbour(target, nn, ref nnDist, distFunc); } return(nn); }
public float Score(IPointIdFloat p, float epsilon, Dictionary <long, int> mapClusters) { var res = RegionQuery(kdt, p, epsilon); if (res.Count() <= 1) { return(1f); } else { var sorted = res.Select(pe => new Tuple <float, int>((float)(1 / (epsilon + p.DistanceTo(pe))), mapClusters[pe.id])) .OrderBy(c => c); float score = 0f; int last = mapClusters[p.id]; float lastd = 0f; foreach (var el in sorted) { if (el.Item2 != last) { score += el.Item1 - lastd; lastd = el.Item1; } } return(score); } }
/// <summary> /// Returns the N points in the tree which are closest to the target. /// </summary> public IList <IPointIdFloat> NearestNNeighbors(IPointIdFloat target, int N) { var nns = NearestNNeighborsAndDistance(target, N) .ToList() .OrderBy(kvp => - kvp.Key) .Select(kvp => kvp.Value) .ToList(); Comparison <IPointIdFloat> comparePointsByDistanceToTarget = (a, b) => { float dA = _distFunc(a.coordinates, target.coordinates); float dB = _distFunc(b.coordinates, target.coordinates); if (dA < dB) { return(-1); } else if (dA > dB) { return(1); } else { return(0); } }; nns.Sort(comparePointsByDistanceToTarget); return(nns); }
public void PointsWithinDistance(IPointIdFloat center, float distance, ref IList <IPointIdFloat> results, Func <VBuffer <float>, VBuffer <float>, float> distFunc) { float key = KeyByDepth(point, depth); float centerKey = KeyByDepth(center, depth); float d = distFunc(point.coordinates, center.coordinates); IKdTreeNode closestBranch, fartherBranch; if (d <= distance) { results.Add(point); } if (centerKey <= key) { closestBranch = left; fartherBranch = right; } else { closestBranch = right; fartherBranch = left; } closestBranch.PointsWithinDistance(center, distance, ref results, distFunc); if (Math.Abs(centerKey - key) <= distance) { fartherBranch.PointsWithinDistance(center, distance, ref results, distFunc); } }
public IPointIdFloat NearestNeighbour(IPointIdFloat p) { ValidatePoint(p); float tmp = float.MaxValue; return(root.NearestNeighbour(p, null, ref tmp, _distFunc)); }
/** * */ internal static void ExpandCluster(Dictionary <long, int> clusters, HashSet <long> processed, IList <IPointIdFloat> points, IPointIdFloat pAdd, List <IPointIdFloat> pNeighbours, int clusterId, float epsilon, int minPoints) { if (!clusters.ContainsKey(pAdd.id)) { // Some points might have been added as neighbours even though they were not visited. // Line A below. clusters.Add(pAdd.id, clusterId); } for (int i = 0; i < pNeighbours.Count; i++) { IPointIdFloat q = pNeighbours[i]; if (!processed.Contains(q.id)) { processed.Add(q.id); var qNeighbours = RegionQuery(points, q, epsilon); if (qNeighbours.Count() > minPoints) { pNeighbours.AddRange(qNeighbours); } } if (!clusters.ContainsKey(q.id)) { clusters.Add(q.id, clusterId); } } }
public IList <IPointIdFloat> PointsWithinDistance(IPointIdFloat center, float distance) { ValidatePoint(center); IList <IPointIdFloat> results = new List <IPointIdFloat>(); root.PointsWithinDistance(center, distance, ref results, _distFunc); return(results); }
internal static void MarkProcessed(IPointIdFloat p, Dictionary <long, long> orderingMapping, List <IPointIdFloat> ordering, HashSet <long> processed, ref int currentIndex) { processed.Add(p.id); orderingMapping.Add(p.id, currentIndex); ordering.Add(p); currentIndex += 1; }
internal void ValidatePoint(IPointIdFloat p) { if (p == null) { throw new ArgumentNullException(); } else if (p.dimension != dimension) { throw new ArgumentException(string.Format("Wrong Point dimension: expected {0}, got {1}", dimension, p.dimension)); } }
public KdTreeNode(IPointIdFloat point, IKdTreeNode left, IKdTreeNode right, int depth) { this.point = point; this.left = left; this.right = right; this.depth = depth; size = 1 + left.size + right.size; if (depth > MaxDepth) { throw Contracts.Except("The k-d tree depth is too high (> {0}). This probably means the datasets is too sparse to be effective. You should reduce the number of dimensions (PCA for example).", MaxDepth); } }
public void Add(IPointIdFloat p) { if (root == null) { var points = new IPointIdFloat[] { p }; ValidatePointsArray(points); root = CreateTree(points.ToList(), _rnd); } else { ValidatePoint(p); root.Add(p); } }
public bool Contains(IPointIdFloat p) { if (point == p) { return(true); } else if (KeyByDepth(p, depth) <= KeyByDepth(point, depth)) { return(left.Contains(p)); } else { return(right.Contains(p)); } }
public IKdTreeNode Add(IPointIdFloat p) { float key = this.Key(); float pKey = KeyByDepth(p, depth); if (pKey <= key) { left = left.Add(p); size = 1 + left.size + right.size; } else { right = right.Add(p); size = 1 + left.size + right.size; } return(this); }
private void testMedian( IList <IPointIdFloat> points, IPointIdFloat expectedMedian, IList <IPointIdFloat> expectedLeft, IList <IPointIdFloat> expectedRight, int depth = 0) { IList <IPointIdFloat> left = null; IList <IPointIdFloat> right = null; Func <IPointIdFloat, float> keySelector = t => KdTree.KdTreeNode.KeyByDepth(t, depth); IPointIdFloat median = KdTree.MedianPoint(points, ref left, ref right, depth, rnd); Assert.AreEqual(expectedMedian, median); Assert.IsTrue(SequenceEquivalent(expectedLeft, left, keySelector)); Assert.IsTrue(SequenceEquivalent(expectedRight, right, keySelector)); }
internal float?CoreDistance(KdTree kdt, IPointIdFloat p, float eps, int minPoints) { float?distance; long id = p.id; var nNeighbours = NNearestNeighbours(kdt, p, minPoints); //There will always be at least one element, i.e. p itself var nthDistance = nNeighbours.Last().DistanceTo(p); if (nNeighbours.Count < minPoints || nthDistance > eps) { distance = null; } else { distance = nthDistance; } return(distance); }
internal static IKdTreeNode CreateTree(IList <IPointIdFloat> points, Random rnd, int depth = 0) { switch (points.Count()) { case 0: return(new KdTreeLeaf(depth)); case 1: return(new KdTreeNode(points.First(), new KdTreeLeaf(depth + 1), new KdTreeLeaf(depth + 1), depth)); default: IList <IPointIdFloat> leftPoints = null; IList <IPointIdFloat> rightPoints = null; IPointIdFloat median = MedianPoint(points, ref leftPoints, ref rightPoints, depth, rnd); IKdTreeNode left = CreateTree(leftPoints, rnd, depth + 1); IKdTreeNode right = CreateTree(rightPoints, rnd, depth + 1); return(new KdTreeNode(median, left, right, depth)); } }
public FixedSizePriorityQueue <float, IPointIdFloat> NearestNNeighbors(IPointIdFloat target, FixedSizePriorityQueue <float, IPointIdFloat> nns, Func <VBuffer <float>, VBuffer <float>, float> distFunc) { float key = KeyByDepth(point, depth); float targetKey = KeyByDepth(target, depth); float d = distFunc(point.coordinates, target.coordinates); IKdTreeNode closestBranch, fartherBranch; float nthNnDist = -nns.Peek().GetValueOrDefault(InfinitePoint).Key; if (!nns.IsFull || d < nthNnDist) { nns.Enqueue(-d, point); } if (targetKey <= key) { closestBranch = left; fartherBranch = right; } else { closestBranch = right; fartherBranch = left; } nns = closestBranch.NearestNNeighbors(target, nns, distFunc); nthNnDist = -nns.Peek().GetValueOrDefault(InfinitePoint).Key; if (Math.Abs(targetKey - key) <= nthNnDist) { nns = fartherBranch.NearestNNeighbors(target, nns, distFunc); } return(nns); }
internal void Update( ref PriorityQueue <float, IPointIdFloat> seeds, HashSet <long> processed, Dictionary <long, float?> reachabilityDistances, Dictionary <long, float?> coreDistancesCache, IPointIdFloat p, float eps, int minPoints) { IList <IPointIdFloat> neighbours = EpsilonNeighbourhood(kdt, p, eps); foreach (var o in neighbours) { long oId = o.id; if (!processed.Contains(oId)) { float?coreDistance; coreDistancesCache.TryGetValue(p.id, out coreDistance); float?reachDist; // INVARIANT: coreDistance != null float newReachDist = Math.Max(coreDistance.Value, o.DistanceTo(p)); reachabilityDistances.TryGetValue(oId, out reachDist); if (reachDist == null || newReachDist < reachDist) { // reachDist == null => o is not in Seeds // newReachDist < reachDist => o in Seeds, check for improvement reachabilityDistances[oId] = newReachDist; if (reachDist == null) { seeds.Enqueue(newReachDist, o); } } } } }
public void PointsWithinDistance(IPointIdFloat center, float distance, ref IList <IPointIdFloat> results, Func <VBuffer <float>, VBuffer <float>, float> distFunc) { //Nothing to do }
/** * */ internal static IList <IPointIdFloat> RegionQuery(KdTree points, IPointIdFloat p, float epsilon) { return(points.PointsWithinDistance(p, epsilon)); }
/** * */ internal static IList <IPointIdFloat> RegionQuery(IList <IPointIdFloat> points, IPointIdFloat p, float epsilon) { return(points.Where(x => p.DistanceTo(x) <= epsilon).ToList()); }
public IList <IPointIdFloat> RegionQuery(IPointIdFloat p, float epsilon) { return(RegionQuery(kdt, p, epsilon)); }
internal void expandClusterOrder(IPointIdFloat p) { throw new NotImplementedException(); }
public bool Delete(IPointIdFloat point) { throw new NotImplementedException(); }
internal static IList <IPointIdFloat> NNearestNeighbours(KdTree kdt, IPointIdFloat p, int minPoints) { return(kdt.NearestNNeighbors(p, minPoints)); }
internal static IList <IPointIdFloat> EpsilonNeighbourhood(KdTree kdt, IPointIdFloat p, float epsilon) { return(kdt.PointsWithinDistance(p, epsilon)); }
public bool Contains(IPointIdFloat p) { return(false); }
public FixedSizePriorityQueue <float, IPointIdFloat> NearestNNeighbors(IPointIdFloat target, FixedSizePriorityQueue <float, IPointIdFloat> nns, Func <VBuffer <float>, VBuffer <float>, float> distFunc) { return(nns); }
public IPointIdFloat NearestNeighbour(IPointIdFloat target, IPointIdFloat nn, ref float nnDist, Func <VBuffer <float>, VBuffer <float>, float> distFunc) { return(nn); }