|
|
@ -88,9 +88,10 @@ namespace storm { |
|
|
|
std::vector<uint64_t> observationResolutionVector(pomdp.getNrObservations(), gridResolution); |
|
|
|
auto overRes = storm::utility::one<ValueType>(); |
|
|
|
auto underRes = storm::utility::zero<ValueType>(); |
|
|
|
uint64_t underApproxModelSize = 50; |
|
|
|
uint64_t refinementCounter = 1; |
|
|
|
std::unique_ptr<POMDPCheckResult<ValueType>> res = computeReachabilityOTF(pomdp, targetObservations, min, observationResolutionVector, false, explorationThreshold, |
|
|
|
overApproxMap, underApproxMap); |
|
|
|
overApproxMap, underApproxMap, underApproxModelSize); |
|
|
|
// TODO the actual refinement
|
|
|
|
return res; |
|
|
|
} |
|
|
@ -102,10 +103,11 @@ namespace storm { |
|
|
|
std::vector<uint64_t> &observationResolutionVector, |
|
|
|
bool computeRewards, double explorationThreshold, |
|
|
|
boost::optional<std::map<uint64_t, ValueType>> overApproximationMap, |
|
|
|
boost::optional<std::map<uint64_t, ValueType>> underApproximationMap) { |
|
|
|
boost::optional<std::map<uint64_t, ValueType>> underApproximationMap, |
|
|
|
uint64_t maxUaModelSize) { |
|
|
|
STORM_PRINT("Use On-The-Fly Grid Generation" << std::endl) |
|
|
|
auto result = computeFirstRefinementStep(pomdp, targetObservations, min, observationResolutionVector, computeRewards, explorationThreshold, overApproximationMap, |
|
|
|
underApproximationMap); |
|
|
|
underApproximationMap, maxUaModelSize); |
|
|
|
return std::make_unique<POMDPCheckResult<ValueType>>(POMDPCheckResult<ValueType>{result->overApproxValue, result->underApproxValue}); |
|
|
|
} |
|
|
|
|
|
|
@ -117,7 +119,8 @@ namespace storm { |
|
|
|
std::vector<uint64_t> &observationResolutionVector, |
|
|
|
bool computeRewards, double explorationThreshold, |
|
|
|
boost::optional<std::map<uint64_t, ValueType>> overApproximationMap, |
|
|
|
boost::optional<std::map<uint64_t, ValueType>> underApproximationMap) { |
|
|
|
boost::optional<std::map<uint64_t, ValueType>> underApproximationMap, |
|
|
|
uint64_t maxUaModelSize) { |
|
|
|
bool boundMapsSet = overApproximationMap && underApproximationMap; |
|
|
|
std::map<uint64_t, ValueType> overMap; |
|
|
|
std::map<uint64_t, ValueType> underMap; |
|
|
@ -413,183 +416,8 @@ namespace storm { |
|
|
|
auto overApprox = overApproxResultMap[beliefStateMap.left.at(initialBelief.id)]; |
|
|
|
|
|
|
|
STORM_PRINT("Time Overapproximation: " << overApproxTimer << std::endl) |
|
|
|
|
|
|
|
// Prototypical implementation of the underapproximation - WRONG
|
|
|
|
/*
|
|
|
|
// The map has the following form: (beliefId, action) --> stateId
|
|
|
|
uamap_type uaStateMap; |
|
|
|
// Reserve states 0 and 1 as always sink/goal states
|
|
|
|
std::map<uint64_t, std::vector<std::map<uint64_t, ValueType>>> uaTransitions = {{0,{{{0, storm::utility::one<ValueType>()}}}}, |
|
|
|
{1,{{{1, storm::utility::one<ValueType>()}}}}}; |
|
|
|
// Hint vector for the MDP modelchecker (initialize with constant sink/goal values)
|
|
|
|
std::vector<uint64_t> uaTargetStates = {1}; |
|
|
|
uint64_t uaStateId = 2; |
|
|
|
|
|
|
|
// for beliefs which are both in the actual belief support and the grid, we use the max value for the action to indicate the support belief
|
|
|
|
uaStateMap.insert(uamap_type::value_type(std::make_pair(initialBelief.id, std::numeric_limits<uint64_t>::max()), uaStateId)); |
|
|
|
++uaStateId; |
|
|
|
beliefsToBeExpanded.push_back(initialBelief.id); |
|
|
|
while(!beliefsToBeExpanded.empty()){ |
|
|
|
uint64_t currId = beliefsToBeExpanded.front(); |
|
|
|
beliefsToBeExpanded.pop_front(); |
|
|
|
bool isTarget = beliefIsTarget[currId]; |
|
|
|
|
|
|
|
if(isTarget){ |
|
|
|
// For target states we add a self-loop
|
|
|
|
uaTargetStates.push_back(uaStateMap.left.at(std::make_pair(currId, std::numeric_limits<uint64_t>::max()))); |
|
|
|
uaTransitions[uaStateMap.left.at(std::make_pair(currId, std::numeric_limits<uint64_t>::max()))] = {{{uaStateMap.left.at(std::make_pair(currId, std::numeric_limits<uint64_t>::max())), storm::utility::one<ValueType>()}}}; |
|
|
|
} else { |
|
|
|
uint64_t numChoices = pomdp.getNumberOfChoices(pomdp.getStatesWithObservation(beliefList[currId].observation).front()); |
|
|
|
//Triangulate the current belief to determine its approximation bases
|
|
|
|
std::vector<std::vector<ValueType>> subSimplex; |
|
|
|
std::vector<ValueType> lambdas; |
|
|
|
if (cacheSubsimplices && subSimplexCache.count(currId) > 0) { |
|
|
|
subSimplex = subSimplexCache[currId]; |
|
|
|
lambdas = lambdaCache[currId]; |
|
|
|
} else { |
|
|
|
std::pair<std::vector<std::vector<ValueType>>, std::vector<ValueType>> temp = computeSubSimplexAndLambdas( |
|
|
|
beliefList[currId].probabilities, observationResolutionVector[beliefList[currId].observation]); |
|
|
|
subSimplex = temp.first; |
|
|
|
lambdas = temp.second; |
|
|
|
if(cacheSubsimplices){ |
|
|
|
subSimplexCache[currId] = subSimplex; |
|
|
|
lambdaCache[currId] = lambdas; |
|
|
|
} |
|
|
|
} |
|
|
|
std::deque<std::pair<uint64_t,uint64_t>> approxToExpand; |
|
|
|
std::vector<std::map<uint64_t, ValueType>> approxActionTransitions(numChoices); |
|
|
|
for (size_t j = 0; j < lambdas.size(); ++j) { |
|
|
|
if (!cc.isEqual(lambdas[j], storm::utility::zero<ValueType>())){ |
|
|
|
uint64_t approxId = getBeliefIdInVector(beliefGrid, beliefList[currId].observation, subSimplex[j]); |
|
|
|
//STORM_PRINT("ApproxId " << approxId << std::endl)
|
|
|
|
if (approxId == uint64_t(-1)) { |
|
|
|
// If the approximation base is not yet in the grid, we add it and it has to be expanded
|
|
|
|
storm::pomdp::Belief<ValueType> gridBelief = {nextId, beliefList[currId].observation, subSimplex[j]}; |
|
|
|
beliefList.push_back(gridBelief); |
|
|
|
beliefGrid.push_back(gridBelief); |
|
|
|
beliefIsTarget.push_back(targetObservations.find(beliefList[currId].observation) != targetObservations.end()); |
|
|
|
for(uint64_t action=0; action < numChoices; ++action) { |
|
|
|
approxToExpand.push_back(std::make_pair(nextId, action)); |
|
|
|
uaStateMap.insert(uamap_type::value_type(std::make_pair(nextId, action), uaStateId)); |
|
|
|
approxActionTransitions[action][uaStateId] = lambdas[j]; |
|
|
|
++uaStateId; |
|
|
|
} |
|
|
|
++nextId; |
|
|
|
} else if(uaStateMap.left.find(std::pair<uint64_t,uint64_t>(approxId,0)) != uaStateMap.left.end()){ |
|
|
|
// we can check only for (approxId,0) as that always exists if the grid state is mapped
|
|
|
|
for(uint64_t action=0; action < numChoices; ++action) { |
|
|
|
approxActionTransitions[action][uaStateMap.left.at(std::make_pair(approxId,action))] = lambdas[j]; |
|
|
|
} |
|
|
|
} else { |
|
|
|
for(uint64_t action=0; action < numChoices; ++action) { |
|
|
|
approxToExpand.push_back(std::make_pair(approxId, action)); |
|
|
|
uaStateMap.insert(uamap_type::value_type(std::make_pair(approxId, action), uaStateId)); |
|
|
|
approxActionTransitions[action][uaStateId] = lambdas[j]; |
|
|
|
++uaStateId; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
uaTransitions[uaStateMap.left.at(std::make_pair(currId,std::numeric_limits<uint64_t>::max()))] = approxActionTransitions; |
|
|
|
// Now expand all approximation bases
|
|
|
|
while(!approxToExpand.empty()){ |
|
|
|
uint64_t approxId = approxToExpand.front().first; |
|
|
|
uint64_t approxAction = approxToExpand.front().second; |
|
|
|
approxToExpand.pop_front(); |
|
|
|
|
|
|
|
// Iterate over all actions and determine the successor states
|
|
|
|
std::map<uint64_t, ValueType> transitionsInAction; |
|
|
|
std::map<uint32_t, ValueType> actionObservationProbabilities = computeObservationProbabilitiesAfterAction(pomdp, beliefList[approxId], approxAction); |
|
|
|
for (auto iter = actionObservationProbabilities.begin(); iter != actionObservationProbabilities.end(); ++iter) { |
|
|
|
uint32_t observation = iter->first; |
|
|
|
uint64_t idNextBelief = getBeliefAfterActionAndObservation(pomdp, beliefList, beliefIsTarget, targetObservations, beliefList[approxId], approxAction, |
|
|
|
observation, nextId); |
|
|
|
nextId = beliefList.size(); |
|
|
|
if(uaStateMap.left.find(std::make_pair(idNextBelief, std::numeric_limits<uint64_t>::max())) == uaStateMap.left.end()){ |
|
|
|
// add state to the mapping and set it t be expanded
|
|
|
|
uaStateMap.insert(uamap_type::value_type(std::make_pair(idNextBelief,std::numeric_limits<uint64_t>::max()), uaStateId)); |
|
|
|
++uaStateId; |
|
|
|
beliefsToBeExpanded.push_back(idNextBelief); |
|
|
|
} |
|
|
|
transitionsInAction[uaStateMap.left.at(std::make_pair(idNextBelief,std::numeric_limits<uint64_t>::max()))] = iter->second; |
|
|
|
} |
|
|
|
uaTransitions[uaStateMap.left.at(std::make_pair(approxId,approxAction))] = {transitionsInAction}; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::vector<std::map<uint64_t, ValueType>>> uaTransitionVector; |
|
|
|
for(auto iter = uaTransitions.begin(); iter != uaTransitions.end(); ++iter){ |
|
|
|
uaTransitionVector.push_back(iter->second); |
|
|
|
} |
|
|
|
STORM_PRINT(uaTransitions.size() << std::endl) |
|
|
|
|
|
|
|
storm::models::sparse::StateLabeling uaLabeling(uaTransitions.size()); |
|
|
|
uaLabeling.addLabel("init"); |
|
|
|
uaLabeling.addLabel("target"); |
|
|
|
uaLabeling.addLabel("belief"); |
|
|
|
uaLabeling.addLabel("grid"); |
|
|
|
uaLabeling.addLabelToState("init", uaStateMap.left.at(std::make_pair(initialBelief.id,std::numeric_limits<uint64_t>::max()))); |
|
|
|
for (auto targetState : uaTargetStates) { |
|
|
|
uaLabeling.addLabelToState("target", targetState); |
|
|
|
} |
|
|
|
for (auto &iter : uaStateMap.right) { |
|
|
|
std::stringstream mapEntryStr; |
|
|
|
mapEntryStr << std::to_string(iter.first); |
|
|
|
mapEntryStr << " --> "; |
|
|
|
mapEntryStr << "[{" + std::to_string(beliefList[iter.second.first].observation) << "} | " ; |
|
|
|
for(uint64_t state = 0; state < beliefList[iter.second.first].probabilities.size(); ++state){ |
|
|
|
if(beliefList[iter.second.first].probabilities[state] > storm::utility::zero<ValueType>()){ |
|
|
|
mapEntryStr << std::to_string(state) << " : " << beliefList[iter.second.first].probabilities[state] << ", "; |
|
|
|
} |
|
|
|
} |
|
|
|
mapEntryStr << "]" << std::endl; |
|
|
|
STORM_PRINT(mapEntryStr.str()); |
|
|
|
if(!uaLabeling.containsLabel(mapEntryStr.str())){ |
|
|
|
uaLabeling.addLabel(mapEntryStr.str()); |
|
|
|
} |
|
|
|
if(iter.second.second == std::numeric_limits<uint64_t>::max()){ |
|
|
|
uaLabeling.addLabelToState("belief", iter.first); |
|
|
|
} else { |
|
|
|
uaLabeling.addLabelToState("grid", iter.first); |
|
|
|
} |
|
|
|
uaLabeling.addLabelToState(mapEntryStr.str(), iter.first); |
|
|
|
} |
|
|
|
|
|
|
|
//STORM_PRINT(buildTransitionMatrix(uaTransitionVector))
|
|
|
|
storm::storage::sparse::ModelComponents<ValueType, RewardModelType> uaModelComponents(buildTransitionMatrix(uaTransitionVector), uaLabeling); |
|
|
|
storm::models::sparse::Mdp<ValueType, RewardModelType> underApproxMdp(uaModelComponents); |
|
|
|
if (computeRewards) { |
|
|
|
storm::models::sparse::StandardRewardModel<ValueType> uaMdpRewardModel(boost::none, std::vector<ValueType>(uaModelComponents.transitionMatrix.getRowCount())); |
|
|
|
for (auto const &iter : uaStateMap.left) { |
|
|
|
auto currentBelief = beliefList[iter.first.first]; |
|
|
|
auto representativeState = pomdp.getStatesWithObservation(currentBelief.observation).front(); |
|
|
|
for (uint64_t action = 0; action < underApproxMdp.getNumberOfChoices(iter.second); ++action) { |
|
|
|
// Add the reward
|
|
|
|
uaMdpRewardModel.setStateActionReward(overApproxMdp.getChoiceIndex(storm::storage::StateActionPair(iter.second, action)), |
|
|
|
getRewardAfterAction(pomdp, pomdp.getChoiceIndex(storm::storage::StateActionPair(representativeState, action)), |
|
|
|
currentBelief)); |
|
|
|
} |
|
|
|
} |
|
|
|
underApproxMdp.addRewardModel("std", uaMdpRewardModel); |
|
|
|
underApproxMdp.restrictRewardModels(std::set<std::string>({"std"})); |
|
|
|
} |
|
|
|
underApproxMdp.printModelInformationToStream(std::cout); |
|
|
|
|
|
|
|
auto uaModel = std::make_shared<storm::models::sparse::Mdp<ValueType, RewardModelType>>(underApproxMdp); |
|
|
|
auto uaModelPtr = std::static_pointer_cast<storm::models::sparse::Model<ValueType, RewardModelType>>(uaModel); |
|
|
|
storm::api::exportSparseModelAsDot(uaModelPtr, "ua_model.dot"); |
|
|
|
auto uaTask = storm::api::createTask<ValueType>(property, false); |
|
|
|
storm::utility::Stopwatch underApproxTimer(true); |
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> uaRes(storm::api::verifyWithSparseEngine<ValueType>(uaModelPtr, uaTask)); |
|
|
|
underApproxTimer.stop(); |
|
|
|
STORM_LOG_ASSERT(uaRes, "Result not exist."); |
|
|
|
uaRes->filter(storm::modelchecker::ExplicitQualitativeCheckResult(storm::storage::BitVector(underApproxMdp.getNumberOfStates(), true))); |
|
|
|
auto underApproxResultMap = uaRes->asExplicitQuantitativeCheckResult<ValueType>().getValueMap(); |
|
|
|
auto underApprox = underApproxResultMap[uaStateMap.left.at(std::make_pair(initialBelief.id, std::numeric_limits<uint64_t>::max()))]; |
|
|
|
*/ |
|
|
|
auto underApprox = weightedSumUnderMap[initialBelief.id]; |
|
|
|
//auto underApprox = weightedSumUnderMap[initialBelief.id];
|
|
|
|
auto underApprox = computeUnderapproximation(pomdp, beliefList, beliefIsTarget, targetObservations, initialBelief.id, min, computeRewards, maxUaModelSize); |
|
|
|
STORM_PRINT("Over-Approximation Result: " << overApprox << std::endl); |
|
|
|
STORM_PRINT("Under-Approximation Result: " << underApprox << std::endl); |
|
|
|
|
|
|
@ -837,10 +665,10 @@ namespace storm { |
|
|
|
|
|
|
|
// Now onto the under-approximation
|
|
|
|
storm::utility::Stopwatch underApproxTimer(true); |
|
|
|
ValueType underApprox = computeUnderapproximation(pomdp, beliefList, beliefIsTarget, targetObservations, observationProbabilities, nextBelieves, |
|
|
|
result, chosenActions, gridResolution, initialBelief.id, min, computeRewards, useMdp); |
|
|
|
/*ValueType underApprox = computeUnderapproximation(pomdp, beliefList, beliefIsTarget, targetObservations, observationProbabilities, nextBelieves,
|
|
|
|
result, chosenActions, gridResolution, initialBelief.id, min, computeRewards, useMdp);*/ |
|
|
|
underApproxTimer.stop(); |
|
|
|
|
|
|
|
auto underApprox = storm::utility::zero<ValueType>(); |
|
|
|
STORM_PRINT("Time Belief Grid Generation: " << beliefGridTimer << std::endl |
|
|
|
<< "Time Overapproximation: " << overApproxTimer |
|
|
|
<< std::endl |
|
|
@ -874,64 +702,60 @@ namespace storm { |
|
|
|
std::vector<storm::pomdp::Belief<ValueType>> &beliefList, |
|
|
|
std::vector<bool> &beliefIsTarget, |
|
|
|
std::set<uint32_t> const &targetObservations, |
|
|
|
std::map<uint64_t, std::vector<std::map<uint32_t, ValueType>>> &observationProbabilities, |
|
|
|
std::map<uint64_t, std::vector<std::map<uint32_t, uint64_t>>> &nextBelieves, |
|
|
|
std::map<uint64_t, ValueType> &result, |
|
|
|
std::map<uint64_t, std::vector<uint64_t>> &chosenActions, |
|
|
|
uint64_t gridResolution, uint64_t initialBeliefId, bool min, |
|
|
|
bool computeRewards, bool generateMdp) { |
|
|
|
uint64_t initialBeliefId, bool min, |
|
|
|
bool computeRewards, uint64_t maxModelSize) { |
|
|
|
std::set<uint64_t> visitedBelieves; |
|
|
|
std::deque<uint64_t> believesToBeExpanded; |
|
|
|
std::map<uint64_t, uint64_t> beliefStateMap; |
|
|
|
std::vector<std::vector<std::map<uint64_t, ValueType>>> transitions; |
|
|
|
std::vector<uint64_t> targetStates; |
|
|
|
std::vector<std::vector<std::map<uint64_t, ValueType>>> transitions = {{{{0, storm::utility::one<ValueType>()}}}, |
|
|
|
{{{1, storm::utility::one<ValueType>()}}}}; |
|
|
|
std::vector<uint64_t> targetStates = {1}; |
|
|
|
|
|
|
|
uint64_t stateId = 0; |
|
|
|
uint64_t stateId = 2; |
|
|
|
beliefStateMap[initialBeliefId] = stateId; |
|
|
|
++stateId; |
|
|
|
uint64_t nextId = beliefList.size(); |
|
|
|
uint64_t counter = 0; |
|
|
|
|
|
|
|
// Expand the believes
|
|
|
|
visitedBelieves.insert(initialBeliefId); |
|
|
|
believesToBeExpanded.push_back(initialBeliefId); |
|
|
|
while (!believesToBeExpanded.empty()) { |
|
|
|
//TODO think of other ways to stop exploration besides model size
|
|
|
|
auto currentBeliefId = believesToBeExpanded.front(); |
|
|
|
std::vector<std::map<uint64_t, ValueType>> actionTransitionStorage; |
|
|
|
uint64_t numChoices = pomdp.getNumberOfChoices(pomdp.getStatesWithObservation(beliefList[currentBeliefId].observation).front()); |
|
|
|
// for targets, we only consider one action with one transition
|
|
|
|
if (beliefIsTarget[currentBeliefId]) { |
|
|
|
// add a self-loop to target states and save them
|
|
|
|
std::map<uint64_t, ValueType> transitionsInStateWithAction; |
|
|
|
transitionsInStateWithAction[beliefStateMap[currentBeliefId]] = storm::utility::one<ValueType>(); |
|
|
|
// add a self-loop to target states
|
|
|
|
targetStates.push_back(beliefStateMap[currentBeliefId]); |
|
|
|
actionTransitionStorage.push_back(transitionsInStateWithAction); |
|
|
|
transitions.push_back({{{beliefStateMap[currentBeliefId], storm::utility::one<ValueType>()}}}); |
|
|
|
} else if (counter > maxModelSize) { |
|
|
|
transitions.push_back({{{0, storm::utility::one<ValueType>()}}}); |
|
|
|
} else { |
|
|
|
if (chosenActions.find(currentBeliefId) == chosenActions.end()) { |
|
|
|
chosenActions[currentBeliefId] = generateMdp ? extractBestActions(pomdp, beliefList, beliefIsTarget, targetObservations, |
|
|
|
observationProbabilities, |
|
|
|
nextBelieves, result, gridResolution, |
|
|
|
currentBeliefId, beliefList.size(), min) : |
|
|
|
extractBestAction(pomdp, beliefList, beliefIsTarget, targetObservations, |
|
|
|
observationProbabilities, |
|
|
|
nextBelieves, result, gridResolution, |
|
|
|
currentBeliefId, beliefList.size(), min); |
|
|
|
} |
|
|
|
// Iterate over all actions and add the corresponding transitions
|
|
|
|
for (auto const &action : chosenActions[currentBeliefId]) { |
|
|
|
std::vector<std::map<uint64_t, ValueType>> actionTransitionStorage; |
|
|
|
//TODO add a way to extract the actions from the over-approx and use them here?
|
|
|
|
for (uint64_t action = 0; action < numChoices; ++action) { |
|
|
|
std::map<uint64_t, ValueType> transitionsInStateWithAction; |
|
|
|
|
|
|
|
for (auto iter = observationProbabilities[currentBeliefId][action].begin(); iter != observationProbabilities[currentBeliefId][action].end(); ++iter) { |
|
|
|
std::map<uint32_t, ValueType> observationProbabilities = computeObservationProbabilitiesAfterAction(pomdp, beliefList[currentBeliefId], action); |
|
|
|
for (auto iter = observationProbabilities.begin(); iter != observationProbabilities.end(); ++iter) { |
|
|
|
uint32_t observation = iter->first; |
|
|
|
uint64_t nextBeliefId = nextBelieves[currentBeliefId][action][observation]; |
|
|
|
uint64_t nextBeliefId = getBeliefAfterActionAndObservation(pomdp, beliefList, beliefIsTarget, targetObservations, beliefList[currentBeliefId], |
|
|
|
action, |
|
|
|
observation, nextId); |
|
|
|
nextId = beliefList.size(); |
|
|
|
if (visitedBelieves.insert(nextBeliefId).second) { |
|
|
|
beliefStateMap[nextBeliefId] = stateId; |
|
|
|
++stateId; |
|
|
|
believesToBeExpanded.push_back(nextBeliefId); |
|
|
|
++counter; |
|
|
|
} |
|
|
|
transitionsInStateWithAction[beliefStateMap[nextBeliefId]] = iter->second; |
|
|
|
} |
|
|
|
actionTransitionStorage.push_back(transitionsInStateWithAction); |
|
|
|
} |
|
|
|
transitions.push_back(actionTransitionStorage); |
|
|
|
} |
|
|
|
transitions.push_back(actionTransitionStorage); |
|
|
|
believesToBeExpanded.pop_front(); |
|
|
|
} |
|
|
|
|
|
|
@ -949,44 +773,28 @@ namespace storm { |
|
|
|
transitionMatrix.makeRowGroupingTrivial(); |
|
|
|
} |
|
|
|
storm::storage::sparse::ModelComponents<ValueType, RewardModelType> modelComponents(transitionMatrix, labeling); |
|
|
|
if (transitionMatrix.hasTrivialRowGrouping()) { |
|
|
|
|
|
|
|
storm::models::sparse::Dtmc<ValueType, RewardModelType> underApproxMc(modelComponents); |
|
|
|
storm::models::sparse::StandardRewardModel<ValueType> rewardModel(std::vector<ValueType>(beliefStateMap.size())); |
|
|
|
if (computeRewards) { |
|
|
|
for (auto const &iter : beliefStateMap) { |
|
|
|
auto currentBelief = beliefList[iter.first]; |
|
|
|
// Add the reward collected by taking the chosen Action in the belief
|
|
|
|
rewardModel.setStateReward(iter.second, getRewardAfterAction(pomdp, pomdp.getChoiceIndex( |
|
|
|
storm::storage::StateActionPair(pomdp.getStatesWithObservation(currentBelief.observation).front(), chosenActions[iter.first][0])), |
|
|
|
currentBelief)); |
|
|
|
} |
|
|
|
} |
|
|
|
underApproxMc.addRewardModel("std", rewardModel); |
|
|
|
underApproxMc.restrictRewardModels(std::set<std::string>({"std"})); |
|
|
|
|
|
|
|
model = std::make_shared<storm::models::sparse::Dtmc<ValueType, RewardModelType>>(underApproxMc); |
|
|
|
} else { |
|
|
|
storm::models::sparse::Mdp<ValueType, RewardModelType> underApproxMdp(modelComponents); |
|
|
|
if (computeRewards) { |
|
|
|
storm::models::sparse::StandardRewardModel<ValueType> rewardModel(boost::none, std::vector<ValueType>(modelComponents.transitionMatrix.getRowCount())); |
|
|
|
for (auto const &iter : beliefStateMap) { |
|
|
|
auto currentBelief = beliefList[iter.first]; |
|
|
|
auto representativeState = pomdp.getStatesWithObservation(currentBelief.observation).front(); |
|
|
|
for (uint64_t action = 0; action < underApproxMdp.getNumberOfChoices(iter.second); ++action) { |
|
|
|
// Add the reward
|
|
|
|
rewardModel.setStateActionReward(underApproxMdp.getChoiceIndex(storm::storage::StateActionPair(iter.second, action)), |
|
|
|
getRewardAfterAction(pomdp, pomdp.getChoiceIndex(storm::storage::StateActionPair(representativeState, action)), |
|
|
|
currentBelief)); |
|
|
|
} |
|
|
|
storm::models::sparse::Mdp<ValueType, RewardModelType> underApproxMdp(modelComponents); |
|
|
|
if (computeRewards) { |
|
|
|
storm::models::sparse::StandardRewardModel<ValueType> rewardModel(boost::none, std::vector<ValueType>(modelComponents.transitionMatrix.getRowCount())); |
|
|
|
for (auto const &iter : beliefStateMap) { |
|
|
|
auto currentBelief = beliefList[iter.first]; |
|
|
|
auto representativeState = pomdp.getStatesWithObservation(currentBelief.observation).front(); |
|
|
|
for (uint64_t action = 0; action < underApproxMdp.getNumberOfChoices(iter.second); ++action) { |
|
|
|
// Add the reward
|
|
|
|
rewardModel.setStateActionReward(underApproxMdp.getChoiceIndex(storm::storage::StateActionPair(iter.second, action)), |
|
|
|
getRewardAfterAction(pomdp, pomdp.getChoiceIndex(storm::storage::StateActionPair(representativeState, action)), |
|
|
|
currentBelief)); |
|
|
|
} |
|
|
|
underApproxMdp.addRewardModel("std", rewardModel); |
|
|
|
underApproxMdp.restrictRewardModels(std::set<std::string>({"std"})); |
|
|
|
} |
|
|
|
model = std::make_shared<storm::models::sparse::Mdp<ValueType, RewardModelType>>(underApproxMdp); |
|
|
|
underApproxMdp.addRewardModel("std", rewardModel); |
|
|
|
underApproxMdp.restrictRewardModels(std::set<std::string>({"std"})); |
|
|
|
} |
|
|
|
model = std::make_shared<storm::models::sparse::Mdp<ValueType, RewardModelType>>(underApproxMdp); |
|
|
|
|
|
|
|
model->printModelInformationToStream(std::cout); |
|
|
|
|
|
|
|
storm::api::exportSparseModelAsDot(model, "ua_model.dot"); |
|
|
|
|
|
|
|
std::string propertyString; |
|
|
|
if (computeRewards) { |
|
|
|
propertyString = min ? "Rmin=? [F \"target\"]" : "Rmax=? [F \"target\"]"; |
|
|
@ -996,10 +804,13 @@ namespace storm { |
|
|
|
std::vector<storm::jani::Property> propertyVector = storm::api::parseProperties(propertyString); |
|
|
|
std::shared_ptr<storm::logic::Formula const> property = storm::api::extractFormulasFromProperties(propertyVector).front(); |
|
|
|
|
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> res(storm::api::verifyWithSparseEngine<ValueType>(model, storm::api::createTask<ValueType>(property, true))); |
|
|
|
std::unique_ptr<storm::modelchecker::CheckResult> res(storm::api::verifyWithSparseEngine<ValueType>(model, storm::api::createTask<ValueType>(property, false))); |
|
|
|
STORM_LOG_ASSERT(res, "Result does not exist."); |
|
|
|
res->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); |
|
|
|
return res->asExplicitQuantitativeCheckResult<ValueType>().getValueMap().begin()->second; |
|
|
|
res->filter(storm::modelchecker::ExplicitQualitativeCheckResult(storm::storage::BitVector(underApproxMdp.getNumberOfStates(), true))); |
|
|
|
auto underApproxResultMap = res->asExplicitQuantitativeCheckResult<ValueType>().getValueMap(); |
|
|
|
auto underApprox = underApproxResultMap[beliefStateMap[initialBeliefId]]; |
|
|
|
|
|
|
|
return underApprox; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1406,4 +1217,4 @@ namespace storm { |
|
|
|
#endif
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |