private static Solution OptimizeCycleDuration(Problem problem, Solution solution) { Solution bestSolution = null; int bestSolutionScore = -1; int timesSinceOptimized = 0; while (timesSinceOptimized < 10) { timesSinceOptimized++; SimulationResult simulationResult = problem.RunSimulation(solution); if (simulationResult.Score > bestSolutionScore) { bestSolution = (Solution)solution.Clone(); bestSolutionScore = simulationResult.Score; timesSinceOptimized = 0; } Console.WriteLine("Score: {0}, Max Blocked Traffic: {1}, Best score: {2}", simulationResult.Score, simulationResult.GetMaxBlockedTraffic(), bestSolutionScore); List <SimulationResult.IntersectionResult> intersectionResults = simulationResult.IntersectionResults.OrderByDescending(o => o.MaxStreetBlockedTraffic).ToList(); // Remove intersection without blocked cars for (int i = 0; i < intersectionResults.Count; i++) { if (intersectionResults[i].MaxStreetBlockedTraffic == 0) { intersectionResults.RemoveAt(i); i--; } } // Nothing to optimize - break if (intersectionResults.Count == 0) { break; } // Add cycle time for the top blocked cars for (int i = 0; i < intersectionResults.Count / 50; i++) { SimulationResult.IntersectionResult intersectionResult = intersectionResults[i]; SolutionIntersection intersection = solution.Intersections[intersectionResult.ID]; foreach (GreenLightCycle greenLightCycle in intersection.GreenLigths) { if (greenLightCycle.Street.Name.Equals(intersectionResult.MaxStreetName)) { greenLightCycle.Duration++; } } } } return(bestSolution); }
public object Clone() { SolutionIntersection solutionIntersection = new SolutionIntersection(this.ID); solutionIntersection.GreenLigths = new List <GreenLightCycle>(); foreach (GreenLightCycle cycle in this.GreenLigths) { solutionIntersection.GreenLigths.Add((GreenLightCycle)cycle.Clone()); } return(solutionIntersection); }
/// <summary> /// Optimize green light by runnig full simulation & try to change the order of the green lights /// to make the cars pass intersections without waiting. /// </summary> /// <returns></returns> public int OptimizeGreenLightOrder(Solution solution) { int score = 0; int currentTime = 0; foreach (SolutionIntersection intersetion in solution.Intersections) { foreach (GreenLightCycle greenLightCycle in intersetion.GreenLigths) { greenLightCycle.GreenLightUsed = false; } } // Create list of cars in simulation List <CarSimultionPosition> carSimultionPositions = new List <CarSimultionPosition>(); int simulationCarStart = -(this.Cars.Count + 1); foreach (Car car in this.Cars) { carSimultionPositions.Add(new CarSimultionPosition(car, simulationCarStart)); simulationCarStart++; } // Init green lights foreach (SolutionIntersection intersection in solution.Intersections) { intersection.CurrentGreenLigth = 0; if (intersection.GreenLigths.Count > 0) { intersection.CurrentGreenLightChangeTime = intersection.GreenLigths[0].Duration; } else { intersection.CurrentGreenLightChangeTime = int.MaxValue; } } while (currentTime <= this.Duration) { // Update traffic lights cycle foreach (SolutionIntersection intersection in solution.Intersections) { if (intersection.CurrentGreenLightChangeTime <= currentTime) { intersection.CurrentGreenLigth = (intersection.CurrentGreenLigth + 1) % intersection.GreenLigths.Count; intersection.CurrentGreenLightChangeTime = currentTime + intersection.GreenLigths[intersection.CurrentGreenLigth].Duration; } } // Update cars HashSet <int> usedIntersection = new HashSet <int>(); for (int i = 0; i < carSimultionPositions.Count; i++) { CarSimultionPosition carSimultionPosition = carSimultionPositions[i]; if (carSimultionPosition.TimeGotHere > currentTime) { break; } Street street = carSimultionPosition.Car.Streets[carSimultionPosition.StreetNumber]; // Check if a car already used this intersection this cycle if (usedIntersection.Contains(street.EndIntersection)) { continue; } SolutionIntersection intersection = solution.Intersections[street.EndIntersection]; // Not green light, try swapping to green light if (!street.Name.Equals(intersection.GreenLigths[intersection.CurrentGreenLigth].Street.Name)) { // Green light already used - can't do it if (intersection.GreenLigths[intersection.CurrentGreenLigth].GreenLightUsed) { continue; } // Find required green light int requiredGreenLight = -1; for (int g = 0; g < intersection.GreenLigths.Count; g++) { if (street.Name.Equals(intersection.GreenLigths[g].Street.Name)) { requiredGreenLight = g; break; } } // Required green light not found - skip if (requiredGreenLight == -1) { continue; } // Required green light already used - skip if (intersection.GreenLigths[requiredGreenLight].GreenLightUsed) { continue; } // Swap possible only if it's the same green light duration if (intersection.GreenLigths[requiredGreenLight].Duration != intersection.GreenLigths[intersection.CurrentGreenLigth].Duration) { continue; } // Swap green lights - now the car can continue! GreenLightCycle tmp = intersection.GreenLigths[requiredGreenLight]; intersection.GreenLigths[requiredGreenLight] = intersection.GreenLigths[intersection.CurrentGreenLigth]; intersection.GreenLigths[intersection.CurrentGreenLigth] = tmp; } // Mark intersection as used for this cycle usedIntersection.Add(street.EndIntersection); // Mark green light used - changing no longer possible intersection.GreenLigths[intersection.CurrentGreenLigth].GreenLightUsed = true; // Process car green light carSimultionPosition.StreetNumber++; carSimultionPosition.TimeGotHere = currentTime + carSimultionPosition.Car.Streets[carSimultionPosition.StreetNumber].Length; // Check if car finished if (carSimultionPosition.StreetNumber == carSimultionPosition.Car.Streets.Count - 1) { // Check if finished on time - if so give bonus if (carSimultionPosition.TimeGotHere <= this.Duration) { score += this.BonusPerCar + (this.Duration - carSimultionPosition.TimeGotHere); } carSimultionPositions.RemoveAt(i); i--; } } // Sort cars by time carSimultionPositions.Sort((x, y) => x.TimeGotHere.CompareTo(y.TimeGotHere)); currentTime++; } return(score); }
public SimulationResult RunSimulation(Solution solution) { SimulationResult simulationResult = new SimulationResult(this.Intersections.Count); int currentTime = 0; // Create list of cars in simulation List <CarSimultionPosition> carSimultionPositions = new List <CarSimultionPosition>(); int simulationCarStart = -(this.Cars.Count + 1); foreach (Car car in this.Cars) { carSimultionPositions.Add(new CarSimultionPosition(car, simulationCarStart)); simulationCarStart++; } // Init green lights foreach (SolutionIntersection intersection in solution.Intersections) { intersection.CurrentGreenLigth = 0; if (intersection.GreenLigths.Count > 0) { intersection.CurrentGreenLightChangeTime = intersection.GreenLigths[0].Duration; } else { intersection.CurrentGreenLightChangeTime = int.MaxValue; } } while (currentTime <= this.Duration) { // Update traffic lights cycle foreach (SolutionIntersection intersection in solution.Intersections) { if (intersection.CurrentGreenLightChangeTime <= currentTime) { intersection.CurrentGreenLigth = (intersection.CurrentGreenLigth + 1) % intersection.GreenLigths.Count; intersection.CurrentGreenLightChangeTime = currentTime + intersection.GreenLigths[intersection.CurrentGreenLigth].Duration; } } // Update cars HashSet <int> usedIntersection = new HashSet <int>(); for (int i = 0; i < carSimultionPositions.Count; i++) { CarSimultionPosition carSimultionPosition = carSimultionPositions[i]; if (carSimultionPosition.TimeGotHere > currentTime) { break; } Street street = carSimultionPosition.Car.Streets[carSimultionPosition.StreetNumber]; // Check if a car already used this intersection this cycle if (usedIntersection.Contains(street.EndIntersection)) { simulationResult.IntersectionResults[street.EndIntersection].AddBlockedTraffic(street.Name); continue; } SolutionIntersection intersection = solution.Intersections[street.EndIntersection]; // Not green light, skip to next car if (!street.Name.Equals(intersection.GreenLigths[intersection.CurrentGreenLigth].Street.Name)) { simulationResult.IntersectionResults[street.EndIntersection].AddBlockedTraffic(street.Name); continue; } // Mark intersection as used for this cycle usedIntersection.Add(street.EndIntersection); // Process car green light carSimultionPosition.StreetNumber++; carSimultionPosition.TimeGotHere = currentTime + carSimultionPosition.Car.Streets[carSimultionPosition.StreetNumber].Length; // Check if car finished if (carSimultionPosition.StreetNumber == carSimultionPosition.Car.Streets.Count - 1) { // Check if finished on time - if so give bonus if (carSimultionPosition.TimeGotHere <= this.Duration) { simulationResult.Score += this.BonusPerCar + (this.Duration - carSimultionPosition.TimeGotHere); } carSimultionPositions.RemoveAt(i); i--; } } // Sort cars by time carSimultionPositions.Sort((x, y) => x.TimeGotHere.CompareTo(y.TimeGotHere)); currentTime++; } return(simulationResult); }