Skip to content
Snippets Groups Projects
Commit 56ba3a25 authored by Johannes Mey's avatar Johannes Mey
Browse files

update state machine, sync dg and extendj

parent 81697652
No related branches found
No related tags found
No related merge requests found
aspect CycleGraph {
inh String Vertex.name();
eq CycleGraph.getVertex(int i).name() = "v" + i;
syn String Vertex.label() = name();
syn String CycleGraph.toDot() {
StringBuilder b = new StringBuilder();
b.append("strict digraph cycles {\n");
for (Vertex from: getVertexList()) {
b.append(" ").append(from.name()).append("[label=\"").append(from.label()).append("\"];\n");
for (Vertex to: from.getRefList()) {
b.append(" ").append(from.name()).append(" -> ").append(to.name()).append(";\n");
}
for (Vertex to: from.getRelList()) {
b.append(" ").append(from.name()).append(" -> ").append(to.name()).append("[dir=\"both\"];\n");
}
}
b.append("}\n");
return b.toString();
}
syn String CycleGraph.toPlant() {
StringBuilder b = new StringBuilder();
b.append("@startuml\n")
.append("hide circle\n")
.append("skinparam shadowing false\n")
.append("skinparam monochrome true\n")
.append("skinparam classAttributeIconSize 0\n")
.append("/'Remove automatic namespace generation'/\n")
.append("set namespaceSeparator none\n");
for (Vertex from: getVertexList()) {
b.append("package ").append(from.label()).append("\n");
}
for (Vertex from: getVertexList()) {
for (Vertex to: from.getRefList()) {
b.append(from.label()).append(" ..> ").append(to.label()).append("\n");
}
for (Vertex to: from.getRelList()) {
b.append(from.label()).append(" <..> ").append(to.label()).append("\n");
}
}
b.append("@enduml\n");
return b.toString();
}
}
CycleGraph ::= Vertex*;
Vertex;
rel Vertex.Ref* -> Vertex;
rel Vertex.Rel* -> Vertex;
aspect DGtoCG {
syn CycleGraph Component.cycleGraph() {
CycleGraph cg = new CycleGraph();
Set<Component> scc = SCC();
Map<Component,Vertex> componentMap = new HashMap<>();
for (Component component: scc) {
Vertex v = new Vertex();
v.setComponent(component);
cg.addVertex(v);
componentMap.put(component, v);
}
for (Component from: scc) {
for (Component to: from.getToList()) {
if (scc.contains(to)) {
if (to.getToList().contains(from)) {
if (to.hashCode() < from.hashCode()) {
componentMap.get(from).addRel(componentMap.get(to));
}
} else {
componentMap.get(from).addRef(componentMap.get(to));
}
}
}
}
return cg;
}
}
rel Vertex.Component -> Component;
......@@ -23,36 +23,23 @@ aspect Reachability {
// coll HashSet<Set<Component>> DependencyGraph.SCC() with add root DependencyGraph;
// Component contributes SCC() when SCC().size() > 0 to DependencyGraph.SCC();
// stubs for tests that use old algorithm
syn lazy Set<Component> Component.predecessors() = new HashSet<>();
syn lazy Set<Component> Component.successors() = new HashSet<>();
syn lazy Set<Component> Component.SCC() = new HashSet<>();
/**
* Kosaraju's algorithm
*/
syn Set<Set<Component>> DependencyGraph.SCC() {
// System.out.println("Kosaraju's algorithm");
Map<Component, Integer> visited = new HashMap<>();
Deque<Component> locked = new LinkedList<>();
//Visit nodes forward
// long startVisit = System.nanoTime();
// visit nodes forward
for (Component n : getComponentList())
visit(n, visited, locked);
//Assign nodes to SCCs backward
// long startAssign = System.nanoTime();
// assign nodes to SCCs backward
int scc = 0;
for (Component n : locked) {
assign(n, visited, scc);
scc++;
}
// long stop = System.nanoTime();
//Map visited Map[Node,int]-> result Map[int,Set[Node]]
// System.out.println("visit : " + (startAssign - startVisit));
// System.out.println("assign: " + (stop - startAssign));
// System.out.println("sum: " + (stop - startVisit));
Map<Integer, Set<Component>> result = visited.entrySet().stream().collect(
Collectors.groupingBy(
......
......@@ -5,24 +5,24 @@ aspect DotGraphToPlantUML {
syn String DotNode.label() = name();
// syn String CycleGraph.toDot() {
// StringBuilder b = new StringBuilder();
// b.append("strict digraph cycles {\n");
// for (Vertex from: getVertexList()) {
// b.append(" ").append(from.name()).append("[label=\"").append(from.label()).append("\"];\n");
// for (Vertex to: from.getRefList()) {
// b.append(" ").append(from.name()).append(" -> ").append(to.name()).append(";\n");
// }
// for (Vertex to: from.getRelList()) {
// b.append(" ").append(from.name()).append(" -> ").append(to.name()).append("[dir=\"both\"];\n");
// }
// }
// b.append("}\n");
// return b.toString();
// }
syn String DotGraph.toDot() {
StringBuilder b = new StringBuilder();
b.append("strict digraph cycles {\n");
for (DotNode from: getDotNodeList()) {
b.append(" ").append(from.name()).append("[label=\"").append(from.label()).append("\"];\n");
for (DotNode to: from.getRefList()) {
b.append(" ").append(from.name()).append(" -> ").append(to.name()).append(";\n");
}
for (DotNode to: from.getRelList()) {
b.append(" ").append(from.name()).append(" -> ").append(to.name()).append("[dir=\"both\"];\n");
}
}
b.append("}\n");
return b.toString();
}
syn String DotGraph.toPlant(String shape, String relation) {
StringBuilder b = new StringBuilder();
......
Subproject commit bab01c7e6df0d3e6aa2a0bc0ba7dc9f6f2ee3184
Subproject commit c23954e3ad62befd3a293f7e02b85526cba194ed
......@@ -38,7 +38,7 @@ task cleanRagdoc(type: Delete) {
dependencies {
compile 'org.jgrapht:jgrapht-core:1.3.1'
compile 'org.jastadd:jastadd:2.3.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
......@@ -86,29 +86,26 @@ task preprocess(type: JavaExec) {
"libs/relast.jar",
"./src/main/jastadd/StateMachine.relast",
"../dg/src/main/jastadd/DependencyGraph.relast",
"../dg/src/main/jastadd/CycleGraph.relast",
"../dg/src/main/jastadd/DGtoCG.relast",
"../dg/src/main/jastadd/DotGraph.relast",
"../dg/src/main/jastadd/DGtoDotG.relast",
"./src/main/jastadd/mapping/SMtoDG.relast",
"--listClass=ArrayList",
"--jastAddList=JastAddList",
"--serializer=jackson",
// "--serializer=jackson",
"--useJastAddNames",
"--file",
"--resolverHelper",
// "--resolverHelper",
"--grammarName=./src/gen/jastadd/StateMachine"
]
inputs.files file("./src/main/jastadd/StateMachine.relast"),
file("../dg/src/main/jastadd/DependencyGraph.relast"),
file("../dg/src/main/jastadd/CycleGraph.relast"),
file("../dg/src/main/jastadd/DGtoCG.relast"),
file("../dg/src/main/jastadd/DotGraph.relast"),
file("../dg/src/main/jastadd/DGtoDotG.relast"),
file("./src/main/jastadd/mapping/SMtoDG.relast"),
file("./libs/relast.jar")
outputs.files file("./src/gen/jastadd/StateMachine.ast"),
file("./src/gen/jastadd/StateMachine.jadd"),
file("./src/gen/jastadd/StateMachineRefResolver.jadd"),
file('./src/gen/jastadd/StateMachineResolverStubs.jrag'),
file("./src/gen/jastadd/StateMachineSerializer.jadd")
file("./src/gen/jastadd/StateMachine.jadd")
}
task jastadd2(type: JavaExec) {
......@@ -122,7 +119,7 @@ task jastadd2(type: JavaExec) {
"--visitCheck=false",
"--package=de.tudresden.inf.st.sle19.jastadd.model",
"--o=src/gen/java"
] + fileTree("./src/main/jastadd/").matching {exclude "**/*.relast"} + fileTree("../dg/src/main/jastadd/").matching {exclude "**/*.relast"} + file("./src/gen/jastadd/StateMachine.ast") + file("./src/gen/jastadd/StateMachine.jadd") + file("./src/gen/jastadd/StateMachineRefResolver.jadd") + file('./src/gen/jastadd/StateMachineResolverStubs.jrag') + file("./src/gen/jastadd/StateMachineSerializer.jadd")
] + fileTree("./src/main/jastadd/").matching {exclude "**/*.relast"} + fileTree("../dg/src/main/jastadd/").matching {exclude "**/*.relast"} + file("./src/gen/jastadd/StateMachine.ast") + file("./src/gen/jastadd/StateMachine.jadd")
doFirst {
delete fileTree('src/gen/java/')
......
......@@ -3,8 +3,18 @@ package de.tudresden.inf.st.sle19;
import de.tudresden.inf.st.sle19.jastadd.model.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jgrapht.Graph;
import org.jgrapht.alg.connectivity.KosarajuStrongConnectivityInspector;
import org.jgrapht.alg.interfaces.StrongConnectivityAlgorithm;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Main {
......@@ -107,37 +117,79 @@ public class Main {
gg.setTo(g);
gg.setLabel("gg");
stateMachine.addElement(gg);
{
// show reachability table
Set<Set<Component>> dgComponentSCCType = stateMachine.dependencyGraph().SCC();
Set<Set<State>> dgSCCType = dgComponentSCCType.stream()
.map(scc -> scc.stream().map(Component::getState).collect(Collectors.toSet()))
.collect(Collectors.toSet());
logger.info("Reachability (ORIGINAL):");
for (State state: stateMachine.states()) {
logger.info("state {}", state);
logger.info(" is in cycle: {}", state.hasCycle());
logger.info(" suc {}", state.successors());
logger.info(" pre {}", state.predecessors());
logger.info(" SCC: {}", state.SCC());
}
List<Set<Component>> dgJGraphTSCCType = jgraphtComputeSCC(stateMachine.dependencyGraph());
Set<Set<State>> dgSCCType2 = dgJGraphTSCCType.stream()
.map(scc -> scc.stream().map(Component::getState).collect(Collectors.toSet()))
.collect(Collectors.toSet());
logger.info("SCCs: {}", stateMachine.SCC());
System.out.println("\nType Dependency analysis:");
System.out.println(" DepGrap SCC: " + dgSCCType);
System.out.println(" JGraphT SCC: " + dgSCCType2);
System.out.println(" SCCs are equal: " + dgSCCType.equals(dgSCCType2));
System.out.println("\n\n");
DependencyGraph dependencyGraph = stateMachine.dependencyGraph();
logger.info("Reachability (DependencyGraph):");
for (Component component: dependencyGraph.getComponentList()) {
logger.info("component {}", component);
logger.info(" suc {}", component.successors());
logger.info(" pre {}", component.predecessors());
logger.info(" SCC: {}", component.SCC());
try {
new File("graph/statemachine/dot/").mkdirs();
int sccIndex = 0;
for (Set<Component> scc : dgComponentSCCType) {
if (scc.size() > 1) {
PrintWriter writer = new PrintWriter("graph/statemachine/dot/scc" + sccIndex + ".dot");
writer.println(stateMachine.dependencyGraph().dotGraph(scc).toDot());
writer.flush();
writer.close();
sccIndex++;
}
}
logger.info("SCCs: {}", dependencyGraph.SCC());
new File("graph/statemachine/puml/").mkdirs();
sccIndex = 0;
for (Set<Component> scc : dgComponentSCCType) {
if (scc.size() > 1) {
PrintWriter writer = new PrintWriter("graph/statemachine/puml/scc" + sccIndex + ".puml");
writer.println(stateMachine.dependencyGraph().dotGraph(scc).toPlant("class", ".."));
writer.flush();
writer.close();
sccIndex++;
}
}
try {
stateMachine.serialize(new File("simpleSM.json"));
} catch (SerializationException e1) {
e1.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
}
}
}
/**
* Computes the set of SCC subgraphs utilizing JGraphT.
* This function is generic wrt. the actual ASTNode the Component
* is associated to.
*
* @param dg the given DependencyGraph
* @return a list of subgraphs of the SCCs
**/
private static List<Set<Component>> jgraphtComputeSCC(DependencyGraph dg) {
Graph<Component, DefaultEdge> directedGraph = new DefaultDirectedGraph<>(DefaultEdge.class);
for (Component c : dg.getComponentList()) {
directedGraph.addVertex(c);
}
for (Component to : dg.getComponentList()) {
for (Component from : to.getFromList()) {
directedGraph.addEdge(from, to);
}
}
// computes all the strongly connected components of the directed graph
StrongConnectivityAlgorithm<Component, DefaultEdge> alg =
new KosarajuStrongConnectivityInspector<>(directedGraph);
List<Set<Component>> scc = alg.stronglyConnectedSets();
return scc;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment