| 
						
						
						
					 | 
				
				 | 
				
					@ -1,6 +1,8 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "storm/modelchecker/multiobjective/rewardbounded/MultiDimensionalRewardUnfolding.h"
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <string>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <set>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <functional>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "storm/utility/macros.h"
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "storm/logic/Formulas.h"
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -178,6 +180,43 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					     | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template<typename ValueType, bool SingleObjectiveMode> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<typename MultiDimensionalRewardUnfolding<ValueType, SingleObjectiveMode>::Epoch> MultiDimensionalRewardUnfolding<ValueType, SingleObjectiveMode>::getEpochComputationOrder(Epoch const& startEpoch) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Perform a DFS to find all the reachable epochs
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::vector<Epoch> dfsStack; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::set<Epoch, std::function<bool(Epoch const&, Epoch const&)>> collectedEpochs(std::bind(&MultiDimensionalRewardUnfolding<ValueType, SingleObjectiveMode>::epochClassZigZagOrder, this, std::placeholders::_1, std::placeholders::_2)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                collectedEpochs.insert(startEpoch); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                dfsStack.push_back(startEpoch); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                while (!dfsStack.empty()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    Epoch currentEpoch = dfsStack.back(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    dfsStack.pop_back(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for (auto const& step : possibleEpochSteps) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        Epoch successorEpoch = getSuccessorEpoch(currentEpoch, step); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        /*
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        for (auto const& e : collectedEpochs) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            std::cout << "Comparing " << epochToString(e) << " and " << epochToString(successorEpoch) << std::endl; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if (epochClassZigZagOrder(e, successorEpoch)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                std::cout << "    " << epochToString(e) << " < " << epochToString(successorEpoch) << std::endl; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if (epochClassZigZagOrder(successorEpoch, e)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                std::cout << "    " << epochToString(e) << " > " << epochToString(successorEpoch) << std::endl; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                         */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (collectedEpochs.insert(successorEpoch).second) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            dfsStack.push_back(std::move(successorEpoch)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                /*
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::cout << "Resulting order: "; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (auto const& e : collectedEpochs) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::cout << epochToString(e) << ", "; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::cout << std::endl; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return std::vector<Epoch>(collectedEpochs.begin(), collectedEpochs.end()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                /*
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // perform DFS to get the 'reachable' epochs in the correct order.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::vector<Epoch> result, dfsStack; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -201,6 +240,7 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return result; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template<typename ValueType, bool SingleObjectiveMode> | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -988,15 +1028,105 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template<typename ValueType, bool SingleObjectiveMode> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::string MultiDimensionalRewardUnfolding<ValueType, SingleObjectiveMode>::epochToString(Epoch const& epoch) const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::string res = "<" + std::to_string(getDimensionOfEpoch(epoch, 0)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::string res = "<" + (isBottomDimension(epoch, 0) ? "_" : std::to_string(getDimensionOfEpoch(epoch, 0))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (uint64_t d = 1; d < dimensionCount; ++d) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    res += ", "; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    res += std::to_string(getDimensionOfEpoch(epoch, d)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    res += (isBottomDimension(epoch, d) ? "_" : std::to_string(getDimensionOfEpoch(epoch, d))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                res += ">"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return res; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template<typename ValueType, bool SingleObjectiveMode> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            bool MultiDimensionalRewardUnfolding<ValueType, SingleObjectiveMode>::epochClassZigZagOrder(Epoch const& epoch1, Epoch const& epoch2) const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // 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
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                uint64_t e1Class = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                uint64_t e2Class = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                uint64_t mask = dimensionBitMask; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (uint64_t dim = 0; dim < dimensionCount; ++dim) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (isBottomDimension(epoch1, dim)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        e1Class |= mask; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (isBottomDimension(epoch2, dim)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        e2Class |= mask; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    mask = mask << bitsPerDimension; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (e1Class < e2Class) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } else if (e1Class > e2Class) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                assert(sameEpochClass(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; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MultiDimensionalRewardUnfolding<double, true>; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MultiDimensionalRewardUnfolding<double, false>; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MultiDimensionalRewardUnfolding<storm::RationalNumber, true>; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |