package inport; import java.io.*; import java.util.*; import java.util.function.Consumer; import java.util.function.Supplier; import static inport.Testing.*; import inport.ConversionUtils.*; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; import org.kohsuke.args4j.Option; public class Main { private static final int DEFAULT_TIME_LIMIT_S = 3600; private enum ConversionType { Undefined ("", Testing::getTask_2_Solver), WithoutSplitting("Without splitting", Testing::getTask_2_Solver), WithSplitting ("With splitting", Testing::getTaskWithPartialCargoOp_Solver), Greedy ("Greedy", Testing::getTaskWithGreedyConstraints_Solver), Greedy_v2 ("Greedy v2", Testing::getTaskWithGreedyConstraintsV2_Solver); private final String text; private final Supplier solversGetter; static final String legalValues = "\"Without splitting\", \"With splitting\", \"Greedy\", \"Greedy v2\""; ConversionType(String text, Supplier solversGerrer) { this.text = text; this.solversGetter = solversGerrer; } public static ConversionType fromString(String text) { for (ConversionType t : ConversionType.values()) { if (t.text.equalsIgnoreCase(text)) { return t; } } return Undefined; } } private static String undefinedTypeErrorMess(String undefType) { StringBuilder s = new StringBuilder("Undefined conversion type - \"" + undefType + "\".\n"); ArrayList values = new ArrayList<>(); for (ConversionType conversionType : ConversionType.values()) { if (! conversionType.equals(ConversionType.Undefined)) { values.add("\"" + conversionType.text + "\""); } } s.append("Conversion type can be one of ").append(String.join(", ", values)).append("."); return s.toString(); } private static class MainCommandsData { Boolean isHidden; String description; Consumer> command; MainCommandsData(Boolean isHidden, String description, Consumer> command) { this.isHidden = isHidden; this.description = description; this.command = command; } } private static void solve(Collection args) { try { class Arguments { @Option(name = "-fzs", aliases = "--flat_zinc_solver", usage = "Path to executable of flatZinc solver.", forbids = {"-s", "-opls"}) private String flatZincSolver = ""; @Option(name = "-opls", aliases = "--opl_solver", usage = "Path to \"oplrun\" from CPLEX.", forbids = {"-s", "-fzs"}) private String oplSolver = ""; @Argument(usage = "Path to task.", required = true) private String pathToTask = ""; @Option(name = "-ct", usage = "Type of conversion, one of " + ConversionType.legalValues + ".") private String conversionType = ConversionType.WithoutSplitting.text; @Option(name = "-s", aliases = "--solver", usage = "Solver from list : " + Solver.SolverName.legalValues + ".", forbids = {"-fzs", "-opls"}) private String solverName = Solver.SolverName.Chuffed.text; } Arguments arguments = new Arguments(); CmdLineParser parser = new CmdLineParser(arguments); if (args.isEmpty()) { parser.printUsage(System.out); return; } parser.parseArgument(args); long start = System.currentTimeMillis(); TaskCase task = new TaskCase(); task.deserialize(arguments.pathToTask); Solver solver; if (! task.isTypified()) { solver = getTask_2_Solver(); } else { ConversionType t = ConversionType.fromString(arguments.conversionType); if (t.equals(ConversionType.Undefined)) { System.out.println(undefinedTypeErrorMess(arguments.conversionType)); return; } solver = t.solversGetter.get(); } solver.setTask(task); solver.setTimeLimitS(DEFAULT_TIME_LIMIT_S); solver.setTempDir("temp_data"); if (! arguments.flatZincSolver.isEmpty()) { solver.setFlatZincSolver(arguments.flatZincSolver); } else if (! arguments.oplSolver.isEmpty()) { solver.setOPLSolver(arguments.oplSolver); solver.setConstraintName(solver.getConstraintName().replace(".mzn", ".mod")); solver.setConversionFormat(Task.ConversionFormat.OPL); } else { solver.setSolverName(arguments.solverName); } String error = solver.solve(); long finish = System.currentTimeMillis(); System.out.println((finish - start) + " milliseconds"); if (!error.isEmpty()) { System.out.println("Error : " + error); } else { task.serialize(arguments.pathToTask); } } catch (IOException ex) { throw new UncheckedIOException(ex); } catch (CmdLineException ex) { System.out.println("Illegal arguments: " + ex.getLocalizedMessage()); } } private static void tippToMzn(Collection args) { try { class Arguments { @Argument(usage = "Path to task.", required = true) private String pathToTask = ""; @Option(name = "-ct", usage = "Type of conversion, one of " + ConversionType.legalValues + ".") private String conversionType = ConversionType.WithoutSplitting.text; @Option(name = "-o", usage = "Directory for results.") private String outDir = "."; } Arguments arguments = new Arguments(); CmdLineParser parser = new CmdLineParser(arguments); if (args.isEmpty()) { parser.printUsage(System.out); return; } parser.parseArgument(args); ConversionType type = ConversionType.fromString(arguments.conversionType); if (type.equals(ConversionType.Undefined)) { System.out.println(undefinedTypeErrorMess(arguments.conversionType)); return; } TaskCase task = new TaskCase(); task.deserialize(arguments.pathToTask); String constraints = arguments.outDir + "/conversion.mzn"; String minizincData = arguments.outDir + "/minizinc_data.dzn"; Solver solver = type.solversGetter.get(); solver.getConverterToMiniZincFormat().accept(task, minizincData, solver.getConversionFormat()); try (FileWriter res = new FileWriter(constraints)) { BufferedReader reader = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream("/constraints/" + solver.getConstraintName()))); String line; while ((line = reader.readLine()) != null) { res.write(line + "\n"); } } } catch (CmdLineException ex) { System.out.println("Illegal arguments: " + ex.getLocalizedMessage()); } catch (IOException ex) { System.out.println("Error : " + ex.getMessage()); } } private static void tippToOpl(Collection args) { try { class Arguments { @Argument(usage = "Path to task.", required = true) private String pathToTask = ""; @Option(name = "-ct", usage = "Type of conversion, one of " + ConversionType.legalValues + ".") private String conversionType = ConversionType.WithoutSplitting.text; @Option(name = "-o", usage = "Directory for results.") private String outDir = "."; } Arguments arguments = new Arguments(); CmdLineParser parser = new CmdLineParser(arguments); if (args.isEmpty()) { parser.printUsage(System.out); return; } parser.parseArgument(args); ConversionType type = ConversionType.fromString(arguments.conversionType); if (type.equals(ConversionType.Undefined)) { System.out.println(undefinedTypeErrorMess(arguments.conversionType)); return; } TaskCase task = new TaskCase(); task.deserialize(arguments.pathToTask); String constraints = arguments.outDir + "/conversion.mod"; String minizincData = arguments.outDir + "/cplex_data.dat"; Solver solver = type.solversGetter.get(); solver.getConverterToMiniZincFormat().accept(task, minizincData, Task.ConversionFormat.OPL); try (FileWriter res = new FileWriter(constraints)) { BufferedReader reader = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream("/constraints/" + solver.getConstraintName().replace(".mzn", ".mod")))); String line; while ((line = reader.readLine()) != null) { res.write(line + "\n"); } } } catch (CmdLineException ex) { System.out.println("Illegal arguments: " + ex.getLocalizedMessage()); } catch (IOException ex) { System.out.println("Error : " + ex.getMessage()); } } private static void debug(Collection args) { class Arguments { @Option(name = "-fzs", aliases = "--flat_zinc_solver", usage = "Path to executable of flatZinc solver.", forbids = {"-s"}) private String flatZincSolver = ""; @Option(name = "-ct", usage = "Type of conversion, one of " + ConversionType.legalValues + ".") private String conversionType = ConversionType.WithoutSplitting.text; @Option(name = "-s", aliases = "--solver", usage = "Solver from list : " + Solver.SolverName.legalValues + ".", forbids = {"-fzs"}) private String solverName = Solver.SolverName.Chuffed.text; } Arguments arguments = new Arguments(); CmdLineParser parser = new CmdLineParser(arguments); if (args.isEmpty()) { parser.printUsage(System.out); return; } try { parser.parseArgument(args); ConversionType t = ConversionType.fromString(arguments.conversionType); if (t.equals(ConversionType.Undefined)) { System.out.println(undefinedTypeErrorMess(arguments.conversionType)); return; } Solver s = t.solversGetter.get(); if (arguments.flatZincSolver.isEmpty()) { s.setSolverName(arguments.solverName); } else { s.setFlatZincSolver(arguments.flatZincSolver); } debug(s, DEFAULT_TIME_LIMIT_S); } catch (CmdLineException ex) { System.out.println("Illegal arguments: " + ex.getLocalizedMessage()); } } private static void resolveResults(Collection args) { class Arguments { @Argument(usage = "Path to solution.", required = true) private String pathToSolution = ""; @Argument(usage = "Path to task.", required = true, index = 1) private String pathToTask = ""; } Arguments arguments = new Arguments(); CmdLineParser parser = new CmdLineParser(arguments); if (args.isEmpty()) { parser.printUsage(System.out); return; } try { parser.parseArgument(args); TaskCase task = new TaskCase(); task.deserialize(arguments.pathToTask); MZnResultsResolver.resolveMiniZincResults(task, arguments.pathToSolution); task.serialize(arguments.pathToTask); } catch (CmdLineException ex) { System.out.println("Illegal arguments: " + ex.getLocalizedMessage()); } catch (IOException ex) { System.out.println("Error : " + ex.getMessage()); } } private static void testing(Collection args) { class Arguments { @Option(name = "-fzs", aliases = "--flat_zinc_solver", usage = "Путь к исполняемому файлу flatZinc solver-а.", forbids = {"-s", "-opls"}) private String flatZincSolver = ""; @Option(name = "-opls", aliases = "--opl_solver", usage = "Path to \"oplrun\" from CPLEX.", forbids = {"-s", "-fzs"}) private String oplSolver = ""; @Option(name = "-ct", usage = "Тип сведения, один из " + ConversionType.legalValues + ".") private String conversionType = ConversionType.WithoutSplitting.text; @Option(name = "-s", aliases = "--solver", usage = "Тип solver-а из предопределённого списка : " + Solver.SolverName.legalValues + ".", forbids = {"-fzs", "-opls"}) private String solverName = Solver.SolverName.Chuffed.text; @Option(name = "-d", aliases = "--test_dir", usage = "Директория, задачи из которых необходимо протестировать.") private String testDir = "tests/with_typing"; } Arguments arguments = new Arguments(); CmdLineParser parser = new CmdLineParser(arguments); if (args.isEmpty()) { parser.printUsage(System.out); return; } try { parser.parseArgument(args); ConversionType t = ConversionType.fromString(arguments.conversionType); if (t.equals(ConversionType.Undefined)) { System.out.println(undefinedTypeErrorMess(arguments.conversionType)); return; } Solver s = t.solversGetter.get(); if (! arguments.flatZincSolver.isEmpty()) { s.setFlatZincSolver(arguments.flatZincSolver); } else if (! arguments.oplSolver.isEmpty()) { s.setOPLSolver(arguments.oplSolver); s.setConstraintName(s.getConstraintName().replace(".mzn", ".mod")); s.setConversionFormat(Task.ConversionFormat.OPL); } else { s.setSolverName(arguments.solverName); } testGroup(arguments.testDir, "", s, DEFAULT_TIME_LIMIT_S); } catch (CmdLineException ex) { System.out.println("Illegal arguments: " + ex.getLocalizedMessage()); } } public static void main(String[] args) { Map mainCommands = new TreeMap<>(); mainCommands.put("solve", new MainCommandsData(false, "Решение задачи.", Main::solve)); mainCommands.put("tippToMzn", new MainCommandsData( false , "Сводит задачу к формату MiniZinc-а используя заданное сведение. " + "Производит два файла - conversion.mzn и minizinc_data.dzn ." , Main::tippToMzn)); mainCommands.put("tippToOpl", new MainCommandsData( false , "Сводит задачу к формату OPL используя заданное сведение. " , Main::tippToOpl)); mainCommands.put("debug", new MainCommandsData(true, "", Main::debug)); mainCommands.put("resolve_results", new MainCommandsData(false, "Интерпретирует результат решения, как из MiniZinc-а, так и из FlatZinc-а.", Main::resolveResults)); mainCommands.put("testing", new MainCommandsData(false, "Тестирует все задачи в заданной директории с помошью одного solver-а.", Main::testing)); if (args.length < 1) { System.out.println("usage: java -jar Conversion.jar []"); System.out.println("Стандартные команды: "); int maxLength = 0; for (String name : mainCommands.keySet()) { if (! mainCommands.get(name).isHidden) { maxLength = Math.max(maxLength, name.length()); } } for (String name : mainCommands.keySet()) { MainCommandsData data = mainCommands.get(name); if (! data.isHidden) { System.out.print(name); for (int i = maxLength - name.length(); i > 0; i--) { System.out.print(" "); } System.out.println(" " + data.description); } } return; } MainCommandsData data = mainCommands.get(args[0]); if (data == null) { System.out.println("Unknown type \"" + args[0] + "\""); return; } data.command.accept(Arrays.asList(args).subList(1, args.length)); /* String type = args[0]; // TODO переделать switch (type) { case "debug read-write" : { debugReadWrite(); break; } case "different_parameters": testingWithDiffParameters( "tests/with_typing/Case2.tipp", 1, 30, 16, 35, 1.1, 30); break; default: System.out.println("Unknown type \"" + type + "\""); } */ } private static void debug(Solver solver, int timeLimitS) { String fileName = "experiment/in.ipp"; String solverResults = "experiment/solver_results.txt"; String output = "experiment/debug_info.txt"; TaskCase task = new TaskCase(); try { task.deserialize(fileName); } catch (IOException e) { System.out.println(e.getMessage()); return; } long start = System.currentTimeMillis(); solver.setTimeLimitS(timeLimitS); solver.setTempDir("temp_data"); solver.setTask(task); solver.setSolverResults(solverResults); String error = solver.solve(); long finish = System.currentTimeMillis(); System.out.println(" " + (finish - start) / 1000.0 + " s"); if (!error.isEmpty()) { System.out.println("Error : " + error); return; } else { task.serialize(fileName); } debugInfo(task, solverResults, output); } private static void debugReadWrite() { String fileName = "experiment/in.ipp"; TaskCase task = new TaskCase(); try { task.deserialize(fileName); } catch (IOException e) { System.out.println(e.getMessage()); return; } task.serialize(fileName); } private static void debugInfo(TaskCase task, String solverResults, String output) { try (FileInputStream fstream = new FileInputStream(solverResults)) { BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); FileWriter writer = new FileWriter(output, false); { ArrayList operations = new ArrayList<>(task.getTemplates()); if (task.isTypified()) { operations = Task.renumberOperations(task); } writer.write("operations :\n"); int no = 1; for (OperationTemplate op : operations) { writer.write(" " + no + " " + op.toString() + "\n"); no++; } writer.write("\n"); } Task t = new Task(task, ""); { ArrayList movingObjects = Task.calcMovingObjects(task); Map objByNo = new TreeMap<>(); for (MovingObject obj : movingObjects) { objByNo.put(t.getMObjNumberById().get(obj.getId()), obj); } writer.write("moving_objects : \n"); for (int i = 0; i < movingObjects.size(); i++) { writer.write(" " + (i + 1) + " " + objByNo.get(i).toString() + "\n"); } writer.write("\n"); } String line; while (((line = br.readLine()) != null)) { line = line.trim(); if (line.equals("")) { continue; } int pos = 0; while ((pos < line.length()) && (line.charAt(pos) != ' ')) { pos++; } String name = line.substring(0, pos); if ((name.equals("----------")) || (name.equals("=====UNSATISFIABLE====="))) { break; } ArrayList> array = MZnResultsResolver.parse2dArray(pos, line, task); if (array != null) { int maxSize = 0; for (ArrayList a : array) { for (int j = 0; j < a.size(); j++) { if (a.get(j).equals("true")) { a.set(j, "1"); } if (a.get(j).equals("false")) { a.set(j, "0"); } maxSize = Math.max(maxSize, a.get(j).length()); } } writer.write(name + " :\n"); for (ArrayList a : array) { writer.write(" "); for (String val : a) { writer.write(new String(new char[maxSize - val.length()]).replace("\0", " ") + val + " "); } writer.write("\n"); } writer.write("\n"); } } writer.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } }