Пример #1
0
        public void DoClusters(out CostMatrix CostMatrix, out List<CityNodeData> CityData, 
            out List<CityCluster> CityClusters, out Dictionary<int, CityCluster> CityToClusterItsIn,
            out Dictionary<int, int> SizeClusterToNumberOfThatSize)
        {
            CostMatrix = new CostMatrix(Cities);
                _costMatrix = CostMatrix;
                Stopwatch clusterWatch = new Stopwatch();
                clusterWatch.Start();
                CityData = new List<CityNodeData>();
                _cityNodes = CityData;
                for (int i = 0; i < CostMatrix.Size; i++)
                {
                    CityData.Add(new CityNodeData(i, CostMatrix, Cities));
                }

                //Clustering
                double threshold = CostMatrix.DistanceRange * _clusterPercent;
                _threshold = (float)threshold;
                List<CityNodeData> citiesSortedByNumberUnderThreshold = new List<CityNodeData>(CityData);
                citiesSortedByNumberUnderThreshold.Sort((a, b) =>
                    (a.AverageWorstDistanceOfBelowThreshold(threshold).CompareTo(
                    b.AverageWorstDistanceOfBelowThreshold(threshold))));

                List<List<CityNodeData>> finalClusters = new List<List<CityNodeData>>();
                List<CityNodeData> visited = new List<CityNodeData>(CityData);
                Dictionary<CityNodeData, int> clusterAssignment = new Dictionary<CityNodeData, int>();
                foreach (CityNodeData c in visited)
                {
                    clusterAssignment.Add(c, -1);
                }

                while (citiesSortedByNumberUnderThreshold.Count > 0)
                {
                    List<CityNodeData> curCluster = new List<CityNodeData>();
                    CityNodeData cur = citiesSortedByNumberUnderThreshold[0];
                    clusterAssignment[cur] = finalClusters.Count;

                    citiesSortedByNumberUnderThreshold.RemoveAt(0);
                    visited.Remove(cur);
                    curCluster.Add(cur);

                    for (int i = 0; i < cur.SortedWorstDistance.Count; i++)
                    {
                        bool canAdd = true;
                        CityNodeData curCloseCheck = CityData[cur.SortedWorstDistance[i].CityId];
                        if (!visited.Contains(curCloseCheck))
                        {
                            continue;
                        }
                        foreach (CityNodeData inCluster in curCluster)
                        {
                            double worstDistance = CostMatrix.WorstDistanceBetween(inCluster.CityId, curCloseCheck.CityId);
                            if (worstDistance > threshold)
                            {
                                canAdd = false;
                                break;
                            }
                        }

                        if (canAdd)
                        {
                            curCluster.Add(curCloseCheck);
                            visited.Remove(curCloseCheck);
                            citiesSortedByNumberUnderThreshold.Remove(curCloseCheck);
                        }
                    }

                    finalClusters.Add(curCluster);
                }
                clusterWatch.Stop();
                Console.WriteLine("SAVED: " + (CostMatrix.Size - finalClusters.Count));
                _storedClusters = finalClusters;

                CityClusters = new List<CityCluster>();
                CityToClusterItsIn = new Dictionary<int, CityCluster>();
                SizeClusterToNumberOfThatSize = new Dictionary<int, int>();
                foreach (List<CityNodeData> clust in finalClusters)
                {
                    CityCluster actualCluster = new CityCluster(clust, CityData, CostMatrix);
                    CityClusters.Add(actualCluster);
                    foreach (int city in actualCluster.ContainedCityIds)
                    {
                        CityToClusterItsIn.Add(city, actualCluster);
                    }
                    if (!SizeClusterToNumberOfThatSize.ContainsKey(clust.Count))
                    {
                        SizeClusterToNumberOfThatSize.Add(clust.Count, 0);
                    }
                    SizeClusterToNumberOfThatSize[clust.Count] =
                        SizeClusterToNumberOfThatSize[clust.Count] + 1;
                }
        }
Пример #2
0
        public static int ShortedValidEdgeBetweenClusters(CityCluster from, CityCluster to)
        {
            foreach (int edgeId in from._outgoingEdgesSortedByDistance)
            {
                KeyValuePair<int, int> coords = from._costMatrix.EdgeCoords(edgeId);
                if (from._cityEntryPoint != coords.Key || from._containedCities.Count == 1)
                {
                    //If valid to leave from here
                    if (to.ContainedCityIds.Contains(coords.Value))
                    {
                        //If target has this city
                        if (to._cityExitPoint != coords.Value || to._containedCities.Count == 1)
                        {
                            //If target city is valid
                            from.OutgoingOnEdge(edgeId);
                            to.IncomingFromEdge(edgeId);
                            return edgeId;
                        }
                    }
                }

            }

            return -1;
        }