public IEnumerable <(string trainId, int sectionId, DateTime start, DateTime end)> TryAdd(string resId, string trainId, int sequenceNumber, DateTime entry, DateTime exit) { if (!_container.ContainsKey(resId)) { _container.Add(resId, new Dictionary <string, Dictionary <int, Tuple <DateTime, DateTime> > >()); } if (!_container[resId].ContainsKey(trainId)) { _container[resId].Add(trainId, new Dictionary <int, Tuple <DateTime, DateTime> >()); } // Look for conflicts foreach (var collection in _container[resId].Where(kvp => kvp.Key != trainId)) { foreach (var keyVal in collection.Value) { if (Math.Intersect(entry, exit, keyVal.Value.Item1, keyVal.Value.Item2)) { yield return(collection.Key, keyVal.Key, keyVal.Value.Item1, keyVal.Value.Item2); // Means this period intersect an existing one } } } _container[resId][trainId][sequenceNumber] = new Tuple <DateTime, DateTime>(entry, exit); }
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); }