@ -269,26 +269,42 @@ namespace storm {
template < typename ParametricSparseModelType , typename ConstantType >
ConstantType ApproximationModel < ParametricSparseModelType , ConstantType > : : computeInitialStateValue ( ParameterRegion < ParametricType > const & region , bool computeLowerBounds ) {
instantiate ( region , computeLowerBounds ) ;
std : : vector < std : : size_t > policy ;
invokeSolver ( computeLowerBounds , policy ) ;
std : : shared_ptr < Policy > policy ;
if ( computeLowerBounds & & ! this - > minimizingPolicies . empty ( ) ) {
policy = std : : make_shared < Policy > ( * * ( this - > minimizingPolicies . begin ( ) ) ) ; //we need a fresh policy, initialized with the values of the old one
} else if ( ! computeLowerBounds & & ! this - > maximizingPolicies . empty ( ) ) {
policy = std : : make_shared < Policy > ( * * ( this - > maximizingPolicies . begin ( ) ) ) ; //we need a fresh policy, initialized with the values of the old one
} else {
policy = std : : make_shared < Policy > ( this - > matrixData . matrix . getRowGroupCount ( ) ) ;
}
invokeSolver ( computeLowerBounds , * policy ) ;
if ( computeLowerBounds ) {
this - > minimizingPolicies . insert ( policy ) ;
std : : cout < < minimizingPolicies . size ( ) < < std : : endl ;
} else {
this - > maximizingPolicies . insert ( policy ) ;
std : : cout < < maximizingPolicies . size ( ) < < std : : endl ;
}
//TODO: policy for games.
//TODO: do this only when necessary.
//TODO: (maybe) when a few parameters are mapped to another value, build a "nicer" scheduler and check whether it induces values that are more optimal.
if ( policy . empty ( ) ) return this - > eqSysResult [ this - > eqSysInitIndex ] ;
if ( policy - > empty ( ) ) return this - > eqSysResult [ this - > eqSysInitIndex ] ;
//Get the set of parameters which are (according to the policy) always mapped to the same region boundary.
//First, collect all (relevant) parameters, i.e., the ones that are set to the lower or upper boundary.
std : : map < VariableType , RegionBoundary > fixedVariables ;
std : : map < VariableType , std : : pair < std : : size_t , std : : size_t > > VarCount ;
std : : size_t substitutionCount = 0 ;
for ( auto const & substitution : this - > funcSubData . substitutions ) {
for ( auto const & sub : substitution ) {
if ( sub . second ! = RegionBoundary : : UNSPECIFIED ) {
fixedVariables . insert ( typename std : : map < VariableType , RegionBoundary > : : value_type ( sub . first , RegionBoundary : : UNSPECIFIED ) ) ;
VarCount . insert ( typename std : : map < VariableType , std : : pair < std : : size_t , std : : size_t > > : : value_type ( sub . first , std : : pair < std : : size_t , std : : size_t > ( 0 , 0 ) ) ) ;
}
}
}
//Now erase the parameters that are mapped to different boundaries.
for ( std : : size_t rowGroup = 0 ; rowGroup < this - > matrixData . matrix . getRowGroupCount ( ) ; + + rowGroup ) {
std : : size_t row = this - > matrixData . matrix . getRowGroupIndices ( ) [ rowGroup ] + policy [ rowGroup ] ;
std : : size_t row = this - > matrixData . matrix . getRowGroupIndices ( ) [ rowGroup ] + ( * policy ) [ rowGroup ] ;
for ( std : : pair < VariableType , RegionBoundary > const & sub : this - > funcSubData . substitutions [ this - > matrixData . rowSubstitutions [ row ] ] ) {
auto fixedVarIt = fixedVariables . find ( sub . first ) ;
if ( fixedVarIt ! = fixedVariables . end ( ) & & fixedVarIt - > second ! = sub . second ) {
@ -299,15 +315,29 @@ namespace storm {
fixedVariables . erase ( fixedVarIt ) ;
}
}
auto varcountIt = VarCount . find ( sub . first ) ;
if ( sub . second = = RegionBoundary : : LOWER ) {
+ + ( varcountIt - > second . first ) ;
} else if ( sub . second = = RegionBoundary : : UPPER ) {
+ + ( varcountIt - > second . second ) ;
}
+ + substitutionCount ;
}
if ( fixedVariables . empty ( ) ) {
break ;
// break;
}
}
// std::cout << "Used Approximation" << std::endl;
for ( auto const & varcount : VarCount ) {
if ( varcount . second . first > 0 & & varcount . second . second > 0 ) {
// std::cout << " Variable " << varcount.first << " has been set to lower " << varcount.second.first << " times and to upper " << varcount.second.second << " times. (total: " << substitutionCount << ")" << std::endl;
}
}
for ( auto const & fixVar : fixedVariables ) {
//std::cout << "APPROXMODEL: variable " << fixVar.first << " is always mapped to " << fixVar.second << std::endl;
//std::cout << " APPROXMODEL: variable " << fixVar.first << " is always mapped to " << fixVar.second << std::endl;
}
// std::cout << " Result is " << this->eqSysResult[this->eqSysInitIndex] << std::endl;
return this - > eqSysResult [ this - > eqSysInitIndex ] ;
}
@ -342,17 +372,17 @@ namespace storm {
auto & result = functionResult . second ;
result = computeLowerBounds ? storm : : utility : : infinity < ConstantType > ( ) : storm : : utility : : zero < ConstantType > ( ) ;
//Iterate over the different combinations of lower and upper bounds and update the min and max values
auto const & vertices = region . getVerticesOfRegion ( unspecifiedParameters [ funcSub . getSubstitution ( ) ] ) ;
auto const & vertices = region . getVerticesOfRegion ( unspecifiedParameters [ funcSub . second ] ) ;
for ( auto const & vertex : vertices ) {
//extend the substitution
for ( auto const & vertexSub : vertex ) {
instantiatedSubs [ funcSub . getSubstitution ( ) ] [ vertexSub . first ] = vertexSub . second ;
instantiatedSubs [ funcSub . second ] [ vertexSub . first ] = vertexSub . second ;
}
//evaluate the function
ConstantType currValue = storm : : utility : : region : : convertNumber < ConstantType > (
storm : : utility : : region : : evaluateFunction (
funcSub . getFunction ( ) ,
instantiatedSubs [ funcSub . getSubstitution ( ) ]
funcSub . first ,
instantiatedSubs [ funcSub . second ]
)
) ;
result = computeLowerBounds ? std : : min ( result , currValue ) : std : : max ( result , currValue ) ;
@ -370,16 +400,16 @@ namespace storm {
template < >
void ApproximationModel < storm : : models : : sparse : : Dtmc < storm : : RationalFunction > , double > : : invokeSolver ( bool computeLowerBounds , std : : vector < std : : size_t > & policy ) {
void ApproximationModel < storm : : models : : sparse : : Dtmc < storm : : RationalFunction > , double > : : invokeSolver ( bool computeLowerBounds , Policy & policy ) {
storm : : solver : : SolveGoal goal ( computeLowerBounds ) ;
std : : unique_ptr < storm : : solver : : MinMaxLinearEquationSolver < double > > solver = storm : : solver : : configureMinMaxLinearEquationSolver ( goal , storm : : utility : : solver : : MinMaxLinearEquationSolverFactory < double > ( ) , this - > matrixData . matrix ) ;
solver - > setPolicyTracking ( ) ;
solver - > solveEquationSystem ( this - > eqSysResult , this - > vectorData . vector ) ;
solver - > solveEquationSystem ( goal . direction ( ) , this - > eqSysResult , this - > vectorData . vector , nullptr , nullptr , & policy ) ;
policy = solver - > getPolicy ( ) ;
}
template < >
void ApproximationModel < storm : : models : : sparse : : Mdp < storm : : RationalFunction > , double > : : invokeSolver ( bool computeLowerBounds , std : : vector < std : : size_t > & policy ) {
void ApproximationModel < storm : : models : : sparse : : Mdp < storm : : RationalFunction > , double > : : invokeSolver ( bool computeLowerBounds , Policy & policy ) {
storm : : solver : : SolveGoal player2Goal ( computeLowerBounds ) ;
std : : unique_ptr < storm : : solver : : GameSolver < double > > solver = storm : : utility : : solver : : GameSolverFactory < double > ( ) . create ( this - > player1Matrix , this - > matrixData . matrix ) ;
solver - > solveGame ( this - > player1Goal . direction ( ) , player2Goal . direction ( ) , this - > eqSysResult , this - > vectorData . vector ) ;