Browse Source
Merge branch 'jani_support' of https://sselab.de/lab9/private/git/storm into jani_support
Merge branch 'jani_support' of https://sselab.de/lab9/private/git/storm into jani_support
Former-commit-id:main340ae66b7c
[formerlyd8d53ddacd
] Former-commit-id:d16ac728bf
35 changed files with 1480 additions and 771 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
-
116src/storage/jani/ParallelComposition.cpp
-
78src/storage/jani/ParallelComposition.h
-
2src/storage/prism/ToJaniConverter.cpp
-
4src/storage/sparse/StateValuations.cpp
-
4src/storage/sparse/StateValuations.h
-
66test/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,33 +1,131 @@ |
|||
#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."); |
|||
this->checkSynchronizationVectors(); |
|||
} |
|||
|
|||
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) { |
|||
STORM_LOG_THROW(vector.size() == this->subcompositions.size(), storm::exceptions::WrongFormatException, "Synchronization vectors must match parallel composition size."); |
|||
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); |
|||
} |
|||
} |
|||
} |
|||
|
|||
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