Metaheuristiques-Lacroix-Le.../src/main/java/jobshop/solvers/GreedySolver.java
2023-03-20 10:07:40 +01:00

192 lines
7.1 KiB
Java

package jobshop.solvers;
import jobshop.Instance;
import jobshop.encodings.Schedule;
import jobshop.encodings.Task;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/** An empty shell to implement a greedy solver. */
public class GreedySolver implements Solver {
/** All possible priorities for the greedy solver. */
public enum Priority {
SPT, LPT, SRPT, LRPT, EST_SPT, EST_LPT, EST_SRPT, EST_LRPT
}
/** Priority that the solver should use. */
final Priority priority;
/** Creates a new greedy solver that will use the given priority. */
public GreedySolver(Priority p) {
this.priority = p;
}
private Integer heuristiqueSPT(Task t, Instance instance){
return instance.duration(t);
}
private Integer heuristiqueLPT(Task t, Instance instance){
return instance.duration(t);
}
private Integer heuristiqueSRPT(Task t, Instance instance){
return instance.duration(t);
}
private Integer heuristiqueLRPT(Task t, Instance instance){
int sum = 0;
// we sum all durations starting at the current tasks' in the job
for (int i = t.task; i < instance.numTasks; i++){
sum += instance.duration(t.job, i);
}
return sum;
}
private Integer heuristiqueEST(Task t, Instance instance, int[] machineStatus, int[] jobStatus){
return Integer.max(machineStatus[instance.machine(t)], jobStatus[t.job]);
}
private Integer heuristiqueEST_SRPT(Task t, Instance instance){
return instance.duration(t);
}
private Integer heuristiqueEST_LRPT(Task t, Instance instance){
return instance.duration(t);
}
public Task findNextTask(ArrayList<Task> lTask, Instance instance, int[] machineStatus, int[] jobStatus){
switch (priority) {
case SPT:
return(
lTask.stream()
.sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance)))
.toArray(Task[]::new)[0]
);
case LPT:
// TODO
return(
lTask.stream()
.sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance)))
.toArray(Task[]::new)[0]
);
case SRPT:
// TODO
return(
lTask.stream()
.sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance)))
.toArray(Task[]::new)[0]
);
case LRPT:
return(
lTask.stream()
.max(Comparator.comparing(e -> heuristiqueLRPT(e, instance)))
.get() // it returns an optional
);
case EST_SPT:
// find the minimal next execution time value
int EST_SPT_minValue = lTask.stream()
.map(e -> heuristiqueEST(e, instance,machineStatus, jobStatus))
.sorted()
.toArray(Integer[]::new)[0];
// find all tasks with this next execution time value
Task[] EST_SPT_closestTasks = lTask.stream()
.filter(e -> heuristiqueEST(e, instance,machineStatus, jobStatus) == EST_SPT_minValue)
.toArray(Task[]::new);
// run SPT (see above) on this
return(
Arrays.stream(EST_SPT_closestTasks)
.sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance)))
.toArray(Task[]::new)[0]
);
case EST_LPT:
// TODO
return(
lTask.stream()
.sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance)))
.toArray(Task[]::new)[0]
);
case EST_SRPT:
//TODO
return(
lTask.stream()
.sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance)))
.toArray(Task[]::new)[0]
);
case EST_LRPT:
// find the minimal next execution time value
int EST_LRPT_minValue = lTask.stream()
.map(e -> heuristiqueEST(e, instance,machineStatus, jobStatus))
.sorted()
.toArray(Integer[]::new)[0];
// find all tasks with this next execution time value
Task[] EST_LRPT_closestTasks = lTask.stream()
.filter(e -> heuristiqueEST(e, instance,machineStatus, jobStatus) == EST_LRPT_minValue)
.toArray(Task[]::new);
// run LRPT (see above) on this
return(
Arrays.stream(EST_LRPT_closestTasks)
.max(Comparator.comparing(e -> heuristiqueLRPT(e, instance)))
.get() // it returns an optional
);
}
return null;
}
@Override
public Optional<Schedule> solve(Instance instance, long deadline) {
return solve(instance,deadline,5);
}
public Optional<Schedule> solve(Instance instance, long deadline, int percentRandom) {
Random r = new Random();
// keeps track of the next time the machine is free
int[] machineStatus = new int[instance.numMachines];
// keeps track of the next time the job is free
int[] jobStatus = new int[instance.numJobs];
Arrays.fill(machineStatus,0);
Arrays.fill(jobStatus,0);
int time ;
Schedule schedule = new Schedule(instance);
ArrayList<Task> possibleTasks = new ArrayList<>();
/* Initialization */
for (int i = 0; i < instance.numJobs; i++){
possibleTasks.add(new Task(i, 0));
}
/* Main Loop*/
while(possibleTasks.size() > 0){
Task task;
if (r.nextInt(100) < percentRandom) {
task = possibleTasks.get(r.nextInt(possibleTasks.size()));
} else {
task = findNextTask(possibleTasks, instance, machineStatus, jobStatus);
}
possibleTasks.remove(task);
// Update schedule
time = Integer.max(machineStatus[instance.machine(task)], jobStatus[task.job]);
schedule.setStartTime(task.job, task.task, time);
// recalculate next free time for job/machine
machineStatus[instance.machine(task)] = time + instance.duration(task);
jobStatus[task.job] = time + instance.duration(task);
// if there are any more remaining tasks : add the next one
if ((task.task + 1) < instance.numTasks) {
possibleTasks.add(new Task(task.job, task.task + 1));
}
}
return Optional.of(schedule);
}
}