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..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
@@ -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,51 @@ 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.
+ // 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 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
+ // 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
// 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
+
+
+