2 changed files with 306 additions and 42 deletions
			
			
		- 
					340src/storm/storage/jani/traverser/ArrayEliminator.cpp
- 
					8src/storm/storage/jani/traverser/ArrayEliminator.h
| @ -1,99 +1,357 @@ | |||||
| #include "storm/storage/jani/traverser/ArrayEliminator.h"
 | #include "storm/storage/jani/traverser/ArrayEliminator.h"
 | ||||
| 
 | 
 | ||||
|  | #include <unordered_map>
 | ||||
| 
 | 
 | ||||
| #include "storm/storage/expressions/ExpressionVisitor.h"
 | #include "storm/storage/expressions/ExpressionVisitor.h"
 | ||||
| #include "storm/storage/jani/expressions/JaniExpressionVisitor.h"
 | #include "storm/storage/jani/expressions/JaniExpressionVisitor.h"
 | ||||
|  | #include "storm/storage/jani/Variable.h"
 | ||||
|  | #include "storm/storage/expressions/Expressions.h"
 | ||||
|  | #include "storm/storage/jani/expressions/JaniExpressions.h"
 | ||||
|  | #include "storm/storage/expressions/ExpressionManager.h"
 | ||||
|  | 
 | ||||
|  | #include "storm/exceptions/NotSupportedException.h"
 | ||||
| 
 | 
 | ||||
