From 63b5ec883d8fbcca2cd24713b229f31e99f7cbc0 Mon Sep 17 00:00:00 2001 From: TKasekamp <toniskasekamp@gmail.com> Date: Mon, 25 May 2015 19:59:21 +0300 Subject: [PATCH] Config file support The miner can now accept very basic properties files. The query parsing part is very very basic. All rules will be generated with all events, no default placeholders are allowed. v1.1.0 --- pom.xml | 2 +- .../java/ee/tkasekamp/ltlminer/LTLMiner.java | 45 +++++++---- .../tkasekamp/ltlminer/LTLMinerStarter.java | 37 +++++++++ .../ltlminer/RuleTemplateCreator.java | 75 +++++++++++++++++++ .../ee/tkasekamp/ltlminer/LTLMinerTest.java | 21 ------ .../ltlminer/RuleTemplateCreatorTest.java | 25 +++++++ .../ee/tkasekamp/ltlminer/StarterTest.java | 40 ++++++++++ 7 files changed, 210 insertions(+), 35 deletions(-) create mode 100644 src/main/java/ee/tkasekamp/ltlminer/RuleTemplateCreator.java delete mode 100644 src/test/java/ee/tkasekamp/ltlminer/LTLMinerTest.java create mode 100644 src/test/java/ee/tkasekamp/ltlminer/RuleTemplateCreatorTest.java create mode 100644 src/test/java/ee/tkasekamp/ltlminer/StarterTest.java diff --git a/pom.xml b/pom.xml index 5287715..e51662e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ <groupId>ee.tkasekamp</groupId> <artifactId>ltlminer</artifactId> - <version>1.0.1</version> + <version>1.1.0</version> <packaging>jar</packaging> <name>LTLMiner</name> diff --git a/src/main/java/ee/tkasekamp/ltlminer/LTLMiner.java b/src/main/java/ee/tkasekamp/ltlminer/LTLMiner.java index 70da138..ccc7bf4 100644 --- a/src/main/java/ee/tkasekamp/ltlminer/LTLMiner.java +++ b/src/main/java/ee/tkasekamp/ltlminer/LTLMiner.java @@ -32,6 +32,7 @@ public class LTLMiner { private RuleCreator ruleCreator; private LTLChecker checker; private LogFilter logFilter; + private double minSupport = 0.0; public LTLMiner() { ruleCreator = new RuleCreator(); @@ -40,29 +41,50 @@ public LTLMiner() { } public ArrayList<RuleModel> mine(XLog log, ArrayList<String> ruleTemplates, - double threshold) { + double minSupport) { + this.minSupport = minSupport; ArrayList<String> events = logFilter.getAllEvents(log); ArrayList<String> rules = ruleCreator.generateRules(ruleTemplates, events); Object[] objList = checkRules(log, rules); - return filter(objList, threshold); + return filter(objList); } public ArrayList<RuleModel> mineWithEventTypes(XLog log, - ArrayList<String> ruleTemplates, double threshold) { + ArrayList<String> ruleTemplates, double minSupport) { + this.minSupport = minSupport; ArrayList<String> events = logFilter.getAllEvents(log); ArrayList<String> eventTypes = logFilter.getEventTypes(log); ArrayList<String> rules = ruleCreator.generateRules(ruleTemplates, events, eventTypes); Object[] objList = checkRules(log, rules); - return filter(objList, threshold); + return filter(objList); } - + public ArrayList<RuleModel> mine(XLog log, Properties properties) { - // TODO - return null; + this.minSupport = Double.parseDouble(properties + .getProperty("minSupport")); + String queries = properties.getProperty("queries"); + ArrayList<String> ruleTemplates = RuleTemplateCreator + .createTemplates(queries); + + boolean considerEventTypes = Boolean.parseBoolean(properties + .getProperty("considerEventTypes")); + + ArrayList<String> events = logFilter.getAllEvents(log); + ArrayList<String> rules; + + if (considerEventTypes) { + ArrayList<String> eventTypes = logFilter.getEventTypes(log); + rules = ruleCreator + .generateRules(ruleTemplates, events, eventTypes); + } else { + rules = ruleCreator.generateRules(ruleTemplates, events); + } + Object[] objList = checkRules(log, rules); + return filter(objList); } private Object[] checkRules(XLog log, ArrayList<String> rules) { @@ -86,22 +108,19 @@ private void addRulesToChecker(ArrayList<String> rules) { /** * Gets {@link RuleModel} from {@link CheckResultObject} and returns the - * ones with coverage greater or equal to the threshold. + * ones with coverage greater or equal to the minSupport. * * @param objList * {@link Object} array containing {@link CheckResultObject} - * @param threshold - * double * @return */ - private static ArrayList<RuleModel> filter(Object[] objList, - double threshold) { + private ArrayList<RuleModel> filter(Object[] objList) { CheckResultObject output = (CheckResultObject) objList[0]; ArrayList<RuleModel> result = new ArrayList<>(); for (RuleModel r : output.getRules()) { // TODO double comparison isn't good. Do with delta - if (r.getCoverage() >= threshold) { + if (r.getCoverage() >= minSupport) { result.add(r); } diff --git a/src/main/java/ee/tkasekamp/ltlminer/LTLMinerStarter.java b/src/main/java/ee/tkasekamp/ltlminer/LTLMinerStarter.java index b74417f..27d97da 100644 --- a/src/main/java/ee/tkasekamp/ltlminer/LTLMinerStarter.java +++ b/src/main/java/ee/tkasekamp/ltlminer/LTLMinerStarter.java @@ -1,8 +1,11 @@ package ee.tkasekamp.ltlminer; +import java.io.BufferedWriter; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Properties; @@ -30,6 +33,17 @@ public LTLMinerStarter(Properties properties) { public void mine() throws Exception { XLog log = readLogFile(config.getProperty("logPath")); ArrayList<RuleModel> output = miner.mine(log, config); + String asd = config.getProperty("outputFormat"); + switch (asd) { + case "console": + printToConsole(output); + break; + case "text": + saveToFile(output, config.getProperty("outputPath")); + break; + default: + break; + } } private Properties loadProperties(String propFileName) throws IOException { @@ -49,4 +63,27 @@ private Properties loadProperties(String propFileName) throws IOException { private XLog readLogFile(String logPath) throws Exception { return XLogReader.openLog(logPath); } + + private void printToConsole(ArrayList<RuleModel> output) { + System.out.println("coverage\tLTLRule"); + for (RuleModel ruleModel : output) { + System.out.println(ruleModel.getCoverage() + "\t" + + ruleModel.getLtlRule()); + } + } + + public void saveToFile(ArrayList<RuleModel> output, String outputPath) { + try { + BufferedWriter out = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(outputPath), "UTF-8")); + for (RuleModel ruleModel : output) { + out.write(ruleModel.getCoverage() + "\t" + + ruleModel.getLtlRule() + "\n"); + } + out.close(); + } catch (IOException e) { + System.err.println("Couldn't save to file: " + outputPath); + } + + } } diff --git a/src/main/java/ee/tkasekamp/ltlminer/RuleTemplateCreator.java b/src/main/java/ee/tkasekamp/ltlminer/RuleTemplateCreator.java new file mode 100644 index 0000000..955d939 --- /dev/null +++ b/src/main/java/ee/tkasekamp/ltlminer/RuleTemplateCreator.java @@ -0,0 +1,75 @@ +package ee.tkasekamp.ltlminer; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RuleTemplateCreator { + private static Pattern queryParameter = Pattern.compile("\\?(\\w+)"); + + public static ArrayList<String> createTemplates(String queries) { + ArrayList<String> templates = new ArrayList<>(); + + String[] s = queries.split(","); + for (String string : s) { + templates.add(bla(string)); + } + return templates; + } + + private static String bla(String thing) { + thing = thing.replaceAll("\"", ""); + + HashSet<String> a = getParameters(thing); + + thing = doSomething(thing); + return makeProper(thing, a); + + } + + private static String makeProper(String thing, HashSet<String> parameters) { + StringBuilder s = new StringBuilder(); + + s.append("formula rule("); + for (String string : parameters) { + s.append(string + ": activity,"); + } + if (parameters.size() != 0) { + s.deleteCharAt(s.lastIndexOf(",")); + } + s.append(") := {} \n"); + s.append(thing); + s.append(";"); + + return s.toString(); + } + + private static HashSet<String> getParameters(String query) { + Matcher m = queryParameter.matcher(query); + HashSet<String> asasdf = new HashSet<>(); + + while (m.find()) { + String parameter = m.group(1); + asasdf.add(parameter); + + } + + return asasdf; + } + + private static String doSomething(String query) { + Matcher m = queryParameter.matcher(query); + + StringBuffer sb = new StringBuffer(query.length()); + + while (m.find()) { + String parameter = m.group(1); + String text = "activity == " + parameter; + m.appendReplacement(sb, Matcher.quoteReplacement(text)); + + } + m.appendTail(sb); + return sb.toString(); + } +} diff --git a/src/test/java/ee/tkasekamp/ltlminer/LTLMinerTest.java b/src/test/java/ee/tkasekamp/ltlminer/LTLMinerTest.java deleted file mode 100644 index 6754b0c..0000000 --- a/src/test/java/ee/tkasekamp/ltlminer/LTLMinerTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package ee.tkasekamp.ltlminer; - -import static org.junit.Assert.*; - -import org.deckfour.xes.model.XLog; -import org.junit.Before; -import org.junit.Test; - -import ee.tkasekamp.ltlminer.util.XLogReader; - -public class LTLMinerTest { - LTLMiner miner; - XLog log; - - @Before - public void setUp() throws Exception { - miner = new LTLMiner(); - log = XLogReader.openLog("src/test/resources/exercise1.xes"); - } - -} diff --git a/src/test/java/ee/tkasekamp/ltlminer/RuleTemplateCreatorTest.java b/src/test/java/ee/tkasekamp/ltlminer/RuleTemplateCreatorTest.java new file mode 100644 index 0000000..db41f6c --- /dev/null +++ b/src/test/java/ee/tkasekamp/ltlminer/RuleTemplateCreatorTest.java @@ -0,0 +1,25 @@ +package ee.tkasekamp.ltlminer; + +import static org.junit.Assert.*; + +import java.util.ArrayList; + +import org.junit.Before; +import org.junit.Test; + +public class RuleTemplateCreatorTest { + + @Test + public void test() { + + String queries = "\"[]( (?x) -> <>(?y))\", \"<>(?x)\", \"[]( (?x) -> <>(?y)\" , \"[]( (?x) -> <>(?y)\""; + + ArrayList<String> templates = RuleTemplateCreator + .createTemplates(queries); + // for (String string : templates) { + // System.out.println(string); + // } + assertEquals(4, templates.size()); + } + +} diff --git a/src/test/java/ee/tkasekamp/ltlminer/StarterTest.java b/src/test/java/ee/tkasekamp/ltlminer/StarterTest.java new file mode 100644 index 0000000..91dab54 --- /dev/null +++ b/src/test/java/ee/tkasekamp/ltlminer/StarterTest.java @@ -0,0 +1,40 @@ +package ee.tkasekamp.ltlminer; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.Properties; + +import org.junit.Test; + +public class StarterTest { + + @Test + public void test() throws Exception { + LTLMinerStarter starter = new LTLMinerStarter(getProps()); + starter.mine(); + } + + @Test + public void test2() throws Exception { + Properties props = getProps(); + props.setProperty("outputFormat", "text"); + props.setProperty("outputPath", "rules.txt"); + LTLMinerStarter starter = new LTLMinerStarter(props); + starter.mine(); + assertTrue(new File("rules.txt").exists()); + } + + private Properties getProps() { + Properties props = new Properties(); + props.setProperty("logPath", "src/test/resources/exercise1.xes"); + props.setProperty("considerEventTypes", "true"); + props.setProperty("minSupport", "0.5"); + props.setProperty("outputFormat", "console"); + String queries = "\"[](( (?x) -> <>(?y)))\", \"<>(?x)\""; + props.setProperty("queries", queries); + + return props; + } + +}