diff --git a/src/storm-dft-cli/storm-dyftee.cpp b/src/storm-dft-cli/storm-dyftee.cpp
index 6ed375d79..f246438fe 100644
--- a/src/storm-dft-cli/storm-dyftee.cpp
+++ b/src/storm-dft-cli/storm-dyftee.cpp
@@ -3,7 +3,8 @@
 #include "storm/utility/storm.h"
 #include "storm/cli/cli.h"
 #include "storm/exceptions/BaseException.h"
-#include "storm/utility/macros.h"
+
+#include "storm/logic/Formula.h"
 
 #include "storm/settings/modules/GeneralSettings.h"
 #include "storm/settings/modules/CoreSettings.h"
@@ -14,17 +15,22 @@
 #include "storm/settings/modules/EliminationSettings.h"
 
 #include "storm-dft/parser/DFTGalileoParser.h"
+#include "storm-dft/parser/DFTJsonParser.h"
 #include "storm-dft/modelchecker/dft/DFTModelChecker.h"
 #include "storm-dft/modelchecker/dft/DFTASFChecker.h"
+#include "storm-dft/transformations/DftToGspnTransformator.h"
+
 
 #include "storm-dft/settings/modules/DFTSettings.h"
 
 #include "storm-gspn/storage/gspn/GSPN.h"
+#include "storm-gspn/storm-gspn.h"
 #include "storm/settings/modules/GSPNSettings.h"
 #include "storm/settings/modules/GSPNExportSettings.h"
 
 
 #include <boost/lexical_cast.hpp>
+#include <memory>
 
 /*!
  * Load DFT from filename, build corresponding Model and check against given property.
@@ -68,17 +74,6 @@ void analyzeWithSMT(std::string filename) {
     //std::cout << "SMT result: " << sat << std::endl;
 }
 
-/*!
- * Load DFT from filename and transform into a GSPN.
- *
- * @param filename Path to DFT file in Galileo format.
- *
- */
-template <typename ValueType>
-storm::gspn::GSPN transformDFT(std::string filename) {
-    storm::parser::DFTGalileoParser<ValueType> parser;
-    storm::storage::DFT<ValueType> dft = parser.parseDFT(filename);
-}
 
 /*!
  * Initialize the settings manager.
@@ -107,6 +102,7 @@ void initializeSettings() {
     // For translation into JANI via GSPN.
     storm::settings::addModule<storm::settings::modules::GSPNSettings>();
     storm::settings::addModule<storm::settings::modules::GSPNExportSettings>();
+    storm::settings::addModule<storm::settings::modules::JaniExportSettings>();
 }
 
 /*!
@@ -129,14 +125,48 @@ int main(const int argc, const char** argv) {
         
         storm::settings::modules::DFTSettings const& dftSettings = storm::settings::getModule<storm::settings::modules::DFTSettings>();
         storm::settings::modules::GeneralSettings const& generalSettings = storm::settings::getModule<storm::settings::modules::GeneralSettings>();
-        if (!dftSettings.isDftFileSet()) {
+        if (!dftSettings.isDftFileSet() && !dftSettings.isDftJsonFileSet()) {
             STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "No input model.");
         }
 
+        
         if (dftSettings.isTransformToGspn()) {
-            // For now we only transform the DFT to a GSPN and then exit
-            transformDFT<double>(dftSettings.getDftFilename());
+            std::shared_ptr<storm::storage::DFT<double>> dft;
+            if (dftSettings.isDftJsonFileSet()) {
+                storm::parser::DFTJsonParser<double> parser;
+                dft = std::make_shared<storm::storage::DFT<double>>(parser.parseJson(dftSettings.getDftJsonFilename()));
+            } else {
+                storm::parser::DFTGalileoParser<double> parser(true, false);
+                dft = std::make_shared<storm::storage::DFT<double>>(parser.parseDFT(dftSettings.getDftFilename()));
+            }
+            storm::transformations::dft::DftToGspnTransformator<double> gspnTransformator(*dft);
+            gspnTransformator.transform();
+            storm::gspn::GSPN* gspn = gspnTransformator.obtainGSPN();
+            uint64_t toplevelFailedPlace = gspnTransformator.toplevelFailedPlaceId();
+            
+            storm::handleGSPNExportSettings(*gspn);
+            
+            std::shared_ptr<storm::expressions::ExpressionManager> exprManager(new storm::expressions::ExpressionManager());
+            storm::builder::JaniGSPNBuilder builder(*gspn, exprManager);
+            storm::jani::Model* model =  builder.build();
+            storm::jani::Variable const& topfailedVar = builder.getPlaceVariable(toplevelFailedPlace);
+            
+
+            storm::expressions::Expression targetExpression = exprManager->integer(1) == topfailedVar.getExpressionVariable().getExpression();
+            auto evtlFormula = std::make_shared<storm::logic::AtomicExpressionFormula>(targetExpression);
+            auto tbFormula = std::make_shared<storm::logic::BoundedUntilFormula>(std::make_shared<storm::logic::BooleanLiteralFormula>(true), evtlFormula, 0.0, 10.0);
+            auto tbUntil = std::make_shared<storm::logic::ProbabilityOperatorFormula>(tbFormula);
+            
+            auto evFormula = std::make_shared<storm::logic::EventuallyFormula>(evtlFormula, storm::logic::FormulaContext::Time);
+            auto rewFormula = std::make_shared<storm::logic::TimeOperatorFormula>(evFormula, storm::logic::OperatorInformation(), storm::logic::RewardMeasureType::Expectation);
+            
+            storm::settings::modules::JaniExportSettings const& janiSettings = storm::settings::getModule<storm::settings::modules::JaniExportSettings>();
+            if (janiSettings.isJaniFileSet()) {
+                storm::exportJaniModel(*model, {storm::jani::Property("time-bounded", tbUntil), storm::jani::Property("mttf", rewFormula)}, janiSettings.getJaniFilename());
+            }
             
+            delete model;
+            delete gspn;
             storm::utility::cleanUp();
             return 0;
         }
diff --git a/src/storm-dft/CMakeLists.txt b/src/storm-dft/CMakeLists.txt
index df0c067e0..10d9b8508 100644
--- a/src/storm-dft/CMakeLists.txt
+++ b/src/storm-dft/CMakeLists.txt
@@ -10,4 +10,4 @@ file(GLOB_RECURSE STORM_DFT_HEADERS ${PROJECT_SOURCE_DIR}/src/storm-dft/*/*.h)
 
 # Create storm-pgcl.
 add_library(storm-dft SHARED ${STORM_DFT_SOURCES} ${STORM_DFT_HEADERS})
-target_link_libraries(storm-dft storm ${STORM_DFT_LINK_LIBRARIES})
+target_link_libraries(storm-dft storm storm-gspn ${STORM_DFT_LINK_LIBRARIES})
diff --git a/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp b/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp
index ae4144ee7..2de46e599 100644
--- a/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp
+++ b/src/storm-dft/modelchecker/dft/DFTModelChecker.cpp
@@ -8,6 +8,7 @@
 #include "storm-dft/storage/dft/DFTIsomorphism.h"
 #include "storm-dft/settings/modules/DFTSettings.h"
 
+
 namespace storm {
     namespace modelchecker {
 
diff --git a/src/storm-dft/parser/DFTGalileoParser.cpp b/src/storm-dft/parser/DFTGalileoParser.cpp
index 776eb64d9..f872f4526 100644
--- a/src/storm-dft/parser/DFTGalileoParser.cpp
+++ b/src/storm-dft/parser/DFTGalileoParser.cpp
@@ -4,6 +4,7 @@
 #include <fstream>
 #include <boost/algorithm/string.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/replace.hpp>
 #include "storm/storage/expressions/ExpressionManager.h"
 #include "storm/exceptions/NotImplementedException.h"
 #include "storm/exceptions/FileIoException.h"
@@ -34,6 +35,11 @@ namespace storm {
                 return name.substr(firstQuots+1,secondQuots-1);
             }
         }
+        
+        template<typename ValueType>
+        std::string DFTGalileoParser<ValueType>::parseNodeIdentifier(std::string const& name) {
+            return boost::replace_all_copy(name, "'", "__prime__");
+        }
 
         template<typename ValueType>
         void DFTGalileoParser<ValueType>::readFile(const std::string& filename) {
@@ -84,11 +90,11 @@ namespace storm {
                 } else {
                     std::vector<std::string> tokens;
                     boost::split(tokens, line, boost::is_any_of(" "));
-                    std::string name(stripQuotsFromName(tokens[0]));
+                    std::string name(parseNodeIdentifier(stripQuotsFromName(tokens[0])));
 
                     std::vector<std::string> childNames;
                     for(unsigned i = 2; i < tokens.size(); ++i) {
-                        childNames.push_back(stripQuotsFromName(tokens[i]));
+                        childNames.push_back(parseNodeIdentifier(stripQuotsFromName(tokens[i])));
                     }
                     if(tokens[1] == "and") {
                         success = builder.addAndElement(name, childNames);
@@ -104,8 +110,16 @@ namespace storm {
                         success = builder.addVotElement(name, threshold, childNames);
                     } else if (tokens[1] == "pand") {
                         success = builder.addPandElement(name, childNames);
+                    } else if (tokens[1] == "pand-inc") {
+                        success = builder.addPandElement(name, childNames, true);
+                    } else if (tokens[1] == "pand-ex") {
+                        success = builder.addPandElement(name, childNames, false);
                     } else if (tokens[1] == "por") {
                         success = builder.addPorElement(name, childNames);
+                    } else if (tokens[1] == "por-ex") {
+                        success = builder.addPorElement(name, childNames, false);
+                    } else if (tokens[1] == "por-inc") {
+                        success = builder.addPorElement(name, childNames, true);
                     } else if (tokens[1] == "wsp" || tokens[1] == "csp") {
                         success = builder.addSpareElement(name, childNames);
                     } else if (tokens[1] == "seq") {
diff --git a/src/storm-dft/parser/DFTGalileoParser.h b/src/storm-dft/parser/DFTGalileoParser.h
index 3f19683ff..c2a35bc50 100644
--- a/src/storm-dft/parser/DFTGalileoParser.h
+++ b/src/storm-dft/parser/DFTGalileoParser.h
@@ -26,7 +26,7 @@ namespace storm {
             std::unordered_map<std::string, storm::expressions::Expression> identifierMapping;
 
         public:
-            DFTGalileoParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) {
+            DFTGalileoParser(bool defaultInclusive = true, bool binaryDependencies = true) : builder(defaultInclusive, binaryDependencies), manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) {
             }
 
             storm::storage::DFT<ValueType> parseDFT(std::string const& filename);
@@ -35,8 +35,11 @@ namespace storm {
             void readFile(std::string const& filename);
 
             std::string stripQuotsFromName(std::string const& name);
+            std::string parseNodeIdentifier(std::string const& name);
 
             ValueType parseRationalExpression(std::string const& expr);
+            
+            bool defaultInclusive;
         };
     }
 }
diff --git a/src/storm-dft/parser/DFTJsonParser.cpp b/src/storm-dft/parser/DFTJsonParser.cpp
new file mode 100644
index 000000000..9a5c5d047
--- /dev/null
+++ b/src/storm-dft/parser/DFTJsonParser.cpp
@@ -0,0 +1,167 @@
+#include "DFTJsonParser.h"
+
+#include <iostream>
+#include <fstream>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include "storm/storage/expressions/ExpressionManager.h"
+#include "storm/exceptions/NotImplementedException.h"
+#include "storm/exceptions/FileIoException.h"
+#include "storm/exceptions/NotSupportedException.h"
+#include "storm/utility/macros.h"
+
+namespace storm {
+    namespace parser {
+
+        template<typename ValueType>
+        storm::storage::DFT<ValueType> DFTJsonParser<ValueType>::parseJson(const std::string& filename) {
+            readFile(filename);
+            storm::storage::DFT<ValueType> dft = builder.build();
+            STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString());
+            STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString());
+            return dft;
+        }
+
+        template<typename ValueType>
+        std::string DFTJsonParser<ValueType>::stripQuotsFromName(std::string const& name) {
+            size_t firstQuots = name.find("\"");
+            size_t secondQuots = name.find("\"", firstQuots+1);
+            
+            if(firstQuots == std::string::npos) {
+                return name;
+            } else {
+                STORM_LOG_THROW(secondQuots != std::string::npos, storm::exceptions::FileIoException, "No ending quotation mark found in " << name);
+                return name.substr(firstQuots+1,secondQuots-1);
+            }
+        }
+
+        template<typename ValueType>
+        std::string DFTJsonParser<ValueType>::getString(json const& structure, std::string const& errorInfo) {
+            STORM_LOG_THROW(structure.is_string(), storm::exceptions::FileIoException, "Expected a string in " << errorInfo << ", got '" << structure.dump() << "'");
+            return structure.front();
+        }
+
+        template<typename ValueType>
+        std::string DFTJsonParser<ValueType>::parseNodeIdentifier(std::string const& name) {
+            return boost::replace_all_copy(name, "'", "__prime__");
+        }
+
+        template<typename ValueType>
+        void DFTJsonParser<ValueType>::readFile(const std::string& filename) {
+            STORM_LOG_DEBUG("Parsing from JSON");
+
+            std::ifstream file;
+            file.exceptions ( std::ifstream::failbit );
+            try {
+                file.open(filename);
+            }
+            catch (std::ifstream::failure e) {
+                STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Exception during file opening on " << filename << ".");
+                return;
+            }
+            file.exceptions( std::ifstream::goodbit );
+
+            json parsedJson;
+            parsedJson << file;
+            file.close();
+
+            // Start by building mapping from ids to names
+            std::map<std::string, std::string> nameMapping;
+            for (auto& element: parsedJson) {
+                if (element.at("classes") != "") {
+                    json data = element.at("data");
+                    std::string id = data.at("id");
+                    std::string name = data.at("name");
+                    nameMapping[id] = name;
+                }
+            }
+
+            // TODO: avoid hack
+            std::string toplevelId = nameMapping["1"];
+
+            for (auto& element : parsedJson) {
+                bool success = true;
+                if (element.at("classes") == "") {
+                    continue;
+                }
+                json data = element.at("data");
+                std::string name = data.at("name");
+                std::vector<std::string> childNames;
+                if (data.count("children") > 0) {
+                    for (auto& child : data.at("children")) {
+                        childNames.push_back(nameMapping[child]);
+                    }
+                }
+
+                std::string type = getString(element.at("classes"), "classes");
+
+                if(type == "and") {
+                    success = builder.addAndElement(name, childNames);
+                } else if (type == "or") {
+                    success = builder.addOrElement(name, childNames);
+                } else if (type == "pand") {
+                    success = builder.addPandElement(name, childNames);
+                } else if (type == "por") {
+                    success = builder.addPorElement(name, childNames);
+                } else if (type == "spare") {
+                    success = builder.addSpareElement(name, childNames);
+                } else if (type == "seq") {
+                    success = builder.addSequenceEnforcer(name, childNames);
+                } else if (type== "fdep") {
+                    success = builder.addDepElement(name, childNames, storm::utility::one<ValueType>());
+                } else if (type== "pdep") {
+                    ValueType probability = parseRationalExpression(data.at("prob"));
+                    success = builder.addDepElement(name, childNames, probability);
+                } else if (type == "be") {
+                    ValueType failureRate = parseRationalExpression(data.at("rate"));
+                    ValueType dormancyFactor = parseRationalExpression(data.at("dorm"));
+                    success = builder.addBasicElement(name, failureRate, dormancyFactor);
+                } else {
+                    STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " << type << "  not recognized.");
+                    success = false;
+                }
+
+                // Set layout positions
+                json position = element.at("position");
+                double x = position.at("x");
+                double y = position.at("y");
+                builder.addLayoutInfo(name, x / 7, y / 7);
+                STORM_LOG_THROW(success, storm::exceptions::FileIoException, "Error while adding element '" << element << "'.");
+            }
+
+            if(!builder.setTopLevel(toplevelId)) {
+                STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown.");
+            }
+        }
+
+        template<typename ValueType>
+        ValueType DFTJsonParser<ValueType>::parseRationalExpression(std::string const& expr) {
+            STORM_LOG_ASSERT(false, "Specialized method should be called.");
+            return 0;
+        }
+
+        template<>
+        double DFTJsonParser<double>::parseRationalExpression(std::string const& expr) {
+            return boost::lexical_cast<double>(expr);
+        }
+
+        // Explicitly instantiate the class.
+        template class DFTJsonParser<double>;
+
+#ifdef STORM_HAVE_CARL
+        template<>
+        storm::RationalFunction DFTJsonParser<storm::RationalFunction>::parseRationalExpression(std::string const& expr) {
+            STORM_LOG_TRACE("Translating expression: " << expr);
+            storm::expressions::Expression expression = parser.parseFromString(expr);
+            STORM_LOG_TRACE("Expression: " << expression);
+            storm::RationalFunction rationalFunction = evaluator.asRational(expression);
+            STORM_LOG_TRACE("Parsed expression: " << rationalFunction);
+            return rationalFunction;
+        }
+
+        template class DFTJsonParser<RationalFunction>;
+#endif
+        
+    }
+}
diff --git a/src/storm-dft/parser/DFTJsonParser.h b/src/storm-dft/parser/DFTJsonParser.h
new file mode 100644
index 000000000..cf2e83826
--- /dev/null
+++ b/src/storm-dft/parser/DFTJsonParser.h
@@ -0,0 +1,48 @@
+#pragma  once
+
+#include <map>
+
+#include "storm/storage/expressions/ExpressionManager.h"
+#include "storm/parser/ExpressionParser.h"
+#include "storm/storage/expressions/ExpressionEvaluator.h"
+
+#include "storm-dft/storage/dft/DFT.h"
+#include "storm-dft/storage/dft/DFTBuilder.h"
+
+// JSON parser
+#include "json.hpp"
+
+using json = nlohmann::json;
+
+namespace storm {
+    namespace parser {
+
+        template<typename ValueType>
+        class DFTJsonParser {
+            storm::storage::DFTBuilder<ValueType> builder;
+
+            std::shared_ptr<storm::expressions::ExpressionManager> manager;
+
+            storm::parser::ExpressionParser parser;
+
+            storm::expressions::ExpressionEvaluator<ValueType> evaluator;
+
+            std::unordered_map<std::string, storm::expressions::Expression> identifierMapping;
+
+        public:
+            DFTJsonParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) {
+            }
+
+            storm::storage::DFT<ValueType> parseJson(std::string const& filename);
+            
+        private:
+            void readFile(std::string const& filename);
+
+            std::string stripQuotsFromName(std::string const& name);
+            std::string parseNodeIdentifier(std::string const& name);
+            std::string getString(json const& structure, std::string const& errorInfo);
+
+            ValueType parseRationalExpression(std::string const& expr);
+        };
+    }
+}
diff --git a/src/storm-dft/settings/modules/DFTSettings.cpp b/src/storm-dft/settings/modules/DFTSettings.cpp
index 5bf705d8a..898360c4b 100644
--- a/src/storm-dft/settings/modules/DFTSettings.cpp
+++ b/src/storm-dft/settings/modules/DFTSettings.cpp
@@ -16,6 +16,8 @@ namespace storm {
             const std::string DFTSettings::moduleName = "dft";
             const std::string DFTSettings::dftFileOptionName = "dftfile";
             const std::string DFTSettings::dftFileOptionShortName = "dft";
+            const std::string DFTSettings::dftJsonFileOptionName = "dftfile-json";
+            const std::string DFTSettings::dftJsonFileOptionShortName = "dftjson";
             const std::string DFTSettings::symmetryReductionOptionName = "symmetryreduction";
             const std::string DFTSettings::symmetryReductionOptionShortName = "symred";
             const std::string DFTSettings::modularisationOptionName = "modularisation";
@@ -37,6 +39,8 @@ namespace storm {
             DFTSettings::DFTSettings() : ModuleSettings(moduleName) {
                 this->addOption(storm::settings::OptionBuilder(moduleName, dftFileOptionName, false, "Parses the model given in the Galileo format.").setShortName(dftFileOptionShortName)
                                 .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the file from which to read the DFT model.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build());
+                this->addOption(storm::settings::OptionBuilder(moduleName, dftJsonFileOptionName, false, "Parses the model given in the Cytoscape JSON format.").setShortName(dftJsonFileOptionShortName)
+                                .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The name of the JSON file from which to read the DFT model.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, symmetryReductionOptionName, false, "Exploit symmetric structure of model.").setShortName(symmetryReductionOptionShortName).build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, modularisationOptionName, false, "Use modularisation (not applicable for expected time).").build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, disableDCOptionName, false, "Disable Dont Care propagation.").build());
@@ -60,7 +64,15 @@ namespace storm {
             std::string DFTSettings::getDftFilename() const {
                 return this->getOption(dftFileOptionName).getArgumentByName("filename").getValueAsString();
             }
-            
+
+            bool DFTSettings::isDftJsonFileSet() const {
+                return this->getOption(dftJsonFileOptionName).getHasOptionBeenSet();
+            }
+
+            std::string DFTSettings::getDftJsonFilename() const {
+                return this->getOption(dftJsonFileOptionName).getArgumentByName("filename").getValueAsString();
+            }
+
             bool DFTSettings::useSymmetryReduction() const {
                 return this->getOption(symmetryReductionOptionName).getHasOptionBeenSet();
             }
diff --git a/src/storm-dft/settings/modules/DFTSettings.h b/src/storm-dft/settings/modules/DFTSettings.h
index 1b1b097f9..c1a9df7e5 100644
--- a/src/storm-dft/settings/modules/DFTSettings.h
+++ b/src/storm-dft/settings/modules/DFTSettings.h
@@ -34,6 +34,20 @@ namespace storm {
                  */
                 std::string getDftFilename() const;
 
+                /*!
+                 * Retrieves whether the dft file option for Json was set.
+                 *
+                 * @return True if the dft file option was set.
+                 */
+                bool isDftJsonFileSet() const;
+
+                /*!
+                 * Retrieves the name of the json file that contains the dft specification.
+                 *
+                 * @return The name of the json file that contains the dft specification.
+                 */
+                std::string getDftJsonFilename() const;
+
                 /*!
                  * Retrieves whether the option to use symmetry reduction is set.
                  *
@@ -144,6 +158,8 @@ namespace storm {
                // Define the string names of the options as constants.
                 static const std::string dftFileOptionName;
                 static const std::string dftFileOptionShortName;
+                static const std::string dftJsonFileOptionName;
+                static const std::string dftJsonFileOptionShortName;
                 static const std::string symmetryReductionOptionName;
                 static const std::string symmetryReductionOptionShortName;
                 static const std::string modularisationOptionName;
diff --git a/src/storm-dft/storage/dft/DFT.cpp b/src/storm-dft/storage/dft/DFT.cpp
index 8f19119a2..e38c40ce1 100644
--- a/src/storm-dft/storage/dft/DFT.cpp
+++ b/src/storm-dft/storage/dft/DFT.cpp
@@ -174,7 +174,8 @@ namespace storm {
                 std::shared_ptr<DFTDependency<ValueType> const> dependency = getDependency(idDependency);
                 visitQueue.push(dependency->id());
                 visitQueue.push(dependency->triggerEvent()->id());
-                visitQueue.push(dependency->dependentEvent()->id());
+                STORM_LOG_THROW(dependency->dependentEvents().size() == 1, storm::exceptions::NotSupportedException, "Direct state generation does not support n-ary dependencies. Consider rewriting them by setting the binary dependency flag.");
+                visitQueue.push(dependency->dependentEvents()[0]->id());
             }
             stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
 
@@ -284,7 +285,13 @@ namespace storm {
         
         template<typename ValueType>
         uint64_t DFT<ValueType>::maxRank() const {
-            return mElements.back()->rank();
+            uint64_t max = 0;
+            for (auto const& e : mElements) {
+                if(e->rank() > max) {
+                    max = e->rank();
+                }
+            }
+            return max;
         }
         
         template<typename ValueType>
diff --git a/src/storm-dft/storage/dft/DFT.h b/src/storm-dft/storage/dft/DFT.h
index 9ef232a65..4c904ec5c 100644
--- a/src/storm-dft/storage/dft/DFT.h
+++ b/src/storm-dft/storage/dft/DFT.h
@@ -15,7 +15,7 @@
 #include "storm-dft/storage/dft/DFTElements.h"
 #include "storm-dft/storage/dft/SymmetricUnits.h"
 #include "storm-dft/storage/dft/DFTStateGenerationInfo.h"
-
+#include "storm-dft/storage/dft/DFTLayoutInfo.h"
 
 namespace storm {
     namespace storage {
@@ -63,7 +63,8 @@ namespace storm {
             std::vector<size_t> mTopModule;
             std::map<size_t, size_t> mRepresentants; // id element -> id representative
             std::vector<std::vector<size_t>> mSymmetries;
-            
+            std::map<size_t, DFTLayoutInfo> mLayoutInfo;
+
         public:
             DFT(DFTElementVector const& elements, DFTElementPointer const& tle);
             
@@ -263,7 +264,19 @@ namespace storm {
             std::vector<size_t> immediateFailureCauses(size_t index) const;
             
             std::vector<size_t> findModularisationRewrite() const;
-        
+
+            void setElementLayoutInfo(size_t id, DFTLayoutInfo const& layoutInfo) {
+                mLayoutInfo[id] = layoutInfo;
+            }
+
+            DFTLayoutInfo const& getElementLayoutInfo(size_t id) const {
+                if(mLayoutInfo.count(id) == 0) {
+                    STORM_LOG_WARN("Layout info for element with id " << id << " not found");
+                    return DFTLayoutInfo();
+                }
+                return mLayoutInfo.at(id);
+            }
+
         private:
             std::pair<std::vector<size_t>, std::vector<size_t>> getSortedParentAndOutDepIds(size_t index) const;
             
diff --git a/src/storm-dft/storage/dft/DFTBuilder.cpp b/src/storm-dft/storage/dft/DFTBuilder.cpp
index 612008226..70df810cf 100644
--- a/src/storm-dft/storage/dft/DFTBuilder.cpp
+++ b/src/storm-dft/storage/dft/DFTBuilder.cpp
@@ -25,9 +25,11 @@ namespace storm {
                     if (itFind != mElements.end()) {
                         // Child found
                         DFTElementPointer childElement = itFind->second;
-                        STORM_LOG_ASSERT(!childElement->isDependency(), "Child is dependency.");
-                        gate->pushBackChild(childElement);
-                        childElement->addParent(gate);
+                        STORM_LOG_TRACE("Ignore functional dependency " << child << " in gate " << gate->name());
+                        if(!childElement->isDependency()) {
+                            gate->pushBackChild(childElement);
+                            childElement->addParent(gate);
+                        }
                     } else {
                         // Child not found -> find first dependent event to assure that child is dependency
                         // TODO: Not sure whether this is the intended behaviour?
@@ -50,17 +52,31 @@ namespace storm {
                 }
             }
 
-            // Initialize dependencies
-            for (auto& dependency : mDependencies) {
-                DFTGatePointer triggerEvent = std::static_pointer_cast<DFTGate<ValueType>>(mElements[dependency->nameTrigger()]);
-                STORM_LOG_ASSERT(mElements[dependency->nameDependent()]->isBasicElement(), "Dependent element is not BE.");
-                std::shared_ptr<DFTBE<ValueType>> dependentEvent = std::static_pointer_cast<DFTBE<ValueType>>(mElements[dependency->nameDependent()]);
-                dependency->initialize(triggerEvent, dependentEvent);
-                triggerEvent->addOutgoingDependency(dependency);
-                dependentEvent->addIngoingDependency(dependency);
+            for(auto& elem : mDependencyChildNames) {
+                bool first = true;
+                std::vector<std::shared_ptr<DFTBE<ValueType>>> dependencies;
+                for(auto const& childName : elem.second) {
+                    auto itFind = mElements.find(childName);
+                    STORM_LOG_ASSERT(itFind != mElements.end(), "Child '" << childName << "' not found");
+                    DFTElementPointer childElement = itFind->second;
+                    if (!first) {
+                        dependencies.push_back(std::static_pointer_cast<DFTBE<ValueType>>(childElement));
+                    } else {
+                        elem.first->setTriggerElement(std::static_pointer_cast<DFTGate<ValueType>>(childElement));
+                        childElement->addOutgoingDependency(elem.first);
+                    }
+                    first = false;
+                }
+                if (binaryDependencies) {
+                    assert(dependencies.size() == 1);
+                }
+                elem.first->setDependentEvents(dependencies);
+                for (auto& dependency : dependencies) {
+                    dependency->addIngoingDependency(elem.first);
+                }
+                
             }
-
-
+            
 
             // Sort elements topologically
             // compute rank
@@ -73,8 +89,18 @@ namespace storm {
             for(DFTElementPointer e : elems) {
                 e->setId(id++);
             }
+
             STORM_LOG_ASSERT(!mTopLevelIdentifier.empty(), "No top level element.");
-            return DFT<ValueType>(elems, mElements[mTopLevelIdentifier]);
+            DFT<ValueType> dft(elems, mElements[mTopLevelIdentifier]);
+
+            // Set layout info
+            for (auto& elem : mElements) {
+                if(mLayoutInfo.count(elem.first) > 0) {
+                    dft.setElementLayoutInfo(elem.second->id(), mLayoutInfo.at(elem.first));
+                }
+            }
+
+            return dft;
         }
 
         template<typename ValueType>
@@ -144,10 +170,10 @@ namespace storm {
                     element = std::make_shared<DFTOr<ValueType>>(mNextId++, name);
                     break;
                 case DFTElementType::PAND:
-                    element = std::make_shared<DFTPand<ValueType>>(mNextId++, name);
+                    element = std::make_shared<DFTPand<ValueType>>(mNextId++, name, pandDefaultInclusive);
                     break;
                 case DFTElementType::POR:
-                    element = std::make_shared<DFTPor<ValueType>>(mNextId++, name);
+                    element = std::make_shared<DFTPor<ValueType>>(mNextId++, name, porDefaultInclusive);
                     break;
                 case DFTElementType::SPARE:
                    element = std::make_shared<DFTSpare<ValueType>>(mNextId++, name);
@@ -175,10 +201,24 @@ namespace storm {
             } else if(visited[n] == topoSortColour::WHITE) {
                 if(n->isGate()) {
                     visited[n] = topoSortColour::GREY;
-                    for(DFTElementPointer const& c : std::static_pointer_cast<DFTGate<ValueType>>(n)->children()) {
+                    for (DFTElementPointer const& c : std::static_pointer_cast<DFTGate<ValueType>>(n)->children()) {
+                        topoVisit(c, visited, L);
+                    }
+                }
+                // TODO restrictions and dependencies have no parents, so this can be done more efficiently.
+                if(n->isRestriction()) {
+                    visited[n] = topoSortColour::GREY;
+                    for (DFTElementPointer const& c : std::static_pointer_cast<DFTRestriction<ValueType>>(n)->children()) {
                         topoVisit(c, visited, L);
                     }
                 }
+                if(n->isDependency()) {
+                    visited[n] = topoSortColour::GREY;
+                    for (DFTElementPointer const& c : std::static_pointer_cast<DFTDependency<ValueType>>(n)->dependentEvents()) {
+                        topoVisit(c, visited, L);
+                    }
+                    topoVisit(std::static_pointer_cast<DFTDependency<ValueType>>(n)->triggerEvent(), visited, L);
+                }
                 visited[n] = topoSortColour::BLACK;
                 L.push_back(n);
             }
@@ -240,7 +280,9 @@ namespace storm {
                 {
                     DFTDependencyPointer dependency = std::static_pointer_cast<DFTDependency<ValueType>>(element);
                     children.push_back(dependency->triggerEvent()->name());
-                    children.push_back(dependency->dependentEvent()->name());
+                    for(auto const& depEv : dependency->dependentEvents()) {
+                        children.push_back(depEv->name());
+                    }
                     addDepElement(element->name(), children, dependency->probability());
                     break;
                 }
diff --git a/src/storm-dft/storage/dft/DFTBuilder.h b/src/storm-dft/storage/dft/DFTBuilder.h
index f9a11d52b..636b5e5a1 100644
--- a/src/storm-dft/storage/dft/DFTBuilder.h
+++ b/src/storm-dft/storage/dft/DFTBuilder.h
@@ -7,7 +7,7 @@
 
 #include "storm-dft/storage/dft/DFTElements.h"
 #include "storm-dft/storage/dft/elements/DFTRestriction.h"
-
+#include "storm-dft/storage/dft/DFTLayoutInfo.h"
 
 namespace storm {
     namespace storage {
@@ -31,11 +31,13 @@ namespace storm {
             std::unordered_map<std::string, DFTElementPointer> mElements;
             std::unordered_map<DFTElementPointer, std::vector<std::string>> mChildNames;
             std::unordered_map<DFTRestrictionPointer, std::vector<std::string>> mRestrictionChildNames;
+            std::unordered_map<DFTDependencyPointer, std::vector<std::string>> mDependencyChildNames;
             std::vector<DFTDependencyPointer> mDependencies;
             std::vector<DFTRestrictionPointer> mRestrictions;
+            std::unordered_map<std::string, DFTLayoutInfo> mLayoutInfo;
             
         public:
-            DFTBuilder() {
+            DFTBuilder(bool defaultInclusive = true, bool binaryDependencies = true) : pandDefaultInclusive(defaultInclusive), porDefaultInclusive(defaultInclusive), binaryDependencies(binaryDependencies) {
                 
             }
             
@@ -51,10 +53,26 @@ namespace storm {
                 return addStandardGate(name, children, DFTElementType::PAND);
             }
             
+            bool addPandElement(std::string const& name, std::vector<std::string> const& children, bool inclusive) {
+                bool tmpDefault = pandDefaultInclusive;
+                pandDefaultInclusive = inclusive;
+                bool result = addStandardGate(name, children, DFTElementType::PAND);
+                pandDefaultInclusive = tmpDefault;
+                return result;
+            }
+            
             bool addPorElement(std::string const& name, std::vector<std::string> const& children) {
                 return addStandardGate(name, children, DFTElementType::POR);
             }
             
+            bool addPorElement(std::string const& name, std::vector<std::string> const& children, bool inclusive) {
+                bool tmpDefault = porDefaultInclusive;
+                porDefaultInclusive = inclusive;
+                bool result = addStandardGate(name, children, DFTElementType::POR);
+                pandDefaultInclusive = tmpDefault;
+                return result;
+            }
+            
             bool addSpareElement(std::string const& name, std::vector<std::string> const& children) {
                 return addStandardGate(name, children, DFTElementType::SPARE);
             }
@@ -84,7 +102,7 @@ namespace storm {
 
                 //TODO Matthias: collect constraints for SMT solving
                 //0 <= probability <= 1
-                if (!storm::utility::isOne(probability) && children.size() > 2) {
+                if (binaryDependencies && !storm::utility::isOne(probability) && children.size() > 2) {
                     // Introduce additional element for first capturing the proabilistic dependency
                     std::string nameAdditional = name + "_additional";
                     addBasicElement(nameAdditional, storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>());
@@ -97,16 +115,27 @@ namespace storm {
                     return true;
                 } else {
                     // Add dependencies
-                    for (size_t i = 1; i < children.size(); ++i) {
-                        std::string nameDep = name + "_" + std::to_string(i);
-                        if(mElements.count(nameDep) != 0) {
-                            // Element with that name already exists.
-                            STORM_LOG_ERROR("Element with name: " << nameDep << " already exists.");
-                            return false;
+                    if(binaryDependencies) {
+                        for (size_t i = 1; i < children.size(); ++i) {
+                            std::string nameDep = name + "_" + std::to_string(i);
+                            if (mElements.count(nameDep) != 0) {
+                                // Element with that name already exists.
+                                STORM_LOG_ERROR("Element with name: " << nameDep << " already exists.");
+                                return false;
+                            }
+                            STORM_LOG_ASSERT(storm::utility::isOne(probability) || children.size() == 2,
+                                             "PDep with multiple children supported.");
+                            DFTDependencyPointer element = std::make_shared<DFTDependency<ValueType>>(mNextId++,
+                                                                                                      nameDep,
+                                                                                                      probability);
+                            mElements[element->name()] = element;
+                            mDependencyChildNames[element] = {trigger, children[i]};
+                            mDependencies.push_back(element);
                         }
-                        STORM_LOG_ASSERT(storm::utility::isOne(probability) || children.size() == 2, "PDep with multiple children supported.");
-                        DFTDependencyPointer element = std::make_shared<DFTDependency<ValueType>>(mNextId++, nameDep, trigger, children[i], probability);
+                    } else {
+                        DFTDependencyPointer element = std::make_shared<DFTDependency<ValueType>>(mNextId++, name, probability);
                         mElements[element->name()] = element;
+                        mDependencyChildNames[element] = children;
                         mDependencies.push_back(element);
                     }
                     return true;
@@ -147,6 +176,11 @@ namespace storm {
                 mElements[name] = std::make_shared<DFTBE<ValueType>>(mNextId++, name, failureRate, dormancyFactor);
                 return true;
             }
+
+            void addLayoutInfo(std::string const& name, double x, double y) {
+                STORM_LOG_ASSERT(mElements.count(name) > 0, "Element '" << name << "' not found.");
+                mLayoutInfo[name] = storm::storage::DFTLayoutInfo(x, y);
+            }
             
             bool setTopLevel(std::string const& tle) {
                 mTopLevelIdentifier = tle;
@@ -187,6 +221,13 @@ namespace storm {
 
             DFTElementVector topoSort();
             
+            // If true, the standard gate adders make a pand inclusive, and exclusive otherwise.
+            bool pandDefaultInclusive;
+            // If true, the standard gate adders make a pand inclusive, and exclusive otherwise.
+            bool porDefaultInclusive;
+
+            bool binaryDependencies;
+            
         };
     }
 }
diff --git a/src/storm-dft/storage/dft/DFTIsomorphism.h b/src/storm-dft/storage/dft/DFTIsomorphism.h
index 86625c975..081b76f0b 100644
--- a/src/storm-dft/storage/dft/DFTIsomorphism.h
+++ b/src/storm-dft/storage/dft/DFTIsomorphism.h
@@ -258,7 +258,8 @@ namespace storage {
         }
         
         void colourize(std::shared_ptr<const DFTDependency<ValueType>> const& dep) {
-            depColour[dep->id()] = std::pair<ValueType, ValueType>(dep->probability(), dep->dependentEvent()->activeFailureRate());
+            // TODO this can be improved for n-ary dependencies.
+            depColour[dep->id()] = std::pair<ValueType, ValueType>(dep->probability(), dep->dependentEvents()[0]->activeFailureRate());
         }
         
         void colourize(std::shared_ptr<const DFTRestriction<ValueType>> const& restr) {
@@ -486,10 +487,26 @@ namespace storage {
                     STORM_LOG_ASSERT(dft.isDependency(indexpair.second), "Element is no dependency.");
                     auto const& lDep = dft.getDependency(indexpair.first);
                     auto const& rDep = dft.getDependency(indexpair.second);
+
                     if(bijection.at(lDep->triggerEvent()->id()) != rDep->triggerEvent()->id()) {
                         return false;
-                    } 
-                    if(bijection.at(lDep->dependentEvent()->id()) != rDep->dependentEvent()->id()) {
+                    }
+
+                    std::set<size_t> dependenciesLeftMapped;
+                    for (auto const& depEv : lDep->dependentEvents()) {
+                        if (bleft.has(depEv->id())) {
+                            dependenciesLeftMapped.insert(bijection.at(depEv->id()));
+                        }
+                    }
+
+                    std::set<size_t> dependenciesRight;
+                    for (auto const& depEv : rDep->dependentEvents()) {
+                        if (bright.has(depEv->id())) {
+                            dependenciesRight.insert(depEv->id());
+                        }
+                    }
+
+                    if (dependenciesLeftMapped != dependenciesRight) {
                         return false;
                     }
                 } else if(dft.isRestriction(indexpair.first)) {
diff --git a/src/storm-dft/storage/dft/DFTLayoutInfo.h b/src/storm-dft/storage/dft/DFTLayoutInfo.h
new file mode 100644
index 000000000..c61de0f6d
--- /dev/null
+++ b/src/storm-dft/storage/dft/DFTLayoutInfo.h
@@ -0,0 +1,15 @@
+#pragma once
+
+namespace storm {
+    namespace storage {
+        struct DFTLayoutInfo {
+            DFTLayoutInfo() {};
+            DFTLayoutInfo(double x, double y) : x(x), y(y) {};
+            
+            // x location
+            double x = 0.0;
+            // y location
+            double y = 0.0;
+        };
+    }
+}
diff --git a/src/storm-dft/storage/dft/DFTState.cpp b/src/storm-dft/storage/dft/DFTState.cpp
index 78c0937d8..ec6509944 100644
--- a/src/storm-dft/storage/dft/DFTState.cpp
+++ b/src/storm-dft/storage/dft/DFTState.cpp
@@ -57,7 +57,8 @@ namespace storm {
             for (size_t dependencyId : mDft.getDependencies()) {
                 std::shared_ptr<DFTDependency<ValueType> const> dependency = mDft.getDependency(dependencyId);
                 STORM_LOG_ASSERT(dependencyId == dependency->id(), "Ids do not match.");
-                if (hasFailed(dependency->triggerEvent()->id()) && getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) {
+                assert(dependency->dependentEvents().size() == 1);
+                if (hasFailed(dependency->triggerEvent()->id()) && getElementState(dependency->dependentEvents()[0]->id()) == DFTElementState::Operational) {
                     mFailableDependencies.push_back(dependencyId);
                     STORM_LOG_TRACE("New dependency failure: " << dependency->toString());
                 }
@@ -198,8 +199,9 @@ namespace storm {
             
             for (auto dependency : mDft.getElement(id)->outgoingDependencies()) {
                 STORM_LOG_ASSERT(dependency->triggerEvent()->id() == id, "Ids do not match.");
-                if (getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) {
-                    STORM_LOG_ASSERT(!isFailsafe(dependency->dependentEvent()->id()), "Dependent event is failsafe.");
+                assert(dependency->dependentEvents().size() == 1);
+                if (getElementState(dependency->dependentEvents()[0]->id()) == DFTElementState::Operational) {
+                    STORM_LOG_ASSERT(!isFailsafe(dependency->dependentEvents()[0]->id()), "Dependent event is failsafe.");
                     mFailableDependencies.push_back(dependency->id());
                     STORM_LOG_TRACE("New dependency failure: " << dependency->toString());
                 }
@@ -213,7 +215,8 @@ namespace storm {
             STORM_LOG_ASSERT(hasFailed(id), "Element has not failed.");
             
             for (auto dependency : mDft.getBasicElement(id)->ingoingDependencies()) {
-                STORM_LOG_ASSERT(dependency->dependentEvent()->id() == id, "Ids do not match.");
+                assert(dependency->dependentEvents().size() == 1);
+                STORM_LOG_ASSERT(dependency->dependentEvents()[0]->id() == id, "Ids do not match.");
                 setDependencyDontCare(dependency->id());
             }
         }
@@ -244,7 +247,8 @@ namespace storm {
                 // Consider failure due to dependency
                 STORM_LOG_ASSERT(index < nrFailableDependencies(), "Index invalid.");
                 std::shared_ptr<DFTDependency<ValueType> const> dependency = mDft.getDependency(mFailableDependencies[index]);
-                std::pair<std::shared_ptr<DFTBE<ValueType> const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true);
+                assert(dependency->dependentEvents().size() == 1);
+                std::pair<std::shared_ptr<DFTBE<ValueType> const>,bool> res(mDft.getBasicElement(dependency->dependentEvents()[0]->id()), true);
                 mFailableDependencies.erase(mFailableDependencies.begin() + index);
                 setFailed(res.first->id());
                 setDependencySuccessful(dependency->id());
diff --git a/src/storm-dft/storage/dft/elements/DFTBE.h b/src/storm-dft/storage/dft/elements/DFTBE.h
index 216227af6..3be82d9f1 100644
--- a/src/storm-dft/storage/dft/elements/DFTBE.h
+++ b/src/storm-dft/storage/dft/elements/DFTBE.h
@@ -38,7 +38,8 @@ namespace storm {
             }
             
             bool addIngoingDependency(DFTDependencyPointer const& e) {
-                STORM_LOG_ASSERT(e->dependentEvent()->id() == this->id(), "Ids do not match.");
+                // TODO write this assertion for n-ary dependencies, probably by addign a method to the dependencies to support this.
+                //STORM_LOG_ASSERT(e->dependentEvent()->id() == this->id(), "Ids do not match.");
                 if(std::find(mIngoingDependencies.begin(), mIngoingDependencies.end(), e) != mIngoingDependencies.end()) {
                     return false;
                 }
diff --git a/src/storm-dft/storage/dft/elements/DFTDependency.h b/src/storm-dft/storage/dft/elements/DFTDependency.h
index 2c5b7d0cc..7d11bae2a 100644
--- a/src/storm-dft/storage/dft/elements/DFTDependency.h
+++ b/src/storm-dft/storage/dft/elements/DFTDependency.h
@@ -12,35 +12,28 @@ namespace storm {
             using DFTBEPointer = std::shared_ptr<DFTBE<ValueType>>;
             
         protected:
-            std::string mNameTrigger;
-            std::string mNameDependent;
             ValueType mProbability;
             DFTGatePointer mTriggerEvent;
-            DFTBEPointer mDependentEvent;
+            std::vector<DFTBEPointer> mDependentEvents;
 
         public:
-            DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent, ValueType probability) :
-                DFTElement<ValueType>(id, name), mNameTrigger(trigger), mNameDependent(dependent), mProbability(probability)
+            DFTDependency(size_t id, std::string const& name, ValueType probability) :
+                DFTElement<ValueType>(id, name), mProbability(probability)
             {
             }
 
             virtual ~DFTDependency() {}
 
-            void initialize(DFTGatePointer triggerEvent, DFTBEPointer dependentEvent) {
-                STORM_LOG_ASSERT(triggerEvent->name() == mNameTrigger, "Name does not match.");
-                STORM_LOG_ASSERT(dependentEvent->name() == mNameDependent, "Name does not match.");
+            void setTriggerElement(DFTGatePointer const& triggerEvent) {
                 mTriggerEvent = triggerEvent;
-                mDependentEvent = dependentEvent;
-            }
 
-            std::string nameTrigger() const {
-                return mNameTrigger;
             }
 
-            std::string nameDependent() const {
-                return mNameDependent;
+            void setDependentEvents(std::vector<DFTBEPointer> const& dependentEvents) {
+                mDependentEvents = dependentEvents;
             }
 
+
             ValueType const& probability() const {
                 return mProbability;
             }
@@ -50,9 +43,9 @@ namespace storm {
                 return mTriggerEvent;
             }
 
-            DFTBEPointer const& dependentEvent() const {
-                STORM_LOG_ASSERT(mDependentEvent, "Dependent element does not exists.");
-                return mDependentEvent;
+            std::vector<DFTBEPointer> const& dependentEvents() const {
+                STORM_LOG_ASSERT(mDependentEvents.size() > 0, "Dependent element does not exists.");
+                return mDependentEvents;
             }
 
             DFTElementType type() const override {
@@ -76,9 +69,11 @@ namespace storm {
 
             virtual std::vector<size_t> independentUnit() const override {
                 std::set<size_t> unit = {this->mId};
-                mDependentEvent->extendUnit(unit);
-                if(unit.count(mTriggerEvent->id()) != 0) {
-                    return {};
+                for(auto const& depEv : mDependentEvents) {
+                    depEv->extendUnit(unit);
+                    if(unit.count(mTriggerEvent->id()) != 0) {
+                        return {};
+                    }
                 }
                 return std::vector<size_t>(unit.begin(), unit.end());
             }
@@ -90,7 +85,10 @@ namespace storm {
                     // Parent in the subdft, ie it is *not* a subdft
                     return;
                 }
-                mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves);
+                for (auto const& depEv : mDependentEvents) {
+                    depEv->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves);
+                    if (elemsInSubtree.empty()) return;
+                }
                 if(elemsInSubtree.empty()) {
                     // Parent in the subdft, ie it is *not* a subdft
                     return;
@@ -102,7 +100,11 @@ namespace storm {
             virtual std::string toString() const override {
                 std::stringstream stream;
                 bool fdep = storm::utility::isOne(mProbability);
-                stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")";
+                stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => { ";
+                for(auto const& depEv : mDependentEvents) {
+                    stream << depEv->name() << " ";
+                }
+                stream << "}";
                 if (!fdep) {
                     stream << " with probability " << mProbability;
                 }
diff --git a/src/storm-dft/storage/dft/elements/DFTElement.cpp b/src/storm-dft/storage/dft/elements/DFTElement.cpp
index 61a087bdb..287af8e98 100644
--- a/src/storm-dft/storage/dft/elements/DFTElement.cpp
+++ b/src/storm-dft/storage/dft/elements/DFTElement.cpp
@@ -14,8 +14,10 @@ namespace storm {
             }
             
             // Check that no outgoing dependencies can be triggered anymore
+            // Notice that n-ary dependencies are supported via rewriting them during build-time
             for (DFTDependencyPointer dependency : mOutgoingDependencies) {
-                if (state.isOperational(dependency->dependentEvent()->id()) && state.isOperational(dependency->triggerEvent()->id())) {
+                assert(dependency->dependentEvents().size() == 1);
+                if (state.isOperational(dependency->dependentEvents()[0]->id()) && state.isOperational(dependency->triggerEvent()->id())) {
                     return false;
                 }
             }
diff --git a/src/storm-dft/storage/dft/elements/DFTPand.h b/src/storm-dft/storage/dft/elements/DFTPand.h
index bb18efe72..21cda29a9 100644
--- a/src/storm-dft/storage/dft/elements/DFTPand.h
+++ b/src/storm-dft/storage/dft/elements/DFTPand.h
@@ -7,11 +7,13 @@ namespace storm {
         class DFTPand : public DFTGate<ValueType> {
 
         public:
-            DFTPand(size_t id, std::string const& name, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
-                    DFTGate<ValueType>(id, name, children)
+            DFTPand(size_t id, std::string const& name, bool inclusive, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
+                    DFTGate<ValueType>(id, name, children),
+                    inclusive(inclusive)
             {}
 
             void checkFails(storm::storage::DFTState<ValueType>& state,  DFTStateSpaceGenerationQueues<ValueType>& queues) const override {
+                assert(inclusive);
                 if(state.isOperational(this->mId)) {
                     bool childOperationalBefore = false;
                     for(auto const& child : this->mChildren)
@@ -31,6 +33,7 @@ namespace storm {
             }
 
             void checkFailsafe(storm::storage::DFTState<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& queues) const override {
+                assert(inclusive);
                 STORM_LOG_ASSERT(this->hasFailsafeChild(state), "No failsafe child.");
                 if(state.isOperational(this->mId)) {
                     this->failsafe(state, queues);
@@ -42,9 +45,15 @@ namespace storm {
                 return DFTElementType::PAND;
             }
             
+            bool isInclusive() const {
+                return inclusive;
+            }
+            
             std::string typestring() const override {
-                return "PAND";
+                return inclusive ? "PAND-inc" : "PAND-ex";
             }
+        protected:
+            bool inclusive;
         };
         
         template<typename ValueType>
diff --git a/src/storm-dft/storage/dft/elements/DFTPor.h b/src/storm-dft/storage/dft/elements/DFTPor.h
index 6e2fe731c..857e19714 100644
--- a/src/storm-dft/storage/dft/elements/DFTPor.h
+++ b/src/storm-dft/storage/dft/elements/DFTPor.h
@@ -6,12 +6,14 @@ namespace storm {
         template<typename ValueType>
         class DFTPor : public DFTGate<ValueType> {
         public:
-            DFTPor(size_t id, std::string const& name, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
-                    DFTGate<ValueType>(id, name, children)
+            DFTPor(size_t id, std::string const& name, bool inclusive, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children = {}) :
+                    DFTGate<ValueType>(id, name, children),
+                    inclusive(inclusive)
             {}
 
             void checkFails(storm::storage::DFTState<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& queues) const override {
-                 if(state.isOperational(this->mId)) {
+                assert(inclusive);
+                if(state.isOperational(this->mId)) {
                     if (state.hasFailed(this->mChildren.front()->id())) {
                         // First child has failed before others
                         this->fail(state, queues);
@@ -28,6 +30,7 @@ namespace storm {
             }
 
             void checkFailsafe(storm::storage::DFTState<ValueType>& state, DFTStateSpaceGenerationQueues<ValueType>& queues) const override {
+                assert(inclusive);
                 if (state.isFailsafe(this->mChildren.front()->id())) {
                     this->failsafe(state, queues);
                     this->childrenDontCare(state, queues);
@@ -39,8 +42,14 @@ namespace storm {
             }
             
             std::string  typestring() const override {
-                return "POR";
+                return inclusive ? "POR-inc" : "POR-ex";
             }
+            
+            bool isInclusive() const {
+                return inclusive;
+            }
+        protected:
+            bool inclusive;
         };
 
         template<typename ValueType>
diff --git a/src/storm-dft/storage/dft/elements/DFTRestriction.h b/src/storm-dft/storage/dft/elements/DFTRestriction.h
index f4a03f688..195a217bb 100644
--- a/src/storm-dft/storage/dft/elements/DFTRestriction.h
+++ b/src/storm-dft/storage/dft/elements/DFTRestriction.h
@@ -36,6 +36,15 @@ namespace storm {
             virtual bool isSeqEnforcer() const {
                 return false;
             }
+            
+            bool allChildrenBEs() const {
+                for(auto const& elem : mChildren) {
+                    if (!elem->isBasicElement()) {
+                        return false;
+                    }
+                }
+                return true;
+            }
 
 
             virtual std::string typestring() const = 0;
diff --git a/src/storm-dft/transformations/DftToGspnTransformator.cpp b/src/storm-dft/transformations/DftToGspnTransformator.cpp
new file mode 100644
index 000000000..8c3ef0448
--- /dev/null
+++ b/src/storm-dft/transformations/DftToGspnTransformator.cpp
@@ -0,0 +1,629 @@
+#include "DftToGspnTransformator.h"
+#include "storm/exceptions/NotImplementedException.h"
+#include <memory>
+
+namespace storm {
+    namespace transformations {
+        namespace dft {
+            
+            // Prevent some magic constants
+            static constexpr const uint64_t defaultPriority = 1;
+            static constexpr const uint64_t defaultCapacity = 1;
+
+            template <typename ValueType>
+            DftToGspnTransformator<ValueType>::DftToGspnTransformator(storm::storage::DFT<ValueType> const& dft) : mDft(dft) {
+                // Intentionally left empty.
+            }
+
+            template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::transform() {
+				
+                builder.setGspnName("DftToGspnTransformation");
+				
+				// Loop through every DFT element and draw them as a GSPN.
+				drawGSPNElements();
+
+				// Draw restrictions into the GSPN (i.e. SEQ or MUTEX).
+				//drawGSPNRestrictions();
+            }
+            
+            template<typename ValueType>
+            uint64_t DftToGspnTransformator<ValueType>::toplevelFailedPlaceId() {
+                assert(failedNodes.size() > mDft.getTopLevelIndex());
+                return failedNodes[mDft.getTopLevelIndex()];
+            }
+            
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawGSPNElements() {
+                
+                
+				// Loop through every DFT element and draw them as a GSPN.
+				for (std::size_t i = 0; i < mDft.nrElements(); i++) {
+					auto dftElement = mDft.getElement(i);
+                    bool isRepresentative = mDft.isRepresentative(i);
+                    
+					// Check which type the element is and call the corresponding drawing-function.
+					switch (dftElement->type()) {
+						case storm::storage::DFTElementType::AND:
+							drawAND(std::static_pointer_cast<storm::storage::DFTAnd<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::OR:
+							drawOR(std::static_pointer_cast<storm::storage::DFTOr<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::VOT:
+							drawVOT(std::static_pointer_cast<storm::storage::DFTVot<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::PAND:
+							drawPAND(std::static_pointer_cast<storm::storage::DFTPand<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::SPARE:
+							drawSPARE(std::static_pointer_cast<storm::storage::DFTSpare<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::POR:
+							drawPOR(std::static_pointer_cast<storm::storage::DFTPor<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::SEQ:
+                            drawSeq(std::static_pointer_cast<storm::storage::DFTSeq<ValueType> const>(dftElement));
+                            break;
+						case storm::storage::DFTElementType::MUTEX:
+							// No method call needed here. MUTEX only consists of restrictions, which are handled later.
+							break;
+						case storm::storage::DFTElementType::BE:
+							drawBE(std::static_pointer_cast<storm::storage::DFTBE<ValueType> const>(dftElement), isRepresentative);
+							break;
+						case storm::storage::DFTElementType::CONSTF:
+							drawCONSTF(dftElement, isRepresentative);
+							break;
+						case storm::storage::DFTElementType::CONSTS:
+							drawCONSTS(dftElement, isRepresentative);
+							break;
+						case storm::storage::DFTElementType::PDEP:
+                            drawPDEP(std::static_pointer_cast<storm::storage::DFTDependency<ValueType> const>(dftElement));
+							break;
+						default:
+							STORM_LOG_ASSERT(false, "DFT type unknown.");
+							break;
+					}
+				}
+                
+			}
+            
+            template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawBE(std::shared_ptr<storm::storage::DFTBE<ValueType> const> dftBE, bool isRepresentative) {
+                uint64_t beActive = builder.addPlace(defaultCapacity, isBEActive(dftBE) ? 1 : 0, dftBE->name() + STR_ACTIVATED);
+                activeNodes.emplace(dftBE->id(), beActive);
+                uint64_t beFailed = builder.addPlace(defaultCapacity, 0, dftBE->name() + STR_FAILED);
+
+                double xcenter = mDft.getElementLayoutInfo(dftBE->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftBE->id()).y;
+                builder.setPlaceLayoutInfo(beActive, storm::gspn::LayoutInfo(xcenter - 3.0, ycenter));
+                builder.setPlaceLayoutInfo(beFailed, storm::gspn::LayoutInfo(xcenter + 3.0, ycenter));
+
+                
+                uint64_t disabledNode = 0;
+                if (!smart || dftBE->nrRestrictions() > 0) {
+                    disabledNode = addDisabledPlace(dftBE);
+                }
+                
+                uint64_t unavailableNode = 0;
+                if (!smart || isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftBE, storm::gspn::LayoutInfo(xcenter+9.0, ycenter));
+                }
+                
+                assert(failedNodes.size() == dftBE->id());
+                failedNodes.push_back(beFailed);
+                uint64_t tActive = builder.addTimedTransition(defaultPriority, dftBE->activeFailureRate(), dftBE->name() + "_activeFailing");
+                builder.setTransitionLayoutInfo(tActive, storm::gspn::LayoutInfo(xcenter, ycenter + 3.0));
+                builder.addInputArc(beActive, tActive);
+                builder.addInhibitionArc(beFailed, tActive);
+                builder.addOutputArc(tActive, beActive);
+                builder.addOutputArc(tActive, beFailed);
+                uint64_t tPassive = builder.addTimedTransition(defaultPriority, dftBE->passiveFailureRate(), dftBE->name() + "_passiveFailing");
+                builder.setTransitionLayoutInfo(tPassive, storm::gspn::LayoutInfo(xcenter, ycenter - 3.0));
+                builder.addInhibitionArc(beActive, tPassive);
+                builder.addInhibitionArc(beFailed, tPassive);
+                builder.addOutputArc(tPassive, beFailed);
+                
+                if (!smart || dftBE->nrRestrictions() > 0) {
+                    builder.addInhibitionArc(disabledNode, tActive);
+                    builder.addInhibitionArc(disabledNode, tPassive);
+                }
+                
+                if (!smart || isRepresentative) {
+                    builder.addOutputArc(tActive, unavailableNode);
+                    builder.addOutputArc(tPassive, unavailableNode);
+                }
+            }
+			
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawAND(std::shared_ptr<storm::storage::DFTAnd<ValueType> const> dftAnd, bool isRepresentative) {
+                uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftAnd->name() + STR_FAILED);
+                assert(failedNodes.size() == dftAnd->id());
+                failedNodes.push_back(nodeFailed);
+
+                double xcenter = mDft.getElementLayoutInfo(dftAnd->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftAnd->id()).y;
+                builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter, ycenter-3.0));
+
+                uint64_t unavailableNode = 0;
+                if (isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftAnd, storm::gspn::LayoutInfo(xcenter+6.0, ycenter-3.0));
+                }
+
+                
+                uint64_t tAndFailed = builder.addImmediateTransition( getFailPriority(dftAnd)  , 0.0, dftAnd->name() + STR_FAILING );
+                builder.setTransitionLayoutInfo(tAndFailed, storm::gspn::LayoutInfo(xcenter, ycenter+3.0));
+                builder.addInhibitionArc(nodeFailed, tAndFailed);
+                builder.addOutputArc(tAndFailed, nodeFailed);
+                if (isRepresentative) {
+                    builder.addOutputArc(tAndFailed, unavailableNode);
+                }
+                for(auto const& child : dftAnd->children()) {
+                    assert(failedNodes.size() > child->id());
+                    builder.addInputArc(failedNodes[child->id()], tAndFailed);
+                    builder.addOutputArc(tAndFailed, failedNodes[child->id()]);
+                }
+			}
+
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawOR(std::shared_ptr<storm::storage::DFTOr<ValueType> const> dftOr, bool isRepresentative) {
+                uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftOr->name() + STR_FAILED);
+                assert(failedNodes.size() == dftOr->id());
+                failedNodes.push_back(nodeFailed);
+
+                double xcenter = mDft.getElementLayoutInfo(dftOr->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftOr->id()).y;
+                builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter, ycenter-3.0));
+
+                uint64_t unavailableNode = 0;
+                if (isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftOr, storm::gspn::LayoutInfo(xcenter+6.0, ycenter-3.0));
+                }
+                
+                uint64_t i = 0;
+                for (auto const& child : dftOr->children()) {
+                    uint64_t tNodeFailed = builder.addImmediateTransition( getFailPriority(dftOr), 0.0, dftOr->name() + STR_FAILING + std::to_string(i) );
+                    builder.setTransitionLayoutInfo(tNodeFailed, storm::gspn::LayoutInfo(xcenter-5.0+i*3.0, ycenter+3.0));
+                    builder.addInhibitionArc(nodeFailed, tNodeFailed);
+                    builder.addOutputArc(tNodeFailed, nodeFailed);
+                    if (isRepresentative) {
+                        builder.addOutputArc(tNodeFailed, unavailableNode);
+                    }
+                    assert(failedNodes.size() > child->id());
+                    builder.addInputArc(failedNodes[child->id()], tNodeFailed);
+                    builder.addOutputArc(tNodeFailed, failedNodes[child->id()]);
+                    ++i;
+                }
+			}
+			
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawVOT(std::shared_ptr<storm::storage::DFTVot<ValueType> const> dftVot, bool isRepresentative) {
+                // TODO: finish layouting
+                uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftVot->name() + STR_FAILED);
+                assert(failedNodes.size() == dftVot->id());
+                failedNodes.push_back(nodeFailed);
+
+                double xcenter = mDft.getElementLayoutInfo(dftVot->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftVot->id()).y;
+                builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter, ycenter-3.0));
+
+                uint64_t unavailableNode = 0;
+                if (isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftVot, storm::gspn::LayoutInfo(xcenter+6.0, ycenter-3.0));
+                }
+                
+                uint64_t nodeCollector = builder.addPlace(dftVot->nrChildren(), 0, dftVot->name() + "_collector");
+                builder.setPlaceLayoutInfo(nodeCollector, storm::gspn::LayoutInfo(xcenter, ycenter));
+
+                uint64_t tNodeFailed = builder.addImmediateTransition(getFailPriority(dftVot), 0.0, dftVot->name() + STR_FAILING);
+                builder.addOutputArc(tNodeFailed, nodeFailed);
+                if (isRepresentative) {
+                    builder.addOutputArc(tNodeFailed, unavailableNode);
+                }
+                builder.addInhibitionArc(nodeFailed, tNodeFailed);
+                builder.addInputArc(nodeCollector, tNodeFailed, dftVot->threshold());
+                builder.addOutputArc(tNodeFailed, nodeCollector, dftVot->threshold());
+                uint64_t i = 0;
+                for (auto const& child : dftVot->children()) {
+                    uint64_t childInhibPlace = builder.addPlace(1, 0, dftVot->name() + "_child_fail_inhib" + std::to_string(i));
+                    uint64_t tCollect = builder.addImmediateTransition(getFailPriority(dftVot), 0.0, dftVot->name() + "_child_collect" + std::to_string(i));
+                    builder.addOutputArc(tCollect, nodeCollector);
+                    builder.addOutputArc(tCollect, childInhibPlace);
+                    builder.addInhibitionArc(childInhibPlace, tCollect);
+                    builder.addInputArc(failedNodes[child->id()], tCollect);
+                    builder.addOutputArc(tCollect, failedNodes[child->id()]);
+                    ++i;
+                }
+			}
+
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawPAND(std::shared_ptr<storm::storage::DFTPand<ValueType> const> dftPand, bool isRepresentative) {
+                uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftPand->name()  + STR_FAILED);
+                assert(failedNodes.size() == dftPand->id());
+                failedNodes.push_back(nodeFailed);
+
+                double xcenter = mDft.getElementLayoutInfo(dftPand->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftPand->id()).y;
+                builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter+3.0, ycenter-3.0));
+
+                uint64_t unavailableNode = 0;
+                if (!smart || isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftPand, storm::gspn::LayoutInfo(xcenter+9.0, ycenter-3.0));
+                }
+                
+                uint64_t tNodeFailed = builder.addImmediateTransition(getFailPriority(dftPand), 0.0,  dftPand->name() + STR_FAILING);
+                builder.setTransitionLayoutInfo(tNodeFailed, storm::gspn::LayoutInfo(xcenter+3.0, ycenter+3.0));
+                builder.addInhibitionArc(nodeFailed, tNodeFailed);
+                builder.addOutputArc(tNodeFailed, nodeFailed);
+                if (!smart || isRepresentative) {
+                    builder.addOutputArc(tNodeFailed, nodeFailed);
+                }
+
+                if(dftPand->isInclusive()) {
+                    // Inclusive PAND
+                    uint64_t nodeFS = builder.addPlace(defaultCapacity, 0, dftPand->name() + STR_FAILSAVE);
+                    builder.setPlaceLayoutInfo(nodeFS, storm::gspn::LayoutInfo(xcenter-3.0, ycenter-3.0));
+
+                    builder.addInhibitionArc(nodeFS, tNodeFailed);
+                    for(auto const& child : dftPand->children()) {
+                        builder.addInputArc(failedNodes[child->id()], tNodeFailed);
+                        builder.addOutputArc(tNodeFailed, failedNodes[child->id()]);
+                    }
+                    for (uint64_t j = 1; j < dftPand->nrChildren(); ++j) {
+                        uint64_t tfs = builder.addImmediateTransition(getFailPriority(dftPand), 0.0, dftPand->name() + STR_FAILSAVING + std::to_string(j));
+                        builder.setTransitionLayoutInfo(tfs, storm::gspn::LayoutInfo(xcenter-6.0+j*3.0, ycenter+3.0));
+
+                        builder.addInputArc(failedNodes[dftPand->children().at(j)->id()], tfs);
+                        builder.addOutputArc(tfs, failedNodes[dftPand->children().at(j)->id()]);
+                        builder.addInhibitionArc(failedNodes[dftPand->children().at(j-1)->id()], tfs);
+                        builder.addOutputArc(tfs, nodeFS);
+                        builder.addInhibitionArc(nodeFS, tfs);
+                        
+                    }
+                } else {
+                    // Exclusive PAND
+                    uint64_t fi = 0;
+                    uint64_t tn = 0;
+                    for(uint64_t j = 0; j < dftPand->nrChildren(); ++j) {
+                        auto const& child = dftPand->children()[j];
+                        if (j > 0) {
+                            builder.addInhibitionArc(failedNodes.at(child->id()), tn);
+                        }
+                        if (j != dftPand->nrChildren() - 1) {
+                            tn = builder.addImmediateTransition(getFailPriority(dftPand), 0.0, dftPand->name() + STR_FAILING + "_" +std::to_string(j));
+                            builder.setTransitionLayoutInfo(tn, storm::gspn::LayoutInfo(xcenter-3.0, ycenter+3.0));
+                        } else {
+                            tn = tNodeFailed;
+                        }
+                        builder.addInputArc(failedNodes.at(child->id()), tn);
+                        builder.addOutputArc(tn, failedNodes.at(child->id()));
+                        if (j > 0) {
+                            builder.addInputArc(fi, tn);
+                        }
+                        if (j != dftPand->nrChildren() - 1) {
+                            fi = builder.addPlace(defaultCapacity, 0, dftPand->name() + "_F_" + std::to_string(j));
+                            builder.setPlaceLayoutInfo(fi, storm::gspn::LayoutInfo(xcenter-3.0+j*3.0, ycenter));
+                            builder.addOutputArc(tn, fi);
+                        }
+                        
+                    }
+                }
+            }
+
+            template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawPOR(std::shared_ptr<storm::storage::DFTPor<ValueType> const> dftPor, bool isRepresentative) {
+                uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftPor->name() + STR_FAILED);
+                failedNodes.push_back(nodeFailed);
+
+                double xcenter = mDft.getElementLayoutInfo(dftPor->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftPor->id()).y;
+                builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter+3.0, ycenter-3.0));
+
+                uint64_t unavailableNode = 0;
+                if (!smart || isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftPor, storm::gspn::LayoutInfo(xcenter+9.0, ycenter-3.0));
+                }
+
+                uint64_t tfail = builder.addImmediateTransition(getFailPriority(dftPor), 0.0, dftPor->name() + STR_FAILING);
+                builder.setTransitionLayoutInfo(tfail, storm::gspn::LayoutInfo(xcenter+3.0, ycenter+3.0));
+                builder.addOutputArc(tfail, nodeFailed);
+                builder.addInhibitionArc(nodeFailed, tfail);
+
+                builder.addInputArc(failedNodes.at(dftPor->children().front()->id()), tfail);
+                builder.addOutputArc(tfail, failedNodes.at(dftPor->children().front()->id()));
+
+                if(!smart || isRepresentative) {
+                    builder.addOutputArc(tfail, unavailableNode);
+                }
+
+                if(dftPor->isInclusive()) {
+                    // Inclusive POR
+                    uint64_t nodeFS = builder.addPlace(defaultCapacity, 0, dftPor->name() + STR_FAILSAVE);
+                    builder.setPlaceLayoutInfo(nodeFS, storm::gspn::LayoutInfo(xcenter-3.0, ycenter-3.0));
+
+                    builder.addInhibitionArc(nodeFS, tfail);
+                    uint64_t j = 0;
+                    for (auto const& child : dftPor->children()) {
+                        if(j > 0) {
+                            uint64_t tfailsf = builder.addImmediateTransition(getFailPriority(dftPor), 0.0, dftPor->name() + STR_FAILSAVING + std::to_string(j));
+                            builder.setTransitionLayoutInfo(tfailsf, storm::gspn::LayoutInfo(xcenter-3.0+j*3.0, ycenter+3.0));
+                            builder.addInputArc(failedNodes.at(child->id()), tfailsf);
+                            builder.addOutputArc(tfailsf, failedNodes.at(child->id()));
+                            builder.addOutputArc(tfailsf, nodeFS);
+                            builder.addInhibitionArc(nodeFS, tfailsf);
+                            builder.addInhibitionArc(failedNodes.at(dftPor->children().front()->id()), tfailsf);
+                        }
+
+                        ++j;
+                    }
+                } else {
+                    // Exclusive POR
+                    uint64_t j = 0;
+                    for (auto const& child : dftPor->children()) {
+                        if(j > 0) {
+                            builder.addInhibitionArc(failedNodes.at(child->id()), tfail);
+                        }
+                        ++j;
+                    }
+
+                }
+                
+            }
+
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawSPARE(std::shared_ptr<storm::storage::DFTSpare<ValueType> const> dftSpare, bool isRepresentative) {
+                
+                uint64_t nodeFailed = builder.addPlace(defaultCapacity, 0, dftSpare->name() + STR_FAILED);
+                failedNodes.push_back(nodeFailed);
+
+                double xcenter = mDft.getElementLayoutInfo(dftSpare->id()).x;
+                double ycenter = mDft.getElementLayoutInfo(dftSpare->id()).y;
+                builder.setPlaceLayoutInfo(nodeFailed, storm::gspn::LayoutInfo(xcenter+10.0, ycenter-8.0));
+
+                uint64_t unavailableNode = 0;
+                if (isRepresentative) {
+                    unavailableNode = addUnavailableNode(dftSpare, storm::gspn::LayoutInfo(xcenter+16.0, ycenter-8.0));
+                }
+                uint64_t spareActive = builder.addPlace(defaultCapacity, isBEActive(dftSpare) ? 1 : 0, dftSpare->name() + STR_ACTIVATED);
+                builder.setPlaceLayoutInfo(spareActive, storm::gspn::LayoutInfo(xcenter-20.0, ycenter-8.0));
+                activeNodes.emplace(dftSpare->id(), spareActive);
+
+                
+                std::vector<uint64_t> cucNodes;
+                std::vector<uint64_t> considerNodes;
+                std::vector<uint64_t> nextclTransitions;
+                std::vector<uint64_t> nextconsiderTransitions;
+                uint64_t j = 0;
+                for(auto const& child : dftSpare->children()) {
+                    if (j > 0) {
+                        size_t nodeConsider = builder.addPlace(defaultCapacity, 0, dftSpare->name()+ "_consider_" + child->name());
+                        considerNodes.push_back(nodeConsider);
+                        builder.setPlaceLayoutInfo(nodeConsider, storm::gspn::LayoutInfo(xcenter-15.0+j*14.0, ycenter-8.0));
+
+                        builder.addOutputArc(nextclTransitions.back(), considerNodes.back(), 1);
+                        if (j > 1) {
+                            builder.addOutputArc(nextconsiderTransitions.back(), considerNodes.back());
+                        }
+                        
+                        uint64_t tnextconsider = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_cannot_claim_" + child->name());
+                        builder.setTransitionLayoutInfo(tnextconsider, storm::gspn::LayoutInfo(xcenter-7.0+j*14.0, ycenter-8.0));
+                        builder.addInputArc(considerNodes.back(), tnextconsider);
+                        builder.addInputArc(unavailableNodes.at(child->id()), tnextconsider);
+                        nextconsiderTransitions.push_back(tnextconsider);
+                        
+                    }
+                    size_t nodeCUC = builder.addPlace(defaultCapacity, j == 0 ? 1 : 0, dftSpare->name() + "_claimed_" + child->name());
+                    cucNodes.push_back(nodeCUC);
+                    builder.setPlaceLayoutInfo(nodeCUC, storm::gspn::LayoutInfo(xcenter-9.0+j*14.0, ycenter+5.0));
+                    if (j > 0) {
+                        uint64 tclaim = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_claim_" + child->name());
+                        builder.setTransitionLayoutInfo(tclaim, storm::gspn::LayoutInfo(xcenter-9.0+j*14.0, ycenter));
+                        builder.addInhibitionArc(unavailableNodes.at(child->id()), tclaim);
+                        builder.addInputArc(considerNodes.back(), tclaim);
+                        builder.addOutputArc(tclaim, cucNodes.back());
+                    }
+                    uint64_t tnextcl = builder.addImmediateTransition(getFailPriority(dftSpare), 0.0, dftSpare->name() + "_next_claim_" + std::to_string(j));
+                    builder.setTransitionLayoutInfo(tnextcl, storm::gspn::LayoutInfo(xcenter-3.0+j*14.0, ycenter+5.0));
+                    builder.addInputArc(cucNodes.back(), tnextcl);
+                    builder.addInputArc(failedNodes.at(child->id()), tnextcl);
+                    builder.addOutputArc(tnextcl, failedNodes.at(child->id()));
+                    nextclTransitions.push_back(tnextcl);
+                    ++j;
+                    for (uint64_t k : mDft.module(child->id())) {
+                        
+                        uint64_t tactive = builder.addImmediateTransition(defaultPriority+1, 0.0, dftSpare->name() + "_activate_" + std::to_string(j) + "_" +  std::to_string(k));
+                        builder.addInputArc(cucNodes.back(), tactive);
+                        builder.addOutputArc(tactive, cucNodes.back());
+                        builder.addInputArc(spareActive, tactive);
+                        builder.addOutputArc(tactive, activeNodes.at(k));
+                        builder.addInhibitionArc(activeNodes.at(k), tactive);
+                    }
+                    
+                    
+                }
+                builder.addOutputArc(nextconsiderTransitions.back(), nodeFailed);
+                builder.addOutputArc(nextclTransitions.back(), nodeFailed);
+
+                if (isRepresentative) {
+                    builder.addOutputArc(nextconsiderTransitions.back(), unavailableNode);
+                    builder.addOutputArc(nextclTransitions.back(), unavailableNode);
+                }
+                
+                
+
+			}
+
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawCONSTF(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftConstF, bool isRepresentative) {
+			    failedNodes.push_back(builder.addPlace(defaultCapacity, 1, dftConstF->name() + STR_FAILED));
+                uint64_t unavailableNode = 0;
+                if (isRepresentative) {
+                    // TODO set position
+                    unavailableNode = addUnavailableNode(dftConstF, storm::gspn::LayoutInfo(0, 0), false);
+                }
+
+			}
+//			
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawCONSTS(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftConstS, bool isRepresentative) {
+//				storm::gspn::Place placeCONSTSFailed;
+//				placeCONSTSFailed.setName(dftConstS->name() + STR_FAILED);
+//				placeCONSTSFailed.setNumberOfInitialTokens(0);
+//				placeCONSTSFailed.setCapacity(0); // It cannot contain a token, because it cannot fail.
+//				mGspn.addPlace(placeCONSTSFailed);
+			}
+//			
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawPDEP(std::shared_ptr<storm::storage::DFTDependency<ValueType> const> dftDependency) {
+                double xcenter = mDft.getElementLayoutInfo(dftDependency->id()).x;;
+                double ycenter = mDft.getElementLayoutInfo(dftDependency->id()).y;;
+                
+                uint64_t coinPlace = builder.addPlace(defaultCapacity, 1, dftDependency->name() + "_coin");
+                builder.setPlaceLayoutInfo(coinPlace, storm::gspn::LayoutInfo(xcenter-5.0, ycenter+2.0));
+                uint64_t t1 = builder.addImmediateTransition(defaultPriority, 0.0, dftDependency->name() + "_start_flip");
+                
+                builder.addInputArc(coinPlace, t1);
+                builder.addInputArc(failedNodes.at(dftDependency->triggerEvent()->id()), t1);
+                builder.addOutputArc(t1, failedNodes.at(dftDependency->triggerEvent()->id()));
+                uint64_t forwardPlace = builder.addPlace(defaultCapacity, 0, dftDependency->name() + "_forward");
+                builder.setPlaceLayoutInfo(forwardPlace, storm::gspn::LayoutInfo(xcenter+1.0, ycenter+2.0));
+                
+                if (!smart || dftDependency->probability() < 1.0) {
+                    uint64_t flipPlace = builder.addPlace(defaultCapacity, 0, dftDependency->name() + "_flip");
+                    builder.addOutputArc(t1, flipPlace);
+                    
+                    builder.setPlaceLayoutInfo(flipPlace, storm::gspn::LayoutInfo(xcenter-2.0, ycenter+2.0));
+                    uint64_t t2 = builder.addImmediateTransition(defaultPriority + 1, dftDependency->probability(), "_win_flip");
+                    builder.addInputArc(flipPlace, t2);
+                    builder.addOutputArc(t2, forwardPlace);
+                    if (dftDependency->probability() < 1.0) {
+                        uint64_t t3 = builder.addImmediateTransition(defaultPriority + 1, 1 - dftDependency->probability(), "_loose_flip");
+                        builder.addInputArc(flipPlace, t3);
+                    }
+                } else {
+                    builder.addOutputArc(t1, forwardPlace);
+                }
+                for(auto const& depEv : dftDependency->dependentEvents()) {
+                    uint64_t tx = builder.addImmediateTransition(defaultPriority, 0.0, dftDependency->name() + "_propagate_" + depEv->name());
+                    builder.addInputArc(forwardPlace, tx);
+                    builder.addOutputArc(tx, forwardPlace);
+                    builder.addOutputArc(tx, failedNodes.at(depEv->id()));
+                    builder.addInhibitionArc(failedNodes.at(depEv->id()), tx);
+                    if (!smart || depEv->nrRestrictions() > 0) {
+                        builder.addInhibitionArc(disabledNodes.at(depEv->id()), tx);
+                    }
+                    if (!smart || mDft.isRepresentative(depEv->id())) {
+                        builder.addOutputArc(tx, unavailableNodes.at(depEv->id()));
+                    }
+                   
+                }
+                
+                
+                
+                
+                
+			}
+            
+            template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawSeq(std::shared_ptr<storm::storage::DFTSeq<ValueType> const> dftSeq) {
+                STORM_LOG_THROW(dftSeq->allChildrenBEs(), storm::exceptions::NotImplementedException, "Sequence enforcers with gates as children are currently not supported");
+                uint64_t j = 0;
+                uint64_t tEnable = 0;
+                uint64_t nextPlace = 0;
+                for(auto const& child : dftSeq->children()) {
+                    nextPlace = builder.addPlace(defaultCapacity, j==0 ? 1 : 0, dftSeq->name() + "_next_" + child->name());
+                    if (j>0) {
+                        builder.addOutputArc(tEnable, nextPlace);
+                    }
+                    tEnable = builder.addImmediateTransition(defaultPriority + 1, 0.0, dftSeq->name() + "_unblock_" +child->name() );
+                    builder.addInputArc(nextPlace, tEnable);
+                    builder.addInputArc(disabledNodes.at(child->id()), tEnable);
+                    if (j>0) {
+                        builder.addInputArc(failedNodes.at(dftSeq->children().at(j-1)->id()), tEnable);
+                    }
+                    ++j;
+                }
+                
+            }
+            
+            template<typename ValueType>
+            uint64_t DftToGspnTransformator<ValueType>::addUnavailableNode(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftElement, storm::gspn::LayoutInfo const& layoutInfo, bool initialAvailable) {
+                uint64_t unavailableNode = builder.addPlace(defaultCapacity, initialAvailable ? 0 : 1, dftElement->name() + "_unavailable");
+                assert(unavailableNode != 0);
+                unavailableNodes.emplace(dftElement->id(), unavailableNode);
+                builder.setPlaceLayoutInfo(unavailableNode, layoutInfo);
+                return unavailableNode;
+            }
+            
+            template<typename ValueType>
+            uint64_t DftToGspnTransformator<ValueType>::addDisabledPlace(std::shared_ptr<const storm::storage::DFTBE<ValueType> > dftBe) {
+                uint64_t disabledNode = builder.addPlace(dftBe->nrRestrictions(), dftBe->nrRestrictions(), dftBe->name() + "_dabled");
+                disabledNodes.emplace(dftBe->id(), disabledNode);
+                return disabledNode;
+            }
+//			
+			
+			template <typename ValueType>
+            bool DftToGspnTransformator<ValueType>::isBEActive(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftElement)
+			{
+				// If element is the top element, return true.
+				if (dftElement->id() == mDft.getTopLevelIndex()) {
+					return true;
+				}
+				else { // Else look at all parents.
+					auto parents = dftElement->parents();
+					std::vector<bool> pathValidities;
+					
+					for (std::size_t i = 0; i < parents.size(); i++) {
+						// Add all parents to the vector, except if the parent is a SPARE and the current element is an inactive child of the SPARE.
+						if (parents[i]->type() == storm::storage::DFTElementType::SPARE) {
+							auto children = std::static_pointer_cast<storm::storage::DFTSpare<ValueType> const>(parents[i])->children();
+							if (children[0]->id() != dftElement->id()) {
+								continue;
+							}
+						}
+						
+						pathValidities.push_back(isBEActive(parents[i]));
+					}
+					
+					// Check all vector entries. If one is true, a "valid" path has been found.
+					for (std::size_t i = 0; i < pathValidities.size(); i++) {
+						if (pathValidities[i]) {
+							return true;
+						}
+					}
+				}
+				
+				// No "valid" path found. BE is inactive.
+				return false;
+			}
+			
+			template <typename ValueType>
+            uint64_t DftToGspnTransformator<ValueType>::getFailPriority(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftElement)
+			{
+                return mDft.maxRank() - dftElement->rank() + 2;
+			}
+
+			
+			template <typename ValueType>
+            void DftToGspnTransformator<ValueType>::drawGSPNRestrictions() {
+			}
+
+			template <typename ValueType>
+            gspn::GSPN* DftToGspnTransformator<ValueType>::obtainGSPN() {
+                return builder.buildGspn();
+            }
+			
+            // Explicitly instantiate the class.
+            template class DftToGspnTransformator<double>;
+            
+
+    #ifdef STORM_HAVE_CARL
+            // template class DftToGspnTransformator<storm::RationalFunction>;
+    #endif
+
+        } // namespace dft
+    } // namespace transformations
+} // namespace storm
+
+
diff --git a/src/storm-dft/transformations/DftToGspnTransformator.h b/src/storm-dft/transformations/DftToGspnTransformator.h
new file mode 100644
index 000000000..4ec911b23
--- /dev/null
+++ b/src/storm-dft/transformations/DftToGspnTransformator.h
@@ -0,0 +1,163 @@
+#pragma once
+
+#include "storm-dft/storage/dft/DFT.h"
+#include "storm-gspn/storage/gspn/GSPN.h"
+#include "storm-gspn/storage/gspn/GspnBuilder.h"
+
+namespace storm {
+    namespace transformations {
+        namespace dft {
+
+            /*!
+             * Transformator for DFT -> GSPN.
+             */
+            template<typename ValueType>
+            class DftToGspnTransformator {
+
+            public:
+                /*!
+                 * Constructor.
+                 *
+                 * @param dft DFT
+                 */
+                DftToGspnTransformator(storm::storage::DFT<ValueType> const& dft);
+
+                /*!
+                 * Transform the DFT to a GSPN.
+                 */
+                void transform();
+
+                /*!
+                 * Extract Gspn by building
+                 *
+                 */
+                gspn::GSPN* obtainGSPN();
+                
+                
+                uint64_t toplevelFailedPlaceId();
+                
+            private:
+                /*
+				 * Draw all elements of the GSPN.
+				 */
+				void drawGSPNElements();
+				/*
+				 * Draw restrictions between the elements of the GSPN (i.e. SEQ or MUTEX).
+				 */
+				void drawGSPNRestrictions();
+				
+				/*
+				 * Draw a Petri net Basic Event.
+				 * 
+				 * @param dftBE The Basic Event.
+				 */
+				void drawBE(std::shared_ptr<storm::storage::DFTBE<ValueType> const> dftBE, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net AND.
+				 * 
+				 * @param dftAnd The AND gate.
+				 */
+				void drawAND(std::shared_ptr<storm::storage::DFTAnd<ValueType> const> dftAnd, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net OR.
+				 * 
+				 * @param dftOr The OR gate.
+				 */
+				void drawOR(std::shared_ptr<storm::storage::DFTOr<ValueType> const> dftOr, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net VOT.
+				 * 
+				 * @param dftVot The VOT gate.
+				 */
+				void drawVOT(std::shared_ptr<storm::storage::DFTVot<ValueType> const> dftVot, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net PAND. 
+				 * This PAND is inklusive (children are allowed to fail simultaneously and the PAND will fail nevertheless).
+				 * 
+				 * @param dftPand The PAND gate.
+				 */
+				void drawPAND(std::shared_ptr<storm::storage::DFTPand<ValueType> const> dftPand, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net SPARE.
+				 * 
+				 * @param dftSpare The SPARE gate.
+				 */
+				void drawSPARE(std::shared_ptr<storm::storage::DFTSpare<ValueType> const> dftSpare, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net POR.
+				 * This POR is inklusive (children are allowed to fail simultaneously and the POR will fail nevertheless).
+				 * 
+				 * @param dftPor The POR gate.
+				 */
+				void drawPOR(std::shared_ptr<storm::storage::DFTPor<ValueType> const> dftPor, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net CONSTF (Constant Failure, a Basic Event that has already failed).
+				 * 
+				 * @param dftPor The CONSTF Basic Event.
+				 */
+				void drawCONSTF(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftConstF, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net CONSTS (Constant Save, a Basic Event that cannot fail).
+				 * 
+				 * @param dftPor The CONSTS Basic Event.
+				 */
+				void drawCONSTS(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftConstS, bool isRepresentative);
+				
+				/*
+				 * Draw a Petri net PDEP (FDEP is included with a firerate of 1).
+				 */
+				void drawPDEP(std::shared_ptr<storm::storage::DFTDependency<ValueType> const> dftDependency);
+				
+                
+                void drawSeq(std::shared_ptr<storm::storage::DFTSeq<ValueType> const> dftSeq);
+				 /*
+				  * Return true if BE is active (corresponding place contains one initial token) or false if BE is inactive (corresponding place contains no initial token).
+				  * 
+				  * @param dFTElement DFT element.
+				  */
+				 bool isBEActive(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dFTElement);
+				 
+				 /*
+				  * Get the priority of the element.
+				  * The priority is two times the length of the shortest path to the top event.
+				  * 
+				  * @param priority The priority of the gate. Top Event has priority 0,  its children 2, its grandchildren 4, ...
+				  * 
+				  * @param dftElement The element whose priority shall be determined.
+				  */
+				 uint64_t getFailPriority(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dFTElement);
+
+                
+                uint64_t addUnavailableNode(std::shared_ptr<storm::storage::DFTElement<ValueType> const> dftElement, storm::gspn::LayoutInfo const& layoutInfo, bool initialAvailable = true);
+                
+                uint64_t addDisabledPlace(std::shared_ptr<storm::storage::DFTBE<ValueType> const> dftBe);
+                
+                storm::storage::DFT<ValueType> const& mDft;
+                storm::gspn::GspnBuilder builder;
+                std::vector<uint64_t> failedNodes;
+                std::map<uint64_t, uint64_t> unavailableNodes;
+                std::map<uint64_t, uint64_t> activeNodes;
+                std::map<uint64_t, uint64_t> disabledNodes;
+                bool smart = true;
+                
+                static constexpr const char* STR_FAILING = "_failing";			// Name standard for transitions that point towards a place, which in turn indicates the failure of a gate.
+                static constexpr const char* STR_FAILED = "_failed";			// Name standard for place which indicates the failure of a gate.
+                static constexpr const char* STR_FAILSAVING = "_failsaving";	// Name standard for transition that point towards a place, which in turn indicates the failsave state of a gate.
+                static constexpr const char* STR_FAILSAVE = "_failsave";		// Name standard for place which indicates the failsave state of a gate.
+                static constexpr const char* STR_ACTIVATED = "_activated";		// Name standard for place which indicates the activity.
+                static constexpr const char* STR_ACTIVATING = "_activating";	// Name standard for transition that point towards a place, which in turn indicates its activity.
+                
+
+            };
+        }
+    }
+}
+
diff --git a/src/storm-gspn-cli/storm-gspn.cpp b/src/storm-gspn-cli/storm-gspn.cpp
index b973d046d..17b45222d 100644
--- a/src/storm-gspn-cli/storm-gspn.cpp
+++ b/src/storm-gspn-cli/storm-gspn.cpp
@@ -66,9 +66,7 @@ std::unordered_map<std::string, uint64_t> parseCapacitiesList(std::string const&
 }
 
 void handleJani(storm::gspn::GSPN const& gspn) {
-    std::shared_ptr<storm::expressions::ExpressionManager> exprManager(new storm::expressions::ExpressionManager());
-    storm::builder::JaniGSPNBuilder builder(gspn, exprManager);
-    storm::jani::Model* model = builder.build();
+
     storm::jani::JsonExporter::toFile(*model, {}, storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
     delete model;
 }
diff --git a/src/storm-gspn/builder/JaniGSPNBuilder.h b/src/storm-gspn/builder/JaniGSPNBuilder.h
index 76517a3a1..196d29562 100644
--- a/src/storm-gspn/builder/JaniGSPNBuilder.h
+++ b/src/storm-gspn/builder/JaniGSPNBuilder.h
@@ -9,17 +9,11 @@ namespace storm {
         class JaniGSPNBuilder {
         public:
             JaniGSPNBuilder(storm::gspn::GSPN const& gspn, std::shared_ptr<storm::expressions::ExpressionManager> const& expManager) : gspn(gspn), expressionManager(expManager) {
-                gspn.writeDotToStream(std::cout);
+                
             }
             
             virtual ~JaniGSPNBuilder() {
-                for (auto const& varEntry : vars) {
-                    delete varEntry.second;
-                }
-            }
-            
-            void setIgnoreWeights(bool ignore = true)  {
-                ignoreWeights = ignore;
+                
             }
             
             
@@ -34,6 +28,10 @@ namespace storm {
                 return model;
             }
             
+            storm::jani::Variable const& getPlaceVariable(uint64_t placeId) {
+                return *vars.at(placeId);
+            }
+            
             void addVariables(storm::jani::Model* model) {
                 for (auto const& place : gspn.getPlaces()) {
                     storm::jani::Variable* janiVar = nullptr;
@@ -46,8 +44,8 @@ namespace storm {
                     }
                     assert(janiVar != nullptr);
                     assert(vars.count(place.getID()) == 0);
-                    vars[place.getID()] = janiVar;
-                    model->addVariable(*janiVar);
+                    vars[place.getID()] = &model->addVariable(*janiVar);
+                    delete janiVar;
                 }
             }
             
@@ -59,95 +57,76 @@ namespace storm {
             
             void addEdges(storm::jani::Automaton& automaton, uint64_t locId) {
                 
-                storm::expressions::Expression guard = expressionManager->boolean(true);
-                for (auto const& trans : gspn.getImmediateTransitions()) {
-                    if (ignoreWeights || trans.noWeightAttached()) {
-                        std::vector<storm::jani::Assignment> assignments;
+                uint64_t lastPriority = -1;
+                storm::expressions::Expression lastPriorityGuard = expressionManager->boolean(false);
+                storm::expressions::Expression priorityGuard = expressionManager->boolean(true);
+                // TODO here there is something to fix if we add transition partitions.
+                
+                for (auto const& partition : gspn.getPartitions()) {
+                    storm::expressions::Expression guard = expressionManager->boolean(false);
+                    std::vector<storm::jani::EdgeDestination> weightedDestinations;
+                    
+                    assert(lastPriority >= partition.priority);
+                    if (lastPriority > partition.priority) {
+                        priorityGuard = priorityGuard && !lastPriorityGuard;
+                        lastPriority = partition.priority;
+                    } else {
+                        assert(lastPriority == partition.priority);
+                    }
+                    
+                    // Compute enabled weight expression.
+                    storm::expressions::Expression totalWeight = expressionManager->rational(0.0);
+                    for (auto const& transId : partition.transitions) {
+                        auto const& trans = gspn.getImmediateTransitions()[transId];
+                        if (trans.noWeightAttached()) {
+                            continue;
+                        }
+                        storm::expressions::Expression destguard = expressionManager->boolean(true);
                         for (auto const& inPlaceEntry : trans.getInputPlaces()) {
-                            guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second);
-                            assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second);
+                            destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second);
                         }
                         for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
-                            guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second);
-                        }
-                        for (auto const& outputPlaceEntry : trans.getOutputPlaces()) {
-                            assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second );
+                            destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second);
                         }
-                        storm::jani::OrderedAssignments oa(assignments);
-                        storm::jani::EdgeDestination dest(locId, expressionManager->integer(1), oa);
-                        storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, boost::none, guard, {dest});
-                        automaton.addEdge(e);
+                        totalWeight = totalWeight + storm::expressions::ite(destguard, expressionManager->rational(trans.getWeight()), expressionManager->rational(0.0));
+                        
                     }
+                    totalWeight = totalWeight.simplify();
                     
-                }
-                if(!ignoreWeights) {
-                    uint64_t lastPriority;
-                    storm::expressions::Expression lastPriorityGuard = expressionManager->boolean(false);
-                    storm::expressions::Expression priorityGuard = expressionManager->boolean(true);
-                    // TODO here there is something to fix if we add transition partitions.
                     
-                    for (auto const& partition : gspn.getPartitions()) {
-                        storm::expressions::Expression guard = expressionManager->boolean(false);
-                        std::vector<storm::jani::EdgeDestination> weightedDestinations;
-                        
-                        
-                        assert(lastPriority <= partition.priority);
-                        if (lastPriority < partition.priority) {
-                            priorityGuard = priorityGuard && !lastPriorityGuard;
-                            lastPriority = partition.priority;
-                        } else {
-                            assert(lastPriority == partition.priority);
+                    for (auto const& transId : partition.transitions) {
+                        auto const& trans = gspn.getImmediateTransitions()[transId];
+                        if (trans.noWeightAttached()) {
+                            std::cout << "ERROR -- no weights attached at transition" << std::endl;
+                            continue;
                         }
-                        
-                        // Compute enabled weight expression.
-                        storm::expressions::Expression totalWeight = expressionManager->rational(0.0);
-                        for (auto const& transId : partition.transitions) {
-                            auto const& trans = gspn.getImmediateTransitions()[transId];
-                            if (trans.noWeightAttached()) {
-                                continue;
-                            }
-                            storm::expressions::Expression destguard = expressionManager->boolean(true);
-                            for (auto const& inPlaceEntry : trans.getInputPlaces()) {
-                                destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second);
-                            }
-                            for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
-                                destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second);
+                        storm::expressions::Expression destguard = expressionManager->boolean(true);
+                        std::vector<storm::jani::Assignment> assignments;
+                        for (auto const& inPlaceEntry : trans.getInputPlaces()) {
+                            destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second);
+                            if (trans.getOutputPlaces().count(inPlaceEntry.first) == 0) {
+                                assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second);
                             }
-                            totalWeight = totalWeight + storm::expressions::ite(destguard, expressionManager->rational(trans.getWeight()), expressionManager->rational(0.0));
-                            
                         }
-                        totalWeight = totalWeight.simplify();
-                        
-                        
-                        for (auto const& transId : partition.transitions) {
-                            auto const& trans = gspn.getImmediateTransitions()[transId];
-                            if (trans.noWeightAttached()) {
-                                continue;
-                            }
-                            storm::expressions::Expression destguard = expressionManager->boolean(true);
-                            std::vector<storm::jani::Assignment> assignments;
-                            for (auto const& inPlaceEntry : trans.getInputPlaces()) {
-                                destguard = destguard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second);
-                                assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first]->getExpressionVariable() - inPlaceEntry.second) );
-                            }
-                            for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
-                                destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second);
-                            }
-                            for (auto const& outputPlaceEntry : trans.getOutputPlaces()) {
-                                assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first]->getExpressionVariable() + outputPlaceEntry.second) );
+                        for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
+                            destguard = destguard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second);
+                        }
+                        for (auto const& outputPlaceEntry : trans.getOutputPlaces()) {
+                            if (trans.getInputPlaces().count(outputPlaceEntry.first) == 0) {
+                                assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second );
+                            } else {
+                                assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second -  trans.getInputPlaces().at(outputPlaceEntry.first));
                             }
