123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- package jobshop;
-
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.PrintStream;
- import java.nio.file.Path;
- import java.nio.file.Paths;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Collectors;
-
- import jobshop.encodings.Schedule;
- import jobshop.solvers.*;
- import net.sourceforge.argparse4j.ArgumentParsers;
- import net.sourceforge.argparse4j.inf.ArgumentParser;
- import net.sourceforge.argparse4j.inf.ArgumentParserException;
- import net.sourceforge.argparse4j.inf.Namespace;
-
- /**
- * This class is the main entry point for doing comparative performance tests of solvers.
- */
- public class Main {
-
- public static void main(String[] args) {
- boolean csv = true;
-
- // configure the argument parser
- ArgumentParser parser = ArgumentParsers.newFor("jsp-solver").build()
- .defaultHelp(true)
- .description("Solves jobshop problems.");
- parser.addArgument("-t", "--timeout")
- .setDefault(1L)
- .type(Long.class)
- .help("Solver timeout in seconds for each instance. Default is 1 second.");
- parser.addArgument("--solver")
- .nargs("+")
- .required(true)
- .help("Solver(s) to use (space separated if more than one)");
- parser.addArgument("--instance")
- .nargs("+")
- .required(true)
- .help("Instance(s) to solve (space separated if more than one). All instances starting with the given " +
- "string will be selected. (e.g. \"ft\" will select the instances ft06, ft10 and ft20.");
- parser.addArgument("--iterMax")
- .type(Integer.class)
- .setDefault(100)
- .help("Iteration max le taboo");
- parser.addArgument("--pts")
- .type(Integer.class)
- .setDefault(20)
- .help("Nombre de points sur la méthode taboo");
-
- // parse command line arguments
- Namespace ns = null;
- try {
- ns = parser.parseArgs(args);
- } catch (ArgumentParserException e) {
- // error while parsing arguments, provide helpful error message and exit.
- System.err.println("Invalid arguments provided to the program.\n");
- System.err.println("In IntelliJ, you can provide arguments to the program by opening the dialog,");
- System.err.println("\"Run > Edit Configurations\" and filling in the \"program arguments\" box.");
- System.err.println("See the README for a documentation of the expected arguments.");
- System.err.println();
- parser.handleError(e);
- System.exit(0);
- }
-
- File file = new File("data_" + String.join("-",ns.getList("instance")) + "_instances_" + ns.getInt("iterMax") + "_iters_" + ns.getInt("pts") + "_pts.csv");
- try {
- file.createNewFile();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- PrintStream output = null;
-
- if (csv) {
- try {
- output = new PrintStream(file);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- } else {
- output = System.out;
- }
-
- // convert the timeout from seconds to milliseconds.
- long solveTimeMs = ns.getLong("timeout") * 1000 * 1000;
-
- // Get the list of solvers that we should benchmark.
- // We also check that we have a solver available for the given name and print an error message otherwise.
- List<String> solversToTest = ns.getList("solver");
- List<Solver> solvers = solversToTest.stream().map(Solver::getSolver).collect(Collectors.toList());
-
- // retrieve all instances on which we should run the solvers.
- List<String> instances = new ArrayList<>();
- List<String> instancePrefixes = ns.getList("instance");
- for(String instancePrefix : instancePrefixes) {
- List<String> matches = BestKnownResults.instancesMatching(instancePrefix);
- if(matches.isEmpty()) {
- System.err.println("ERROR: instance prefix \"" + instancePrefix + "\" does not match any instance.");
- System.err.println(" available instances: " + Arrays.toString(BestKnownResults.instances));
- System.exit(1);
- }
- instances.addAll(matches);
- }
-
- float[][] avg_distances = new float[solversToTest.size()][ns.getInt("pts")];
- float[][] avg_voisins = new float[solversToTest.size()][ns.getInt("pts")];
- int i;
- for (i=0; i<solversToTest.size(); i++) {
- int j;
- for (j=0; j<ns.getInt("pts"); j++) {
- avg_distances[i][j] = 0;
- avg_voisins[i][j] = 0;
- }
- }
-
- if (csv) {
- try {
- output.print("iterMax;");
- for (String s : solversToTest)
- output.printf("%s;;", s);
- output.println();
- for (String s : solversToTest) {
- output.print(";ecart;voisins");
- }
- output.println();
-
- for (int solverId = 0; solverId < solvers.size(); solverId++) {
- System.out.println("Solver : " + solversToTest.get(solverId));
- Solver solver = solvers.get(solverId);
- solver.setIterMax(ns.getInt("iterMax"));
- solver.setpts(ns.getInt("pts"));
-
- //Table des resultats
- ArrayList<ArrayList<Result>> table = new ArrayList<>();
- int[] bestKnownResults = new int[instances.size()];
-
- int index = 0;
- for (String instanceName : instances) {
- // get the best known result for this instance
- bestKnownResults[index] = BestKnownResults.of(instanceName);
- index++;
-
- // load instance from file.
- Path path = Paths.get("instances/", instanceName);
- Instance instance = Instance.fromFile(path);
-
- long deadline = System.currentTimeMillis() + solveTimeMs;
- // run the solver on the current instance
- table.add(solver.solve(instance, deadline));
- }
-
- int k;
- for (k=0; k<ns.getInt("pts"); k++) {
- int numInstance;
- for (numInstance=0; numInstance<instances.size(); numInstance++) {
-
- // check that the solver returned a valid solution
- if (table.get(numInstance).get(k).schedule.isEmpty() || !table.get(numInstance).get(k).schedule.get().isValid()) {
- System.err.println("ERROR: solver returned an invalid schedule");
- System.exit(1); // bug in implementation, bail out
- }
- // we have a valid schedule
- Schedule schedule = table.get(numInstance).get(k).schedule.get();
-
- // compute some statistics on the solution and print them.
- int makespan = schedule.makespan();
- float dist = 100f * (makespan - bestKnownResults[numInstance]) / (float) bestKnownResults[numInstance];
-
- avg_distances[solverId][k] += dist / (float) instances.size();
- avg_voisins[solverId][k] += (float) table.get(numInstance).get(k).getVoisinsVisites() / (float) instances.size();
- }
- }
- }
-
- // we have finished all benchmarks, compute the average solve time and distance of each solver.
- for (int k = 0; k<ns.getInt("pts"); k++) {
- output.printf("%d;", (k+1) * (ns.getInt("iterMax") / ns.getInt("pts")));
- for (int solverId = 0; solverId < solversToTest.size(); solverId++) {
- output.printf("%.2f;%.2f;", avg_distances[solverId][k], avg_voisins[solverId][k]);
- }
- output.println();
- output.flush();
- }
- output.println();
- output.flush();
- } catch (Exception e) {
- // there was uncaught exception, print the stack trace and exit with error.
- e.printStackTrace();
- System.exit(1);
- }
- }
- }
- }
|