public void ExpandRegionTest()
        {
            var points = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1.5f, 1.5f, 1.5f
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
                new PointIdFloat(new List <float>()
                {
                    3, 3, 3
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 2, 2
                })
            };

            PointIdFloat.SetIds(points);

            var   clusters = new Dictionary <long, int>();
            var   visited  = new HashSet <long>();
            var   p        = points[0];
            float epsilon  = 1f;

            var neighbours = DBScan.RegionQuery(points, p, epsilon);

            Assert.IsTrue(neighbours.Contains(p));

            DBScan.ExpandCluster(clusters, visited, points, p, neighbours.ToList(), 0, epsilon, 3);
            Assert.IsTrue(clusters.ContainsKey(p.id));
            foreach (var q in neighbours)
            {
                Assert.IsTrue(clusters.ContainsKey(q.id));
                Assert.IsTrue(clusters[q.id] == clusters[p.id]);
            }

            Assert.IsFalse(clusters.ContainsKey(points.Count() + 1));
        }
        public void StartTest()
        {
            var points = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
                new PointIdFloat(new List <float>()
                {
                    3, 3, 3
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 2, 2
                })
            };

            PointIdFloat.SetIds(points);

            var dbscan = new DBScan(points);
            var result = dbscan.Cluster(0.5f, 2);

            Assert.IsTrue(result.Count == points.Count);
            Assert.IsTrue(result.Values.Max() <= points.Count);
        }
        static void Main(string[] args)
        {
            var points = new List<List<double>>
            {
                new List<double> { 0.5, 0.5 },
                new List<double> { 0.4, 0.4 },
                new List<double> { 0.6, 0.6 },
                new List<double> { 1.4, 0.5 },
                new List<double> { 1.4, 0.4 },
                new List<double> { 1.4, 0.6 },

                new List<double> { 1.5, 2.5 },
                new List<double> { 1.5, 2.4 },
                new List<double> { 1.5, 2.6 },
                new List<double> { 1.6, 2.5 },
                new List<double> { 1.6, 2.4 },
                new List<double> { 1.6, 2.6 },

                new List<double> { 8, 7 },
            };

            var dbscan = new DBScan();
            dbscan.DistanceFunction = new DistanceEuclidian();
            dbscan.MinPts = 2;
            dbscan.Epsilon = 0.29;
            dbscan.Run(points);

            for (var i = 0; i < dbscan.Clusters.Count(); i++)
            {
                Console.WriteLine("Cluster #" + i);
                foreach (var vector in dbscan.Clusters[i].Vectors)
                {
                    Console.WriteLine(string.Join(" ", vector));
                }
            }
        }
        public void RegionQueryPointsListTest()
        {
            var points = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
                new PointIdFloat(new List <float>()
                {
                    3, 3, 3
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 2, 2
                })
            };

            PointIdFloat.SetIds(points);
            var p = new PointIdFloat(new List <float>()
            {
                1.5f, 1.5f, 1.5f
            });
            Func <IPointIdFloat, Tuple <float, float, float> > keySelector = t => Tuple.Create(
                KdTree.KdTreeNode.KeyByDepth(t, 0), 0.0f, 0.0f);

            var result = DBScan.RegionQuery(points, p, 0.16f);

            Assert.IsTrue(result.Count() == 0);

            result = DBScan.RegionQuery(points, p, 1);
            var expectedResult = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 2, 2
                })
            };

            PointIdFloat.SetIds(expectedResult);

            Assert.IsTrue(SequenceEquivalent(result.ToList(), expectedResult, PointIdFloat.PointsComparison));

            p = new PointIdFloat(new List <float>()
            {
                0.75f, 0.75f, 0.75f
            });
            result         = DBScan.RegionQuery(points, p, (float)Math.Sqrt(2f / 3f));
            expectedResult = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
            };
            PointIdFloat.SetIds(expectedResult);

            Assert.IsTrue(SequenceEquivalent(result.ToList(), expectedResult, PointIdFloat.PointsComparison));
        }
        public void RegionQueryKdTreeTest()
        {
            var points = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
                new PointIdFloat(new List <float>()
                {
                    3, 3, 3
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 2, 2
                })
            };

            PointIdFloat.SetIds(points);

            var p = new PointIdFloat(new List <float>()
            {
                1.5f, 1.5f, 1.5f
            });
            KdTree kdt = new KdTree(points);

            var result = kdt.PointsWithinDistance(p, 0.5f);

            Assert.IsTrue(result.Count == 0);

            result = DBScan.RegionQuery(kdt, p, 1);
            var expectedResult = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 2, 2
                })
            };

            PointIdFloat.SetIds(expectedResult);

            Assert.IsTrue(SequenceEquivalent(result.ToList(), expectedResult, PointIdFloat.PointsComparison));

            p = new PointIdFloat(new List <float>()
            {
                0.75f, 0.75f, 0.75f
            });
            result         = kdt.PointsWithinDistance(p, (float)Math.Sqrt(2));
            expectedResult = new List <IPointIdFloat>()
            {
                new PointIdFloat(new List <float>()
                {
                    1, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    2, 1, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 2, 1
                }),
                new PointIdFloat(new List <float>()
                {
                    1, 1, 2
                }),
            };
            PointIdFloat.SetIds(expectedResult);

            Assert.IsTrue(SequenceEquivalent(result.ToList(), expectedResult, PointIdFloat.PointsComparison));
        }
        /// <summary>
        /// Estimates traffic delay from the collection of travel times
        /// </summary>
        /// <param name="travelTimes"></param>
        /// <param name="model"></param>
        void EstimateTrafficDelay(IEnumerable<TravelTime> travelTimes, Model model)
        {
            List<TravelTimeDelay> delays = new List<TravelTimeDelay>();
            foreach (var traveltime in travelTimes) {
                double delay = 0;
                if (model.TrafficSignalsDelay.Probability > 0 && traveltime.Stops.Count > 0)
                    delay = traveltime.TotalTravelTime.TotalSeconds - model.FreeFlowTravelTime - traveltime.Stops.Last().Length.TotalSeconds;
                else
                    delay = traveltime.TotalTravelTime.TotalSeconds - model.FreeFlowTravelTime;

                delay = Math.Max(0, delay);
                delays.Add(new TravelTimeDelay() { TravelTime = traveltime, Delay = delay });
            }

            // avg delay as median of delays
            delays.Sort(new Comparison<TravelTimeDelay>((TravelTimeDelay td1, TravelTimeDelay td2) => td1.Delay.CompareTo(td2.Delay)));
            model.AvgDelay = delays[delays.Count / 2].Delay;

            TrafficDelayMap delaysMap = new TrafficDelayMap(Properties.Settings.Default.ModelResolution, model.FreeFlowTravelTime);

            List<List<TravelTimeDelay>> travelTimeClusters = null;
            DBScan<TravelTimeDelay> clusterAnalyzer = new DBScan<TravelTimeDelay>(new DBScan<TravelTimeDelay>.FindNeighbours(FindNeighbours));
            for (int i = _parameters.Length -1; i >= 0; i--) {
                _parametersIndex = i;

                int desiredClusterSize = (int)Math.Max(Properties.Settings.Default.MinimalClusterSize, travelTimes.Count() * Properties.Settings.Default.ClusterSizePercentage / 100.0);
                int clusterSize = Math.Min(travelTimes.Count(), desiredClusterSize);
                travelTimeClusters = clusterAnalyzer.ClusterAnalysis(delays, clusterSize);

                foreach (var cluster in travelTimeClusters) {
                    TrafficDelayInfo delayInfo = new TrafficDelayInfo();
                    if (_parameters[_parametersIndex].Dates == DatesHandling.Any)
                        delayInfo.AppliesTo = DayOfWeek.Any;
                    else if (_parameters[_parametersIndex].Dates == DatesHandling.WeekendWorkdays)
                        delayInfo.AppliesTo = (DayOfWeek.Workday & DayOfWeekHelper.FromDate(cluster[0].TravelTime.TimeStart)) > 0 ? DayOfWeek.Workday : DayOfWeek.Weekend;
                    else
                        delayInfo.AppliesTo = DayOfWeekHelper.FromDate(cluster[0].TravelTime.TimeStart);

                    cluster.Sort(new Comparison<TravelTimeDelay>((TravelTimeDelay td1, TravelTimeDelay td2) => td1.Delay.CompareTo(td2.Delay)));

                    delayInfo.Delay = cluster.Sum(tt => tt.Delay) / cluster.Count;
                    delayInfo.From = cluster.Min(tt => tt.TravelTime.TimeStart.TimeOfDay).Subtract(new TimeSpan(0, _parameters[_parametersIndex].MembersTimeDifference / 2, 0));
                    if (delayInfo.From < new TimeSpan(0))
                        delayInfo.From = new TimeSpan(0);

                    delayInfo.To = cluster.Max(tt => tt.TravelTime.TimeEnd.TimeOfDay).Add(new TimeSpan(0, _parameters[_parametersIndex].MembersTimeDifference / 2, 0));
                    if (delayInfo.To > new TimeSpan(23, 59, 59)) {
                        delayInfo.To = new TimeSpan(23, 59, 59);
                    }
                    delaysMap.AddDelay(delayInfo.From, delayInfo.To, delayInfo.AppliesTo, delayInfo.Delay);
                }

                if (travelTimeClusters.Sum(cluster => cluster.Count) > Properties.Settings.Default.ClusterAnalysisStopPercentage * delays.Count / 100)
                    break;
            }

            model.TrafficDelay.AddRange(delaysMap.GetDelays());
        }