diff --git a/src/main/java/jobshop/Main.java b/src/main/java/jobshop/Main.java index 81f1b3a..71fec4f 100644 --- a/src/main/java/jobshop/Main.java +++ b/src/main/java/jobshop/Main.java @@ -122,12 +122,13 @@ public class Main { Instance instance = Instance.fromFile(path); // print some general statistics on the instance - output.println("\u001b[36m" + "------------------------------------------------------------------------------------------------------------------" + "\u001b[0m"); + output.println("\u001b[36m" + "-----------------------------".repeat(solvers.size() +1) + "\u001b[0m"); // adapts to the number of elements output.printf("%-8s %-5s %4d ",instanceName, instance.numJobs +"x"+instance.numTasks, bestKnown); // used to get a csv file of all compared makespans ArrayList instanceMakespans = new ArrayList<>(); + instanceMakespans.add(bestKnown); // run all selected solvers on the instance and print the results for(int solverId = 0 ; solverId < solvers.size() ; solverId++) { // Select the next solver to run. Given the solver name passed on the command line, @@ -157,7 +158,8 @@ public class Main { avg_distances[solverId] += dist / (float) instances.size(); output.printf("%7d %8s %5.1f ", runtime, makespan, dist); - instanceMakespans.add(makespan); + instanceMakespans.add(makespan); // to store the makespan time + //instanceMakespans.add(Math.toIntExact(runtime)); // to store the execution time output.flush(); } diff --git a/src/main/java/jobshop/solvers/TabooSolver.java b/src/main/java/jobshop/solvers/TabooSolver.java index b631fdd..f53e8ca 100644 --- a/src/main/java/jobshop/solvers/TabooSolver.java +++ b/src/main/java/jobshop/solvers/TabooSolver.java @@ -18,6 +18,9 @@ import java.util.stream.IntStream; public class TabooSolver implements Solver { final Neighborhood neighborhood; final Solver baseSolver; + private int historyForbidenSize; + + /** Creates a new descent solver with a given neighborhood and a solver for the initial solution. @@ -28,6 +31,7 @@ public class TabooSolver implements Solver { public TabooSolver(Neighborhood neighborhood, Solver baseSolver) { this.neighborhood = neighborhood; this.baseSolver = baseSolver; + this.historyForbidenSize = 6; } @Override @@ -61,11 +65,10 @@ public class TabooSolver implements Solver { Arrays.fill(forbiddenNeighbours[i],zeroArray); } int iterationCount = 0; - Boolean noMoreSolution = false; Integer best = Integer.MAX_VALUE; ResourceOrder bestRO = order; ResourceOrder previousRO; - while(System.currentTimeMillis() < deadline && !noMoreSolution) { + while(System.currentTimeMillis() < deadline) { List neighbours = neighborhood.generateNeighbors(order); previousRO = order; try { @@ -91,12 +94,10 @@ public class TabooSolver implements Solver { .toArray(ResourceOrder[]::new)[0]; result = order; } - } catch (ArrayIndexOutOfBoundsException e2) { // no solution found ==> stop + } catch (ArrayIndexOutOfBoundsException e2) { // no solution found ==> wait } /* Check if we have a cycle */ - // TODO : on ne mmet pas a jour l'historiaue ? - // todo add la liste des interdits dans le calcul du hash if (isCycle(historic, result.toSchedule().get())){ System.out.println("CYCLE"); break; @@ -165,7 +166,7 @@ public class TabooSolver implements Solver { if (changes[0] == -1) {return true;} if ((forbiddenNeighbours[changes[0]][changes[1]][changes[2]] == 0) - || (forbiddenNeighbours[changes[0]][changes[1]][changes[2]] < iterationCount - 10 /*to tune*/)){ + || (forbiddenNeighbours[changes[0]][changes[1]][changes[2]] < iterationCount - historyForbidenSize)){ return false; } else { return true; @@ -184,36 +185,40 @@ public class TabooSolver implements Solver { historic.add(schedule.hashCode()); Boolean found = false; Boolean result = true; - int indexCycle = 0; - int testTurtle = 0; - int testRabbit = 0; - if (historic.size() > 50) { + int turtle = 1; + int rabbit = 2; + int lenCycle = 0; + if (historic.size() > 1000) { // to only store the last thousand historic.remove(0); } - int rabbit = 0; - for (int turtle = 1; turtle < (historic.size()/2); turtle ++){ - rabbit = 2*turtle; - if (historic.get(turtle).equals(historic.get(rabbit))){ - indexCycle = turtle; - found = true; - testTurtle = turtle; - testRabbit = rabbit; - break; - } - } - if (found && 2 * rabbit - indexCycle < historic.size()){ - for (int i = indexCycle; i < rabbit; i++) { - if (!historic.get(testTurtle).equals(historic.get(testRabbit))) { - result = false; + + /*find the first occurence of duplicate state*/ + if (historic.size() > 100) { // in order not to cut too short + for (turtle = 1; turtle < (historic.size() / 2); turtle++) { + rabbit = 2 * turtle; + if (historic.get(turtle).equals(historic.get(rabbit))) { + lenCycle = rabbit - turtle; + found = true; + break; } - testTurtle++; - testRabbit++; } } - if (result && found){ - return true; + + /*if there is one then checks that the sequence leading one to the other is the same n times*/ + if (found) { + try { + result = true; + for (int k = 1; k < 5 /*tune this for more or less tolerance*/; k++){ + result = result && historic.subList(turtle, rabbit).equals(historic.subList(turtle + lenCycle * k, rabbit + lenCycle * k)); + }; + } catch (IndexOutOfBoundsException e) { // if one occurs then the list is too short to include a cycle + } + } + if (found){ + return true; + } else { + return false; } - return false; } }