diff --git a/beaver.gradle b/beaver.gradle
index f3aabfe3a3981548dc8a23f344432c03c2253bac..00c2e82335c3b6579534c95d2aa0179f17cd25b6 100644
--- a/beaver.gradle
+++ b/beaver.gradle
@@ -13,6 +13,107 @@ dependencies {
     jflex2 group:  'de.jflex', name: 'jflex', version: '1.6.1'
 }
 
+
+task generateMarkingCheckerBeaver(type: JavaExec) {
+
+    inputs.files {
+        project.file("src/main/jastadd/bcg/TinaMarkingParser.beaver")
+    }
+    outputs.dir {
+        // This closure is needed to delay reading the genDir setting.
+        project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaParser")
+    }
+
+    classpath = configurations.myBeaver2
+    main = 'beaver.comp.run.Make'
+
+    doFirst {
+        def outdir = project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaParser")
+        if (!outdir.isDirectory()) {
+            outdir.mkdirs()
+        }
+        def inputFile = project.file("src/main/jastadd/bcg/TinaMarkingParser.beaver")
+        args ([ '-d', outdir.path, '-t', '-c', '-w', inputFile.path ])
+    }
+}
+
+task generateReachabilityCheckerBeaver(type: JavaExec) {
+
+    inputs.files {
+        project.file("src/main/jastadd/bcg/TinaReachabilityParser.beaver")
+    }
+    outputs.dir {
+        // This closure is needed to delay reading the genDir setting.
+        project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaParser")
+    }
+
+    classpath = configurations.myBeaver2
+    main = 'beaver.comp.run.Make'
+
+    doFirst {
+        def outdir = project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaParser")
+        if (!outdir.isDirectory()) {
+            outdir.mkdirs()
+        }
+        def inputFile = project.file("src/main/jastadd/bcg/TinaReachabilityParser.beaver")
+        args ([ '-d', outdir.path, '-t', '-c', '-w', inputFile.path ])
+    }
+}
+
+task generateMarkingScanner(type: JavaExec) {
+
+    inputs.files {
+        project.file("src/main/jastadd/bcg/TinaMarking.flex")
+    }
+
+    outputs.dir {
+        // This closure is needed to delay reading the genDir setting.
+        project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaScanner")
+    }
+
+    classpath = configurations.jflex2
+    mainClass = 'jflex.Main'
+
+    doFirst {
+
+        def outdir = project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaScanner")
+        if (!outdir.isDirectory()) {
+            outdir.mkdirs()
+        }
+
+        def inputFile = project.file("src/main/jastadd/bcg/TinaMarking.flex")
+
+        args ([ '-d', outdir.path, inputFile.path ])
+    }
+}
+
+task generateReachabilityScanner(type: JavaExec) {
+
+    inputs.files {
+        project.file("src/main/jastadd/bcg/TinaReachability.flex")
+    }
+
+    outputs.dir {
+        // This closure is needed to delay reading the genDir setting.
+        project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaScanner")
+    }
+
+    classpath = configurations.jflex2
+    mainClass = 'jflex.Main'
+
+    doFirst {
+
+        def outdir = project.file("src/gen/java/de/tudresden/inf/st/pnml/jastadd/tinaScanner")
+        if (!outdir.isDirectory()) {
+            outdir.mkdirs()
+        }
+
+        def inputFile = project.file("src/main/jastadd/bcg/TinaReachability.flex")
+
+        args ([ '-d', outdir.path, inputFile.path ])
+    }
+}
+
 task generateExpressionBeaver(type: JavaExec) {
 
     inputs.files {
diff --git a/build.gradle b/build.gradle
index c33d01327163fdbf5c108e8c8022326e5f54778e..a259ac8f56ca20fbbb9eae5ad0ef62771ad3fb6b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -233,16 +233,11 @@ jastadd {
 }
 
 // Workflow configuration for phases
-//relastToJastAdd.dependsOn ":pnml-relast-base:ecoreToRelast"
-//generateAst.dependsOn  ":pnml-relast-base:relastToJastAdd"
-//compileJava.dependsOn ":pnml-relast-base:generateBeaver"
-
-/*compileJava.dependsOn ":pnml-relast-checker:generateMarkingCheckerBeaver"
-compileJava.dependsOn ":pnml-relast-checker:generateReachabilityCheckerBeaver"
-compileJava.dependsOn ":pnml-relast-checker:generateMarkingScanner"
-compileJava.dependsOn ":pnml-relast-checker:generateReachabilityScanner"
-*/
 relastToJastAdd.dependsOn ecoreToRelast
 generateAst.dependsOn relastToJastAdd
 
+compileJava.dependsOn generateMarkingCheckerBeaver
+compileJava.dependsOn generateReachabilityCheckerBeaver
+compileJava.dependsOn generateMarkingScanner
+compileJava.dependsOn generateReachabilityScanner
 compileJava.dependsOn generateExpressionBeaver
\ No newline at end of file
diff --git a/src/main/jastadd/bcg/TinaMarking.flex b/src/main/jastadd/bcg/TinaMarking.flex
new file mode 100644
index 0000000000000000000000000000000000000000..3346ed5073a73af80396c2f14ddbb1216096d25b
--- /dev/null
+++ b/src/main/jastadd/bcg/TinaMarking.flex
@@ -0,0 +1,50 @@
+package de.tudresden.inf.st.pnml.jastadd.scanner;
+
+import de.tudresden.inf.st.pnml.jastadd.tinaParser.TinaMarkingParser.Terminals;
+
+%%
+
+// define the signature for the generated scanner
+%public
+%final
+%class TinaMarkingScanner
+%extends beaver.Scanner
+
+// the interface between the scanner and the parser is the nextToken() method
+%type beaver.Symbol
+%function nextToken
+%yylexthrow beaver.Scanner.Exception
+
+// store line and column information in the tokens
+%line
+%column
+
+// this code will be inlined in the body of the generated scanner class
+%{
+  private beaver.Symbol sym(short id) {
+    return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext());
+  }
+%}
+
+WhiteSpace = [ ] | \t | \f
+NewLine    = \n | \r | \r\n
+Identifier = [:jletter:][:jletterdigit:]*
+
+
+Number = [:digit:]+
+// Number = [:digit:]+ | [:digit:]+ "." [:digit:]* | "." [:digit:]+
+
+%%
+
+// discard whitespace information
+// {WhiteSpace}  { }
+{NewLine}  { }
+
+// token definitions
+":"           { return sym(Terminals.COLON); }
+"*"           { return sym(Terminals.MULT); }
+// {NewLine}     { return sym(Terminals.NEWLINE); }
+{Identifier}  { return sym(Terminals.IDENTIFIER); }
+{Number}      { return sym(Terminals.NUMBER); }
+{WhiteSpace}  { return sym(Terminals.WHITESPACE); }
+<<EOF>>       { return sym(Terminals.EOF); }
diff --git a/src/main/jastadd/bcg/TinaMarkingParser.beaver b/src/main/jastadd/bcg/TinaMarkingParser.beaver
new file mode 100644
index 0000000000000000000000000000000000000000..bb26aed417b1828b0a510c1c84440ab1ef4187cb
--- /dev/null
+++ b/src/main/jastadd/bcg/TinaMarkingParser.beaver
@@ -0,0 +1,54 @@
+%header {:
+ package de.tudresden.inf.st.pnml.jastadd.tinaParser;
+ import de.tudresden.inf.st.pnml.jastadd.model.*;
+:};
+
+%terminals COLON;
+%terminals MULT;
+%terminals NUMBER;
+%terminals IDENTIFIER;
+%terminals WHITESPACE;
+
+%typeof tm_goal = "TinaMarking";
+%typeof netMarking_list = "JastAddList";
+%typeof netMarking = "NetMarking";
+%typeof placeMarking = "PlaceMarking";
+%typeof placeMarkingList = "JastAddList";
+
+%goal tm_goal;
+
+tm_goal =
+  netMarking_list.nm {: return new Symbol(new TinaMarking(nm)); :}
+  ;
+
+netMarking_list =
+    netMarking.nm                  {: return new Symbol(new JastAddList().add(nm)); :}
+  | netMarking_list.nml netMarking.nm2 {: return new Symbol(nml.add(nm2)); :}
+  ;
+
+netMarking =
+   NUMBER.name WHITESPACE.WS1 COLON.C WHITESPACE.WS2 placeMarkingList.list
+   {:
+     NetMarking result = new NetMarking();
+     result.setStateName(Integer.parseInt((String) name.value));
+     result.setPlaceMarkingList(list);
+     return new Symbol(result);
+   :}
+   | NUMBER.name WHITESPACE.WS1 COLON.C WHITESPACE.WS2
+   {:
+        NetMarking result = new NetMarking();
+        result.setStateName(Integer.parseInt((String) name.value));
+        return new Symbol(result);
+      :}
+  ;
+
+placeMarking =
+    IDENTIFIER.a         {: return new Symbol(new UnaryMarking((String)a.value)); :}
+  | IDENTIFIER.a MULT.M NUMBER.n1        {: return new Symbol(new MultMarking((String)a.value, Integer.parseInt((String) n1.value))); :}
+  ;
+
+placeMarkingList =
+    placeMarking.pm                              {: JastAddList result = new JastAddList<PlaceMarking>(); result.addChild(pm); return new Symbol(result); :}
+  | placeMarking.pm WHITESPACE.WS placeMarkingList.list        {: list.addChild(pm); return new Symbol(list); :}
+  | WHITESPACE.WS                                  {: return new Symbol(new JastAddList()); :}
+  ;
\ No newline at end of file
diff --git a/src/main/jastadd/bcg/TinaReachability.flex b/src/main/jastadd/bcg/TinaReachability.flex
new file mode 100644
index 0000000000000000000000000000000000000000..9187ce65f7f95af5c77b8bb99205555c95c30005
--- /dev/null
+++ b/src/main/jastadd/bcg/TinaReachability.flex
@@ -0,0 +1,51 @@
+package de.tudresden.inf.st.pnml.jastadd.scanner;
+
+import de.tudresden.inf.st.pnml.jastadd.tinaParser.TinaReachabilityParser.Terminals;
+
+%%
+
+// define the signature for the generated scanner
+%public
+%final
+%class TinaReachabilityScanner
+%extends beaver.Scanner
+
+// the interface between the scanner and the parser is the nextToken() method
+%type beaver.Symbol
+%function nextToken
+%yylexthrow beaver.Scanner.Exception
+
+// store line and column information in the tokens
+%line
+%column
+
+// this code will be inlined in the body of the generated scanner class
+%{
+  private beaver.Symbol sym(short id) {
+    return new beaver.Symbol(id, yyline + 1, yycolumn + 1, yylength(), yytext());
+  }
+%}
+
+WhiteSpace = [ ] | \t | \f
+NewLine    = \n | \r | \r\n
+Identifier = [:jletter:][:jletterdigit:]*
+
+
+Number = [:digit:]+
+// Number = [:digit:]+ | [:digit:]+ "." [:digit:]* | "." [:digit:]+
+
+%%
+
+// discard whitespace information
+// {WhiteSpace}  { }
+{NewLine}  { }
+
+// token definitions
+"->"           { return sym(Terminals.ARROW); }
+"/"           { return sym(Terminals.SLASH); }
+","           { return sym(Terminals.COMMA); }
+// {NewLine}     { return sym(Terminals.NEWLINE); }
+{Identifier}  { return sym(Terminals.IDENTIFIER); }
+{Number}      { return sym(Terminals.NUMBER); }
+{WhiteSpace}  { return sym(Terminals.WHITESPACE); }
+<<EOF>>       { return sym(Terminals.EOF); }
diff --git a/src/main/jastadd/bcg/TinaReachabilityParser.beaver b/src/main/jastadd/bcg/TinaReachabilityParser.beaver
new file mode 100644
index 0000000000000000000000000000000000000000..87b4b37ae32cc7f5943c824412b2dba22cd18e5e
--- /dev/null
+++ b/src/main/jastadd/bcg/TinaReachabilityParser.beaver
@@ -0,0 +1,54 @@
+%header {:
+ package de.tudresden.inf.st.pnml.jastadd.tinaParser;
+ import de.tudresden.inf.st.pnml.jastadd.model.*;
+:};
+
+%terminals SLASH;
+%terminals ARROW;
+%terminals NUMBER;
+%terminals COMMA;
+%terminals IDENTIFIER;
+%terminals WHITESPACE;
+
+%typeof tr_goal = "TinaReachability";
+%typeof netReachability_list = "JastAddList";
+%typeof netReachability = "NetReachability";
+%typeof enabledTransition = "EnabledTransition";
+%typeof enabledTransitionList = "JastAddList";
+
+%goal tr_goal;
+
+tr_goal =
+  netReachability_list.nm {: return new Symbol(new TinaReachability(nm)); :}
+  ;
+
+netReachability_list =
+    netReachability.nm                  {: return new Symbol(new JastAddList().add(nm)); :}
+  | netReachability_list.nml netReachability.nm2 {: return new Symbol(nml.add(nm2)); :}
+  ;
+
+netReachability =
+   NUMBER.name WHITESPACE.WS1 ARROW.A WHITESPACE.WS2 enabledTransitionList.list
+   {:
+     NetReachability result = new NetReachability();
+     result.setTargetReachabilityStateName(Integer.parseInt((String) name.value));
+     result.setEnabledTransitionList(list);
+     return new Symbol(result);
+   :}
+   | NUMBER.name WHITESPACE.WS1 ARROW.A WHITESPACE.WS2
+   {:
+        NetReachability result = new NetReachability();
+        result.setTargetReachabilityStateName(Integer.parseInt((String) name.value));
+        return new Symbol(result);
+      :}
+  ;
+
+enabledTransition =
+    IDENTIFIER.a SLASH.S NUMBER.n1        {: return new Symbol(new EnabledTransition((String)a.value, Integer.parseInt((String) n1.value))); :}
+  ;
+
+enabledTransitionList =
+    enabledTransition.pm                              {: JastAddList result = new JastAddList<EnabledTransition>(); result.addChild(pm); return new Symbol(result); :}
+  | enabledTransition.pm COMMA.C WHITESPACE.WS enabledTransitionList.list        {: list.addChild(pm); return new Symbol(list); :}
+  | WHITESPACE.WS                                  {: return new Symbol(new JastAddList()); :}
+  ;
\ No newline at end of file
diff --git a/src/main/jastadd/bcg/tinaMarking.ast b/src/main/jastadd/bcg/tinaMarking.ast
new file mode 100644
index 0000000000000000000000000000000000000000..e2671948df65c2c3b3eff9f2ea2716c053f55ea7
--- /dev/null
+++ b/src/main/jastadd/bcg/tinaMarking.ast
@@ -0,0 +1,7 @@
+TinaMarking ::= NetMarking*;
+
+NetMarking ::= <StateName:java.lang.Integer> PlaceMarking*;
+
+abstract PlaceMarking ::= <PlaceName:String>;
+MultMarking:PlaceMarking ::= <Multiplier:java.lang.Integer>;
+UnaryMarking:PlaceMarking;
\ No newline at end of file
diff --git a/src/main/jastadd/bcg/tinaMarking.jadd b/src/main/jastadd/bcg/tinaMarking.jadd
new file mode 100644
index 0000000000000000000000000000000000000000..0a7667610cda88b95e5470e8543bff85ef5861f9
--- /dev/null
+++ b/src/main/jastadd/bcg/tinaMarking.jadd
@@ -0,0 +1,14 @@
+aspect TinaMarkingNavigation {
+
+    syn boolean PlaceMarking.isMultMarking() = false;
+    eq MultMarking.isMultMarking() = true;
+
+    syn boolean PlaceMarking.isUnaryMarking() = false;
+    eq UnaryMarking.isUnaryMarking() = true;
+
+    syn MultMarking PlaceMarking.asMultMarking() = null;
+    eq MultMarking.asMultMarking() = this;
+
+    syn UnaryMarking PlaceMarking.asUnaryMarking() = null;
+    eq UnaryMarking.asUnaryMarking() = this;
+}
\ No newline at end of file
diff --git a/src/main/jastadd/bcg/tinaReachability.ast b/src/main/jastadd/bcg/tinaReachability.ast
new file mode 100644
index 0000000000000000000000000000000000000000..ea6c1175a959344466ee71a67da86e5974c06a33
--- /dev/null
+++ b/src/main/jastadd/bcg/tinaReachability.ast
@@ -0,0 +1,5 @@
+TinaReachability ::= NetReachability*;
+
+NetReachability ::= <TargetReachabilityStateName:java.lang.Integer> EnabledTransition*;
+
+EnabledTransition ::= <TransitionName:String> <TargetReachabilityState:java.lang.Integer>;
diff --git a/src/main/jastadd/flatter/transforms/TopicTransforms.jadd b/src/main/jastadd/flatter/transforms/TopicTransforms.jadd
index fd86c8e69dde64f9af768f13a5102f9e39649e00..726fa5c201f389bfc14423352312fa6c5e4938e8 100644
--- a/src/main/jastadd/flatter/transforms/TopicTransforms.jadd
+++ b/src/main/jastadd/flatter/transforms/TopicTransforms.jadd
@@ -7,87 +7,119 @@ aspect TopicTransforms {
         return this.getStaticTransitionInformation().isTopicTransitionInformation();
     }
 
-    syn Page DinerosTransition.transformTopicElement(boolean withoutInhibitorArc) {
-
-            System.out.println("Transforming topic transition: " + this.getId());
-            TopicTransitionInformation tti = this.getStaticTransitionInformation().asTopicTransitionInformation();
-
-            Page res = new Page();
-            res.setId(TemplateConstants.CHANNEL_TOPIC_PAGE_PREFIX + "-" + tti.getTopic());
-
-            // apply rule T1
-            DinerosPlace pTopic = PrimitiveTemplates.getDinerosPlace();
-            pTopic.setId(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
-
-            PlaceInformation pi = new PlaceInformation();
-            pi.setSubNet(PnmlConstants.CHANNEL);
-            pi.setNode(PnmlConstants.CHANNEL);
-            pTopic.setMutablePlaceInformation(pi);
-            pTopic.getInitialMarking().setText(0);
-            Name pName = new Name();
-            pName.setText(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
-            pTopic.setName(pName);
-            res.addObject(pTopic);
-
-            DinerosTransition tTopic = PrimitiveTemplates.getDinerosTransition();
-            tTopic.setId(TemplateConstants.CHANNEL_TOPIC_TRANSITION + "-" + tti.getTopic());
-
-            SignalTransitionInformation sti = new SignalTransitionInformation();
-            sti.setSubNet(PnmlConstants.CHANNEL);
-            sti.setNode(PnmlConstants.CHANNEL);
-            Name tName = new Name();
-            tName.setText(TemplateConstants.CHANNEL_TOPIC_TRANSITION + "-" + tti.getTopic());
-            tTopic.setName(tName);
-            res.addObject(tTopic);
-
-            TransformationUtils.createAndIncludeArc(res, pTopic.getId() + "-to-" + tTopic.getId(), pTopic, tTopic);
-
-            // apply rule T2
-           int i = 0;
-            for(PublisherPort pp : tti.getPublisherPorts()){
-                Map<String, Node> pubMap = new HashMap<>();
-                pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_REF + "-" + tti.getTopic() + "-" + i, petriNet().getPlaceById(pp.getPlaceId()));
-                pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + i, pTopic);
-                PetriNet pubNet = TopicTemplates.getTopicPublisherPetriNet(tti.getTopic() + "-" + i, pp.getLimit(), withoutInhibitorArc);
-                TransformationUtils.includeTemplateInstance(res, petriNet(), pubNet, pubMap, null);
-                i++;
-            }
-
-            // create node to port mapping as prep for T3 und T4
-            Map<String, List<SubscriberPort>> nodePortMap = new HashMap<>();
-            for(SubscriberPort sp : tti.getSubscriberPorts()){
-                String node = petriNet().getPlaceById(sp.getPlaceId()).asDinerosPlace().getStaticPlaceInformation().getNode();
-                if(nodePortMap.containsKey(node)){
-                    nodePortMap.get(node).add(sp);
-                } else {
-                    List<SubscriberPort> portList = new ArrayList<>();
-                    portList.add(sp);
-                    nodePortMap.put(node, portList);
+    syn Page DinerosTransition.transformTopicElement(Map<String, Integer> bounds, boolean withoutInhibitorArc, boolean withSimpleChannel) {
+
+                System.out.println("[TRANSFORM] Transforming topic transition: " + this.getId());
+                TopicTransitionInformation tti = this.getStaticTransitionInformation().asTopicTransitionInformation();
+
+                Page res = new Page();
+                res.setId(TemplateConstants.CHANNEL_TOPIC_PAGE_PREFIX + "-" + tti.getTopic());
+
+                // apply rule T1
+                DinerosPlace pTopic = PrimitiveTemplates.getDinerosPlace();
+                pTopic.setId(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
+
+                PlaceInformation pi = new PlaceInformation();
+                pi.setSubNet(PnmlConstants.CHANNEL);
+                pi.setNode(PnmlConstants.CHANNEL);
+                pTopic.setMutablePlaceInformation(pi);
+                pTopic.getInitialMarking().setText(0);
+                Name pName = new Name();
+                pName.setText(TemplateConstants.CHANNEL_TOPIC_PLACE + "-" + tti.getTopic());
+                pTopic.setName(pName);
+                res.addObject(pTopic);
+
+                DinerosTransition tTopic = PrimitiveTemplates.getDinerosTransition();
+                tTopic.setId(TemplateConstants.CHANNEL_TOPIC_TRANSITION + "-" + tti.getTopic());
+
+                SignalTransitionInformation sti = new SignalTransitionInformation();
+                sti.setSubNet(PnmlConstants.CHANNEL);
+                sti.setNode(PnmlConstants.CHANNEL);
+                Name tName = new Name();
+                tName.setText(TemplateConstants.CHANNEL_TOPIC_TRANSITION + "-" + tti.getTopic());
+                tTopic.setName(tName);
+                res.addObject(tTopic);
+
+                TransformationUtils.createAndIncludeArc(res, pTopic.getId() + "-to-" + tTopic.getId(), pTopic, tTopic);
+
+                // apply rule T2
+                int i = 0;
+                int boundNetCount = 0;
+                int boundSum = Integer.MAX_VALUE;
+                for(PublisherPort pp : tti.getPublisherPorts()){
+                    Map<String, Node> pubMap = new HashMap<>();
+                    pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_REF + "-" + tti.getTopic() + "-" + i, petriNet().getPlaceById(pp.getPlaceId()));
+                    pubMap.put(TemplateConstants.PLACE_TOPIC_PUBLISHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + i, pTopic);
+                    PetriNet pubNet = null;
+
+                    if(withSimpleChannel && bounds.containsKey(pp.getPlaceId())){
+                      System.out.println("[TRANSFORM] Using flat publisher template for: " + pp.getPlaceId());
+                      pubNet = TopicTemplates.getFlatTopicPublisherPetriNet(tti.getTopic() + "-" + i);
+                      boundNetCount++;
+
+                      if(boundSum == Integer.MAX_VALUE){
+                        boundSum = bounds.get(pp.getPlaceId());
+                      } else {
+                        boundSum += bounds.get(pp.getPlaceId());
+                      }
+                    } else {
+                      pubNet = TopicTemplates.getTopicPublisherPetriNet(tti.getTopic() + "-" + i, pp.getLimit(), withoutInhibitorArc);
+                    }
+
+                    TransformationUtils.includeTemplateInstance(res, petriNet(), pubNet, pubMap, null);
+                    i++;
                 }
-            }
-
-            // apply rule T3
-            int j = 0;
-           for(Map.Entry<String, List<SubscriberPort>> entry : nodePortMap.entrySet()){
-                Map<String, Node> dispatchMap = new HashMap<>();
-                dispatchMap.put(TemplateConstants.TRANSITION_TOPIC_DISPATCHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + j, tTopic);
-                // TODO: make capacity configurable
-                PetriNet dispatchNet = TopicTemplates.getTopicDispatcherPetriNet(tti.getTopic() + "-" + j, 16, withoutInhibitorArc);
-                Map<String, PnObject> addedObjects = TransformationUtils.includeTemplateInstance(res, petriNet(), dispatchNet, dispatchMap, null);
-
-                // apply rule T4
-                int k = 0;
+
+                // create node to port mapping as prep for T3 und T4
+                Map<String, List<SubscriberPort>> nodePortMap = new HashMap<>();
                 for(SubscriberPort sp : tti.getSubscriberPorts()){
-                    Map<String, Node> subMap = new HashMap<>();
-                    subMap.put(TemplateConstants.PLACE_TOPIC_CALLBACK_REF + "-" + tti.getTopic() + "-" + j + "-" + k, petriNet().getPlaceById(sp.getPlaceId()));
-                    subMap.put(TemplateConstants.TRANSITION_TOPIC_CALLBACK_INPUT_REF + "-" + tti.getTopic() + "-" + j + "-" + k,
-                            addedObjects.get(TemplateConstants.DISPATCHER_OUTPUT_TRANSITION + "-" + tti.getTopic() + "-" + j).asNode());
-                    PetriNet callbackNet = TopicTemplates.getTopicCallbackQueuePetriNet(tti.getTopic() + "-" + j + "-" + k, sp.getLimit(), withoutInhibitorArc);
-                    TransformationUtils.includeTemplateInstance(res, petriNet(), callbackNet, subMap, null);
-                    k++;
+                    String node = petriNet().getPlaceById(sp.getPlaceId()).asDinerosPlace().getStaticPlaceInformation().getNode();
+                    if(nodePortMap.containsKey(node)){
+                        nodePortMap.get(node).add(sp);
+                    } else {
+                        List<SubscriberPort> portList = new ArrayList<>();
+                        portList.add(sp);
+                        nodePortMap.put(node, portList);
+                    }
+                }
+
+                // apply rule T3
+               int j = 0;
+               for(Map.Entry<String, List<SubscriberPort>> entry : nodePortMap.entrySet()){
+                    Map<String, Node> dispatchMap = new HashMap<>();
+                    dispatchMap.put(TemplateConstants.TRANSITION_TOPIC_DISPATCHER_CHANNEL_REF + "-" + tti.getTopic() + "-" + j, tTopic);
+                    // TODO: make capacity configurable
+                    int dispatcherCapacity = 16;
+                    PetriNet dispatchNet = null;
+                    if(withSimpleChannel && boundSum <= dispatcherCapacity && boundNetCount == tti.getNumPublisherPort()){
+                      System.out.println("[TRANSFORM] Using flat dispatcher template for: " + entry.getKey());
+                      dispatchNet = TopicTemplates.getFlatTopicDispatcherPetriNet(tti.getTopic() + "-" + j);
+                    } else {
+                      dispatchNet = TopicTemplates.getTopicDispatcherPetriNet(tti.getTopic() + "-" + j, dispatcherCapacity, withoutInhibitorArc);
+                    }
+                    Map<String, PnObject> addedObjects = TransformationUtils.includeTemplateInstance(res, petriNet(), dispatchNet, dispatchMap, null);
+
+                    // apply rule T4
+                    int k = 0;
+                    for(SubscriberPort sp : tti.getSubscriberPorts()){
+                        PetriNet callbackNet = null;
+                        Map<String, Node> subMap = new HashMap<>();
+                        subMap.put(TemplateConstants.PLACE_TOPIC_CALLBACK_REF + "-" + tti.getTopic() + "-" + j + "-" + k, petriNet().getPlaceById(sp.getPlaceId()));
+                        subMap.put(TemplateConstants.TRANSITION_TOPIC_CALLBACK_INPUT_REF + "-" + tti.getTopic() + "-" + j + "-" + k,
+                                addedObjects.get(TemplateConstants.DISPATCHER_OUTPUT_TRANSITION + "-" + tti.getTopic() + "-" + j).asNode());
+                        if(withSimpleChannel && boundSum <= sp.getLimit() && boundNetCount == tti.getNumPublisherPort()){
+                          System.out.println("[TRANSFORM] Using flat callback template for: " + sp.getPlaceId());
+                          callbackNet = TopicTemplates.getFlatTopicCallbackPetriNet(tti.getTopic() + "-" + j + "-" + k);
+                        } else {
+                          callbackNet = TopicTemplates.getTopicCallbackQueuePetriNet(tti.getTopic() + "-" + j + "-" + k,
+                                  sp.getLimit(), withoutInhibitorArc);
+                        }
+
+                        TransformationUtils.includeTemplateInstance(res, petriNet(), callbackNet, subMap, null);
+                        k++;
+                    }
+                    j++;
                 }
-                j++;
-            }
-            return res;
+                return res;
     }
 }
\ No newline at end of file
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
index 8736cba06b7d1a0710b1e5eb3115ba5468aafb26..1a3dfcc65da017526470c2fe967cf565ca3e8c80 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/Main.java
@@ -1,5 +1,6 @@
 package de.tudresden.inf.st.pnml.flatter;
 
+import beaver.Parser;
 import de.tudresden.inf.st.pnml.base.constants.PnmlConstants;
 import de.tudresden.inf.st.pnml.flatter.config.ConfigReader;
 import de.tudresden.inf.st.pnml.flatter.graph.ServiceGraph;
@@ -22,23 +23,22 @@ import java.util.UUID;
 
 public class Main {
 
-    public static void main(String[] args) throws InvalidIDException, InterruptedException, IOException {
+    public static void main(String[] args) throws InvalidIDException, InterruptedException, IOException, Parser.Exception {
 
         String configPath = (args.length > 1) ? args[1] : null;
         String pnmlPath = (args.length > 0) ? args[0] : null;
-        //"/home/sebastian/git/dineros-public/dineros/pnml-relast-apps/" +
-               // "robotic-sorting/rpn-models/full-models/sorting-wf-synced-safe-sensor-grpn-sig.pnml";//
-                //"/home/sebastian/git/dineros-public/dineros/pnml-relast-apps/robotic-sorting/test-models/pubsub.pnml";
+        // "/home/sebastian/git/dineros-public/dineros/pnml-relast-apps/robotic-sorting/rpn-models/full-models" +
+        //                "/sorting-wf-synced-safe-sensor-grpn.pnml"; //
 
         boolean flagInhibitor = Boolean.parseBoolean(args[2]);
-        boolean flagSignal = Boolean.parseBoolean(args[3]);
-        boolean flagPurge = Boolean.parseBoolean(args[4]);
+        boolean flagSignal =  Boolean.parseBoolean(args[3]);
+        boolean flagPurge =  Boolean.parseBoolean(args[4]);
         doFlattening(configPath, pnmlPath, flagInhibitor, flagSignal, flagPurge);
 
     }
 
     private static void doFlattening(String configPath, String pnmlPath, boolean flagInhibitor, boolean flagSignal, boolean flagPurge)
-            throws InvalidIDException, IOException, InterruptedException {
+            throws InvalidIDException, IOException, InterruptedException, Parser.Exception {
 
         if (pnmlPath == null) {
             System.out.println("[ERROR] No model found on given input path.");
@@ -51,7 +51,11 @@ public class Main {
 
         // parse the global not flatted petri net
         PetriNet petriNet = PnmlParser.parsePnml(pnmlPath, false).get(0);
+        Map<String, Integer> bounds = null;
 
+        if(flagPurge) {
+            bounds = TransformationUtils.getPlaceToBoundMapping(pnmlPath, petriNet, TransformationUtils.getSourceNodePages(petriNet));
+        }
         // [STAGE 1] Resolve service prototype pages
         ServiceGraph serviceGraph = new ServiceGraph();
         serviceGraph.init(petriNet);
@@ -61,9 +65,10 @@ public class Main {
         petriNet.flushAttrAndCollectionCache();
 
         // [STAGE 2] Transform topic transitions
+
         for(DinerosTransition dt : petriNet.allDinerosTransitions()){
             if(dt.canTransformTopicTransition()){
-                Page topicTransformedPage = dt.transformTopicElement(flagInhibitor);
+                Page topicTransformedPage = dt.transformTopicElement(bounds, flagInhibitor, flagPurge);
                 for ( int i = 0; i < dt.ContainingPage().getNumObject(); i++ ){
                     if(dt.ContainingPage().getObject(i).getId().equals(dt.getId())){
                         dt.ContainingPage().setObject(topicTransformedPage, i);
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/analysis/TinaUtils.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/analysis/TinaUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..3923e146da4fd001db1286cefff4ae84412a3a23
--- /dev/null
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/analysis/TinaUtils.java
@@ -0,0 +1,113 @@
+package de.tudresden.inf.st.pnml.flatter.analysis;
+
+import beaver.Parser;
+import de.tudresden.inf.st.pnml.flatter.tina.TinaProxy;
+import de.tudresden.inf.st.pnml.jastadd.model.*;
+import de.tudresden.inf.st.pnml.jastadd.scanner.TinaMarkingScanner;
+import de.tudresden.inf.st.pnml.jastadd.scanner.TinaReachabilityScanner;
+import de.tudresden.inf.st.pnml.jastadd.tinaParser.TinaMarkingParser;
+import de.tudresden.inf.st.pnml.jastadd.tinaParser.TinaReachabilityParser;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.*;
+import java.util.UUID;
+
+public class TinaUtils {
+
+    public static int checkBoundednessOfPlace(String placeId, String inputPath, String pageId) throws IOException, Parser.Exception {
+
+        TinaProxy tinaProxy = new TinaProxy();
+        String tinaTargetPath = System.getProperty("user.dir") + "/temp/post/" + "tina-result-" + pageId + "-" + UUID.randomUUID().toString() + ".txt";
+
+        String[] config = {"-NET", "-stats"};
+        tinaProxy.analyzePetriNet(inputPath, tinaTargetPath, config);
+
+        // clip and parse result
+        StringBuilder clippedMarkingData = new StringBuilder();
+
+        BufferedReader br = new BufferedReader(new FileReader(new File(tinaTargetPath)));
+        String line;
+        while ((line = br.readLine()) != null) {
+            if (line.contains(":") && !line.contains("MARKINGS")
+                    && !line.contains("REACHABILITY")
+                    && !line.contains("unbounded places")) {
+                clippedMarkingData.append(line).append("\n");
+            }
+        }
+
+        clippedMarkingData = new StringBuilder(StringUtils.chomp(clippedMarkingData.toString()));
+
+        if (clippedMarkingData.length() == 0 ) {
+            System.err.println("Could not construct marking graph. Reason: no data.");
+            return -1;
+        }
+
+        // construct a graph
+        TinaMarking tm = parseTinaMarking(clippedMarkingData.toString());
+        // printTinaMarking(tm);
+
+        int maxMarking = -1;
+
+        for(NetMarking nm : tm.getNetMarkingList()) {
+            for (PlaceMarking pm : nm.getPlaceMarkingList()) {
+                if(pm.getPlaceName().equals(placeId)){
+                    if (pm.isMultMarking() && pm.asMultMarking().getMultiplier() > maxMarking) {
+                        maxMarking = pm.asMultMarking().getMultiplier();
+                    } else {
+                        if(maxMarking < 1){
+                            maxMarking = 1;
+                        }
+                    }
+                }
+            }
+        }
+
+        return maxMarking;
+    }
+
+    public static TinaMarking parseTinaMarking(String data) throws IOException, Parser.Exception {
+
+        StringReader input = new StringReader(data);
+
+        TinaMarkingScanner tms = new TinaMarkingScanner(input);
+        TinaMarkingParser tmp = new TinaMarkingParser();
+
+        return (TinaMarking) tmp.parse(tms);
+    }
+
+    public static TinaReachability parseTinaReachability(String data) throws IOException, Parser.Exception {
+
+        StringReader input = new StringReader(data);
+
+        TinaReachabilityScanner trs = new TinaReachabilityScanner(input);
+        TinaReachabilityParser trp = new TinaReachabilityParser();
+
+        return (TinaReachability) trp.parse(trs);
+    }
+
+    public static void printTinaMarking(TinaMarking tm){
+
+        for(NetMarking nm : tm.getNetMarkingList()){
+            System.out.println("NetMarking: " + nm.getStateName());
+            for(PlaceMarking pm : nm.getPlaceMarkingList()){
+                System.out.println("--- PlaceMarking: " + pm.getPlaceName());
+
+                if(pm.isMultMarking()){
+                    System.out.println("----- Multiplier: " + pm.asMultMarking().getMultiplier());
+                } else {
+                    System.out.println("----- Multiplier: 1");
+                }
+            }
+        }
+    }
+
+    public static void printTinaReachability(TinaReachability tr){
+
+        for(NetReachability nr : tr.getNetReachabilityList()){
+            System.out.println("NetReachability: " + nr.getTargetReachabilityStateName());
+            for(EnabledTransition et : nr.getEnabledTransitionList()){
+                System.out.println("--- EnabledTransition: " + et.getTransitionName() + "/" + et.getTargetReachabilityState());
+            }
+        }
+    }
+}
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java
index e885d1ccc3e9468b8ff58155b60e018c1a490ef3..4c931ab4e45f96509482918cbe2899e12402fb3e 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TopicTemplates.java
@@ -22,6 +22,30 @@ public class TopicTemplates extends PnmlTemplate {
         return templateNet;
     }
 
+    public static PetriNet getFlatTopicPublisherPetriNet(String idSuffix){
+
+        PetriNet templateNet = PnmlParser.parsePnml(homeDirectory +
+                TEMPLATE_PATH + "TopicPublisherTemplateFlat.pnml", false).get(0);
+        updateTemplateNaming(idSuffix, templateNet, TemplateConstants.PUBLISHER_TEMPLATE_PAGE);
+        return templateNet;
+    }
+
+    public static PetriNet getFlatTopicDispatcherPetriNet(String idSuffix){
+
+        PetriNet templateNet = PnmlParser.parsePnml(homeDirectory +
+                TEMPLATE_PATH + "TopicSubDispatcherTemplateFlat.pnml", false).get(0);
+        updateTemplateNaming(idSuffix, templateNet, TemplateConstants.DISPATCHER_TEMPLATE_PAGE);
+        return templateNet;
+    }
+
+    public static PetriNet getFlatTopicCallbackPetriNet(String idSuffix){
+
+        PetriNet templateNet = PnmlParser.parsePnml(homeDirectory +
+                TEMPLATE_PATH + "TopicSubCallbackQueueTemplateFlat.pnml", false).get(0);
+        updateTemplateNaming(idSuffix, templateNet, TemplateConstants.CALLBACK_QUEUE_TEMPLATE_PAGE);
+        return templateNet;
+    }
+
     private static PetriNet getTopicPublisherOptPetriNet(String idSuffix, int capacity){
 
         PetriNet templateNet = PnmlParser.parsePnml(homeDirectory +
@@ -89,6 +113,10 @@ public class TopicTemplates extends PnmlTemplate {
             }
         }
 
+        updateTemplateNaming(idSuffix, templateNet, templatePage);
+    }
+
+    private static void updateTemplateNaming(String idSuffix, PetriNet templateNet, String templatePage) {
         for (PnObject po : templateNet.allObjects()) {
             if (!po.getId().equals(templatePage)) {
                 updatePnObjectIdAndName(po, idSuffix);
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/AbstractTinaProxy.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/AbstractTinaProxy.java
index 6af55f980c5f96277e18fc6b94dc2a78f408807a..0152ba28be7190bbf4afd3d989f4c050d28f0e45 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/AbstractTinaProxy.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/AbstractTinaProxy.java
@@ -30,7 +30,7 @@ public abstract class AbstractTinaProxy {
             fileWriter.close();
 
             int exitVal = process.waitFor();
-            if (exitVal == 0) {
+            if (exitVal != 0) {
                 System.exit(0);
             }
 
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/KtzioProxy.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/KtzioProxy.java
index de95281f89824a8e34b7041cfd048ee64269b8d8..58b6a74671a9e084f170c265084809b5079588e4 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/KtzioProxy.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/KtzioProxy.java
@@ -18,7 +18,7 @@ public class KtzioProxy extends AbstractTinaProxy {
             }
 
             List<String> commandParts = new ArrayList<>();
-            if (homeDirectory.contains("pnml-relast-flatter")) {
+            if (homeDirectory.contains("pnml-relast-flattener")) {
 
                 commandParts.add(homeDirectory + "/libs/tina-3.7.0/bin/ktzio");
             } else {
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
index 602d3a05b13f252ff96e6f5f0fdd36578ee6bfe3..e202319fbdfdab386c0d5285784861f503c655ca 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/NdrioProxy.java
@@ -77,7 +77,7 @@ public class NdrioProxy extends AbstractTinaProxy{
 
         for(Arc a : petriNet.allArcs()){
             if(a.getNumToolspecific() > 0 && a.getType().equals(PnmlConstants.INHIBITOR_ARC)){
-                System.out.println("[FLATTER] Found inh arc: " + a.getId());
+                System.out.println("[FLATTENER] Found inh arc: " + a.getId());
                 inhibitorArcs.add(a);
             }
         }
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/TinaProxy.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/TinaProxy.java
index e15fd6abe666ed56219ad61e459deb9330c59864..b2485644eb6dd56cd3f28099c31b8b759dfb0983 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/TinaProxy.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/tina/TinaProxy.java
@@ -22,12 +22,12 @@ public class TinaProxy extends AbstractTinaProxy{
         if (!isWindows) {
 
             List<String> commandParts = new ArrayList<>();
-            if (homeDirectory.contains("pnml-relast-flatter")) {
+            if (homeDirectory.contains("pnml-relast-flattener")) {
 
                 commandParts.add(homeDirectory + "/libs/tina-3.7.0/bin/tina");
             } else {
 
-                commandParts.add(homeDirectory + "/pnml-relast-flatter/libs/tina-3.7.0/bin/tina");
+                commandParts.add(homeDirectory + "/pnml-relast-flattener/libs/tina-3.7.0/bin/tina");
             }
             commandParts.addAll(Arrays.asList(config));
             commandParts.add(inputPath);
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
index 06cd961cfdccaca55665f4fc4289408b0f87f289..07fea97a145b0ab6fde32b08bce10e6a6be1b0d9 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/transform/TransformationUtils.java
@@ -1,8 +1,13 @@
 package de.tudresden.inf.st.pnml.flatter.transform;
 
+import beaver.Parser;
+import de.tudresden.inf.st.pnml.flatter.analysis.TinaUtils;
 import de.tudresden.inf.st.pnml.flatter.graph.ServiceGraph;
+import de.tudresden.inf.st.pnml.flatter.tina.NdrioProxy;
 import de.tudresden.inf.st.pnml.jastadd.model.*;
+import fr.lip6.move.pnml.framework.utils.exception.InvalidIDException;
 
+import java.io.IOException;
 import java.util.*;
 
 public class TransformationUtils {
@@ -297,6 +302,26 @@ public class TransformationUtils {
         return null;
     }
 
+    public static PetriNet sliceOutPage(String pnmlPath, Page page){
+
+        PetriNet petriNet = PnmlParser.parsePnml(pnmlPath, false).get(0);
+        List<PnObject> objectsToDelete = new ArrayList<>();
+
+        for(PnObject po : petriNet.getPage(0).getObjects()){
+            if(!po.getId().equals(page.getId())){
+                objectsToDelete.add(po);
+            }
+        }
+
+        for(PnObject po : objectsToDelete){
+            System.out.println("Deleting: " + po.getId());
+            po.removeSelf();
+        }
+
+        petriNet.flushTreeCache();
+        return petriNet;
+    }
+
     public static List<Page> getSourceNodePages(PetriNet petriNet){
 
         List<Page> pages = new ArrayList<>();
@@ -351,6 +376,7 @@ public class TransformationUtils {
                     }
 
                     if(isPublisher && !isSubscriber && !isClient && !isServer){
+                        System.out.println("Found source page: " + page.getId());
                         pages.add(page);
                     }
 
@@ -361,6 +387,50 @@ public class TransformationUtils {
         return pages;
     }
 
+    public static Map<String, Integer> getPlaceToBoundMapping(String pnmlPath, PetriNet petriNet, List<Page> sourceNodePages) throws InvalidIDException, IOException, Parser.Exception {
+
+        Map<String, Integer> mapping = new HashMap<>();
+
+        for(Page sourcePage : sourceNodePages){
+
+            Set<String> pagePlaces = new HashSet<>();
+            placesInPage(sourcePage, pagePlaces);
+
+            for(String pid : pagePlaces){
+                for(DinerosTransition dt : petriNet.allDinerosTransitions()){
+                    if(dt.getStaticTransitionInformation().isTopicTransitionInformation()){
+                        for(PublisherPort pp : dt.getStaticTransitionInformation().asTopicTransitionInformation().getPublisherPorts()){
+                            if (pp.getPlaceId().equals(pid)){
+
+                                System.out.println("Computing bound for place: " + pid);
+                                String sliceId = UUID.randomUUID().toString();
+                                PetriNet pnSlice = TransformationUtils.sliceOutPage(pnmlPath, sourcePage);
+
+                                for(Page p : pnSlice.allPages()){
+                                    if(p.getId().equals("top")){
+                                        ReferenceFlatter.flatReferencesAndPages(pnSlice, p);
+                                        break;
+                                    }
+                                }
+
+                                String pnmlExportPath = PnmlExporter.serializeToPnmlFile(pnSlice, "-slice-" + sliceId);
+                                NdrioProxy ndrioProxy = new NdrioProxy();
+                                String ndrioTargetPath = System.getProperty("user.dir") + "/temp/net/" + sliceId + ".net";
+                                ndrioProxy.pnml2net(pnmlExportPath, ndrioTargetPath);
+
+                                int bound = TinaUtils.checkBoundednessOfPlace(pid, ndrioTargetPath, sourcePage.getId());
+                                System.out.println("Adding new bound mapping: " + pid + " >> " + bound);
+                                mapping.put(pid, bound);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return mapping;
+    }
+
     private static void placesInPage(Page page, Set<String> places){
 
         for(PnObject po : page.getObjects()){
diff --git a/src/main/resources/templates/TopicPublisherTemplateFlat.pnml b/src/main/resources/templates/TopicPublisherTemplateFlat.pnml
new file mode 100644
index 0000000000000000000000000000000000000000..acd4ccae7a7a4f5ba8869c04a645f9b76860f4ef
--- /dev/null
+++ b/src/main/resources/templates/TopicPublisherTemplateFlat.pnml
@@ -0,0 +1,114 @@
+<pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+        <name>
+            <text>DinerosTemplate</text>
+        </name>
+        <page id="DinerosTemplatePage">
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referencePlace id="PublisherPlaceRef" ref="PublisherConnectorPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                </toolspecific>
+                <name>
+                    <text>PublisherPlaceRef</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="20" y="20"/>
+                </graphics>
+            </referencePlace>
+
+            <arc id="arc-7" source="PublisherPlaceRef" target="PublisherInputTransition">
+            </arc>
+
+            <referencePlace id="PublisherChannelPlaceRef" ref="PublisherConnectorPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                </toolspecific>
+                <name>
+                    <text>PublisherChannelPlaceRef</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="20" y="20"/>
+                </graphics>
+            </referencePlace>
+
+            <arc id="arc-8" source="PublisherOutputTransition" target="PublisherChannelPlaceRef">
+            </arc>
+
+            <place id="PublisherConnectorPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discretePlaceType</type>
+                    <outputsignalbindings>
+                    </outputsignalbindings>
+                </toolspecific>
+                <name>
+                    <text>PublisherConnectorPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <initialMarking>
+                    <text>0</text>
+                </initialMarking>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </place>
+
+            <transition id="PublisherInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discreteTransitionType</type>
+                    <inputsignalbindings>
+                    </inputsignalbindings>
+                    <inputsignalclause></inputsignalclause>
+                </toolspecific>
+                <name>
+                    <text>PublisherInputTransition</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </transition>
+            <transition id="PublisherOutputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discreteTransitionType</type>
+                    <inputsignalbindings>
+                    </inputsignalbindings>
+                    <inputsignalclause></inputsignalclause>
+                </toolspecific>
+                <name>
+                    <text>PublisherOutputTransition</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </transition>
+
+            <arc id="pub-arc-2" source="PublisherInputTransition" target="PublisherConnectorPlace">
+            </arc>
+            <arc id="pub-arc-3" source="PublisherConnectorPlace" target="PublisherOutputTransition">
+            </arc>
+        </page>
+    </net>
+</pnml>
diff --git a/src/main/resources/templates/TopicSubCallbackQueueTemplateFlat.pnml b/src/main/resources/templates/TopicSubCallbackQueueTemplateFlat.pnml
new file mode 100644
index 0000000000000000000000000000000000000000..25c087f2a6ecdf378939f73a947f2f4f0327979e
--- /dev/null
+++ b/src/main/resources/templates/TopicSubCallbackQueueTemplateFlat.pnml
@@ -0,0 +1,130 @@
+<pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+        <name>
+            <text>DinerosTemplate</text>
+        </name>
+        <page id="DinerosTemplatePage">
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referenceTransition id="CallbackInputRefTransition" ref="CallbackInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>channel</location>
+                    <subnet>channel</subnet>
+                </toolspecific>
+            </referenceTransition>
+
+            <arc id="arc-8" source="CallbackInputRefTransition" target="CallbackInputPlace">
+            </arc>
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referencePlace id="CallbackRefPlace" ref="CallbackInputPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                </toolspecific>
+                <name>
+                    <text>CallbackRefPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="20" y="20"/>
+                </graphics>
+            </referencePlace>
+
+            <arc id="arc-9" source="CallbackOutputTransition" target="CallbackRefPlace">
+            </arc>
+
+            <place id="CallbackConnectorPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discretePlaceType</type>
+                    <outputsignalbindings>
+                    </outputsignalbindings>
+                </toolspecific>
+                <name>
+                    <text>CallbackConnectorPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <initialMarking>
+                    <text>0</text>
+                </initialMarking>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </place>
+
+            <place id="CallbackInputPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discretePlaceType</type>
+                    <outputsignalbindings>
+                    </outputsignalbindings>
+                </toolspecific>
+                <name>
+                    <text>CallbackInputPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <initialMarking>
+                    <text>0</text>
+                </initialMarking>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </place>
+
+            <transition id="CallbackInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discreteTransitionType</type>
+                    <inputsignalbindings>
+                    </inputsignalbindings>
+                    <inputsignalclause></inputsignalclause>
+                </toolspecific>
+                <name>
+                    <text>CallbackInputTransition</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </transition>
+            <transition id="CallbackOutputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discreteTransitionType</type>
+                    <inputsignalbindings>
+                    </inputsignalbindings>
+                    <inputsignalclause></inputsignalclause>
+                </toolspecific>
+                <name>
+                    <text>CallbackOutputTransition</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </transition>
+
+            <arc id="callback-arc-2" source="CallbackInputTransition" target="CallbackConnectorPlace">
+            </arc>
+            <arc id="callback-arc-3" source="CallbackConnectorPlace" target="CallbackOutputTransition">
+            </arc>
+            <arc id="callback-arc-6" source="CallbackInputPlace" target="CallbackInputTransition">
+            </arc>
+        </page>
+    </net>
+</pnml>
diff --git a/src/main/resources/templates/TopicSubDispatcherTemplateFlat.pnml b/src/main/resources/templates/TopicSubDispatcherTemplateFlat.pnml
new file mode 100644
index 0000000000000000000000000000000000000000..939a92a81c06bd3b4042d4477d6bc7973b838370
--- /dev/null
+++ b/src/main/resources/templates/TopicSubDispatcherTemplateFlat.pnml
@@ -0,0 +1,102 @@
+<pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
+    <net id="DinerosTemplate" type ="http://www.pnml.org/version-2009/grammar/ptnet">
+        <name>
+            <text>DinerosTemplate</text>
+        </name>
+
+        <page id="DinerosTemplatePage">
+
+            <!-- the reference target is just used here, because pnml does not allow dangling refs -->
+            <referenceTransition id="DispatcherChannelTransitionRef" ref="DispatcherInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>channel</location>
+                    <subnet>channel</subnet>
+                </toolspecific>
+            </referenceTransition>
+
+            <place id="DispatcherConnectorPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discretePlaceType</type>
+                </toolspecific>
+                <name>
+                    <text>DispatcherConnectorPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <initialMarking>
+                    <text>0</text>
+                </initialMarking>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </place>
+
+            <place id="DispatcherInputPlace">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discretePlaceType</type>
+                </toolspecific>
+                <name>
+                    <text>DispatcherInputPlace</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <initialMarking>
+                    <text>0</text>
+                </initialMarking>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </place>
+
+            <transition id="DispatcherInputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discreteTransitionType</type>
+                    <inputsignalclause></inputsignalclause>
+                </toolspecific>
+                <name>
+                    <text>DispatcherInputTransition</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </transition>
+            <transition id="DispatcherOutputTransition">
+                <toolspecific tool="de.tudresden.inf.st.pnml.distributedPN" version="0.1">
+                    <location>none</location>
+                    <subnet>none</subnet>
+                    <type>discreteTransitionType</type>
+                    <inputsignalclause></inputsignalclause>
+                </toolspecific>
+                <name>
+                    <text>DispatcherOutputTransition</text>
+                    <graphics>
+                        <offset x="0" y="0" />
+                    </graphics>
+                </name>
+                <graphics>
+                    <position x="0" y="0"/>
+                </graphics>
+            </transition>
+
+            <arc id="dis-arc-2" source="DispatcherInputTransition" target="DispatcherConnectorPlace">
+            </arc>
+            <arc id="dis-arc-3" source="DispatcherConnectorPlace" target="DispatcherOutputTransition">
+            </arc>
+            <arc id="dis-arc-6" source="DispatcherInputPlace" target="DispatcherInputTransition">
+            </arc>
+            <arc id="dis-arc-8" source="DispatcherChannelTransitionRef" target="DispatcherInputPlace">
+            </arc>
+        </page>
+    </net>
+</pnml>