/* * private List<Job> BuildSuccessorList(Job j) * { * throw new Exception("What uses this?"); * Console.WriteLine("WARNING: BuildSuccessorList is slow. Are you sure you need it?"); * List<Job> Succs = new List<Job>(j.Successors.Count + 1); * Job MSucc = GetMachineSuccessor(j); * Succs.Add(MSucc); * foreach (Job v in j.Successors) * { * if (v != MSucc) { Succs.Add(v); } * } * return Succs; * }*/ /// <summary> /// Performs the Action (Job ==> Void) on each Job in Precedence order (topological order). Considers Machine Predecessors. /// </summary> /// <param name="PerFormAction"></param> public void ForeachJobInPrecOrderDo(Action <Job> PerFormAction) { int[] nParentsProcessed = new int[PrecedenceDAG.N + 1]; // Position i contains the number of parents of Job with ID i that have been fully updated. Stack <Job> AllPredDone = new Stack <Job>(); // The jobs that will no longer change Rj are those for which all Parents have been considered. bool[] IsPushed = new bool[PrecedenceDAG.N + 1]; bool[] IsVisited = new bool[PrecedenceDAG.N + 1]; for (int i = 0; i < PrecedenceDAG.N + 1; i++) { IsPushed[i] = false; IsVisited[i] = false; } foreach (Job j in PrecedenceDAG.Jobs) //All jobs without predecessors can know their final Rj (it is equal to their own rj). { if (j.Predecessors.Count == 0 && GetMachinePredecessor(j) == null) { AllPredDone.Push(j); IsPushed[j.ID] = true; // ESS[j.ID] = j.EarliestReleaseDate; Do this as part of the action! } } Job CurrentJob = null; //algo int DebugJobsPopped = 0; while (AllPredDone.Count > 0) { CurrentJob = AllPredDone.Pop(); if (IsVisited[CurrentJob.ID]) { // Oops, found it twice. continue; } DebugJobsPopped++; PerFormAction(CurrentJob); IsVisited[CurrentJob.ID] = true; Job MachineSucc = GetMachineSuccessor(CurrentJob); foreach (Job Child in CurrentJob.Successors) { nParentsProcessed[Child.ID]++; Job MachinePred = GetMachinePredecessor(Child); if (nParentsProcessed[Child.ID] == Child.Predecessors.Count && (MachinePred == null || IsVisited[MachinePred.ID])) { if (MachinePred == null) { //Console.WriteLine("Debug note: No machine pred for job {0}", Child.ID); } if (!IsPushed[Child.ID]) { AllPredDone.Push(Child); IsPushed[Child.ID] = true; } } } if (MachineSucc != null && nParentsProcessed[MachineSucc.ID] == MachineSucc.Predecessors.Count) { if (!IsPushed[MachineSucc.ID]) { AllPredDone.Push(MachineSucc); IsPushed[MachineSucc.ID] = true; } } // missing machine arcs? NO! Machine arcs are dealt with. } for (int i = 0; i < PrecedenceDAG.N; i++) { if (!IsVisited[i]) { Console.WriteLine("ERROR! Printing Schedule for debugging then aborting."); Console.WriteLine("Processed {0}/{1} jobs in Prec Order", DebugJobsPopped, PrecedenceDAG.N); Console.WriteLine("Checking for cycles..."); bool Cyclesfound = false; foreach (Machine M in this.Machines) { for (int higherindex = 1; higherindex < M.AssignedJobs.Count; higherindex++) { for (int lowerindex = 0; lowerindex < higherindex; lowerindex++) { if (PrecedenceDAG.PrecPathExists(M.AssignedJobs[higherindex], M.AssignedJobs[lowerindex])) { Console.WriteLine("Cycle found on M{2}: Job {0} --Marcs--> Job {1} --Precs--> Job {0}", M.AssignedJobs[lowerindex].ID, M.AssignedJobs[higherindex].ID, M.MachineID); Cyclesfound = true; } } } } if (!Cyclesfound) { Console.WriteLine("No cycles found"); } this.Print(); this.PrintJobInfo(); Console.Write("Missed jobs: "); for (int j = 0; j < PrecedenceDAG.N; j++) { if (!IsVisited[j]) { Console.Write("{0}, ", j); } } Console.Write(Environment.NewLine); throw new Exception("Not all jobs visited!"); } } }