-                            destguard = destguard.simplify();
-                            guard = guard || destguard;
-                            storm::jani::OrderedAssignments oa(assignments);
-                            storm::jani::EdgeDestination dest(locId, storm::expressions::ite(destguard, (expressionManager->rational(trans.getWeight()) / totalWeight), expressionManager->rational(0.0)), oa);
-                            weightedDestinations.push_back(dest);
                         }
-                        storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, boost::none, (priorityGuard && guard).simplify(), weightedDestinations);
-                        automaton.addEdge(e);
-                        lastPriorityGuard = lastPriorityGuard || guard;
+                        destguard = destguard.simplify();
+                        guard = guard || destguard;
+                        storm::jani::OrderedAssignments oa(assignments);
+                        storm::jani::EdgeDestination dest(locId, storm::expressions::ite(destguard, (expressionManager->rational(trans.getWeight()) / totalWeight), expressionManager->rational(0.0)), oa);
+                        weightedDestinations.push_back(dest);
                     }
-                    
-                    
+                    storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, boost::none, (priorityGuard && guard).simplify(), weightedDestinations);
+                    automaton.addEdge(e);
+                    lastPriorityGuard = lastPriorityGuard || guard;
                     
                 }
                 for (auto const& trans : gspn.getTimedTransitions()) {
@@ -155,27 +134,33 @@ namespace storm {
                     
                     std::vector<storm::jani::Assignment> assignments;
                     for (auto const& inPlaceEntry : trans.getInputPlaces()) {
-                        guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() > inPlaceEntry.second);
-                        assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first]->getExpressionVariable() - inPlaceEntry.second) );
+                        guard = guard && (vars[inPlaceEntry.first]->getExpressionVariable() >= inPlaceEntry.second);
+                        if (trans.getOutputPlaces().count(inPlaceEntry.first) == 0) {
+                            assignments.emplace_back( *vars[inPlaceEntry.first], (vars[inPlaceEntry.first])->getExpressionVariable() - inPlaceEntry.second);
+                        }
                     }
                     for (auto const& inhibPlaceEntry : trans.getInhibitionPlaces()) {
-                        guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() > inhibPlaceEntry.second);
+                        guard = guard && (vars[inhibPlaceEntry.first]->getExpressionVariable() < inhibPlaceEntry.second);
                     }
                     for (auto const& outputPlaceEntry : trans.getOutputPlaces()) {
-                        assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first]->getExpressionVariable() + outputPlaceEntry.second) );
+                        if (trans.getInputPlaces().count(outputPlaceEntry.first) == 0) {
+                            assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second );
+                        } else {
+                            assignments.emplace_back( *vars[outputPlaceEntry.first], (vars[outputPlaceEntry.first])->getExpressionVariable() + outputPlaceEntry.second -  trans.getInputPlaces().at(outputPlaceEntry.first));
+                        }
                     }
                     storm::jani::OrderedAssignments oa(assignments);
                     storm::jani::EdgeDestination dest(locId, expressionManager->integer(1), oa);
                     storm::jani::Edge e(locId, storm::jani::Model::SILENT_ACTION_INDEX, expressionManager->rational(trans.getRate()), guard, {dest});
                     automaton.addEdge(e);
