TimQu
6 years ago
4 changed files with 416 additions and 12 deletions
-
99src/storm/generator/JaniNextStateGenerator.cpp
-
18src/storm/generator/JaniNextStateGenerator.h
-
183src/storm/generator/TransientVariableInformation.cpp
-
124src/storm/generator/TransientVariableInformation.h
@ -0,0 +1,183 @@ |
|||
#include "storm/generator/TransientVariableInformation.h"
|
|||
|
|||
#include "storm/storage/jani/Model.h"
|
|||
|
|||
#include "storm/storage/jani/Automaton.h"
|
|||
#include "storm/storage/jani/ArrayEliminator.h"
|
|||
#include "storm/storage/jani/AutomatonComposition.h"
|
|||
#include "storm/storage/jani/ParallelComposition.h"
|
|||
#include "storm/storage/expressions/ExpressionManager.h"
|
|||
|
|||
#include "storm/utility/macros.h"
|
|||
#include "storm/exceptions/InvalidArgumentException.h"
|
|||
#include "storm/exceptions/WrongFormatException.h"
|
|||
#include "storm/exceptions/OutOfRangeException.h"
|
|||
|
|||
|
|||
#include <cmath>
|
|||
|
|||
namespace storm { |
|||
namespace generator { |
|||
|
|||
template <> |
|||
TransientVariableData<storm::RationalFunction>::TransientVariableData(storm::expressions::Variable const& variable, boost::optional<storm::RationalFunction> const& lowerBound, boost::optional<storm::RationalFunction> const& upperBound, storm::RationalFunction const& defaultValue, bool global) : variable(variable), lowerBound(lowerBound), upperBound(upperBound), defaultValue(defaultValue) { |
|||
// There is no '<=' for rational functions. Therefore, do not check the bounds for this ValueType
|
|||
} |
|||
|
|||
template <typename VariableType> |
|||
TransientVariableData<VariableType>::TransientVariableData(storm::expressions::Variable const& variable, boost::optional<VariableType> const& lowerBound, boost::optional<VariableType> const& upperBound, VariableType const& defaultValue, bool global) : variable(variable), lowerBound(lowerBound), upperBound(upperBound), defaultValue(defaultValue) { |
|||
STORM_LOG_THROW(!lowerBound.is_initialized() || lowerBound.get() <= defaultValue, storm::exceptions::OutOfRangeException, "The default value for transient variable " << variable.getName() << " is smaller than its lower bound."); |
|||
STORM_LOG_THROW(!upperBound.is_initialized() || defaultValue <= upperBound.get(), storm::exceptions::OutOfRangeException, "The default value for transient variable " << variable.getName() << " is higher than its upper bound."); |
|||
} |
|||
|
|||
template <typename VariableType> |
|||
TransientVariableData<VariableType>::TransientVariableData(storm::expressions::Variable const& variable, VariableType const& defaultValue, bool global) : variable(variable), defaultValue(defaultValue) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template <typename ValueType> |
|||
TransientVariableInformation<ValueType>::TransientVariableInformation(storm::jani::Model const& model, std::vector<std::reference_wrapper<storm::jani::Automaton const>> const& parallelAutomata) { |
|||
|
|||
createVariablesForVariableSet(model.getGlobalVariables(), true); |
|||
|
|||
for (auto const& automatonRef : parallelAutomata) { |
|||
createVariablesForAutomaton(automatonRef.get()); |
|||
} |
|||
|
|||
sortVariables(); |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
void TransientVariableInformation<ValueType>::registerArrayVariableReplacements(storm::jani::ArrayEliminatorData const& arrayEliminatorData) { |
|||
arrayVariableToElementInformations.clear(); |
|||
// Find for each replaced array variable the corresponding references in this variable information
|
|||
for (auto const& arrayVariable : arrayEliminatorData.eliminatedArrayVariables) { |
|||
if (arrayVariable->isTransient()) { |
|||
STORM_LOG_ASSERT(arrayEliminatorData.replacements.count(arrayVariable->getExpressionVariable()) > 0, "No replacement for array variable."); |
|||
auto const& replacements = arrayEliminatorData.replacements.find(arrayVariable->getExpressionVariable())->second; |
|||
std::vector<uint64_t> varInfoIndices; |
|||
for (auto const& replacedVar : replacements) { |
|||
if (replacedVar->getExpressionVariable().hasIntegerType()) { |
|||
uint64_t index = 0; |
|||
for (auto const& intInfo : integerVariableInformation) { |
|||
if (intInfo.variable == replacedVar->getExpressionVariable()) { |
|||
varInfoIndices.push_back(index); |
|||
break; |
|||
} |
|||
++index; |
|||
} |
|||
STORM_LOG_ASSERT(!varInfoIndices.empty() && varInfoIndices.back() == index, "Could not find a basic variable for replacement of array variable " << replacedVar->getExpressionVariable().getName() << " ."); |
|||
} else if (replacedVar->getExpressionVariable().hasBooleanType()) { |
|||
uint64_t index = 0; |
|||
for (auto const& boolInfo : booleanVariableInformation) { |
|||
if (boolInfo.variable == replacedVar->getExpressionVariable()) { |
|||
varInfoIndices.push_back(index); |
|||
break; |
|||
} |
|||
++index; |
|||
} |
|||
STORM_LOG_ASSERT(!varInfoIndices.empty() && varInfoIndices.back() == index, "Could not find a basic variable for replacement of array variable " << replacedVar->getExpressionVariable().getName() << " ."); |
|||
} else if (replacedVar->getExpressionVariable().hasRationalType()) { |
|||
uint64_t index = 0; |
|||
for (auto const& rationalInfo : rationalVariableInformation) { |
|||
if (rationalInfo.variable == replacedVar->getExpressionVariable()) { |
|||
varInfoIndices.push_back(index); |
|||
break; |
|||
} |
|||
++index; |
|||
} |
|||
STORM_LOG_ASSERT(!varInfoIndices.empty() && varInfoIndices.back() == index, "Could not find a basic variable for replacement of array variable " << replacedVar->getExpressionVariable().getName() << " ."); |
|||
} else { |
|||
STORM_LOG_ASSERT(false, "Unhandled type of base variable."); |
|||
} |
|||
} |
|||
this->arrayVariableToElementInformations.emplace(arrayVariable->getExpressionVariable(), std::move(varInfoIndices)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
TransientVariableData<bool> const& TransientVariableInformation<ValueType>::getBooleanArrayVariableReplacement(storm::expressions::Variable const& arrayVariable, uint64_t arrayIndex) { |
|||
std::vector<uint64_t> const& indices = arrayVariableToElementInformations.at(arrayVariable); |
|||
STORM_LOG_THROW(arrayIndex < indices.size(), storm::exceptions::WrongFormatException, "Array access at array " << arrayVariable.getName() << " evaluates to array index " << arrayIndex << " which is out of bounds as the array size is " << indices.size() << "."); |
|||
return booleanVariableInformation[indices[arrayIndex]]; |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
TransientVariableData<int64_t> const& TransientVariableInformation<ValueType>::getIntegerArrayVariableReplacement(storm::expressions::Variable const& arrayVariable, uint64_t arrayIndex) { |
|||
std::vector<uint64_t> const& indices = arrayVariableToElementInformations.at(arrayVariable); |
|||
STORM_LOG_THROW(arrayIndex < indices.size(), storm::exceptions::WrongFormatException, "Array access at array " << arrayVariable.getName() << " evaluates to array index " << arrayIndex << " which is out of bounds as the array size is " << indices.size() << "."); |
|||
return integerVariableInformation[indices[arrayIndex]]; |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
TransientVariableData<ValueType> const& TransientVariableInformation<ValueType>::getRationalArrayVariableReplacement(storm::expressions::Variable const& arrayVariable, uint64_t arrayIndex) { |
|||
std::vector<uint64_t> const& indices = arrayVariableToElementInformations.at(arrayVariable); |
|||
STORM_LOG_THROW(arrayIndex < indices.size(), storm::exceptions::WrongFormatException, "Array access at array " << arrayVariable.getName() << " evaluates to array index " << arrayIndex << " which is out of bounds as the array size is " << indices.size() << "."); |
|||
return rationalVariableInformation[indices[arrayIndex]]; |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
void TransientVariableInformation<ValueType>::createVariablesForAutomaton(storm::jani::Automaton const& automaton) { |
|||
createVariablesForVariableSet(automaton.getVariables(), false); |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
void TransientVariableInformation<ValueType>::createVariablesForVariableSet(storm::jani::VariableSet const& variableSet, bool global) { |
|||
for (auto const& variable : variableSet.getBooleanVariables()) { |
|||
if (variable.isTransient()) { |
|||
booleanVariableInformation.emplace_back(variable.getExpressionVariable(), variable.getInitExpression().evaluateAsBool(), global); |
|||
} |
|||
} |
|||
for (auto const& variable : variableSet.getBoundedIntegerVariables()) { |
|||
if (variable.isTransient()) { |
|||
boost::optional<int64_t> lowerBound; |
|||
boost::optional<int64_t> upperBound; |
|||
if (variable.hasLowerBound()) { |
|||
lowerBound = variable.getLowerBound().evaluateAsInt(); |
|||
} |
|||
if (variable.hasUpperBound()) { |
|||
upperBound = variable.getUpperBound().evaluateAsInt(); |
|||
} |
|||
integerVariableInformation.emplace_back(variable.getExpressionVariable(), lowerBound, upperBound, variable.getInitExpression().evaluateAsInt(), global); |
|||
} |
|||
} |
|||
for (auto const& variable : variableSet.getUnboundedIntegerVariables()) { |
|||
if (variable.isTransient()) { |
|||
integerVariableInformation.emplace_back(variable.getExpressionVariable(), variable.getInitExpression().evaluateAsInt(), global); |
|||
} |
|||
} |
|||
for (auto const& variable : variableSet.getRealVariables()) { |
|||
if (variable.isTransient()) { |
|||
rationalVariableInformation.emplace_back(variable.getExpressionVariable(), storm::utility::convertNumber<ValueType>(variable.getInitExpression().evaluateAsRational()), global); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
void TransientVariableInformation<ValueType>::sortVariables() { |
|||
// Sort the variables so we can make some assumptions when iterating over them (in the next-state generators).
|
|||
std::sort(booleanVariableInformation.begin(), booleanVariableInformation.end(), [] (TransientVariableData<bool> const& a, TransientVariableData<bool> const& b) { return a.variable < b.variable; } ); |
|||
std::sort(integerVariableInformation.begin(), integerVariableInformation.end(), [] (TransientVariableData<int64_t> const& a, TransientVariableData<int64_t> const& b) { return a.variable < b.variable; } ); |
|||
std::sort(rationalVariableInformation.begin(), rationalVariableInformation.end(), [] (TransientVariableData<ValueType> const& a, TransientVariableData<ValueType> const& b) { return a.variable < b.variable; } ); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void TransientVariableInformation<ValueType>::setDefaultValuesInEvaluator(storm::expressions::ExpressionEvaluator<ValueType>& evaluator) const { |
|||
for (auto const& variableData : booleanVariableInformation) { |
|||
evaluator.setBooleanValue(variableData.variable, variableData.defaultValue); |
|||
} |
|||
for (auto const& variableData : integerVariableInformation) { |
|||
evaluator.setIntegerValue(variableData.variable, variableData.defaultValue); |
|||
} |
|||
for (auto const& variableData : rationalVariableInformation) { |
|||
evaluator.setRationalValue(variableData.variable, variableData.defaultValue); |
|||
} |
|||
} |
|||
|
|||
template class TransientVariableInformation<double>; |
|||
template class TransientVariableInformation<storm::RationalNumber>; |
|||
template class TransientVariableInformation<storm::RationalFunction>; |
|||
|
|||
} |
|||
} |
@ -0,0 +1,124 @@ |
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
#include <unordered_map> |
|||
#include <boost/optional.hpp> |
|||
|
|||
#include "storm/storage/expressions/Variable.h" |
|||
#include "storm/storage/expressions/Expression.h" |
|||
#include "storm/storage/expressions/ExpressionEvaluator.h" |
|||
#include "storm/utility/macros.h" |
|||
|
|||
#include "storm/exceptions/OutOfRangeException.h" |
|||
|
|||
namespace storm { |
|||
|
|||
namespace jani { |
|||
class Model; |
|||
class Automaton; |
|||
class ArrayEliminatorData; |
|||
class VariableSet; |
|||
} |
|||
|
|||
namespace expressions { |
|||
template <typename ValueType> |
|||
class ExpressionEvaluator; |
|||
} |
|||
|
|||
namespace generator { |
|||
|
|||
|
|||
// A structure storing information about a transient variable |
|||
|
|||
template <typename VariableType> |
|||
struct TransientVariableData { |
|||
TransientVariableData(storm::expressions::Variable const& variable, boost::optional<VariableType> const& lowerBound, boost::optional<VariableType> const& upperBound, VariableType const& defaultValue, bool global = false); |
|||
TransientVariableData(storm::expressions::Variable const& variable, VariableType const& defaultValue, bool global = false); |
|||
|
|||
// The integer variable. |
|||
storm::expressions::Variable variable; |
|||
|
|||
// The lower bound of its range. |
|||
boost::optional<VariableType> lowerBound; |
|||
|
|||
// The upper bound of its range. |
|||
boost::optional<VariableType> upperBound; |
|||
|
|||
// Its default value |
|||
VariableType defaultValue; |
|||
|
|||
// A flag indicating whether the variable is a global one. |
|||
bool global; |
|||
|
|||
}; |
|||
|
|||
template<typename ValueType> |
|||
struct TransientVariableValuation { |
|||
std::vector<std::pair<TransientVariableData<bool> const*, bool>> booleanValues; |
|||
std::vector<std::pair<TransientVariableData<int64_t> const*, int64_t>> integerValues; |
|||
std::vector<std::pair<TransientVariableData<ValueType> const*, ValueType>> rationalValues; |
|||
|
|||
void clear() { |
|||
booleanValues.clear(); |
|||
integerValues.clear(); |
|||
rationalValues.clear(); |
|||
} |
|||
|
|||
void setInEvaluator(storm::expressions::ExpressionEvaluator<ValueType>& evaluator, bool explorationChecks) const { |
|||
for (auto const& varValue : booleanValues) { |
|||
evaluator.setBooleanValue(varValue.first->variable, varValue.second); |
|||
} |
|||
for (auto const& varValue : integerValues) { |
|||
if (explorationChecks) { |
|||
STORM_LOG_THROW(!varValue.first->lowerBound.is_initialized() || varValue.first->lowerBound.get() <= varValue.second, storm::exceptions::OutOfRangeException, "The assigned value for transient variable " << varValue.first->variable.getName() << " is smaller than its lower bound."); |
|||
STORM_LOG_THROW(varValue.first->upperBound.is_initialized() || varValue.second <= varValue.first->upperBound.get(), storm::exceptions::OutOfRangeException, "The assigned value for transient variable " << varValue.first->variable.getName() << " is higher than its upper bound."); |
|||
} |
|||
evaluator.setIntegerValue(varValue.first->variable, varValue.second); |
|||
} |
|||
for (auto const& varValue : rationalValues) { |
|||
evaluator.setRationalValue(varValue.first->variable, varValue.second); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
// A structure storing information about the used variables of the program. |
|||
template<typename ValueType> |
|||
struct TransientVariableInformation { |
|||
TransientVariableInformation(storm::jani::Model const& model, std::vector<std::reference_wrapper<storm::jani::Automaton const>> const& parallelAutomata); |
|||
|
|||
TransientVariableInformation() = default; |
|||
|
|||
void registerArrayVariableReplacements(storm::jani::ArrayEliminatorData const& arrayEliminatorData); |
|||
TransientVariableData<bool> const& getBooleanArrayVariableReplacement(storm::expressions::Variable const& arrayVariable, uint64_t index); |
|||
TransientVariableData<int64_t> const& getIntegerArrayVariableReplacement(storm::expressions::Variable const& arrayVariable, uint64_t index); |
|||
TransientVariableData<ValueType> const& getRationalArrayVariableReplacement(storm::expressions::Variable const& arrayVariable, uint64_t index); |
|||
|
|||
void setDefaultValuesInEvaluator(storm::expressions::ExpressionEvaluator<ValueType>& evaluator) const; |
|||
|
|||
std::vector<TransientVariableData<bool>> booleanVariableInformation; |
|||
std::vector<TransientVariableData<int64_t>> integerVariableInformation; |
|||
std::vector<TransientVariableData<ValueType>> rationalVariableInformation; |
|||
|
|||
/// Replacements for each array variable |
|||
std::unordered_map<storm::expressions::Variable, std::vector<uint64_t>> arrayVariableToElementInformations; |
|||
|
|||
|
|||
private: |
|||
/*! |
|||
* Sorts the variables to establish a known ordering. |
|||
*/ |
|||
void sortVariables(); |
|||
|
|||
/*! |
|||
* Creates all necessary variables for a JANI automaton. |
|||
*/ |
|||
void createVariablesForAutomaton(storm::jani::Automaton const& automaton); |
|||
|
|||
/*! |
|||
* Creates all non-transient variables from the given set |
|||
*/ |
|||
void createVariablesForVariableSet(storm::jani::VariableSet const& variableSet, bool global); |
|||
}; |
|||
|
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue