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

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