No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Main.java 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package jobshop;
  2. import java.io.PrintStream;
  3. import java.nio.file.Path;
  4. import java.nio.file.Paths;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.stream.Collectors;
  10. import jobshop.solvers.*;
  11. import jobshop.solvers.neighborhood.Nowicki;
  12. import net.sourceforge.argparse4j.ArgumentParsers;
  13. import net.sourceforge.argparse4j.inf.ArgumentParser;
  14. import net.sourceforge.argparse4j.inf.ArgumentParserException;
  15. import net.sourceforge.argparse4j.inf.Namespace;
  16. /**
  17. * This class is the main entry point for testing solver on instances.
  18. * It provides
  19. */
  20. public class Main {
  21. public static void main(String[] args) {
  22. // configure the argument parser
  23. ArgumentParser parser = ArgumentParsers.newFor("jsp-solver").build()
  24. .defaultHelp(true)
  25. .description("Solves jobshop problems.");
  26. parser.addArgument("-t", "--timeout")
  27. .setDefault(1L)
  28. .type(Long.class)
  29. .help("Solver timeout in seconds for each instance. Default is 1 second.");
  30. parser.addArgument("--solver")
  31. .nargs("+")
  32. .required(true)
  33. .help("Solver(s) to use (space separated if more than one)");
  34. parser.addArgument("--instance")
  35. .nargs("+")
  36. .required(true)
  37. .help("Instance(s) to solve (space separated if more than one). All instances starting with the given " +
  38. "string will be selected. (e.g. \"ft\" will select the instances ft06, ft10 and ft20.");
  39. // parse command line arguments
  40. Namespace ns = null;
  41. try {
  42. ns = parser.parseArgs(args);
  43. } catch (ArgumentParserException e) {
  44. // error while parsing arguments, provide helpful error message and exit.
  45. System.err.println("Invalid arguments provided to the program.\n");
  46. System.err.println("In IntelliJ, you can provide arguments to the program by opening the dialog,");
  47. System.err.println("\"Run > Edit Configurations\" and filling in the \"program arguments\" box.");
  48. System.err.println("See the README for a documentation of the expected arguments.");
  49. System.err.println();
  50. parser.handleError(e);
  51. System.exit(0);
  52. }
  53. PrintStream output = System.out;
  54. // convert the timeout from seconds to milliseconds.
  55. long solveTimeMs = ns.getLong("timeout") * 1000;
  56. // Get the list of solvers that we should benchmark.
  57. // We also check that we have a solver available for the given name and print an error message otherwise.
  58. List<String> solversToTest = ns.getList("solver");
  59. List<Solver> solvers = solversToTest.stream().map(Solver::getSolver).collect(Collectors.toList());
  60. // retrieve all instances on which we should run the solvers.
  61. List<String> instances = new ArrayList<>();
  62. List<String> instancePrefixes = ns.getList("instance");
  63. for(String instancePrefix : instancePrefixes) {
  64. List<String> matches = BestKnownResults.instancesMatching(instancePrefix);
  65. if(matches.isEmpty()) {
  66. System.err.println("ERROR: instance prefix \"" + instancePrefix + "\" does not match any instance.");
  67. System.err.println(" available instances: " + Arrays.toString(BestKnownResults.instances));
  68. System.exit(1);
  69. }
  70. instances.addAll(matches);
  71. }
  72. // average runtime of each solver
  73. float[] avg_runtimes = new float[solversToTest.size()];
  74. // average distance to best known result for each solver
  75. float[] avg_distances = new float[solversToTest.size()];
  76. try {
  77. // header of the result table :
  78. // - solver names (first line)
  79. // - name of each column (second line)
  80. output.print( " ");
  81. for(String s : solversToTest)
  82. output.printf("%-30s", s);
  83. output.println();
  84. output.print("instance size best ");
  85. for(String s : solversToTest) {
  86. output.print("runtime makespan ecart ");
  87. }
  88. output.println();
  89. // for all instances, load it from f
  90. for(String instanceName : instances) {
  91. // get the best known result for this instance
  92. int bestKnown = BestKnownResults.of(instanceName);
  93. // load instance from file.
  94. Path path = Paths.get("instances/", instanceName);
  95. Instance instance = Instance.fromFile(path);
  96. // print some general statistics on the instance
  97. output.printf("%-8s %-5s %4d ",instanceName, instance.numJobs +"x"+instance.numTasks, bestKnown);
  98. // run all selected solvers on the instance and print the results
  99. for(int solverId = 0 ; solverId < solvers.size() ; solverId++) {
  100. // Select the next solver to run. Given the solver name passed on the command line,
  101. // we lookup the `Main.solvers` hash map to get the solver object with the given name.
  102. Solver solver = solvers.get(solverId);
  103. // start chronometer and compute deadline for the solver to provide a result.
  104. long start = System.currentTimeMillis();
  105. long deadline = System.currentTimeMillis() + solveTimeMs;
  106. // run the solver on the current instance
  107. Result result = solver.solve(instance, deadline);
  108. // measure elapsed time (in milliseconds)
  109. long runtime = System.currentTimeMillis() - start;
  110. // check that the solver returned a valid solution
  111. if(!result.schedule.isValid()) {
  112. System.err.println("ERROR: solver returned an invalid schedule");
  113. System.exit(1); // bug in implementation, bail out
  114. }
  115. // compute some statistics on the solution and print them.
  116. int makespan = result.schedule.makespan();
  117. float dist = 100f * (makespan - bestKnown) / (float) bestKnown;
  118. avg_runtimes[solverId] += (float) runtime / (float) instances.size();
  119. avg_distances[solverId] += dist / (float) instances.size();
  120. output.printf("%7d %8s %5.1f ", runtime, makespan, dist);
  121. output.flush();
  122. }
  123. output.println();
  124. }
  125. // we have finished all benchmarks, compute the average solve time and distance of each solver.
  126. output.printf("%-8s %-5s %4s ", "AVG", "-", "-");
  127. for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) {
  128. output.printf("%7.1f %8s %5.1f ", avg_runtimes[solverId], "-", avg_distances[solverId]);
  129. }
  130. } catch (Exception e) {
  131. // there was uncaught exception, print the stack trace and exit with error.
  132. e.printStackTrace();
  133. System.exit(1);
  134. }
  135. }
  136. }