Browse Source
			
			
			Merge branch 'rewards_in_jani' into jani_support
			
				
		Merge branch 'rewards_in_jani' into jani_support
	
		
	
			
				Former-commit-id:main223c63b543[formerly5a8bf98651] Former-commit-id:db35c1c439
				 35 changed files with 1480 additions and 770 deletions
			
			
		- 
					1197src/builder/DdJaniModelBuilder.cpp
 - 
					4src/builder/DdPrismModelBuilder.cpp
 - 
					4src/builder/ExplicitModelBuilder.cpp
 - 
					35src/generator/Choice.cpp
 - 
					19src/generator/Choice.h
 - 
					33src/generator/JaniNextStateGenerator.cpp
 - 
					3src/generator/JaniNextStateGenerator.h
 - 
					12src/generator/PrismNextStateGenerator.cpp
 - 
					2src/storage/dd/Dd.cpp
 - 
					4src/storage/dd/Dd.h
 - 
					8src/storage/jani/Automaton.cpp
 - 
					7src/storage/jani/Automaton.h
 - 
					144src/storage/jani/CompositionActionInformationVisitor.cpp
 - 
					50src/storage/jani/CompositionActionInformationVisitor.h
 - 
					77src/storage/jani/CompositionInformationVisitor.cpp
 - 
					10src/storage/jani/CompositionInformationVisitor.h
 - 
					6src/storage/jani/Model.cpp
 - 
					5src/storage/jani/Model.h
 - 
					122src/storage/jani/ParallelComposition.cpp
 - 
					78src/storage/jani/ParallelComposition.h
 - 
					2src/storage/prism/ToJaniConverter.cpp
 - 
					4src/storage/sparse/StateValuations.cpp
 - 
					4src/storage/sparse/StateValuations.h
 - 
					59test/functional/builder/DdJaniModelBuilderTest.cpp
 - 
					127test/functional/builder/DdPrismModelBuilderTest.cpp
 - 
					27test/functional/builder/SmallPrismTest.nm
 - 
					25test/functional/modelchecker/GmmxxHybridCtmcCslModelCheckerTest.cpp
 - 
					31test/functional/modelchecker/GmmxxHybridDtmcPrctlModelCheckerTest.cpp
 - 
					21test/functional/modelchecker/GmmxxHybridMdpPrctlModelCheckerTest.cpp
 - 
					25test/functional/modelchecker/NativeHybridCtmcCslModelCheckerTest.cpp
 - 
					21test/functional/modelchecker/NativeHybridDtmcPrctlModelCheckerTest.cpp
 - 
					13test/functional/modelchecker/NativeHybridMdpPrctlModelCheckerTest.cpp
 - 
					19test/functional/modelchecker/SymbolicDtmcPrctlModelCheckerTest.cpp
 - 
					13test/functional/modelchecker/SymbolicMdpPrctlModelCheckerTest.cpp
 - 
					39test/functional/utility/GraphTest.cpp
 
						
							
						
						
							1197
	
						
						src/builder/DdJaniModelBuilder.cpp
						
							File diff suppressed because it is too large
							
							
								
									View File
								
							
						
					
				File diff suppressed because it is too large
							
							
								
									View File
								
							
						@ -0,0 +1,144 @@ | 
				
			|||
#include "src/storage/jani/CompositionActionInformationVisitor.h"
 | 
				
			|||
 | 
				
			|||
#include "src/storage/jani/Model.h"
 | 
				
			|||
#include "src/storage/jani/Compositions.h"
 | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
    namespace jani { | 
				
			|||
         | 
				
			|||
        ActionInformation::ActionInformation(std::set<uint64_t> const& nonsilentActionIndices, std::map<uint64_t, std::string> const& indexToNameMap, std::map<std::string, uint64_t> const& nameToIndexMap, uint64_t silentActionIndex) : silentActionIndex(silentActionIndex), nonsilentActionIndices(nonsilentActionIndices), indexToNameMap(indexToNameMap), nameToIndexMap(nameToIndexMap) { | 
				
			|||
            // Intentionally left empty.
 | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::string const& ActionInformation::getActionName(uint64_t index) const { | 
				
			|||
            return indexToNameMap.at(index); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint64_t ActionInformation::getActionIndex(std::string const& name) const { | 
				
			|||
            return nameToIndexMap.at(name); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::set<uint64_t> const& ActionInformation::getNonSilentActionIndices() const { | 
				
			|||
            return nonsilentActionIndices; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint64_t ActionInformation::getSilentActionIndex() const { | 
				
			|||
            return silentActionIndex; | 
				
			|||
        } | 
				
			|||
      | 
				
			|||
        CompositionActionInformationVisitor::CompositionActionInformationVisitor(storm::jani::Model const& model) : model(model), nextFreeActionIndex(0), nameToIndexMap(), indexToNameMap() { | 
				
			|||
            // Intentionally left empty.
 | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        ActionInformation CompositionActionInformationVisitor::getActionInformation() { | 
				
			|||
            indexToNameMap.clear(); | 
				
			|||
            nameToIndexMap.clear(); | 
				
			|||
 | 
				
			|||
            // Determine the next free index we can give out to a new action.
 | 
				
			|||
            for (auto const& action : model.getActions()) { | 
				
			|||
                uint64_t actionIndex = model.getActionIndex(action.getName()); | 
				
			|||
                 | 
				
			|||
                nameToIndexMap[action.getName()] = model.getActionIndex(action.getName()); | 
				
			|||
                indexToNameMap[actionIndex] = action.getName(); | 
				
			|||
 | 
				
			|||
                nextFreeActionIndex = std::max(nextFreeActionIndex, model.getActionIndex(action.getName())); | 
				
			|||
            } | 
				
			|||
            ++nextFreeActionIndex; | 
				
			|||
             | 
				
			|||
            std::set<uint64_t> nonSilentActionIndices = boost::any_cast<std::set<uint64_t>>(model.getSystemComposition().accept(*this, boost::none)); | 
				
			|||
             | 
				
			|||
            return ActionInformation(nonSilentActionIndices, indexToNameMap, nameToIndexMap); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        boost::any CompositionActionInformationVisitor::visit(AutomatonComposition const& composition, boost::any const& data) { | 
				
			|||
            std::set<uint64_t> result = model.getAutomaton(composition.getAutomatonName()).getUsedActionIndices(); | 
				
			|||
            result.erase(model.getSilentActionIndex()); | 
				
			|||
            return result; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        boost::any CompositionActionInformationVisitor::visit(RenameComposition const& composition, boost::any const& data) { | 
				
			|||
            std::set<uint64_t> usedActions = boost::any_cast<std::set<uint64_t>>(composition.getSubcomposition().accept(*this, boost::none)); | 
				
			|||
             | 
				
			|||
            std::set<uint64_t> newUsedActions; | 
				
			|||
            for (auto const& index : usedActions) { | 
				
			|||
                auto renamingIt = composition.getRenaming().find(indexToNameMap.at(index)); | 
				
			|||
                if (renamingIt != composition.getRenaming().end()) { | 
				
			|||
                    if (renamingIt->second) { | 
				
			|||
                        newUsedActions.insert(addOrGetActionIndex(renamingIt->second.get())); | 
				
			|||
 | 
				
			|||
                        auto actionIndexIt = nameToIndexMap.find(renamingIt->second.get()); | 
				
			|||
                        if (actionIndexIt != nameToIndexMap.end()) { | 
				
			|||
                            newUsedActions.insert(actionIndexIt->second); | 
				
			|||
                        } else { | 
				
			|||
                            nameToIndexMap[renamingIt->second.get()] = nextFreeActionIndex; | 
				
			|||
                            indexToNameMap[nextFreeActionIndex] = renamingIt->second.get(); | 
				
			|||
                            ++nextFreeActionIndex; | 
				
			|||
                        } | 
				
			|||
                    } | 
				
			|||
                } else { | 
				
			|||
                    newUsedActions.insert(index); | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            return newUsedActions; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        boost::any CompositionActionInformationVisitor::visit(ParallelComposition const& composition, boost::any const& data) { | 
				
			|||
            std::vector<std::set<uint64_t>> subresults; | 
				
			|||
            for (auto const& subcomposition : composition.getSubcompositions()) { | 
				
			|||
                subresults.push_back(boost::any_cast<std::set<uint64_t>>(subcomposition->accept(*this, boost::none))); | 
				
			|||
            } | 
				
			|||
 | 
				
			|||
            std::set<uint64_t> effectiveSynchronizationVectors; | 
				
			|||
            for (uint64_t index = 0; index < composition.getNumberOfSynchronizationVectors(); ++index) { | 
				
			|||
                effectiveSynchronizationVectors.insert(index); | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            // Determine all actions that do not take part in synchronization vectors.
 | 
				
			|||
            std::set<uint64_t> result; | 
				
			|||
            for (uint64_t subresultIndex = 0; subresultIndex < subresults.size(); ++subresultIndex) { | 
				
			|||
                 | 
				
			|||
                std::set<uint64_t> actionsInSynch; | 
				
			|||
                std::set<uint64_t> localEffectiveSynchVectors; | 
				
			|||
                for (uint64_t synchVectorIndex = 0; synchVectorIndex < composition.getNumberOfSynchronizationVectors(); ++synchVectorIndex) { | 
				
			|||
                    auto const& synchVector = composition.getSynchronizationVector(synchVectorIndex); | 
				
			|||
                    uint64_t synchVectorActionIndex = nameToIndexMap.at(synchVector.getInput(subresultIndex)); | 
				
			|||
                    actionsInSynch.insert(synchVectorActionIndex); | 
				
			|||
                     | 
				
			|||
                    // If the action of they synchronization vector at this position is one that is actually contained
 | 
				
			|||
                    // in the corresponding subcomposition, the synchronization vector is effective.
 | 
				
			|||
                    if (subresults[subresultIndex].find(synchVectorActionIndex) != subresults[subresultIndex].end()) { | 
				
			|||
                        effectiveSynchronizationVectors.insert(synchVectorIndex); | 
				
			|||
                    } | 
				
			|||
                } | 
				
			|||
                 | 
				
			|||
                std::set_difference(subresults[subresultIndex].begin(), subresults[subresultIndex].end(), actionsInSynch.begin(), actionsInSynch.end(), std::inserter(result, result.begin())); | 
				
			|||
                 | 
				
			|||
                // Intersect the previously effective synchronization vectors with the ones that were derived to be
 | 
				
			|||
                // effective for the current subcomposition.
 | 
				
			|||
                std::set<uint64_t> newEffectiveSynchVectors; | 
				
			|||
                std::set_intersection(effectiveSynchronizationVectors.begin(), effectiveSynchronizationVectors.end(), newEffectiveSynchVectors.begin(), newEffectiveSynchVectors.end(), std::inserter(newEffectiveSynchVectors, newEffectiveSynchVectors.begin())); | 
				
			|||
                effectiveSynchronizationVectors = std::move(newEffectiveSynchVectors); | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            // Now add all outputs of synchronization vectors.
 | 
				
			|||
            for (auto const& synchVector : composition.getSynchronizationVectors()) { | 
				
			|||
                result.insert(addOrGetActionIndex(synchVector.getOutput())); | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            return result; | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        uint64_t CompositionActionInformationVisitor::addOrGetActionIndex(std::string const& name) { | 
				
			|||
            auto it = nameToIndexMap.find(name); | 
				
			|||
            if (it != nameToIndexMap.end()) { | 
				
			|||
                return it->second; | 
				
			|||
            } else { | 
				
			|||
                nameToIndexMap[name] = nextFreeActionIndex; | 
				
			|||
                indexToNameMap[nextFreeActionIndex] = name; | 
				
			|||
                return nextFreeActionIndex++; | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,50 @@ | 
				
			|||
#pragma once | 
				
			|||
 | 
				
			|||
#include <set> | 
				
			|||
#include <map> | 
				
			|||
 | 
				
			|||
#include "src/storage/jani/CompositionVisitor.h" | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
    namespace jani { | 
				
			|||
         | 
				
			|||
        class Model; | 
				
			|||
         | 
				
			|||
        class ActionInformation { | 
				
			|||
        public: | 
				
			|||
            ActionInformation(std::set<uint64_t> const& nonsilentActionIndices, std::map<uint64_t, std::string> const& indexToNameMap, std::map<std::string, uint64_t> const& nameToIndexMap, uint64_t silentActionIndex = 0); | 
				
			|||
             | 
				
			|||
            std::string const& getActionName(uint64_t index) const; | 
				
			|||
            uint64_t getActionIndex(std::string const& name) const; | 
				
			|||
            std::set<uint64_t> const& getNonSilentActionIndices() const; | 
				
			|||
            uint64_t getSilentActionIndex() const; | 
				
			|||
             | 
				
			|||
        private: | 
				
			|||
            uint64_t silentActionIndex; | 
				
			|||
            std::set<uint64_t> nonsilentActionIndices; | 
				
			|||
            std::map<uint64_t, std::string> indexToNameMap; | 
				
			|||
            std::map<std::string, uint64_t> nameToIndexMap; | 
				
			|||
        }; | 
				
			|||
         | 
				
			|||
        class CompositionActionInformationVisitor : public CompositionVisitor { | 
				
			|||
        public: | 
				
			|||
            CompositionActionInformationVisitor(storm::jani::Model const& model); | 
				
			|||
             | 
				
			|||
            ActionInformation getActionInformation(); | 
				
			|||
             | 
				
			|||
            virtual boost::any visit(AutomatonComposition const& composition, boost::any const& data) override; | 
				
			|||
            virtual boost::any visit(RenameComposition const& composition, boost::any const& data) override; | 
				
			|||
            virtual boost::any visit(ParallelComposition const& composition, boost::any const& data) override; | 
				
			|||
             | 
				
			|||
        private: | 
				
			|||
            uint64_t addOrGetActionIndex(std::string const& name); | 
				
			|||
             | 
				
			|||
            storm::jani::Model const& model; | 
				
			|||
            uint64_t nextFreeActionIndex; | 
				
			|||
            std::map<std::string, uint64_t> nameToIndexMap; | 
				
			|||
            std::map<uint64_t, std::string> indexToNameMap; | 
				
			|||
        }; | 
				
			|||
 | 
				
			|||
         | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -1,32 +1,138 @@ | 
				
			|||
#include "src/storage/jani/ParallelComposition.h"
 | 
				
			|||
 | 
				
			|||
#include <sstream>
 | 
				
			|||
 | 
				
			|||
#include <boost/algorithm/string/join.hpp>
 | 
				
			|||
 | 
				
			|||
#include "src/utility/macros.h"
 | 
				
			|||
#include "src/exceptions/WrongFormatException.h"
 | 
				
			|||
 | 
				
			|||
namespace storm { | 
				
			|||
    namespace jani { | 
				
			|||
         | 
				
			|||
        ParallelComposition::ParallelComposition(std::shared_ptr<Composition> const& leftSubcomposition, std::shared_ptr<Composition> const& rightSubcomposition, std::set<std::string> const& alphabet) : leftSubcomposition(leftSubcomposition), rightSubcomposition(rightSubcomposition), alphabet(alphabet) { | 
				
			|||
        SynchronizationVector::SynchronizationVector(std::vector<std::string> const& input, std::string const& output) : input(input), output(output) { | 
				
			|||
            // Intentionally left empty.
 | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Composition const& ParallelComposition::getLeftSubcomposition() const { | 
				
			|||
            return *leftSubcomposition; | 
				
			|||
        std::size_t SynchronizationVector::size() const { | 
				
			|||
            return input.size(); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::vector<std::string> const& SynchronizationVector::getInput() const { | 
				
			|||
            return input; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::string const& SynchronizationVector::getInput(uint64_t index) const { | 
				
			|||
            return input[index]; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::string const& SynchronizationVector::getOutput() const { | 
				
			|||
            return output; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Composition const& ParallelComposition::getRightSubcomposition() const { | 
				
			|||
            return *rightSubcomposition; | 
				
			|||
        std::ostream& operator<<(std::ostream& stream, SynchronizationVector const& synchronizationVector) { | 
				
			|||
            bool first = true; | 
				
			|||
            stream << "("; | 
				
			|||
            for (auto const& element : synchronizationVector.getInput()) { | 
				
			|||
                if (!first) { | 
				
			|||
                    stream << ", "; | 
				
			|||
                } | 
				
			|||
                stream << element; | 
				
			|||
            } | 
				
			|||
            stream << ") -> " << synchronizationVector.getOutput(); | 
				
			|||
            return stream; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::set<std::string> const& ParallelComposition::getSynchronizationAlphabet() const { | 
				
			|||
            return alphabet; | 
				
			|||
        ParallelComposition::ParallelComposition(std::vector<std::shared_ptr<Composition>> const& subcompositions, std::vector<SynchronizationVector> const& synchronizationVectors) : subcompositions(subcompositions), synchronizationVectors(synchronizationVectors) { | 
				
			|||
            STORM_LOG_THROW(subcompositions.size() > 1, storm::exceptions::WrongFormatException, "At least two automata required for parallel composition."); | 
				
			|||
 | 
				
			|||
            for (auto const& vector : this->synchronizationVectors) { | 
				
			|||
                STORM_LOG_THROW(vector.size() == this->subcompositions.size(), storm::exceptions::WrongFormatException, "Synchronization vectors must match parallel composition size."); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        ParallelComposition::ParallelComposition(std::vector<std::shared_ptr<Composition>> const& subcompositions, std::set<std::string> const& synchronizationAlphabet) : subcompositions(subcompositions), synchronizationVectors() { | 
				
			|||
            STORM_LOG_THROW(subcompositions.size() > 1, storm::exceptions::WrongFormatException, "At least two automata required for parallel composition."); | 
				
			|||
 | 
				
			|||
            // Manually construct the synchronization vectors for all elements of the synchronization alphabet.
 | 
				
			|||
            for (auto const& action : synchronizationAlphabet) { | 
				
			|||
                synchronizationVectors.emplace_back(std::vector<std::string>(this->subcompositions.size(), action), action); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        ParallelComposition::ParallelComposition(std::shared_ptr<Composition> const& leftSubcomposition, std::shared_ptr<Composition> const& rightSubcomposition, std::set<std::string> const& synchronizationAlphabet) { | 
				
			|||
            subcompositions.push_back(leftSubcomposition); | 
				
			|||
            subcompositions.push_back(rightSubcomposition); | 
				
			|||
             | 
				
			|||
            // Manually construct the synchronization vectors for all elements of the synchronization alphabet.
 | 
				
			|||
            for (auto const& action : synchronizationAlphabet) { | 
				
			|||
                synchronizationVectors.emplace_back(std::vector<std::string>(this->subcompositions.size(), action), action); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        Composition const& ParallelComposition::getSubcomposition(uint64_t index) const { | 
				
			|||
            return *subcompositions[index]; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::vector<std::shared_ptr<Composition>> const& ParallelComposition::getSubcompositions() const { | 
				
			|||
            return subcompositions; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        uint64_t ParallelComposition::getNumberOfSubcompositions() const { | 
				
			|||
            return subcompositions.size(); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        SynchronizationVector const& ParallelComposition::getSynchronizationVector(uint64_t index) const { | 
				
			|||
            return synchronizationVectors[index]; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::vector<SynchronizationVector> const& ParallelComposition::getSynchronizationVectors() const { | 
				
			|||
            return synchronizationVectors; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        std::size_t ParallelComposition::getNumberOfSynchronizationVectors() const { | 
				
			|||
            return synchronizationVectors.size(); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void ParallelComposition::checkSynchronizationVectors() const { | 
				
			|||
            for (uint_fast64_t inputIndex = 0; inputIndex < subcompositions.size(); ++ inputIndex) { | 
				
			|||
                std::set<std::string> actions; | 
				
			|||
                for (auto const& vector : synchronizationVectors) { | 
				
			|||
                    std::string const& action = vector.getInput(inputIndex); | 
				
			|||
                    STORM_LOG_THROW(actions.find(action) == actions.end(), storm::exceptions::WrongFormatException, "Cannot use the same action multiple times as input in synchronization vectors."); | 
				
			|||
                    actions.insert(action); | 
				
			|||
                } | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            std::set<std::string> actions; | 
				
			|||
            for (auto const& vector : synchronizationVectors) { | 
				
			|||
                STORM_LOG_THROW(actions.find(vector.getOutput()) == actions.end(), storm::exceptions::WrongFormatException, "Cannot use the same output action multiple times in synchronization vectors."); | 
				
			|||
                actions.insert(vector.getOutput()); | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        boost::any ParallelComposition::accept(CompositionVisitor& visitor, boost::any const& data) const { | 
				
			|||
            return visitor.visit(*this, data); | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
        void ParallelComposition::write(std::ostream& stream) const { | 
				
			|||
            stream << this->getLeftSubcomposition() << " |[" << boost::algorithm::join(alphabet, ", ") << "]| " << this->getRightSubcomposition(); | 
				
			|||
            std::vector<std::string> synchronizationVectorsAsStrings; | 
				
			|||
            for (auto const& synchronizationVector : synchronizationVectors) { | 
				
			|||
                std::stringstream tmpStream; | 
				
			|||
                tmpStream << synchronizationVector; | 
				
			|||
                synchronizationVectorsAsStrings.push_back(tmpStream.str()); | 
				
			|||
            } | 
				
			|||
             | 
				
			|||
            bool first = true; | 
				
			|||
            stream << "("; | 
				
			|||
            for (auto const& subcomposition : subcompositions) { | 
				
			|||
                if (!first) { | 
				
			|||
                    stream << " || "; | 
				
			|||
                    first = false; | 
				
			|||
                } | 
				
			|||
                stream << *subcomposition; | 
				
			|||
            } | 
				
			|||
            stream << ")[" << boost::algorithm::join(synchronizationVectorsAsStrings, ", ") << "]"; | 
				
			|||
        } | 
				
			|||
         | 
				
			|||
    } | 
				
			|||
@ -0,0 +1,27 @@ | 
				
			|||
mdp | 
				
			|||
 | 
				
			|||
module one | 
				
			|||
	s1 : [0 .. 3]; | 
				
			|||
 | 
				
			|||
	[a] s1=0 -> (s1'=1); | 
				
			|||
 | 
				
			|||
	[c] s1=1 -> (s1'=2); | 
				
			|||
 | 
				
			|||
	[d] s1=1 -> (s1'=3); | 
				
			|||
endmodule | 
				
			|||
 | 
				
			|||
module two | 
				
			|||
	s2 : [0 .. 2]; | 
				
			|||
 | 
				
			|||
	[b] s2=0 -> (s2'=1); | 
				
			|||
 | 
				
			|||
	[c] s2=1 -> (s2'=2); | 
				
			|||
endmodule | 
				
			|||
 | 
				
			|||
module three | 
				
			|||
	s3 : [0 .. 1]; | 
				
			|||
 | 
				
			|||
	[c] s3=0 -> (s3'=1); | 
				
			|||
endmodule | 
				
			|||
 | 
				
			|||
// (one || two || three)[(a, b, c) -> d, (c, c, a) -> a] | 
				
			|||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue