public static int ScheduleTrains(ProblemInstance problem, IEnumerable <TrainRun> trainRuns) { var nbConflicts = 0; var usedResources = new UsedResourceCollection(); foreach (var trainRun in trainRuns) { // ---------------------------------------------------- //Log($"Delay train {trainRun.ServiceIntentionId} start ? ", Utils.Logging.LogEventArgs.MessageType.Info, false); var delay = TimeSpan.Zero; var initialRunSection = trainRun.TrainRunSections[0]; var initialSection = problem.TryGetRouteSection(initialRunSection.Key); foreach (var resId in initialSection.ResourceIds) { var resource = problem.TryGetResource(resId); if (resource != null) { foreach (var usage in usedResources.UsageByOtherThan(resId, trainRun.ServiceIntentionId)) { if (Math.Intersect(initialRunSection.EntryTime, initialRunSection.ExitTime + resource.ReleaseTime, usage.Item3, usage.Item4)) { delay = Math.Max(delay, usage.Item4 - initialRunSection.EntryTime); } } } } // Postpone train departure if (delay > TimeSpan.Zero) { ++nbConflicts; //Log($"Yes. Delay is {delay}"); initialRunSection.EntryTime += delay; trainRun.ApplyDelay(delay); } //Log($"Check other sections for delays ... "); for (int k = 1; k < trainRun.TrainRunSections.Count; ++k) { var runSection = trainRun.TrainRunSections[k]; var section = problem.TryGetRouteSection(runSection.Key); // Check resource occupation for next section delay = TimeSpan.Zero; foreach (var resId in section.ResourceIds) { var resource = problem.TryGetResource(resId); if (resource != null) { foreach (var usage in usedResources.UsageByOtherThan(resId, trainRun.ServiceIntentionId)) { if (Math.Intersect(runSection.EntryTime, runSection.ExitTime + resource.ReleaseTime, usage.Item3, usage.Item4)) { delay = Math.Max(delay, usage.Item4 - runSection.EntryTime); } } } } if (delay > TimeSpan.Zero) { ++nbConflicts; //Log($"Delay exit of train {trainRun.ServiceIntentionId}, from section {k-1} by {delay}"); trainRun.ApplyDelay(delay, k - 1); } } // ---------------------------------------------------- //Log($"Add current train resource occupation ... "); foreach (var runSection in trainRun.TrainRunSections) { var section = problem.TryGetRouteSection(runSection.Key); foreach (var resId in section.ResourceIds) { var resource = problem.TryGetResource(resId); if (resource != null) { usedResources.Add(resId, trainRun.ServiceIntentionId, runSection.SequenceNumber, runSection.EntryTime, runSection.ExitTime + resource.ReleaseTime); } } } } return(nbConflicts); }
public static void ScheduleTrains(ProblemInstance problem, IEnumerable <TrainRun> trainRuns, UsedResourceCollection usedResources) { foreach (var trainRun in trainRuns) { // Schedule train accordingly for (int k = 0; k < trainRun.TrainRunSections.Count; ++k) { var thisRunSection = trainRun.TrainRunSections[k]; var nextRunSection = (k < trainRun.TrainRunSections.Count - 1) ? trainRun.TrainRunSections[k + 1] : null; var thisSection = problem.TryGetRouteSection(thisRunSection.Key); var nextSection = problem.TryGetRouteSection(nextRunSection?.Key); // ------------------------------------------------ // Is there a min entry/exit time var thisRequirement = trainRun.Train.GetRequirement(thisSection.SectionMarker); var nextRequirement = trainRun.Train.GetRequirement(nextSection?.SectionMarker); // ------------------------------------------------ // Start time is always last exit time unless this is the first section if (k > 0) { thisRunSection.EntryTime = trainRun.TrainRunSections[k - 1].ExitTime; } else { thisRunSection.EntryTime = Math.Max(thisRunSection.EntryTime, thisRequirement.minEntryTime); // Check resource occupation if (nextRunSection != null) { foreach (var resId in thisSection.ResourceIds) { foreach (var usage in usedResources.UsageByOtherThan(resId, trainRun.ServiceIntentionId)) { thisRunSection.EntryTime = Math.Max(thisRunSection.EntryTime, usage.Item4); } } } } // ------------------------------------------------ // Set exit time, taking into acount resource occupation of next section thisRunSection.ExitTime = Math.Max(thisRequirement.minExitTime, thisRunSection.EntryTime + thisSection.MinimumRunningTime + thisRequirement.minStoppingTime); // Consider minEntryTime for next section thisRunSection.ExitTime = Math.Max(thisRunSection.ExitTime, nextRequirement.minEntryTime); // Check resource occupation if (nextRunSection != null) { foreach (var resId in nextSection.ResourceIds) { foreach (var usage in usedResources.UsageByOtherThan(resId, trainRun.ServiceIntentionId)) { thisRunSection.ExitTime = Math.Max(thisRunSection.ExitTime, usage.Item4); } } } // ------------------------------------------------ // Add current resource occupation foreach (var resId in thisSection.ResourceIds) { var resource = problem.TryGetResource(resId); if (resource != null) { usedResources.Add(resId, trainRun.ServiceIntentionId, thisRunSection.SequenceNumber, thisRunSection.EntryTime, thisRunSection.ExitTime + resource.ReleaseTime); } } } } }