| namespace storm { | namespace storm { | ||||
|     namespace jani { |     namespace jani { | ||||
|         namespace detail { |         namespace detail { | ||||
| /*
 |  | ||||
|          |  | ||||
| 
 |  | ||||
|             class MaxArraySizeVisitor : public ExpressionVisitor, public JaniExpressionVisitor { |  | ||||
|                 virtual MaxArraySizeVisitor() = default; |  | ||||
|                 virtual ~MaxArraySizeVisitor() = default; |  | ||||
|  |              | ||||
|  |             class MaxArraySizeExpressionVisitor : public storm::expressions::ExpressionVisitor, public storm::expressions::JaniExpressionVisitor { | ||||
|  |             public: | ||||
|  |                 MaxArraySizeExpressionVisitor() = default; | ||||
|  |                 virtual ~MaxArraySizeExpressionVisitor() = default; | ||||
|      |      | ||||
|                 std::size_t getMaxSize(Expression const& expression) { |  | ||||
|                     return boost::any_cast<std::size_t> expression.accept(*this); |  | ||||
|  |                 std::size_t getMaxSize(storm::expressions::Expression const& expression, std::unordered_map<storm::expressions::Variable, std::size_t> arrayVariableSizeMap) { | ||||
|  |                     return boost::any_cast<std::size_t>(expression.accept(*this, &arrayVariableSizeMap)); | ||||
|                 } |                 } | ||||
|       |       | ||||
|                 virtual boost::any visit(IfThenElseExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::IfThenElseExpression const& expression, boost::any const& data) override { | ||||
|  |                     if (expression.getCondition()->containsVariables()) { | ||||
|  |                         return std::max<std::size_t>(boost::any_cast<std::size_t>(expression.getThenExpression()->accept(*this, data)), boost::any_cast<std::size_t>(expression.getElseExpression()->accept(*this, data))); | ||||
|  |                     } else { | ||||
|  |                         if (expression.getCondition()->evaluateAsBool()) { | ||||
|  |                             return boost::any_cast<std::size_t>(expression.getThenExpression()->accept(*this, data)); | ||||
|  |                         } | ||||
|  |                             return boost::any_cast<std::size_t>(expression.getElseExpression()->accept(*this, data)); | ||||
|  |                     } | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(BinaryBooleanFunctionExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::BinaryBooleanFunctionExpression const& expression, boost::any const& data) override { | ||||
|  |                     return std::max<std::size_t>(boost::any_cast<std::size_t>(expression.getFirstOperand()->accept(*this, data)), boost::any_cast<std::size_t>(expression.getSecondOperand()->accept(*this, data))); | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(BinaryNumericalFunctionExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::BinaryNumericalFunctionExpression const& expression, boost::any const& data) override { | ||||
|  |                     return std::max<std::size_t>(boost::any_cast<std::size_t>(expression.getFirstOperand()->accept(*this, data)), boost::any_cast<std::size_t>(expression.getSecondOperand()->accept(*this, data))); | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(BinaryRelationExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::BinaryRelationExpression const& expression, boost::any const& data) override { | ||||
|  |                     return std::max<std::size_t>(boost::any_cast<std::size_t>(expression.getFirstOperand()->accept(*this, data)), boost::any_cast<std::size_t>(expression.getSecondOperand()->accept(*this, data))); | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(VariableExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::VariableExpression const& expression, boost::any const& data) override { | ||||
|  |                     std::unordered_map<storm::expressions::Variable, std::size_t>* arrayVariableSizeMap = boost::any_cast<std::unordered_map<storm::expressions::Variable, std::size_t>*>(data); | ||||
|  |                     if (expression.getType().isArrayType()) { | ||||
|  |                         auto varIt = arrayVariableSizeMap->find(expression.getVariable()); | ||||
|  |                         if (varIt != arrayVariableSizeMap->end()) { | ||||
|  |                             return varIt->second; | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                     return static_cast<std::size_t>(0); | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(UnaryBooleanFunctionExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::UnaryBooleanFunctionExpression const& expression, boost::any const& data) override { | ||||
|  |                     return boost::any_cast<std::size_t>(expression.getOperand()->accept(*this, data)); | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(UnaryNumericalFunctionExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::UnaryNumericalFunctionExpression const& expression, boost::any const& data) override { | ||||
|  |                     return boost::any_cast<std::size_t>(expression.getOperand()->accept(*this, data)); | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(BooleanLiteralExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::BooleanLiteralExpression const& expression, boost::any const& data) override { | ||||
|  |                     return 0; | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(IntegerLiteralExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::IntegerLiteralExpression const& expression, boost::any const& data) override { | ||||
|  |                     return 0; | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(RationalLiteralExpression const& expression, boost::any const& data) override { |  | ||||
|                  |  | ||||
|  |                 virtual boost::any visit(storm::expressions::RationalLiteralExpression const& expression, boost::any const& data) override { | ||||
|  |                     return 0; | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|  |                 virtual boost::any visit(storm::expressions::ValueArrayExpression const& expression, boost::any const& data) override { | ||||
|  |                     STORM_LOG_ASSERT(expression.size()->isIntegerLiteralExpression(), "unexpected kind of size expression of ValueArrayExpression (" << expression.size()->toExpression() << ")."); | ||||
|  |                     return static_cast<std::size_t>(expression.size()->evaluateAsInt()); | ||||
|  |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(ValueArrayExpression const& expression, boost::any const& data) override { |  | ||||
|  |                 virtual boost::any visit(storm::expressions::ConstructorArrayExpression const& expression, boost::any const& data) override { | ||||
|  |                     if (!expression.size()->containsVariables()) { | ||||
|  |                         return static_cast<std::size_t>(expression.size()->evaluateAsInt()); | ||||
|  |                     } else { | ||||
|  |                         auto vars = expression.toExpression().getVariables(); | ||||
|  |                         std::string variables = ""; | ||||
|  |                         for (auto const& v : vars) { | ||||
|  |                             if (variables != "") { | ||||
|  |                                 variables += ", "; | ||||
|  |                             } | ||||
|  |                             variables += v.getName(); | ||||
|  |                         } | ||||
|  |                         if (vars.size() == 1) { | ||||
|  |                             variables = "variable "; | ||||
|  |                         } else { | ||||
|  |                             variables = "variables "; | ||||
|  |                         } | ||||
|  |                         STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Unable to get determine array size: Size of ConstructorArrayExpression still contains the " << variables << "."); | ||||
|  |                     } | ||||
|  |                 } | ||||
|                  |                  | ||||
|  |                 virtual boost::any visit(storm::expressions::ArrayAccessExpression const& expression, boost::any const& data) override { | ||||
|  |                     STORM_LOG_WARN("Array access expression on rhs of array assignment. This is not expected since nested arrays are currently not supported."); | ||||
|  |                     return 0; | ||||
|                 } |                 } | ||||
|  |             }; | ||||
|  |              | ||||
|  |             class MaxArraySizeDeterminer : public ConstJaniTraverser { | ||||
|  |             public: | ||||
|                  |                  | ||||
|                 virtual boost::any visit(ConstructorArrayExpression const& expression, boost::any const& data) override { |  | ||||
|  |                 typedef std::unordered_map<storm::expressions::Variable, std::size_t>* MapPtr; | ||||
|                  |                  | ||||
|  |                 MaxArraySizeDeterminer() = default; | ||||
|  |                 virtual ~MaxArraySizeDeterminer() = default; | ||||
|  |                 std::unordered_map<storm::expressions::Variable, std::size_t> getMaxSizes(Model const& model) { | ||||
|  |                     // We repeatedly determine the max array sizes until convergence. This is to cover assignments of one array variable to another (A := B)
 | ||||
|  |                     std::unordered_map<storm::expressions::Variable, std::size_t> result, previousResult; | ||||
|  |                     do { | ||||
|  |                         previousResult = result; | ||||
|  |                         ConstJaniTraverser::traverse(model, &result); | ||||
|  |                     } while (previousResult != result); | ||||
|  |                     return result; | ||||
|                 } |                 } | ||||
|                  |                  | ||||
|                 virtual boost::any visit(ArrayAccessExpression const& expression, boost::any const& data) override { |  | ||||
|  |                 virtual void traverse(Assignment const& assignment, boost::any const& data) const override { | ||||
|  |                     if (assignment.lValueIsVariable() && assignment.getExpressionVariable().getType().isArrayType()) { | ||||
|  |                         auto& map = *boost::any_cast<MapPtr>(data); | ||||
|  |                         std::size_t newSize = MaxArraySizeExpressionVisitor().getMaxSize(assignment.getAssignedExpression(), map); | ||||
|  |                         auto insertionRes = map.emplace(assignment.getExpressionVariable(), newSize); | ||||
|  |                         if (!insertionRes.second) { | ||||
|  |                             insertionRes.first->second = std::max(newSize, insertionRes.first->second); | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                 } | ||||
|                  |                  | ||||
|  |                 virtual void traverse(ArrayVariable const& variable, boost::any const& data) const override { | ||||
|  |                     if (variable.hasInitExpression()) { | ||||
|  |                         auto& map = *boost::any_cast<MapPtr>(data); | ||||
|  |                         std::size_t newSize = MaxArraySizeExpressionVisitor().getMaxSize(variable.getInitExpression(), map); | ||||
|  |                         auto insertionRes = map.emplace(variable.getExpressionVariable(), newSize); | ||||
|  |                         if (!insertionRes.second) { | ||||
|  |                             insertionRes.first->second = std::max(newSize, insertionRes.first->second); | ||||
|  |                         } | ||||
|  |                     } | ||||
|                 } |                 } | ||||
|             }; |             }; | ||||
|  |              | ||||
|          |          | ||||
|             class ArrayVariableReplacer : public JaniTraverser { |             class ArrayVariableReplacer : public JaniTraverser { | ||||
|             public: |             public: | ||||
| 
 | 
 | ||||
|                 ArrayVariableReplacer() = default; |  | ||||
|  |                 typedef ArrayEliminatorData ResultType; | ||||
|  |                  | ||||
|  |                 ArrayVariableReplacer(storm::expressions::ExpressionManager& expressionManager, bool keepNonTrivialArrayAccess) : expressionManager(expressionManager) , keepNonTrivialArrayAccess(keepNonTrivialArrayAccess) {} | ||||
|  |                  | ||||
|                 virtual ~ArrayVariableReplacer() = default; |                 virtual ~ArrayVariableReplacer() = default; | ||||
|                 std::unordered_map<storm::expressions::Variable, std::vector<reference_wrapper<storm::jani::Variable>> replace(); |  | ||||
|  |                 ResultType replace(Model& model, std::unordered_map<storm::expressions::Variable, std::size_t> const& arrayVarToSizesMap) { | ||||
|  |                     ResultType result; | ||||
|  |                     for (auto const& arraySize : arrayVarToSizesMap) { | ||||
|  |                         result.replacements.emplace(arraySize.first, std::vector<storm::jani::Variable const*>(arraySize.second, nullptr)); | ||||
|  |                     } | ||||
|  |                     traverse(model, &result); | ||||
|  |                     return result; | ||||
|  |                 } | ||||
|  | 
 | ||||
|  |                 virtual void traverse(Model& model, boost::any const& data) const override { | ||||
|  |                      | ||||
|  |                     // Insert fresh basic variables for global array variables
 | ||||
|  |                     auto& replacements = boost::any_cast<ResultType*>(data)->replacements; | ||||
|  |                     for (storm::jani::ArrayVariable const& arrayVariable : model.getGlobalVariables().getArrayVariables()) { | ||||
|  |                         std::vector<storm::jani::Variable const*>& basicVars = replacements.at(arrayVariable.getExpressionVariable()); | ||||
|  |                         for (uint64_t index = 0; index < basicVars.size(); ++index) { | ||||
|  |                             basicVars[index] = &model.addVariable(*getBasicVariable(arrayVariable, index)); | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                     // drop all occuring array variables
 | ||||
|  |                     auto elVars = model.getGlobalVariables().dropAllArrayVariables(); | ||||
|  |                     auto& eliminatedArrayVariables = boost::any_cast<ResultType*>(data)->eliminatedArrayVariables; | ||||
|  |                     eliminatedArrayVariables.insert(eliminatedArrayVariables.end(), elVars.begin(), elVars.end()); | ||||
|  |                      | ||||
|  |                     for (auto& aut : model.getAutomata()) { | ||||
|  |                         traverse(aut, data); | ||||
|  |                     } | ||||
|  |                      | ||||
|  |                     // traverse remaining components
 | ||||
|  |                     for (auto& c : model.getConstants()) { | ||||
|  |                         traverse(c, data); | ||||
|  |                     } | ||||
|  |                     if (model.hasInitialStatesRestriction()) { | ||||
|  |                         //model.setInitialStatesRestriction();
 | ||||
|  |                     } | ||||
|  |                 } | ||||
|  |                  | ||||
|  |                 virtual void traverse(Automaton& automaton, boost::any const& data) const override { | ||||
|  |                     // No need to traverse the init restriction.
 | ||||
|  |                      | ||||
|  |                     // Insert fresh basic variables for local array variables
 | ||||
|  |                     auto& replacements = boost::any_cast<ResultType*>(data)->replacements; | ||||
|  |                     for (storm::jani::ArrayVariable const& arrayVariable : automaton.getVariables().getArrayVariables()) { | ||||
|  |                         std::vector<storm::jani::Variable const*>& basicVars = replacements.at(arrayVariable.getExpressionVariable()); | ||||
|  |                         for (uint64_t index = 0; index < basicVars.size(); ++index) { | ||||
|  |                             basicVars[index] = &automaton.addVariable(*getBasicVariable(arrayVariable, index)); | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                     // drop all occuring array variables
 | ||||
|  |                     auto elVars = automaton.getVariables().dropAllArrayVariables(); | ||||
|  |                     auto& eliminatedArrayVariables = boost::any_cast<ResultType*>(data)->eliminatedArrayVariables; | ||||
|  |                     eliminatedArrayVariables.insert(eliminatedArrayVariables.end(), elVars.begin(), elVars.end()); | ||||
|  | 
 | ||||
|  |                     for (auto& loc : automaton.getLocations()) { | ||||
|  |                         JaniTraverser::traverse(loc, data); | ||||
|  |                     } | ||||
|  |                     JaniTraverser::traverse(automaton.getEdgeContainer(), data); | ||||
|  |                 } | ||||
|  |                  | ||||
|  |                 void traverse(Constant& constant, boost::any const& data) const { | ||||
|  |                     if (constant.isDefined()) { | ||||
|  |                         // todo:
 | ||||
|  |                         //traverse(constant.getExpression(), data);
 | ||||
|  |                     } | ||||
|  |                 } | ||||
|  | 
 | ||||
|  |                 virtual void traverse(OrderedAssignments& orderedAssignments, boost::any const& data) const override { | ||||
|  |                     auto const& replacements = boost::any_cast<ResultType*>(data)->replacements; | ||||
| 
 | 
 | ||||
|                 virtual void traverse(Assignment const& assignment, boost::any const& data) const override; |  | ||||
|  |                     // Replace array occurrences in LValues.
 | ||||
|  |                     std::vector<Assignment> newAssignments; | ||||
|  |                     uint64_t level = 0; | ||||
|  |                     std::unordered_map<storm::expressions::Variable, std::vector<Assignment const*>> collectedArrayAccessAssignments; | ||||
|  |                     for (Assignment const& assignment : orderedAssignments) { | ||||
|  |                         if (assignment.getLevel() != level) { | ||||
|  |                             STORM_LOG_ASSERT(assignment.getLevel() > level, "Ordered Assignment does not have the expected order."); | ||||
|  |                             for (auto const& arrayAssignments : collectedArrayAccessAssignments) { | ||||
|  |                                 insertLValueArrayAccessReplacements(arrayAssignments.second, replacements.at(arrayAssignments.first), level, newAssignments); | ||||
|  |                             } | ||||
|  |                             collectedArrayAccessAssignments.clear(); | ||||
|  |                             level = assignment.getLevel(); | ||||
|  |                         } | ||||
|  |                         if (assignment.getLValue().isArrayAccess()) { | ||||
|  |                             if (!keepNonTrivialArrayAccess || !assignment.getLValue().getArrayIndex().containsVariables()) { | ||||
|  |                                 auto insertionRes = collectedArrayAccessAssignments.emplace(assignment.getLValue().getArray().getExpressionVariable(), std::vector<Assignment const*>({&assignment})); | ||||
|  |                                 if (!insertionRes.second) { | ||||
|  |                                     insertionRes.first->second.push_back(&assignment); | ||||
|  |                                 } | ||||
|  |                                 continue; | ||||
|  |                             } | ||||
|  |                         } else if (assignment.getLValue().isVariable() && assignment.getVariable().isArrayVariable()) { | ||||
|  |                             STORM_LOG_ASSERT(assignment.getAssignedExpression().getType().isArrayType(), "Assigning a non-array expression to an array variable..."); | ||||
|  |                             std::vector<storm::jani::Variable const*> const& arrayVariableReplacements = replacements.at(assignment.getExpressionVariable()); | ||||
|  |                             for (uint64_t index = 0; index < arrayVariableReplacements.size(); ++index) { | ||||
|  |                                 auto arrayAccessExpression = std::make_shared<storm::expressions::ArrayAccessExpression>(expressionManager, assignment.getAssignedExpression().getType().getElementType(), assignment.getAssignedExpression().getBaseExpressionPointer(), expressionManager.integer(index).getBaseExpressionPointer()); | ||||
|  |                                 newAssignments.emplace_back(LValue(*arrayVariableReplacements[index]), arrayAccessExpression->toExpression(), level); | ||||
|  |                             } | ||||
|  |                             continue; | ||||
|  |                         } | ||||
|  |                         newAssignments.push_back(assignment); | ||||
|  |                     } | ||||
|  |                     for (auto const& arrayAssignments : collectedArrayAccessAssignments) { | ||||
|  |                         insertLValueArrayAccessReplacements(arrayAssignments.second, replacements.at(arrayAssignments.first), level, newAssignments); | ||||
|  |                     } | ||||
|  |                     collectedArrayAccessAssignments.clear(); | ||||
|  |                     orderedAssignments.clear(); | ||||
|  |                     for (auto const& assignment : newAssignments) { | ||||
|  |                         orderedAssignments.add(assignment); | ||||
|  |                     } | ||||
|  |                 } | ||||
|                  |                  | ||||
|             private: |             private: | ||||
|                 void std::unordered_map<storm::expressions::Variable, std::size_t>::getMaxSizes(Model& model); |  | ||||
|                  |                  | ||||
|  |                 std::shared_ptr<Variable> getBasicVariable(ArrayVariable const& arrayVariable, uint64_t index) const { | ||||
|  |                     std::string name = arrayVariable.getExpressionVariable().getName() + "_at_" + std::to_string(index); | ||||
|  |                     storm::expressions::Expression initValue; | ||||
|  |                     if (arrayVariable.hasInitExpression()) { | ||||
|  |                         initValue = std::make_shared<storm::expressions::ArrayAccessExpression>(expressionManager, arrayVariable.getExpressionVariable().getType().getElementType(), arrayVariable.getInitExpression().getBaseExpressionPointer(), expressionManager.integer(index).getBaseExpressionPointer())->toExpression(); | ||||
|  |                     } | ||||
|  |                     if (arrayVariable.getElementType() == ArrayVariable::ElementType::Int) { | ||||
|  |                         storm::expressions::Variable exprVariable = expressionManager.declareIntegerVariable(name); | ||||
|  |                         if (arrayVariable.hasElementTypeBounds()) { | ||||
|  |                             if (initValue.isInitialized()) { | ||||
|  |                                 return std::make_shared<BoundedIntegerVariable>(name, exprVariable, initValue, arrayVariable.isTransient(), arrayVariable.getElementTypeBounds().first, arrayVariable.getElementTypeBounds().second); | ||||
|  |                             } else { | ||||
|  |                                 return std::make_shared<BoundedIntegerVariable>(name, exprVariable, arrayVariable.getElementTypeBounds().first, arrayVariable.getElementTypeBounds().second); | ||||
|  |                             } | ||||
|  |                         } else { | ||||
|  |                             if (initValue.isInitialized()) { | ||||
|  |                                 return std::make_shared<UnboundedIntegerVariable>(name, exprVariable, initValue, arrayVariable.isTransient()); | ||||
|  |                             } else { | ||||
|  |                                 return std::make_shared<UnboundedIntegerVariable>(name, exprVariable); | ||||
|  |                             } | ||||
|  |                         } | ||||
|  |                     } else if (arrayVariable.getElementType() == ArrayVariable::ElementType::Real) { | ||||
|  |                         storm::expressions::Variable exprVariable = expressionManager.declareRationalVariable(name); | ||||
|  |                         if (initValue.isInitialized()) { | ||||
|  |                             return std::make_shared<RealVariable>(name, exprVariable, initValue, arrayVariable.isTransient()); | ||||
|  |                         } else { | ||||
|  |                             return std::make_shared<RealVariable>(name, exprVariable); | ||||
|  |                         } | ||||
|  |                     } else if (arrayVariable.getElementType() == ArrayVariable::ElementType::Bool) { | ||||
|  |                         storm::expressions::Variable exprVariable = expressionManager.declareBooleanVariable(name); | ||||
|  |                         if (initValue.isInitialized()) { | ||||
|  |                             return std::make_shared<BooleanVariable>(name, exprVariable, initValue, arrayVariable.isTransient()); | ||||
|  |                         } else { | ||||
|  |                             return std::make_shared<BooleanVariable>(name, exprVariable); | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                     STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Unhandled array base type."); | ||||
|  |                     return nullptr; | ||||
|  |                 } | ||||
|  |                  | ||||
|  |                 void insertLValueArrayAccessReplacements(std::vector<Assignment const*> const& arrayAccesses, std::vector<storm::jani::Variable const*> const& arrayVariableReplacements, uint64_t level, std::vector<Assignment>& newAssignments) const { | ||||
|  |                     storm::expressions::Variable const& arrayVariable = arrayAccesses.front()->getLValue().getArray().getExpressionVariable(); | ||||
|  |                     bool onlyConstantIndices = true; | ||||
|  |                     for (auto const& aa : arrayAccesses) { | ||||
|  |                         if (aa->getLValue().getArrayIndex().containsVariables()) { | ||||
|  |                             onlyConstantIndices = false; | ||||
|  |                             break; | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                     if (onlyConstantIndices) { | ||||
|  |                         for (auto const& aa : arrayAccesses) { | ||||
|  |                             LValue lvalue(*arrayVariableReplacements.at(aa->getLValue().getArrayIndex().evaluateAsInt())); | ||||
|  |                             newAssignments.emplace_back(lvalue, aa->getAssignedExpression(), level); | ||||
|  |                         } | ||||
|  |                     } else { | ||||
|  |                         for (uint64_t index = 0; index < arrayVariableReplacements.size(); ++index) { | ||||
|  |                             storm::expressions::Expression assignedExpression = arrayVariableReplacements[index]->getExpressionVariable().getExpression(); | ||||
|  |                             auto indexExpression = expressionManager.integer(index); | ||||
|  |                             for (auto const& aa : arrayAccesses) { | ||||
|  |                                 assignedExpression = storm::expressions::ite(aa->getLValue().getArrayIndex() == indexExpression, aa->getAssignedExpression(), assignedExpression); | ||||
|  |                                 newAssignments.emplace_back(LValue(*arrayVariableReplacements[index]), assignedExpression, level); | ||||
|  |                             } | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |                 } | ||||
|  |                  | ||||
|  |                 storm::expressions::ExpressionManager& expressionManager; | ||||
|  |                 bool const keepNonTrivialArrayAccess; | ||||
|             }; |             }; | ||||
|              |              | ||||
|             class ArrayAccessLValueReplacer : public JaniTraverser { |  | ||||
|             } |  | ||||
|            */ |  | ||||
|         } |  | ||||
|  |              | ||||
|          |          | ||||
|         ArrayEliminator::eliminate(Model& model) { |  | ||||
|             //auto variableReplacements ArrayVariableReplacer().replace(model)
 |  | ||||
|  |         } // namespace detail
 | ||||
|          |          | ||||
|  |         ArrayEliminatorData ArrayEliminator::eliminate(Model& model, bool keepNonTrivialArrayAccess) { | ||||
|  |             auto sizes = detail::MaxArraySizeDeterminer().getMaxSizes(model); | ||||
|  |             ArrayEliminatorData result = detail::ArrayVariableReplacer(model.getExpressionManager(), keepNonTrivialArrayAccess).replace(model, sizes); | ||||
|  |              | ||||
|  |             model.finalize(); | ||||
|  |             return result; | ||||
|         } |         } | ||||
|     } |     } | ||||
| } | } | ||||
|  | |||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue