@ -1,4 +1,4 @@
# include "storm/storage/jani/traverser/ ArrayEliminator.h"
# include "storm/storage/jani/ArrayEliminator.h"
# include <unordered_map>
@ -10,6 +10,7 @@
# include "storm/storage/expressions/ExpressionManager.h"
# include "storm/exceptions/NotSupportedException.h"
# include "storm/exceptions/UnexpectedException.h"
namespace storm {
namespace jani {
@ -105,11 +106,188 @@ namespace storm {
}
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." ) ;
STORM_LOG_WARN ( " Found Array access expression within an array expression . This is not expected since nested arrays are currently not supported." ) ;
return 0 ;
}
} ;
class ArrayExpressionEliminationVisitor : public storm : : expressions : : ExpressionVisitor , public storm : : expressions : : JaniExpressionVisitor {
public :
typedef std : : shared_ptr < storm : : expressions : : BaseExpression const > BaseExprPtr ;
ArrayExpressionEliminationVisitor ( std : : unordered_map < storm : : expressions : : Variable , std : : vector < storm : : jani : : Variable const * > > const & replacements , std : : unordered_map < storm : : expressions : : Variable , std : : size_t > const & sizes ) : replacements ( replacements ) , arraySizes ( sizes ) { }
virtual ~ ArrayExpressionEliminationVisitor ( ) = default ;
storm : : expressions : : Expression eliminate ( storm : : expressions : : Expression const & expression , storm : : expressions : : Expression const & outOfBoundsExpression ) {
auto res = eliminate ( expression , false ) ;
if ( outOfBoundsError ) {
return outOfBoundsExpression ;
} else {
return res ;
}
}
storm : : expressions : : Expression eliminate ( storm : : expressions : : Expression const & expression , bool failIfOutOfBounds = true ) {
outOfBoundsError = false ;
// here, data is the accessed index of the most recent array access expression. Initially, there is none.
auto res = storm : : expressions : : Expression ( boost : : any_cast < BaseExprPtr > ( expression . accept ( * this , boost : : any ( ) ) ) ) ;
STORM_LOG_THROW ( ! failIfOutOfBounds | | ! outOfBoundsError , storm : : exceptions : : UnexpectedException , " Out of bounds array access occured while eliminating expression " < < expression ) ;
return res . simplify ( ) ;
}
virtual boost : : any visit ( storm : : expressions : : IfThenElseExpression const & expression , boost : : any const & data ) override {
// for the condition expression, outer array accesses should not matter.
BaseExprPtr conditionExpression = boost : : any_cast < BaseExprPtr > ( expression . getCondition ( ) - > accept ( * this , boost : : any ( ) ) ) ;
BaseExprPtr thenExpression = boost : : any_cast < BaseExprPtr > ( expression . getThenExpression ( ) - > accept ( * this , data ) ) ;
BaseExprPtr elseExpression = boost : : any_cast < BaseExprPtr > ( expression . getElseExpression ( ) - > accept ( * this , data ) ) ;
// If the arguments did not change, we simply push the expression itself.
if ( conditionExpression . get ( ) = = expression . getCondition ( ) . get ( ) & & thenExpression . get ( ) = = expression . getThenExpression ( ) . get ( ) & & elseExpression . get ( ) = = expression . getElseExpression ( ) . get ( ) ) {
return expression . getSharedPointer ( ) ;
} else {
return std : : const_pointer_cast < storm : : expressions : : BaseExpression const > ( std : : shared_ptr < storm : : expressions : : BaseExpression > ( new storm : : expressions : : IfThenElseExpression ( expression . getManager ( ) , thenExpression - > getType ( ) , conditionExpression , thenExpression , elseExpression ) ) ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : BinaryBooleanFunctionExpression const & expression , boost : : any const & data ) override {
STORM_LOG_ASSERT ( data . empty ( ) , " BinaryBooleanFunctionExpressions should not be direct subexpressions of array access expressions. However, the expression " < < expression < < " is. " ) ;
BaseExprPtr firstExpression = boost : : any_cast < BaseExprPtr > ( expression . getFirstOperand ( ) - > accept ( * this , data ) ) ;
BaseExprPtr secondExpression = boost : : any_cast < BaseExprPtr > ( expression . getSecondOperand ( ) - > accept ( * this , data ) ) ;
// If the arguments did not change, we simply push the expression itself.
if ( firstExpression . get ( ) = = expression . getFirstOperand ( ) . get ( ) & & secondExpression . get ( ) = = expression . getSecondOperand ( ) . get ( ) ) {
return expression . getSharedPointer ( ) ;
} else {
return std : : const_pointer_cast < storm : : expressions : : BaseExpression const > ( std : : shared_ptr < storm : : expressions : : BaseExpression > ( new storm : : expressions : : BinaryBooleanFunctionExpression ( expression . getManager ( ) , expression . getType ( ) , firstExpression , secondExpression , expression . getOperatorType ( ) ) ) ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : BinaryNumericalFunctionExpression const & expression , boost : : any const & data ) override {
STORM_LOG_ASSERT ( data . empty ( ) , " BinaryNumericalFunctionExpression should not be direct subexpressions of array access expressions. However, the expression " < < expression < < " is. " ) ;
BaseExprPtr firstExpression = boost : : any_cast < BaseExprPtr > ( expression . getFirstOperand ( ) - > accept ( * this , data ) ) ;
BaseExprPtr secondExpression = boost : : any_cast < BaseExprPtr > ( expression . getSecondOperand ( ) - > accept ( * this , data ) ) ;
// If the arguments did not change, we simply push the expression itself.
if ( firstExpression . get ( ) = = expression . getFirstOperand ( ) . get ( ) & & secondExpression . get ( ) = = expression . getSecondOperand ( ) . get ( ) ) {
return expression . getSharedPointer ( ) ;
} else {
return std : : const_pointer_cast < storm : : expressions : : BaseExpression const > ( std : : shared_ptr < storm : : expressions : : BaseExpression > ( new storm : : expressions : : BinaryNumericalFunctionExpression ( expression . getManager ( ) , expression . getType ( ) , firstExpression , secondExpression , expression . getOperatorType ( ) ) ) ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : BinaryRelationExpression const & expression , boost : : any const & data ) override {
STORM_LOG_ASSERT ( data . empty ( ) , " BinaryRelationExpression should not be direct subexpressions of array access expressions. However, the expression " < < expression < < " is. " ) ;
BaseExprPtr firstExpression = boost : : any_cast < BaseExprPtr > ( expression . getFirstOperand ( ) - > accept ( * this , data ) ) ;
BaseExprPtr secondExpression = boost : : any_cast < BaseExprPtr > ( expression . getSecondOperand ( ) - > accept ( * this , data ) ) ;
// If the arguments did not change, we simply push the expression itself.
if ( firstExpression . get ( ) = = expression . getFirstOperand ( ) . get ( ) & & secondExpression . get ( ) = = expression . getSecondOperand ( ) . get ( ) ) {
return expression . getSharedPointer ( ) ;
} else {
return std : : const_pointer_cast < storm : : expressions : : BaseExpression const > ( std : : shared_ptr < storm : : expressions : : BaseExpression > ( new storm : : expressions : : BinaryRelationExpression ( expression . getManager ( ) , expression . getType ( ) , firstExpression , secondExpression , expression . getRelationType ( ) ) ) ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : VariableExpression const & expression , boost : : any const & data ) override {
if ( expression . getType ( ) . isArrayType ( ) ) {
STORM_LOG_THROW ( ! data . empty ( ) , storm : : exceptions : : NotSupportedException , " Unable to translate array variable to basic variable, since it does not seem to be within an array access expression. " ) ;
uint64_t index = boost : : any_cast < uint64_t > ( data ) ;
STORM_LOG_ASSERT ( replacements . find ( expression . getVariable ( ) ) ! = replacements . end ( ) , " Unable to find array variable " < < expression < < " in array replacements. " ) ;
auto const & arrayVarReplacements = replacements . at ( expression . getVariable ( ) ) ;
STORM_LOG_ASSERT ( index < arrayVarReplacements . size ( ) , " No replacement for array variable, since index " < < index < < " is out of bounds. " ) ;
return arrayVarReplacements [ index ] - > getExpressionVariable ( ) . getExpression ( ) . getBaseExpressionPointer ( ) ;
} else {
return expression . getSharedPointer ( ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : UnaryBooleanFunctionExpression const & expression , boost : : any const & data ) override {
STORM_LOG_ASSERT ( data . empty ( ) , " UnaryBooleanFunctionExpression should not be direct subexpressions of array access expressions. However, the expression " < < expression < < " is. " ) ;
BaseExprPtr operandExpression = boost : : any_cast < BaseExprPtr > ( expression . getOperand ( ) - > accept ( * this , data ) ) ;
// If the argument did not change, we simply push the expression itself.
if ( operandExpression . get ( ) = = expression . getOperand ( ) . get ( ) ) {
return expression . getSharedPointer ( ) ;
} else {
return std : : const_pointer_cast < storm : : expressions : : BaseExpression const > ( std : : shared_ptr < storm : : expressions : : BaseExpression > ( new storm : : expressions : : UnaryBooleanFunctionExpression ( expression . getManager ( ) , expression . getType ( ) , operandExpression , expression . getOperatorType ( ) ) ) ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : UnaryNumericalFunctionExpression const & expression , boost : : any const & data ) override {
STORM_LOG_ASSERT ( data . empty ( ) , " UnaryBooleanFunctionExpression should not be direct subexpressions of array access expressions. However, the expression " < < expression < < " is. " ) ;
BaseExprPtr operandExpression = boost : : any_cast < BaseExprPtr > ( expression . getOperand ( ) - > accept ( * this , data ) ) ;
// If the argument did not change, we simply push the expression itself.
if ( operandExpression . get ( ) = = expression . getOperand ( ) . get ( ) ) {
return expression . getSharedPointer ( ) ;
} else {
return std : : const_pointer_cast < storm : : expressions : : BaseExpression const > ( std : : shared_ptr < storm : : expressions : : BaseExpression > ( new storm : : expressions : : UnaryNumericalFunctionExpression ( expression . getManager ( ) , expression . getType ( ) , operandExpression , expression . getOperatorType ( ) ) ) ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : BooleanLiteralExpression const & expression , boost : : any const & ) override {
return expression . getSharedPointer ( ) ;
}
virtual boost : : any visit ( storm : : expressions : : IntegerLiteralExpression const & expression , boost : : any const & ) override {
return expression . getSharedPointer ( ) ;
}
virtual boost : : any visit ( storm : : expressions : : RationalLiteralExpression const & expression , boost : : any const & ) override {
return expression . getSharedPointer ( ) ;
}
virtual boost : : any visit ( storm : : expressions : : ValueArrayExpression const & expression , boost : : any const & data ) override {
STORM_LOG_THROW ( ! data . empty ( ) , storm : : exceptions : : NotSupportedException , " Unable to translate ValueArrayExpression to element expression since it does not seem to be within an array access expression. " ) ;
uint64_t index = boost : : any_cast < uint64_t > ( data ) ;
STORM_LOG_ASSERT ( expression . size ( ) - > isIntegerLiteralExpression ( ) , " unexpected kind of size expression of ValueArrayExpression ( " < < expression . size ( ) - > toExpression ( ) < < " ). " ) ;
if ( index < static_cast < uint64_t > ( expression . size ( ) - > evaluateAsInt ( ) ) ) {
return expression . at ( index ) ;
} else {
outOfBoundsError = true ;
return expression . at ( 0 ) ;
}
}
virtual boost : : any visit ( storm : : expressions : : ConstructorArrayExpression const & expression , boost : : any const & data ) override {
STORM_LOG_THROW ( ! data . empty ( ) , storm : : exceptions : : NotSupportedException , " Unable to translate ValueArrayExpression to element expression since it does not seem to be within an array access expression. " ) ;
uint64_t index = boost : : any_cast < uint64_t > ( data ) ;
if ( expression . size ( ) - > containsVariables ( ) ) {
STORM_LOG_WARN ( " Ignoring length of constructorArrayExpression " < < expression < < " as it still contains variables. " ) ;
} else if ( index > = static_cast < uint64_t > ( expression . size ( ) - > evaluateAsInt ( ) ) ) {
outOfBoundsError = true ;
}
return expression . at ( index ) ;
}
virtual boost : : any visit ( storm : : expressions : : ArrayAccessExpression const & expression , boost : : any const & data ) override {
if ( expression . getSecondOperand ( ) - > containsVariables ( ) ) {
//get the size of the array expression
uint64_t size = MaxArraySizeExpressionVisitor ( ) . getMaxSize ( expression . getFirstOperand ( ) - > toExpression ( ) , arraySizes ) ;
STORM_LOG_THROW ( size > 0 , storm : : exceptions : : NotSupportedException , " Unable to get size of array expression for array access " < < expression < < " . " ) ;
uint64_t index = size - 1 ;
storm : : expressions : : Expression result = boost : : any_cast < BaseExprPtr > ( expression . getFirstOperand ( ) - > accept ( * this , index ) ) - > toExpression ( ) ;
while ( index > 0 ) {
- - index ;
result = storm : : expressions : : ite (
expression . getSecondOperand ( ) - > toExpression ( ) = = expression . getManager ( ) . integer ( index ) ,
boost : : any_cast < BaseExprPtr > ( expression . getFirstOperand ( ) - > accept ( * this , index ) ) - > toExpression ( ) ,
result ) ;
}
return result . getBaseExpressionPointer ( ) ;
} else {
uint64_t index = expression . getSecondOperand ( ) - > evaluateAsInt ( ) ;
return boost : : any_cast < BaseExprPtr > ( expression . getFirstOperand ( ) - > accept ( * this , index ) ) ;
}
}
private :
std : : unordered_map < storm : : expressions : : Variable , std : : vector < storm : : jani : : Variable const * > > const & replacements ;
std : : unordered_map < storm : : expressions : : Variable , std : : size_t > const & arraySizes ;
bool outOfBoundsError ;
} ;
class MaxArraySizeDeterminer : public ConstJaniTraverser {
public :
@ -127,7 +305,7 @@ namespace storm {
return result ;
}
virtual void traverse ( Assignment const & assignment , boost : : any const & data ) const override {
virtual void traverse ( Assignment const & assignment , boost : : any const & data ) override {
if ( assignment . lValueIsVariable ( ) & & assignment . getExpressionVariable ( ) . getType ( ) . isArrayType ( ) ) {
auto & map = * boost : : any_cast < MapPtr > ( data ) ;
std : : size_t newSize = MaxArraySizeExpressionVisitor ( ) . getMaxSize ( assignment . getAssignedExpression ( ) , map ) ;
@ -138,7 +316,7 @@ namespace storm {
}
}
virtual void traverse ( ArrayVariable const & variable , boost : : any const & data ) const override {
virtual void traverse ( ArrayVariable const & variable , boost : : any const & data ) override {
if ( variable . hasInitExpression ( ) ) {
auto & map = * boost : : any_cast < MapPtr > ( data ) ;
std : : size_t newSize = MaxArraySizeExpressionVisitor ( ) . getMaxSize ( variable . getInitExpression ( ) , map ) ;
@ -156,19 +334,21 @@ namespace storm {
typedef ArrayEliminatorData ResultType ;
ArrayVariableReplacer ( storm : : expressions : : ExpressionManager & expressionManager , bool keepNonTrivialArrayAccess ) : expressionManager ( expressionManager ) , keepNonTrivialArrayAccess ( keepNonTrivialArrayAccess ) { }
ArrayVariableReplacer ( storm : : expressions : : ExpressionManager & expressionManager , bool keepNonTrivialArrayAccess , std : : unordered_map < storm : : expressions : : Variable , std : : size_t > const & arrayVarToSizesMap ) : expressionManager ( expressionManager ) , keepNonTrivialArrayAccess ( keepNonTrivialArrayAccess ) , arraySizes ( arrayVarToSizesMap ) { }
virtual ~ ArrayVariableReplacer ( ) = default ;
ResultType replace ( Model & model , std : : unordered_map < storm : : expressions : : Variable , std : : size_t > const & arrayVarToSizesMap ) {
ResultType replace ( Model & model ) {
ResultType result ;
for ( auto const & arraySize : arrayVarToSizesMap ) {
arrayExprEliminator = std : : make_unique < ArrayExpressionEliminationVisitor > ( result . replacements , arraySizes ) ;
for ( auto const & arraySize : arraySizes ) {
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 {
virtual void traverse ( Model & model , boost : : any const & data ) override {
// Insert fresh basic variables for global array variables
auto & replacements = boost : : any_cast < ResultType * > ( data ) - > replacements ;
@ -183,20 +363,20 @@ namespace storm {
auto & eliminatedArrayVariables = boost : : any_cast < ResultType * > ( data ) - > eliminatedArrayVariables ;
eliminatedArrayVariables . insert ( eliminatedArrayVariables . end ( ) , elVars . begin ( ) , elVars . end ( ) ) ;
// Make new variable replacements known to the expression eliminator
arrayExprEliminator = std : : make_unique < ArrayExpressionEliminationVisitor > ( replacements , arraySizes ) ;
for ( auto & aut : model . getAutomata ( ) ) {
traverse ( aut , data ) ;
}
// traverse remaining components
for ( auto & c : model . getConstants ( ) ) {
traverse ( c , data ) ;
}
// traversal of remaining components
if ( model . hasInitialStatesRestriction ( ) ) {
//model.setInitialStatesRestriction();
model . setInitialStatesRestriction ( arrayExprEliminator - > eliminate ( model . getInitialStatesRestriction ( ) ) ) ;
}
}
virtual void traverse ( Automaton & automaton , boost : : any const & data ) const override {
virtual void traverse ( Automaton & automaton , boost : : any const & data ) override {
// No need to traverse the init restriction.
// Insert fresh basic variables for local array variables
@ -212,23 +392,23 @@ namespace storm {
auto & eliminatedArrayVariables = boost : : any_cast < ResultType * > ( data ) - > eliminatedArrayVariables ;
eliminatedArrayVariables . insert ( eliminatedArrayVariables . end ( ) , elVars . begin ( ) , elVars . end ( ) ) ;
// Make new variable replacements known to the expression eliminator
arrayExprEliminator = std : : make_unique < ArrayExpressionEliminationVisitor > ( replacements , arraySizes ) ;
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);
if ( automaton . hasInitialStatesRestriction ( ) ) {
automaton . setInitialStatesRestriction ( arrayExprEliminator - > eliminate ( automaton . getInitialStatesRestriction ( ) ) ) ;
}
}
virtual void traverse ( OrderedAssignments & orderedAssignments , boost : : any const & data ) const override {
virtual void traverse ( OrderedAssignments & orderedAssignments , boost : : any const & data ) override {
auto const & replacements = boost : : any_cast < ResultType * > ( data ) - > replacements ;
// Replace array occurrences in LValues.
// Replace array occurrences in LValues and assigned expressions .
std : : vector < Assignment > newAssignments ;
uint64_t level = 0 ;
std : : unordered_map < storm : : expressions : : Variable , std : : vector < Assignment const * > > collectedArrayAccessAssignments ;
@ -253,12 +433,14 @@ namespace storm {
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 ) ;
auto const & replacement = * arrayVariableReplacements [ index ] ;
auto arrayAccessExpression = std : : make_shared < storm : : expressions : : ArrayAccessExpression > ( expressionManager , assignment . getAssignedExpression ( ) . getType ( ) . getElementType ( ) , assignment . getAssignedExpression ( ) . getBaseExpressionPointer ( ) , expressionManager . integer ( index ) . getBaseExpressionPointer ( ) ) - > toExpression ( ) ;
arrayAccessExpression = arrayExprEliminator - > eliminate ( arrayAccessExpression , getOutOfBoundsValue ( replacement ) ) ;
newAssignments . emplace_back ( LValue ( replacement ) , arrayAccessExpression , level ) ;
}
continue ;
}
newAssignments . push _back( assignment ) ;
newAssignments . emplace _back( assignment . getLValue ( ) , arrayExprEliminator - > eliminate ( assignment . getAssignedExpression ( ) ) , assignment . getLevel ( ) ) ;
}
for ( auto const & arrayAssignments : collectedArrayAccessAssignments ) {
insertLValueArrayAccessReplacements ( arrayAssignments . second , replacements . at ( arrayAssignments . first ) , level , newAssignments ) ;
@ -276,7 +458,7 @@ namespace storm {
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 ( ) ;
initValue = arrayExprEliminator - > eliminate ( 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 ) ;
@ -324,31 +506,50 @@ namespace storm {
if ( onlyConstantIndices ) {
for ( auto const & aa : arrayAccesses ) {
LValue lvalue ( * arrayVariableReplacements . at ( aa - > getLValue ( ) . getArrayIndex ( ) . evaluateAsInt ( ) ) ) ;
newAssignments . emplace_back ( lvalue , aa - > getAssignedExpression ( ) , level ) ;
newAssignments . emplace_back ( lvalue , arrayExprEliminator - > eliminate ( a a - > 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 ) ;
assignedExpression = storm : : expressions : : ite ( aa - > getLValue ( ) . getArrayIndex ( ) = = indexExpression , arrayExprEliminator - > eliminate ( a a - > getAssignedExpression ( ) ) , assignedExpression ) ;
newAssignments . emplace_back ( LValue ( * arrayVariableReplacements [ index ] ) , assignedExpression , level ) ;
}
}
}
}
storm : : expressions : : Expression getOutOfBoundsValue ( Variable const & var ) const {
if ( var . hasInitExpression ( ) ) {
return var . getInitExpression ( ) ;
}
if ( var . isBooleanVariable ( ) ) {
return expressionManager . boolean ( false ) ;
}
if ( var . isBoundedIntegerVariable ( ) ) {
return var . asBoundedIntegerVariable ( ) . getLowerBound ( ) ;
}
if ( var . isUnboundedIntegerVariable ( ) ) {
return expressionManager . integer ( 0 ) ;
}
if ( var . isRealVariable ( ) ) {
return expressionManager . rational ( 0.0 ) ;
}
STORM_LOG_THROW ( false , storm : : exceptions : : UnexpectedException , " unhandled variabe type " ) ;
return storm : : expressions : : Expression ( ) ;
}
std : : unique_ptr < ArrayExpressionEliminationVisitor > arrayExprEliminator ;
storm : : expressions : : ExpressionManager & expressionManager ;
bool const keepNonTrivialArrayAccess ;
std : : unordered_map < storm : : expressions : : Variable , std : : size_t > const & arraySizes ;
} ;
} // 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 ) ;
ArrayEliminatorData result = detail : : ArrayVariableReplacer ( model . getExpressionManager ( ) , keepNonTrivialArrayAccess , sizes ) . replace ( model ) ;
model . finalize ( ) ;
return result ;