package net.seninp.grammarviz.cli; import com.beust.jcommander.JCommander; import net.seninp.gi.logic.GrammarRules; import net.seninp.gi.rulepruner.RulePrunerFactory; import net.seninp.gi.sequitur.SAXRule; import net.seninp.gi.sequitur.SequiturFactory; import net.seninp.jmotif.sax.SAXException; import net.seninp.jmotif.sax.SAXProcessor; import net.seninp.jmotif.sax.TSProcessor; import net.seninp.jmotif.sax.alphabet.NormalAlphabet; import net.seninp.jmotif.sax.datastructure.SAXRecords; import net.seninp.jmotif.sax.parallel.ParallelSAXImplementation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; /** * CLI for SAX + Sequitur rules production and pruning. */ public class TS2SequiturGrammar { private static Logger consoleLogger = LoggerFactory.getLogger(TS2SequiturGrammar.class); private static final String NEWLINE = System.lineSeparator(); private static TSProcessor tp = new TSProcessor(); private static NormalAlphabet na = new NormalAlphabet(); private static SAXProcessor sp = new SAXProcessor(); private static ParallelSAXImplementation psax = new ParallelSAXImplementation(); public static void main(String[] args) throws Exception { parseArgs(args); double[] series = readTimeSeries(); SAXRecords saxData = discretize(series); String str = saxData.getSAXString(" "); GrammarRules rules = inferGrammarRules(series, saxData, str); if (TS2GrammarParameters.PRUNE_RULES) { consoleLogger.info("Pruning rules ..."); rules = RulePrunerFactory.performPruning(series, rules); } consoleLogger.info("Producing the output ..."); new RulesWriter(TS2GrammarParameters.OUT_FILE) .write(rules); } private static void parseArgs(String[] args) { TS2GrammarParameters params = new TS2GrammarParameters(); JCommander jct = new JCommander(params, args); if (0 == args.length) { jct.usage(); } else { logParams(); } } private static void logParams() { String output = "GrammarViz2 CLI converter v.1" + NEWLINE + "parameters:" + NEWLINE + " input file: " + TS2GrammarParameters.IN_FILE + NEWLINE + " output file: " + TS2GrammarParameters.OUT_FILE + NEWLINE + " SAX sliding window size: " + TS2GrammarParameters.SAX_WINDOW_SIZE + NEWLINE + " SAX PAA size: " + TS2GrammarParameters.SAX_PAA_SIZE + NEWLINE + " SAX alphabet size: " + TS2GrammarParameters.SAX_ALPHABET_SIZE + NEWLINE + " SAX numerosity reduction: " + TS2GrammarParameters.SAX_NR_STRATEGY + NEWLINE + " SAX normalization threshold: " + TS2GrammarParameters.SAX_NORM_THRESHOLD + NEWLINE + " Pruning rules: " + TS2GrammarParameters.PRUNE_RULES + NEWLINE + NEWLINE; consoleLogger.info(output); } private static GrammarRules inferGrammarRules(double[] series, SAXRecords saxData, String str) throws Exception { consoleLogger.info("Inferring Sequitur grammar ..."); SAXRule grammar = SequiturFactory.runSequitur(str); consoleLogger.info("Collecting stats ..."); GrammarRules rules = grammar.toGrammarRulesData(); SequiturFactory.updateRuleIntervals(rules, saxData, true, series, TS2GrammarParameters.SAX_WINDOW_SIZE, TS2GrammarParameters.SAX_PAA_SIZE); return rules; } private static SAXRecords discretize(double[] series) throws SAXException { consoleLogger.info("Performing SAX conversion ..."); if (TS2GrammarParameters.NUM_WORKERS <= 1) { return sp.ts2saxViaWindow(series, TS2GrammarParameters.SAX_WINDOW_SIZE, TS2GrammarParameters.SAX_PAA_SIZE, na.getCuts(TS2GrammarParameters.SAX_ALPHABET_SIZE), TS2GrammarParameters.SAX_NR_STRATEGY, TS2GrammarParameters.SAX_NORM_THRESHOLD); } else { return psax.process(series, TS2GrammarParameters.NUM_WORKERS, TS2GrammarParameters.SAX_WINDOW_SIZE, TS2GrammarParameters.SAX_PAA_SIZE, TS2GrammarParameters.SAX_ALPHABET_SIZE, TS2GrammarParameters.SAX_NR_STRATEGY, TS2GrammarParameters.SAX_NORM_THRESHOLD); } } private static double[] readTimeSeries() throws SAXException, IOException { consoleLogger.info("Reading data ..."); double[] series = tp.readTS(TS2GrammarParameters.IN_FILE, 0); consoleLogger.info("read " + series.length + " points from " + TS2GrammarParameters.IN_FILE); return series; } }