@ -85,17 +85,94 @@ namespace storm {
template < class SparseMdpModelType >
void SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : computeEpochSolution ( typename MultiDimensionalRewardUnfolding < ValueType , false > : : Epoch const & epoch , std : : vector < ValueType > const & weightVector , EpochCheckingData & cachedData ) {
auto & epochModel = rewardUnfolding . setCurrentEpoch ( epoch ) ;
updateCachedData ( epochModel , cachedData , weightVector ) ;
+ + numCheckedEpochs ;
swEqBuilding . start ( ) ;
+ + numCheckedEpochs ;
swEpochModelBuild . start ( ) ;
auto & epochModel = rewardUnfolding . setCurrentEpoch ( epoch ) ;
swEpochModelBuild . stop ( ) ;
swEpochModelAnalysis . start ( ) ;
std : : vector < typename MultiDimensionalRewardUnfolding < ValueType , false > : : SolutionType > result ;
result . reserve ( epochModel . epochInStates . getNumberOfSetBits ( ) ) ;
uint64_t solutionSize = this - > objectives . size ( ) + 1 ;
// If the epoch matrix is empty we do not need to solve linear equation systems
if ( epochModel . epochMatrix . getEntryCount ( ) = = 0 ) {
std : : vector < ValueType > weights = weightVector ;
for ( uint64_t objIndex = 0 ; objIndex < this - > objectives . size ( ) ; + + objIndex ) {
if ( storm : : solver : : minimize ( this - > objectives [ objIndex ] . formula - > getOptimalityType ( ) ) ) {
weights [ objIndex ] * = - storm : : utility : : one < ValueType > ( ) ;
}
}
auto stepSolutionIt = epochModel . stepSolutions . begin ( ) ;
auto stepChoiceIt = epochModel . stepChoices . begin ( ) ;
for ( auto const & state : epochModel . epochInStates ) {
// Obtain the best choice for this state according to the weighted combination of objectives
ValueType bestValue ;
uint64_t bestChoice = std : : numeric_limits < uint64_t > : : max ( ) ;
auto bestChoiceStepSolutionIt = epochModel . stepSolutions . end ( ) ;
uint64_t lastChoice = epochModel . epochMatrix . getRowGroupIndices ( ) [ state + 1 ] ;
bool firstChoice = true ;
for ( uint64_t choice = epochModel . epochMatrix . getRowGroupIndices ( ) [ state ] ; choice < lastChoice ; + + choice ) {
ValueType choiceValue = storm : : utility : : zero < ValueType > ( ) ;
// Obtain the (weighted) objective rewards
for ( uint64_t objIndex = 0 ; objIndex < this - > objectives . size ( ) ; + + objIndex ) {
if ( epochModel . objectiveRewardFilter [ objIndex ] . get ( choice ) ) {
choiceValue + = weights [ objIndex ] * epochModel . objectiveRewards [ objIndex ] [ choice ] ;
}
}
// Obtain the step solution if this is a step choice
while ( * stepChoiceIt < choice ) {
+ + stepChoiceIt ;
+ + stepSolutionIt ;
}
if ( * stepChoiceIt = = choice ) {
choiceValue + = stepSolutionIt - > front ( ) ;
// Check if this choice is better
if ( firstChoice | | choiceValue > bestValue ) {
bestValue = std : : move ( choiceValue ) ;
bestChoice = choice ;
bestChoiceStepSolutionIt = stepSolutionIt ;
}
} else if ( firstChoice | | choiceValue > bestValue ) {
bestValue = std : : move ( choiceValue ) ;
bestChoice = choice ;
bestChoiceStepSolutionIt = epochModel . stepSolutions . end ( ) ;
}
firstChoice = false ;
}
// Insert the solution w.r.t. this choice
result . emplace_back ( ) ;
result . back ( ) . reserve ( solutionSize ) ;
result . back ( ) . push_back ( std : : move ( bestValue ) ) ;
if ( bestChoiceStepSolutionIt ! = epochModel . stepSolutions . end ( ) ) {
for ( uint64_t objIndex = 0 ; objIndex < this - > objectives . size ( ) ; + + objIndex ) {
if ( epochModel . objectiveRewardFilter [ objIndex ] . get ( bestChoice ) ) {
result . back ( ) . push_back ( ( epochModel . objectiveRewards [ objIndex ] [ bestChoice ] + ( * bestChoiceStepSolutionIt ) [ objIndex + 1 ] ) ) ;
} else {
result . back ( ) . push_back ( ( * bestChoiceStepSolutionIt ) [ objIndex + 1 ] ) ;
}
}
} else {
for ( uint64_t objIndex = 0 ; objIndex < this - > objectives . size ( ) ; + + objIndex ) {
if ( epochModel . objectiveRewardFilter [ objIndex ] . get ( bestChoice ) ) {
result . back ( ) . push_back ( ( epochModel . objectiveRewards [ objIndex ] [ bestChoice ] ) ) ;
} else {
result . back ( ) . push_back ( storm : : utility : : zero < ValueType > ( ) ) ;
}
}
}
}
} else {
updateCachedData ( epochModel , cachedData , weightVector ) ;
// Formulate a min-max equation system max(A*x+b)=x for the weighted sum of the objectives
swAux1 . start ( ) ;
assert ( cachedData . bMinMax . capacity ( ) > = epochModel . epochMatrix . getRowCount ( ) ) ;
assert ( cachedData . xMinMax . size ( ) = = epochModel . epochMatrix . getRowGroupCount ( ) ) ;
cachedData . bMinMax . assign ( epochModel . epochMatrix . getRowCount ( ) , storm : : utility : : zero < ValueType > ( ) ) ;
@ -113,14 +190,9 @@ namespace storm {
cachedData . bMinMax [ choice ] + = stepSolutionIt - > front ( ) ;
+ + stepSolutionIt ;
}
swAux1 . stop ( ) ;
// Invoke the min max solver
swEqBuilding . stop ( ) ;
swMinMaxSolving . start ( ) ;
cachedData . minMaxSolver - > solveEquations ( cachedData . xMinMax , cachedData . bMinMax ) ;
swMinMaxSolving . stop ( ) ;
swEqBuilding . start ( ) ;
for ( auto const & state : epochModel . epochInStates ) {
result . emplace_back ( ) ;
result . back ( ) . reserve ( solutionSize ) ;
@ -132,7 +204,6 @@ namespace storm {
if ( cachedData . schedulerChoices ! = choices ) {
std : : vector < uint64_t > choicesTmp = choices ;
cachedData . minMaxSolver - > setInitialScheduler ( std : : move ( choicesTmp ) ) ;
swAux2 . start ( ) ;
+ + numSchedChanges ;
cachedData . schedulerChoices = choices ;
storm : : solver : : GeneralLinearEquationSolverFactory < ValueType > linEqSolverFactory ;
@ -143,11 +214,9 @@ namespace storm {
}
cachedData . linEqSolver = linEqSolverFactory . create ( std : : move ( subMatrix ) ) ;
cachedData . linEqSolver - > setCachingEnabled ( true ) ;
swAux2 . stop ( ) ;
}
// Formulate for each objective the linear equation system induced by the performed choices
swAux3 . start ( ) ;
assert ( cachedData . bLinEq . size ( ) = = choices . size ( ) ) ;
for ( uint64_t objIndex = 0 ; objIndex < this - > objectives . size ( ) ; + + objIndex ) {
auto const & obj = this - > objectives [ objIndex ] ;
@ -195,26 +264,21 @@ namespace storm {
req . clearUpperBounds ( ) ;
}
STORM_LOG_THROW ( req . empty ( ) , storm : : exceptions : : UncheckedRequirementException , " At least one requirement of the LinearEquationSolver was not met. " ) ;
swEqBuilding . stop ( ) ;
swLinEqSolving . start ( ) ;
cachedData . linEqSolver - > solveEquations ( x , cachedData . bLinEq ) ;
swLinEqSolving . stop ( ) ;
swEqBuilding . start ( ) ;
auto resultIt = result . begin ( ) ;
for ( auto const & state : epochModel . epochInStates ) {
resultIt - > push_back ( x [ state ] ) ;
+ + resultIt ;
}
}
swEqBuilding . stop ( ) ;
swAux3 . stop ( ) ;
}
rewardUnfolding . setSolutionForCurrentEpoch ( std : : move ( result ) ) ;
swEpochModelAnalysis . stop ( ) ;
}
template < class SparseMdpModelType >
void SparseMdpRewardBoundedPcaaWeightVectorChecker < SparseMdpModelType > : : updateCachedData ( typename MultiDimensionalRewardUnfolding < ValueType , false > : : EpochModel const & epochModel , EpochCheckingData & cachedData , std : : vector < ValueType > const & weightVector ) {
if ( epochModel . epochMatrixChanged ) {
swDataUpdate . start ( ) ;
// Update the cached MinMaxSolver data
cachedData . bMinMax . resize ( epochModel . epochMatrix . getRowCount ( ) ) ;
@ -249,7 +313,6 @@ namespace storm {
for ( auto & x_o : cachedData . xLinEq ) {
x_o . assign ( epochModel . epochMatrix . getRowGroupCount ( ) , storm : : utility : : zero < ValueType > ( ) ) ;
}
swDataUpdate . stop ( ) ;
}
}