@ -1,11 +1,14 @@
# include "src/modelchecker/multiobjective/helper/SparseMaMultiObjectiveWeightVectorChecker.h"
# include <cmath>
# include "src/adapters/CarlAdapter.h"
# include "src/models/sparse/MarkovAutomaton.h"
# include "src/models/sparse/StandardRewardModel.h"
# include "src/utility/macros.h"
# include "src/utility/vector.h"
# include "src/exceptions/InvalidOperationException.h"
namespace storm {
namespace modelchecker {
@ -26,11 +29,17 @@ namespace storm {
}
}
}
template < class SparseMaModelType >
void SparseMaMultiObjectiveWeightVectorChecker < SparseMaModelType > : : boundedPhase ( std : : vector < ValueType > const & weightVector , std : : vector < ValueType > & weightedRewardVector ) {
STORM_LOG_ERROR ( " BOUNDED OBJECTIVES FOR MARKOV AUTOMATA NOT YET IMPLEMENTED " ) ;
// Set the digitization constant
ValueType digitizationConstant = getDigitizationConstant ( ) ;
std : : cout < < " Got delta: " < < digitizationConstant < < std : : endl ;
/*
// Allocate some memory so this does not need to happen for each time epoch
std : : vector < uint_fast64_t > optimalChoicesInCurrentEpoch ( this - > data . preprocessedModel . getNumberOfStates ( ) ) ;
@ -84,9 +93,91 @@ namespace storm {
}
*/
}
template < class SparseMaModelType >
template < typename VT , typename std : : enable_if < storm : : NumberTraits < VT > : : SupportsExponential , int > : : type >
VT SparseMaMultiObjectiveWeightVectorChecker < SparseMaModelType > : : getDigitizationConstant ( ) const {
STORM_LOG_DEBUG ( " Retrieving digitization constant " ) ;
// We need to find a delta such that for each pair of lower and upper bounds it holds that
// 1 - e^(-maxRate lowerbound) * (1 + maxRate delta) ^ (lowerbound / delta) + 1-e^(-maxRate upperbound) * (1 + maxRate delta) ^ (upperbound / delta) <= maximumLowerUpperBoundGap
// and lowerbound/delta , upperbound/delta are natural numbers.
// Initialize some data for fast and easy access
VT const maxRate = this - > data . preprocessedModel . getMaximalExitRate ( ) ;
std : : vector < std : : pair < VT , VT > > lowerUpperBounds ;
std : : vector < std : : pair < VT , VT > > eToPowerOfMinusMaxRateTimesBound ;
for ( auto const & obj : this - > data . objectives ) {
if ( obj . timeBounds ) {
if ( obj . timeBounds - > which ( ) = = 0 ) {
lowerUpperBounds . emplace_back ( storm : : utility : : zero < VT > ( ) , boost : : get < uint_fast64_t > ( * obj . timeBounds ) ) ;
eToPowerOfMinusMaxRateTimesBound . emplace_back ( storm : : utility : : one < VT > ( ) , std : : exp ( - maxRate * lowerUpperBounds . back ( ) . second ) ) ;
} else {
auto const & pair = boost : : get < std : : pair < double , double > > ( * obj . timeBounds ) ;
lowerUpperBounds . emplace_back ( storm : : utility : : convertNumber < VT > ( pair . first ) , storm : : utility : : convertNumber < VT > ( pair . second ) ) ;
eToPowerOfMinusMaxRateTimesBound . emplace_back ( std : : exp ( - maxRate * lowerUpperBounds . back ( ) . first ) , std : : exp ( - maxRate * lowerUpperBounds . back ( ) . second ) ) ;
}
}
}
VT smallestNonZeroBound = storm : : utility : : zero < VT > ( ) ;
for ( auto const & bounds : lowerUpperBounds ) {
if ( ! storm : : utility : : isZero ( bounds . first ) ) {
smallestNonZeroBound = storm : : utility : : isZero ( smallestNonZeroBound ) ? bounds . first : std : : min ( smallestNonZeroBound , bounds . first ) ;
} else if ( ! storm : : utility : : isZero ( bounds . second ) ) {
smallestNonZeroBound = storm : : utility : : isZero ( smallestNonZeroBound ) ? bounds . second : std : : min ( smallestNonZeroBound , bounds . second ) ;
}
}
if ( storm : : utility : : isZero ( smallestNonZeroBound ) ) {
// All time bounds are zero which means that any delta>0 is valid.
// This includes the case where there are no time bounds
return storm : : utility : : one < VT > ( ) ;
}
// We brute-force a delta, since a direct computation is apparently not easy.
// Also note that the number of times this loop runs is a lower bound for the number of minMaxSolver invocations.
// Hence, this brute-force approach will most likely not be a bottleneck.
uint_fast64_t smallestStepBound = 1 ;
VT delta = smallestNonZeroBound / smallestStepBound ;
while ( true ) {
bool deltaValid = true ;
for ( auto const & bounds : lowerUpperBounds ) {
if ( bounds . first / delta ! = std : : floor ( bounds . first / delta ) | |
bounds . second / delta ! = std : : floor ( bounds . second / delta ) ) {
deltaValid = false ;
break ;
}
}
if ( deltaValid ) {
for ( uint_fast64_t i = 0 ; i < lowerUpperBounds . size ( ) ; + + i ) {
VT precisionOfObj = storm : : utility : : one < VT > ( ) - ( eToPowerOfMinusMaxRateTimesBound [ i ] . first * storm : : utility : : pow ( storm : : utility : : one < VT > ( ) + maxRate * delta , lowerUpperBounds [ i ] . first / delta ) ) ;
precisionOfObj + = storm : : utility : : one < VT > ( ) - ( eToPowerOfMinusMaxRateTimesBound [ i ] . second * storm : : utility : : pow ( storm : : utility : : one < VT > ( ) + maxRate * delta , lowerUpperBounds [ i ] . second / delta ) ) ;
if ( precisionOfObj > this - > maximumLowerUpperBoundGap ) {
deltaValid = false ;
break ;
}
}
}
if ( deltaValid ) {
break ;
}
+ + smallestStepBound ;
STORM_LOG_ASSERT ( delta > smallestNonZeroBound / smallestStepBound , " Digitization constant is expected to become smaller in every iteration " ) ;
delta = smallestNonZeroBound / smallestStepBound ;
}
STORM_LOG_DEBUG ( " Found digitization constant: " < < delta < < " . At least " < < smallestStepBound < < " digitization steps will be necessarry " ) ;
return delta ;
}
template < class SparseMaModelType >
template < typename VT , typename std : : enable_if < ! storm : : NumberTraits < VT > : : SupportsExponential , int > : : type >
VT SparseMaMultiObjectiveWeightVectorChecker < SparseMaModelType > : : getDigitizationConstant ( ) const {
STORM_LOG_THROW ( false , storm : : exceptions : : InvalidOperationException , " Computing bounded probabilities of MAs is unsupported for this value type. " ) ;
}
template class SparseMaMultiObjectiveWeightVectorChecker < storm : : models : : sparse : : MarkovAutomaton < double > > ;
template double SparseMaMultiObjectiveWeightVectorChecker < storm : : models : : sparse : : MarkovAutomaton < double > > : : getDigitizationConstant < double > ( ) const ;
# ifdef STORM_HAVE_CARL
template storm : : RationalNumber SparseMaMultiObjectiveWeightVectorChecker < storm : : models : : sparse : : MarkovAutomaton < storm : : RationalNumber > > : : getDigitizationConstant < storm : : RationalNumber > ( ) const ;
template class SparseMaMultiObjectiveWeightVectorChecker < storm : : models : : sparse : : MarkovAutomaton < storm : : RationalNumber > > ;
# endif