123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- package jobshop;
-
- 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.HashMap;
- import java.util.List;
- import java.util.stream.Collectors;
-
- import jobshop.solvers.*;
- import jobshop.solvers.neighborhood.Nowicki;
- 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 testing solver on instances.
- * It provides
- */
- public class Main {
-
-
-
-
- public static void main(String[] args) {
- // 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.");
-
- // 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);
- }
-
- PrintStream output = System.out;
-
- // convert the timeout from seconds to milliseconds.
- long solveTimeMs = ns.getLong("timeout") * 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);
- }
-
- // average runtime of each solver
- float[] avg_runtimes = new float[solversToTest.size()];
- // average distance to best known result for each solver
- float[] avg_distances = new float[solversToTest.size()];
-
- try {
- // header of the result table :
- // - solver names (first line)
- // - name of each column (second line)
- output.print( " ");
- for(String s : solversToTest)
- output.printf("%-30s", s);
- output.println();
- output.print("instance size best ");
- for(String s : solversToTest) {
- output.print("runtime makespan ecart ");
- }
- output.println();
-
- // for all instances, load it from f
- for(String instanceName : instances) {
- // get the best known result for this instance
- int bestKnown = BestKnownResults.of(instanceName);
-
- // load instance from file.
- Path path = Paths.get("instances/", instanceName);
- Instance instance = Instance.fromFile(path);
-
- // print some general statistics on the instance
- output.printf("%-8s %-5s %4d ",instanceName, instance.numJobs +"x"+instance.numTasks, 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,
- // we lookup the `Main.solvers` hash map to get the solver object with the given name.
- Solver solver = solvers.get(solverId);
-
- // start chronometer and compute deadline for the solver to provide a result.
- long start = System.currentTimeMillis();
- long deadline = System.currentTimeMillis() + solveTimeMs;
- // run the solver on the current instance
- Result result = solver.solve(instance, deadline);
- // measure elapsed time (in milliseconds)
- long runtime = System.currentTimeMillis() - start;
-
- // check that the solver returned a valid solution
- if(!result.schedule.isValid()) {
- System.err.println("ERROR: solver returned an invalid schedule");
- System.exit(1); // bug in implementation, bail out
- }
-
- // compute some statistics on the solution and print them.
- int makespan = result.schedule.makespan();
- float dist = 100f * (makespan - bestKnown) / (float) bestKnown;
- avg_runtimes[solverId] += (float) runtime / (float) instances.size();
- avg_distances[solverId] += dist / (float) instances.size();
-
- output.printf("%7d %8s %5.1f ", runtime, makespan, dist);
- output.flush();
- }
- output.println();
- }
-
-
- // we have finished all benchmarks, compute the average solve time and distance of each solver.
- output.printf("%-8s %-5s %4s ", "AVG", "-", "-");
- for(int solverId = 0 ; solverId < solversToTest.size() ; solverId++) {
- output.printf("%7.1f %8s %5.1f ", avg_runtimes[solverId], "-", avg_distances[solverId]);
- }
-
-
-
- } catch (Exception e) {
- // there was uncaught exception, print the stack trace and exit with error.
- e.printStackTrace();
- System.exit(1);
- }
- }
- }
|