Skip to content

Commit a9d0f0d

Browse files
authored
Add DOT parser for CFMPSs (#102)
* initial work on CFMPS parser * some more work * add more tests and documentation * improve documentation
1 parent 429f928 commit a9d0f0d

24 files changed

Lines changed: 1217 additions & 295 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1515
* Added `KWay{State,Transition}CoverTestsIterator`s to `automata-util` as a new means for conformance testing.
1616
* Added `CollectionUtil#allCombintationsIterator` and `CollectionUtil#allPermutationsIterator` for computing k-combinations and k-permutations.
1717
* Added `NFAs#canonize` to canonize NFAs via [Brzozowski's algorithm](https://en.wikipedia.org/wiki/DFA_minimization#Brzozowski's_algorithm).
18+
* Added a DOT parser for `ContextFreeModalProcessSystem`s.
19+
* For nondeterministic model types, `DOTParsers` now contains methods that accept an initial node prefix, in case the number of initial nodes is not known beforehand.
1820

1921
### Changed
2022

api/src/main/java/net/automatalib/graph/CFMPSGraphView.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,13 @@
4141
*/
4242
public class CFMPSGraphView<N, L, E, AP> implements Graph<Pair<L, N>, Pair<L, E>> {
4343

44+
private final L mainProcedure;
4445
private final Map<L, ProceduralModalProcessGraph<N, L, E, AP, ?>> pmpgs;
4546

4647
// cast is fine, because we make sure to only query nodes/edges belonging to the respective procedures
4748
@SuppressWarnings("unchecked")
48-
public CFMPSGraphView(Map<L, ? extends ProceduralModalProcessGraph<? extends N, L, ? extends E, AP, ?>> pmpgs) {
49+
public CFMPSGraphView(L mainProcedure, Map<L, ? extends ProceduralModalProcessGraph<? extends N, L, ? extends E, AP, ?>> pmpgs) {
50+
this.mainProcedure = mainProcedure;
4951
this.pmpgs = (Map<L, ProceduralModalProcessGraph<N, L, E, AP, ?>>) pmpgs;
5052
}
5153

@@ -91,6 +93,6 @@ public Collection<Pair<L, N>> getNodes() {
9193

9294
@Override
9395
public VisualizationHelper<Pair<L, N>, Pair<L, E>> getVisualizationHelper() {
94-
return new CFMPSVisualizationHelper<>(this.pmpgs);
96+
return new CFMPSVisualizationHelper<>(this.mainProcedure, this.pmpgs);
9597
}
9698
}

api/src/main/java/net/automatalib/graph/ContextFreeModalProcessSystem.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,6 @@ default int size() {
5050

5151
@Override
5252
default Graph<?, ?> graphView() {
53-
return new CFMPSGraphView<>(getPMPGs());
53+
return new CFMPSGraphView<>(getMainProcess(), getPMPGs());
5454
}
5555
}

api/src/main/java/net/automatalib/graph/visualization/CFMPSVisualizationHelper.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Map;
2323
import java.util.Map.Entry;
24+
import java.util.Objects;
2425

2526
import net.automatalib.common.util.HashUtil;
2627
import net.automatalib.common.util.Pair;
@@ -30,25 +31,26 @@
3031

3132
public class CFMPSVisualizationHelper<N, L, E> extends DefaultVisualizationHelper<Pair<L, N>, Pair<L, E>> {
3233

33-
private final Map<L, PMPGVisualizationHelper<N, E, ?>> visualizers;
34+
private final Map<L, PMPGVisualizationHelper<N, L, E, ?>> visualizers;
3435
private final List<Pair<L, N>> initialNodes;
3536

3637
// cast is fine, because we make sure to only query nodes/edges belonging to the respective procedures
3738
@SuppressWarnings("unchecked")
38-
public CFMPSVisualizationHelper(Map<L, ? extends ProceduralModalProcessGraph<? extends N, L, ? extends E, ?, ?>> pmpgs) {
39-
39+
public CFMPSVisualizationHelper(L mainProcedure,
40+
Map<L, ? extends ProceduralModalProcessGraph<? extends N, L, ? extends E, ?, ?>> pmpgs) {
4041
this.visualizers = new HashMap<>(HashUtil.capacity(pmpgs.size()));
4142
this.initialNodes = new ArrayList<>(pmpgs.size());
4243

4344
for (Entry<L, ? extends ProceduralModalProcessGraph<? extends N, L, ? extends E, ?, ?>> e : pmpgs.entrySet()) {
4445
final ProceduralModalProcessGraph<N, L, E, ?, ?> value =
4546
(ProceduralModalProcessGraph<N, L, E, ?, ?>) e.getValue();
47+
final L key = e.getKey();
4648
final N initialNode = value.getInitialNode();
4749

48-
this.visualizers.put(e.getKey(), new PMPGVisualizationHelper<>(value));
50+
this.visualizers.put(key, new PMPGVisualizationHelper<>(key, Objects.equals(key, mainProcedure), value));
4951

5052
if (initialNode != null) {
51-
this.initialNodes.add(Pair.of(e.getKey(), initialNode));
53+
this.initialNodes.add(Pair.of(key, initialNode));
5254
}
5355
}
5456
}
@@ -63,7 +65,7 @@ public boolean getNodeProperties(Pair<L, N> node, Map<String, String> properties
6365

6466
final L process = node.getFirst();
6567
@SuppressWarnings("assignment") // we only use identifier for which procedures exist
66-
final @NonNull PMPGVisualizationHelper<N, E, ?> visualizer = this.visualizers.get(process);
68+
final @NonNull PMPGVisualizationHelper<N, L, E, ?> visualizer = this.visualizers.get(process);
6769

6870
return visualizer.getNodeProperties(node.getSecond(), properties);
6971
}
@@ -73,7 +75,7 @@ public boolean getEdgeProperties(Pair<L, N> src, Pair<L, E> edge, Pair<L, N> tgt
7375

7476
final L process = edge.getFirst();
7577
@SuppressWarnings("assignment") // we only use identifier for which procedures exist
76-
final @NonNull PMPGVisualizationHelper<N, E, ?> visualizer = this.visualizers.get(process);
78+
final @NonNull PMPGVisualizationHelper<N, L, E, ?> visualizer = this.visualizers.get(process);
7779

7880
return visualizer.getEdgeProperties(src.getSecond(), edge.getSecond(), tgt.getSecond(), properties);
7981
}

api/src/main/java/net/automatalib/graph/visualization/PMPGVisualizationHelper.java

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,21 @@
2525
import net.automatalib.graph.ProceduralModalProcessGraph;
2626
import net.automatalib.ts.modal.transition.ProceduralModalEdgeProperty;
2727
import net.automatalib.visualization.DefaultVisualizationHelper;
28+
import org.checkerframework.checker.nullness.qual.Nullable;
2829

29-
public class PMPGVisualizationHelper<N, E, AP> extends DefaultVisualizationHelper<N, E> {
30+
public class PMPGVisualizationHelper<N, L, E, AP> extends DefaultVisualizationHelper<N, E> {
3031

32+
private final @Nullable L label;
33+
private final boolean isMain;
3134
private final ProceduralModalProcessGraph<N, ?, E, AP, ?> pmpg;
3235

3336
public PMPGVisualizationHelper(ProceduralModalProcessGraph<N, ?, E, AP, ?> pmpg) {
37+
this(null, false, pmpg);
38+
}
39+
40+
public PMPGVisualizationHelper(@Nullable L label, boolean isMain, ProceduralModalProcessGraph<N, ?, E, AP, ?> pmpg) {
41+
this.label = label;
42+
this.isMain = isMain;
3443
this.pmpg = pmpg;
3544
}
3645

@@ -52,17 +61,26 @@ public boolean getNodeProperties(N node, Map<String, String> properties) {
5261
final Set<AP> aps = pmpg.getNodeProperty(node);
5362

5463
if (aps.isEmpty()) {
55-
properties.put(NodeAttrs.LABEL, "");
64+
properties.put(PMPGNodeAttrs.LABEL, "");
5665
} else {
57-
properties.put(NodeAttrs.LABEL, aps.toString());
66+
properties.put(PMPGNodeAttrs.LABEL, aps.toString());
67+
}
68+
69+
if (label != null) {
70+
properties.put(PMPGNodeAttrs.PROCESS, label.toString());
71+
if (isMain) {
72+
properties.put(PMPGNodeAttrs.MAIN, "true");
73+
}
5874
}
5975

6076
if (Objects.equals(pmpg.getInitialNode(), node)) {
61-
properties.put(NodeAttrs.SHAPE, NodeShapes.OCTAGON);
77+
properties.put(PMPGNodeAttrs.SHAPE, NodeShapes.OCTAGON);
78+
properties.put(PMPGNodeAttrs.INITIAL, "true");
6279
} else if (Objects.equals(pmpg.getFinalNode(), node)) {
63-
properties.put(NodeAttrs.SHAPE, NodeShapes.BOX);
80+
properties.put(PMPGNodeAttrs.SHAPE, NodeShapes.BOX);
81+
properties.put(PMPGNodeAttrs.FINAL, "true");
6482
} else {
65-
properties.put(NodeAttrs.SHAPE, NodeShapes.CIRCLE);
83+
properties.put(PMPGNodeAttrs.SHAPE, NodeShapes.CIRCLE);
6684
}
6785

6886
return true;
@@ -83,8 +101,10 @@ public boolean getEdgeProperties(N src, E edge, N tgt, Map<String, String> prope
83101
styleJoiner.add(EdgeStyles.BOLD);
84102
}
85103

86-
properties.put(EdgeAttrs.LABEL, String.valueOf(pmpg.getEdgeLabel(edge)));
87-
properties.put(EdgeAttrs.STYLE, styleJoiner.toString());
104+
properties.put(PMPGEdgeAttrs.LABEL, String.valueOf(pmpg.getEdgeLabel(edge)));
105+
properties.put(PMPGEdgeAttrs.MODALITY, prop.getModalType().toString());
106+
properties.put(PMPGEdgeAttrs.PROCEDURALITY, prop.getProceduralType().toString());
107+
properties.put(PMPGEdgeAttrs.STYLE, styleJoiner.toString());
88108

89109
return true;
90110
}

api/src/main/java/net/automatalib/visualization/VisualizationHelper.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private CommonAttrs() {
8484
}
8585
}
8686

87-
sealed class NodeAttrs extends CommonAttrs permits MMLTNodeAttrs {
87+
sealed class NodeAttrs extends CommonAttrs permits MMLTNodeAttrs, PMPGNodeAttrs {
8888

8989
public static final String SHAPE = "shape";
9090
public static final String WIDTH = "width";
@@ -107,6 +107,17 @@ private MMLTNodeAttrs() {
107107
}
108108
}
109109

110+
final class PMPGNodeAttrs extends NodeAttrs {
111+
112+
public static final String PROCESS = "process";
113+
public static final String MAIN = "main";
114+
public static final String FINAL = "final";
115+
116+
private PMPGNodeAttrs() {
117+
// prevent instantiation
118+
}
119+
}
120+
110121
sealed class EdgeAttrs extends CommonAttrs permits MTSEdgeAttrs, MMLTEdgeAttrs {
111122

112123
public static final String PENWIDTH = "penwidth";
@@ -117,7 +128,7 @@ private EdgeAttrs() {
117128
}
118129
}
119130

120-
final class MTSEdgeAttrs extends EdgeAttrs {
131+
sealed class MTSEdgeAttrs extends EdgeAttrs permits PMPGEdgeAttrs {
121132

122133
public static final String MODALITY = "modality";
123134

@@ -135,6 +146,15 @@ private MMLTEdgeAttrs() {
135146
}
136147
}
137148

149+
final class PMPGEdgeAttrs extends MTSEdgeAttrs {
150+
151+
public static final String PROCEDURALITY = "procedurality";
152+
153+
private PMPGEdgeAttrs() {
154+
// prevent instantiation
155+
}
156+
}
157+
138158
final class NodeShapes {
139159

140160
public static final String NONE = "none";

0 commit comments

Comments
 (0)