public static Func <Operation, bool> NeighbourSelector(IGraphLayer graph, Route route, int rank) { HashSet <int> current = route.Select(op => op.Id).ToHashSet(); for (int i = 0; i < rank; i++) { HashSet <int> next = new HashSet <int>(); foreach (int i1 in current) { foreach (int i2 in graph.OutgoingArcs(i1).Select(a => a.Head)) { next.Add(i2); } foreach (int i2 in graph.IncomingArcs(i1).Select(a => a.Tail)) { next.Add(i2); } } current.UnionWith(next); } return(op => current.Contains(op.Id)); }
public ISequencingLayer Clone() { IGraphLayer graphClone = GraphLayer.Clone(); return(new SequencingLayer( _sequences.Select(p => p.Clone(graphClone)).ToArray(), graphClone)); }
/// <summary> /// Creates an empty MachineLayer; No disjunctive arcs shall be present. /// </summary> public SequencingLayer(IGraphLayer graphLayer) { GraphLayer = graphLayer; _sequences = new IJobSequence[Problem.MachineAndConnectionCount]; for (int i = 0; i < Problem.MachineAndConnectionCount; i++) { _sequences[i] = new JobSequence(i, GraphLayer); } }
public static void DoCheck(IGraphLayer graphLayer) { var costLayer = graphLayer.CostLayer; var solution = costLayer.Solution; if (!TimesGraphChecks.On) { return; } Assert(TimesGraphChecks, graphLayer.IsAcyclic()); for (int i = 0; i < graphLayer.Count; i++) { var actualEntryTime = solution.GetEntryTime(i); TimeSpan shouldBe; if (solution.GetRoute(i, canBeNull: true) == null || // if no route set. solution.GetOperation(i, canBeNull: true) == null) // if the current route is short. { shouldBe = TimeSpan.Zero; } else { shouldBe = graphLayer.IncomingArcs(i) .Select(ia => solution.GetEntryTime(ia.Tail) + ia.Length) .Append(solution.GetOperation(i).EarliestEarliestEntry) .Max(); } var deltaTicks = Math.Abs(shouldBe.Ticks - actualEntryTime.Ticks); if (deltaTicks > 0) { Assert(TimesGraphChecks, false, CreateDebugMessageOnDetectedTimeInconsistency(graphLayer, i)); } } }
public static void VisualizeRelevant( this IGraphLayer graphLayer) { Console.WriteLine($"Visualizing graph."); var solution = graphLayer.CostLayer.Solution; var problem = solution.Problem; TimeSpan[] delayAvoidingEntryTimes = new TimeSpan[graphLayer.Count]; foreach (int v in graphLayer.TopologicalOrder().Reverse()) { var op = solution.GetOperation(v); delayAvoidingEntryTimes[v] = graphLayer .OutgoingArcs(v) .Select(a => delayAvoidingEntryTimes[a.Head] - a.Length) .Prepend(op.DelayWeight > 0? op.LatestEntry : TimeSpan.MaxValue) .Prepend(TimeSpan.MaxValue) .Min(); } bool[] select = new bool[graphLayer.Count]; for (int i = 0; i < graphLayer.Count; i++) { if (solution.GetOperation(i, canBeNull: true) != null && solution.GetEntryTime(i) > delayAvoidingEntryTimes[i]) { select[i] = true; } } Console.WriteLine($"Selecting {select.Count(x => x)} of {graphLayer.Count} nodes."); graphLayer.Visualize( op => select[op.Id], null, op => $"avoiding={delayAvoidingEntryTimes[op.Id].Show()}"); }
public static void Check( Problem problem, ISolution solution, IGraphLayer graphLayer, ISequencingLayer sequencingLayer) { if (!Switch.On) { return; } Asserts.Assert(Switch, graphLayer.Count == problem.OperationCount); IGraph newGraph = new Graph(graphLayer.Count); foreach (Route route in problem.Select(j => solution.GetRoute(j, canBeNull: true)).Where(r => r != null)) { foreach (var(op0, op1) in route.Pairwise()) { newGraph.AddArc(op0.Id, op1.Id, -1, op0.Runtime); } } foreach (IJobSequence permutation in sequencingLayer) { foreach (var(mOcc0, mOcc1) in permutation.Pairwise()) { newGraph.AddArc( mOcc0.LastOperation + 1, mOcc1.FirstOperation, mOcc0.MachineId, solution.GetMachineReleaseTime(mOcc0, mOcc1)); } } Asserts.Assert(Switch, newGraph.Equals(graphLayer), "1 = graphLayer, 2 = implicit graph\n" + graphLayer.DifferencesToString(newGraph)); }
public static string CreateDebugMessageOnDetectedTimeInconsistency(IGraphLayer graphLayer, int vertex) { var solution = graphLayer.CostLayer.Solution; if (solution.GetRoute(vertex, canBeNull: true) == null) { return("Inconsistent time at a vertex along a critical path:\n" + "\tIf no route is set, the entry time must be 0, but is " + solution.GetEntryTime(vertex).Show() + "\n"); } StringBuilder report = new StringBuilder() .AppendLine("Inconsistent time at a vertex along a critical path:") .Append($"\ttime @ {vertex} = ") .AppendLine(solution.GetEntryTime(vertex).Show()) .Append($"\tearliest entry time @ {vertex} = ") .AppendLine(solution.GetOperation(vertex).EarliestEarliestEntry.Show()) .Append($"\t(latest entry @ {vertex} = ") .Append(solution.GetOperation(vertex).LatestEntry.Show()) .AppendLine(")"); report.AppendLine(graphLayer.IncomingArcs(vertex).Any() ? $"\tthere are the following ({graphLayer.IncomingArcs(vertex).Count()}) incoming arcs: " : "\tthere are no incoming arcs."); foreach (Arc incomingArc in graphLayer.IncomingArcs(vertex)) { report.Append("\t\t").Append(incomingArc).Append(": ") .Append($"length = {incomingArc.Length.Show()}, ") .Append($"time@{incomingArc.Tail} = {solution.GetEntryTime(incomingArc.Tail).Show()}") .Append(", hence: entryTime >= ") .AppendLine((solution.GetEntryTime(incomingArc.Tail) + incomingArc.Length).Show()); } return(report.ToString()); }
private SequencingLayer(IJobSequence[] sequences, IGraphLayer graphLayer) { GraphLayer = graphLayer; _sequences = sequences; }
public static void Visualize( this IGraphLayer graphLayer, Func <Operation, bool> opSelector = null, Func <Arc, bool> arcSelector = null, Func <Operation, string> additionalOpLabel = null) { GraphvizWrapper.Graph g = new GraphvizWrapper.Graph(); opSelector = opSelector ?? (x => true); arcSelector = arcSelector ?? (x => true); additionalOpLabel = additionalOpLabel ?? (x => ""); HashSet <Arc> allCriticalArcs; if (graphLayer.TimesAreUpToDate()) { allCriticalArcs = graphLayer.GetCriticalArcs(onlyDisjunctive: false).ToHashSet(); } else { allCriticalArcs = new HashSet <Arc>(); } Func <Operation, bool> opAndCriticalSelector = x => opSelector(x) || allCriticalArcs.Any(a => a.Head == x.Id || a.Tail == x.Id); Dictionary <Operation, Node> nodes = new Dictionary <Operation, Node>(); var solution = graphLayer.CostLayer.Solution; var problem = solution.Problem; var colors = ColorScale.ShuffledPalette(problem.JobCount); var connectedComponents = graphLayer.GetNonTrivialScc().SelectMany(x => x).ToHashSet(); foreach (var job in problem.Jobs) { Route route = solution.GetRoute(job); foreach (var op in route.Operations.Where(opAndCriticalSelector)) { StringBuilder label = new StringBuilder(); label.AppendLine($"id={op.Id}") .AppendLine($"time={solution.GetEntryTime(op.Id).Show()}") .AppendLine($"earliest={solution.GetOperation(op.Id).EarliestEarliestEntry.Show()}") .AppendLine($"latest={solution.GetOperation(op.Id).LatestEntry.Show()}"); if (op.DelayWeight > 0) { label.AppendLine($"weight={op.DelayWeight}"); if (graphLayer.CostLayer.GetCostAtOperation(op.Id) > 0) { label.AppendLine($"cost={Math.Round(graphLayer.CostLayer.GetCostAtOperation(op.Id))}"); } } var additional = additionalOpLabel(op); if (!string.IsNullOrWhiteSpace(additional)) { label.AppendLine(additional); } if (graphLayer.OutgoingArcs(op.Id).Where(arcSelector).Any() || graphLayer.IncomingArcs(op.Id).Where(arcSelector).Any()) { var n = new Node() { Label = label.ToString(), Shape = NodeShape.Box, FillColor = colors[job.Id], Style = NodeStyle.Filled, FontColor = connectedComponents.Contains(op.Id)? Color.Red : Color.Black }; nodes.Add(op, n); } } } g.AddNodes(nodes.Values); Console.WriteLine($"Nodes added."); foreach (var arc in Enumerable.Range(0, graphLayer.Count) .SelectMany(graphLayer.OutgoingArcs) .Where(arcSelector)) { if (nodes.TryGetValue(solution.GetOperation(arc.Tail), out var n0) && nodes.TryGetValue(solution.GetOperation(arc.Head), out var n1)) { var label = (arc.MachineId != -1 ? $"M={arc.MachineId} " : "") + $"t={arc.Length.Show()}"; var edge = new Edge(n0, n1) { Label = label, Style = arc.MachineId == -1 ? EdgeStyle.Solid : EdgeStyle.Dashed, Color = allCriticalArcs.Contains(arc) ? Color.Red : Color.Black, }; if (solution.GetEntryTime(arc.Tail) + arc.Length == solution.GetEntryTime(arc.Head)) { edge.Style = EdgeStyle.Bold; } g.AddEdges(edge); } } Console.WriteLine($"Edges added."); g.Display(); Console.WriteLine("Done."); }