From 18cd90dd048e07b0c4d599f5cda7b6e7ad97fafd Mon Sep 17 00:00:00 2001 From: hoechp Date: Thu, 18 May 2017 23:52:33 +0200 Subject: [PATCH] #36 not done yet, but having a little progress --- .../org/fujaba/graphengine/PatternEngine.java | 16 ++- .../TestLoadingTTCStateCaseData.java | 104 ++++++++++++++++-- 2 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/fujaba/graphengine/PatternEngine.java b/src/main/java/org/fujaba/graphengine/PatternEngine.java index 14c03ae..871f0b6 100644 --- a/src/main/java/org/fujaba/graphengine/PatternEngine.java +++ b/src/main/java/org/fujaba/graphengine/PatternEngine.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Set; import java.util.concurrent.TimeUnit; import javax.naming.spi.DirStateFactory.Result; @@ -1233,7 +1234,20 @@ public static Graph applyMatch(Match match) { for (PatternEdge patternEdge: patternNode.getPatternEdges()) { switch (patternEdge.getAction()) { case "-": // remove - matchedNode.removeEdge(patternEdge.getName(), clonedNodeMatch.get(patternEdge.getTarget())); + if (patternEdge.getName() == null) { + + //##### NEW TTC2017 FEATURE: + + Set oldKeys = new HashSet(matchedNode.getEdges().keySet()); + for (String s: oldKeys) { // TODO: this is experimental - too many edges could be removed... + matchedNode.removeEdge(s, clonedNodeMatch.get(patternEdge.getTarget())); + } + + //##### + + } else { + matchedNode.removeEdge(patternEdge.getName(), clonedNodeMatch.get(patternEdge.getTarget())); + } break; case "+": // create matchedNode.addEdge(patternEdge.getName(), clonedNodeMatch.get(patternEdge.getTarget())); diff --git a/src/test/java/org/fujaba/graphengine/unitTests/TestLoadingTTCStateCaseData.java b/src/test/java/org/fujaba/graphengine/unitTests/TestLoadingTTCStateCaseData.java index cb55de4..f72cf86 100644 --- a/src/test/java/org/fujaba/graphengine/unitTests/TestLoadingTTCStateCaseData.java +++ b/src/test/java/org/fujaba/graphengine/unitTests/TestLoadingTTCStateCaseData.java @@ -5,6 +5,8 @@ import org.fujaba.graphengine.Match; import org.fujaba.graphengine.PatternEngine; import org.fujaba.graphengine.graph.Graph; +import org.fujaba.graphengine.graph.Node; +import org.fujaba.graphengine.pattern.PatternAttribute; import org.fujaba.graphengine.pattern.PatternGraph; import org.fujaba.graphengine.pattern.PatternNode; import org.fujaba.graphengine.stateelimination.TTCStateCaseGraphLoader; @@ -56,26 +58,108 @@ public void testLoadingTTCStateCaseData() { @Test public void testTransformingTTCStateCaseData() { + // get data: String taskMainPath = "src/main/resources/ExperimentalData/testdata/emf/task-main/"; Graph g = TTCStateCaseGraphLoader.load(taskMainPath + "leader3_2.xmi"); - - PatternGraph gtr1 = new PatternGraph("gtr1"); - + System.out.println("loaded:\n" + g + "\n"); + + // gtr for new initial state: + PatternGraph gtrInitial = new PatternGraph("new initial state"); + PatternNode initialNode = new PatternNode("#{initial} == 1").addPatternAttribute(new PatternAttribute().setAction("-").setName("initial")); + PatternNode newInitialNode = new PatternNode().setAction("+").addPatternAttribute(new PatternAttribute().setAction("+").setName("newInitial").setValue(true)); + PatternNode noExistingNewInitialNode = new PatternNode("#{newInitial} == 1").setAction("!="); + gtrInitial.addPatternNode(initialNode, newInitialNode, noExistingNewInitialNode); + newInitialNode.addPatternEdge("+", "", initialNode); + ArrayList matches = PatternEngine.matchPattern(g, gtrInitial, true); // just a single match + Assert.assertEquals(1, matches.size()); + g = PatternEngine.applyMatch(matches.get(0)); + System.out.println("added new initial state (and removed 'initial' flag for the old one):\n" + g + "\n"); + + // gtr for new final state: + PatternGraph gtrFinal = new PatternGraph("new final state"); + PatternNode finalNode = new PatternNode("#{final} == 1").addPatternAttribute(new PatternAttribute().setAction("-").setName("final")); + PatternNode newFinalNode = new PatternNode().setAction("+").addPatternAttribute(new PatternAttribute().setAction("+").setName("newFinal").setValue(true)); + PatternNode noExistingNewFinalNode = new PatternNode("#{newFinal} == 1").setAction("!="); + gtrFinal.addPatternNode(finalNode, newFinalNode, noExistingNewFinalNode); + finalNode.addPatternEdge("+", "", newFinalNode); + matches = PatternEngine.matchPattern(g, gtrFinal, true); // just a single match + Assert.assertEquals(1, matches.size()); + g = PatternEngine.applyMatch(matches.get(0)); + System.out.println("added new final state (and removed 'final' flag for the old one):\n" + g + "\n"); + + // gtr for adding to new final state: + PatternGraph gtrOtherFinal = new PatternGraph("adding to the existing new final state"); + PatternNode otherFinalNode = new PatternNode("#{final == 1}").addPatternAttribute(new PatternAttribute().setAction("-").setName("final")); + PatternNode existingNewFinalNode = new PatternNode("#{newFinal} == 1"); + gtrOtherFinal.addPatternNode(otherFinalNode, existingNewFinalNode); + otherFinalNode.addPatternEdge("+", "", existingNewFinalNode); + do { + matches = PatternEngine.matchPattern(g, gtrOtherFinal, true); // just a single match (each time) + if (matches != null && matches.size() > 0) { + g = PatternEngine.applyMatch(matches.get(0)); + System.out.println("added edge to the new final state (and removed 'final' flag for the other one):\n" + g + "\n"); + } else { + break; + } + } while (true); + + // gtr for joining multiple edges between the same two nodes + /** + * this doesn't seem possible right now. you can't have a PatternGraph that says: + * 'find two (different) edges with any label between some nodes!' + * + * so we unfortunately seem to have to do this by hand: + */ + ArrayList sources = new ArrayList(); + ArrayList targets = new ArrayList(); + ArrayList firstLabels = new ArrayList(); + ArrayList secondLabels = new ArrayList(); + for (Node source: g.getNodes()) { + for (Node target: g.getNodes()) { + for (String sourceLabel1: source.getEdges().keySet()) { + if (source.getEdges(sourceLabel1).contains(target)) { + for (String sourceLabel2: source.getEdges().keySet()) { + if (!sourceLabel1.equals(sourceLabel2) && source.getEdges(sourceLabel2).contains(target)) { + sources.add(source); + targets.add(target); + firstLabels.add(sourceLabel1); + secondLabels.add(sourceLabel2); + } + } + } + } + } + } + for (int i = 0; i < sources.size(); ++i) { + sources.get(i).removeEdge(firstLabels.get(i), targets.get(i)); + sources.get(i).removeEdge(secondLabels.get(i), targets.get(i)); + sources.get(i).addEdge("[(" + firstLabels.get(i) + ")(" + secondLabels.get(i) + ")]", targets.get(i)); + } + System.out.println("after joining multiple labels with the same sources and same targets:\n" + g + "\n"); + + // gtr for state elimination itself (the q->k->p to q->p case) + PatternGraph gtrEliminate = new PatternGraph("eliminate state"); PatternNode p = new PatternNode(); - PatternNode k = new PatternNode(); + PatternNode k = new PatternNode().setAction("-"); PatternNode q = new PatternNode(); - - gtr1.addPatternNode(p, k, q); - + gtrEliminate.addPatternNode(p, k, q); p.addPatternEdge("-", (String)null, k); k.addPatternEdge("-", (String)null, q); p.addPatternEdge("+", "calculated", q); - ArrayList matches = PatternEngine.matchPattern(g, gtr1, false); + do { + matches = PatternEngine.matchPattern(g, gtrEliminate, true); // just a single match (each time) + if (matches != null && matches.size() > 0) { + g = PatternEngine.applyMatch(matches.get(0)); + System.out.println("eliminated a state (q->k->p to q->p):\n" + g + "\n"); + } else { + break; + } + } while (true); - Assert.assertTrue(matches.size() > 0); + // TODO: gtr for state elimination itself (the q->k->q to q->q case) - System.out.println("yay, " + matches.size() + " matches!"); + System.out.println("final graph: " + g); }