/** * */ package xhail; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import xhail.core.Config; import xhail.core.Dialler; import xhail.core.Finder; import xhail.core.Logger; import xhail.core.Utils; import xhail.core.entities.Answers; import xhail.core.entities.Problem; /** * @author stefano * */ public class Application implements Callable<Answers> { static { Answers.started(); } /** * The <code>PATHS</code> where <code>gringo</code> and <code>clasp</code> * most likely are. */ private static final Path[] PATHS = { Paths.get("/Library/Gringo/"), Paths.get("/Library/Clasp/"), Paths.get("/usr/bin/gringo/"), Paths.get("/usr/bin/clasp/"), Paths.get("/usr/bin/"), Paths.get("/usr/local/gringo/"), Paths.get("/usr/local/clasp/"), Paths.get("/usr/local/"), Paths.get("/opt/bin/"), Paths.get("/opt/local/"), Paths.get("/opt/clasp/"), Paths.get("/opt/gringo/"), Paths.get("/opt/local/gringo/"), Paths.get("/opt/local/clasp/"), Paths.get("C:\\Gringo\\"), Paths.get("C:\\Clasp\\") }; private static final Path ROOT = Paths.get(".").toAbsolutePath().getRoot().normalize(); private static final ExecutorService service = Executors.newSingleThreadExecutor(); /** * @param args */ public static void main(String[] args) { Config.Builder builder = new Config.Builder(); if (null == args) builder.missingParameter(); else for (int i = 0; i < args.length; i++) switch (args[i]) { case "-a": case "--all": builder.setAll(true); break; case "-b": case "--blind": builder.setBlind(true); break; case "-c": case "--clasp": if (args.length - i <= 1) builder.missingParameter(); else builder.setClasp(args[++i]); break; case "-d": case "--debug": builder.setDebug(true); break; case "-f": case "--full": builder.setFull(true); break; case "-g": case "--gringo": if (args.length - i <= 1) builder.missingParameter(); else builder.setGringo(args[++i]); break; case "-h": case "--help": builder.setHelp(true); break; case "-i": case "--iter": if (args.length - i <= 1) builder.missingParameter(); else builder.setIterations(args[++i]); break; case "-k": case "--kill": if (args.length - i <= 1) builder.missingParameter(); else builder.setKill(args[++i]); break; case "-m": case "--mute": builder.setMute(true); break; case "-o": case "--output": builder.setOutput(true); break; case "-p": case "--prettify": builder.setPrettify(true); // if (args.length - i > 1) { // String arg = args[i + 1].trim(); // int index = 0; // boolean found = true; // for (int p = 0; found && p < arg.length(); p++) { // found = Character.isDigit(arg.charAt(p)); // if (found) // index = 10 * index + (arg.charAt(p) - '0'); // } // if (found) { // builder.setIndex(index); // i += 1; // } // } break; case "-s": case "--search": builder.setSearch(true); break; case "-t": case "--terminate": builder.setTerminate(true); break; case "-v": case "--version": builder.setVersion(true); break; default: builder.addSource(args[i]); } Config config = builder.build(); Application application = new Application(config); application.execute(); } private final Config config; private final Problem problem; private Application(Config config) { if (null == config) throw new IllegalArgumentException("Illegal 'config' argument in Application(Config): " + config); this.config = config; if (config.isHelp()) Logger.help(); if (config.isVersion()) Logger.version(); Logger.header(config); if (!config.isPrettify()) { // || config.getIndex() > 0 Finder finder = new Finder(" 3.", "gringo", "clasp"); finder.test("gringo", config.getGringo()); finder.test("clasp", config.getClasp()); if (!finder.isFound() && config.isSearch()) { Logger.message("Locating needed applications..."); boolean found = false; for (int i = 0; !found && i < PATHS.length; i++) found = finder.find(PATHS[i], false); if (!found) found = finder.find(ROOT, true); config.setGringo(finder.get("gringo")); config.setClasp(finder.get("clasp")); if (found) Logger.found(config); } if (!finder.isFound()) { String message = ""; if (null == finder.get("gringo")) message += String.format("'gringo v3.*' needed to run %s", Logger.SIGNATURE); if (null == finder.get("clasp")) if (message.isEmpty()) message += String.format("'clasp v3.*' needed to run %s", Logger.SIGNATURE); else message += String.format("\n*** ERROR (%s): 'clasp v3.*' needed to run %s", Logger.SIGNATURE, Logger.SIGNATURE); Logger.error(message); } } Problem.Builder problem = new Problem.Builder(config); if (config.hasSources()) for (Path path : config.getSources()) { Logger.message(String.format("Reading from '%s'...", path.toString())); problem.parse(path); } else { Logger.message("Reading from 'stdin'..."); problem.parse(System.in); } this.problem = problem.build(); Answers.loaded(); } @Override public Answers call() throws Exception { Logger.message("\nSolving...\n"); return problem.solve(); } /** * */ public void execute() { if (config.isPrettify()) { System.out.println(); Utils.dump(problem, System.err); // int index = config.getIndex(); // switch (index) { // case -1: // Utils.dump(problem, System.err); // break; // case 0: // Utils.save(problem, System.err); // break; // default: // Dialler dialer = new Dialler.Builder(config, problem).build(); // String[] outputs = dialer.execute().getValue().toArray(new // String[0]); // if (index <= outputs.length) // Utils.save(new // Grounding.Builder(problem).addAtoms(Parser.parseAnswer(outputs[index // - 1])).build(), System.err); // else // Logger.message(String.format("*** Info (%s): no such inductive phase for this problem", // Logger.SIGNATURE)); // } } else { long kill = config.getKill(); try { final Future<Answers> task = service.submit(this); Answers answers = kill > 0L ? task.get(kill, TimeUnit.SECONDS) : task.get(); Logger.stamp(answers); } catch (CancellationException e) { Logger.message(String.format("*** Info (%s): computation was cancelled", Logger.SIGNATURE)); } catch (ExecutionException e) { Logger.message(String.format("*** Info (%s): computation threw an exception", Logger.SIGNATURE)); } catch (InterruptedException e) { Logger.message(String.format("*** Info (%s): current thread was interrupted while waiting", Logger.SIGNATURE)); } catch (TimeoutException e) { Logger.message(String.format("*** Info (%s): solving interrupted after %d second/s", Logger.SIGNATURE, kill)); if (config.isOutput()) { System.out.println("Problem,Answers,Calls,Loading,Abduction,Deduction,Induction,Wall"); System.err.format("interrupted,%d,%d,%.3f,%.3f,%.3f,%.3f,%.3f\n", problem.count(), Dialler.calls(), // Answers.getLoading(), Answers.getAbduction(), Answers.getDeduction(), Answers.getInduction(), kill * 1.0); } } catch (final Exception e) { // If something independent by our will happens... String message = "unexpected runtime error:\n " + e.getMessage(); for (StackTraceElement element : e.getStackTrace()) message += "\n " + element.toString(); Logger.error(message); } finally { service.shutdownNow(); } } } }