Пример #1
0
 /// <summary>
 /// Group of methods and operator overloads that add some (0-...) arcs to the graph,
 /// AddArc(IArc arc) only is basic method
 /// </summary>
 /// <param name="arc"></param>
 public virtual void AddArc(IArc arc)
 {
     if (arc == null)
     {
         throw new ArgumentNullException();
     }
     if (_insideGraph == null)
     {
         throw new NullReferenceException();
     }
     _insideGraph.AddArc(arc.Clone());
 }
Пример #2
0
 // IGraph extension methods:
 public static void AddArc(this IGraph graph, Arc arc) =>
 graph.AddArc(arc.Tail, arc.Head, arc.MachineId, arc.Length);
Пример #3
0
        /// <summary>
        /// Sets the route for a job, on the graph layer. Ie. insert/remove/change length of all conjunctive arcs,
        /// propagate the entry time changes into the cost layer and keep track the effects this has on the rest of
        /// the graph (by inserting into _necessaryFixes when necessary). Note, that it is not the graph layers job
        /// to handle machine occupations, but we do not want to delete and reinsert those that do not change
        /// (with a route swap). Hence, this method expects that all disjunctive arcs present (adjacent to the 'job')
        /// correspond to machine occupations that  do not change with the route swap.
        /// </summary>
        /// <param name="job">The job, whose route we set</param>
        /// <param name="route">The route to insert, null if the route of this job is to be removed.</param>
        public void SetRoute(Job job, Route route)
        {
            Route newRoute = route;
            Route oldRoute = Solution.GetRoute(job, canBeNull: true);

            Assert(GraphLayerChecks, !(oldRoute == null && newRoute == null));
            Assert(GraphLayerChecks, (oldRoute == null || job.Contains(oldRoute)) &&
                   (newRoute == null || job.Contains(newRoute)));

            if (oldRoute != null)
            {
                var report = new StringBuilder();
                Assert(GraphLayerChecks, ConjunctiveRouteProperlyLoaded(oldRoute, report), report.ToString());
                //Assert(GraphLayerChecks, oldRoute.Pairwise((o0, o1) => ArcExists(o0.Id, o1.Id, -1, out _)).All(x => x));
            }

            // Precondition:
            //
            // AdjacentArcs(job) == ArcsOf (Intersect (MachineOcc (newRoute), MachineOcc (oldRoute)))
            //
            // This is, all disjunctive arcs adjacent to the job in question, are disjunctive arcs of
            // machine occupations that occur in both routes.
            if (GraphLayerChecks.On)
            {
                // ReSharper disable once InvokeAsExtensionMethod (more readable)
                var relevantOccupations =
                    Enumerable.Intersect(
                        newRoute?.SelectMany(op => op.EndingMachineOccupations) ?? new MachineOccupation[0],
                        oldRoute?.SelectMany(op => op.EndingMachineOccupations) ?? new MachineOccupation[0]);

                IEnumerable <Arc> incomingDisjunctive =
                    Enumerable.Range(job.FirstOperation, job.LongestRoute).SelectMany(IncomingArcs)
                    .Where(a => a.MachineId != -1);

                IEnumerable <Arc> outgoingDisjunctive =
                    Enumerable.Range(job.FirstOperation, job.LongestRoute).SelectMany(OutgoingArcs)
                    .Where(a => a.MachineId != -1);

                Assert(GraphLayerChecks, incomingDisjunctive.All(a =>
                                                                 relevantOccupations.Any(occ =>
                                                                                         occ.FirstOperation == a.Head && occ.MachineId == a.MachineId)));

                Assert(GraphLayerChecks, outgoingDisjunctive.All(a =>
                                                                 relevantOccupations.Any(occ =>
                                                                                         occ.LastOperation == a.Tail - 1 && occ.MachineId == a.MachineId)));
            }
            // end precondition.

            // 1)  For conjunctive arcs:
            //     insert/delete/change length
            //
            // 2)  Given the incoming disjunctive arcs and earliest entry times,
            //     update the entryTimes within the job
            //
            // 3)  For all leaving disjunctive arcs:
            //     If the head entry time changes, update and set a necessary fix.

            // Note, _graph.<someMethod>(...) bypasses the registration of the necessaryFixes.
            // (as opposed to this.<someMethod>())

            // Step 1:
            for (int i = 0; i < job.LongestRoute - 1; i++)
            {
                var oldOp = oldRoute == null || (oldRoute.Count - 1) <= i ? null : oldRoute[i];
                var newOp = newRoute == null || (newRoute.Count - 1) <= i ? null : newRoute[i];
                // On the '-1': arcs are inserted for the operations [0, ..., n-1] ; there is no arc for the
                // last (dummy) operation

                var vertexIndex = job.FirstOperation + i;
                var arc         = new Arc(vertexIndex, vertexIndex + 1, newOp?.Runtime ?? TimeSpan.Zero, -1);

                if (newOp == null && oldOp == null)
                // only if both routes are shorter than the longest route:
                // oldRoute.length < i && newRoute.length < i, but there is a route longer than 'old' and 'new'
                {
                    Assert(GraphLayerChecks, oldRoute == null || vertexIndex > (oldRoute.Count - 1));
                    Assert(GraphLayerChecks, newRoute == null || vertexIndex > (newRoute.Count - 1));
                    break;
                }

                else if (newOp == null /* && oldOp != null */)
                {
                    _graph.RemoveArc(arc);
                }

                else if (/* newOp != null && */ oldOp == null)
                {
                    _graph.AddArc(arc);
                }

                else /* if (newOp != null && oldOp != null) */
                if (oldOp.Runtime != newOp.Runtime)
                {
                    _graph.RemoveArc(arc);
                    _graph.AddArc(arc);
                }
            }

            CostLayer.SetRoute(job, route);

            // Step 2:
            TimeSpan ArcBasedIncomingTime(int index) =>
            IncomingArcs(index).Select(a => Solution.GetEntryTime(a.Tail) + a.Length).Prepend(TimeSpan.MinValue)
            .Max();

            TimeSpan ShouldBeEntryTime(int index) =>
            (Solution.GetOperation(index, canBeNull: true)?.EarliestEarliestEntry ?? TimeSpan.Zero).Max(
                ArcBasedIncomingTime(index));

            if (newRoute == null)
            {
                // ReSharper disable once PossibleNullReferenceException (see assert above)
                foreach (var op in oldRoute)
                {
                    CostLayer.SetEntryTime(op.Id, TimeSpan.Zero);
                }
            }

            else
            {
                foreach (var op in newRoute)
                {
                    var time = ShouldBeEntryTime(op.Id);

                    if (Solution.GetEntryTime(op.Id) != time)
                    {
                        CostLayer.SetEntryTime(op.Id, time);
                    }
                }
            }


            // Step 3:
            if (newRoute != null)
            {
                var outgoingDisjunctive = Enumerable.Range(job.FirstOperation, newRoute.Count)
                                          .SelectMany(OutgoingArcs).Where(a => a.MachineId != -1);

                foreach (Arc arc in outgoingDisjunctive)
                {
                    var shouldBe = ShouldBeEntryTime(arc.Head);
                    var actual   = Solution.GetEntryTime(arc.Head);

                    if (actual != shouldBe)
                    {
                        CostLayer.SetEntryTime(arc.Head, shouldBe);
                        _necessaryFixes.Add(new TimeAtVertex(arc.Head, shouldBe));
                    }
                }
            }

            // Checks:
            if (newRoute != null && GraphLayerChecks.On)
            {
                StringBuilder report = new StringBuilder();
                Assert(GraphLayerChecks, ConjunctiveRouteProperlyLoaded(newRoute, report), report.ToString());
            }
        }