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