+                    
                 }
             }
             
         private:
-            bool ignoreWeights;
             const uint64_t janiVersion = 1;
             storm::gspn::GSPN const& gspn;
-            std::map<uint64_t, storm::jani::Variable*> vars;
+            std::map<uint64_t, storm::jani::Variable const*> vars;
             std::shared_ptr<storm::expressions::ExpressionManager> expressionManager;
             
         };
diff --git a/src/storm-gspn/storage/gspn/GSPN.cpp b/src/storm-gspn/storage/gspn/GSPN.cpp
index 5a7f819de..ce0d47d44 100644
--- a/src/storm-gspn/storage/gspn/GSPN.cpp
+++ b/src/storm-gspn/storage/gspn/GSPN.cpp
@@ -36,6 +36,14 @@ namespace storm {
         uint64_t GSPN::getNumberOfPlaces() const {
             return places.size();
         }
+        
+        uint64_t GSPN::getNumberOfImmediateTransitions() const {
+            return immediateTransitions.size();
+        }
+        
+        uint64_t GSPN::getNumberOfTimedTransitions() const {
+            return timedTransitions.size();
+        }
 
         std::vector<storm::gspn::TimedTransition<GSPN::RateType>> const& GSPN::getTimedTransitions() const {
             return this->timedTransitions;
@@ -368,6 +376,20 @@ namespace storm {
 
             return result;
         }
+        
+        void GSPN::setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layout) const {
+            placeLayout[placeId] = layout;
+        }
+        void GSPN::setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layout) const {
+            transitionLayout[transitionId] = layout;
+        }
+        
+        void GSPN::setPlaceLayoutInfo(std::map<uint64_t, LayoutInfo> const& placeLayout) const {
+            this->placeLayout = placeLayout;
+        }
+        void GSPN::setTransitionLayoutInfo(std::map<uint64_t, LayoutInfo> const& transitionLayout) const {
+            this->transitionLayout = transitionLayout;
+        }
 
         void GSPN::toPnpro(std::ostream &stream) const {
             auto space = "  ";
@@ -382,8 +404,14 @@ namespace storm {
             for (auto& place : places) {
                 stream << space3 << "<place marking=\"" << place.getNumberOfInitialTokens() <<"\" ";
                 stream << "name =\"" << place.getName() << "\" ";
-                stream << "x=\"" << x << "\" ";
-                stream << "y=\"1\" ";
+                if (placeLayout.count(place.getID()) > 0) {
+                    stream << "x=\"" << placeLayout.at(place.getID()).x << "\" ";
+                    stream << "y=\"" << placeLayout.at(place.getID()).y << "\" ";
+                } else {
+                    stream << "x=\"" << x << "\" ";
+                    stream << "y=\"1\" ";
+                    
+                }
                 stream << "/>" << std::endl;
                 x = x + 3;
             }
@@ -392,16 +420,28 @@ namespace storm {
                 stream << space3 << "<transition name=\"" << trans.getName() << "\" ";
                 stream << "type=\"EXP\" ";
                 stream << "nservers-x=\"" << trans.getRate() << "\" ";
-                stream << "x=\"" << x << "\" ";
-                stream << "y=\"4\" ";
+                if (transitionLayout.count(trans.getID()) > 0) {
+                    stream << "x=\"" << transitionLayout.at(trans.getID()).x << "\" ";
+                    stream << "y=\"" << transitionLayout.at(trans.getID()).y << "\" ";
+                } else {
+                    stream << "x=\"" << x << "\" ";
+                    stream << "y=\"4\" ";
+                    
+                }
                 stream << "/>" << std::endl;
                 x = x + 3;
             }
             for (auto& trans : immediateTransitions) {
                 stream << space3 << "<transition name=\"" << trans.getName() << "\" ";
                 stream << "type=\"IMM\" ";
-                stream << "x=\"" << x << "\" ";
-                stream << "y=\"4\" ";
+                stream << "priority=\"" << trans.getPriority() << "\" ";
+                if (transitionLayout.count(trans.getID()) > 0) {
+                    stream << "x=\"" << transitionLayout.at(trans.getID()).x << "\" ";
+                    stream << "y=\"" << transitionLayout.at(trans.getID()).y << "\" ";
+                } else {
+                    stream << "x=\"" << x << "\" ";
+                    stream << "y=\"4\" ";
+                }
                 stream << "/>" << std::endl;
                 x = x + 3;
             }
@@ -565,6 +605,12 @@ namespace storm {
             stream << space << "</net>" << std::endl;
             stream << "</pnml>" << std::endl;
         }
+        
+        void GSPN::writeStatsToStream(std::ostream& stream) const {
+            stream << "Number of places: " << getNumberOfPlaces() << std::endl;
+            stream << "Number of timed transitions: " << getNumberOfTimedTransitions() << std::endl;
+            stream << "Number of immediate transitions: " << getNumberOfImmediateTransitions() << std::endl;
+        }
     }
 }
 
diff --git a/src/storm-gspn/storage/gspn/GSPN.h b/src/storm-gspn/storage/gspn/GSPN.h
index 7086a6c1c..947769af3 100644
--- a/src/storm-gspn/storage/gspn/GSPN.h
+++ b/src/storm-gspn/storage/gspn/GSPN.h
@@ -11,6 +11,7 @@
 #include "storm-gspn/storage/gspn/Place.h"
 #include "storm-gspn/storage/gspn/TimedTransition.h"
 #include "storm-gspn/storage/gspn/TransitionPartition.h"
+#include "storm-gspn/storage/gspn/PlacementInfo.h"
 
 namespace storm {
     namespace gspn {
@@ -37,6 +38,10 @@ namespace storm {
              * @return The number of places.
              */
             uint64_t getNumberOfPlaces() const;
+            
+            uint64_t getNumberOfImmediateTransitions() const;
+            
+            uint64_t getNumberOfTimedTransitions() const;
 
             /*!
              *  
@@ -136,7 +141,13 @@ namespace storm {
              *  Set Capacities according to name->capacity map.
              */
             void setCapacities(std::unordered_map<std::string, uint64_t> const& mapping);
-
+            
+            void setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layout) const;
+            void setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layout) const;
+            void setPlaceLayoutInfo(std::map<uint64_t, LayoutInfo> const& placeLayout) const;
+            void setTransitionLayoutInfo(std::map<uint64_t, LayoutInfo> const& transitionLayout) const;
+            
+            
             /*!
              * Performe some checks
              * - testPlaces()
@@ -146,9 +157,11 @@ namespace storm {
              */
             bool isValid() const;
             // TODO doc
-            void toPnpro(std::ostream &stream) const;
+            void toPnpro(std::ostream& stream) const;
             // TODO doc
-            void toPnml(std::ostream &stream) const;
+            void toPnml(std::ostream& stream) const;
+            
+            void writeStatsToStream(std::ostream& stream) const;
         private:
             storm::gspn::Place* getPlace(uint64_t id);
             storm::gspn::Place* getPlace(std::string const& name);
@@ -185,6 +198,10 @@ namespace storm {
 
             std::vector<storm::gspn::TransitionPartition> partitions;
             
+            mutable std::map<uint64_t, LayoutInfo> placeLayout;
+            mutable std::map<uint64_t, LayoutInfo> transitionLayout;
+            
+            
         };
     }
 }
diff --git a/src/storm-gspn/storage/gspn/GspnBuilder.cpp b/src/storm-gspn/storage/gspn/GspnBuilder.cpp
index 9cb662eb7..e0bbd76fd 100644
--- a/src/storm-gspn/storage/gspn/GspnBuilder.cpp
+++ b/src/storm-gspn/storage/gspn/GspnBuilder.cpp
@@ -23,6 +23,15 @@ namespace storm {
             places.push_back(place);
             return newId;
         }
+        
+        
+        void GspnBuilder::setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layoutInfo) {
+            placeLayout[placeId] = layoutInfo;
+        }
+        
+        void GspnBuilder::setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layoutInfo) {
+            transitionLayout[transitionId] = layoutInfo;
+        }
 
         uint_fast64_t GspnBuilder::addImmediateTransition(uint_fast64_t const& priority, double const& weight, std::string const& name) {
             auto trans = storm::gspn::ImmediateTransition<double>();
@@ -35,7 +44,7 @@ namespace storm {
             if(partitions.count(priority) == 0) {
                 TransitionPartition newPart;
                 newPart.priority = priority;
-                partitions.at(priority).push_back(newPart);
+                partitions[priority].push_back(newPart);
             }
             
             if(storm::utility::isZero(weight)) {
@@ -164,7 +173,10 @@ namespace storm {
             }
             std::reverse(orderedPartitions.begin(), orderedPartitions.end());
             
-            return new GSPN(gspnName, places, immediateTransitions, timedTransitions, orderedPartitions);
+            GSPN* result = new GSPN(gspnName, places, immediateTransitions, timedTransitions, orderedPartitions);
+            result->setTransitionLayoutInfo(transitionLayout);
+            result->setPlaceLayoutInfo(placeLayout);
+            return result;
         }
     }
 }
diff --git a/src/storm-gspn/storage/gspn/GspnBuilder.h b/src/storm-gspn/storage/gspn/GspnBuilder.h
index 2f63ba719..79fb2e712 100644
--- a/src/storm-gspn/storage/gspn/GspnBuilder.h
+++ b/src/storm-gspn/storage/gspn/GspnBuilder.h
@@ -20,29 +20,32 @@ namespace storm {
             
             /**
              * Add a place to the gspn.
-             * @param id The id must be unique for the gspn.
              * @param name The name must be unique for the gspn.
              * @param capacity The capacity is the limit of tokens in the place.
              *                 A capacity of -1 indicates an unbounded place.
              * @param initialTokens The number of inital tokens in the place.
              */
             uint_fast64_t addPlace(int_fast64_t const& capacity = 1, uint_fast64_t const& initialTokens = 0, std::string const& name = "");
+            
+            void setPlaceLayoutInfo(uint64_t placeId, LayoutInfo const& layoutInfo);
 
             /**
              * Adds an immediate transition to the gspn.
-             * @param id The id must be unique for the gspn.
              * @param priority The priority for the transtion.
              * @param weight The weight for the transition.
              */
             uint_fast64_t addImmediateTransition(uint_fast64_t const& priority = 0, WeightType const& weight = 0, std::string const& name = "");
-
+            
+            
             /**
              * Adds an timed transition to the gspn.
-             * @param id The name id be unique for the gspn.
              * @param priority The priority for the transtion.
              * @param weight The weight for the transition.
              */
             uint_fast64_t addTimedTransition(uint_fast64_t const &priority, RateType const& rate, std::string const& name = "");
+            
+            void setTransitionLayoutInfo(uint64_t transitionId, LayoutInfo const& layoutInfo);
+
 
             /**
              * Adds an new input arc from a place to an transition.
@@ -112,6 +115,9 @@ namespace storm {
             
             // set containing all places
             std::vector<storm::gspn::Place> places;
+            
+            std::map<uint64_t, LayoutInfo> placeLayout;
+            std::map<uint64_t, LayoutInfo> transitionLayout;
         };
     }
 }
diff --git a/src/storm-gspn/storage/gspn/PlacementInfo.h b/src/storm-gspn/storage/gspn/PlacementInfo.h
new file mode 100644
index 000000000..e59218686
--- /dev/null
+++ b/src/storm-gspn/storage/gspn/PlacementInfo.h
@@ -0,0 +1,17 @@
+#pragma once
+
+namespace storm {
+    namespace gspn {
+        struct LayoutInfo {
+            LayoutInfo() {};
+            LayoutInfo(double x, double y, double rotation = 0.0) : x(x), y(y), rotation(rotation) {};
+            
+            // x location
+            double x = 0.0;
+            // y location
+            double y = 0.0;
+            // degrees
+            double rotation = 0.0;
+        };
+    }
+}
\ No newline at end of file
diff --git a/src/storm-gspn/storage/gspn/Transition.h b/src/storm-gspn/storage/gspn/Transition.h
index d61affaea..9deab2fb0 100644
--- a/src/storm-gspn/storage/gspn/Transition.h
+++ b/src/storm-gspn/storage/gspn/Transition.h
@@ -168,6 +168,9 @@ namespace storm {
             void setID(uint64_t const& id) {
                 this->id = id;
             }
+            
+            
+            uint64_t getID() const { return id; }
         private:
 
             // maps place ids connected to this transition with an input arc to the corresponding multiplicity
diff --git a/src/storm-gspn/storm-gspn.h b/src/storm-gspn/storm-gspn.h
new file mode 100644
index 000000000..63b0746f1
--- /dev/null
+++ b/src/storm-gspn/storm-gspn.h
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "storm/storage/jani/Model.h"
+
+#include "storm-gspn/builder/JaniGSPNBuilder.h"
+#include "storm-gspn/storage/gspn/GSPN.h"
+
+#include "storm/settings/modules/GSPNExportSettings.h"
+
+namespace storm {
+    /**
+     *    Builds JANI model from GSPN.
+     */
+    storm::jani::Model* buildJani(storm::gspn::GSPN const& gspn) {
+        std::shared_ptr<storm::expressions::ExpressionManager> exprManager(new storm::expressions::ExpressionManager());
+        storm::builder::JaniGSPNBuilder builder(gspn, exprManager);
+        return builder.build();
+    }
+    
+    void handleGSPNExportSettings(storm::gspn::GSPN const& gspn) {
+        storm::settings::modules::GSPNExportSettings const& exportSettings = storm::settings::getModule<storm::settings::modules::GSPNExportSettings>();
+        if (exportSettings.isWriteToDotSet()) {
+            std::ofstream fs;
+            fs.open(exportSettings.getWriteToDotFilename());
+            gspn.writeDotToStream(fs);
+            fs.close();
+        }
+        
+        if (exportSettings.isWriteToPnproSet()) {
+            std::ofstream fs;
+            fs.open(exportSettings.getWriteToPnproFilename());
+            gspn.toPnpro(fs);
+            fs.close();
+        }
+        
+        if (exportSettings.isWriteToPnmlSet()) {
+            std::ofstream fs;
+            fs.open(exportSettings.getWriteToPnmlFilename());
+            gspn.toPnml(fs);
+            fs.close();
+        }
+        
+        if (exportSettings.isDisplayStatsSet()) {
+            std::cout << "============GSPN Statistics==============" << std::endl;
+            gspn.writeStatsToStream(std::cout);
+            std::cout << "=========================================" << std::endl;
+        }
+        
+        if (exportSettings.isWriteStatsToFileSet()) {
+            std::ofstream fs;
+            fs.open(exportSettings.getWriteStatsFilename());
+            gspn.writeStatsToStream(fs);
+            fs.close();
+        }
+        
+        
+        
+    }
+    
+}
\ No newline at end of file
diff --git a/src/storm/cli/cli.cpp b/src/storm/cli/cli.cpp
index 7ba6cc09e..cfa8c66d1 100644
--- a/src/storm/cli/cli.cpp
+++ b/src/storm/cli/cli.cpp
@@ -12,7 +12,7 @@
 #include "storm/settings/modules/JaniExportSettings.h"
 
 #include "storm/utility/storm-version.h"
