From 959672ff20c007256f80ac6fa12a23996e275687 Mon Sep 17 00:00:00 2001 From: fred Date: Tue, 7 Oct 2025 10:18:57 -0300 Subject: [PATCH 1/2] chore: minor adjustments --- .../examples/flowshop/domain/Job.java | 52 +++++++++---------- .../flowshop/domain/JobCompletionTime.java | 37 +++++++++++++ .../examples/flowshop/domain/JobMakespan.java | 37 ------------- .../examples/flowshop/domain/Machine.java | 2 +- .../flowshop/flowShopSolverConfig.xml | 5 ++ 5 files changed, 69 insertions(+), 64 deletions(-) create mode 100644 src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobCompletionTime.java delete mode 100644 src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobMakespan.java diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java index 6aa494b9..3974f8e8 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java @@ -2,7 +2,7 @@ import ai.timefold.solver.core.api.domain.entity.PlanningEntity; import ai.timefold.solver.core.api.domain.lookup.PlanningId; -import ai.timefold.solver.core.api.domain.variable.IndexShadowVariable; +import ai.timefold.solver.core.api.domain.variable.InverseRelationShadowVariable; import ai.timefold.solver.core.api.domain.variable.PreviousElementShadowVariable; import ai.timefold.solver.core.api.domain.variable.ShadowSources; import ai.timefold.solver.core.api.domain.variable.ShadowVariable; @@ -20,15 +20,15 @@ public class Job { private int id; @JsonIdentityReference(alwaysAsId = true) private Machine[] allMachines; - @IndexShadowVariable(sourceVariableName = "jobs") + @InverseRelationShadowVariable(sourceVariableName = "jobs") @JsonIgnore - private Integer index; + private Machine machine; @PreviousElementShadowVariable(sourceVariableName = "jobs") @JsonIgnore private Job previousJob; - @ShadowVariable(supplierName = "updateMakespan") + @ShadowVariable(supplierName = "updateCompletionTime") @JsonIgnore - private JobMakespan makespan; + private JobCompletionTime completionTime; private int processTimeSum = 0; public Job() { @@ -55,17 +55,17 @@ public void setPreviousJob(Job previousJob) { this.previousJob = previousJob; } - public JobMakespan getMakespan() { - return makespan; + public JobCompletionTime getCompletionTime() { + return completionTime; } - public void setMakespan(JobMakespan makespan) { - this.makespan = makespan; + public void setCompletionTime(JobCompletionTime completionTime) { + this.completionTime = completionTime; } public int getProcessingTimeSum() { if (processTimeSum == 0) { - for (Machine allMachine : allMachines) { + for (var allMachine : allMachines) { processTimeSum += allMachine.getProcessTime(id); } } @@ -77,52 +77,52 @@ public int getProcessingTime(int machineId) { } @JsonIgnore - @ShadowSources(value = { "previousJob.makespan", "index" }) - public JobMakespan updateMakespan() { - if (index == null) { + @ShadowSources(value = { "previousJob.completionTime", "machine" }) + public JobCompletionTime updateCompletionTime() { + if (machine == null) { return null; } - var newMakespan = new JobMakespan(allMachines.length); + var newCompletionTime = new JobCompletionTime(allMachines.length); // A machine can perform only one job at a time, // and a job can only start on one machine after finishing the process at the previous machine. // The makespan of this job in the first machine depends only on the previous job makespan. // It can only start after the previous job is completed. - var newPreviousMakespan = newMakespan.setMakespan(0, getPreviousMakespan(0) + allMachines[0].getProcessTime(id)); + var previousMachineCompletionTime = newCompletionTime.setCompletionTime(0, getPreviousCompletionTime(0) + allMachines[0].getProcessTime(id)); for (var i = 1; i < allMachines.length; i++) { // The job execution for the following machines relies on the makespan of either the previous job // or the previous machine, // depending on which is greater. // That way, the job can only begin on the machine once it has completed on the previous machine // or after the prior job has finished. - newPreviousMakespan = newMakespan.setMakespan(i, - Math.max(getPreviousMakespan(i), newPreviousMakespan) + allMachines[i].getProcessTime(id)); + previousMachineCompletionTime = newCompletionTime.setCompletionTime(i, + Math.max(getPreviousCompletionTime(i), previousMachineCompletionTime) + allMachines[i].getProcessTime(id)); } - return newMakespan; + return newCompletionTime; } @JsonIgnore - private int getPreviousMakespan(int machineId) { + private int getPreviousCompletionTime(int machineId) { if (previousJob != null) { - return previousJob.getMakespan(machineId); + return previousJob.getCompletionTime(machineId); } return 0; } @JsonIgnore - public int getMakespan(int machineId) { - if (makespan == null) { + public int getCompletionTime(int machineId) { + if (completionTime == null) { return 0; } - return makespan.getMakespan(machineId); + return completionTime.getCompletionTime(machineId); } @JsonIgnore - public int getLastMachineMakespan() { - if (makespan == null) { + public int getCompletionTimeLastMachine() { + if (completionTime == null) { return 0; } // The makespan is given by the makespan of the last machine - return makespan.getLastMachineMakespan(); + return completionTime.getCompletionTimeLastMachine(); } @Override diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobCompletionTime.java b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobCompletionTime.java new file mode 100644 index 00000000..8a2ddfdb --- /dev/null +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobCompletionTime.java @@ -0,0 +1,37 @@ +package ai.timefold.solver.benchmarks.examples.flowshop.domain; + +import java.util.Arrays; + +public class JobCompletionTime { + + private final int[] completionTime; + + public JobCompletionTime(int numberOfMachines) { + this.completionTime = new int[numberOfMachines]; + } + + public int setCompletionTime(int machineId, int value) { + return completionTime[machineId] = value; + } + + public int getCompletionTime(int machineId) { + return completionTime[machineId]; + } + + public int getCompletionTimeLastMachine() { + return completionTime[completionTime.length - 1]; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof JobCompletionTime makespan)) { + return false; + } + return Arrays.equals(completionTime, makespan.completionTime); + } + + @Override + public int hashCode() { + return Arrays.hashCode(completionTime); + } +} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobMakespan.java b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobMakespan.java deleted file mode 100644 index d13b151c..00000000 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/JobMakespan.java +++ /dev/null @@ -1,37 +0,0 @@ -package ai.timefold.solver.benchmarks.examples.flowshop.domain; - -import java.util.Arrays; - -public class JobMakespan { - - private final int[] makespanPerMachine; - - public JobMakespan(int numberOfMachines) { - this.makespanPerMachine = new int[numberOfMachines]; - } - - public int setMakespan(int machineId, int value) { - return makespanPerMachine[machineId] = value; - } - - public int getMakespan(int machineId) { - return makespanPerMachine[machineId]; - } - - public int getLastMachineMakespan() { - return makespanPerMachine[makespanPerMachine.length - 1]; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof JobMakespan makespan)) { - return false; - } - return Arrays.equals(makespanPerMachine, makespan.makespanPerMachine); - } - - @Override - public int hashCode() { - return Arrays.hashCode(makespanPerMachine); - } -} diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Machine.java b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Machine.java index 8fd1cf23..f4db3ba6 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Machine.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Machine.java @@ -58,7 +58,7 @@ public int getMakespan() { if (jobs.isEmpty()) { return 0; } - return jobs.getLast().getLastMachineMakespan(); + return jobs.getLast().getCompletionTimeLastMachine(); } @Override diff --git a/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml b/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml index df10e837..2ee9ec17 100644 --- a/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml +++ b/src/main/resources/ai/timefold/solver/benchmarks/examples/flowshop/flowShopSolverConfig.xml @@ -18,4 +18,9 @@ 2 + + ai.timefold.solver.benchmarks.examples.flowshop.phase.NEHCustomPhase + + + From 2240fa159211ecaa63eab909ea2367e82485ebd7 Mon Sep 17 00:00:00 2001 From: fred Date: Tue, 7 Oct 2025 11:06:25 -0300 Subject: [PATCH 2/2] chore: address comments --- .../solver/benchmarks/examples/flowshop/domain/Job.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java index 3974f8e8..c766aa90 100644 --- a/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java +++ b/src/main/java/ai/timefold/solver/benchmarks/examples/flowshop/domain/Job.java @@ -85,11 +85,11 @@ public JobCompletionTime updateCompletionTime() { var newCompletionTime = new JobCompletionTime(allMachines.length); // A machine can perform only one job at a time, // and a job can only start on one machine after finishing the process at the previous machine. - // The makespan of this job in the first machine depends only on the previous job makespan. + // The completion time of this job in the first machine depends only on the previous job completion time. // It can only start after the previous job is completed. var previousMachineCompletionTime = newCompletionTime.setCompletionTime(0, getPreviousCompletionTime(0) + allMachines[0].getProcessTime(id)); for (var i = 1; i < allMachines.length; i++) { - // The job execution for the following machines relies on the makespan of either the previous job + // The job execution for the following machines relies on the completion time of either the previous job // or the previous machine, // depending on which is greater. // That way, the job can only begin on the machine once it has completed on the previous machine @@ -121,7 +121,6 @@ public int getCompletionTimeLastMachine() { if (completionTime == null) { return 0; } - // The makespan is given by the makespan of the last machine return completionTime.getCompletionTimeLastMachine(); }