No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JobNumbers.java 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package jobshop.encodings;
  2. import jobshop.Instance;
  3. import java.util.Arrays;
  4. import java.util.Comparator;
  5. import java.util.Objects;
  6. import java.util.Optional;
  7. import java.util.stream.IntStream;
  8. /** Encoding of the solution of a jobshop problem by job numbers. */
  9. public final class JobNumbers extends Encoding {
  10. /** A numJobs * numTasks array containing the representation by job numbers. */
  11. public final int[] jobs;
  12. /** In case the encoding is only partially filled, indicates the index of the first
  13. * element of `jobs` that has not been set yet. */
  14. public int nextToSet = 0;
  15. /** Creates a new empty encoding. */
  16. public JobNumbers(Instance instance) {
  17. super(instance);
  18. jobs = new int[instance.numJobs * instance.numMachines];
  19. Arrays.fill(jobs, -1);
  20. }
  21. /** Creates a new encoding based on the given schedule. */
  22. public JobNumbers(Schedule schedule) {
  23. super(schedule.instance);
  24. this.jobs = new int[instance.numJobs * instance.numTasks];
  25. // for each job indicates which is the next task to be scheduled
  26. int[] nextOnJob = new int[instance.numJobs];
  27. while(Arrays.stream(nextOnJob).anyMatch(t -> t < instance.numTasks)) {
  28. Task next = IntStream
  29. // for all jobs numbers
  30. .range(0, instance.numJobs)
  31. // build the next task for this job
  32. .mapToObj(j -> new Task(j, nextOnJob[j]))
  33. // only keep valid tasks (some jobs have no task left to be executed)
  34. .filter(t -> t.task < instance.numTasks)
  35. // select the task with the earliest execution time
  36. .min(Comparator.comparing(t -> schedule.startTime(t.job, t.task)))
  37. .get();
  38. this.addTaskOfJob(next.job);
  39. nextOnJob[next.job] += 1;
  40. }
  41. }
  42. /** Schedule the next task of the given job. */
  43. public void addTaskOfJob(int jobNumber) {
  44. this.jobs[nextToSet++] = jobNumber;
  45. }
  46. @Override
  47. public Optional<Schedule> toSchedule() {
  48. // time at which each machine is going to be freed
  49. int[] nextFreeTimeResource = new int[instance.numMachines];
  50. // for each job, the first task that has not yet been scheduled
  51. int[] nextTask = new int[instance.numJobs];
  52. // for each task, its start time
  53. Schedule schedule = new Schedule(instance);
  54. // compute the earliest start time for every task of every job
  55. for(int job : jobs) {
  56. int task = nextTask[job];
  57. int machine = instance.machine(job, task);
  58. // earliest start time for this task
  59. int est = task == 0 ? 0 : schedule.endTime(job, task-1);
  60. est = Math.max(est, nextFreeTimeResource[machine]);
  61. schedule.setStartTime(job, task, est);
  62. nextFreeTimeResource[machine] = est + instance.duration(job, task);
  63. nextTask[job] = task + 1;
  64. }
  65. return Optional.of(schedule);
  66. }
  67. @Override
  68. public String toString() {
  69. return Arrays.toString(Arrays.copyOfRange(jobs,0, nextToSet));
  70. }
  71. @Override
  72. public boolean equals(Object o) {
  73. if (this == o) return true;
  74. if (o == null || getClass() != o.getClass()) return false;
  75. JobNumbers that = (JobNumbers) o;
  76. return nextToSet == that.nextToSet && Arrays.equals(jobs, that.jobs);
  77. }
  78. @Override
  79. public int hashCode() {
  80. int result = Objects.hash(nextToSet);
  81. result = 31 * result + Arrays.hashCode(jobs);
  82. return result;
  83. }
  84. }