-#include "storm/storage/jani/JSONExporter.h"
+
 
 
 // Includes for the linked libraries and versions header.
@@ -253,14 +253,7 @@ namespace storm {
                 }
                 
                 if (model.isJaniModel() && storm::settings::getModule<storm::settings::modules::JaniExportSettings>().isJaniFileSet()) {
-                    STORM_LOG_TRACE("Exporting JANI model.");
-                    if (storm::settings::getModule<storm::settings::modules::JaniExportSettings>().isExportAsStandardJaniSet()) {
-                        storm::jani::Model normalisedModel = storm::jani::Model(model.asJaniModel());
-                        normalisedModel.makeStandardJaniCompliant();
-                        storm::jani::JsonExporter::toFile(normalisedModel, formulasInProperties(properties), storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
-                    } else {
-                        storm::jani::JsonExporter::toFile(model.asJaniModel(), formulasInProperties(properties), storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
-                    }
+                    exportJaniModel(model.asJaniModel(), properties, storm::settings::getModule<storm::settings::modules::JaniExportSettings>().getJaniFilename());
                 }
                 
                 if (ioSettings.isNoBuildModelSet()) {
diff --git a/src/storm/generator/NextStateGenerator.cpp b/src/storm/generator/NextStateGenerator.cpp
index 588edb70a..7f931051f 100644
--- a/src/storm/generator/NextStateGenerator.cpp
+++ b/src/storm/generator/NextStateGenerator.cpp
@@ -119,7 +119,7 @@ namespace storm {
                             result.getChoices().front().add(choice);
                             
                             // Swap the choice to the end to indicate it can be removed (if it's not already there).
-                            if (index != result.getNumberOfChoices() - 1) {
+                            if (index != result.getNumberOfChoices() - 1 - numberOfChoicesToDelete) {
                                 choice = std::move(result.getChoices()[result.getNumberOfChoices() - 1 - numberOfChoicesToDelete]);
                             }
                             ++numberOfChoicesToDelete;
diff --git a/src/storm/settings/modules/GSPNExportSettings.cpp b/src/storm/settings/modules/GSPNExportSettings.cpp
index 9be15c75e..8a5c315dc 100644
--- a/src/storm/settings/modules/GSPNExportSettings.cpp
+++ b/src/storm/settings/modules/GSPNExportSettings.cpp
@@ -19,6 +19,8 @@ namespace storm {
             
             const std::string GSPNExportSettings::writeToPnmlOptionName = "to-pnml";
             const std::string GSPNExportSettings::writeToPnproOptionName = "to-pnpro";
+            const std::string GSPNExportSettings::writeStatsOptionName = "to-stats";
+            const std::string GSPNExportSettings::displayStatsOptionName = "show-stats";
             
             //const std::string GSPNExportSettings::janiFileOptionShortName = "dotoutput";
             
@@ -27,6 +29,8 @@ namespace storm {
                 this->addOption(storm::settings::OptionBuilder(moduleName, writeToDotOptionName, false, "Destination for the dot output.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, writeToPnmlOptionName, false, "Destination for the pnml output").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build());
                 this->addOption(storm::settings::OptionBuilder(moduleName, writeToPnproOptionName, false, "Destination for the pnpro output").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build());
+                this->addOption(storm::settings::OptionBuilder(moduleName, writeStatsOptionName, false, "Destination for the stats file").addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "path to file").build()).build());
+                this->addOption(storm::settings::OptionBuilder(moduleName, displayStatsOptionName, false, "Print stats to stdout").build());
             }
             
             bool GSPNExportSettings::isWriteToDotSet() const {
@@ -54,6 +58,18 @@ namespace storm {
             }
             
             
+            bool GSPNExportSettings::isDisplayStatsSet() const {
+                return this->getOption(displayStatsOptionName).getHasOptionBeenSet();
+            }
+            
+            bool GSPNExportSettings::isWriteStatsToFileSet() const {
+                return this->getOption(writeStatsOptionName).getHasOptionBeenSet();
+            }
+            
+            std::string GSPNExportSettings::getWriteStatsFilename() const {
+                return this->getOption(writeStatsOptionName).getArgumentByName("filename").getValueAsString();
+            }
+            
             void GSPNExportSettings::finalize() {
                 
             }
diff --git a/src/storm/settings/modules/GSPNExportSettings.h b/src/storm/settings/modules/GSPNExportSettings.h
index 3db836cf7..554cce223 100644
--- a/src/storm/settings/modules/GSPNExportSettings.h
+++ b/src/storm/settings/modules/GSPNExportSettings.h
@@ -15,7 +15,7 @@ namespace storm {
                 GSPNExportSettings();
                 
                 /**
-                 * Retrievew whether the pgcl file option was set
+                 * Retrieve whether the pgcl file option was set
                  */
                 bool isWriteToDotSet() const;
                 
@@ -38,6 +38,12 @@ namespace storm {
                  */
                 std::string getWriteToPnproFilename() const;
                 
+                bool isDisplayStatsSet() const;
+                
+                bool isWriteStatsToFileSet() const;
+                
+                std::string getWriteStatsFilename() const;
+                
                 
                 bool check() const override;
                 void finalize() override;
@@ -48,6 +54,9 @@ namespace storm {
                 static const std::string writeToDotOptionName;
                 static const std::string writeToPnmlOptionName;
                 static const std::string writeToPnproOptionName;
+                static const std::string displayStatsOptionName;
+                static const std::string writeStatsOptionName;
+                
                 //static const std::string writeToDotOptionShortName;
                 
             };
diff --git a/src/storm/storage/BitVector.cpp b/src/storm/storage/BitVector.cpp
index 89113d718..a0004263a 100644
--- a/src/storm/storage/BitVector.cpp
+++ b/src/storm/storage/BitVector.cpp
@@ -486,7 +486,7 @@ namespace storm {
         
         void BitVector::setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value) {
             STORM_LOG_ASSERT(numberOfBits <= 64, "Number of bits must be <= 64.");
-            STORM_LOG_ASSERT(numberOfBits == 64 || (value >> numberOfBits) == 0, "Integer value too large to fit in the given number of bits.");
+            STORM_LOG_ASSERT(numberOfBits == 64 || (value >> numberOfBits) == 0, "Integer value ("<< value << ") too large to fit in the given number of bits (" << numberOfBits << ").");
 
             uint64_t bucket = bitIndex >> 6;
             uint64_t bitIndexInBucket = bitIndex & mod64mask;
diff --git a/src/storm/storage/expressions/Expression.cpp b/src/storm/storage/expressions/Expression.cpp
index 9dbd46986..c9ca8a320 100644
--- a/src/storm/storage/expressions/Expression.cpp
+++ b/src/storm/storage/expressions/Expression.cpp
@@ -235,6 +235,12 @@ namespace storm {
         
         Expression operator&&(Expression const& first, Expression const& second) {
             assertSameManager(first.getBaseExpression(), second.getBaseExpression());
+            if (first.isTrue()) {
+                return second;
+            }
+            if (second.isTrue()) {
+                return first;
+            }
             return Expression(std::shared_ptr<BaseExpression>(new BinaryBooleanFunctionExpression(first.getBaseExpression().getManager(), first.getType().logicalConnective(second.getType()), first.getBaseExpressionPointer(), second.getBaseExpressionPointer(), BinaryBooleanFunctionExpression::OperatorType::And)));
         }
         
diff --git a/src/storm/storage/jani/JSONExporter.cpp b/src/storm/storage/jani/JSONExporter.cpp
index 7548fd323..889496265 100644
--- a/src/storm/storage/jani/JSONExporter.cpp
+++ b/src/storm/storage/jani/JSONExporter.cpp
@@ -516,7 +516,7 @@ namespace storm {
         
         
         
-        void JsonExporter::toFile(storm::jani::Model const& janiModel, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::string const& filepath, bool checkValid) {
+        void JsonExporter::toFile(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& formulas, std::string const& filepath, bool checkValid) {
             std::ofstream ofs;
             ofs.open (filepath, std::ofstream::out );
             if(ofs.is_open()) {
@@ -526,7 +526,7 @@ namespace storm {
             }
         }
         
-        void JsonExporter::toStream(storm::jani::Model const& janiModel,  std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::ostream& os, bool checkValid) {
+        void JsonExporter::toStream(storm::jani::Model const& janiModel,  std::vector<storm::jani::Property> const& formulas, std::ostream& os, bool checkValid) {
             if(checkValid) {
                 janiModel.checkValid();
             }
@@ -759,13 +759,13 @@ namespace storm {
         }
         
         
-        void JsonExporter::convertProperties( std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, storm::jani::Model const& model) {
+        void JsonExporter::convertProperties( std::vector<storm::jani::Property> const& formulas, storm::jani::Model const& model) {
             std::vector<modernjson::json> properties;
             uint64_t index = 0;
             for(auto const& f : formulas) {
                 modernjson::json propDecl;
-                propDecl["name"] = "prop" + std::to_string(index);
-                propDecl["expression"] = convertFilterExpression(storm::jani::FilterExpression(f), model);
+                propDecl["name"] = f.getName();
+                propDecl["expression"] = convertFilterExpression(f.getFilter(), model);
                 ++index;
                 properties.push_back(propDecl);
             }
diff --git a/src/storm/storage/jani/JSONExporter.h b/src/storm/storage/jani/JSONExporter.h
index 1008ec097..1eceb5d2e 100644
--- a/src/storm/storage/jani/JSONExporter.h
+++ b/src/storm/storage/jani/JSONExporter.h
@@ -4,6 +4,7 @@
 #include "storm/storage/expressions/ExpressionVisitor.h"
 #include "storm/logic/FormulaVisitor.h"
 #include "Model.h"
+#include "storm/storage/jani/Property.h"
 #include "storm/adapters/NumberAdapter.h"
 // JSON parser
 #include "json.hpp"
@@ -66,12 +67,13 @@ namespace storm {
             JsonExporter() = default;
             
         public:
-            static void toFile(storm::jani::Model const& janiModel, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::string const& filepath, bool checkValid = true);
-            static void toStream(storm::jani::Model const& janiModel, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, std::ostream& ostream, bool checkValid = false);
+            static void toFile(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& formulas, std::string const& filepath, bool checkValid = true);
+            static void toStream(storm::jani::Model const& janiModel, std::vector<storm::jani::Property> const& formulas, std::ostream& ostream, bool checkValid = false);
+            
             
         private:
             void convertModel(storm::jani::Model const& model);
-            void convertProperties(std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas, storm::jani::Model const& model);
+            void convertProperties(std::vector<storm::jani::Property> const& formulas, storm::jani::Model const& model);
             void appendVariableDeclaration(storm::jani::Variable const& variable);
             
             modernjson::json finalize() {
diff --git a/src/storm/storage/jani/OrderedAssignments.cpp b/src/storm/storage/jani/OrderedAssignments.cpp
index 667952719..18f0aebae 100644
--- a/src/storm/storage/jani/OrderedAssignments.cpp
+++ b/src/storm/storage/jani/OrderedAssignments.cpp
@@ -141,5 +141,14 @@ namespace storm {
             return std::lower_bound(assignments.begin(), assignments.end(), assignment, storm::jani::AssignmentPartialOrderByLevelAndVariable());
         }
         
+        std::ostream& operator<<(std::ostream& stream, OrderedAssignments const& assignments) {
+            stream << "[";
+            for(auto const& e : assignments.allAssignments) {
+                stream << *e << std::endl;
+            }
+            stream << "]";
+            return stream;
+        }
+        
     }
 }
diff --git a/src/storm/storage/jani/OrderedAssignments.h b/src/storm/storage/jani/OrderedAssignments.h
index 789b1014a..999b9d95f 100644
--- a/src/storm/storage/jani/OrderedAssignments.h
+++ b/src/storm/storage/jani/OrderedAssignments.h
@@ -109,6 +109,8 @@ namespace storm {
              */
             void substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution);
 
+            friend std::ostream& operator<<(std::ostream& stream, OrderedAssignments const& assignments);
+            
         private:
             static std::vector<std::shared_ptr<Assignment>>::const_iterator lowerBound(Assignment const& assignment, std::vector<std::shared_ptr<Assignment>> const& assignments);
                         
diff --git a/src/storm/utility/storm.cpp b/src/storm/utility/storm.cpp
index 40ab41b91..9a0e6faba 100644
--- a/src/storm/utility/storm.cpp
+++ b/src/storm/utility/storm.cpp
@@ -30,6 +30,17 @@ namespace storm{
         modelAndFormulae.first.checkValid();
         return modelAndFormulae;
     }
+    
+    void exportJaniModel(storm::jani::Model const& model, std::vector<storm::jani::Property> const& properties, std::string const& filepath) {
+        STORM_LOG_TRACE("Exporting JANI model.");
+        if (storm::settings::getModule<storm::settings::modules::JaniExportSettings>().isExportAsStandardJaniSet()) {
+            storm::jani::Model normalisedModel = model;
+            normalisedModel.makeStandardJaniCompliant();
+            storm::jani::JsonExporter::toFile(normalisedModel, properties, filepath);
+        } else {
+            storm::jani::JsonExporter::toFile(model, properties, filepath);
+        }
+    }
 
     /**
      * Helper
diff --git a/src/storm/utility/storm.h b/src/storm/utility/storm.h
index cee49998b..343832e00 100644
--- a/src/storm/utility/storm.h
+++ b/src/storm/utility/storm.h
@@ -23,6 +23,7 @@
 #include "storm/settings/modules/RegionSettings.h"
 #include "storm/settings/modules/EliminationSettings.h"
 #include "storm/settings/modules/JitBuilderSettings.h"
+#include "storm/settings/modules/JaniExportSettings.h"
 
 // Formula headers.
 #include "storm/logic/Formulas.h"
@@ -55,6 +56,7 @@
 #include "storm/storage/bisimulation/NondeterministicModelBisimulationDecomposition.h"
 #include "storm/storage/ModelFormulasPair.h"
 #include "storm/storage/SymbolicModelDescription.h"
+#include "storm/storage/jani/JSONExporter.h"
 
 // Headers for model checking.
 #include "storm/modelchecker/prctl/SparseDtmcPrctlModelChecker.h"
@@ -225,6 +227,7 @@ namespace storm {
     std::shared_ptr<storm::models::ModelBase> preprocessModel(std::shared_ptr<storm::models::ModelBase> model, std::vector<std::shared_ptr<storm::logic::Formula const>> const& formulas) {
         if (model->getType() == storm::models::ModelType::MarkovAutomaton && model->isSparseModel()) {
             std::shared_ptr<storm::models::sparse::MarkovAutomaton<typename ModelType::ValueType>> ma = model->template as<storm::models::sparse::MarkovAutomaton<typename ModelType::ValueType>>();
+            ma->close();
             if (ma->hasOnlyTrivialNondeterminism()) {
                 // Markov automaton can be converted into CTMC.
                 model = ma->convertToCTMC();
@@ -575,7 +578,13 @@ namespace storm {
         }
         return result;
     }
-
+    
+    
+    /**
+     *
+     */
+    void exportJaniModel(storm::jani::Model const& model, std::vector<storm::jani::Property> const& properties, std::string const& filepath);
+    
     template<typename ValueType>
     void exportMatrixToFile(std::shared_ptr<storm::models::sparse::Model<ValueType>> model, std::string const& filepath) {
         STORM_LOG_THROW(model->getType() != storm::models::ModelType::Ctmc, storm::exceptions::NotImplementedException, "This functionality is not yet implemented." );