TimQu
7 years ago
4 changed files with 332 additions and 238 deletions
-
237src/storm/modelchecker/multiobjective/rewardbounded/EpochManager.cpp
-
55src/storm/modelchecker/multiobjective/rewardbounded/EpochManager.h
-
261src/storm/modelchecker/multiobjective/rewardbounded/MultiDimensionalRewardUnfolding.cpp
-
17src/storm/modelchecker/multiobjective/rewardbounded/MultiDimensionalRewardUnfolding.h
@ -0,0 +1,237 @@ |
|||
#include "storm/modelchecker/multiobjective/rewardbounded/EpochManager.h"
|
|||
|
|||
#include "storm/utility/macros.h"
|
|||
|
|||
#include "storm/exceptions/IllegalArgumentException.h"
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace multiobjective { |
|||
|
|||
EpochManager::EpochManager() : dimensionCount(0) { |
|||
// Intentionally left empty
|
|||
} |
|||
|
|||
EpochManager::EpochManager(uint64_t dimensionCount) : dimensionCount(dimensionCount) { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
bitsPerDimension = 64 / dimensionCount; |
|||
if (dimensionCount == 1) { |
|||
dimensionBitMask = -1ull; |
|||
} else { |
|||
dimensionBitMask = (1ull << bitsPerDimension) - 1; |
|||
} |
|||
|
|||
if (dimensionCount * bitsPerDimension == 64ull) { |
|||
relevantBitsMask = -1ull; |
|||
} else { |
|||
relevantBitsMask = (1ull << (dimensionCount * bitsPerDimension)) - 1; |
|||
} |
|||
} |
|||
|
|||
uint64_t const& EpochManager::getDimensionCount() const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
return dimensionCount; |
|||
} |
|||
|
|||
bool EpochManager::compareEpochClass(Epoch const& epoch1, Epoch const& epoch2) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
uint64_t mask = dimensionBitMask; |
|||
for (uint64_t d = 0; d < dimensionCount; ++d) { |
|||
if (((epoch1 & mask) == mask) != ((epoch2 & mask) == mask)) { |
|||
assert(getEpochClass(epoch1) != getEpochClass(epoch2)); |
|||
return false; |
|||
} |
|||
mask = mask << bitsPerDimension; |
|||
} |
|||
assert(getEpochClass(epoch1) == getEpochClass(epoch2)); |
|||
return true; |
|||
} |
|||
|
|||
typename EpochManager::EpochClass EpochManager::getEpochClass(Epoch const& epoch) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
EpochClass result = 0; |
|||
uint64_t mask = dimensionBitMask; |
|||
for (uint64_t d = 0; d < dimensionCount; ++d) { |
|||
if ((epoch & mask) == mask) { |
|||
++result; |
|||
} |
|||
result = result << 1; |
|||
mask = mask << bitsPerDimension; |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
typename EpochManager::Epoch EpochManager::getSuccessorEpoch(Epoch const& epoch, Epoch const& step) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
|
|||
// Start with dimension zero
|
|||
uint64_t mask = dimensionBitMask; |
|||
uint64_t e_d = epoch & mask; |
|||
uint64_t s_d = step & mask; |
|||
assert(s_d != mask); |
|||
uint64_t result = (e_d < s_d || e_d == mask) ? mask : e_d - s_d; |
|||
|
|||
// Consider the remaining dimensions
|
|||
for (uint64_t d = 1; d < dimensionCount; ++d) { |
|||
mask = mask << bitsPerDimension; |
|||
e_d = epoch & mask; |
|||
s_d = step & mask; |
|||
assert(s_d != mask); |
|||
result |= ((e_d < s_d || e_d == mask) ? mask : e_d - s_d); |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
std::vector<typename EpochManager::Epoch> EpochManager::getPredecessorEpochs(Epoch const& epoch, Epoch const& step) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
|
|||
} |
|||
|
|||
void EpochManager::gatherPredecessorEpochs(std::set<Epoch>& gatheredPredecessorEpochs, Epoch const& epoch, Epoch const& step) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
|
|||
} |
|||
|
|||
bool EpochManager::isValidDimensionValue(uint64_t const& value) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
return ((value & dimensionBitMask) == value) && value != dimensionBitMask; |
|||
} |
|||
|
|||
bool EpochManager::isZeroEpoch(Epoch const& epoch) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
return (epoch & relevantBitsMask) == 0; |
|||
} |
|||
|
|||
bool EpochManager::isBottomEpoch(Epoch const& epoch) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
return (epoch & relevantBitsMask) == relevantBitsMask; |
|||
} |
|||
|
|||
bool EpochManager::hasBottomDimension(Epoch const& epoch) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
uint64_t mask = dimensionBitMask; |
|||
for (uint64_t d = 0; d < dimensionCount; ++d) { |
|||
if ((epoch | mask) == epoch) { |
|||
return true; |
|||
} |
|||
mask = mask << bitsPerDimension; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void EpochManager::setBottomDimension(Epoch& epoch, uint64_t const& dimension) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
epoch |= (dimensionBitMask << (dimension * bitsPerDimension)); |
|||
} |
|||
|
|||
void EpochManager::setDimensionOfEpoch(Epoch& epoch, uint64_t const& dimension, uint64_t const& value) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
STORM_LOG_ASSERT(isValidDimensionValue(value), "The dimension value " << value << " is too high."); |
|||
epoch &= ~(dimensionBitMask << (dimension * bitsPerDimension)); |
|||
epoch |= (value << (dimension * bitsPerDimension)); |
|||
} |
|||
|
|||
bool EpochManager::isBottomDimension(Epoch const& epoch, uint64_t const& dimension) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
return (epoch | (dimensionBitMask << (dimension * bitsPerDimension))) == epoch; |
|||
} |
|||
|
|||
uint64_t EpochManager::getDimensionOfEpoch(Epoch const& epoch, uint64_t const& dimension) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
return (epoch >> (dimension * bitsPerDimension)) & dimensionBitMask; |
|||
} |
|||
|
|||
std::string EpochManager::toString(Epoch const& epoch) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
std::string res = "<" + (isBottomDimension(epoch, 0) ? "_" : std::to_string(getDimensionOfEpoch(epoch, 0))); |
|||
for (uint64_t d = 1; d < dimensionCount; ++d) { |
|||
res += ", "; |
|||
res += (isBottomDimension(epoch, d) ? "_" : std::to_string(getDimensionOfEpoch(epoch, d))); |
|||
} |
|||
res += ">"; |
|||
return res; |
|||
} |
|||
|
|||
bool EpochManager::epochClassZigZagOrder(Epoch const& epoch1, Epoch const& epoch2) const { |
|||
STORM_LOG_THROW(dimensionCount > 0, storm::exceptions::IllegalArgumentException, "Invoked EpochManager with zero dimension count."); |
|||
|
|||
// Return true iff epoch 1 has to be computed before epoch 2
|
|||
|
|||
// Check whether the number of bottom dimensions is not equal
|
|||
uint64_t e1Count = 0; |
|||
uint64_t e2Count = 0; |
|||
for (uint64_t dim = 0; dim < dimensionCount; ++dim) { |
|||
if (isBottomDimension(epoch1, dim)) { |
|||
++e1Count; |
|||
} |
|||
if (isBottomDimension(epoch2, dim)) { |
|||
++e2Count; |
|||
} |
|||
} |
|||
if (e1Count > e2Count) { |
|||
return true; |
|||
} else if (e1Count < e2Count) { |
|||
return false; |
|||
} |
|||
|
|||
// Check the epoch classes
|
|||
EpochClass e1Class = getEpochClass(epoch1); |
|||
uint64_t e2Class = getEpochClass(epoch2); |
|||
if (e1Class < e2Class) { |
|||
return true; |
|||
} else if (e1Class > e2Class) { |
|||
return false; |
|||
} |
|||
assert(compareEpochClass(epoch1, epoch2)); |
|||
|
|||
// check whether the sum of dimensions is the same
|
|||
uint64_t e1Sum = 0; |
|||
uint64_t e2Sum = 0; |
|||
for (uint64_t dim = 0; dim < dimensionCount; ++dim) { |
|||
if (!isBottomDimension(epoch1, dim)) { |
|||
assert(!isBottomDimension(epoch2, dim)); |
|||
e1Sum += getDimensionOfEpoch(epoch1, dim); |
|||
e2Sum += getDimensionOfEpoch(epoch2, dim); |
|||
} |
|||
} |
|||
if (e1Sum < e2Sum) { |
|||
return true; |
|||
} else if (e1Sum > e2Sum) { |
|||
return false; |
|||
} |
|||
|
|||
// find the first dimension where the epochs do not match.
|
|||
// if the sum is even, we search from left to right, otherwise from right to left
|
|||
bool sumEven = (e1Sum % 2) == 0; |
|||
if (sumEven) { |
|||
for (uint64_t dim = 0; dim < dimensionCount; ++dim) { |
|||
uint64_t e1Value = getDimensionOfEpoch(epoch1, dim); |
|||
uint64_t e2Value = getDimensionOfEpoch(epoch2, dim); |
|||
if (e1Value < e2Value) { |
|||
return true; |
|||
} else if (e1Value > e2Value) { |
|||
return false; |
|||
} |
|||
} |
|||
} else { |
|||
uint64_t dim = dimensionCount; |
|||
while (dim > 0) { |
|||
--dim; |
|||
uint64_t e1Value = getDimensionOfEpoch(epoch1, dim); |
|||
uint64_t e2Value = getDimensionOfEpoch(epoch2, dim); |
|||
if (e1Value < e2Value) { |
|||
return true; |
|||
} else if (e1Value > e2Value) { |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// reaching this point means that the epochs are equal
|
|||
assert(epoch1 == epoch2); |
|||
return false; |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,55 @@ |
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
#include <set> |
|||
#include <string> |
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace multiobjective { |
|||
|
|||
|
|||
class EpochManager { |
|||
public: |
|||
|
|||
typedef uint64_t Epoch; // The number of reward steps that are "left" for each dimension |
|||
typedef uint64_t EpochClass; // The number of reward steps that are "left" for each dimension |
|||
|
|||
EpochManager(); |
|||
EpochManager(uint64_t dimensionCount); |
|||
|
|||
uint64_t const& getDimensionCount() const; |
|||
|
|||
bool compareEpochClass(Epoch const& epoch1, Epoch const& epoch2) const; |
|||
EpochClass getEpochClass(Epoch const& epoch) const; |
|||
|
|||
Epoch getSuccessorEpoch(Epoch const& epoch, Epoch const& step) const; |
|||
std::vector<Epoch> getPredecessorEpochs(Epoch const& epoch, Epoch const& step) const; |
|||
void gatherPredecessorEpochs(std::set<Epoch>& gatheredPredecessorEpochs, Epoch const& epoch, Epoch const& step) const; |
|||
|
|||
bool isZeroEpoch(Epoch const& epoch) const; |
|||
bool isBottomEpoch(Epoch const& epoch) const; |
|||
bool hasBottomDimension(Epoch const& epoch) const; |
|||
|
|||
bool isValidDimensionValue(uint64_t const& value) const; |
|||
|
|||
void setBottomDimension(Epoch& epoch, uint64_t const& dimension) const; |
|||
void setDimensionOfEpoch(Epoch& epoch, uint64_t const& dimension, uint64_t const& value) const; // assumes that the value is valid, i.e., small enough |
|||
|
|||
bool isBottomDimension(Epoch const& epoch, uint64_t const& dimension) const; |
|||
uint64_t getDimensionOfEpoch(Epoch const& epoch, uint64_t const& dimension) const; // assumes that the dimension is not bottom |
|||
|
|||
std::string toString(Epoch const& epoch) const; |
|||
|
|||
bool epochClassZigZagOrder(Epoch const& epoch1, Epoch const& epoch2) const; |
|||
|
|||
private: |
|||
|
|||
uint64_t dimensionCount; |
|||
uint64_t bitsPerDimension; |
|||
uint64_t dimensionBitMask; |
|||
uint64_t relevantBitsMask; |
|||
}; |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue