public void AssignJobToMachineById(int Jid, int Mid) { // Console.WriteLine("Assigning J{0} to M{1}", PrecedenceDAG.GetJobById(Jid).ID, GetMachineByID(Mid).MachineID); if (Mid == 0) { throw new Exception("Machines are 1 based"); } AssignJobToMachine(PrecedenceDAG.GetJobById(Jid), GetMachineByID(Mid)); }
public void PrintJobInfo() { Console.WriteLine("Printing job information........"); Console.WriteLine("| id | px | rx | sx | tx | Sum | Estimated Cmax (check) |"); Job CurrentJob; for (int JobID = 0; JobID < PrecedenceDAG.N; JobID++) { CurrentJob = PrecedenceDAG.GetJobById(JobID); Console.WriteLine("| {0,-3} | {1,-3} | {6,-3} | {2,-3} | {3,-3} | {4,-3} | {5,-3} |", JobID, CurrentJob.MeanProcessingTime, GetEarliestStart(CurrentJob), CalcTailTime(CurrentJob), CurrentJob.MeanProcessingTime + GetEarliestStart(CurrentJob) + CalcTailTime(CurrentJob), DeterministicCmax, CurrentJob.EarliestReleaseDate); } }
/* * 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!"); } } }
/// <summary> /// Given a problem with precedence arcs as a DAG. Creates an assignment by iterating jobs over machines. Very naive. /// </summary> public void MakeRollingMachineAssignment() { AssignmentDescription = "Rolling Machine Assignment"; if (PrecedenceDAG.N <= 1) { throw new Exception("No DAG given. Cannot build schedule without problem instance"); } int NJobsAssigned = 0; int[] nParentsProcessed = new int[PrecedenceDAG.N + 1]; Queue <Job> AllPredDone = new Queue <Job>(); // The jobs that will no longer change Rj are those for which all Parents have been considered. 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) { AllPredDone.Enqueue(j); } } int CandidateMachineID = 0; while (AllPredDone.Count > 0) { bool DebugAssignmentSuccess = false; CandidateMachineID++; if (CandidateMachineID >= Machines.Count + 1) { CandidateMachineID = 1; } Job CurrentJob = AllPredDone.Dequeue(); for (int i = 0; i < Machines.Count; i++) { if (!IsFeasibleAssignment(CurrentJob, GetMachineByID(CandidateMachineID))) { // try the next machine: CandidateMachineID++; if (CandidateMachineID >= Machines.Count) { CandidateMachineID = 0; } } else { // assign to that machine //IMPORTANT: Update the Queue before adding any arcs, or things may be added to the queue twice: foreach (Job Succ in CurrentJob.Successors) { nParentsProcessed[Succ.ID]++; if (nParentsProcessed[Succ.ID] == Succ.Predecessors.Count) { AllPredDone.Enqueue(Succ); } } //IMPORTANT: Only do this after the queue has been updated. // if it is the first job on the machine, no precedence arc is needed: if (GetMachineByID(CandidateMachineID).AssignedJobs.Count > 0) { PrecedenceDAG.AddArc(GetMachineByID(CandidateMachineID).LastJob(), CurrentJob); } //IMPORTANT: Only do this after the queue has been updated and after machine arcs have been updated AssignJobToMachine(CurrentJob, GetMachineByID(CandidateMachineID)); DebugAssignmentSuccess = true; break; } } if (!DebugAssignmentSuccess) { throw new Exception("Schedulde.Build was unable to create a feasible schedule: the algorithm is bugged."); } NJobsAssigned++; } if (NJobsAssigned < PrecedenceDAG.N) { throw new Exception("Not all jobs assigned"); } }