Пример #1
0
        /// <summary>
        /// Missing mapping to P objects
        /// KdTree could be refactored to use P object instead of Math.Net
        /// 
        /// O(k * log n) 
        /// </summary>
        /// <param name="s"></param>
        /// <param name="origin"></param>
        /// <param name="k"></param>
        /// <param name="conf"></param>        
        /// <returns></returns>
        public long UpdateKnn(IAlgorithm s, IP origin, KnnConfiguration conf)
        {
            if (conf == null) conf = new KnnConfiguration();
            if (conf.SameTypeOnly) throw new NotImplementedException();
            if (conf.MaxDistance.HasValue) throw new NotImplementedException();

            var sw = new Stopwatch();
            sw.Start();

            var vector = new DenseVector(new[] { origin.X, origin.Y });
            var nn = Tree.FindNearestNNeighbors(vector, conf.K).ToList();

            s.Knn.Clear();
            s.Knn.Origin = origin;
            s.Knn.K = conf.K;
            foreach (var i in nn)
            {
                var p = new P { X = i[0], Y = i[1] };
                var dist = origin.Distance(p.X,p.Y);
                s.Knn.NNs.Add(new PDist {Point = p, Distance = dist});
            }

            sw.Stop();
            return sw.ElapsedMilliseconds;
        }
Пример #2
0
        // K nearest neighbor
        protected void UpdateKnnGridStrategy(IAlgorithm s, int max, KnnConfiguration conf)
        {
            var g = s.GridContainer;
            var nn = s.Knn;
            var square = s.Rectangle.Square;

            var currRing = new List<IPDist>();
            var nextRing = new List<IPDist>();

            for (var i = 1; i <= max; i++)
            {
                var temp = new List<IPDist>();
                foreach (var p in nextRing)
                {
                    if (p.Distance < i * square) currRing.Add(p);
                    else temp.Add(p);
                }

                nextRing.Clear();
                nextRing.AddRange(temp);

                var list = g.GetRing(nn.Origin, i);

                // First 9 squares, dont include origin
                if (i == 1) list.AddRange(g.GetSet(nn.Origin).Where(a => !a.Equals(nn.Origin)).ToList());

                // Only NN on same type if set
                if (conf.SameTypeOnly) list = list.Where(a => a.Type == nn.Origin.Type).ToList();

                var dataWasAdded = false;
                foreach (var p in list)
                {
                    var dist = nn.Origin.Distance(p.X, p.Y);
                    if(dist >= conf.MaxDistance) continue; // not within max distance

                    if (dist < i * square) currRing.Add(new PDist { Point = p, Distance = dist });
                    else nextRing.Add(new PDist { Point = p, Distance = dist });

                    dataWasAdded = true;
                }

                if(conf.MaxDistance.HasValue && !dataWasAdded) break; // max distance used and no new data was added, then we are done
                if (currRing.Count >= nn.K) break; // enough neighbors? then done
            }

            if (currRing.Count < nn.K)
            {
                // Only NN on same type if set
                currRing.AddRange(conf.SameTypeOnly
                                      ? nextRing.Where(a => a.Point.Type == nn.Origin.Type).ToList()
                                      : nextRing);

                if (conf.MaxDistance.HasValue) currRing = currRing.Where(i => i.Distance < conf.MaxDistance.Value).ToList();
            }

            currRing.Sort();
            nn.NNs = currRing.Count > nn.K ? currRing.Take(nn.K).ToList() : currRing.ToList();
        }
Пример #3
0
        static void Run()
        {
            // Config
            var rect = new Rectangle
            {
                XMin = -200,
                XMax = 200,
                YMin = -100,
                YMax = 100,
                MaxDistance = 20,
            };
            rect.Validate();

            var conf = new KnnConfiguration { K = 100 };

            // Random points
            IPoints points = new Points();
            var rand = new Random();
            for (var i = 0; i < 500000; i++)
            {
                var x = rect.XMin + rand.NextDouble() * rect.Width;
                var y = rect.YMin + rand.NextDouble() * rect.Height;
                points.Data.Add(new P
                {
                    X = x,
                    Y = y,
                });
            }
            points.Round(3);

            // Init algo
            IAlgorithm algo =
                new Algorithm(points, rect, StrategyType.Grid);

            // Use algo

            var origin = new P { X = 0, Y = 0 };
            var duration = algo.UpdateKnn(origin, conf);

            // Print result
            WL(string.Format("{0} msec. {1}:", algo.Strategy.Name, duration));
            WL("K Nearest Neighbors:");
            WL(string.Format("Origin: {0}", origin));
            WL(string.Format("Distance sum: {0}", algo.Knn.GetDistanceSum()));
            algo.Knn.NNs.OrderBy(i => i.Distance).ToList().ForEach(WL);

            // Update strategy
            algo.SetAlgorithmStrategy(new NaiveStrategy());

            // Use algo
            duration = algo.UpdateKnn(origin, conf);

            // Print result
            WL(string.Format("\n{0} msec. {1}:", algo.Strategy.Name, duration));
            WL("K Nearest Neighbors:");
            WL(string.Format("Distance sum: {0}", algo.Knn.GetDistanceSum()));
            algo.Knn.NNs.OrderBy(i => i.Distance).ToList().ForEach(WL);
        }
