package jobshop.solvers; import jobshop.Instance; import jobshop.encodings.ResourceOrder; import jobshop.encodings.Schedule; import jobshop.encodings.Task; import jobshop.solvers.neighborhood.Neighborhood; import jobshop.solvers.neighborhood.Nowicki; import java.time.format.ResolverStyle; import java.util.Comparator; import java.util.List; import java.util.Optional; /** An empty shell to implement a descent solver. */ public class DescentSolver implements Solver { final Neighborhood neighborhood; final Solver baseSolver; /** Creates a new descent solver with a given neighborhood and a solver for the initial solution. * * @param neighborhood Neighborhood object that should be used to generates neighbor solutions to the current candidate. * @param baseSolver A solver to provide the initial solution. */ public DescentSolver(Neighborhood neighborhood, Solver baseSolver) { this.neighborhood = neighborhood; this.baseSolver = baseSolver; } @Override public Optional solve(Instance instance, long deadline, int randomness, int randomRunNumber) { Schedule schedule = baseSolver.solve(instance, deadline,randomness,randomRunNumber).get(); ResourceOrder order = new ResourceOrder(schedule); ResourceOrder result = order; Boolean bestFound = false; Integer best = Integer.MAX_VALUE; while(!bestFound) { List neighbours = neighborhood.generateNeighbors(order); try { Integer finalBest = best; order = neighbours.stream() .filter(e -> e.toSchedule().get().isValid()) // removes invalid solutions .filter(e -> e.toSchedule().get().makespan() < finalBest) // removes solutions that do not improve .sorted(Comparator.comparing(e -> e.toSchedule().get().makespan())) // takes the best .toArray(ResourceOrder[]::new)[0]; result = order; best = order.toSchedule().get().makespan(); System.out.println("\u001b[32m" + "Current best makespam : " + best + "\u001b[0m, " + "\u001b[33m" + "Number of neighbours : " + getNumberOfNeighbours(neighbours) + "\u001b[0m"); } catch (ArrayIndexOutOfBoundsException e) { // no solution found ==> stop bestFound = true; } } return result.toSchedule(); } // used to compute the number of neighbours seen private int getNumberOfNeighbours(List neighbours) { return neighbours.stream() .filter(e -> e.toSchedule().get().isValid()) // removes invalid solutions .toArray(ResourceOrder[]::new).length; } }