From 0e290c85a1ed6283ba5b4ddacdb4eb822982edca Mon Sep 17 00:00:00 2001 From: J-morag <38430800+J-morag@users.noreply.github.com> Date: Mon, 13 Feb 2023 18:25:50 +0200 Subject: [PATCH] Add cli support (#31) * Added a CLI * Fixed OS dependent paths * Better default results output --- pom.xml | 9 +- .../InstanceBuilders/InstanceBuilder_BGU.java | 5 +- .../InstanceBuilder_MovingAI.java | 12 +- .../InstanceBuilder_Warehouse.java | 12 +- .../BasicMAPF/Instances/InstanceManager.java | 10 +- .../Instances/InstanceProperties.java | 18 +- .../Environment/RunManagers/A_RunManager.java | 28 ++- .../RunManagers/GenericRunManager.java | 56 +++++ .../RunManagers/ModularRunManager.java | 4 + .../RunManagerMovingAIBenchmark.java | 2 +- .../RunManagers/RunManagerSimpleExample.java | 4 + .../RunManagers/RunManagerWarehouse.java | 2 +- .../TestingBenchmarkRunManager.java | 4 + src/main/java/Main.java | 214 ++++++++++++++++-- 14 files changed, 329 insertions(+), 51 deletions(-) create mode 100644 src/main/java/Environment/RunManagers/GenericRunManager.java diff --git a/pom.xml b/pom.xml index f6fd94ea..d22285c7 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ MAPF MAPF 1.0-SNAPSHOT + jar org.junit.jupiter @@ -29,11 +30,17 @@ commons-collections4 4.4 + + + commons-cli + commons-cli + 1.5.0 + org.json json - 20211205 + 20220320 org.jetbrains diff --git a/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_BGU.java b/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_BGU.java index ff1cf889..34766bda 100644 --- a/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_BGU.java +++ b/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_BGU.java @@ -136,13 +136,12 @@ private MAPF_Instance getInstance(String instanceName, InstanceManager.InstanceP public void prepareInstances(String instanceName, InstanceManager.InstancePath instancePath, InstanceProperties instanceProperties){ MAPF_Instance mapf_instance = this.getInstance(instanceName, instancePath, instanceProperties); - if ( mapf_instance != null ){ + if ( mapf_instance != null && + (instanceProperties == null || instanceProperties.regexPattern.matcher(mapf_instance.extendedName).matches())){ this.instanceStack.push(mapf_instance); } } - - @Override public MAPF_Instance getNextExistingInstance(){ if( ! this.instanceStack.empty() ){ diff --git a/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_MovingAI.java b/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_MovingAI.java index 4ee2b2e8..72ae15b4 100644 --- a/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_MovingAI.java +++ b/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_MovingAI.java @@ -78,7 +78,7 @@ public InstanceBuilder_MovingAI(Priorities priorities) { } @Override - public void prepareInstances(String instanceName, InstanceManager.InstancePath instancePath, InstanceProperties instanceProperties) { + public void prepareInstances(String mapName, InstanceManager.InstancePath instancePath, InstanceProperties instanceProperties) { if (!(instancePath instanceof InstanceManager.Moving_AI_Path)) { return; } @@ -101,11 +101,13 @@ public void prepareInstances(String instanceName, InstanceManager.InstancePath i Agent[] agents = getAgents(agentLines,numOfAgentsFromProperties[i]); - if (instanceName == null || agents == null) { continue; /* Invalid parameters */ } + if (mapName == null || agents == null) { continue; /* Invalid parameters */ } - mapf_instance = makeInstance(instanceName, graphMap, agents, moving_ai_path); - mapf_instance.setObstaclePercentage(instanceProperties.obstacles.getReportPercentage()); - this.instanceList.add(mapf_instance); + mapf_instance = makeInstance(mapName, graphMap, agents, moving_ai_path); + if (instanceProperties.regexPattern.matcher(mapf_instance.extendedName).matches()){ + mapf_instance.setObstaclePercentage(instanceProperties.obstacles.getReportPercentage()); + this.instanceList.add(mapf_instance); + } } } diff --git a/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_Warehouse.java b/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_Warehouse.java index ffb29c6d..a81b9b1e 100644 --- a/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_Warehouse.java +++ b/src/main/java/BasicMAPF/Instances/InstanceBuilders/InstanceBuilder_Warehouse.java @@ -52,7 +52,7 @@ public InstanceBuilder_Warehouse(Boolean dropDisabledEdges) { } @Override - public void prepareInstances(String instanceName, InstanceManager.InstancePath instancePath, InstanceProperties instanceProperties) { + public void prepareInstances(String mapName, InstanceManager.InstancePath instancePath, InstanceProperties instanceProperties) { if (!(instancePath instanceof InstanceManager.Moving_AI_Path)) { return; } InstanceManager.Moving_AI_Path moving_ai_path = (InstanceManager.Moving_AI_Path) instancePath; @@ -73,11 +73,13 @@ public void prepareInstances(String instanceName, InstanceManager.InstancePath i Agent[] agents = getAgents(agentLines, numOfAgentsFromProperties[i]); - if (instanceName == null || agents == null) { continue; /* Invalid parameters */ } + if (mapName == null || agents == null) { continue; /* Invalid parameters */ } - mapf_instance = makeInstance(instanceName, graphMap, agents, moving_ai_path); - mapf_instance.setObstaclePercentage(instanceProperties.obstacles.getReportPercentage()); - this.instanceList.add(mapf_instance); + mapf_instance = makeInstance(mapName, graphMap, agents, moving_ai_path); + if (instanceProperties.regexPattern.matcher(mapf_instance.extendedName).matches()){ + mapf_instance.setObstaclePercentage(instanceProperties.obstacles.getReportPercentage()); + this.instanceList.add(mapf_instance); + } } } diff --git a/src/main/java/BasicMAPF/Instances/InstanceManager.java b/src/main/java/BasicMAPF/Instances/InstanceManager.java index 1447c36c..804716d4 100644 --- a/src/main/java/BasicMAPF/Instances/InstanceManager.java +++ b/src/main/java/BasicMAPF/Instances/InstanceManager.java @@ -1,11 +1,13 @@ package BasicMAPF.Instances; import BasicMAPF.Instances.InstanceBuilders.I_InstanceBuilder; +import Environment.IO_Package.IO_Manager; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; +import java.util.regex.Pattern; public class InstanceManager { @@ -47,11 +49,13 @@ public InstanceManager(String sourceDirectory, I_InstanceBuilder instanceBuilder public MAPF_Instance getSpecificInstance(InstancePath currentPath){ - String regexSeparator = "\\\\"; // this is actually: '\\' - String[] splitedPath = currentPath.path.split(regexSeparator); - String instanceName = splitedPath[splitedPath.length-1]; + String regexSeparator = IO_Manager.pathSeparator; + String[] splitPath = currentPath.path.split(Pattern.quote(regexSeparator)); + String instanceName = splitPath[splitPath.length-1]; + // one instance can become many (different amounts of agents...) this.instanceBuilder.prepareInstances(instanceName, currentPath, this.instanceProperties); + return this.instanceBuilder.getNextExistingInstance(); } diff --git a/src/main/java/BasicMAPF/Instances/InstanceProperties.java b/src/main/java/BasicMAPF/Instances/InstanceProperties.java index cbb0ba3e..fd4e5b7c 100644 --- a/src/main/java/BasicMAPF/Instances/InstanceProperties.java +++ b/src/main/java/BasicMAPF/Instances/InstanceProperties.java @@ -2,17 +2,19 @@ import BasicMAPF.Instances.Maps.MapDimensions; +import java.util.Objects; +import java.util.regex.Pattern; + public class InstanceProperties { public final MapDimensions mapSize; public final ObstacleWrapper obstacles; public final int[] numOfAgents; + public final Pattern regexPattern; public InstanceProperties() { - this.mapSize = new MapDimensions(); - this.obstacles = new ObstacleWrapper(); - this.numOfAgents = new int[0]; + this(null, -1, null, null); } public InstanceProperties(MapDimensions.Enum_mapOrientation enumMapOrientation){ @@ -21,20 +23,26 @@ public InstanceProperties(MapDimensions.Enum_mapOrientation enumMapOrientation){ } + + public InstanceProperties(MapDimensions mapSize, double obstacleRate, int[] numOfAgents) { + this(mapSize, obstacleRate, numOfAgents, null); + } + /*** * Properties constructor * @param mapSize - {@link MapDimensions} indicates the Axis lengths , zero for unknown * @param obstacleRate - A double that indicates the obstacle rate of the map. For unknown obstacles enter -1 * @param numOfAgents - An array of different num of agents. + * @param instancesRegex - Only use instances matching this regular expression. */ - public InstanceProperties(MapDimensions mapSize, double obstacleRate, int[] numOfAgents) { + public InstanceProperties(MapDimensions mapSize, double obstacleRate, int[] numOfAgents, String instancesRegex) { this.mapSize = (mapSize == null ? new MapDimensions() : mapSize); this.obstacles = (obstacleRate == -1 ? new ObstacleWrapper() : new ObstacleWrapper(obstacleRate)); this.numOfAgents = (numOfAgents == null ? new int[0] : numOfAgents); + this.regexPattern = Pattern.compile(Objects.requireNonNullElse(instancesRegex, ".*")); } - public class ObstacleWrapper { public static final double DEFAULT_OBSTACLE_RATE = -1; diff --git a/src/main/java/Environment/RunManagers/A_RunManager.java b/src/main/java/Environment/RunManagers/A_RunManager.java index ac436360..b914e145 100644 --- a/src/main/java/Environment/RunManagers/A_RunManager.java +++ b/src/main/java/Environment/RunManagers/A_RunManager.java @@ -8,11 +8,13 @@ import Environment.Metrics.InstanceReport; import Environment.Metrics.S_Metrics; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.DateFormat; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * This in an abstract class that overcomes the need to comment out lines in the 'Main' method @@ -24,7 +26,27 @@ public abstract class A_RunManager { protected List solvers = new ArrayList<>(); protected List experiments = new ArrayList<>(); - protected String resultsOutputDir = IO_Manager.buildPath(new String[]{System.getProperty("user.home"), "CBS_Results"}); + public static final String DEFAULT_RESULTS_OUTPUT_DIR = IO_Manager.buildPath(new String[]{System.getProperty("user.home"), "MAPF_Results"}); + private final String resultsOutputDir; + protected String resultsFilePrefix = "results"; + + protected A_RunManager(String resultsOutputDir) { + this.resultsOutputDir = Objects.requireNonNullElse(resultsOutputDir, DEFAULT_RESULTS_OUTPUT_DIR); + verifyOutputPath(this.resultsOutputDir); + } + + public static boolean verifyOutputPath(String path) { + File directory = new File(path); + if (! directory.exists()){ + boolean created = directory.mkdir(); + if(!created){ + String errString = "Could not locate or create output directory."; + System.out.println(errString); + return false; + } + } + return true; + } abstract void setSolvers(); abstract void setExperiments(); @@ -81,7 +103,7 @@ protected void setOutputStreamsBeforeRunning() { sleepToAvoidOverridingPreviousResultsFiles(); DateFormat dateFormat = S_Metrics.defaultDateFormat; - String pathWithStartTime = resultsOutputDir + "\\results " + dateFormat.format(System.currentTimeMillis()) + " .csv"; + String pathWithStartTime = IO_Manager.buildPath(new String[]{resultsOutputDir, "log " + resultsFilePrefix + " " + dateFormat.format(System.currentTimeMillis())}) + " .csv"; try { S_Metrics.addOutputStream(new FileOutputStream((pathWithStartTime))); } catch (IOException e) { @@ -93,7 +115,7 @@ protected void setOutputStreamsBeforeRunning() { protected void exportAllResults() { sleepToAvoidOverridingPreviousResultsFiles(); DateFormat dateFormat = S_Metrics.defaultDateFormat; - String pathWithEndTime = resultsOutputDir + "\\results " + dateFormat.format(System.currentTimeMillis()) + " .csv"; + String pathWithEndTime = IO_Manager.buildPath(new String[]{resultsOutputDir, "res " + resultsFilePrefix + " " + dateFormat.format(System.currentTimeMillis())}) + " .csv"; try { S_Metrics.exportCSV(new FileOutputStream(pathWithEndTime) ); } catch (IOException e) { diff --git a/src/main/java/Environment/RunManagers/GenericRunManager.java b/src/main/java/Environment/RunManagers/GenericRunManager.java new file mode 100644 index 00000000..a52d10a9 --- /dev/null +++ b/src/main/java/Environment/RunManagers/GenericRunManager.java @@ -0,0 +1,56 @@ +package Environment.RunManagers; + +import BasicMAPF.Instances.InstanceBuilders.I_InstanceBuilder; +import BasicMAPF.Instances.InstanceManager; +import BasicMAPF.Instances.InstanceProperties; +import BasicMAPF.Solvers.CBS.CBS_Solver; +import BasicMAPF.Solvers.PrioritisedPlanning.PrioritisedPlanning_Solver; +import Environment.Experiment; +import org.jetbrains.annotations.NotNull; + +public class GenericRunManager extends A_RunManager { + + private final String instancesDir; + private final int[] agentNums; + private final I_InstanceBuilder instanceBuilder; + private final String experimentName; + private final boolean skipAfterFail; + private final String instancesRegex; + + public GenericRunManager(@NotNull String instancesDir, int[] agentNums, @NotNull I_InstanceBuilder instanceBuilder, + @NotNull String experimentName, boolean skipAfterFail, String instancesRegex, + String resultsOutputDir, String resultsFilePrefix) { + super(resultsOutputDir); + if (agentNums == null){ + throw new IllegalArgumentException("AgentNums can't be null"); + } + this.instancesDir = instancesDir; + this.agentNums = agentNums; + this.instanceBuilder = instanceBuilder; + this.experimentName = experimentName; + this.skipAfterFail = skipAfterFail; + this.instancesRegex = instancesRegex; + this.resultsFilePrefix = resultsFilePrefix; + } + @Override + void setSolvers() { + // TODO modular solvers? + super.solvers.add(new PrioritisedPlanning_Solver()); + super.solvers.add(new CBS_Solver()); + } + + @Override + void setExperiments() { + /* = Set Properties = */ + InstanceProperties properties = new InstanceProperties(null, -1, agentNums, instancesRegex); + + /* = Set Instance Manager = */ + InstanceManager instanceManager = new InstanceManager(instancesDir, instanceBuilder, properties); + + /* = Add new experiment = */ + Experiment experiment = new Experiment(experimentName, instanceManager); + experiment.skipAfterFail = this.skipAfterFail; + this.experiments.add(experiment); + } + +} diff --git a/src/main/java/Environment/RunManagers/ModularRunManager.java b/src/main/java/Environment/RunManagers/ModularRunManager.java index 43a5113c..cd76111b 100644 --- a/src/main/java/Environment/RunManagers/ModularRunManager.java +++ b/src/main/java/Environment/RunManagers/ModularRunManager.java @@ -9,6 +9,10 @@ public class ModularRunManager extends A_RunManager{ + public ModularRunManager() { + super(null); + } + @Override void setSolvers() { diff --git a/src/main/java/Environment/RunManagers/RunManagerMovingAIBenchmark.java b/src/main/java/Environment/RunManagers/RunManagerMovingAIBenchmark.java index f4dde083..5da83227 100644 --- a/src/main/java/Environment/RunManagers/RunManagerMovingAIBenchmark.java +++ b/src/main/java/Environment/RunManagers/RunManagerMovingAIBenchmark.java @@ -6,7 +6,6 @@ import BasicMAPF.Solvers.CBS.CBS_Solver; import BasicMAPF.Solvers.PrioritisedPlanning.PrioritisedPlanning_Solver; import Environment.Experiment; -import java.util.stream.IntStream; public class RunManagerMovingAIBenchmark extends A_RunManager{ @@ -14,6 +13,7 @@ public class RunManagerMovingAIBenchmark extends A_RunManager{ private final int[] agentNums; public RunManagerMovingAIBenchmark(String entireBenchmarkDir, int[] agentNums) { + super(null); this.entireBenchmarkDir = entireBenchmarkDir; this.agentNums = agentNums; } diff --git a/src/main/java/Environment/RunManagers/RunManagerSimpleExample.java b/src/main/java/Environment/RunManagers/RunManagerSimpleExample.java index 8e884c33..f74d84d5 100644 --- a/src/main/java/Environment/RunManagers/RunManagerSimpleExample.java +++ b/src/main/java/Environment/RunManagers/RunManagerSimpleExample.java @@ -14,6 +14,10 @@ public class RunManagerSimpleExample extends A_RunManager { + public RunManagerSimpleExample() { + super(null); + } + /* = Set BasicCBS.Solvers = */ @Override void setSolvers() { diff --git a/src/main/java/Environment/RunManagers/RunManagerWarehouse.java b/src/main/java/Environment/RunManagers/RunManagerWarehouse.java index 928f5e31..c90bc835 100644 --- a/src/main/java/Environment/RunManagers/RunManagerWarehouse.java +++ b/src/main/java/Environment/RunManagers/RunManagerWarehouse.java @@ -6,7 +6,6 @@ import BasicMAPF.Solvers.CBS.CBS_Solver; import BasicMAPF.Solvers.PrioritisedPlanning.PrioritisedPlanning_Solver; import Environment.Experiment; -import java.util.stream.IntStream; public class RunManagerWarehouse extends A_RunManager{ @@ -14,6 +13,7 @@ public class RunManagerWarehouse extends A_RunManager{ private final int[] agentNums; public RunManagerWarehouse(String warehouseMaps, int[] agentNums) { + super(null); this.warehouseMaps = warehouseMaps; this.agentNums = agentNums; } diff --git a/src/main/java/Environment/RunManagers/TestingBenchmarkRunManager.java b/src/main/java/Environment/RunManagers/TestingBenchmarkRunManager.java index 121e7e31..9e5caf6e 100644 --- a/src/main/java/Environment/RunManagers/TestingBenchmarkRunManager.java +++ b/src/main/java/Environment/RunManagers/TestingBenchmarkRunManager.java @@ -14,6 +14,10 @@ public class TestingBenchmarkRunManager extends A_RunManager { private final String path = IO_Manager.buildPath( new String[]{ IO_Manager.testResources_Directory, "TestingBenchmark"}); + public TestingBenchmarkRunManager() { + super(null); + } + @Override void setSolvers() { this.solvers.add( new CBS_Solver()); diff --git a/src/main/java/Main.java b/src/main/java/Main.java index fc7b59b8..ed3c864f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -1,3 +1,6 @@ +import BasicMAPF.Instances.InstanceBuilders.I_InstanceBuilder; +import BasicMAPF.Instances.InstanceBuilders.InstanceBuilder_MovingAI; +import BasicMAPF.Instances.InstanceBuilders.InstanceBuilder_Warehouse; import Environment.IO_Package.IO_Manager; import BasicMAPF.Instances.InstanceBuilders.InstanceBuilder_BGU; import BasicMAPF.Instances.InstanceManager; @@ -7,34 +10,210 @@ import BasicMAPF.Solvers.CBS.CBS_Solver; import BasicMAPF.Solvers.RunParameters; import BasicMAPF.Solvers.Solution; -import Environment.RunManagers.A_RunManager; -import Environment.RunManagers.RunManagerSimpleExample; -import Environment.RunManagers.TestingBenchmarkRunManager; +import Environment.RunManagers.*; +import org.apache.commons.cli.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.DateFormat; +import java.util.Arrays; + +import static Environment.RunManagers.A_RunManager.verifyOutputPath; /** * We wanted to keep {@link #main(String[])} short and simple as possible * Things to consider before running: - * 1. Check that the {@link #resultsOutputDir} is correct + * 1. Check that the {@link #exampleResultsOutputDir} is correct * 2. Check that {@link #outputResults()} is as you need - * 3. Running an experiment should be done through {@link A_RunManager}, + * 3. Running an experiment should be done through a {@link A_RunManager}. * Solving a single Instance is also possible by giving a path. * For more information, view the examples below */ public class Main { - // where to put generated reports. The default is a new folder called CBS_Results, under the user's home directory. - public static final String resultsOutputDir = IO_Manager.buildPath(new String[]{System.getProperty("user.home"), "CBS_Results"}); -// public static final String resultsOutputDir = IO_Manager.buildPath(new String[]{ IO_Manager.testResources_Directory + -// "\\Reports default directory"}); + // where to put generated reports. The default is a new folder called MAPF_Results, under the user's home directory. + public static final String exampleResultsOutputDir = A_RunManager.DEFAULT_RESULTS_OUTPUT_DIR; + public static final String STR_AGENT_NUMS = "agentNums"; + private static final String STR_MOVING_AI = "MovingAI"; + private static final String STR_BGU = "BGU"; + public static final String STR_INSTANCES_DIR = "instancesDir"; + public static final String STR_INSTANCES_REGEX = "instancesRegex"; + private static final String STR_WAREHOUSE = "Warehouse"; + private static final String STR_RESULTS_DIR_OPTION = "resultsOutputDir"; + private static final String STR_RESULTS_FILE_PREFIX = "resultsFilePrefix"; public static void main(String[] args) { - if(verifyOutputPath()){ + if (args.length > 0){ + CLIMain(args); + } + else { + // Example + staticMain(); + } + } + + private static void CLIMain(String[] args) { + Options options = new Options(); + Option skipOption = new Option("s", "skipAfterFail", false, + "To skip attempting the same instance with the same solver, but with more agents, if we already failed with less agents."); + options.addOption(skipOption); + + Option nameOption = Option.builder("n").longOpt("name") + .argName("name") + .hasArg() + .required(false) + .desc("Name for the experiment. Optional.") + .build(); + options.addOption(nameOption); + + Option instancesDirOption = Option.builder("iDir").longOpt(STR_INSTANCES_DIR) + .argName(STR_INSTANCES_DIR) + .hasArg() + .required(true) + .desc("Set the directory (path) where maps and instances are to be found. Required.") + .build(); + options.addOption(instancesDirOption); + + Option resultsDirOption = Option.builder("resDir").longOpt(STR_RESULTS_DIR_OPTION) + .argName(STR_RESULTS_DIR_OPTION) + .hasArg() + .required(false) + .desc("The directory (path) where results will be saved. Will be created if it doesn't exist. Optional.") + .build(); + options.addOption(resultsDirOption); + + Option resultsFileOption = Option.builder("resPref").longOpt(STR_RESULTS_FILE_PREFIX) + .argName(STR_RESULTS_FILE_PREFIX) + .hasArg() + .required(false) + .desc("The prefix to give results file names. Optional.") + .build(); + options.addOption(resultsFileOption); + + Option instancesRegexOption = Option.builder("iRegex").longOpt(STR_INSTANCES_REGEX) + .argName(STR_INSTANCES_REGEX) + .hasArg() + .required(false) + .desc("If given, only instances matching this Regex will be used. Optional.") + .build(); + options.addOption(instancesRegexOption); + + Option InstancesFormatOption = Option.builder("iForm").longOpt("instancesFormat") + .argName("instancesFormat") + .hasArg() + .required(false) + .desc(String.format("Set the format of the instances. " + + "Supports %s format (https://movingai.com/benchmarks/formats.html) and %s format.", STR_MOVING_AI, STR_BGU) + + " Optional (default is " + STR_MOVING_AI + ").") + .build(); + options.addOption(InstancesFormatOption); + + Option agentNumsOption = Option.builder("a").longOpt(STR_AGENT_NUMS) + .argName(STR_AGENT_NUMS) + .hasArgs() + .required(true) + .valueSeparator(',') + .desc("Set the numbers of agents to try. Use ',' (comma) as a separator and no spaces." + + " Will use the maximum available if an instance does not have enough agents. Required.") + .build(); + options.addOption(agentNumsOption); + + CommandLine cmd; + CommandLineParser parser = new DefaultParser(); + HelpFormatter helper = new HelpFormatter(); + + try { + String instancesDir; + int[] agentNums = null; + I_InstanceBuilder instanceBuilder = new InstanceBuilder_MovingAI(); + String experimentName = "Unnamed Experiment"; + boolean skipAfterFail = false; + String instancesRegex = null; + String resultsOutputDir = null; + String optResultsFilePrefix = null; + + // Parse arguments + + cmd = parser.parse(options, args); + if(cmd.hasOption("s")) { + System.out.println("skipAfterFail set: Will skip trying more agents for the same instance and solver after failing."); + skipAfterFail = true; + } + + if (cmd.hasOption("n")) { + String optName = cmd.getOptionValue("name"); + System.out.println("Experiment Name: " + optName); + experimentName = optName; + } + + String optInstancesDir = cmd.getOptionValue(STR_INSTANCES_DIR); + System.out.println("Instances Dir: " + optInstancesDir); + instancesDir = optInstancesDir; + if (! new File(instancesDir).exists()){ + System.out.printf("Could not locate the provided instances dir (%s)", instancesDir); + System.exit(0); + } + + if(cmd.hasOption("resDir")) { + String optResultsDir = cmd.getOptionValue(STR_RESULTS_DIR_OPTION); + System.out.println("Trying to set results dir to " + optResultsDir); + resultsOutputDir = optResultsDir; + verifyOutputPath(resultsOutputDir); + } + + if(cmd.hasOption("resPref")) { + optResultsFilePrefix = cmd.getOptionValue(STR_RESULTS_FILE_PREFIX); + } + + if (cmd.hasOption(STR_INSTANCES_REGEX)){ + String optInstancesRegex = cmd.getOptionValue(STR_INSTANCES_REGEX); + System.out.println("Instances Regex: " + optInstancesRegex); + instancesRegex = optInstancesRegex; + } + + if (cmd.hasOption("iForm")) { + String optInstancesFormat = cmd.getOptionValue("instancesFormat"); + System.out.println("Instances Format: " + optInstancesFormat); + switch (optInstancesFormat) { + case STR_MOVING_AI -> instanceBuilder = new InstanceBuilder_MovingAI(); + case STR_BGU -> instanceBuilder = new InstanceBuilder_BGU(); + case STR_WAREHOUSE -> instanceBuilder = new InstanceBuilder_Warehouse(); + default -> { + System.out.printf("Unrecognized instance format: %s", optInstancesFormat); + System.exit(0); + } + } + } + else { + System.out.printf("Using default instance format %s", STR_MOVING_AI); + } + + String[] optAgents = cmd.getOptionValues(STR_AGENT_NUMS); + System.out.println("Agent nums: " + Arrays.toString(optAgents)); + + try { + agentNums = Arrays.stream(optAgents).mapToInt(Integer::parseInt).toArray(); + } + catch (NumberFormatException e){ + System.out.printf("%s should be an array of integers, got %s", STR_AGENT_NUMS, Arrays.toString(optAgents)); + System.exit(0); + } + + // Run! + new GenericRunManager(instancesDir, agentNums, instanceBuilder, experimentName, skipAfterFail, instancesRegex, resultsOutputDir, optResultsFilePrefix) + .runAllExperiments(); + + } catch (ParseException e) { + System.out.println(e.getMessage()); + helper.printHelp("Usage:", options); + System.exit(0); + } + } + + private static void staticMain() { + if (verifyOutputPath(exampleResultsOutputDir)){ // will solve a single instance and print the solution solveOneInstanceExample(); // will solve multiple instances and print a simple report for each instance @@ -46,19 +225,6 @@ public static void main(String[] args) { } } - private static boolean verifyOutputPath() { - File directory = new File(resultsOutputDir); - if (! directory.exists()){ - boolean created = directory.mkdir(); - if(!created){ - String errString = "Could not locate or create output directory."; - System.out.println(errString); - return false; - } - } - return true; - } - public static void solveOneInstanceExample(){ // write the reports to System.out addConsoleAsOutputStream(); @@ -116,7 +282,7 @@ private static void outputResults() { throw new RuntimeException(e); } DateFormat dateFormat = S_Metrics.defaultDateFormat; - String updatedPath = resultsOutputDir + "\\results " + dateFormat.format(System.currentTimeMillis()) + " .csv"; + String updatedPath = IO_Manager.buildPath(new String[]{exampleResultsOutputDir, "results " + dateFormat.format(System.currentTimeMillis())}) + " .csv"; try { S_Metrics.exportCSV(new FileOutputStream(updatedPath), new String[]{ InstanceReport.StandardFields.experimentName,