#pragma once #include "logic/Formula.h" #include "parser/DFTGalileoParser.h" #include "builder/ExplicitDFTModelBuilder.h" #include "modelchecker/results/CheckResult.h" #include "utility/storm.h" #include "storage/dft/DFTIsomorphism.h" #include "utility/bitoperations.h" #include template class DFTAnalyser { std::chrono::duration buildingTime = std::chrono::duration::zero(); std::chrono::duration explorationTime = std::chrono::duration::zero(); std::chrono::duration bisimulationTime = std::chrono::duration::zero(); std::chrono::duration modelCheckingTime = std::chrono::duration::zero(); std::chrono::duration totalTime = std::chrono::duration::zero(); ValueType checkResult = storm::utility::zero(); public: void check(storm::storage::DFT dft , std::shared_ptr const& formula, bool symred = true, bool allowModularisation = true, bool enableDC = true) { // Building DFT std::chrono::high_resolution_clock::time_point totalStart = std::chrono::high_resolution_clock::now(); // Optimizing DFT dft = dft.optimize(); std::vector> dfts; checkResult = checkHelper(dft, formula, symred, allowModularisation, enableDC); totalTime = std::chrono::high_resolution_clock::now() - totalStart; } private: ValueType checkHelper(storm::storage::DFT const& dft , std::shared_ptr const& formula, bool symred = true, bool allowModularisation = true, bool enableDC = true) { std::cout << "check helper called" << std::endl; bool invResults = false; std::vector> dfts = {dft}; std::vector res; size_t nrK = 0; // K out of M size_t nrM = 0; // K out of M if(allowModularisation) { if(dft.topLevelType() == storm::storage::DFTElementType::AND) { STORM_LOG_TRACE("top modularisation called AND"); dfts = dft.topModularisation(); STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); nrK = dfts.size(); nrM = dfts.size(); } if(dft.topLevelType() == storm::storage::DFTElementType::OR) { STORM_LOG_TRACE("top modularisation called OR"); dfts = dft.topModularisation(); STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); nrK = 0; nrM = dfts.size(); invResults = true; } if(dft.topLevelType() == storm::storage::DFTElementType::VOT) { STORM_LOG_TRACE("top modularisation called VOT"); dfts = dft.topModularisation(); STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); nrK = std::static_pointer_cast const>(dft.getTopLevelGate())->threshold(); nrM = dfts.size(); if(nrK <= nrM/2) { nrK -= 1; invResults = true; } } if(dfts.size() > 1) { STORM_LOG_TRACE("Recursive CHECK Call"); for(auto const ft : dfts) { res.push_back(checkHelper(ft, formula, symred, allowModularisation)); } } } if(res.empty()) { // Model based modularisation. auto const& models = buildMarkovModels(dfts, formula, symred, enableDC); for (auto const& model : models) { // Model checking std::cout << "Model checking..." << std::endl; std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); std::unique_ptr result(storm::verifySparseModel(model, formula)); std::cout << "done." << std::endl; assert(result); result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); modelCheckingTime += std::chrono::high_resolution_clock::now() - modelCheckingStart; res.push_back(result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second); } } if(nrM <= 1) { // No modularisation done. assert(res.size()==1); return res[0]; } STORM_LOG_TRACE("Combining all results... K=" << nrK << "; M=" << nrM << "; invResults=" << (invResults?"On":"Off")); ValueType result = storm::utility::zero(); int limK = invResults ? -1 : nrM+1; int chK = invResults ? -1 : 1; for(int cK = nrK; cK != limK; cK += chK ) { assert(cK >= 0); size_t permutation = smallestIntWithNBitsSet(static_cast(cK)); do { STORM_LOG_TRACE("Permutation="<(); for(size_t i = 0; i < res.size(); ++i) { if(permutation & (1 << i)) { permResult *= res[i]; } else { permResult *= storm::utility::one() - res[i]; } } STORM_LOG_TRACE("Result for permutation:"<() - result; } return result; } std::vector>> buildMarkovModels(std::vector> const& dfts, std::shared_ptr const& formula, bool symred, bool enableDC) { std::vector>> models; for(auto& dft : dfts) { std::chrono::high_resolution_clock::time_point buildingStart = std::chrono::high_resolution_clock::now(); std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) { auto colouring = dft.colourDFT(); symmetries = dft.findSymmetries(colouring); std::cout << "Found " << symmetries.groups.size() << " symmetries." << std::endl; STORM_LOG_TRACE("Symmetries: " << std::endl << symmetries); } std::chrono::high_resolution_clock::time_point buildingEnd = std::chrono::high_resolution_clock::now(); buildingTime += buildingEnd - buildingStart; // Building Markov Automaton std::cout << "Building Model..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft, symmetries, enableDC); typename storm::builder::ExplicitDFTModelBuilder::LabelOptions labeloptions; // TODO initialize this with the formula std::shared_ptr> model = builder.buildModel(labeloptions); //model->printModelInformationToStream(std::cout); std::cout << "No. states (Explored): " << model->getNumberOfStates() << std::endl; std::cout << "No. transitions (Explored): " << model->getNumberOfTransitions() << std::endl; std::chrono::high_resolution_clock::time_point explorationEnd = std::chrono::high_resolution_clock::now(); explorationTime += explorationEnd -buildingEnd; // Bisimulation if (model->isOfType(storm::models::ModelType::Ctmc)) { std::cout << "Bisimulation..." << std::endl; model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), {formula}, storm::storage::BisimulationType::Weak)->template as>(); //model->printModelInformationToStream(std::cout); } std::cout << "No. states (Bisimulation): " << model->getNumberOfStates() << std::endl; std::cout << "No. transitions (Bisimulation): " << model->getNumberOfTransitions() << std::endl; bisimulationTime += std::chrono::high_resolution_clock::now() - explorationEnd; models.push_back(model); } return models; } public: void printTimings(std::ostream& os = std::cout) { os << "Times:" << std::endl; os << "Building:\t" << buildingTime.count() << std::endl; os << "Exploration:\t" << explorationTime.count() << std::endl; os << "Bisimulation:\t" << bisimulationTime.count() << std::endl; os << "Modelchecking:\t" << modelCheckingTime.count() << std::endl; os << "Total:\t\t" << totalTime.count() << std::endl; } void printResult(std::ostream& os = std::cout) { os << "Result: ["; os << checkResult << "]" << std::endl; } };