public CityCluster(List<CityNodeData> Cities, List<CityNodeData> AllCities, CostMatrix costMatrix) { _containedCities = new List<CityNodeData>(Cities); _allCities = new List<CityNodeData>(AllCities); _costMatrix = costMatrix; _cityEntryPoint = -1; _cityExitPoint = -1; _incomingEdgesSortedByDistance = new List<int>(); _outgoingEdgesSortedByDistance = new List<int>(); _incomingEdgesByCitySortedByDistance = new Dictionary<int, List<int>>(); _outgoingEdgesByCitySortedByDistance = new Dictionary<int, List<int>>(); foreach (CityNodeData innerCity in _containedCities) { int innerCityId = innerCity.CityId; foreach (CityNodeData outerCity in AllCities) { if (!_containedCities.Contains(outerCity)) { int outerCityId = outerCity.CityId; if (!_incomingEdgesByCitySortedByDistance.ContainsKey(outerCityId)) { _incomingEdgesByCitySortedByDistance.Add(outerCityId, new List<int>()); } if (!_outgoingEdgesByCitySortedByDistance.ContainsKey(outerCityId)) { _outgoingEdgesByCitySortedByDistance.Add(outerCityId, new List<int>()); } int incomingId = costMatrix.EdgeId(outerCityId, innerCityId); int outgoingId = costMatrix.EdgeId(innerCityId, outerCityId); _incomingEdgesSortedByDistance.Add(incomingId); _incomingEdgesByCitySortedByDistance[outerCityId].Add(incomingId); _outgoingEdgesSortedByDistance.Add(outgoingId); _outgoingEdgesByCitySortedByDistance[outerCityId].Add(outgoingId); } } } _incomingEdgesSortedByDistance.Sort((a, b) => costMatrix.CostAtEdgeId(a).CompareTo(costMatrix.CostAtEdgeId(b)) ); _outgoingEdgesSortedByDistance.Sort((a, b) => costMatrix.CostAtEdgeId(a).CompareTo(costMatrix.CostAtEdgeId(b))); ContainedCityIds = new List<int>(); foreach (CityNodeData city in _containedCities) { ContainedCityIds.Add(city.CityId); } }
public double SolveExternalClusters(CostMatrix costMatrix, List<CityNodeData> CityData, List<CityCluster> cityClusters, Dictionary<int, CityCluster> cityToClusterItsIn, out List<int> interNodeEdges) { int startingEdge = -1; foreach (int i in costMatrix.AllEdgesSortedByDistance) { KeyValuePair<int, int> coords = costMatrix.EdgeCoords(i); if (!cityToClusterItsIn[coords.Key].Equals(cityToClusterItsIn[coords.Value])) { startingEdge = i; break; } } KeyValuePair<int, int> curCoords = costMatrix.EdgeCoords(startingEdge); CityCluster curFromCluster = cityToClusterItsIn[curCoords.Key]; List<int> visitedCities = new List<int>(); List<CityCluster> clustersVisitedInOrder = new List<CityCluster>(); interNodeEdges = new List<int>(); clustersVisitedInOrder.Add(cityToClusterItsIn[curCoords.Key]); visitedCities.AddRange(cityToClusterItsIn[curCoords.Key].ContainedCityIds); cityToClusterItsIn[curCoords.Value].IncomingFromEdge(startingEdge); cityToClusterItsIn[curCoords.Key].OutgoingOnEdge(startingEdge); interNodeEdges.Add(startingEdge); while (interNodeEdges.Count < cityClusters.Count - 1) { curFromCluster = cityToClusterItsIn[curCoords.Value]; int newEdgeId = curFromCluster.GetShortestValidOutgoingEdgeIgnoringCities(visitedCities); curCoords = costMatrix.EdgeCoords(newEdgeId); cityToClusterItsIn[curCoords.Value].IncomingFromEdge(newEdgeId); cityToClusterItsIn[curCoords.Value].OutgoingOnEdge(newEdgeId); clustersVisitedInOrder.Add(curFromCluster); visitedCities.AddRange(curFromCluster.ContainedCityIds); interNodeEdges.Add(newEdgeId); } CityCluster end = cityToClusterItsIn[curCoords.Value]; CityCluster start = clustersVisitedInOrder[0]; int lastEdge = CityCluster.ShortedValidEdgeBetweenClusters(end, start); interNodeEdges.Add(lastEdge); _interNodeEdges = interNodeEdges; double retVal = 0; foreach (int edge in interNodeEdges) { retVal += costMatrix.CostAtEdgeId(edge); } return retVal; }
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; } }
private TSPSolution Solve(CostMatrix costMatrix, List<CityNodeData> CityData, List<CityCluster> cityClusters, Dictionary<int, CityCluster> cityToClusterItsIn, List<int> interNodeEdges) { List<int> allEdges = new List<int>(); ArrayList sol = new ArrayList(); foreach (int edge in interNodeEdges) { KeyValuePair<int, int> coords = costMatrix.EdgeCoords(edge); CityCluster target = cityToClusterItsIn[coords.Value]; allEdges.Add(edge); List<int> edgesSolved = target.GreedySolveEdges(); if (edgesSolved.Count == 0) { sol.Add(Cities[target.ContainedCityIds[0]]); } else { for (int i = 0; i < edgesSolved.Count; i++) { int curEdge = edgesSolved[i]; KeyValuePair<int, int> innerCoords = costMatrix.EdgeCoords(curEdge); if (i == 0) { sol.Add(Cities[innerCoords.Key]); } sol.Add(Cities[innerCoords.Value]); allEdges.Add(curEdge); } } } return new TSPSolution(sol); }