Browse Source

standard system composition of JANI models now only use synchronization vectors on the topmost level

Former-commit-id: 3c328b05b4 [formerly 5509822ac1]
Former-commit-id: 20ebbd8ee2
tempestpy_adaptions
dehnert 8 years ago
parent
commit
02f545c54d
  1. 25
      src/builder/DdJaniModelBuilder.cpp
  2. 8
      src/storage/jani/Automaton.cpp
  3. 2
      src/storage/jani/CompositionActionInformationVisitor.cpp
  4. 58
      src/storage/jani/Model.cpp
  5. 47
      src/storage/jani/ParallelComposition.cpp
  6. 21
      src/storage/jani/ParallelComposition.h

25
src/builder/DdJaniModelBuilder.cpp

@ -1109,22 +1109,31 @@ namespace storm {
for (uint64_t subcompositionIndex = 0; subcompositionIndex < composition.getNumberOfSubcompositions(); ++subcompositionIndex) {
// Prepare the new offset mapping.
std::map<uint64_t, uint64_t> newSynchronizingActionToOffsetMap = actionIndexToLocalNondeterminismVariableOffset;
if (subcompositionIndex == 0) {
for (auto const& synchVector : composition.getSynchronizationVectors()) {
auto it = actionIndexToLocalNondeterminismVariableOffset.find(actionInformation.getActionIndex(synchVector.getOutput()));
STORM_LOG_THROW(it != actionIndexToLocalNondeterminismVariableOffset.end(), storm::exceptions::InvalidArgumentException, "Invalid action " << synchVector.getOutput() << ".");
newSynchronizingActionToOffsetMap[actionInformation.getActionIndex(synchVector.getInput(0))] = it->second;
if (synchVector.getInput(0) != storm::jani::SynchronizationVector::getNoActionInput()) {
newSynchronizingActionToOffsetMap[actionInformation.getActionIndex(synchVector.getInput(0))] = it->second;
}
}
} else {
AutomatonDd const& previousAutomatonDd = subautomata.back();
// Based on the previous results, we need to update the offsets.
for (auto const& synchVector : composition.getSynchronizationVectors()) {
auto it = previousAutomatonDd.actionIndexToAction.find(actionInformation.getActionIndex(synchVector.getInput(subcompositionIndex - 1)));
if (it != previousAutomatonDd.actionIndexToAction.end()) {
newSynchronizingActionToOffsetMap[actionInformation.getActionIndex(synchVector.getInput(subcompositionIndex))] = it->second.getHighestLocalNondeterminismVariable();
} else {
STORM_LOG_ASSERT(false, "Subcomposition does not have action that is mentioned in parallel composition.");
if (synchVector.getInput(subcompositionIndex) != storm::jani::SynchronizationVector::getNoActionInput()) {
boost::optional<uint64_t> previousActionPosition = synchVector.getPositionOfPrecedingParticipatingAction(subcompositionIndex);
if (previousActionPosition) {
AutomatonDd const& previousAutomatonDd = subautomata[previousActionPosition.get()];
std::string const& previousAction = synchVector.getInput(previousActionPosition.get());
auto it = previousAutomatonDd.actionIndexToAction.find(actionInformation.getActionIndex(previousAction));
if (it != previousAutomatonDd.actionIndexToAction.end()) {
newSynchronizingActionToOffsetMap[actionInformation.getActionIndex(synchVector.getInput(subcompositionIndex))] = it->second.getHighestLocalNondeterminismVariable();
} else {
STORM_LOG_ASSERT(false, "Subcomposition does not have action that is mentioned in parallel composition.");
}
}
}
}
}

8
src/storage/jani/Automaton.cpp

@ -392,14 +392,6 @@ namespace storm {
}
}
std::set<uint64_t> Automaton::getUsedActionIndices() const {
std::set<uint64_t> result;
for (auto const& edge : edges) {
result.insert(edge.getActionIndex());
}
return result;
}
bool Automaton::containsVariablesOnlyInProbabilitiesOrTransientAssignments(std::set<storm::expressions::Variable> const& variables) const {
// Check initial states restriction expression.
if (this->hasInitialStatesRestriction()) {

2
src/storage/jani/CompositionActionInformationVisitor.cpp

@ -51,7 +51,7 @@ namespace storm {
}
boost::any CompositionActionInformationVisitor::visit(AutomatonComposition const& composition, boost::any const& data) {
std::set<uint64_t> result = model.getAutomaton(composition.getAutomatonName()).getUsedActionIndices();
std::set<uint64_t> result = model.getAutomaton(composition.getAutomatonName()).getActionIndices();
result.erase(model.getSilentActionIndex());
return result;
}

58
src/storage/jani/Model.cpp

@ -215,35 +215,45 @@ namespace storm {
}
std::shared_ptr<Composition> Model::getStandardSystemComposition() const {
std::shared_ptr<Composition> current;
current = std::make_shared<AutomatonComposition>(this->automata.front().getName());
std::set<uint64_t> leftHandActionIndices = this->automata.front().getActionIndices();
// If there's just one automaton, we must not use the parallel composition operator.
if (this->getNumberOfAutomata() == 1) {
return std::make_shared<AutomatonComposition>(this->getAutomata().front().getName());
}
for (uint64_t index = 1; index < automata.size(); ++index) {
std::set<uint64_t> newActionIndices = automata[index].getActionIndices();
// Compute the intersection of actions of the left- and right-hand side.
std::set<uint64_t> intersectionActions;
std::set_intersection(leftHandActionIndices.begin(), leftHandActionIndices.end(), newActionIndices.begin(), newActionIndices.end(), std::inserter(intersectionActions, intersectionActions.begin()));
// If the silent action is in the intersection, we remove it since we cannot synchronize over it.
auto it = intersectionActions.find(this->getSilentActionIndex());
if (it != intersectionActions.end()) {
intersectionActions.erase(it);
// Determine the action indices used by each of the automata and create the standard subcompositions.
std::set<uint64_t> allActionIndices;
std::vector<std::set<uint64_t>> automatonActionIndices;
std::vector<std::shared_ptr<Composition>> subcompositions;
for (auto const& automaton : automata) {
automatonActionIndices.push_back(automaton.getActionIndices());
automatonActionIndices.back().erase(silentActionIndex);
allActionIndices.insert(automatonActionIndices.back().begin(), automatonActionIndices.back().end());
subcompositions.push_back(std::make_shared<AutomatonComposition>(automaton.getName()));
}
// Create the standard synchronization vectors: every automaton with that action participates in the
// synchronization.
std::vector<storm::jani::SynchronizationVector> synchVectors;
for (auto actionIndex : allActionIndices) {
std::string const& actionName = this->getAction(actionIndex).getName();
std::vector<std::string> synchVectorInputs;
uint64_t numberOfParticipatingAutomata = 0;
for (auto const& actionIndices : automatonActionIndices) {
if (actionIndices.find(actionIndex) != actionIndices.end()) {
++numberOfParticipatingAutomata;
synchVectorInputs.push_back(actionName);
} else {
synchVectorInputs.push_back(storm::jani::SynchronizationVector::getNoActionInput());
}
}
// Then join the actions to reflect the actions of the new left-hand side.
leftHandActionIndices.insert(newActionIndices.begin(), newActionIndices.end());
// Create the set of strings that represents the actions over which to synchronize.
std::set<std::string> intersectionActionNames;
for (auto const& actionIndex : intersectionActions) {
intersectionActionNames.insert(this->getAction(actionIndex).getName());
// Only add the synchronization vector if there is more than one participating automaton.
if (numberOfParticipatingAutomata > 1) {
synchVectors.push_back(storm::jani::SynchronizationVector(synchVectorInputs, actionName));
}
current = std::make_shared<ParallelComposition>(current, std::make_shared<AutomatonComposition>(automata[index].getName()), intersectionActionNames);
}
return current;
return std::make_shared<ParallelComposition>(subcompositions, synchVectors);
}
Composition const& Model::getSystemComposition() const {

47
src/storage/jani/ParallelComposition.cpp

@ -28,7 +28,7 @@ namespace storm {
return input[index];
}
std::string const& SynchronizationVector::getNoActionInput() const {
std::string const& SynchronizationVector::getNoActionInput() {
return SynchronizationVector::noAction;
}
@ -36,7 +36,36 @@ namespace storm {
return output;
}
bool SynchronizationVector::isNoActionInput(std::string const& action) const {
boost::optional<std::string> SynchronizationVector::getPrecedingParticipatingAction(uint64_t index) const {
boost::optional<uint64_t> position = getPositionOfPrecedingParticipatingAction(index);
if (position) {
return getInput(position.get());
} else {
return boost::none;
}
}
boost::optional<uint64_t> SynchronizationVector::getPositionOfPrecedingParticipatingAction(uint64_t index) const {
if (index == 0) {
return boost::none;
}
uint64_t i = index - 1;
for (; i > 0; --i) {
if (this->getInput(i) != SynchronizationVector::getNoActionInput()) {
return boost::make_optional(i);
}
}
// Check the 0-index.
if (this->getInput(i) != SynchronizationVector::getNoActionInput()) {
return boost::make_optional(i);
}
return boost::none;
}
bool SynchronizationVector::isNoActionInput(std::string const& action) {
return action == noAction;
}
@ -108,8 +137,10 @@ namespace storm {
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);
if (action != SynchronizationVector::getNoActionInput()) {
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);
}
}
}
}
@ -127,15 +158,19 @@ namespace storm {
}
bool first = true;
bool hasSynchVectors = !synchronizationVectors.empty();
stream << "(";
for (auto const& subcomposition : subcompositions) {
if (!first) {
stream << " || ";
stream << (hasSynchVectors ? " || " : " ||| ");
}
stream << *subcomposition;
first = false;
}
stream << ")[" << boost::algorithm::join(synchronizationVectorsAsStrings, ", ") << "]";
stream << ")";
if (hasSynchVectors) {
stream << "[" << boost::algorithm::join(synchronizationVectorsAsStrings, ", ") << "]";
}
}
}

21
src/storage/jani/ParallelComposition.h

@ -5,6 +5,8 @@
#include <vector>
#include <string>
#include <boost/optional.hpp>
#include "src/storage/jani/Composition.h"
namespace storm {
@ -16,12 +18,23 @@ namespace storm {
std::size_t size() const;
std::vector<std::string> const& getInput() const;
std::string const& getNoActionInput() const;
static std::string const& getNoActionInput();
std::string const& getInput(uint64_t index) const;
std::string const& getOutput() const;
bool isNoActionInput(std::string const& action) const;
static bool isNoActionInput(std::string const& action);
/*!
* Retrieves the action name that is the last participating action before the given input index. If there is
* no such action none is returned.
*/
boost::optional<std::string> getPrecedingParticipatingAction(uint64_t index) const;
/*!
* Retrieves the position with the last participating action before the given input index. If there is
* no such action none is returned.
*/
boost::optional<uint64_t> getPositionOfPrecedingParticipatingAction(uint64_t index) const;
private:
// A marker that can be used as one of the inputs. The semantics is that no action of the corresponding
// automaton takes part in the synchronization.

Loading…
Cancel
Save