diff --git a/src/main/java/jobshop/Main.java b/src/main/java/jobshop/Main.java index 08b3d05..f138695 100644 --- a/src/main/java/jobshop/Main.java +++ b/src/main/java/jobshop/Main.java @@ -30,6 +30,10 @@ public class Main { .setDefault(1L) .type(Long.class) .help("Solver timeout in seconds for each instance. Default is 1 second."); + parser.addArgument("-r", "--random") + .setDefault(0) + .type(Integer.class) + .help("percentage of randomness in solving"); parser.addArgument("--solver") .nargs("+") .required(true) @@ -65,6 +69,10 @@ public class Main { List solversToTest = ns.getList("solver"); List solvers = solversToTest.stream().map(Solver::getSolver).collect(Collectors.toList()); + + // TODO : passer ca a la fonction + //Integer randomness = (Integer) ns.getList("random").get(0); + // retrieve all instances on which we should run the solvers. List instances = new ArrayList<>(); List instancePrefixes = ns.getList("instance"); diff --git a/src/main/java/jobshop/solvers/GreedySolver.java b/src/main/java/jobshop/solvers/GreedySolver.java index 3be5989..14662dc 100644 --- a/src/main/java/jobshop/solvers/GreedySolver.java +++ b/src/main/java/jobshop/solvers/GreedySolver.java @@ -41,11 +41,8 @@ public class GreedySolver implements Solver { } return sum; } - private Integer heuristiqueEST_SPT(Task t, Instance instance){ - return instance.duration(t); - } - private Integer heuristiqueEST_LPT(Task t, Instance instance){ - return instance.duration(t); + 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); @@ -55,7 +52,7 @@ public class GreedySolver implements Solver { } - public Task min(ArrayList lTask, Instance instance){ + public Task findNextTask(ArrayList lTask, Instance instance, int[] machineStatus, int[] jobStatus){ switch (priority) { case SPT: return( @@ -84,12 +81,25 @@ public class GreedySolver implements Solver { .get() // it returns an optional ); case EST_SPT: - // TODO + + // 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( - lTask.stream() + Arrays.stream(EST_SPT_closestTasks) .sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance))) .toArray(Task[]::new)[0] ); + case EST_LPT: // TODO return( @@ -98,18 +108,30 @@ public class GreedySolver implements Solver { .toArray(Task[]::new)[0] ); case EST_SRPT: - // TODO + //TODO return( lTask.stream() .sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance))) .toArray(Task[]::new)[0] ); case EST_LRPT: - // TODO + + // 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( - lTask.stream() - .sorted(Comparator.comparing(e -> heuristiqueSPT(e, instance))) - .toArray(Task[]::new)[0] + Arrays.stream(EST_LRPT_closestTasks) + .max(Comparator.comparing(e -> heuristiqueLRPT(e, instance))) + .get() // it returns an optional ); } return null; @@ -119,12 +141,18 @@ public class GreedySolver implements Solver { @Override public Optional solve(Instance instance, long deadline) { + return solve(instance,deadline,5); + } + + public Optional solve(Instance instance, long deadline, int percentRandom) { + Random r = new Random(); + // keeps track of the next time the machine is free - int[] statusMachines = new int[instance.numMachines]; + int[] machineStatus = new int[instance.numMachines]; // keeps track of the next time the job is free - int[] statusJobs = new int[instance.numJobs]; - Arrays.fill(statusMachines,0); - Arrays.fill(statusJobs,0); + int[] jobStatus = new int[instance.numJobs]; + Arrays.fill(machineStatus,0); + Arrays.fill(jobStatus,0); int time ; Schedule schedule = new Schedule(instance); @@ -136,21 +164,27 @@ public class GreedySolver implements Solver { /* Main Loop*/ while(possibleTasks.size() > 0){ - Task task = min(possibleTasks,instance); + 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(statusMachines[instance.machine(task)], statusJobs[task.job]); + time = Integer.max(machineStatus[instance.machine(task)], jobStatus[task.job]); schedule.setStartTime(task.job, task.task, time); // recalculate next free time for job/machine - statusMachines[instance.machine(task)] = time + instance.duration(task); - statusJobs[task.job] = time + instance.duration(task); - if ((task.task + 1) < instance.numTasks){ - possibleTasks.add(new Task(task.job, task.task+1)); + 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); } diff --git a/src/main/java/jobshop/solvers/Solver.java b/src/main/java/jobshop/solvers/Solver.java index 875c719..9869cf5 100644 --- a/src/main/java/jobshop/solvers/Solver.java +++ b/src/main/java/jobshop/solvers/Solver.java @@ -23,6 +23,8 @@ public interface Solver { case "basic": return new BasicSolver(); case "spt": return new GreedySolver(GreedySolver.Priority.SPT); case "lrpt": return new GreedySolver(GreedySolver.Priority.LRPT); + case "est_spt": return new GreedySolver(GreedySolver.Priority.EST_SPT); + case "est_lrpt": return new GreedySolver(GreedySolver.Priority.EST_LRPT); // TODO: add new solvers default: throw new RuntimeException("Unknown solver: "+ name); }