Пример #4
0
        // O(n * m) where m is grid cells
        public long UpdateKnn(IAlgorithm s, IP p, KnnConfiguration conf)
        {
            if (conf == null) conf = new KnnConfiguration();

            var sw = new Stopwatch();
            sw.Start();
            var max = Math.Max(s.Rectangle.XGrid, s.Rectangle.YGrid);

            s.Knn.Clear();
            s.Knn.Origin = p;
            s.Knn.K = conf.K;
            UpdateKnnGridStrategy(s, max, conf);

            sw.Stop();
            return sw.ElapsedMilliseconds;
        }
Пример #5
0
        /// <summary>        
        /// O(n * k * logk)  // much faster than O(n logn) for k << n
        /// </summary>
        /// <param name="s"></param>
        /// <param name="p"></param>       
        /// <param name="conf"></param>
        /// <returns></returns>
        public override long UpdateKnn(IAlgorithm s, IP p, KnnConfiguration conf)
        {
            if (conf == null) conf = new KnnConfiguration();

            var sw = new Stopwatch();
            sw.Start();

            s.Knn.Clear();
            s.Knn.Origin = p;
            s.Knn.K = conf.K;

            //var all = new List<IPDist>();
            var sortedList2 = new SortedList2();

            var n = s.Points.Count;
            for (var i = 0; i < n; i++)
            {
                var p1 = s.Points[i];
                if (p.Equals(p1)) continue; // don't include origin
                if (conf.SameTypeOnly && p.Type != p1.Type) continue; // only same type used

                var dist = p.Distance(p1.X, p1.Y);
                if (dist >= conf.MaxDistance) continue;

                var pdist = new PDist { Point = p1, Distance = dist };

                //all.Add(pdist);
                sortedList2.Add(pdist, conf.K);
            }

            //s.Knn.NNs = all.OrderBy(i => i.Distance).Take(conf.K).ToList(); // O(n logn)
            s.Knn.NNs = sortedList2.GetAll(); // O(n * k * logk)

            sw.Stop();
            return sw.ElapsedMilliseconds;
        }
Пример #6
0
 public long UpdateKnn(IP p, KnnConfiguration configuration)
 {
     UpdateIndex(p);
     return Strategy.UpdateKnn(this, p, configuration);
 }
        // Example of usage:
        // Get 3 nearest ->             /AreaGMC/gmc.svc/Knn/lat=8_5;lon=10_25;k=3
        // Get 3 nearest type 1 ->      /AreaGMC/gmc.svc/Knn/lat=8_5;lon=10_25;k=3;type=1
        // Get nearest within 1 km ->   /AreaGMC/gmc.svc/Knn/lat=8_5;lon=10_25;k=1000000;dist=1
        public JsonKnnReply Knn(string s)
        {
            var sw = new Stopwatch();
            sw.Start();

            var invalid = new JsonKnnReply {};
            if (string.IsNullOrEmpty(s))
            {
                invalid.EMsg = "param is empty";
                return invalid;
            }

            var arr = s.Split(new[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            if (arr.Length < 3)
            {
                invalid.EMsg = string.Format("param length is not valid: {0}",arr.Length);
                return invalid;
            }

            var nvc = new NameValueCollection();
            foreach (var a in arr)
            {
                var kv = a.Split(new[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                if (kv.Length != 2) continue;

                nvc.Add(kv[0], kv[1]);
            }

            foreach (var key in Ajax.KnnReq)
            {
                if (nvc[key] != null) continue;

                invalid.EMsg = string.Format("param {0} is missing", key);
                return invalid;
            }

            try
            {
                var y = nvc[Ajax.lat].Replace("_", ".").ToDouble();
                var x = nvc[Ajax.lon].Replace("_", ".").ToDouble();
                var k = int.Parse(nvc[Ajax.k]);
                var type = nvc[Ajax.type] == null ? -1 : int.Parse(nvc[Ajax.type]);

                double? dist = null;
                if(! string.IsNullOrEmpty(nvc[Ajax.dist])) dist = nvc[Ajax.dist].Replace("_", ".").ToDouble();
                               
                // knn algo
                var algo = MemoryDatabase.Data as IKnnAlgorithm;
                if (algo == null)
                {
                    invalid.EMsg = "algorithm is not available";
                    return invalid;
                }

                // Use algo
                var origin = new SingleDetectLibrary.Code.Data.P { X = x, Y = y, Type = type };
                var knnSameTypeOnly = type != -1;

                var conf = new KnnConfiguration {K = k, SameTypeOnly = knnSameTypeOnly, MaxDistance = dist};                                
                var duration = algo.UpdateKnn(origin, conf);

                var nns = algo.Knn.NNs.Select(p => p as PDist).ToList();
                var gmsNns = new List<GmcPDist>();
                foreach (var i in nns)
                {
                    //i.Distance = Math.Round(i.Distance, 7);
                    var pdist = new GmcPDist
                                    {
                                        Id = i.Point.Uid.ToString(),
                                        Point = i.Point, 
                                        Distance = Math.Round(i.Distance, 7)
                                    };
                    gmsNns.Add(pdist);
                }
                
                var result = 
                new JsonKnnReply
                {
                    Data = string.Format("Distance in km, x: {0}; y: {1}; k: {2}; sameTypeOnly: {3}, algo msec: {4}",
                        x.DoubleToString(), y.DoubleToString(), k, knnSameTypeOnly, duration),
                    Nns = gmsNns, // cannot be interface, thus casting
                    
                    Msec = Sw(sw),
                };

                return result;
            }
            catch (Exception ex)
            {
                invalid.EMsg = string.Format("Parsing error param: {0}",
                    ex.Message);
                return invalid;
            }                                                         
        }
Пример #8
0
 public abstract long UpdateKnn(IAlgorithm s, IP p, KnnConfiguration configuration);