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, LRPT, EST_SPT, 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; } @Override public String toString() { return "GreedySolver{" + "priority=" + priority + '}'; } private Integer heuristiqueSPT(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]); } public Task findNextTask(ArrayList 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 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_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; } public Schedule solveInner(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 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 schedule; } @Override public Optional solve(Instance instance, long deadline, int percentRandom, int randomRunNumber) { if (percentRandom == 0) { return Optional.of(solveInner(instance, deadline, percentRandom)); } else { Integer bestTime = Integer.MAX_VALUE; Schedule bestSchedule = null; for (int i = 0; i < randomRunNumber; i++) { Schedule schedule = solveInner(instance, deadline, percentRandom); System.out.println(schedule.makespan()); if (schedule.makespan() < bestTime){ bestTime = schedule.makespan(); bestSchedule = schedule; } } return Optional.of(bestSchedule); } } }