public List <RubisStation> Calculate(List <OHCAEvent> eventList, int budget) { List <RubisStation> prevStationList = new List <RubisStation>(); List <RubisStation> nextStationList; double epsilonTemp = 0.1; double alpha = 0.995; double bestSurvivalRate = 0.0; int tempBudget; int maxStations = (int)(budget / (Utils.STATION_PRICE + Utils.DRONE_PRICE)); //for (int stations = 1; stations <= maxStations; stations++) int stations = 16; tempBudget = budget; // Step 1. Finds initial stations with a drone using K-Means tempBudget = tempBudget - (stations * (Utils.STATION_PRICE + Utils.DRONE_PRICE)); KMeansResults <OHCAEvent> kMeansStations = KMeans.Cluster <OHCAEvent>(eventList.ToArray(), stations, Utils.KMEANS_ITERATION_COUNT); prevStationList.Clear(); foreach (double[] d in kMeansStations.Means) { prevStationList.Add(new RubisStation(d[0], d[1], 2)); } // Step 2. Assigns remaining drones to busy stations /*int remainingDrones = (int)(tempBudget / Utils.DRONE_PRICE); * while (remainingDrones > 0) * { * int mostBusyStationIndex = getIndexOfMostBusyStation(prevStationList); * prevStationList[mostBusyStationIndex].droneList.Add(new Drone(prevStationList[mostBusyStationIndex].stationID)); * remainingDrones--; * } */ // Step 4. Simulated Annealing double currentTemp = 100.0; int iteration = 0; double prevSurvivalRate = GetOverallSurvivalRate(ref prevStationList); double delta = 0.0; double nextSurvivalRate = 0.0; while (currentTemp > epsilonTemp) { iteration++; // Near search using local optimization nextStationList = MoveOneStepToBestDirection(prevStationList, prevSurvivalRate); nextSurvivalRate = GetOverallSurvivalRate(ref nextStationList); delta = nextSurvivalRate - prevSurvivalRate; if (delta > 0) { CloneList(nextStationList, prevStationList); prevSurvivalRate = nextSurvivalRate; } else { // Even if worst, choose it randomly according to the current temperature double probility = new Random().NextDouble(); if (probility < Math.Exp(-delta / currentTemp)) { // Far search using random placement nextStationList = FindRandomStationPlacement(prevStationList, 0); CloneList(nextStationList, prevStationList); prevSurvivalRate = GetOverallSurvivalRate(ref prevStationList); if (prevSurvivalRate < bestSurvivalRate * 0.9) //double r = new Random().NextDouble(); //if (r < 0.1) { /* * kMeansStations = KMeans.Cluster<OHCAEvent>(eventList.ToArray(), stations, new Random().Next(50, 100)); * foreach (double[] d in kMeansStations.Means) * { * prevStationList.Add(new RubisStation(d[0], d[1], 2)); * }*/ Random rand = new Random(); bool okay = false; while (!okay) { int pos = rand.Next(0, 990000); kMeansStations = KMeans.Cluster <OHCAEvent>(simulator.GetSimulatedEvents().GetRange(pos, 10000).ToArray(), stations, Utils.KMEANS_ITERATION_COUNT); okay = true; foreach (double[] d in kMeansStations.Means) { if (d[0] == 0.0 || d[1] == 0.0) { okay = false; break; } } } prevStationList.Clear(); foreach (double[] d in kMeansStations.Means) { prevStationList.Add(new RubisStation(d[0], d[1], 2)); } /* * remainingDrones = (int)(tempBudget / Utils.DRONE_PRICE); * while (remainingDrones > 0) * { * int mostBusyStationIndex = getIndexOfMostBusyStation(prevStationList); * prevStationList[mostBusyStationIndex].droneList.Add(new Drone(prevStationList[mostBusyStationIndex].stationID)); * remainingDrones--; * } */ prevSurvivalRate = GetOverallSurvivalRate(ref prevStationList); } } } // Keep the best solution if (prevSurvivalRate > bestSurvivalRate) { CloneList(prevStationList, stationList); bestSurvivalRate = prevSurvivalRate; } // Cool-down currentTemp *= alpha; Console.WriteLine("[" + iteration + "] Stations = " + stations + ", Temp.: " + String.Format("{0:0.000000000000}", currentTemp) + "℃ " + "Best = " + String.Format("{0:0.000000}", (bestSurvivalRate * 100)) + "% " + "Current = " + String.Format("{0:0.000000}", (prevSurvivalRate * 100)) + "%"); } return(stationList); }