diff --git a/src/main/java/org/fujaba/graphengine/PatternEngine.java b/src/main/java/org/fujaba/graphengine/PatternEngine.java index 6c5444b..4862f43 100644 --- a/src/main/java/org/fujaba/graphengine/PatternEngine.java +++ b/src/main/java/org/fujaba/graphengine/PatternEngine.java @@ -9,6 +9,8 @@ import javax.naming.spi.DirStateFactory.Result; +import org.fujaba.graphengine.algorithm.Algorithm; +import org.fujaba.graphengine.algorithm.Application; import org.fujaba.graphengine.graph.Graph; import org.fujaba.graphengine.graph.Node; import org.fujaba.graphengine.isomorphismtools.IsomorphismHandlerCSPLowHeuristics; diff --git a/src/main/java/org/fujaba/graphengine/algorithm/Algorithm.java b/src/main/java/org/fujaba/graphengine/algorithm/Algorithm.java new file mode 100644 index 0000000..eb7873a --- /dev/null +++ b/src/main/java/org/fujaba/graphengine/algorithm/Algorithm.java @@ -0,0 +1,104 @@ +package org.fujaba.graphengine.algorithm; + +import java.util.ArrayList; + +import org.fujaba.graphengine.Match; +import org.fujaba.graphengine.PatternEngine; +import org.fujaba.graphengine.graph.Graph; +import org.fujaba.graphengine.pattern.PatternGraph; + +public class Algorithm { + + private String name; + private ArrayList algorithmSteps; + private PatternGraph atomicAlgorithm; + private boolean repeating; + + public Algorithm(String name) { + this.name = name; + this.algorithmSteps = new ArrayList(); + this.atomicAlgorithm = null; + this.repeating = true; + } + + public Application process(Graph input) { + Graph output = input; + if (atomicAlgorithm != null) { + while (true) { + ArrayList matches = PatternEngine.matchPattern(output, atomicAlgorithm, true); + if (matches.size() > 0) { + output = PatternEngine.applyMatch(matches.get(0)); +// System.err.println("\n" + atomicAlgorithm.getName()); +// System.err.println(output); + if (!repeating) { + break; + } + } else { + break; + } + } + } else { + for (Algorithm algo: algorithmSteps) { + while (true) { + Graph subAlgorithmInput = output; + Application subAlgorithmApplication = algo.process(subAlgorithmInput); + if (subAlgorithmInput != subAlgorithmApplication.getOutput()) { + output = subAlgorithmApplication.getOutput(); + System.err.println("\n" + subAlgorithmApplication.getAlgorithm().getName()); + System.err.println(output); + if (!repeating) { + break; + } + } else { + break; + } + } + } + } + return new Application(this, input, output); + } + + public String getName() { + return name; + } + public Algorithm setName(String name) { + this.name = name; + return this; + } + public ArrayList getAlgorithmSteps() { + return algorithmSteps; + } + public Algorithm setAlgorithmSteps(ArrayList algorithmSteps) { + this.algorithmSteps = algorithmSteps; + return this; + } + public Algorithm addAlgorithmStep(Algorithm step) { + this.algorithmSteps.add(step); + return this; + } + public Algorithm addAlgorithmStep(PatternGraph step) { + return addAlgorithmStep(step, true); + } + public Algorithm addAlgorithmStep(PatternGraph step, boolean repeating) { + Algorithm newStep = new Algorithm(step.getName()); + newStep.setAtomicAlgorithm(step); + newStep.setRepeating(repeating); + this.algorithmSteps.add(newStep); + return this; + } + public PatternGraph getAtomicAlgorithm() { + return atomicAlgorithm; + } + public Algorithm setAtomicAlgorithm(PatternGraph atomicAlgorithm) { + this.atomicAlgorithm = atomicAlgorithm; + return this; + } + public boolean isRepeating() { + return repeating; + } + public Algorithm setRepeating(boolean repeat) { + this.repeating = repeat; + return this; + } + +} diff --git a/src/main/java/org/fujaba/graphengine/algorithm/Application.java b/src/main/java/org/fujaba/graphengine/algorithm/Application.java new file mode 100644 index 0000000..3a8d8fd --- /dev/null +++ b/src/main/java/org/fujaba/graphengine/algorithm/Application.java @@ -0,0 +1,39 @@ +package org.fujaba.graphengine.algorithm; + +import org.fujaba.graphengine.graph.Graph; + +public class Application { + + private Algorithm algorithm; + private Graph input; + private Graph output; + + public Application(Algorithm algorithm, Graph input, Graph output) { + this.algorithm = algorithm; + this.input = input; + this.output = output; + } + + public Algorithm getAlgorithm() { + return algorithm; + } + public Application setAlgorithm(Algorithm algorithm) { + this.algorithm = algorithm; + return this; + } + public Graph getInput() { + return input; + } + public Application setInput(Graph input) { + this.input = input; + return this; + } + public Graph getOutput() { + return output; + } + public Application setOutput(Graph output) { + this.output = output; + return this; + } + +} diff --git a/src/test/java/org/fujaba/graphengine/unitTests/TestTTCStateCase.java b/src/test/java/org/fujaba/graphengine/unitTests/TestTTCStateCase.java index 604623e..6d23dad 100644 --- a/src/test/java/org/fujaba/graphengine/unitTests/TestTTCStateCase.java +++ b/src/test/java/org/fujaba/graphengine/unitTests/TestTTCStateCase.java @@ -6,6 +6,7 @@ import org.fujaba.graphengine.GraphEngine; import org.fujaba.graphengine.Match; import org.fujaba.graphengine.PatternEngine; +import org.fujaba.graphengine.algorithm.Algorithm; import org.fujaba.graphengine.graph.Graph; import org.fujaba.graphengine.graph.Node; import org.fujaba.graphengine.pattern.PatternAttribute; @@ -16,94 +17,131 @@ import org.junit.Test; public class TestTTCStateCase { + + private static final String taskMainPath = "src/main/resources/ExperimentalData/testdata/emf/task-main/"; + private static final String[] fileNamesTaskMain = { + "leader3_2.xmi", + "leader4_2.xmi", + "leader3_3.xmi", + "leader5_2.xmi", + "leader3_4.xmi", + "leader3_5.xmi", + "leader4_3.xmi", + "leader6_2.xmi", + "leader3_6.xmi", + "leader4_4.xmi", + "leader5_3.xmi", + "leader3_8.xmi", + "leader4_5.xmi", + "leader6_3.xmi", + "leader4_6.xmi", + "leader5_4.xmi", + "leader5_5.xmi", + "leader6_4.xmi", + "leader6_5.xmi" + }; + + private static final String taskExtension1Path = "src/main/resources/ExperimentalData/testdata/emf/task-extension1/"; + private static final String[] fileNamesTaskExtension1 = { + "zeroconf.xmi" + }; + + @Test + public void testSolvingTTC2017StateEliminationCaseWithAlgorithm() { + Algorithm algorithmStateCaseTTC2017 = getStateCaseAlgorithmTTC2017(); + String[] fileNamesTaskMain = {"leader3_2.xmi"}; + for (String fileName: fileNamesTaskMain) { + System.out.println("TTC2017 State Elimination: " + fileName + "..."); + long beginTime = System.nanoTime(); + Graph g = TTCStateCaseGraphLoader.load(taskMainPath + fileName); // get data +// System.err.println(g); + Graph result = algorithmStateCaseTTC2017.process(g).getOutput(); + long endTime = System.nanoTime(); +// System.err.println(result); + System.out.println("Done after " + ((endTime - beginTime) / 1e9) + " seconds."); + String resultStringRaw = ""; + for (String s: result.getNodes().get(0).getEdges().keySet()) { + resultStringRaw = s; + } + String resultString = resultStringRaw.replaceAll(Pattern.quote("(ε)"), ""); + System.out.println(resultString + "\n"); + } + } @Test public void testSolvingTTC2017StateEliminationCase() { - - String taskMainPath = "src/main/resources/ExperimentalData/testdata/emf/task-main/"; - - String[] fileNames = { - "leader3_2.xmi", - "leader4_2.xmi", - "leader3_3.xmi", - "leader5_2.xmi", - "leader3_4.xmi", - "leader3_5.xmi", - "leader4_3.xmi", - "leader6_2.xmi", - "leader3_6.xmi", - "leader4_4.xmi", - "leader5_3.xmi", - "leader3_8.xmi", - "leader4_5.xmi", - "leader6_3.xmi", - "leader4_6.xmi", - "leader5_4.xmi", - "leader5_5.xmi", - "leader6_4.xmi", - "leader6_5.xmi" - }; - - for (int i = 0; i < 10; ++i) { - // warm up - solveGraph(TTCStateCaseGraphLoader.load(taskMainPath + fileNames[0])); - } - - for (String fileName: fileNames) { + for (String fileName: fileNamesTaskMain) { System.out.println("TTC2017 State Elimination: " + fileName + "..."); long beginTime = System.nanoTime(); Graph g = TTCStateCaseGraphLoader.load(taskMainPath + fileName); // get data -// System.out.println("Loaded graph:\n" + g + "\n"); Graph result = solveGraph(g); // solve problem long endTime = System.nanoTime(); - System.out.println("Done after " + ((endTime - beginTime) / 1e9) + " seconds."); -// System.out.println("Finished graph:\n" + result + "\n"); String resultStringRaw = ""; for (String s: result.getNodes().get(0).getEdges().keySet()) { resultStringRaw = s; } - String resultString = resultStringRaw.replaceAll(Pattern.quote("(ε)"), ""); -// System.out.println("Extracted string:"); System.out.println(resultString + "\n"); - } - } @Test public void testSolvingTTC2017StateEliminationCaseExtension1() { - - String taskMainPath = "src/main/resources/ExperimentalData/testdata/emf/task-extension1/"; - - String[] fileNames = { - "zeroconf.xmi" - }; - - for (String fileName: fileNames) { + for (String fileName: fileNamesTaskExtension1) { System.out.println("TTC2017 State Elimination (Extension 1): " + fileName + "..."); long beginTime = System.nanoTime(); - Graph g = TTCStateCaseGraphLoader.load(taskMainPath + fileName); // get data -// System.out.println("Loaded graph:\n" + g + "\n"); + Graph g = TTCStateCaseGraphLoader.load(taskExtension1Path + fileName); // get data Graph result = solveGraph(g); // solve problem long endTime = System.nanoTime(); - System.out.println("Done after " + ((endTime - beginTime) / 1e9) + " seconds."); -// System.out.println("Finished graph:\n" + result + "\n"); String resultStringRaw = ""; for (String s: result.getNodes().get(0).getEdges().keySet()) { resultStringRaw = s; } - String resultString = resultStringRaw.replaceAll(Pattern.quote("(ε)"), ""); -// System.out.println("Extracted string:"); System.out.println(resultString + "\n"); - } } + private static Algorithm getStateCaseAlgorithmTTC2017() { + + Algorithm stateCaseTTC2017 = new Algorithm("# TTC 2017 State Case").setRepeating(false); // one time (each) + + Algorithm prepareData = new Algorithm("# prepare data").setRepeating(false); // one time (each) + Algorithm eliminateState = new Algorithm("# eliminate state"); + Algorithm handleSourceNode = new Algorithm("# handle source node"); + Algorithm redirectRoute = new Algorithm("# redirect route"); + + stateCaseTTC2017.addAlgorithmStep(prepareData); + prepareData.addAlgorithmStep(getNewInitialPattern(), false); // one time (each) + prepareData.addAlgorithmStep(getAddToInitialPattern()); + prepareData.addAlgorithmStep(getNewFinalPattern(), false); // one time (each) + prepareData.addAlgorithmStep(getAddToFinalPattern()); + prepareData.addAlgorithmStep(getMergeEdgesPattern()); + stateCaseTTC2017.addAlgorithmStep(eliminateState); + eliminateState.addAlgorithmStep(getMarkStateForEliminationPattern(), false); // one time (each) + eliminateState.addAlgorithmStep(handleSourceNode); + handleSourceNode.addAlgorithmStep(getMarkWithCurrentPattern(), false); // one time (each) + handleSourceNode.addAlgorithmStep(getMarkFallbackWithCurrentPattern(), false); // one time (each) + handleSourceNode.addAlgorithmStep(redirectRoute); + redirectRoute.addAlgorithmStep(getPrepareStateWithPqPkKkKqPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPkKkKqPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPqPkKqPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPkKqPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPpPkKkKpPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPpPkKpPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPkKkKpPattern()); + redirectRoute.addAlgorithmStep(getPrepareStateWithPkKpPattern()); + handleSourceNode.addAlgorithmStep(getUnmarkCurrentPattern(), false); // one time (each) + handleSourceNode.addAlgorithmStep(getRemoveMarksPattern()); + eliminateState.addAlgorithmStep(getEliminateMarkedStatePattern(), false); // one time (each) + eliminateState.addAlgorithmStep(getUnmarkPastPattern(), false); // one time (each) + + return stateCaseTTC2017; + } + private Graph solveGraph(Graph g) { PatternGraph gtr_1_1 = getNewInitialPattern(); PatternGraph gtr_1_1_b = getAddToInitialPattern(); @@ -130,6 +168,7 @@ private Graph solveGraph(Graph g) { * How to loop: * * #1.1 + * #1.1 b) * #1.2 * #1.3 * #1.4 @@ -153,19 +192,22 @@ private Graph solveGraph(Graph g) { g = applyGTR(g, gtr_1_1, true); - g = applyGTR(g, gtr_1_1_b, true); + g = applyGTR(g, gtr_1_1_b); g = applyGTR(g, gtr_1_2, true); g = applyGTR(g, gtr_1_3); g = applyGTR(g, gtr_1_4); while (true) { - Graph copy1 = g.clone(); +// Graph copy1 = g.clone(); + Graph ref1 = g; g = applyGTR(g, gtr_2_1, true); while (true) { - Graph copy2 = g.clone(); +// Graph copy2 = g.clone(); + Graph ref2 = g; g = applyGTR(g, gtr_2_2_1, true); g = applyGTR(g, gtr_2_2_2, true); while (true) { - Graph copy3 = g.clone(); +// Graph copy3 = g.clone(); + Graph ref3 = g; g = applyGTR(g, gtr_2_3_1); g = applyGTR(g, gtr_2_3_2); g = applyGTR(g, gtr_2_3_3); @@ -174,19 +216,22 @@ private Graph solveGraph(Graph g) { g = applyGTR(g, gtr_2_3_6); g = applyGTR(g, gtr_2_3_7); g = applyGTR(g, gtr_2_3_8); - if (GraphEngine.isIsomorphTo(g, copy3)) { +// if (GraphEngine.isIsomorphTo(g, copy3)) { + if (g == ref3) { break; } } g = applyGTR(g, gtr_2_4, true); g = applyGTR(g, gtr_2_5); - if (GraphEngine.isIsomorphTo(g, copy2)) { +// if (GraphEngine.isIsomorphTo(g, copy2)) { + if (g == ref2) { break; } } g = applyGTR(g, gtr_2_6, true); g = applyGTR(g, gtr_2_7); - if (GraphEngine.isIsomorphTo(g, copy1)) { +// if (GraphEngine.isIsomorphTo(g, copy1)) { + if (g == ref1) { break; } } @@ -428,10 +473,10 @@ Graph applyGTR(Graph g, PatternGraph gtr, boolean single) { PatternNode p = new PatternNode(); PatternNode k = new PatternNode("!(#{newFinal} || #{newInitial} || #{eliminate})"); PatternNode q = new PatternNode(); - PatternNode noOtherMarkedOne = new PatternNode("#{eliminate}").setAction("!="); // with this, it can also be repeated + PatternNode noOtherMarkedOne = new PatternNode("#{eliminate}").setAction("!="); k.addPatternAttribute(new PatternAttribute().setAction("+").setName("eliminate").setValue(true)); gtr.addPatternNode(p, k, q); - gtr.addPatternNode(noOtherMarkedOne); // with this, it can also be repeated + gtr.addPatternNode(noOtherMarkedOne); return gtr; } @@ -551,7 +596,7 @@ private static PatternGraph getMarkFallbackWithCurrentPattern() { // #2.2.1 private static PatternGraph getPrepareStateWithPkKkKpPattern() { // #2.3.7 (all matches; don't repeat) - could also be repeated // gtr for adding new calculated labels - PatternGraph gtr = new PatternGraph("##### prepare elimination of state (with just pk, kk, kp)"); + PatternGraph gtr = new PatternGraph("prepare elimination of state (with just pk, kk, kp)"); PatternNode p = new PatternNode("#{current} && !(#{used})").addPatternAttribute(new PatternAttribute().setAction("+").setName("used").setValue(true)); PatternNode k = new PatternNode("#{eliminate}"); gtr.addPatternNode(p, k);