diff --git a/build.gradle b/build.gradle
index 6ab95363d9a485918f21af301c6fb43d9db02f39..c33d01327163fdbf5c108e8c8022326e5f54778e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -108,6 +108,25 @@ jar {
 
 }
 
+task fatJar(type: Jar) {
+    group = "build"
+
+    archiveAppendix = "fatjar"
+    from sourceSets.main.output
+    from sourceSets.main.allSource
+    from {
+        configurations.runtimeClasspath.collect {it.isDirectory() ? it : zipTree(it) }
+    }
+
+    manifest.attributes "Main-Class": "de.tudresden.inf.st.pnml.flatter.Main"
+
+    exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
+
+    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+
+    archiveBaseName = 'pnml-relast-flattener'
+}
+
 // Generated files
 def ecoreFile = './src/main/resources/placeTransition.ecore'
 def ecoreRelastAspect = './src/gen/jastadd/pnml/placeTransition.ecore.jadd'
diff --git a/src/main/jastadd/flatter/transforms/SignalTransforms.jadd b/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
index e478c03c82de3fa116e50e13652f1775a02633e6..90bb155f22c88198976c9546b3906bd384cc1aa2 100644
--- a/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
+++ b/src/main/jastadd/flatter/transforms/SignalTransforms.jadd
@@ -1,5 +1,32 @@
 aspect SignalTransforms {
 
+    syn PetriNet PetriNet.transformSingleUseSignals(){
+
+        Map<String, String> signalDefs = this.getInputSignalDefinition();
+        Map<String, List<DinerosTransition>> signalMapping = TransformationUtils.getSignalToUsageMapping(this);
+
+        for (Map.Entry<String, String> entry : signalDefs.entrySet()) {
+            if (signalMapping.get(entry.getKey()).size() == 1) {
+
+                Transition toTrue = this.getTransitionById(TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_TRUE + "-" + entry.getKey());
+                Transition toFalse = this.getTransitionById(TemplateConstants.INPUT_SIGNAL_TRANSITION_TO_FALSE + "-" + entry.getKey());
+
+                for (Place p : signalMapping.get(entry.getKey()).get(0).incomingPlaces()) {
+                    if(!p.getId().startsWith(TemplateConstants.PD_PLACE_PREFIX)){
+                        System.out.println("[SignalPostProcessing] Creating new linkage between "+p.getId()+" and "+toTrue.getId());
+                        TransformationUtils.createAndIncludeArc(this.getPage(0),p.getId()+"-to-"+toTrue.getId(),p,toTrue);
+                        TransformationUtils.createAndIncludeArc(this.getPage(0),toTrue.getId()+"-to-"+p.getId(),toTrue,p);
+
+                        System.out.println("[SignalPostProcessing] Creating new linkage between "+p.getId()+" and "+toFalse.getId());
+                        TransformationUtils.createAndIncludeArc(this.getPage(0),p.getId()+"-to-"+toFalse.getId(),p,toFalse);
+                        TransformationUtils.createAndIncludeArc(this.getPage(0),toFalse.getId()+"-to-"+p.getId(),toFalse,p);
+                    }
+                }
+            }
+        }
+        return this;
+    }
+
     // apply rule I4
     syn PetriNet PetriNet.transformSignalElements(Page signalValuePage){
 
@@ -10,6 +37,7 @@ aspect SignalTransforms {
 
             PetriNet pubNet = SignalTemplates.getInputSignalTemplate(entry.getKey());
 
+
             if(Boolean.parseBoolean(entry.getValue())){
                 pubNet.getPlaceById(TemplateConstants.INPUT_SIGNAL_PLACE_TRUE + "-" + entry.getKey()).getInitialMarking().setText(1);
                 pubNet.getPlaceById(TemplateConstants.INPUT_SIGNAL_PLACE_FALSE + "-" + entry.getKey()).getInitialMarking().setText(0);
@@ -32,10 +60,10 @@ aspect SignalTransforms {
         int i = 0;
         for(Disjunction dj : this.getDisjunctions()){
             DinerosPlace pdi = PrimitiveTemplates.getDinerosPlace();
-            pdi.setId("PD-" + i + "-" + t.getId());
+            pdi.setId(TemplateConstants.PD_PLACE_PREFIX + i + "-" + t.getId());
             pdi.getName().setText(pdi.getId());
             RefTransition rt = PrimitiveTemplates.getReferenceTransition(t);
-            rt.setId("PD-REF-" + i + "-" + t.getId());
+            rt.setId(TemplateConstants.PD_PLACE_PREFIX + "REF-" + i + "-" + t.getId());
             rt.setRef(t);
             res.addObject(pdi);
             res.addObject(rt);
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 f7bfe86649450deb3a0dea3bafc096e604019fb9..7878f1948429726f6a92b439583732dec6cac9c1 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
@@ -28,8 +28,13 @@ public class Main {
         String pnmlPath = (args.length > 0) ? args[0] : null;
                 //"/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-sig.pnml";
-        boolean flagInhibitor = args.length > 2 && Boolean.parseBoolean(args[2]);
+        boolean flagInhibitor = Boolean.parseBoolean(args[2]);
+        boolean flagSignal =  Boolean.parseBoolean(args[3]);
+        doFlattening(configPath, pnmlPath, flagInhibitor, flagSignal);
 
+    }
+
+    private static void doFlattening(String configPath, String pnmlPath, boolean flagInhibitor, boolean flagSignal) throws InvalidIDException, IOException, InterruptedException {
         if (pnmlPath == null) {
             System.out.println("[ERROR] No model found on given input path.");
             return;
@@ -116,7 +121,13 @@ public class Main {
             }
         }
 
-        // [STAGE 7] export flatted net to pnml
+        // [STAGE 7] Postprocessing
+        System.out.println("[FLATTENER] Running postprocessing.");
+        if(flagSignal) {
+            petriNet.transformSingleUseSignals();
+        }
+
+        // [STAGE 8] export flatted net to pnml
         System.out.println("[FLATTENER] Exporting to pnml.");
         String exportId = UUID.randomUUID().toString();
         String pnmlExportPath = PnmlExporter.serializeToPnmlFile(petriNet, "-flatted-" + exportId);
@@ -134,7 +145,7 @@ public class Main {
         ndrioProxy.pnml2net(pnmlExportPath, ndrioTargetPath);
         ndrioProxy.includeInhibitorArcs(petriNet, ndrioTargetPath, inhibitorTargetPath);
 
-        // [STAGE 8] Analyze
+        // [STAGE 9] Analyze
         // read config for analyzer from file
         if(configPath != null && !configPath.equals("") && !configPath.equals("-nc")) {
             ConfigReader cr = new ConfigReader(configPath);
@@ -164,7 +175,6 @@ public class Main {
         }
 
         System.out.println("[FLATTENER] Finished.");
-
     }
 
     public static void printNet(PetriNet petriNet, boolean withArcs, boolean withToolSpecifics) {
diff --git a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
index ec3a73d6fbf7f0512941c4a11caae2539b8d33d9..6444252dd5c9eecc5a0ef678ed750129d4c338ed 100644
--- a/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
+++ b/src/main/java/de/tudresden/inf/st/pnml/flatter/template/TemplateConstants.java
@@ -48,6 +48,7 @@ public final class TemplateConstants {
     public static final String INPUT_SIGNAL_TRANSITION_TO_TRUE = "InputSignalToTrueTransition";
     public static final String INPUT_SIGNAL_TRANSITION_TO_FALSE = "InputSignalToFalseTransition";
     public static final String INPUT_SIGNAL_PAGE_PREFIX = "InputSignalPage";
+    public static final String PD_PLACE_PREFIX = "PD-";
 
     // services
     // S3
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 c26f21b403d35dec7c2984c83754d2dea56c7fa4..48ff661fcdd18fc163ed6b5a8902e22a18cf5947 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
@@ -3,13 +3,53 @@ package de.tudresden.inf.st.pnml.flatter.transform;
 import de.tudresden.inf.st.pnml.flatter.graph.ServiceGraph;
 import de.tudresden.inf.st.pnml.jastadd.model.*;
 
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 public class TransformationUtils {
 
+
+    /**
+     *
+     * @param petriNet before signals are flatted
+     * @return mapping from signal IDs to transitions using it
+     */
+    public static Map<java.lang.String, List<DinerosTransition>> getSignalToUsageMapping(PetriNet petriNet){
+
+        Map<java.lang.String, List<DinerosTransition>> mapping = new HashMap<>();
+        Map<java.lang.String, java.lang.String> signalDefinitions = petriNet.getInputSignalDefinition();
+
+        // initialize the mapping for all signals
+        for (Map.Entry<java.lang.String, java.lang.String> signalDef : signalDefinitions.entrySet()) {
+            mapping.put(signalDef.getKey(), new ArrayList<>());
+        }
+
+        // insert signal using transitions into the mapping
+        for (Map.Entry<java.lang.String, java.lang.String> signalDef : signalDefinitions.entrySet()) {
+            for(DinerosTransition dt : petriNet.allDinerosTransitions()){
+                if(dt.getStaticTransitionInformation().isSignalTransitionInformation()){
+                    if(clauseHasSignal(dt.getStaticTransitionInformation().
+                            asSignalTransitionInformation().getClause(), signalDef.getKey())){
+                        mapping.get(signalDef.getKey()).add(dt);
+                    }
+                }
+            }
+        }
+        return mapping;
+    }
+
+    private static boolean clauseHasSignal(InputSignalClause clause, String signalId){
+
+        for(Disjunction d : clause.getDisjunctions()){
+            for(Literal l : d.getLiterals()){
+                if(l.getName().equals(signalId)){
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
     public static Arc createArc(String id, Node s, Node t) {
 
         Arc a = new Arc();