You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							514 lines
						
					
					
						
							30 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							514 lines
						
					
					
						
							30 KiB
						
					
					
				| 
 | |
| 
 | |
| #include "storm/utility/initialize.h" | |
|  | |
| #include "storm/settings/modules/GeneralSettings.h" | |
| #include "storm/settings/modules/CoreSettings.h" | |
| #include "storm/settings/modules/IOSettings.h" | |
| #include "storm/settings/modules/DebugSettings.h" | |
| #include "storm/settings/modules/CuddSettings.h" | |
| #include "storm/settings/modules/SylvanSettings.h" | |
| #include "storm/settings/modules/EigenEquationSolverSettings.h" | |
| #include "storm/settings/modules/GmmxxEquationSolverSettings.h" | |
| #include "storm/settings/modules/NativeEquationSolverSettings.h" | |
| #include "storm/settings/modules/EliminationSettings.h" | |
| #include "storm/settings/modules/MinMaxEquationSolverSettings.h" | |
| #include "storm/settings/modules/GameSolverSettings.h" | |
| #include "storm/settings/modules/BisimulationSettings.h" | |
| #include "storm/settings/modules/GlpkSettings.h" | |
| #include "storm/settings/modules/GurobiSettings.h" | |
| #include "storm/settings/modules/Smt2SmtSolverSettings.h" | |
| #include "storm/settings/modules/ExplorationSettings.h" | |
| #include "storm/settings/modules/ResourceSettings.h" | |
| #include "storm/settings/modules/AbstractionSettings.h" | |
| #include "storm/settings/modules/BuildSettings.h" | |
| #include "storm/settings/modules/JitBuilderSettings.h" | |
| #include "storm/settings/modules/TopologicalEquationSolverSettings.h" | |
| #include "storm/settings/modules/ModelCheckerSettings.h" | |
| #include "storm/settings/modules/MultiplierSettings.h" | |
| #include "storm/settings/modules/TransformationSettings.h" | |
| #include "storm/settings/modules/MultiObjectiveSettings.h" | |
| #include "storm-pomdp-cli/settings/modules/POMDPSettings.h" | |
| #include "storm-pomdp-cli/settings/modules/QualitativePOMDPAnalysisSettings.h" | |
|  | |
| #include "storm/analysis/GraphConditions.h" | |
|  | |
| #include "storm-cli-utilities/cli.h" | |
| #include "storm-cli-utilities/model-handling.h" | |
|  | |
| #include "storm-pomdp/transformer/KnownProbabilityTransformer.h" | |
| #include "storm-pomdp/transformer/ApplyFiniteSchedulerToPomdp.h" | |
| #include "storm-pomdp/transformer/GlobalPOMDPSelfLoopEliminator.h" | |
| #include "storm-pomdp/transformer/GlobalPomdpMecChoiceEliminator.h" | |
| #include "storm-pomdp/transformer/PomdpMemoryUnfolder.h" | |
| #include "storm-pomdp/transformer/BinaryPomdpTransformer.h" | |
| #include "storm-pomdp/analysis/UniqueObservationStates.h" | |
| #include "storm-pomdp/analysis/QualitativeAnalysis.h" | |
| #include "storm-pomdp/modelchecker/ApproximatePOMDPModelchecker.h" | |
| #include "storm-pomdp/analysis/MemlessStrategySearchQualitative.h" | |
| #include "storm-pomdp/analysis/QualitativeStrategySearchNaive.h" | |
| #include "storm/api/storm.h" | |
|  | |
| #include <typeinfo> | |
|  | |
| /*! | |
|  * Initialize the settings manager. | |
|  */ | |
| void initializeSettings() { | |
|     storm::settings::mutableManager().setName("Storm-POMDP", "storm-pomdp"); | |
| 
 | |
|     storm::settings::addModule<storm::settings::modules::GeneralSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::IOSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::CoreSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::DebugSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::BuildSettings>(); | |
| 
 | |
|     storm::settings::addModule<storm::settings::modules::TransformationSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::GmmxxEquationSolverSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::EigenEquationSolverSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::NativeEquationSolverSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::EliminationSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::MinMaxEquationSolverSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::GameSolverSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::BisimulationSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::GlpkSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::ExplorationSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::ResourceSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::JitBuilderSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::TopologicalEquationSolverSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::ModelCheckerSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::MultiplierSettings>(); | |
| 
 | |
|     storm::settings::addModule<storm::settings::modules::POMDPSettings>(); | |
|     storm::settings::addModule<storm::settings::modules::QualitativePOMDPAnalysisSettings>(); | |
| } | |
| 
 | |
| template<typename ValueType> | |
| bool extractTargetAndSinkObservationSets(std::shared_ptr<storm::models::sparse::Pomdp<ValueType>> const& pomdp, storm::logic::Formula const& subformula, std::set<uint32_t>& targetObservationSet, storm::storage::BitVector&  targetStates, storm::storage::BitVector&  badStates) { | |
|     //TODO refactor (use model checker to determine the states, then transform into observations). | |
|     //TODO rename into appropriate function name. | |
|     bool validFormula = false; | |
|     if (subformula.isEventuallyFormula()) { | |
|         storm::logic::EventuallyFormula const &eventuallyFormula = subformula.asEventuallyFormula(); | |
|         storm::logic::Formula const &subformula2 = eventuallyFormula.getSubformula(); | |
|         if (subformula2.isAtomicLabelFormula()) { | |
|             storm::logic::AtomicLabelFormula const &alFormula = subformula2.asAtomicLabelFormula(); | |
|             validFormula = true; | |
|             std::string targetLabel = alFormula.getLabel(); | |
|             auto labeling = pomdp->getStateLabeling(); | |
|             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                 if (labeling.getStateHasLabel(targetLabel, state)) { | |
|                     targetObservationSet.insert(pomdp->getObservation(state)); | |
|                     targetStates.set(state); | |
|                 } | |
|             } | |
|         } else if (subformula2.isAtomicExpressionFormula()) { | |
|             validFormula = true; | |
|             std::stringstream stream; | |
|             stream << subformula2.asAtomicExpressionFormula().getExpression(); | |
|             storm::logic::AtomicLabelFormula formula3 = storm::logic::AtomicLabelFormula(stream.str()); | |
|             std::string targetLabel = formula3.getLabel(); | |
|             auto labeling = pomdp->getStateLabeling(); | |
|             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                 if (labeling.getStateHasLabel(targetLabel, state)) { | |
|                     targetObservationSet.insert(pomdp->getObservation(state)); | |
|                     targetStates.set(state); | |
|                 } | |
|             } | |
|         } | |
|     } else if (subformula.isUntilFormula()) { | |
|         storm::logic::UntilFormula const &untilFormula = subformula.asUntilFormula(); | |
|         storm::logic::Formula const &subformula1 = untilFormula.getLeftSubformula(); | |
|         if (subformula1.isAtomicLabelFormula()) { | |
|             storm::logic::AtomicLabelFormula const &alFormula = subformula1.asAtomicLabelFormula(); | |
|             std::string targetLabel = alFormula.getLabel(); | |
|             auto labeling = pomdp->getStateLabeling(); | |
|             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                 if (!labeling.getStateHasLabel(targetLabel, state)) { | |
|                     badStates.set(state); | |
|                 } | |
|             } | |
|         } else if (subformula1.isAtomicExpressionFormula()) { | |
|             std::stringstream stream; | |
|             stream << subformula1.asAtomicExpressionFormula().getExpression(); | |
|             storm::logic::AtomicLabelFormula formula3 = storm::logic::AtomicLabelFormula(stream.str()); | |
|             std::string targetLabel = formula3.getLabel(); | |
|             auto labeling = pomdp->getStateLabeling(); | |
|             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                 if (!labeling.getStateHasLabel(targetLabel, state)) { | |
|                     badStates.set(state); | |
|                 } | |
|             } | |
|         } else { | |
|             return false; | |
|         } | |
|         storm::logic::Formula const &subformula2 = untilFormula.getRightSubformula(); | |
|         if (subformula2.isAtomicLabelFormula()) { | |
|             storm::logic::AtomicLabelFormula const &alFormula = subformula2.asAtomicLabelFormula(); | |
|             validFormula = true; | |
|             std::string targetLabel = alFormula.getLabel(); | |
|             auto labeling = pomdp->getStateLabeling(); | |
|             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                 if (labeling.getStateHasLabel(targetLabel, state)) { | |
|                     targetObservationSet.insert(pomdp->getObservation(state)); | |
|                     targetStates.set(state); | |
|                 } | |
| 
 | |
|             } | |
|         } else if (subformula2.isAtomicExpressionFormula()) { | |
|             validFormula = true; | |
|             std::stringstream stream; | |
|             stream << subformula2.asAtomicExpressionFormula().getExpression(); | |
|             storm::logic::AtomicLabelFormula formula3 = storm::logic::AtomicLabelFormula(stream.str()); | |
|             std::string targetLabel = formula3.getLabel(); | |
|             auto labeling = pomdp->getStateLabeling(); | |
|             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                 if (labeling.getStateHasLabel(targetLabel, state)) { | |
|                     targetObservationSet.insert(pomdp->getObservation(state)); | |
|                     targetStates.set(state); | |
|                 } | |
| 
 | |
|             } | |
|         } | |
|     } | |
|     return validFormula; | |
| } | |
| 
 | |
| template<typename ValueType> | |
| std::set<uint32_t> extractObservations(storm::models::sparse::Pomdp<ValueType> const& pomdp, storm::storage::BitVector const& states) { | |
|     std::set<uint32_t> observations; | |
|     for(auto state : states) { | |
|         observations.insert(pomdp.getObservation(state)); | |
|     } | |
|     return observations; | |
| } | |
| 
 | |
| /*! | |
|  * Entry point for the pomdp backend. | |
|  * | |
|  * @param argc The argc argument of main(). | |
|  * @param argv The argv argument of main(). | |
|  * @return Return code, 0 if successfull, not 0 otherwise. | |
|  */ | |
| int main(const int argc, const char** argv) { | |
|     //try { | |
|         storm::utility::setUp(); | |
|         storm::cli::printHeader("Storm-pomdp", argc, argv); | |
|         initializeSettings(); | |
| 
 | |
|         bool optionsCorrect = storm::cli::parseOptions(argc, argv); | |
|         if (!optionsCorrect) { | |
|             return -1; | |
|         } | |
| 
 | |
| 
 | |
|         auto const& coreSettings = storm::settings::getModule<storm::settings::modules::CoreSettings>(); | |
|         auto const& pomdpSettings = storm::settings::getModule<storm::settings::modules::POMDPSettings>(); | |
|         auto const& ioSettings = storm::settings::getModule<storm::settings::modules::IOSettings>(); | |
|         auto const &general = storm::settings::getModule<storm::settings::modules::GeneralSettings>(); | |
|         auto const &debug = storm::settings::getModule<storm::settings::modules::DebugSettings>(); | |
|         auto const& pomdpQualSettings = storm::settings::getModule<storm::settings::modules::QualitativePOMDPAnalysisSettings>(); | |
| 
 | |
|         if (general.isVerboseSet()) { | |
|             storm::utility::setLogLevel(l3pp::LogLevel::INFO); | |
|         } | |
|         if (debug.isDebugSet()) { | |
|             storm::utility::setLogLevel(l3pp::LogLevel::DEBUG); | |
|         } | |
|         if (debug.isTraceSet()) { | |
|             storm::utility::setLogLevel(l3pp::LogLevel::TRACE); | |
|         } | |
|         if (debug.isLogfileSet()) { | |
|             storm::utility::initializeFileLogging(); | |
|         } | |
| 
 | |
|         // For several engines, no model building step is performed, but the verification is started right away. | |
|         storm::settings::modules::CoreSettings::Engine engine = coreSettings.getEngine(); | |
| 
 | |
|         storm::cli::SymbolicInput symbolicInput = storm::cli::parseAndPreprocessSymbolicInput(); | |
|         // We should not export here if we are going to do some processing first. | |
|         auto model = storm::cli::buildPreprocessExportModelWithValueTypeAndDdlib<storm::dd::DdType::Sylvan, double>(symbolicInput, engine); | |
|         STORM_LOG_THROW(model && model->getType() == storm::models::ModelType::Pomdp, storm::exceptions::WrongFormatException, "Expected a POMDP."); | |
|         std::shared_ptr<storm::models::sparse::Pomdp<double>> pomdp = model->template as<storm::models::sparse::Pomdp<double>>(); | |
| 
 | |
|         std::shared_ptr<storm::logic::Formula const> formula; | |
|         if (!symbolicInput.properties.empty()) { | |
|             formula = symbolicInput.properties.front().getRawFormula(); | |
|             STORM_PRINT_AND_LOG("Analyzing property '" << *formula << "'" << std::endl); | |
|             STORM_LOG_WARN_COND(symbolicInput.properties.size() == 1, "There is currently no support for multiple properties. All other properties will be ignored."); | |
|         } | |
| 
 | |
|         if (pomdpSettings.isAnalyzeUniqueObservationsSet()) { | |
|             STORM_PRINT_AND_LOG("Analyzing states with unique observation ..." << std::endl); | |
|             storm::analysis::UniqueObservationStates<double> uniqueAnalysis(*pomdp); | |
|             std::cout << uniqueAnalysis.analyse() << std::endl; | |
|         } | |
| 
 | |
|         if (formula) { | |
|             storm::logic::ProbabilityOperatorFormula const &probFormula = formula->asProbabilityOperatorFormula(); | |
|             storm::logic::Formula const &subformula1 = probFormula.getSubformula(); | |
| 
 | |
| 
 | |
|             if (formula->isProbabilityOperatorFormula()) { | |
|                 boost::optional<storm::storage::BitVector> prob1States; | |
|                 boost::optional<storm::storage::BitVector> prob0States; | |
|                 if (pomdpSettings.isSelfloopReductionSet() && !storm::solver::minimize(formula->asProbabilityOperatorFormula().getOptimalityType())) { | |
|                     STORM_PRINT_AND_LOG("Eliminating self-loop choices ..."); | |
|                     uint64_t oldChoiceCount = pomdp->getNumberOfChoices(); | |
|                     storm::transformer::GlobalPOMDPSelfLoopEliminator<double> selfLoopEliminator(*pomdp); | |
|                     pomdp = selfLoopEliminator.transform(); | |
|                     STORM_PRINT_AND_LOG(oldChoiceCount - pomdp->getNumberOfChoices() << " choices eliminated through self-loop elimination." << std::endl); | |
|                 } | |
|                 if (pomdpSettings.isQualitativeReductionSet()) { | |
|                     storm::analysis::QualitativeAnalysis<double> qualitativeAnalysis(*pomdp); | |
|                     STORM_PRINT_AND_LOG("Computing states with probability 0 ..."); | |
|                     prob0States = qualitativeAnalysis.analyseProb0(formula->asProbabilityOperatorFormula()); | |
|                     std::cout << *prob0States << std::endl; | |
|                     STORM_PRINT_AND_LOG(" done." << std::endl); | |
|                     STORM_PRINT_AND_LOG("Computing states with probability 1 ..."); | |
|                     prob1States = qualitativeAnalysis.analyseProb1(formula->asProbabilityOperatorFormula()); | |
|                     std::cout << *prob1States << std::endl; | |
|                     STORM_PRINT_AND_LOG(" done." << std::endl); | |
|                     //std::cout << "actual reduction not yet implemented..." << std::endl; | |
|                     storm::pomdp::transformer::KnownProbabilityTransformer<double> kpt = storm::pomdp::transformer::KnownProbabilityTransformer<double>(); | |
|                     pomdp = kpt.transform(*pomdp, *prob0States, *prob1States); | |
|                 } | |
| 
 | |
|                 if (ioSettings.isExportDotSet()) { | |
|                     std::shared_ptr<storm::models::sparse::Model<double>> sparseModel = pomdp; | |
|                     storm::api::exportSparseModelAsDot(sparseModel, ioSettings.getExportDotFilename(), ioSettings.getExportDotMaxWidth()); | |
|                 } | |
|                 if (ioSettings.isExportExplicitSet()) { | |
|                     std::shared_ptr<storm::models::sparse::Model<double>> sparseModel = pomdp; | |
|                     storm::api::exportSparseModelAsDrn(sparseModel, ioSettings.getExportExplicitFilename()); | |
|                 } | |
| 
 | |
| 
 | |
| 
 | |
|                 if (pomdpSettings.isGridApproximationSet()) { | |
| 
 | |
|                     std::set<uint32_t> targetObservationSet; | |
|                     storm::storage::BitVector targetStates(pomdp->getNumberOfStates()); | |
|                     storm::storage::BitVector badStates(pomdp->getNumberOfStates()); | |
| 
 | |
|                     bool validFormula = extractTargetAndSinkObservationSets(pomdp, subformula1, targetObservationSet, targetStates, badStates); | |
|                     STORM_LOG_THROW(validFormula, storm::exceptions::InvalidPropertyException, | |
|                                     "The formula is not supported by the grid approximation"); | |
|                     STORM_LOG_ASSERT(!targetObservationSet.empty(), "The set of target observations is empty!"); | |
| 
 | |
|                     storm::pomdp::modelchecker::ApproximatePOMDPModelchecker<double> checker = storm::pomdp::modelchecker::ApproximatePOMDPModelchecker<double>(); | |
|                     double overRes = storm::utility::one<double>(); | |
|                     double underRes = storm::utility::zero<double>(); | |
|                     std::unique_ptr<storm::pomdp::modelchecker::POMDPCheckResult<double>> result; | |
| 
 | |
|                     //result = checker.refineReachabilityProbability(*pomdp, targetObservationSet,probFormula.getOptimalityType() == storm::OptimizationDirection::Minimize, pomdpSettings.getGridResolution(),1,10); | |
|                     result = checker.computeReachabilityProbabilityOTF(*pomdp, targetObservationSet, probFormula.getOptimalityType() == storm::OptimizationDirection::Minimize, | |
|                                                                        pomdpSettings.getGridResolution(), pomdpSettings.getExplorationThreshold()); | |
|                     overRes = result->OverapproximationValue; | |
|                     underRes = result->UnderapproximationValue; | |
|                     if (overRes != underRes) { | |
|                         STORM_PRINT("Overapproximation Result: " << overRes << std::endl) | |
|                         STORM_PRINT("Underapproximation Result: " << underRes << std::endl) | |
|                     } else { | |
|                         STORM_PRINT("Result: " << overRes << std::endl) | |
|                     } | |
|                 } | |
|                 if (pomdpSettings.isMemlessSearchSet()) { | |
|                     storm::analysis::QualitativeAnalysis<double> qualitativeAnalysis(*pomdp); | |
|                     // After preprocessing, this might be done cheaper. | |
|                     storm::storage::BitVector targetStates = qualitativeAnalysis.analyseProb1(formula->asProbabilityOperatorFormula()); | |
|                     storm::storage::BitVector surelyNotAlmostSurelyReachTarget = qualitativeAnalysis.analyseProbSmaller1(formula->asProbabilityOperatorFormula()); | |
|                     std::set<uint32_t> targetObservationSet = extractObservations(*pomdp, targetStates); | |
| 
 | |
|                     storm::expressions::ExpressionManager expressionManager; | |
|                     std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory = std::make_shared<storm::utility::solver::Z3SmtSolverFactory>(); | |
| 
 | |
|                     uint64_t lookahead = pomdpQualSettings.getLookahead(); | |
|                     if (lookahead == 0) { | |
|                         lookahead = pomdp->getNumberOfStates(); | |
|                     } | |
|                     storm::pomdp::MemlessSearchOptions options; | |
| 
 | |
|                     options.onlyDeterministicStrategies = pomdpQualSettings.isOnlyDeterministicSet(); | |
|                     uint64_t loglevel = 0; | |
|                     // TODO a big ugly, but we have our own loglevels. | |
|                     if(storm::utility::getLogLevel() == l3pp::LogLevel::INFO) { | |
|                         loglevel = 1; | |
|                     } | |
|                     else if(storm::utility::getLogLevel() == l3pp::LogLevel::DEBUG) { | |
|                         loglevel = 2; | |
|                     } | |
|                     else if(storm::utility::getLogLevel() == l3pp::LogLevel::TRACE) { | |
|                         loglevel = 3; | |
|                     } | |
|                     options.setDebugLevel(loglevel); | |
| 
 | |
|                     if (pomdpQualSettings.isExportSATCallsSet()) { | |
|                         options.setExportSATCalls(pomdpQualSettings.getExportSATCallsPath()); | |
|                     } | |
| 
 | |
|                     if (storm::utility::graph::checkIfECWithChoiceExists(pomdp->getTransitionMatrix(), pomdp->getBackwardTransitions(), ~targetStates & ~surelyNotAlmostSurelyReachTarget, storm::storage::BitVector(pomdp->getNumberOfChoices(), true))) { | |
|                         options.lookaheadRequired = true; | |
|                         STORM_LOG_DEBUG("Lookahead required."); | |
|                     } else { | |
|                         options.lookaheadRequired = false; | |
|                         STORM_LOG_DEBUG("No lookahead required."); | |
|                     } | |
| 
 | |
| 
 | |
|                     if (pomdpSettings.getMemlessSearchMethod() == "ccd16memless") { | |
|                         storm::pomdp::QualitativeStrategySearchNaive<double> memlessSearch(*pomdp, targetObservationSet, targetStates, surelyNotAlmostSurelyReachTarget, smtSolverFactory); | |
|                         memlessSearch.findNewStrategyForSomeState(lookahead); | |
|                     } else if (pomdpSettings.getMemlessSearchMethod() == "iterative") { | |
|                         storm::pomdp::MemlessStrategySearchQualitative<double> memlessSearch(*pomdp, targetObservationSet, targetStates, surelyNotAlmostSurelyReachTarget, smtSolverFactory, options); | |
|                         memlessSearch.findNewStrategyForSomeState(lookahead); | |
|                         memlessSearch.finalizeStatistics(); | |
|                         memlessSearch.getStatistics().print(); | |
|                     } else { | |
|                         STORM_LOG_ERROR("This method is not implemented."); | |
|                     } | |
| 
 | |
| 
 | |
|                 } | |
|             } else if (formula->isRewardOperatorFormula()) { | |
|                 if (pomdpSettings.isSelfloopReductionSet() && storm::solver::minimize(formula->asRewardOperatorFormula().getOptimalityType())) { | |
|                     STORM_PRINT_AND_LOG("Eliminating self-loop choices ..."); | |
|                     uint64_t oldChoiceCount = pomdp->getNumberOfChoices(); | |
|                     storm::transformer::GlobalPOMDPSelfLoopEliminator<double> selfLoopEliminator(*pomdp); | |
|                     pomdp = selfLoopEliminator.transform(); | |
|                     STORM_PRINT_AND_LOG(oldChoiceCount - pomdp->getNumberOfChoices() << " choices eliminated through self-loop elimination." << std::endl); | |
|                 } | |
|                 if (pomdpSettings.isGridApproximationSet()) { | |
|                     std::string rewardModelName; | |
|                     storm::logic::RewardOperatorFormula const &rewFormula = formula->asRewardOperatorFormula(); | |
|                     if (rewFormula.hasRewardModelName()) { | |
|                         rewardModelName = rewFormula.getRewardModelName(); | |
|                     } | |
|                     storm::logic::Formula const &subformula1 = rewFormula.getSubformula(); | |
| 
 | |
|                     std::set<uint32_t> targetObservationSet; | |
|                     //TODO refactor | |
|                     bool validFormula = false; | |
|                     if (subformula1.isEventuallyFormula()) { | |
|                         storm::logic::EventuallyFormula const &eventuallyFormula = subformula1.asEventuallyFormula(); | |
|                         storm::logic::Formula const &subformula2 = eventuallyFormula.getSubformula(); | |
|                         if (subformula2.isAtomicLabelFormula()) { | |
|                             storm::logic::AtomicLabelFormula const &alFormula = subformula2.asAtomicLabelFormula(); | |
|                             validFormula = true; | |
|                             std::string targetLabel = alFormula.getLabel(); | |
|                             auto labeling = pomdp->getStateLabeling(); | |
|                             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                                 if (labeling.getStateHasLabel(targetLabel, state)) { | |
|                                     targetObservationSet.insert(pomdp->getObservation(state)); | |
|                                 } | |
|                             } | |
|                         } else if (subformula2.isAtomicExpressionFormula()) { | |
|                             validFormula = true; | |
|                             std::stringstream stream; | |
|                             stream << subformula2.asAtomicExpressionFormula().getExpression(); | |
|                             storm::logic::AtomicLabelFormula formula3 = storm::logic::AtomicLabelFormula(stream.str()); | |
|                             std::string targetLabel = formula3.getLabel(); | |
|                             auto labeling = pomdp->getStateLabeling(); | |
|                             for (size_t state = 0; state < pomdp->getNumberOfStates(); ++state) { | |
|                                 if (labeling.getStateHasLabel(targetLabel, state)) { | |
|                                     targetObservationSet.insert(pomdp->getObservation(state)); | |
|                                 } | |
|                             } | |
|                         } | |
|                     } | |
|                     STORM_LOG_THROW(validFormula, storm::exceptions::InvalidPropertyException, | |
|                                     "The formula is not supported by the grid approximation"); | |
|                     STORM_LOG_ASSERT(!targetObservationSet.empty(), "The set of target observations is empty!"); | |
| 
 | |
|                     storm::pomdp::modelchecker::ApproximatePOMDPModelchecker<double> checker = storm::pomdp::modelchecker::ApproximatePOMDPModelchecker<double>(); | |
|                     double overRes = storm::utility::one<double>(); | |
|                     double underRes = storm::utility::zero<double>(); | |
|                     std::unique_ptr<storm::pomdp::modelchecker::POMDPCheckResult<double>> result; | |
|                     result = checker.computeReachabilityReward(*pomdp, targetObservationSet, | |
|                                                                rewFormula.getOptimalityType() == | |
|                                                                storm::OptimizationDirection::Minimize, | |
|                                                                pomdpSettings.getGridResolution()); | |
|                     overRes = result->OverapproximationValue; | |
|                     underRes = result->UnderapproximationValue; | |
|                 } | |
| 
 | |
|             } | |
|             if (pomdpSettings.getMemoryBound() > 1) { | |
|                 STORM_PRINT_AND_LOG("Computing the unfolding for memory bound " << pomdpSettings.getMemoryBound() << " and memory pattern '" << storm::storage::toString(pomdpSettings.getMemoryPattern()) << "' ..."); | |
|                 storm::storage::PomdpMemory memory = storm::storage::PomdpMemoryBuilder().build(pomdpSettings.getMemoryPattern(), pomdpSettings.getMemoryBound()); | |
|                 std::cout << memory.toString() << std::endl; | |
|                 storm::transformer::PomdpMemoryUnfolder<double> memoryUnfolder(*pomdp, memory); | |
|                 pomdp = memoryUnfolder.transform(); | |
|                 STORM_PRINT_AND_LOG(" done." << std::endl); | |
|                 pomdp->printModelInformationToStream(std::cout); | |
|             } else { | |
|                 STORM_PRINT_AND_LOG("Assumming memoryless schedulers." << std::endl;) | |
|             } | |
| 
 | |
|             // From now on the pomdp is considered memoryless | |
|  | |
|             if (pomdpSettings.isMecReductionSet()) { | |
|                 STORM_PRINT_AND_LOG("Eliminating mec choices ..."); | |
|                 // Note: Elimination of mec choices only preserves memoryless schedulers. | |
|                 uint64_t oldChoiceCount = pomdp->getNumberOfChoices(); | |
|                 storm::transformer::GlobalPomdpMecChoiceEliminator<double> mecChoiceEliminator(*pomdp); | |
|                 pomdp = mecChoiceEliminator.transform(*formula); | |
|                 STORM_PRINT_AND_LOG(" done." << std::endl); | |
|                 STORM_PRINT_AND_LOG(oldChoiceCount - pomdp->getNumberOfChoices() << " choices eliminated through MEC choice elimination." << std::endl); | |
|                 pomdp->printModelInformationToStream(std::cout); | |
|             } | |
| 
 | |
|             if (pomdpSettings.isTransformBinarySet() || pomdpSettings.isTransformSimpleSet()) { | |
|                 if (pomdpSettings.isTransformSimpleSet()) { | |
|                     STORM_PRINT_AND_LOG("Transforming the POMDP to a simple POMDP."); | |
|                     pomdp = storm::transformer::BinaryPomdpTransformer<double>().transform(*pomdp, true); | |
|                 } else { | |
|                     STORM_PRINT_AND_LOG("Transforming the POMDP to a binary POMDP."); | |
|                     pomdp = storm::transformer::BinaryPomdpTransformer<double>().transform(*pomdp, false); | |
|                 } | |
|                 pomdp->printModelInformationToStream(std::cout); | |
|                 STORM_PRINT_AND_LOG(" done." << std::endl); | |
|             } | |
| 
 | |
| 
 | |
|             if (pomdpSettings.isExportToParametricSet()) { | |
|                 STORM_PRINT_AND_LOG("Transforming memoryless POMDP to pMC..."); | |
|                 storm::transformer::ApplyFiniteSchedulerToPomdp<double> toPMCTransformer(*pomdp); | |
|                 std::string transformMode = pomdpSettings.getFscApplicationTypeString(); | |
|                 auto pmc = toPMCTransformer.transform(storm::transformer::parsePomdpFscApplicationMode(transformMode)); | |
|                 STORM_PRINT_AND_LOG(" done." << std::endl); | |
|                 pmc->printModelInformationToStream(std::cout); | |
|                 STORM_PRINT_AND_LOG("Simplifying pMC..."); | |
|                 //if (generalSettings.isBisimulationSet()) { | |
|                 pmc = storm::api::performBisimulationMinimization<storm::RationalFunction>(pmc->as<storm::models::sparse::Dtmc<storm::RationalFunction>>(),{formula}, storm::storage::BisimulationType::Strong)->as<storm::models::sparse::Dtmc<storm::RationalFunction>>(); | |
| 
 | |
|                 //} | |
|                 STORM_PRINT_AND_LOG(" done." << std::endl); | |
|                 pmc->printModelInformationToStream(std::cout); | |
|                 STORM_PRINT_AND_LOG("Exporting pMC..."); | |
|                 storm::analysis::ConstraintCollector<storm::RationalFunction> constraints(*pmc); | |
|                 auto const& parameterSet = constraints.getVariables(); | |
|                 std::vector<storm::RationalFunctionVariable> parameters(parameterSet.begin(), parameterSet.end()); | |
|                 std::vector<std::string> parameterNames; | |
|                 for (auto const& parameter : parameters) { | |
|                     parameterNames.push_back(parameter.name()); | |
|                 } | |
|                 storm::api::exportSparseModelAsDrn(pmc, pomdpSettings.getExportToParametricFilename(), parameterNames); | |
|                 STORM_PRINT_AND_LOG(" done." << std::endl); | |
|             } | |
| 
 | |
|         } else { | |
|             STORM_LOG_WARN("Nothing to be done. Did you forget to specify a formula?"); | |
|         } | |
| 
 | |
|         // All operations have now been performed, so we clean up everything and terminate. | |
|         storm::utility::cleanUp(); | |
|         return 0; | |
|     // } catch (storm::exceptions::BaseException const &exception) { | |
|     //    STORM_LOG_ERROR("An exception caused Storm-pomdp to terminate. The message of the exception is: " << exception.what()); | |
|     //    return 1; | |
|     //} catch (std::exception const &exception) { | |
|     //    STORM_LOG_ERROR("An unexpected exception occurred and caused Storm-pomdp to terminate. The message of this exception is: " << exception.what()); | |
|     //    return 2; | |
|     //} | |
| }
 |