From fd3ffafcd9e0efa27591567fc5efc9d3efae965a Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 8 Jul 2015 15:47:51 +0200 Subject: [PATCH 001/246] First version of the monolithic state space generation Former-commit-id: fab8f6e356ce0187373c5941da1640ac70e642d5 --- src/builder/ExplicitDFTModelBuilder.h | 93 +++ src/parser/DFTGalileoParser.cpp | 102 +++ src/parser/DFTGalileoParser.h | 29 + src/storage/BitVector.cpp | 25 + src/storage/BitVector.h | 7 + src/storage/dft/DFT.cpp | 121 ++++ src/storage/dft/DFT.h | 184 +++++ src/storage/dft/DFTBuilder.cpp | 132 ++++ src/storage/dft/DFTBuilder.h | 116 ++++ src/storage/dft/DFTElementState.h | 26 + src/storage/dft/DFTElements.cpp | 38 ++ src/storage/dft/DFTElements.h | 635 ++++++++++++++++++ src/storage/dft/DFTState.cpp | 125 ++++ src/storage/dft/DFTState.h | 138 ++++ .../dft/DFTStateSpaceGenerationQueues.h | 78 +++ src/storage/dft/OrderDFTElementsById.cpp | 18 + src/storage/dft/OrderDFTElementsById.h | 24 + src/storm-dyftee.cpp | 22 + src/utility/cli.h | 48 -- src/utility/initialize.h | 68 ++ src/utility/math.h | 8 + 21 files changed, 1989 insertions(+), 48 deletions(-) create mode 100644 src/builder/ExplicitDFTModelBuilder.h create mode 100644 src/parser/DFTGalileoParser.cpp create mode 100644 src/parser/DFTGalileoParser.h create mode 100644 src/storage/dft/DFT.cpp create mode 100644 src/storage/dft/DFT.h create mode 100644 src/storage/dft/DFTBuilder.cpp create mode 100644 src/storage/dft/DFTBuilder.h create mode 100644 src/storage/dft/DFTElementState.h create mode 100644 src/storage/dft/DFTElements.cpp create mode 100644 src/storage/dft/DFTElements.h create mode 100644 src/storage/dft/DFTState.cpp create mode 100644 src/storage/dft/DFTState.h create mode 100644 src/storage/dft/DFTStateSpaceGenerationQueues.h create mode 100644 src/storage/dft/OrderDFTElementsById.cpp create mode 100644 src/storage/dft/OrderDFTElementsById.h create mode 100644 src/storm-dyftee.cpp create mode 100644 src/utility/initialize.h diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h new file mode 100644 index 000000000..e8c169976 --- /dev/null +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -0,0 +1,93 @@ +#ifndef EXPLICITDFTMODELBUILDER_H +#define EXPLICITDFTMODELBUILDER_H + +#include "../storage/dft/DFT.h" + +namespace storm { + namespace builder { + class ExplicitDFTModelBuilder { + storm::storage::DFT const& mDft; + std::unordered_map mStateIndices; + size_t newIndex = 0; + //std::stack> mStack; + + public: + ExplicitDFTModelBuilder(storm::storage::DFT const& dft) : mDft(dft) + { + + } + + + void exploreStateSuccessors(storm::storage::DFTState const& state) { + size_t smallest = 0; + + while(smallest < state.nrFailableBEs()) { + //std::cout << "exploring from :" << std::endl; + //mDft.printElementsWithState(state); + //std::cout << "***************" << std::endl; + storm::storage::DFTState newState(state); + std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); + if(nextBE.first == nullptr) { + //std::cout << "break" << std::endl; + break; + + } + //std::cout << "with the failure of: " << nextBE.first->name() << std::endl; + + storm::storage::DFTStateSpaceGenerationQueues queues; + for(std::shared_ptr parent : nextBE.first->parents()) { + if(newState.isOperational(parent->id())) { + queues.propagateFailure(parent); + } + } + + + + while(!queues.failurePropagationDone()) { + std::shared_ptr next = queues.nextFailurePropagation(); + next->checkFails(newState, queues); + } + + while(!queues.failsafePropagationDone()) { + std::shared_ptr next = queues.nextFailsafePropagation(); + next->checkFailsafe(newState, queues); + } + + while(!queues.dontCarePropagationDone()) { + std::shared_ptr next = queues.nextDontCarePropagation(); + next->checkDontCareAnymore(newState, queues); + } + + + + if(!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { + auto it = mStateIndices.find(newState); + if(it == mStateIndices.end()) { + exploreStateSuccessors(newState); + mStateIndices.insert(std::make_pair(newState, newIndex++)); + if(newIndex % 16384 == 0) std::cout << newIndex << std::endl; + } + + } + else { + //std::cout << "done." << std::endl; + } + + + + } + } + + void buildCtmc() { + storm::storage::DFTState state(mDft); + exploreStateSuccessors(state); + std::cout << mStateIndices.size() << std::endl; + } + + }; + } +} + + +#endif /* EXPLICITDFTMODELBUILDER_H */ + diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp new file mode 100644 index 000000000..79e969260 --- /dev/null +++ b/src/parser/DFTGalileoParser.cpp @@ -0,0 +1,102 @@ +#include "DFTGalileoParser.h" + +#include +#include +#include +#include +#include "../exceptions/FileIoException.h" +#include "../exceptions/NotSupportedException.h" +#include "src/utility/macros.h" + +namespace storm { + namespace parser { + storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { + if(readFile(filename)) { + return mBuilder.build(); + } else { + throw storm::exceptions::FileIoException(); + } + } + + std::string stripQuotsFromName(std::string const& name) { + size_t firstQuots = name.find("\""); + size_t secondQuots = name.find("\"", firstQuots+1); + + if(firstQuots == std::string::npos) { + return name; + } else { + return name.substr(firstQuots+1,secondQuots-1); + } + } + + bool DFTGalileoParser::readFile(const std::string& filename) { + // constants + std::string topleveltoken = "toplevel"; + + + std::string toplevelId; + + + std::ifstream file; + file.exceptions ( std::ifstream::failbit ); + try { + file.open(filename); + } + catch (std::ifstream::failure e) { + std::cerr << "Exception during file opening on " << filename << "." << std::endl; + return false; + } + file.exceptions( 0 ); + + + std::string line; + while(std::getline(file, line)) + { + std::cout << line << std::endl; + size_t commentstarts = line.find("//"); + line = line.substr(0, commentstarts); + size_t firstsemicolon = line.find(";"); + line = line.substr(0, firstsemicolon); + + // Top level indicator. + if(boost::starts_with(line, topleveltoken)) { + toplevelId = stripQuotsFromName(line.substr(topleveltoken.size()+1)); + } + else + { + std::vector tokens; + boost::split(tokens, line, boost::is_any_of(" ")); + std::string name(stripQuotsFromName(tokens[0])); + + std::vector childNames; + for(unsigned i = 2; i < tokens.size(); ++i) { + childNames.push_back(stripQuotsFromName(tokens[i])); + } + if(tokens[1] == "and") { + mBuilder.addAndElement(name, childNames); + } else if(tokens[1] == "or") { + mBuilder.addOrElement(name, childNames); + } else if(boost::starts_with(tokens[1], "vot")) { + mBuilder.addVotElement(name, boost::lexical_cast(tokens[1].substr(3)), childNames); + } else if(tokens[1] == "pand") { + mBuilder.addPandElement(name, childNames); + } else if(tokens[1] == "wsp" || tokens[1] == "csp") { + mBuilder.addSpareElement(name, childNames); + } else if(boost::starts_with(tokens[1], "lambda=")) { + mBuilder.addBasicElement(name, boost::lexical_cast(tokens[1].substr(7)), boost::lexical_cast(tokens[2].substr(5))); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " + tokens[1] + " not recognized."); + } + } + + } + if(!mBuilder.setTopLevel(toplevelId)) { + STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown."); + } + file.close(); + return true; + } + + + } +} \ No newline at end of file diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h new file mode 100644 index 000000000..3dc6f11eb --- /dev/null +++ b/src/parser/DFTGalileoParser.h @@ -0,0 +1,29 @@ +#ifndef DFTGALILEOPARSER_H +#define DFTGALILEOPARSER_H + +#include "../storage/dft/DFT.h" +#include "../storage/dft/DFTBuilder.h" + +#include + + + +namespace storm { + namespace parser { + class DFTGalileoParser { + storm::storage::DFTBuilder mBuilder; + public: + storm::storage::DFT parseDFT(std::string const& filename); + + private: + bool readFile(std::string const& filename); + + + }; +} +} + + + +#endif /* DFTGALILEOPARSER_H */ + diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index 923916793..f74ac0312 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -9,6 +9,7 @@ #include "src/utility/OsDetection.h" #include "src/utility/Hash.h" #include "src/utility/macros.h" +#include "resources/3rdparty/glpk-4.53/src/zlib/zconf.h" namespace storm { namespace storage { @@ -71,6 +72,7 @@ namespace storm { } else { bucketVector = std::vector(bucketCount, 0); } + } template @@ -440,6 +442,29 @@ namespace storm { } } + uint_fast64_t BitVector::getTwoBitsAligned(uint_fast64_t bitIndex) const { + // Check whether it is aligned. + assert(bitIndex % 64 != 63); + uint64_t bucket = bitIndex >> 6; + uint64_t bitIndexInBucket = bitIndex & mod64mask; + + uint64_t mask; + if (bitIndexInBucket == 0) { + mask = -1ull; + } else { + mask = (1ull << (64 - bitIndexInBucket)) - 1ull; + } + + if (bitIndexInBucket < 62) { // bitIndexInBucket + 2 < 64 + // If the value stops before the end of the bucket, we need to erase some lower bits. + mask &= ~((1ull << (62 - (bitIndexInBucket))) - 1ull); + return (bucketVector[bucket] & mask) >> (62 - bitIndexInBucket); + } else { + // In this case, it suffices to take the current mask. + return bucketVector[bucket] & mask; + } + } + void BitVector::setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value) { STORM_LOG_ASSERT((value >> numberOfBits) == 0, "Integer value too large to fit in the given number of bits."); diff --git a/src/storage/BitVector.h b/src/storage/BitVector.h index ec4cce693..4759d358c 100644 --- a/src/storage/BitVector.h +++ b/src/storage/BitVector.h @@ -358,6 +358,13 @@ namespace storm { */ uint_fast64_t getAsInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits) const; + /*! + * + * @param bitIndex The index of the first of the two bits to get + * @return A value between 0 and 3, encoded as a byte. + */ + uint_fast64_t getTwoBitsAligned(uint_fast64_t bitIndex) const; + /*! * Sets the selected number of lowermost bits of the provided value at the given bit index. * diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp new file mode 100644 index 000000000..e06661988 --- /dev/null +++ b/src/storage/dft/DFT.cpp @@ -0,0 +1,121 @@ +#include "DFT.h" + +namespace storm { + namespace storage { + + DFT::DFT(std::vector> const& elements, std::shared_ptr const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0) + { + assert(elementIndicesCorrect()); + + size_t stateIndex = 0; + mUsageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; + + for(auto& elem : mElements) { + mIdToFailureIndex.push_back(stateIndex); + stateIndex += 2; + if(elem->isBasicElement()) { + ++mNrOfBEs; + } + else if(elem->isSpareGate()) { + ++mNrOfSpares; + for(auto const& spareReprs : std::static_pointer_cast(elem)->children()) { + if(mActivationIndex.count(spareReprs->id()) == 0) { + mActivationIndex[spareReprs->id()] = stateIndex++; + } + std::set module = {spareReprs->id()}; + spareReprs->extendSpareModule(module); + std::vector sparesAndBes; + for(auto const& modelem : module) { + if(mElements[modelem]->isSpareGate() || mElements[modelem]->isBasicElement()) { + sparesAndBes.push_back(modelem); + } + } + mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); + + } + std::static_pointer_cast(elem)->setUseIndex(stateIndex); + mUsageIndex.insert(std::make_pair(elem->id(), stateIndex)); + stateIndex += mUsageInfoBits; + + + } + } + + // For the top module, we assume, contrary to [Jun15], that we have all spare gates and basic elements which are not in another module. + std::set topModuleSet; + // Initialize with all ids. + for(auto const& elem : mElements) { + if (elem->isBasicElement() || elem->isSpareGate()) { + topModuleSet.insert(elem->id()); + } + } + + for(auto const& module : mSpareModules) { + for(auto const& index : module.second) { + topModuleSet.erase(index); + } + } + mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); + + mStateSize = stateIndex; + mTopLevelIndex = tle->id(); + + } + + void DFT::printElements(std::ostream& os) const { + for (auto const& elem : mElements) { + elem->print(os); + os << std::endl; + } + } + + void DFT::printInfo(std::ostream& os) const { + os << "Top level index: " << mTopLevelIndex << std::endl << "Nr BEs" << mNrOfBEs << std::endl; + } + + void DFT::printSpareModules(std::ostream& os) const { + std::cout << "[" << mElements[mTopLevelIndex] << "] {"; + std::vector::const_iterator it = mTopModule.begin(); + assert(it != mTopModule.end()); + os << mElements[(*it)]->name(); + ++it; + while(it != mTopModule.end()) { + os << ", " << mElements[(*it)]->name(); + ++it; + } + os << "}" << std::endl; + + for(auto const& spareModule : mSpareModules) { + std::cout << "[" << mElements[spareModule.first]->name() << "] = {"; + os.flush(); + std::vector::const_iterator it = spareModule.second.begin(); + assert(it != spareModule.second.end()); + os << mElements[(*it)]->name(); + ++it; + while(it != spareModule.second.end()) { + os << ", " << mElements[(*it)]->name(); + os.flush(); + ++it; + } + os << "}" << std::endl; + } + } + + void DFT::printElementsWithState(DFTState const& state, std::ostream& os) const{ + for (auto const& elem : mElements) { + os << "[" << elem->id() << "]"; + elem->print(os); + os << "\t** " << state.getElementState(elem->id()); + if(elem->isSpareGate()) { + if(state.isActiveSpare(elem->id())) { + os << " actively"; + } + os << " using " << state.uses(elem->id()); + } + std::cout << std::endl; + + + } + } + } +} diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h new file mode 100644 index 000000000..1f8939fd7 --- /dev/null +++ b/src/storage/dft/DFT.h @@ -0,0 +1,184 @@ + +#ifndef DFT_H +#define DFT_H + + +#include "DFTElements.h" +#include "../BitVector.h" +#include +#include +#include +#include + +#include "../../utility/math.h" +#include + +namespace storm { + namespace storage { + + + struct DFTElementSort { + bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const { + if (a->rank() == 0 && b->rank() == 0) { + return a->isConstant(); + } else { + return a->rank() < b->rank(); + } + } + }; + + class DFT { + + + + private: + std::vector> mElements; + size_t mNrOfBEs; + size_t mNrOfSpares; + size_t mTopLevelIndex; + size_t mUsageInfoBits; + size_t mStateSize; + std::map mActivationIndex; + std::map> mSpareModules; + std::vector mTopModule; + std::vector mIdToFailureIndex; + std::map mUsageIndex; + + + public: + DFT(std::vector> const& elements, std::shared_ptr const& tle); + + + size_t stateSize() const { + return mStateSize; + } + + size_t nrElements() const { + return mElements.size(); + } + + size_t nrBasicElements() const { + return mNrOfBEs; + } + + size_t usageInfoBits() const { + return mUsageInfoBits; + } + + size_t usageIndex(size_t id) const { + assert(mUsageIndex.find(id) != mUsageIndex.end()); + return mUsageIndex.find(id)->second; + } + + size_t failureIndex(size_t id) const { + return mIdToFailureIndex[id]; + } + + void initializeUses(DFTState& state) const { + for(auto const& elem : mElements) { + if(elem->isSpareGate()) { + std::static_pointer_cast(elem)->initializeUses(state); + } + } + } + + void initializeActivation(DFTState& state) const { + state.activate(mTopLevelIndex); + for(auto const& elem : mTopModule) { + if(mElements[elem]->isSpareGate()) { + propagateActivation(state, state.uses(elem)); + } + } + } + + std::vector getSpareIndices() const { + std::vector indices; + for(auto const& elem : mElements) { + if(elem->isSpareGate()) { + indices.push_back(elem->id()); + } + } + return indices; + } + + std::vector const& module(size_t representativeId) const { + if(representativeId == mTopLevelIndex) { + return mTopModule; + } else { + assert(mSpareModules.count(representativeId)>0); + return mSpareModules.find(representativeId)->second; + } + } + + + void propagateActivation(DFTState& state, size_t representativeId) const { + state.activate(representativeId); + for(size_t id : module(representativeId)) { + if(mElements[id]->isSpareGate()) { + propagateActivation(state, state.uses(id)); + } + } + } + + std::vector nonColdBEs() const { + std::vector result; + for(std::shared_ptr elem : mElements) { + if(elem->isBasicElement() && !elem->isColdBasicElement()) { + result.push_back(elem->id()); + } + } + return result; + } + + std::shared_ptr const& getElement(size_t index) const { + assert(index < nrElements()); + return mElements[index]; + } + + std::shared_ptr> getBasicElement(size_t index) const { + assert(mElements[index]->isBasicElement()); + return std::static_pointer_cast>(mElements[index]); + } + + bool hasFailed(DFTState const& state) const { + return state.hasFailed(mTopLevelIndex); + } + + bool isFailsafe(DFTState const& state) const { + return state.isFailsafe(mTopLevelIndex); + } + + + void printElements(std::ostream& os = std::cout) const; + + void printInfo(std::ostream& os = std::cout) const; + + void printSpareModules(std::ostream& os = std::cout) const; + + void printElementsWithState(DFTState const& state, std::ostream& os = std::cout) const; + + private: + bool elementIndicesCorrect() const { + for(size_t i = 0; i < mElements.size(); ++i) { + if(mElements[i]->id() != i) return false; + } + return true; + } + + + + + }; + + + + + + + + + + } +} +#endif /* DFT_H */ + diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp new file mode 100644 index 000000000..f6364a523 --- /dev/null +++ b/src/storage/dft/DFTBuilder.cpp @@ -0,0 +1,132 @@ + + +#include "DFTBuilder.h" + +#include "DFT.h" +#include +#include "OrderDFTElementsById.h" +#include "../../exceptions/WrongFormatException.h" + + +namespace storm { + namespace storage { + + + DFT DFTBuilder::build() { + for(auto& elem : mChildNames) { + for(auto const& child : elem.second) { + std::shared_ptr gate = std::static_pointer_cast(elem.first); + gate->pushBackChild(mElements[child]); + mElements[child]->addParent(gate); + } + } + + // Sort elements topologically + + + + // compute rank + for (auto& elem : mElements) { + computeRank(elem.second); + } + + std::vector> elems = topoSort(); + size_t id = 0; + for(std::shared_ptr e : elems) { + e->setId(id++); + } + for(auto& e : elems) { + std::cout << "[" << e->id() << "] "; + e->print(); + std::cout << std::endl; + } + return DFT(elems, mElements[topLevelIdentifier]); + + } + + unsigned DFTBuilder::computeRank(std::shared_ptr const& elem) { + if(elem->rank() == -1) { + if(elem->nrChildren() == 0) { + elem->setRank(0); + return 0; + } + std::shared_ptr gate = std::static_pointer_cast(elem); + unsigned maxrnk = 0; + unsigned newrnk = 0; + + for(std::shared_ptr const& child : gate->children()) { + newrnk = computeRank(child); + if(newrnk > maxrnk) { + maxrnk = newrnk; + } + } + elem->setRank(maxrnk+1); + return maxrnk + 1; + } else { + return elem->rank(); + } + } + + bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp) { + assert(children.size() > 0); + if(mElements.count(name) != 0) { + // Element with that name already exists. + return false; + } + std::shared_ptr element; + switch(tp) { + case DFTElementTypes::AND: + element = std::make_shared(mNextId++, name); + break; + case DFTElementTypes::OR: + element = std::make_shared(mNextId++, name); + break; + case DFTElementTypes::PAND: + element = std::make_shared(mNextId++, name); + break; + case DFTElementTypes::POR: + element = std::make_shared(mNextId++, name); + break; + case DFTElementTypes::SPARE: + element = std::make_shared(mNextId++, name); + break; + } + mElements[name] = element; + mChildNames[element] = children; + return true; + } + + + void DFTBuilder::topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L) { + if(visited[n] == topoSortColour::GREY) { + throw storm::exceptions::WrongFormatException("DFT is cyclic"); + } else if(visited[n] == topoSortColour::WHITE) { + if(n->isGate()) { + visited[n] = topoSortColour::GREY; + for(std::shared_ptr const& c : std::static_pointer_cast(n)->children()) { + topoVisit(c, visited, L); + } + } + visited[n] = topoSortColour::BLACK; + L.push_back(n); + + } + } + + std::vector> DFTBuilder::topoSort() { + std::map, topoSortColour> visited; + for(auto const& e : mElements) { + visited.insert(std::make_pair(e.second, topoSortColour::WHITE)); + } + + std::vector> L; + for(auto const& e : visited) { + topoVisit(e.first, visited, L); + } + //std::reverse(L.begin(), L.end()); + return L; + } + + } +} + diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h new file mode 100644 index 000000000..e29a8aa02 --- /dev/null +++ b/src/storage/dft/DFTBuilder.h @@ -0,0 +1,116 @@ + +#ifndef DFTBUILDER_H +#define DFTBUILDER_H + +#include "DFTElements.h" +#include +#include +#include + +namespace storm { + namespace storage { + class DFT; + + class DFTBuilder { + + std::size_t mNextId = 0; + std::string topLevelIdentifier; + std::unordered_map> mElements; + std::unordered_map, std::vector> mChildNames; + + public: + DFTBuilder() { + + } + + bool addAndElement(std::string const& name, std::vector const& children) { + return addStandardGate(name, children, DFTElementTypes::AND); + } + + bool addOrElement(std::string const& name, std::vector const& children) { + return addStandardGate(name, children, DFTElementTypes::OR); + } + + bool addPandElement(std::string const& name, std::vector const& children) { + return addStandardGate(name, children, DFTElementTypes::PAND); + } + + bool addPorElement(std::string const& name, std::vector const& children) { + return addStandardGate(name, children, DFTElementTypes::POR); + } + + bool addSpareElement(std::string const& name, std::vector const& children) { + return addStandardGate(name, children, DFTElementTypes::SPARE); + } + + + + bool addVotElement(std::string const& name, unsigned threshold, std::vector const& children) { + assert(children.size() > 0); + if(mElements.count(name) != 0) { + std::cerr << "Element with name: " << name << " already exists." << std::endl; + return false; + } + // It is an and-gate + if(children.size() == threshold) { + return addAndElement(name, children); + } + // It is an or-gate + if(threshold == 1) { + return addOrElement(name, children); + } + + if(threshold > children.size()) { + std::cerr << "Voting gates with threshold higher than the number of children is not supported." << std::endl; + return false; + } + std::shared_ptr element = std::make_shared(mNextId++, name, threshold); + + mElements[name] = element; + mChildNames[element] = children; + return true; + } + + bool addBasicElement(std::string const& name, double failureRate, double dormancyFactor) { + if(failureRate <= 0.0) { + std::cerr << "Failure rate must be positive." << std::endl; + return false; + } + + if(dormancyFactor < 0.0 || dormancyFactor > 1.0) { + std::cerr << "Dormancy factor must be between 0 and 1." << std::endl; + return false; + } + + mElements[name] = std::make_shared>(mNextId++, name, failureRate, dormancyFactor); + return true; + } + + bool setTopLevel(std::string const& tle) { + topLevelIdentifier = tle; + return mElements.count(tle) > 0; + } + + DFT build(); + + + private: + + unsigned computeRank(std::shared_ptr const& elem); + + bool addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp); + + enum class topoSortColour {WHITE, BLACK, GREY}; + + void topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L); + std::vector> topoSort(); + + + }; + } +} + + + +#endif /* DFTBUILDER_H */ + diff --git a/src/storage/dft/DFTElementState.h b/src/storage/dft/DFTElementState.h new file mode 100644 index 000000000..1926745bf --- /dev/null +++ b/src/storage/dft/DFTElementState.h @@ -0,0 +1,26 @@ + +#ifndef DFTELEMENTSTATE_H +#define DFTELEMENTSTATE_H + +namespace storm { + namespace storage { + enum class DFTElementState {Operational = 0, Failed = 2, Failsafe = 1, DontCare = 3}; + + inline std::ostream& operator<<(std::ostream& os, DFTElementState st) { + switch(st) { + case DFTElementState::Operational: + return os << "Operational"; + case DFTElementState::Failed: + return os << "Failed"; + case DFTElementState::Failsafe: + return os << "Failsafe"; + case DFTElementState::DontCare: + return os << "Don't Care"; + } + } + } +} + + +#endif /* DFTELEMENTSTATE_H */ + diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp new file mode 100644 index 000000000..b96ceafb4 --- /dev/null +++ b/src/storage/dft/DFTElements.cpp @@ -0,0 +1,38 @@ +#include "DFTElements.h" + +namespace storm { + namespace storage { + bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(!state.dontCare(mId)) + { + for(std::shared_ptr const& parent : mParents) { + if(state.isOperational(parent->id())) { + return false; + } + } + state.setDontCare(mId); + return true; + + } + return false; + } + + void DFTElement::extendSpareModule(std::set& elementsInModule) const { + for(auto const& parent : mParents) { + if(elementsInModule.count(parent->id()) == 0 && !parent->isSpareGate()) { + elementsInModule.insert(parent->id()); + parent->extendSpareModule(elementsInModule); + } + } + } + + template<> + bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(DFTElement::checkDontCareAnymore(state, queues)) { + state.beNoLongerFailable(mId); + return true; + } + return false; + } + } +} diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h new file mode 100644 index 000000000..9d3338022 --- /dev/null +++ b/src/storage/dft/DFTElements.h @@ -0,0 +1,635 @@ +#ifndef DFTELEMENTS_H +#define DFTELEMENTS_H + +#include +#include +#include +#include +#include +#include +#include + +#include "DFTState.h" +#include "DFTStateSpaceGenerationQueues.h" + +using std::size_t; + +namespace storm { + namespace storage { + class DFTGate; + + class DFTElement { + protected: + size_t mId; + std::string mName; + size_t mRank = -1; + std::vector> mParents; + + + + + public: + DFTElement(size_t id, std::string const& name) : mId(id), mName(name) + {} + virtual ~DFTElement() {} + + + virtual size_t id() const { + return mId; + } + + virtual void setRank(size_t rank) { + mRank = rank; + } + + virtual size_t rank() const { + return mRank; + } + + virtual bool isConstant() const { + return false; + } + + virtual bool isGate() const { + return false; + } + + virtual bool isBasicElement() const { + return false; + } + + virtual bool isColdBasicElement() const { + return false; + } + + virtual bool isSpareGate() const { + return false; + } + + virtual void setId(size_t newId) { + mId = newId; + } + + virtual std::string const& name() const { + return mName; + } + + bool addParent(std::shared_ptr const& e) { + if(std::find(mParents.begin(), mParents.end(), e) != mParents.end()) { + return false; + } + else + { + mParents.push_back(e); + return true; + } + } + + bool hasParents() const { + return !mParents.empty(); + } + + std::vector> const& parents() const { + return mParents; + } + + virtual void extendSpareModule(std::set& elementsInModule) const; + + virtual size_t nrChildren() const = 0; + virtual void print(std::ostream& = std::cout) const = 0; + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + }; + + + enum class DFTElementTypes {AND, COUNTING, OR, VOT, BE, CONSTF, CONSTS, PAND, SPARE, POR, FDEP, SEQAND}; + + inline bool isGateType(DFTElementTypes const& tp) { + switch(tp) { + case DFTElementTypes::AND: + case DFTElementTypes::COUNTING: + case DFTElementTypes::OR: + case DFTElementTypes::VOT: + case DFTElementTypes::PAND: + case DFTElementTypes::SPARE: + case DFTElementTypes::POR: + case DFTElementTypes::SEQAND: + return true; + case DFTElementTypes::BE: + case DFTElementTypes::CONSTF: + case DFTElementTypes::CONSTS: + case DFTElementTypes::FDEP: + return false; + default: + assert(false); + } + } + + class DFTGate : public DFTElement { + protected: + std::vector> mChildren; + public: + DFTGate(size_t id, std::string const& name, std::vector> const& children) : + DFTElement(id, name), mChildren(children) + {} + + virtual ~DFTGate() {} + + void pushBackChild(std::shared_ptr elem) { + return mChildren.push_back(elem); + } + + size_t nrChildren() const { + return mChildren.size(); + } + + std::vector> const& children() const { + return mChildren; + } + + virtual bool isGate() const { + return true; + } + + + virtual std::string typestring() const = 0; + virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void extendSpareModule(std::set& elementsInSpareModule) const override { + DFTElement::extendSpareModule(elementsInSpareModule); + for(auto const& child : mChildren) { + if(elementsInSpareModule.count(child->id()) == 0) { + elementsInSpareModule.insert(child->id()); + child->extendSpareModule(elementsInSpareModule); + } + } + } + + virtual void print(std::ostream& os = std::cout) const { + os << "{" << name() << "} " << typestring() << "( "; + std::vector>::const_iterator it = mChildren.begin(); + os << (*it)->name(); + ++it; + while(it != mChildren.end()) { + os << ", " << (*it)->name(); + ++it; + } + os << ")"; + } + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(DFTElement::checkDontCareAnymore(state, queues)) { + childrenDontCare(state, queues); + return true; + } + return false; + } + protected: + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + for(std::shared_ptr parent : mParents) { + if(state.isOperational(parent->id())) { + queues.propagateFailure(parent); + } + } + state.setFailed(mId); + } + + void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + for(std::shared_ptr parent : mParents) { + if(state.isOperational(parent->id())) { + queues.propagateFailsafe(parent); + } + } + state.setFailsafe(mId); + } + + void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + queues.propagateDontCare(mChildren); + } + + bool hasFailsafeChild(DFTState& state) const { + for(auto const& child : mChildren) { + if(state.isFailsafe(child->id())) + { + return true; + } + } + return false; + } + + + bool hasFailedChild(DFTState& state) const { + for(auto const& child : mChildren) { + if(state.hasFailed(child->id())) { + return true; + } + } + return false; + } + + }; + + + + template + class DFTBE : public DFTElement { + + + FailureRateType mActiveFailureRate; + FailureRateType mPassiveFailureRate; + public: + DFTBE(size_t id, std::string const& name, FailureRateType failureRate, FailureRateType dormancyFactor) : + DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) + { + + } + + virtual size_t nrChildren() const { + return 0; + } + + FailureRateType const& activeFailureRate() const { + return mActiveFailureRate; + } + + FailureRateType const& passiveFailureRate() const { + return mPassiveFailureRate; + } + + void print(std::ostream& os = std::cout) const { + os << *this; + } + + bool isBasicElement() const { + return true; + } + + bool isColdBasicElement() const { + return mPassiveFailureRate == 0; + } + + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + }; + + inline std::ostream& operator<<(std::ostream& os, DFTBE const& be) { + return os << "{" << be.name() << "} BE(" << be.activeFailureRate() << ", " << be.passiveFailureRate() << ")"; + } + + + + + class DFTConst : public DFTElement { + bool mFailed; + public: + DFTConst(size_t id, std::string const& name, bool failed) : DFTElement(id, name), mFailed(failed) + { + + } + + bool failed() const { + return mFailed; + } + + virtual bool isConstant() const { + return true; + } + + virtual size_t nrChildren() const { + return 0; + } + + }; + + class DFTAnd : public DFTGate { + + public: + DFTAnd(size_t id, std::string const& name, std::vector> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + if(state.isOperational(mId)) { + for(auto const& child : mChildren) + { + if(!state.hasFailed(child->id())) { + return;// false; + } + } + fail(state, queues); + //return true; + } + //return false; + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(hasFailsafeChild(state)); + if(state.isOperational(mId)) { + failsafe(state, queues); + childrenDontCare(state, queues); + //return true; + } + //return false; + } + + std::string typestring() const { + return "AND"; + } + }; + + inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { + gate.print(os); + return os; + } + + + + class DFTOr : public DFTGate { + public: + DFTOr(size_t id, std::string const& name, std::vector> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + assert(hasFailedChild(state)); + if(state.isOperational(mId)) { + fail(state, queues); + //return true; + } + // return false; + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + for(auto const& child : mChildren) { + if(!state.isFailsafe(child->id())) { + return;// false; + } + } + failsafe(state, queues); + //return true; + } + + std::string typestring() const { + return "OR"; + } + private: + //static const std::string typestring = "or"; + }; + + inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { + gate.print(os); + return os; + } + + class DFTSeqAnd : public DFTGate { + public: + DFTSeqAnd(size_t id, std::string const& name, std::vector> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + if(!state.hasFailed(mId)) { + bool childOperationalBefore = false; + for(auto const& child : mChildren) + { + if(!state.hasFailed(child->id())) { + childOperationalBefore = true; + } + else { + if(childOperationalBefore) { + state.markAsInvalid(); + return; //false; + } + } + } + if(!childOperationalBefore) { + fail(state, queues); + //return true; + } + + } + //return false; + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(hasFailsafeChild(state)); + if(state.isOperational(mId)) { + failsafe(state, queues); + //return true; + } + //return false; + } + + std::string typestring() const { + return "SEQAND"; + } + private: + //static const std::string typestring = "seqand"; + }; + + inline std::ostream& operator<<(std::ostream& os, DFTSeqAnd const& gate) { + gate.print(os); + return os; + } + + class DFTPand : public DFTGate { + public: + DFTPand(size_t id, std::string const& name, std::vector> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(mId)) { + bool childOperationalBefore = false; + for(auto const& child : mChildren) + { + if(!state.hasFailed(child->id())) { + childOperationalBefore = true; + } else if(childOperationalBefore && state.hasFailed(child->id())){ + failsafe(state, queues); + childrenDontCare(state, queues); + return; //false; + } + } + if(!childOperationalBefore) { + fail(state, queues); + //return true; + } + } + // return false; + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(hasFailsafeChild(state)); + if(state.isOperational(mId)) { + failsafe(state, queues); + childrenDontCare(state, queues); + //return true; + } + //return false; + } + + std::string typestring() const { + return "PAND"; + } + }; + + inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { + gate.print(os); + return os; + } + + class DFTPor : public DFTGate { + public: + DFTPor(size_t id, std::string const& name, std::vector> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + assert(false); + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(false); + } + + std::string typestring() const { + return "POR"; + } + }; + + inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { + gate.print(os); + return os; + } + + class DFTVot : public DFTGate { + private: + unsigned mThreshold; + public: + DFTVot(size_t id, std::string const& name, unsigned threshold, std::vector> const& children = {}) : + DFTGate(id, name, children), mThreshold(threshold) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + if(state.isOperational(mId)) { + unsigned nrFailedChildren = 0; + for(auto const& child : mChildren) + { + if(state.hasFailed(child->id())) { + ++nrFailedChildren; + if(nrFailedChildren >= mThreshold) + { + fail(state, queues); + return;// true; + } + } + } + + } + // return false; + + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(hasFailsafeChild(state)); + if(state.isOperational(mId)) { + unsigned nrFailsafeChildren = 0; + for(auto const& child : mChildren) + { + if(state.isFailsafe(child->id())) { + ++nrFailsafeChildren; + if(nrFailsafeChildren > nrChildren() - mThreshold) + { + failsafe(state, queues); + childrenDontCare(state, queues); + return;// true; + } + } + } + } + //return false; + } + + std::string typestring() const { + return "VOT (" + std::to_string(mThreshold) + ")"; + } + + }; + + inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { + gate.print(os); + return os; + } + + class DFTSpare : public DFTGate { + size_t mUseIndex; + size_t mActiveIndex; + + public: + DFTSpare(size_t id, std::string const& name, std::vector> const& children = {}) : + DFTGate(id, name, children) + { + + } + + + std::string typestring() const { + return "SPARE"; + } + + bool isSpareGate() const { + return true; + } + + void setUseIndex(size_t useIndex) { + mUseIndex = useIndex; + } + + void setActiveIndex(size_t activeIndex) { + mActiveIndex = activeIndex; + } + + void initializeUses(storm::storage::DFTState& state) { + assert(mChildren.size() > 0); + state.setUsesAtPosition(mUseIndex, mChildren[0]->id()); + } + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(mId)) { + size_t uses = state.extractUses(mUseIndex); + if(!state.isOperational(uses)) { + // TODO compute children ids before. + std::vector childrenIds; + for(auto const& child : mChildren) { + childrenIds.push_back(child->id()); + } + + bool claimingSuccessful = state.claimNew(mId, mUseIndex, uses, childrenIds); + if(!claimingSuccessful) { + fail(state, queues); + } + } + } + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(mId)) { + if(state.isFailsafe(state.extractUses((mUseIndex)))) { + failsafe(state, queues); + childrenDontCare(state, queues); + } + } + } + }; + } +} + + + +#endif /* DFTELEMENTS_H */ + diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp new file mode 100644 index 000000000..5536b05a6 --- /dev/null +++ b/src/storage/dft/DFTState.cpp @@ -0,0 +1,125 @@ +#include "DFTState.h" +#include "DFTElements.h" +#include "DFT.h" + +namespace storm { + namespace storage { + + DFTState::DFTState(DFT const& dft) : mStatus(dft.stateSize()), mDft(dft) { + mInactiveSpares = dft.getSpareIndices(); + dft.initializeUses(*this); + dft.initializeActivation(*this); + std::vector alwaysActiveBEs = dft.nonColdBEs(); + mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); + + } + + DFTElementState DFTState::getElementState(size_t id) const { + return static_cast(mStatus.getAsInt(mDft.failureIndex(id), 2)); + } + + bool DFTState::isOperational(size_t id) const { + return getElementState(id) == DFTElementState::Operational; + } + + bool DFTState::hasFailed(size_t id) const { + return mStatus[mDft.failureIndex(id)]; + } + + bool DFTState::isFailsafe(size_t id) const { + return mStatus[mDft.failureIndex(id)+1]; + } + + bool DFTState::dontCare(size_t id) const { + return getElementState(id) == DFTElementState::DontCare; + } + + void DFTState::setFailed(size_t id) { + mStatus.set(mDft.failureIndex(id)); + } + + void DFTState::setFailsafe(size_t id) { + mStatus.set(mDft.failureIndex(id)+1); + } + + void DFTState::setDontCare(size_t id) { + mStatus.setFromInt(mDft.failureIndex(id), 2, static_cast(DFTElementState::DontCare) ); + } + + void DFTState::beNoLongerFailable(size_t id) { + auto it = std::find(mIsCurrentlyFailableBE.begin(), mIsCurrentlyFailableBE.end(), id); + if(it != mIsCurrentlyFailableBE.end()) { + mIsCurrentlyFailableBE.erase(it); + } + } + + + std::pair>, bool> DFTState::letNextBEFail(size_t index) + { + assert(index < mIsCurrentlyFailableBE.size()); + //std::cout << "currently failable: "; + //printCurrentlyFailable(std::cout); + std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); + mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); + setFailed(res.first->id()); + return res; + } + + void DFTState::activate(size_t repr) { + std::vector const& module = mDft.module(repr); + for(size_t elem : module) { + if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { + mIsCurrentlyFailableBE.push_back(elem); + } + else if(mDft.getElement(elem)->isSpareGate()) { + assert(std::find(mInactiveSpares.begin(), mInactiveSpares.end(), elem) != mInactiveSpares.end()); + mInactiveSpares.erase(std::find(mInactiveSpares.begin(), mInactiveSpares.end(), elem)); + } + } + } + + + bool DFTState::isActiveSpare(size_t id) const { + assert(mDft.getElement(id)->isSpareGate()); + return (std::find(mInactiveSpares.begin(), mInactiveSpares.end(), id) == mInactiveSpares.end()); + } + + uint_fast64_t DFTState::uses(size_t id) const { + return extractUses(mDft.usageIndex(id)); + } + + uint_fast64_t DFTState::extractUses(size_t from) const { + assert(mDft.usageInfoBits() < 64); + return mStatus.getAsInt(from, mDft.usageInfoBits()); + } + + bool DFTState::isUsed(size_t child) { + return (std::find(mUsedRepresentants.begin(), mUsedRepresentants.end(), child) != mUsedRepresentants.end()); + + } + + + + void DFTState::setUsesAtPosition(size_t usageIndex, size_t child) { + mStatus.setFromInt(usageIndex, mDft.usageInfoBits(), child); + mUsedRepresentants.push_back(child); + } + + bool DFTState::claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds) { + auto it = find(childIds.begin(), childIds.end(), currentlyUses); + assert(it != childIds.end()); + ++it; + while(it != childIds.end()) { + if(!hasFailed(*it) && !isUsed(*it)) { + setUsesAtPosition(usageIndex, *it); + if(isActiveSpare(spareId)) { + mDft.propagateActivation(*this,*it); + } + return true; + } + ++it; + } + return false; + } + } +} diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h new file mode 100644 index 000000000..719d49e37 --- /dev/null +++ b/src/storage/dft/DFTState.h @@ -0,0 +1,138 @@ +#ifndef DFTSTATE_H +#define DFTSTATE_H + +#include "../BitVector.h" +#include "DFTElementState.h" + + +namespace storm { + namespace storage { + + class DFT; + template + class DFTBE; + + + + class DFTState { + friend struct std::hash; + private: + storm::storage::BitVector mStatus; + std::vector mInactiveSpares; + std::vector mIsCurrentlyFailableBE; + std::vector mUsedRepresentants; + bool mValid = true; + const DFT& mDft; + + public: + DFTState(DFT const& dft); + + DFTElementState getElementState(size_t id) const; + + bool isOperational(size_t id) const; + + bool hasFailed(size_t id) const; + + bool isFailsafe(size_t id) const ; + + bool dontCare(size_t id) const; + + void setFailed(size_t id); + + void setFailsafe(size_t id); + + void setDontCare(size_t id); + + void beNoLongerFailable(size_t id); + + void activate(size_t repr); + + bool isActiveSpare(size_t id) const; + + void markAsInvalid() { + mValid = false; + } + + bool isInvalid() { + return !mValid; + } + + storm::storage::BitVector const& status() const { + return mStatus; + } + + /** + * This method gets the usage information for a spare + * @param id Id of the spare + * @return The child that currently is used. + */ + uint_fast64_t uses(size_t id) const; + + /** + * This method is commonly used to get the usage information for spares. + * @param from Starting index where the usage info is. + * @return The child that currently is used. + */ + uint_fast64_t extractUses(size_t from) const; + + /** + * Checks whether an element is currently used. + * @param child The id of the child for which we want to know whether it is currently used. + * @return true iff it is currently used by any of the spares. + */ + bool isUsed(size_t child); + + /** + * Sets to to the usageIndex which child is now used. + * @param usageIndex + * @param child + */ + void setUsesAtPosition(size_t usageIndex, size_t child); + + + + bool claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds); + + bool hasOutgoingEdges() const { + return !mIsCurrentlyFailableBE.empty(); + } + + size_t nrFailableBEs() const { + return mIsCurrentlyFailableBE.size(); + } + + std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); + + void printCurrentlyFailable(std::ostream& os) { + auto it = mIsCurrentlyFailableBE.begin(); + os << "{"; + if(it != mIsCurrentlyFailableBE.end()) { + os << *it; + } + ++it; + while(it != mIsCurrentlyFailableBE.end()) { + os << ", " << *it; + ++it; + } + os << "}" << std::endl; + } + + friend bool operator==(DFTState const& a, DFTState const& b) { + return a.mStatus == b.mStatus; + } + }; + + } +} + +namespace std { + template<> + struct hash { + size_t operator()(storm::storage::DFTState const& s) const { + return hash()(s.mStatus); + } + }; +} + +#endif /* DFTSTATE_H */ + diff --git a/src/storage/dft/DFTStateSpaceGenerationQueues.h b/src/storage/dft/DFTStateSpaceGenerationQueues.h new file mode 100644 index 000000000..f748e8232 --- /dev/null +++ b/src/storage/dft/DFTStateSpaceGenerationQueues.h @@ -0,0 +1,78 @@ +#ifndef DFTSTATESPACEGENERATIONQUEUES_H +#define DFTSTATESPACEGENERATIONQUEUES_H + +#include +#include +#include +#include + +#include "OrderDFTElementsById.h" + +namespace storm { + namespace storage { + class DFTGate; + class DFTElement; + + + + class DFTStateSpaceGenerationQueues { + std::priority_queue, std::vector>, OrderElementsByRank> failurePropagation; + std::vector> failsafePropagation; + std::vector> dontcarePropagation; + std::vector> activatePropagation; + + public: + void propagateFailure(std::shared_ptr const& elem) { + failurePropagation.push(elem); + } + + bool failurePropagationDone() const { + return failurePropagation.empty(); + } + + std::shared_ptr nextFailurePropagation() { + std::shared_ptr next= failurePropagation.top(); + failurePropagation.pop(); + return next; + } + + bool failsafePropagationDone() const { + return failsafePropagation.empty(); + } + + void propagateFailsafe(std::shared_ptr const& gate) { + failsafePropagation.push_back(gate); + } + + std::shared_ptr nextFailsafePropagation() { + std::shared_ptr next = failsafePropagation.back(); + failsafePropagation.pop_back(); + return next; + } + + bool dontCarePropagationDone() const { + return dontcarePropagation.empty(); + } + + void propagateDontCare(std::shared_ptr const& elem) { + dontcarePropagation.push_back(elem); + } + + void propagateDontCare(std::vector> const& elems) { + dontcarePropagation.insert(dontcarePropagation.end(), elems.begin(), elems.end()); + } + + std::shared_ptr nextDontCarePropagation() { + std::shared_ptr next = dontcarePropagation.back(); + dontcarePropagation.pop_back(); + return next; + } + }; + } + +} + + + +#endif /* DFTSTATESPACEGENERATIONQUEUES_H */ + diff --git a/src/storage/dft/OrderDFTElementsById.cpp b/src/storage/dft/OrderDFTElementsById.cpp new file mode 100644 index 000000000..017969848 --- /dev/null +++ b/src/storage/dft/OrderDFTElementsById.cpp @@ -0,0 +1,18 @@ +#include "OrderDFTElementsById.h" +#include "DFTElements.h" + +namespace storm { + namespace storage { + bool OrderElementsById::operator()(std::shared_ptr const& a , std::shared_ptr const& b) const { + return a->id() < b->id(); + } + bool OrderElementsById::operator ()(const std::shared_ptr& a, const std::shared_ptr& b) const { + return a->id() < b->id(); + } + + + bool OrderElementsByRank::operator ()(const std::shared_ptr& a, const std::shared_ptr& b) const { + return a->rank() < b->rank(); + } + } +} diff --git a/src/storage/dft/OrderDFTElementsById.h b/src/storage/dft/OrderDFTElementsById.h new file mode 100644 index 000000000..8dfc22da0 --- /dev/null +++ b/src/storage/dft/OrderDFTElementsById.h @@ -0,0 +1,24 @@ +#ifndef ORDERDFTELEMENTS_H +#define ORDERDFTELEMENTS_H + +#include + +namespace storm { + namespace storage { + class DFTGate; + class DFTElement; + + struct OrderElementsById { + bool operator()(std::shared_ptr const& a , std::shared_ptr const& b) const; + bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const; + }; + + struct OrderElementsByRank { + bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const; + }; + + } +} + +#endif /* ORDERDFTELEMENTSBYID_H */ + diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp new file mode 100644 index 000000000..39b614f8c --- /dev/null +++ b/src/storm-dyftee.cpp @@ -0,0 +1,22 @@ +#include "parser/DFTGalileoParser.h" +#include "utility/initialize.h" +#include "builder/ExplicitDFTModelBuilder.h" + + +/* + * Entry point for the DyFTeE backend. + */ +int main(int argc, char** argv) { + if(argc != 2) { + std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; + } + storm::utility::initialize::setUp(); + + storm::parser::DFTGalileoParser parser; + storm::storage::DFT dft = parser.parseDFT(argv[1]); + dft.printElements(); + dft.printSpareModules(); + storm::builder::ExplicitDFTModelBuilder builder(dft); + builder.buildCtmc(); +} + diff --git a/src/utility/cli.h b/src/utility/cli.h index 40f50acfa..1a44610f4 100644 --- a/src/utility/cli.h +++ b/src/utility/cli.h @@ -35,17 +35,7 @@ #include "lib/smtrat.h" #endif -#include "log4cplus/logger.h" -#include "log4cplus/loggingmacros.h" -#include "log4cplus/consoleappender.h" -#include "log4cplus/fileappender.h" -log4cplus::Logger logger; -log4cplus::Logger printer; -// Headers that provide auxiliary functionality. -#include "src/utility/storm-version.h" -#include "src/utility/OsDetection.h" -#include "src/settings/SettingsManager.h" // Headers related to parsing. #include "src/parser/AutoParser.h" @@ -93,44 +83,6 @@ namespace storm { namespace utility { namespace cli { - /*! - * Initializes the logging framework and sets up logging to console. - */ - void initializeLogger() { - logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main")); - log4cplus::SharedAppenderPtr consoleLogAppender(new log4cplus::ConsoleAppender()); - consoleLogAppender->setName("mainConsoleAppender"); - consoleLogAppender->setLayout(std::auto_ptr(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %b:%L: %m%n"))); - logger.addAppender(consoleLogAppender); - auto loglevel = storm::settings::debugSettings().isTraceSet() ? log4cplus::TRACE_LOG_LEVEL : storm::settings::debugSettings().isDebugSet() ? log4cplus::DEBUG_LOG_LEVEL : log4cplus::WARN_LOG_LEVEL; - logger.setLogLevel(loglevel); - consoleLogAppender->setThreshold(loglevel); - } - - /*! - * Performs some necessary initializations. - */ - void setUp() { - initializeLogger(); - std::cout.precision(10); - } - - /*! - * Performs some necessary clean-up. - */ - void cleanUp() { - // Intentionally left empty. - } - - /*! - * Sets up the logging to file. - */ - void initializeFileLogging() { - log4cplus::SharedAppenderPtr fileLogAppender(new log4cplus::FileAppender(storm::settings::debugSettings().getLogfilename())); - fileLogAppender->setName("mainFileAppender"); - fileLogAppender->setLayout(std::auto_ptr(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %F:%L: %m%n"))); - logger.addAppender(fileLogAppender); - } /*! * Gives the current working directory diff --git a/src/utility/initialize.h b/src/utility/initialize.h new file mode 100644 index 000000000..a58e6d3c9 --- /dev/null +++ b/src/utility/initialize.h @@ -0,0 +1,68 @@ + + +#ifndef INITIALIZE_H +#define INITIALIZE_H + + +#include "log4cplus/logger.h" +#include "log4cplus/loggingmacros.h" +#include "log4cplus/consoleappender.h" +#include "log4cplus/fileappender.h" +log4cplus::Logger logger; +log4cplus::Logger printer; + + +// Headers that provide auxiliary functionality. +#include "src/utility/storm-version.h" +#include "src/utility/OsDetection.h" +#include "src/settings/SettingsManager.h" + +namespace storm { + namespace utility { + namespace initialize { + + /*! + * Initializes the logging framework and sets up logging to console. + */ + void initializeLogger() { + logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main")); + log4cplus::SharedAppenderPtr consoleLogAppender(new log4cplus::ConsoleAppender()); + consoleLogAppender->setName("mainConsoleAppender"); + consoleLogAppender->setLayout(std::auto_ptr(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %b:%L: %m%n"))); + logger.addAppender(consoleLogAppender); + auto loglevel = storm::settings::debugSettings().isTraceSet() ? log4cplus::TRACE_LOG_LEVEL : storm::settings::debugSettings().isDebugSet() ? log4cplus::DEBUG_LOG_LEVEL : log4cplus::WARN_LOG_LEVEL; + logger.setLogLevel(loglevel); + consoleLogAppender->setThreshold(loglevel); + } + + /*! + * Performs some necessary initializations. + */ + void setUp() { + initializeLogger(); + std::cout.precision(10); + } + + /*! + * Performs some necessary clean-up. + */ + void cleanUp() { + // Intentionally left empty. + } + + /*! + * Sets up the logging to file. + */ + void initializeFileLogging() { + log4cplus::SharedAppenderPtr fileLogAppender(new log4cplus::FileAppender(storm::settings::debugSettings().getLogfilename())); + fileLogAppender->setName("mainFileAppender"); + fileLogAppender->setLayout(std::auto_ptr(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %F:%L: %m%n"))); + logger.addAppender(fileLogAppender); + } + + } + } +} + +#endif /* INITIALIZE_H */ + diff --git a/src/utility/math.h b/src/utility/math.h index ba21bcfa1..b2c41adc2 100644 --- a/src/utility/math.h +++ b/src/utility/math.h @@ -17,6 +17,14 @@ namespace storm { return std::log(number) / std::log(2); # endif } + + inline uint64_t uint64_log2(uint64_t n) + { + assert(n != 0); + #define S(k) if (n >= (UINT64_C(1) << k)) { i += k; n >>= k; } + uint64_t i = 0; S(32); S(16); S(8); S(4); S(2); S(1); return i; + #undef S + } } } } From 59fe9ace09ab2c7a607b6aceac7a11dc64aa2bab Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 17 Jul 2015 14:06:15 +0200 Subject: [PATCH 002/246] Further work on state space generation Former-commit-id: bb373138e5982beaa6188ddd21d76751c7a71f19 --- src/storage/dft/DFT.cpp | 3 ++- src/storage/dft/DFTElements.cpp | 14 ++++++++++++++ src/storage/dft/DFTElements.h | 32 +++++++++++++++++++++++++++++++- src/storage/dft/DFTUnit.h | 22 ++++++++++++++++++++++ src/storage/dft/SymmetricUnits.h | 7 +++++++ 5 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/storage/dft/DFTUnit.h create mode 100644 src/storage/dft/SymmetricUnits.h diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index e06661988..551c7ad2a 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -37,7 +37,6 @@ namespace storm { mUsageIndex.insert(std::make_pair(elem->id(), stateIndex)); stateIndex += mUsageInfoBits; - } } @@ -68,6 +67,8 @@ namespace storm { os << std::endl; } } + + void DFT::printInfo(std::ostream& os) const { os << "Top level index: " << mTopLevelIndex << std::endl << "Nr BEs" << mNrOfBEs << std::endl; diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index b96ceafb4..699fe47e5 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -26,6 +26,19 @@ namespace storm { } } + void DFTElement::extendUnit(std::set& unit) const { + unit.insert(mId); + for(auto const& parent : mParents) { + if(unit.count(parent->id()) != 0) { + parent->extendUnit(unit); + } + } + } + + void DFTElement::checkForSymmetricChildren() const { + + } + template<> bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(DFTElement::checkDontCareAnymore(state, queues)) { @@ -34,5 +47,6 @@ namespace storm { } return false; } + } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 9d3338022..12da6a4bf 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -99,6 +99,10 @@ namespace storm { virtual void print(std::ostream& = std::cout) const = 0; virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + + virtual std::vector independentUnit() const = 0; + + virtual void extendUnit(std::set& unit) const; }; @@ -166,6 +170,21 @@ namespace storm { } } + virtual std::vector independentUnit() const { + std::set unit = {mId}; + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + for(auto const& parent : mParents) { + if(unit.count(parent->id()) != 0) { + return {}; + } + } + return std::vector(unit.begin(), unit.end()); + } + + + virtual void print(std::ostream& os = std::cout) const { os << "{" << name() << "} " << typestring() << "( "; std::vector>::const_iterator it = mChildren.begin(); @@ -185,7 +204,16 @@ namespace storm { } return false; } + + virtual void extendUnit(std::set& unit) const { + DFTElement::extendUnit(unit); + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + } + protected: + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { for(std::shared_ptr parent : mParents) { if(state.isOperational(parent->id())) { @@ -269,7 +297,9 @@ namespace storm { return mPassiveFailureRate == 0; } - + virtual std::vector independentUnit() const { + return {mId}; + } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; }; diff --git a/src/storage/dft/DFTUnit.h b/src/storage/dft/DFTUnit.h new file mode 100644 index 000000000..18319b70c --- /dev/null +++ b/src/storage/dft/DFTUnit.h @@ -0,0 +1,22 @@ +#ifndef DFTUNIT_H +#define DFTUNIT_H + +namespace storm { + namespace storage { + class DFT; + + class DFTUnit { + private: + DFT const& mDft; + BitVector mMembers; + + + public: + DFTUnit(DFT const& dft, BitVector const& members); + }; + } +} + + +#endif /* DFTUNIT_H */ + diff --git a/src/storage/dft/SymmetricUnits.h b/src/storage/dft/SymmetricUnits.h new file mode 100644 index 000000000..3959593a1 --- /dev/null +++ b/src/storage/dft/SymmetricUnits.h @@ -0,0 +1,7 @@ +#ifndef SYMMETRICUNITS_H +#define SYMMETRICUNITS_H + + + +#endif /* SYMMETRICUNITS_H */ + From 37eacf574b2a42d2661ff5019f2dbac1bac881e6 Mon Sep 17 00:00:00 2001 From: sjunges Date: Mon, 20 Jul 2015 17:57:42 +0200 Subject: [PATCH 003/246] Further work on state space generation Former-commit-id: 3c0c4c016d0f3b0167070b27994a50bad5aa7d22 --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ae07a267..3e85ecbc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,6 +390,7 @@ endif() file(GLOB_RECURSE STORM_HEADERS ${PROJECT_SOURCE_DIR}/src/*.h) file(GLOB_RECURSE STORM_SOURCES_WITHOUT_MAIN ${PROJECT_SOURCE_DIR}/src/*/*.cpp) file(GLOB_RECURSE STORM_MAIN_FILE ${PROJECT_SOURCE_DIR}/src/storm.cpp) +file(GLOB_RECURSE STORM_MAIN_FILE ${PROJECT_SOURCE_DIR}/src/storm-dyftee.cpp) set(STORM_SOURCES "${STORM_SOURCES_WITHOUT_MAIN};${STORM_MAIN_FILE};") file(GLOB_RECURSE STORM_ADAPTERS_FILES ${PROJECT_SOURCE_DIR}/src/adapters/*.h ${PROJECT_SOURCE_DIR}/src/adapters/*.cpp) file(GLOB_RECURSE STORM_BUILDER_FILES ${PROJECT_SOURCE_DIR}/src/builder/*.h ${PROJECT_SOURCE_DIR}/src/builder/*.cpp) @@ -415,6 +416,7 @@ file(GLOB_RECURSE STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*. file(GLOB_RECURSE STORM_STORAGE_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.h ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.cpp) file(GLOB_RECURSE STORM_STORAGE_PRISM_FILES ${PROJECT_SOURCE_DIR}/src/storage/prism/*.h ${PROJECT_SOURCE_DIR}/src/storage/prism/*.cpp) file(GLOB_RECURSE STORM_STORAGE_SPARSE_FILES ${PROJECT_SOURCE_DIR}/src/storage/sparse/*.h ${PROJECT_SOURCE_DIR}/src/storage/sparse/*.cpp) +file(GLOB_RECURSE STORM_STORAGE_DFT_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/*.h ${PROJECT_SOURCE_DIR}/src/storage/sparse/*.cpp) file(GLOB_RECURSE STORM_UTILITY_FILES ${PROJECT_SOURCE_DIR}/src/utility/*.h ${PROJECT_SOURCE_DIR}/src/utility/*.cpp) # Test Sources # Note that the tests also need the source files, except for the main file @@ -428,6 +430,7 @@ file(GLOB_RECURSE STORM_BUILD_HEADERS ${PROJECT_BINARY_DIR}/include/*.h) # Group the headers and sources source_group(main FILES ${STORM_MAIN_FILE}) +source_group(dft FILES ${STORM_DYFTTEE_FILE}) source_group(adapters FILES ${STORM_ADAPTERS_FILES}) source_group(builder FILES ${STORM_BUILDER_FILES}) source_group(exceptions FILES ${STORM_EXCEPTIONS_FILES}) @@ -453,6 +456,7 @@ source_group(storage\\dd FILES ${STORM_STORAGE_DD_FILES}) source_group(storage\\expressions FILES ${STORM_STORAGE_EXPRESSIONS_FILES}) source_group(storage\\prism FILES ${STORM_STORAGE_PRISM_FILES}) source_group(storage\\sparse FILES ${STORM_STORAGE_SPARSE_FILES}) +source_group(storage\\dft FILES ${STORM_STORAGE_DFT_FILES}) source_group(utility FILES ${STORM_UTILITY_FILES}) source_group(functional-test FILES ${STORM_FUNCTIONAL_TEST_FILES}) source_group(performance-test FILES ${STORM_PERFORMANCE_TEST_FILES} ${}) @@ -518,6 +522,9 @@ target_link_libraries(storm-functional-tests storm) add_executable(storm-performance-tests ${STORM_PERFORMANCE_TEST_MAIN_FILE} ${STORM_PERFORMANCE_TEST_FILES}) target_link_libraries(storm-performance-tests storm) +add_executable(storm-dyftee ${STORM_MAIN_FILE}) +target_link_libraries(storm-dyftee storm) + ############################################################# ## ## Boost From 7643ebc70db9c468503f364a26051af929b39396 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 11 Dec 2015 19:10:55 +0100 Subject: [PATCH 004/246] Compile fixes Former-commit-id: d304a6a8e06346f729acc7f690ee8ae6154c4a4b --- src/storage/dft/DFTElements.h | 2 ++ src/storm-dyftee.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 12da6a4bf..d6245a606 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -103,6 +103,8 @@ namespace storm { virtual std::vector independentUnit() const = 0; virtual void extendUnit(std::set& unit) const; + + void checkForSymmetricChildren() const; }; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 39b614f8c..07e2624ee 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -10,7 +10,7 @@ int main(int argc, char** argv) { if(argc != 2) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; } - storm::utility::initialize::setUp(); + storm::utility::setUp(); storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(argv[1]); From 4bd59b86491eb6cc69df90fb950a25b0b6726661 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 14 Dec 2015 16:44:53 +0100 Subject: [PATCH 005/246] Small formatting changes Former-commit-id: 08eb57a9b0df7ff4f84ca2a4ead102a7ac71eef5 --- src/parser/DFTGalileoParser.cpp | 38 ++++++++++++++++++++------------- src/parser/DFTGalileoParser.h | 4 ---- src/storage/dft/DFT.cpp | 2 +- src/storage/dft/DFT.h | 4 ---- src/storage/dft/DFTBuilder.cpp | 29 +++++++++++-------------- src/storage/dft/DFTBuilder.h | 4 +--- src/storage/dft/DFTUnit.h | 2 ++ src/storm-dyftee.cpp | 12 ++++++++++- 8 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 79e969260..a93e84e92 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -24,6 +24,9 @@ namespace storm { if(firstQuots == std::string::npos) { return name; + } else if (secondQuots ==std::string::npos) { + std::cerr << "No ending quotation mark found in " << name <(tokens[1].substr(3)), childNames); + success = mBuilder.addVotElement(name, boost::lexical_cast(tokens[1].substr(3)), childNames); } else if(tokens[1] == "pand") { - mBuilder.addPandElement(name, childNames); + success = mBuilder.addPandElement(name, childNames); } else if(tokens[1] == "wsp" || tokens[1] == "csp") { - mBuilder.addSpareElement(name, childNames); + success = mBuilder.addSpareElement(name, childNames); } else if(boost::starts_with(tokens[1], "lambda=")) { - mBuilder.addBasicElement(name, boost::lexical_cast(tokens[1].substr(7)), boost::lexical_cast(tokens[2].substr(5))); + success = mBuilder.addBasicElement(name, boost::lexical_cast(tokens[1].substr(7)), boost::lexical_cast(tokens[2].substr(5))); } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " + tokens[1] + " not recognized."); + success = false; } } - + if (generalSuccess) { + generalSuccess = success; + } } if(!mBuilder.setTopLevel(toplevelId)) { STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown."); } file.close(); - return true; + return generalSuccess; } - } } \ No newline at end of file diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h index 3dc6f11eb..9d0cc0096 100644 --- a/src/parser/DFTGalileoParser.h +++ b/src/parser/DFTGalileoParser.h @@ -6,8 +6,6 @@ #include - - namespace storm { namespace parser { class DFTGalileoParser { @@ -23,7 +21,5 @@ namespace storm { } } - - #endif /* DFTGALILEOPARSER_H */ diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 551c7ad2a..8dee2a0b6 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -75,7 +75,7 @@ namespace storm { } void DFT::printSpareModules(std::ostream& os) const { - std::cout << "[" << mElements[mTopLevelIndex] << "] {"; + std::cout << "[" << mElements[mTopLevelIndex]->id() << "] {"; std::vector::const_iterator it = mTopModule.begin(); assert(it != mTopModule.end()); os << mElements[(*it)]->name(); diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 1f8939fd7..fbf035f44 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -16,7 +16,6 @@ namespace storm { namespace storage { - struct DFTElementSort { bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const { if (a->rank() == 0 && b->rank() == 0) { @@ -29,8 +28,6 @@ namespace storm { class DFT { - - private: std::vector> mElements; size_t mNrOfBEs; @@ -44,7 +41,6 @@ namespace storm { std::vector mIdToFailureIndex; std::map mUsageIndex; - public: DFT(std::vector> const& elements, std::shared_ptr const& tle); diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index f6364a523..b8e2c54a2 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -10,7 +10,6 @@ namespace storm { namespace storage { - DFT DFTBuilder::build() { for(auto& elem : mChildNames) { @@ -23,8 +22,6 @@ namespace storm { // Sort elements topologically - - // compute rank for (auto& elem : mElements) { computeRank(elem.second); @@ -48,23 +45,22 @@ namespace storm { if(elem->rank() == -1) { if(elem->nrChildren() == 0) { elem->setRank(0); - return 0; - } - std::shared_ptr gate = std::static_pointer_cast(elem); - unsigned maxrnk = 0; - unsigned newrnk = 0; + } else { + std::shared_ptr gate = std::static_pointer_cast(elem); + unsigned maxrnk = 0; + unsigned newrnk = 0; - for(std::shared_ptr const& child : gate->children()) { - newrnk = computeRank(child); - if(newrnk > maxrnk) { - maxrnk = newrnk; + for (std::shared_ptr const &child : gate->children()) { + newrnk = computeRank(child); + if (newrnk > maxrnk) { + maxrnk = newrnk; + } } + elem->setRank(maxrnk + 1); } - elem->setRank(maxrnk+1); - return maxrnk + 1; - } else { - return elem->rank(); } + + return elem->rank(); } bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp) { @@ -109,7 +105,6 @@ namespace storm { } visited[n] = topoSortColour::BLACK; L.push_back(n); - } } diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index e29a8aa02..68e64b1dc 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -43,8 +43,6 @@ namespace storm { return addStandardGate(name, children, DFTElementTypes::SPARE); } - - bool addVotElement(std::string const& name, unsigned threshold, std::vector const& children) { assert(children.size() > 0); if(mElements.count(name) != 0) { @@ -103,8 +101,8 @@ namespace storm { enum class topoSortColour {WHITE, BLACK, GREY}; void topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L); - std::vector> topoSort(); + std::vector> topoSort(); }; } diff --git a/src/storage/dft/DFTUnit.h b/src/storage/dft/DFTUnit.h index 18319b70c..5e179f091 100644 --- a/src/storage/dft/DFTUnit.h +++ b/src/storage/dft/DFTUnit.h @@ -1,6 +1,8 @@ #ifndef DFTUNIT_H #define DFTUNIT_H +#include "../BitVector.h" + namespace storm { namespace storage { class DFT; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 07e2624ee..e491cbe2b 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -11,12 +11,22 @@ int main(int argc, char** argv) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; } storm::utility::setUp(); - + + std::cout << "Parsing DFT file..." << std::endl; storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(argv[1]); + + std::cout << "Built data structure" << std::endl; dft.printElements(); dft.printSpareModules(); + + std::cout << "Building CTMC..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); builder.buildCtmc(); + std::cout << "Built CTMC" << std::endl; + + //std::cout << "Model checking..." << std::endl; + //TODO check CTMC + //std::cout << "Checked model" << std::endl; } From 7b37023f791145b2ad2e9978d2c958c714834831 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 15 Dec 2015 11:48:11 +0100 Subject: [PATCH 006/246] Some refactoring Former-commit-id: c5954a71a2b035a195f3cb2b1161a803a00dd744 --- src/builder/ExplicitDFTModelBuilder.cpp | 72 +++++++++++++++++++ src/builder/ExplicitDFTModelBuilder.h | 91 +++++-------------------- src/storage/dft/DFT.cpp | 15 +++- src/storage/dft/DFT.h | 4 +- src/storage/dft/DFTState.cpp | 21 ++++-- src/storage/dft/DFTState.h | 14 +++- src/storm-dyftee.cpp | 2 +- 7 files changed, 134 insertions(+), 85 deletions(-) create mode 100644 src/builder/ExplicitDFTModelBuilder.cpp diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp new file mode 100644 index 000000000..8683dd57e --- /dev/null +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -0,0 +1,72 @@ +#include "src/builder/ExplicitDFTModelBuilder.h" + +namespace storm { + namespace builder { + + void ExplicitDFTModelBuilder::exploreStateSuccessors(storm::storage::DFTState const &state) { + size_t smallest = 0; + + while(smallest < state.nrFailableBEs()) { + //std::cout << "exploring from: " << mDft.getStateString(state) << std::endl; + + storm::storage::DFTState newState(state); + std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); + if(nextBE.first == nullptr) { + //std::cout << "break" << std::endl; + break; + + } + //std::cout << "with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]" << std::endl; + + storm::storage::DFTStateSpaceGenerationQueues queues; + + for(std::shared_ptr parent : nextBE.first->parents()) { + if(newState.isOperational(parent->id())) { + queues.propagateFailure(parent); + } + } + + while(!queues.failurePropagationDone()) { + std::shared_ptr next = queues.nextFailurePropagation(); + next->checkFails(newState, queues); + } + + while(!queues.failsafePropagationDone()) { + std::shared_ptr next = queues.nextFailsafePropagation(); + next->checkFailsafe(newState, queues); + } + + while(!queues.dontCarePropagationDone()) { + std::shared_ptr next = queues.nextDontCarePropagation(); + next->checkDontCareAnymore(newState, queues); + } + + auto it = mStates.find(newState); + if (it == mStates.end()) { + // New state + newState.setId(newIndex++); + mStates.insert(newState); + //std::cout << "New state " << mDft.getStateString(newState) << std::endl; + + // Recursive call + if(!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { + exploreStateSuccessors(newState); + } else { + if (mDft.hasFailed(newState)) { + //std::cout << "Failed " << mDft.getStateString(newState) << std::endl; + } else { + assert(mDft.isFailsafe(newState)); + //std::cout << "Failsafe" << mDft.getStateString(newState) << std::endl; + } + } + } else { + // State already exists + //std::cout << "State " << mDft.getStateString(*it) << " already exists" << std::endl; + } + } + } + + } // namespace builder +} // namespace storm + + diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index e8c169976..7009c4896 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -3,91 +3,34 @@ #include "../storage/dft/DFT.h" +#include + namespace storm { namespace builder { class ExplicitDFTModelBuilder { - storm::storage::DFT const& mDft; - std::unordered_map mStateIndices; + storm::storage::DFT const &mDft; + std::unordered_set mStates; size_t newIndex = 0; //std::stack> mStack; - - public: - ExplicitDFTModelBuilder(storm::storage::DFT const& dft) : mDft(dft) - { - - } - - - void exploreStateSuccessors(storm::storage::DFTState const& state) { - size_t smallest = 0; - - while(smallest < state.nrFailableBEs()) { - //std::cout << "exploring from :" << std::endl; - //mDft.printElementsWithState(state); - //std::cout << "***************" << std::endl; - storm::storage::DFTState newState(state); - std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); - if(nextBE.first == nullptr) { - //std::cout << "break" << std::endl; - break; - - } - //std::cout << "with the failure of: " << nextBE.first->name() << std::endl; - - storm::storage::DFTStateSpaceGenerationQueues queues; - for(std::shared_ptr parent : nextBE.first->parents()) { - if(newState.isOperational(parent->id())) { - queues.propagateFailure(parent); - } - } - - - while(!queues.failurePropagationDone()) { - std::shared_ptr next = queues.nextFailurePropagation(); - next->checkFails(newState, queues); - } - - while(!queues.failsafePropagationDone()) { - std::shared_ptr next = queues.nextFailsafePropagation(); - next->checkFailsafe(newState, queues); - } - - while(!queues.dontCarePropagationDone()) { - std::shared_ptr next = queues.nextDontCarePropagation(); - next->checkDontCareAnymore(newState, queues); - } - - - - if(!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { - auto it = mStateIndices.find(newState); - if(it == mStateIndices.end()) { - exploreStateSuccessors(newState); - mStateIndices.insert(std::make_pair(newState, newIndex++)); - if(newIndex % 16384 == 0) std::cout << newIndex << std::endl; - } - - } - else { - //std::cout << "done." << std::endl; - } + public: + ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft) { - - - } } - - void buildCtmc() { - storm::storage::DFTState state(mDft); + + void buildCTMC() { + // Construct starting start + storm::storage::DFTState state(mDft, newIndex++); + mStates.insert(state); + // Begin model generation exploreStateSuccessors(state); - std::cout << mStateIndices.size() << std::endl; + std::cout << "Generated " << mStates.size() << " states" << std::endl; } - + + private: + void exploreStateSuccessors(storm::storage::DFTState const &state); }; } } - -#endif /* EXPLICITDFTMODELBUILDER_H */ - +#endif /* EXPLICITDFTMODELBUILDER_H */ \ No newline at end of file diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 8dee2a0b6..faed81efd 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -114,9 +114,22 @@ namespace storm { os << " using " << state.uses(elem->id()); } std::cout << std::endl; + } + } - + std::string DFT::getStateString(DFTState const& state) const{ + std::stringstream stream; + stream << "(" << state.getId() << ") "; + for (auto const& elem : mElements) { + stream << state.getElementStateInt(elem->id()); + /*if(elem->isSpareGate()) { + if(state.isActiveSpare(elem->id())) { + os << " actively"; + } + os << " using " << state.uses(elem->id()); + }*/ } + return stream.str(); } } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index fbf035f44..64a9ccdc4 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -151,7 +151,9 @@ namespace storm { void printSpareModules(std::ostream& os = std::cout) const; - void printElementsWithState(DFTState const& state, std::ostream& os = std::cout) const; + void printElementsWithState(DFTState const& state, std::ostream& os = std::cout) const; + + std::string getStateString(DFTState const& state) const; private: bool elementIndicesCorrect() const { diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 5536b05a6..01534342b 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -5,7 +5,7 @@ namespace storm { namespace storage { - DFTState::DFTState(DFT const& dft) : mStatus(dft.stateSize()), mDft(dft) { + DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mDft(dft), mId(id) { mInactiveSpares = dft.getSpareIndices(); dft.initializeUses(*this); dft.initializeActivation(*this); @@ -15,7 +15,19 @@ namespace storm { } DFTElementState DFTState::getElementState(size_t id) const { - return static_cast(mStatus.getAsInt(mDft.failureIndex(id), 2)); + return static_cast(getElementStateInt(id)); + } + + int DFTState::getElementStateInt(size_t id) const { + return mStatus.getAsInt(mDft.failureIndex(id), 2); + } + + size_t DFTState::getId() const { + return mId; + } + + void DFTState::setId(size_t id) { + mId = id; } bool DFTState::isOperational(size_t id) const { @@ -58,7 +70,7 @@ namespace storm { { assert(index < mIsCurrentlyFailableBE.size()); //std::cout << "currently failable: "; - //printCurrentlyFailable(std::cout); + //printCurrentlyFailable(); std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); setFailed(res.first->id()); @@ -98,8 +110,6 @@ namespace storm { } - - void DFTState::setUsesAtPosition(size_t usageIndex, size_t child) { mStatus.setFromInt(usageIndex, mDft.usageInfoBits(), child); mUsedRepresentants.push_back(child); @@ -121,5 +131,6 @@ namespace storm { } return false; } + } } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 719d49e37..67eec6598 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -4,6 +4,7 @@ #include "../BitVector.h" #include "DFTElementState.h" +#include namespace storm { namespace storage { @@ -18,6 +19,7 @@ namespace storm { friend struct std::hash; private: storm::storage::BitVector mStatus; + size_t mId; std::vector mInactiveSpares; std::vector mIsCurrentlyFailableBE; std::vector mUsedRepresentants; @@ -25,9 +27,15 @@ namespace storm { const DFT& mDft; public: - DFTState(DFT const& dft); + DFTState(DFT const& dft, size_t id); DFTElementState getElementState(size_t id) const; + + int getElementStateInt(size_t id) const; + + size_t getId() const; + + void setId(size_t id); bool isOperational(size_t id) const; @@ -103,7 +111,7 @@ namespace storm { std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); - void printCurrentlyFailable(std::ostream& os) { + void printCurrentlyFailable(std::ostream& os = std::cout) { auto it = mIsCurrentlyFailableBE.begin(); os << "{"; if(it != mIsCurrentlyFailableBE.end()) { @@ -116,7 +124,7 @@ namespace storm { } os << "}" << std::endl; } - + friend bool operator==(DFTState const& a, DFTState const& b) { return a.mStatus == b.mStatus; } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index e491cbe2b..b86781460 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -22,7 +22,7 @@ int main(int argc, char** argv) { std::cout << "Building CTMC..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); - builder.buildCtmc(); + builder.buildCTMC(); std::cout << "Built CTMC" << std::endl; //std::cout << "Model checking..." << std::endl; From 4c1d71fc9164a9a1ed6e1ea897b061b776d3ea02 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 15 Dec 2015 12:14:12 +0100 Subject: [PATCH 007/246] Fixed compile warnings Former-commit-id: 62ef59c239f558a0adb5db43b3f4fd59b5aa5551 --- src/storage/dft/DFTBuilder.cpp | 12 ++++++++++++ src/storage/dft/DFTElements.h | 12 ++++++------ src/storage/dft/DFTState.cpp | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index b8e2c54a2..d1d6f320f 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -5,6 +5,8 @@ #include "DFT.h" #include #include "OrderDFTElementsById.h" +#include +#include #include "../../exceptions/WrongFormatException.h" @@ -86,6 +88,16 @@ namespace storm { case DFTElementTypes::SPARE: element = std::make_shared(mNextId++, name); break; + case DFTElementTypes::BE: + case DFTElementTypes::VOT: + // Handled separately + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type handled separately."); + case DFTElementTypes::CONSTF: + case DFTElementTypes::CONSTS: + case DFTElementTypes::FDEP: + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); + default: + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not known."); } mElements[name] = element; mChildNames[element] = children; diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index d6245a606..d223387e8 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -145,7 +145,7 @@ namespace storm { return mChildren.push_back(elem); } - size_t nrChildren() const { + size_t nrChildren() const override { return mChildren.size(); } @@ -153,7 +153,7 @@ namespace storm { return mChildren; } - virtual bool isGate() const { + virtual bool isGate() const override { return true; } @@ -172,7 +172,7 @@ namespace storm { } } - virtual std::vector independentUnit() const { + virtual std::vector independentUnit() const override { std::set unit = {mId}; for(auto const& child : mChildren) { child->extendUnit(unit); @@ -187,7 +187,7 @@ namespace storm { - virtual void print(std::ostream& os = std::cout) const { + virtual void print(std::ostream& os = std::cout) const override { os << "{" << name() << "} " << typestring() << "( "; std::vector>::const_iterator it = mChildren.begin(); os << (*it)->name(); @@ -199,7 +199,7 @@ namespace storm { os << ")"; } - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(DFTElement::checkDontCareAnymore(state, queues)) { childrenDontCare(state, queues); return true; @@ -207,7 +207,7 @@ namespace storm { return false; } - virtual void extendUnit(std::set& unit) const { + virtual void extendUnit(std::set& unit) const override { DFTElement::extendUnit(unit); for(auto const& child : mChildren) { child->extendUnit(unit); diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 01534342b..e7756cbbd 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -5,7 +5,7 @@ namespace storm { namespace storage { - DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mDft(dft), mId(id) { + DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mId(id), mDft(dft) { mInactiveSpares = dft.getSpareIndices(); dft.initializeUses(*this); dft.initializeActivation(*this); From 0c37f078fb45243b1585b757f17b58bf43756f0d Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 16 Dec 2015 14:16:26 +0100 Subject: [PATCH 008/246] Build transition matrix for FT Former-commit-id: 2ffb55295ade2c9337e463e94b865f69d18d63f1 --- src/builder/ExplicitDFTModelBuilder.cpp | 155 +++++++++++++++++------- src/builder/ExplicitDFTModelBuilder.h | 30 +++-- src/storage/dft/DFTElements.h | 18 +-- src/storm-dyftee.cpp | 3 +- 4 files changed, 139 insertions(+), 67 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 8683dd57e..788c5a0fa 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -3,69 +3,132 @@ namespace storm { namespace builder { - void ExplicitDFTModelBuilder::exploreStateSuccessors(storm::storage::DFTState const &state) { - size_t smallest = 0; + template + void ExplicitDFTModelBuilder::buildCTMC() { + // Initialize + storm::storage::DFTState state(mDft, newIndex++); + mStates.insert(state); - while(smallest < state.nrFailableBEs()) { - //std::cout << "exploring from: " << mDft.getStateString(state) << std::endl; + std::queue stateQueue; + stateQueue.push(state); - storm::storage::DFTState newState(state); - std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); - if(nextBE.first == nullptr) { - //std::cout << "break" << std::endl; - break; + bool deterministicModel = true; + storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, !deterministicModel, 0); - } - //std::cout << "with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]" << std::endl; + // Begin model generation + exploreStates(stateQueue, transitionMatrixBuilder); + //std::cout << "Generated " << mStates.size() << " states" << std::endl; + + // Build CTMC + transitionMatrix = transitionMatrixBuilder.build(); + //std::cout << "TransitionMatrix: " << std::endl; + //std::cout << transitionMatrix << std::endl; + // TODO Matthias: build CTMC + } + + template + void ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { + + std::vector> outgoingTransitions; + + while (!stateQueue.empty()) { + // Initialization + outgoingTransitions.clear(); + ValueType sum = 0; + + // Consider next state + storm::storage::DFTState state = stateQueue.front(); + stateQueue.pop(); - storm::storage::DFTStateSpaceGenerationQueues queues; + size_t smallest = 0; + + // Let BE fail + while (smallest < state.nrFailableBEs()) { + //std::cout << "exploring from: " << mDft.getStateString(state) << std::endl; + + storm::storage::DFTState newState(state); + std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); + if (nextBE.first == nullptr) { + std::cout << "break" << std::endl; + break; - for(std::shared_ptr parent : nextBE.first->parents()) { - if(newState.isOperational(parent->id())) { - queues.propagateFailure(parent); } - } + //std::cout << "with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]" << std::endl; - while(!queues.failurePropagationDone()) { - std::shared_ptr next = queues.nextFailurePropagation(); - next->checkFails(newState, queues); - } + storm::storage::DFTStateSpaceGenerationQueues queues; - while(!queues.failsafePropagationDone()) { - std::shared_ptr next = queues.nextFailsafePropagation(); - next->checkFailsafe(newState, queues); - } + for (std::shared_ptr parent : nextBE.first->parents()) { + if (newState.isOperational(parent->id())) { + queues.propagateFailure(parent); + } + } - while(!queues.dontCarePropagationDone()) { - std::shared_ptr next = queues.nextDontCarePropagation(); - next->checkDontCareAnymore(newState, queues); - } + while (!queues.failurePropagationDone()) { + std::shared_ptr next = queues.nextFailurePropagation(); + next->checkFails(newState, queues); + } - auto it = mStates.find(newState); - if (it == mStates.end()) { - // New state - newState.setId(newIndex++); - mStates.insert(newState); - //std::cout << "New state " << mDft.getStateString(newState) << std::endl; + while (!queues.failsafePropagationDone()) { + std::shared_ptr next = queues.nextFailsafePropagation(); + next->checkFailsafe(newState, queues); + } - // Recursive call - if(!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { - exploreStateSuccessors(newState); - } else { - if (mDft.hasFailed(newState)) { - //std::cout << "Failed " << mDft.getStateString(newState) << std::endl; + while (!queues.dontCarePropagationDone()) { + std::shared_ptr next = queues.nextDontCarePropagation(); + next->checkDontCareAnymore(newState, queues); + } + + auto it = mStates.find(newState); + if (it == mStates.end()) { + // New state + newState.setId(newIndex++); + auto itInsert = mStates.insert(newState); + assert(itInsert.second); + it = itInsert.first; + //std::cout << "New state " << mDft.getStateString(newState) << std::endl; + + // Recursive call + if (!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { + stateQueue.push(newState); } else { - assert(mDft.isFailsafe(newState)); - //std::cout << "Failsafe" << mDft.getStateString(newState) << std::endl; + if (mDft.hasFailed(newState)) { + //std::cout << "Failed " << mDft.getStateString(newState) << std::endl; + } else { + assert(mDft.isFailsafe(newState)); + //std::cout << "Failsafe" << mDft.getStateString(newState) << std::endl; + } } + } else { + // State already exists + //std::cout << "State " << mDft.getStateString(*it) << " already exists" << std::endl; } - } else { - // State already exists - //std::cout << "State " << mDft.getStateString(*it) << " already exists" << std::endl; + + // Set transition + ValueType prob = nextBE.first->activeFailureRate(); + outgoingTransitions.push_back(std::make_pair(it->getId(), prob)); + sum += prob; + } // end while failing BE + + // Add all transitions + for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) + { + ValueType rate = it->second / sum; + transitionMatrixBuilder.addNextValue(state.getId(), it->first, rate); + //std::cout << "Added transition from " << state.getId() << " to " << it->first << " with " << rate << std::endl; } - } + + } // end while queue } + // Explicitly instantiate the class. + template + class ExplicitDFTModelBuilder, uint32_t>; + +#ifdef STORM_HAVE_CARL + template class ExplicitDFTModelBuilder, uint32_t>; + template class ExplicitDFTModelBuilder, uint32_t>; +#endif + } // namespace builder } // namespace storm diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 7009c4896..8938e690f 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -3,32 +3,42 @@ #include "../storage/dft/DFT.h" +#include +#include +#include +#include +#include +#include #include namespace storm { namespace builder { + + template, typename IndexType = uint32_t> class ExplicitDFTModelBuilder { storm::storage::DFT const &mDft; std::unordered_set mStates; size_t newIndex = 0; - //std::stack> mStack; + + // The transition matrix. + storm::storage::SparseMatrix transitionMatrix; + + // The state labeling. + storm::models::sparse::StateLabeling stateLabeling; + + // A vector that stores a labeling for each choice. + boost::optional>> choiceLabeling; public: ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft) { } - void buildCTMC() { - // Construct starting start - storm::storage::DFTState state(mDft, newIndex++); - mStates.insert(state); - // Begin model generation - exploreStateSuccessors(state); - std::cout << "Generated " << mStates.size() << " states" << std::endl; - } + void buildCTMC(); private: - void exploreStateSuccessors(storm::storage::DFTState const &state); + void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); + }; } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index d223387e8..9479293d2 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -262,14 +262,14 @@ namespace storm { - template + template class DFTBE : public DFTElement { - - FailureRateType mActiveFailureRate; - FailureRateType mPassiveFailureRate; + + ValueType mActiveFailureRate; + ValueType mPassiveFailureRate; public: - DFTBE(size_t id, std::string const& name, FailureRateType failureRate, FailureRateType dormancyFactor) : + DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) { @@ -278,12 +278,12 @@ namespace storm { virtual size_t nrChildren() const { return 0; } - - FailureRateType const& activeFailureRate() const { + + ValueType const& activeFailureRate() const { return mActiveFailureRate; } - - FailureRateType const& passiveFailureRate() const { + + ValueType const& passiveFailureRate() const { return mPassiveFailureRate; } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index b86781460..75f329ccb 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -21,7 +21,7 @@ int main(int argc, char** argv) { dft.printSpareModules(); std::cout << "Building CTMC..." << std::endl; - storm::builder::ExplicitDFTModelBuilder builder(dft); + storm::builder::ExplicitDFTModelBuilder builder(dft); builder.buildCTMC(); std::cout << "Built CTMC" << std::endl; @@ -29,4 +29,3 @@ int main(int argc, char** argv) { //TODO check CTMC //std::cout << "Checked model" << std::endl; } - From 4ae86c76f91a1b526076944a6c14f15cf3127629 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 16 Dec 2015 16:53:33 +0100 Subject: [PATCH 009/246] Output uses logger now Former-commit-id: bb5061ccd41a7c5a7e83f67fa5323e4f138df50c --- src/builder/ExplicitDFTModelBuilder.cpp | 19 ++++--- src/parser/DFTGalileoParser.cpp | 15 +++--- src/storage/dft/DFT.cpp | 53 ++++++++++--------- src/storage/dft/DFT.h | 27 +++------- src/storage/dft/DFTBuilder.cpp | 6 --- src/storage/dft/DFTElements.h | 40 +++++++------- src/storage/dft/DFTState.cpp | 3 +- src/storage/dft/DFTState.h | 14 ++--- .../dft/DFTStateSpaceGenerationQueues.h | 2 +- src/storm-dyftee.cpp | 12 +++-- 10 files changed, 90 insertions(+), 101 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 788c5a0fa..bf23c5d4f 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -17,12 +17,11 @@ namespace storm { // Begin model generation exploreStates(stateQueue, transitionMatrixBuilder); - //std::cout << "Generated " << mStates.size() << " states" << std::endl; + STORM_LOG_DEBUG("Generated " << mStates.size() << " states"); // Build CTMC transitionMatrix = transitionMatrixBuilder.build(); - //std::cout << "TransitionMatrix: " << std::endl; - //std::cout << transitionMatrix << std::endl; + STORM_LOG_DEBUG("TransitionMatrix: " << std::endl << transitionMatrix); // TODO Matthias: build CTMC } @@ -44,7 +43,7 @@ namespace storm { // Let BE fail while (smallest < state.nrFailableBEs()) { - //std::cout << "exploring from: " << mDft.getStateString(state) << std::endl; + STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); storm::storage::DFTState newState(state); std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); @@ -53,7 +52,7 @@ namespace storm { break; } - //std::cout << "with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]" << std::endl; + STORM_LOG_TRACE("with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]"); storm::storage::DFTStateSpaceGenerationQueues queues; @@ -85,22 +84,22 @@ namespace storm { auto itInsert = mStates.insert(newState); assert(itInsert.second); it = itInsert.first; - //std::cout << "New state " << mDft.getStateString(newState) << std::endl; + STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); // Recursive call if (!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { stateQueue.push(newState); } else { if (mDft.hasFailed(newState)) { - //std::cout << "Failed " << mDft.getStateString(newState) << std::endl; + STORM_LOG_TRACE("Failed " << mDft.getStateString(newState)); } else { assert(mDft.isFailsafe(newState)); - //std::cout << "Failsafe" << mDft.getStateString(newState) << std::endl; + STORM_LOG_TRACE("Failsafe" << mDft.getStateString(newState)); } } } else { // State already exists - //std::cout << "State " << mDft.getStateString(*it) << " already exists" << std::endl; + STORM_LOG_TRACE("State " << mDft.getStateString(*it) << " already exists"); } // Set transition @@ -114,7 +113,7 @@ namespace storm { { ValueType rate = it->second / sum; transitionMatrixBuilder.addNextValue(state.getId(), it->first, rate); - //std::cout << "Added transition from " << state.getId() << " to " << it->first << " with " << rate << std::endl; + STORM_LOG_TRACE("Added transition from " << state.getId() << " to " << it->first << " with " << rate); } } // end while queue diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index a93e84e92..a710e81d3 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -12,7 +12,10 @@ namespace storm { namespace parser { storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { if(readFile(filename)) { - return mBuilder.build(); + storm::storage::DFT dft = mBuilder.build(); + STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); + STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); + return dft; } else { throw storm::exceptions::FileIoException(); } @@ -24,9 +27,8 @@ namespace storm { if(firstQuots == std::string::npos) { return name; - } else if (secondQuots ==std::string::npos) { - std::cerr << "No ending quotation mark found in " << name <print(os); - os << std::endl; + stream << "[" << elem->id() << "]" << elem->toString() << std::endl; } + return stream.str(); } - - - void DFT::printInfo(std::ostream& os) const { - os << "Top level index: " << mTopLevelIndex << std::endl << "Nr BEs" << mNrOfBEs << std::endl; + std::string DFT::getInfoString() const { + std::stringstream stream; + stream << "Top level index: " << mTopLevelIndex << ", Nr BEs" << mNrOfBEs; + return stream.str(); } - void DFT::printSpareModules(std::ostream& os) const { - std::cout << "[" << mElements[mTopLevelIndex]->id() << "] {"; + std::string DFT::getSpareModulesString() const { + std::stringstream stream; + stream << "[" << mElements[mTopLevelIndex]->id() << "] {"; std::vector::const_iterator it = mTopModule.begin(); assert(it != mTopModule.end()); - os << mElements[(*it)]->name(); + stream << mElements[(*it)]->name(); ++it; while(it != mTopModule.end()) { - os << ", " << mElements[(*it)]->name(); + stream << ", " << mElements[(*it)]->name(); ++it; } - os << "}" << std::endl; + stream << "}" << std::endl; for(auto const& spareModule : mSpareModules) { - std::cout << "[" << mElements[spareModule.first]->name() << "] = {"; - os.flush(); + stream << "[" << mElements[spareModule.first]->name() << "] = {"; std::vector::const_iterator it = spareModule.second.begin(); assert(it != spareModule.second.end()); - os << mElements[(*it)]->name(); + stream << mElements[(*it)]->name(); ++it; while(it != spareModule.second.end()) { - os << ", " << mElements[(*it)]->name(); - os.flush(); + stream << ", " << mElements[(*it)]->name(); ++it; } - os << "}" << std::endl; + stream << "}" << std::endl; } + return stream.str(); } - void DFT::printElementsWithState(DFTState const& state, std::ostream& os) const{ + std::string DFT::getElementsWithStateString(DFTState const& state) const{ + std::stringstream stream; for (auto const& elem : mElements) { - os << "[" << elem->id() << "]"; - elem->print(os); - os << "\t** " << state.getElementState(elem->id()); + stream << "[" << elem->id() << "]"; + stream << elem->toString(); + stream << "\t** " << state.getElementState(elem->id()); if(elem->isSpareGate()) { if(state.isActiveSpare(elem->id())) { - os << " actively"; + stream << " actively"; } - os << " using " << state.uses(elem->id()); + stream << " using " << state.uses(elem->id()); } - std::cout << std::endl; + stream << std::endl; } + return stream.str(); } std::string DFT::getStateString(DFTState const& state) const{ diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 64a9ccdc4..df97df476 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -11,6 +11,7 @@ #include #include "../../utility/math.h" +#include "src/utility/macros.h" #include namespace storm { @@ -143,15 +144,14 @@ namespace storm { bool isFailsafe(DFTState const& state) const { return state.isFailsafe(mTopLevelIndex); } - - void printElements(std::ostream& os = std::cout) const; - - void printInfo(std::ostream& os = std::cout) const; - - void printSpareModules(std::ostream& os = std::cout) const; - - void printElementsWithState(DFTState const& state, std::ostream& os = std::cout) const; + std::string getElementsString() const; + + std::string getInfoString() const; + + std::string getSpareModulesString() const; + + std::string getElementsWithStateString(DFTState const& state) const; std::string getStateString(DFTState const& state) const; @@ -163,18 +163,7 @@ namespace storm { return true; } - - - }; - - - - - - - - } } diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index d1d6f320f..10d96b6d0 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -34,13 +34,7 @@ namespace storm { for(std::shared_ptr e : elems) { e->setId(id++); } - for(auto& e : elems) { - std::cout << "[" << e->id() << "] "; - e->print(); - std::cout << std::endl; - } return DFT(elems, mElements[topLevelIdentifier]); - } unsigned DFTBuilder::computeRank(std::shared_ptr const& elem) { diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 9479293d2..e7a97e66c 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -96,8 +96,8 @@ namespace storm { virtual void extendSpareModule(std::set& elementsInModule) const; virtual size_t nrChildren() const = 0; - virtual void print(std::ostream& = std::cout) const = 0; - + virtual std::string toString() const = 0; + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; virtual std::vector independentUnit() const = 0; @@ -187,16 +187,18 @@ namespace storm { - virtual void print(std::ostream& os = std::cout) const override { - os << "{" << name() << "} " << typestring() << "( "; + virtual std::string toString() const override { + std::stringstream stream; + stream << "{" << name() << "} " << typestring() << "( "; std::vector>::const_iterator it = mChildren.begin(); - os << (*it)->name(); + stream << (*it)->name(); ++it; while(it != mChildren.end()) { - os << ", " << (*it)->name(); + stream << ", " << (*it)->name(); ++it; } - os << ")"; + stream << ")"; + return stream.str(); } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { @@ -287,8 +289,10 @@ namespace storm { return mPassiveFailureRate; } - void print(std::ostream& os = std::cout) const { - os << *this; + std::string toString() const { + std::stringstream stream; + stream << *this; + return stream.str(); } bool isBasicElement() const { @@ -372,8 +376,7 @@ namespace storm { }; inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { - gate.print(os); - return os; + return os << gate.toString(); } @@ -411,8 +414,7 @@ namespace storm { }; inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { - gate.print(os); - return os; + return os << gate.toString(); } class DFTSeqAnd : public DFTGate { @@ -463,8 +465,7 @@ namespace storm { }; inline std::ostream& operator<<(std::ostream& os, DFTSeqAnd const& gate) { - gate.print(os); - return os; + return os << gate.toString(); } class DFTPand : public DFTGate { @@ -510,8 +511,7 @@ namespace storm { }; inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { - gate.print(os); - return os; + return os << gate.toString(); } class DFTPor : public DFTGate { @@ -534,8 +534,7 @@ namespace storm { }; inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { - gate.print(os); - return os; + return os << gate.toString(); } class DFTVot : public DFTGate { @@ -594,8 +593,7 @@ namespace storm { }; inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { - gate.print(os); - return os; + return os << gate.toString(); } class DFTSpare : public DFTGate { diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index e7756cbbd..599de5525 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -69,8 +69,7 @@ namespace storm { std::pair>, bool> DFTState::letNextBEFail(size_t index) { assert(index < mIsCurrentlyFailableBE.size()); - //std::cout << "currently failable: "; - //printCurrentlyFailable(); + STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); setFailed(res.first->id()); diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 67eec6598..2085ba010 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -4,7 +4,7 @@ #include "../BitVector.h" #include "DFTElementState.h" -#include +#include namespace storm { namespace storage { @@ -111,18 +111,20 @@ namespace storm { std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); - void printCurrentlyFailable(std::ostream& os = std::cout) { + std::string getCurrentlyFailableString() { + std::stringstream stream; auto it = mIsCurrentlyFailableBE.begin(); - os << "{"; + stream << "{"; if(it != mIsCurrentlyFailableBE.end()) { - os << *it; + stream << *it; } ++it; while(it != mIsCurrentlyFailableBE.end()) { - os << ", " << *it; + stream << ", " << *it; ++it; } - os << "}" << std::endl; + stream << "}"; + return stream.str(); } friend bool operator==(DFTState const& a, DFTState const& b) { diff --git a/src/storage/dft/DFTStateSpaceGenerationQueues.h b/src/storage/dft/DFTStateSpaceGenerationQueues.h index f748e8232..ec0879d52 100644 --- a/src/storage/dft/DFTStateSpaceGenerationQueues.h +++ b/src/storage/dft/DFTStateSpaceGenerationQueues.h @@ -31,7 +31,7 @@ namespace storm { } std::shared_ptr nextFailurePropagation() { - std::shared_ptr next= failurePropagation.top(); + std::shared_ptr next = failurePropagation.top(); failurePropagation.pop(); return next; } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 75f329ccb..bd34cdeea 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -10,22 +10,24 @@ int main(int argc, char** argv) { if(argc != 2) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; } + storm::utility::setUp(); + log4cplus::LogLevel level = log4cplus::TRACE_LOG_LEVEL; + logger.setLogLevel(level); + logger.getAppender("mainConsoleAppender")->setThreshold(level); std::cout << "Parsing DFT file..." << std::endl; storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(argv[1]); std::cout << "Built data structure" << std::endl; - dft.printElements(); - dft.printSpareModules(); std::cout << "Building CTMC..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); builder.buildCTMC(); std::cout << "Built CTMC" << std::endl; - //std::cout << "Model checking..." << std::endl; - //TODO check CTMC - //std::cout << "Checked model" << std::endl; + std::cout << "Model checking..." << std::endl; + //TODO Matthias: check CTMC + std::cout << "Checked model" << std::endl; } From 91fe16c699ae3a58f752f99a8bf05ef3b5b5f637 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 16 Dec 2015 17:59:55 +0100 Subject: [PATCH 010/246] 1st try on CTMC model checking Former-commit-id: 5520801c2d2f0fc7c1ccfae7e33ef3382350eb7b --- src/builder/ExplicitDFTModelBuilder.cpp | 34 ++++++++++++++++++++++--- src/builder/ExplicitDFTModelBuilder.h | 30 ++++++++++++++-------- src/storm-dyftee.cpp | 17 ++++++++++--- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index bf23c5d4f..6e938f289 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,10 +1,16 @@ #include "src/builder/ExplicitDFTModelBuilder.h" +#include namespace storm { namespace builder { + template + ExplicitDFTModelBuilder::ModelComponents::ModelComponents() : transitionMatrix(), stateLabeling(), rewardModels(), choiceLabeling() { + // Intentionally left empty. + } + template - void ExplicitDFTModelBuilder::buildCTMC() { + std::shared_ptr> ExplicitDFTModelBuilder::buildCTMC() { // Initialize storm::storage::DFTState state(mDft, newIndex++); mStates.insert(state); @@ -20,9 +26,29 @@ namespace storm { STORM_LOG_DEBUG("Generated " << mStates.size() << " states"); // Build CTMC - transitionMatrix = transitionMatrixBuilder.build(); - STORM_LOG_DEBUG("TransitionMatrix: " << std::endl << transitionMatrix); - // TODO Matthias: build CTMC + ModelComponents modelComponents; + // Build transition matrix + modelComponents.transitionMatrix = transitionMatrixBuilder.build(); + STORM_LOG_DEBUG("TransitionMatrix: " << std::endl << modelComponents.transitionMatrix); + + // Build state labeling + modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size()); + // Also label the initial state with the special label "init". + modelComponents.stateLabeling.addLabel("init"); + modelComponents.stateLabeling.addLabelToState("init", 0); + // TODO Matthias: not fixed + modelComponents.stateLabeling.addLabel("failed"); + modelComponents.stateLabeling.addLabelToState("failed", 7); + + // TODO Matthias: initialize + modelComponents.rewardModels; + modelComponents.choiceLabeling; + + + std::shared_ptr> model; + model = std::shared_ptr>(new storm::models::sparse::Ctmc(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.rewardModels), std::move(modelComponents.choiceLabeling))); + model->printModelInformationToStream(std::cout); + return model; } template diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 8938e690f..f5920bb52 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -16,25 +17,34 @@ namespace storm { template, typename IndexType = uint32_t> class ExplicitDFTModelBuilder { - storm::storage::DFT const &mDft; - std::unordered_set mStates; - size_t newIndex = 0; - // The transition matrix. - storm::storage::SparseMatrix transitionMatrix; + // A structure holding the individual components of a model. + struct ModelComponents { + ModelComponents(); + + // The transition matrix. + storm::storage::SparseMatrix transitionMatrix; + + // The state labeling. + storm::models::sparse::StateLabeling stateLabeling; - // The state labeling. - storm::models::sparse::StateLabeling stateLabeling; + // The reward models associated with the model. + std::unordered_map> rewardModels; - // A vector that stores a labeling for each choice. - boost::optional>> choiceLabeling; + // A vector that stores a labeling for each choice. + boost::optional>> choiceLabeling; + }; + + storm::storage::DFT const &mDft; + std::unordered_set mStates; + size_t newIndex = 0; public: ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft) { } - void buildCTMC(); + std::shared_ptr> buildCTMC(); private: void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index bd34cdeea..a5a4feb98 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -1,7 +1,9 @@ +#include "logic/Formula.h" #include "parser/DFTGalileoParser.h" #include "utility/initialize.h" #include "builder/ExplicitDFTModelBuilder.h" - +#include "modelchecker/results/CheckResult.h" +#include "utility/storm.h" /* * Entry point for the DyFTeE backend. @@ -24,10 +26,19 @@ int main(int argc, char** argv) { std::cout << "Building CTMC..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); - builder.buildCTMC(); + std::shared_ptr> model = builder.buildCTMC(); std::cout << "Built CTMC" << std::endl; std::cout << "Model checking..." << std::endl; - //TODO Matthias: check CTMC + //TODO Matthias: Construct formula, do not fix + std::vector> formulas = storm::parseFormulasForExplicit("Pmax=?[true U \"failed\"]"); + assert(formulas.size() == 1); + // Verify the model, if a formula was given. + std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); + assert(result); + std::cout << "Result (initial states): "; + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + std::cout << *result << std::endl; + std::cout << "Checked model" << std::endl; } From d5474722c0ed470dad3b5121c5339eb553d0dcad Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Dec 2015 11:35:28 +0100 Subject: [PATCH 011/246] Label generation from FT Former-commit-id: 111a02a1437345bffd42806fdf6be4d3e252b949 --- src/builder/ExplicitDFTModelBuilder.cpp | 27 +++++++++++++++++++++---- src/storage/dft/DFT.h | 13 +++++++++++- src/storage/dft/DFTState.h | 11 ++++------ src/storm-dyftee.cpp | 17 ++++++++++++---- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 6e938f289..bb4204918 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -33,18 +33,37 @@ namespace storm { // Build state labeling modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size()); - // Also label the initial state with the special label "init". + // Initial state is always first state without any failure modelComponents.stateLabeling.addLabel("init"); modelComponents.stateLabeling.addLabelToState("init", 0); - // TODO Matthias: not fixed + // Label all states corresponding to their status (failed, failsafe, failed BE) modelComponents.stateLabeling.addLabel("failed"); - modelComponents.stateLabeling.addLabelToState("failed", 7); + modelComponents.stateLabeling.addLabel("failsafe"); + // Collect labels for all BE + std::vector>> basicElements = mDft.getBasicElements(); + for (std::shared_ptr> elem : basicElements) { + modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); + } + + for (storm::storage::DFTState state : mStates) { + if (mDft.hasFailed(state)) { + modelComponents.stateLabeling.addLabelToState("failed", state.getId()); + } + if (mDft.isFailsafe(state)) { + modelComponents.stateLabeling.addLabelToState("failsafe", state.getId()); + }; + // Set fail status for each BE + for (std::shared_ptr> elem : basicElements) { + if (state.hasFailed(elem->id())) { + modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", state.getId()); + } + } + } // TODO Matthias: initialize modelComponents.rewardModels; modelComponents.choiceLabeling; - std::shared_ptr> model; model = std::shared_ptr>(new storm::models::sparse::Ctmc(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.rewardModels), std::move(modelComponents.choiceLabeling))); model->printModelInformationToStream(std::cout); diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index df97df476..69a407461 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -136,7 +136,18 @@ namespace storm { assert(mElements[index]->isBasicElement()); return std::static_pointer_cast>(mElements[index]); } - + + std::vector>> getBasicElements() const { + std::vector>> elements; + for (std::shared_ptr elem : mElements) { + if (elem->isBasicElement()) { + elements.push_back(std::static_pointer_cast>(elem)); + } + } + return elements; + } + + bool hasFailed(DFTState const& state) const { return state.hasFailed(mTopLevelIndex); } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 2085ba010..788162ce3 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -9,12 +9,11 @@ namespace storm { namespace storage { - class DFT; - template + class DFT; + template class DFTBE; - - - + + class DFTState { friend struct std::hash; private: @@ -97,8 +96,6 @@ namespace storm { */ void setUsesAtPosition(size_t usageIndex, size_t child); - - bool claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds); bool hasOutgoingEdges() const { diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index a5a4feb98..d24d2ad08 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -9,7 +9,7 @@ * Entry point for the DyFTeE backend. */ int main(int argc, char** argv) { - if(argc != 2) { + if(argc < 2) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; } @@ -30,10 +30,19 @@ int main(int argc, char** argv) { std::cout << "Built CTMC" << std::endl; std::cout << "Model checking..." << std::endl; - //TODO Matthias: Construct formula, do not fix - std::vector> formulas = storm::parseFormulasForExplicit("Pmax=?[true U \"failed\"]"); + // Construct PCTL forumla + std::string inputFormula; + if (argc < 3) { + // Set explicit reachability formula + inputFormula = "Pmax=?[true U \"failed\"]"; + } else { + // Read formula from input + inputFormula = argv[2]; + } + std::vector> formulas = storm::parseFormulasForExplicit(inputFormula); assert(formulas.size() == 1); - // Verify the model, if a formula was given. + + // Verify the model std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); assert(result); std::cout << "Result (initial states): "; From 4343b5b98001bfb8c5d88903db4d0c8aed33e8d2 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Dec 2015 11:55:29 +0100 Subject: [PATCH 012/246] Refactored some classes into templates Former-commit-id: b495cf93d44619444463b18c189f988a80bf3a55 --- src/builder/ExplicitDFTModelBuilder.cpp | 3 +-- src/parser/DFTGalileoParser.cpp | 21 ++++++++++++---- src/parser/DFTGalileoParser.h | 10 +++++--- src/storage/dft/DFT.h | 4 ++- src/storage/dft/DFTBuilder.cpp | 33 ++++++++++++++++--------- src/storage/dft/DFTBuilder.h | 7 +++--- src/storage/dft/DFTState.cpp | 4 +-- src/storage/dft/DFTState.h | 3 ++- src/storm-dyftee.cpp | 2 +- 9 files changed, 57 insertions(+), 30 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index bb4204918..6dff245c5 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -165,8 +165,7 @@ namespace storm { } // Explicitly instantiate the class. - template - class ExplicitDFTModelBuilder, uint32_t>; + template class ExplicitDFTModelBuilder, uint32_t>; #ifdef STORM_HAVE_CARL template class ExplicitDFTModelBuilder, uint32_t>; diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index a710e81d3..0bce51685 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -10,7 +10,9 @@ namespace storm { namespace parser { - storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { + + template + storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { if(readFile(filename)) { storm::storage::DFT dft = mBuilder.build(); STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); @@ -20,8 +22,9 @@ namespace storm { throw storm::exceptions::FileIoException(); } } - - std::string stripQuotsFromName(std::string const& name) { + + template + std::string DFTGalileoParser::stripQuotsFromName(std::string const& name) { size_t firstQuots = name.find("\""); size_t secondQuots = name.find("\"", firstQuots+1); @@ -33,8 +36,9 @@ namespace storm { return name.substr(firstQuots+1,secondQuots-1); } } - - bool DFTGalileoParser::readFile(const std::string& filename) { + + template + bool DFTGalileoParser::readFile(const std::string& filename) { // constants std::string topleveltoken = "toplevel"; std::string toplevelId; @@ -108,6 +112,13 @@ namespace storm { file.close(); return generalSuccess; } + + // Explicitly instantiate the class. + template class DFTGalileoParser; + +#ifdef STORM_HAVE_CARL + template class DFTGalileoParser; +#endif } } \ No newline at end of file diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h index 9d0cc0096..d0f95383e 100644 --- a/src/parser/DFTGalileoParser.h +++ b/src/parser/DFTGalileoParser.h @@ -8,16 +8,18 @@ namespace storm { namespace parser { + + template class DFTGalileoParser { - storm::storage::DFTBuilder mBuilder; + storm::storage::DFTBuilder mBuilder; public: storm::storage::DFT parseDFT(std::string const& filename); private: bool readFile(std::string const& filename); - - - }; + + std::string stripQuotsFromName(std::string const& name); + }; } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 69a407461..3878198bd 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -131,12 +131,14 @@ namespace storm { assert(index < nrElements()); return mElements[index]; } - + + // TODO Matthias: template std::shared_ptr> getBasicElement(size_t index) const { assert(mElements[index]->isBasicElement()); return std::static_pointer_cast>(mElements[index]); } + // TODO Matthias: template std::vector>> getBasicElements() const { std::vector>> elements; for (std::shared_ptr elem : mElements) { diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 10d96b6d0..bb51852ee 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -12,8 +12,9 @@ namespace storm { namespace storage { - - DFT DFTBuilder::build() { + + template + DFT DFTBuilder::build() { for(auto& elem : mChildNames) { for(auto const& child : elem.second) { std::shared_ptr gate = std::static_pointer_cast(elem.first); @@ -36,8 +37,9 @@ namespace storm { } return DFT(elems, mElements[topLevelIdentifier]); } - - unsigned DFTBuilder::computeRank(std::shared_ptr const& elem) { + + template + unsigned DFTBuilder::computeRank(std::shared_ptr const& elem) { if(elem->rank() == -1) { if(elem->nrChildren() == 0) { elem->setRank(0); @@ -58,8 +60,9 @@ namespace storm { return elem->rank(); } - - bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp) { + + template + bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp) { assert(children.size() > 0); if(mElements.count(name) != 0) { // Element with that name already exists. @@ -97,9 +100,9 @@ namespace storm { mChildNames[element] = children; return true; } - - - void DFTBuilder::topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L) { + + template + void DFTBuilder::topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L) { if(visited[n] == topoSortColour::GREY) { throw storm::exceptions::WrongFormatException("DFT is cyclic"); } else if(visited[n] == topoSortColour::WHITE) { @@ -114,7 +117,8 @@ namespace storm { } } - std::vector> DFTBuilder::topoSort() { + template + std::vector> DFTBuilder::topoSort() { std::map, topoSortColour> visited; for(auto const& e : mElements) { visited.insert(std::make_pair(e.second, topoSortColour::WHITE)); @@ -126,7 +130,14 @@ namespace storm { } //std::reverse(L.begin(), L.end()); return L; - } + } + + // Explicitly instantiate the class. + template class DFTBuilder; + +#ifdef STORM_HAVE_CARL + template class DFTBuilder; +#endif } } diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 68e64b1dc..a78d62224 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -10,7 +10,8 @@ namespace storm { namespace storage { class DFT; - + + template class DFTBuilder { std::size_t mNextId = 0; @@ -69,7 +70,7 @@ namespace storm { return true; } - bool addBasicElement(std::string const& name, double failureRate, double dormancyFactor) { + bool addBasicElement(std::string const& name, ValueType failureRate, ValueType dormancyFactor) { if(failureRate <= 0.0) { std::cerr << "Failure rate must be positive." << std::endl; return false; @@ -80,7 +81,7 @@ namespace storm { return false; } - mElements[name] = std::make_shared>(mNextId++, name, failureRate, dormancyFactor); + mElements[name] = std::make_shared>(mNextId++, name, failureRate, dormancyFactor); return true; } diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 599de5525..201f32810 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -65,8 +65,8 @@ namespace storm { } } - - std::pair>, bool> DFTState::letNextBEFail(size_t index) + // TODO Matthias: template + std::pair>, bool> DFTState::letNextBEFail(size_t index) { assert(index < mIsCurrentlyFailableBE.size()); STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 788162ce3..d2964e152 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -105,7 +105,8 @@ namespace storm { size_t nrFailableBEs() const { return mIsCurrentlyFailableBE.size(); } - + + // TODO Matthias: template std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); std::string getCurrentlyFailableString() { diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index d24d2ad08..2c85edcf6 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -19,7 +19,7 @@ int main(int argc, char** argv) { logger.getAppender("mainConsoleAppender")->setThreshold(level); std::cout << "Parsing DFT file..." << std::endl; - storm::parser::DFTGalileoParser parser; + storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(argv[1]); std::cout << "Built data structure" << std::endl; From 7737205149708a764bfe4194078b83376b79713b Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Dec 2015 12:16:34 +0100 Subject: [PATCH 013/246] More refactoring with templates Former-commit-id: 6b614ed7f306010c1a3d63ecc5a3d527693fee30 --- src/builder/ExplicitDFTModelBuilder.h | 4 ++-- src/parser/DFTGalileoParser.cpp | 19 +++++++++++++---- src/parser/DFTGalileoParser.h | 2 +- src/storage/dft/DFT.cpp | 30 ++++++++++++++++++++------- src/storage/dft/DFT.h | 15 +++++++------- src/storage/dft/DFTBuilder.cpp | 4 ++-- src/storage/dft/DFTBuilder.h | 3 ++- src/storage/dft/DFTState.cpp | 5 +++-- src/storage/dft/DFTState.h | 9 +++++--- src/storm-dyftee.cpp | 10 +++++---- 10 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index f5920bb52..de3a94293 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -35,12 +35,12 @@ namespace storm { boost::optional>> choiceLabeling; }; - storm::storage::DFT const &mDft; + storm::storage::DFT const &mDft; std::unordered_set mStates; size_t newIndex = 0; public: - ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft) { + ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft) { } diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 0bce51685..e3368bbe3 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "../exceptions/FileIoException.h" #include "../exceptions/NotSupportedException.h" #include "src/utility/macros.h" @@ -12,9 +13,9 @@ namespace storm { namespace parser { template - storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { + storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { if(readFile(filename)) { - storm::storage::DFT dft = mBuilder.build(); + storm::storage::DFT dft = mBuilder.build(); STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); return dft; @@ -95,8 +96,18 @@ namespace storm { } else if(tokens[1] == "wsp" || tokens[1] == "csp") { success = mBuilder.addSpareElement(name, childNames); } else if(boost::starts_with(tokens[1], "lambda=")) { - //TODO Matthias: Use ValueType instead of fixed double - success = mBuilder.addBasicElement(name, boost::lexical_cast(tokens[1].substr(7)), boost::lexical_cast(tokens[2].substr(5))); + ValueType failureRate = 0; + ValueType dormancyFactor = 0; + if (std::is_same::value) { + failureRate = boost::lexical_cast(tokens[1].substr(7)); + dormancyFactor = boost::lexical_cast(tokens[2].substr(5)); + } else { + // TODO Matthias: Parse RationalFunction + failureRate; + dormancyFactor; + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Parsing into rational function not supported."); + } + success = mBuilder.addBasicElement(name, failureRate, dormancyFactor); } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " + tokens[1] + " not recognized."); success = false; diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h index d0f95383e..4f7da1566 100644 --- a/src/parser/DFTGalileoParser.h +++ b/src/parser/DFTGalileoParser.h @@ -13,7 +13,7 @@ namespace storm { class DFTGalileoParser { storm::storage::DFTBuilder mBuilder; public: - storm::storage::DFT parseDFT(std::string const& filename); + storm::storage::DFT parseDFT(std::string const& filename); private: bool readFile(std::string const& filename); diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c7801681b..719c59e26 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -2,8 +2,9 @@ namespace storm { namespace storage { - - DFT::DFT(std::vector> const& elements, std::shared_ptr const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0) + + template + DFT::DFT(std::vector> const& elements, std::shared_ptr const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0) { assert(elementIndicesCorrect()); @@ -60,8 +61,9 @@ namespace storm { mTopLevelIndex = tle->id(); } - - std::string DFT::getElementsString() const { + + template + std::string DFT::getElementsString() const { std::stringstream stream; for (auto const& elem : mElements) { stream << "[" << elem->id() << "]" << elem->toString() << std::endl; @@ -69,13 +71,15 @@ namespace storm { return stream.str(); } - std::string DFT::getInfoString() const { + template + std::string DFT::getInfoString() const { std::stringstream stream; stream << "Top level index: " << mTopLevelIndex << ", Nr BEs" << mNrOfBEs; return stream.str(); } - std::string DFT::getSpareModulesString() const { + template + std::string DFT::getSpareModulesString() const { std::stringstream stream; stream << "[" << mElements[mTopLevelIndex]->id() << "] {"; std::vector::const_iterator it = mTopModule.begin(); @@ -103,7 +107,8 @@ namespace storm { return stream.str(); } - std::string DFT::getElementsWithStateString(DFTState const& state) const{ + template + std::string DFT::getElementsWithStateString(DFTState const& state) const{ std::stringstream stream; for (auto const& elem : mElements) { stream << "[" << elem->id() << "]"; @@ -120,7 +125,8 @@ namespace storm { return stream.str(); } - std::string DFT::getStateString(DFTState const& state) const{ + template + std::string DFT::getStateString(DFTState const& state) const{ std::stringstream stream; stream << "(" << state.getId() << ") "; for (auto const& elem : mElements) { @@ -134,5 +140,13 @@ namespace storm { } return stream.str(); } + + // Explicitly instantiate the class. + template class DFT; + +#ifdef STORM_HAVE_CARL + template class DFT; +#endif + } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 3878198bd..068ea4ef1 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -26,7 +26,8 @@ namespace storm { } } }; - + + template class DFT { private: @@ -132,18 +133,16 @@ namespace storm { return mElements[index]; } - // TODO Matthias: template - std::shared_ptr> getBasicElement(size_t index) const { + std::shared_ptr> getBasicElement(size_t index) const { assert(mElements[index]->isBasicElement()); - return std::static_pointer_cast>(mElements[index]); + return std::static_pointer_cast>(mElements[index]); } - // TODO Matthias: template - std::vector>> getBasicElements() const { - std::vector>> elements; + std::vector>> getBasicElements() const { + std::vector>> elements; for (std::shared_ptr elem : mElements) { if (elem->isBasicElement()) { - elements.push_back(std::static_pointer_cast>(elem)); + elements.push_back(std::static_pointer_cast>(elem)); } } return elements; diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index bb51852ee..ee7676449 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -14,7 +14,7 @@ namespace storm { namespace storage { template - DFT DFTBuilder::build() { + DFT DFTBuilder::build() { for(auto& elem : mChildNames) { for(auto const& child : elem.second) { std::shared_ptr gate = std::static_pointer_cast(elem.first); @@ -35,7 +35,7 @@ namespace storm { for(std::shared_ptr e : elems) { e->setId(id++); } - return DFT(elems, mElements[topLevelIdentifier]); + return DFT(elems, mElements[topLevelIdentifier]); } template diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index a78d62224..f129afc0b 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -9,6 +9,7 @@ namespace storm { namespace storage { + template class DFT; template @@ -90,7 +91,7 @@ namespace storm { return mElements.count(tle) > 0; } - DFT build(); + DFT build(); private: diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 201f32810..87838b9a2 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -4,8 +4,9 @@ namespace storm { namespace storage { - - DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mId(id), mDft(dft) { + + // TODO Matthias: template + DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mId(id), mDft(dft) { mInactiveSpares = dft.getSpareIndices(); dft.initializeUses(*this); dft.initializeActivation(*this); diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index d2964e152..1e8f8cb01 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -8,7 +8,8 @@ namespace storm { namespace storage { - + + template class DFT; template class DFTBE; @@ -23,10 +24,12 @@ namespace storm { std::vector mIsCurrentlyFailableBE; std::vector mUsedRepresentants; bool mValid = true; - const DFT& mDft; + // TODO Matthias: template + const DFT& mDft; public: - DFTState(DFT const& dft, size_t id); + // TODO Matthias: template + DFTState(DFT const& dft, size_t id); DFTElementState getElementState(size_t id) const; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 2c85edcf6..7040db9ad 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -5,6 +5,8 @@ #include "modelchecker/results/CheckResult.h" #include "utility/storm.h" +#define VALUE_TYPE double + /* * Entry point for the DyFTeE backend. */ @@ -19,14 +21,14 @@ int main(int argc, char** argv) { logger.getAppender("mainConsoleAppender")->setThreshold(level); std::cout << "Parsing DFT file..." << std::endl; - storm::parser::DFTGalileoParser parser; - storm::storage::DFT dft = parser.parseDFT(argv[1]); + storm::parser::DFTGalileoParser parser; + storm::storage::DFT dft = parser.parseDFT(argv[1]); std::cout << "Built data structure" << std::endl; std::cout << "Building CTMC..." << std::endl; - storm::builder::ExplicitDFTModelBuilder builder(dft); - std::shared_ptr> model = builder.buildCTMC(); + storm::builder::ExplicitDFTModelBuilder builder(dft); + std::shared_ptr> model = builder.buildCTMC(); std::cout << "Built CTMC" << std::endl; std::cout << "Model checking..." << std::endl; From 69168e92364f3dda6786629db782c1dc5f4a186f Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Dec 2015 13:52:34 +0100 Subject: [PATCH 014/246] Use rate instead of prob Former-commit-id: 50bf0a9ba8052385b5dec3002476ae317dc9a593 --- src/builder/ExplicitDFTModelBuilder.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 6dff245c5..fb1c5cd33 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,5 +1,6 @@ #include "src/builder/ExplicitDFTModelBuilder.h" #include +#include namespace storm { namespace builder { @@ -86,6 +87,14 @@ namespace storm { size_t smallest = 0; + // Add self loop for target states + if (mDft.hasFailed(state) || mDft.isFailsafe(state)) { + transitionMatrixBuilder.addNextValue(state.getId(), state.getId(), storm::utility::one()); + STORM_LOG_TRACE("Added self loop for " << state.getId()); + // No further exploration required + continue; + } + // Let BE fail while (smallest < state.nrFailableBEs()) { STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); @@ -131,17 +140,8 @@ namespace storm { it = itInsert.first; STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); - // Recursive call - if (!mDft.hasFailed(newState) && !mDft.isFailsafe(newState)) { - stateQueue.push(newState); - } else { - if (mDft.hasFailed(newState)) { - STORM_LOG_TRACE("Failed " << mDft.getStateString(newState)); - } else { - assert(mDft.isFailsafe(newState)); - STORM_LOG_TRACE("Failsafe" << mDft.getStateString(newState)); - } - } + // Add state to search + stateQueue.push(newState); } else { // State already exists STORM_LOG_TRACE("State " << mDft.getStateString(*it) << " already exists"); @@ -156,7 +156,8 @@ namespace storm { // Add all transitions for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) { - ValueType rate = it->second / sum; + // TODO Matthias: correct? + ValueType rate = it->second;// / sum; transitionMatrixBuilder.addNextValue(state.getId(), it->first, rate); STORM_LOG_TRACE("Added transition from " << state.getId() << " to " << it->first << " with " << rate); } From 7a0207637a68a0a50f2e29c6bc3de230c832047a Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 18 Dec 2015 10:35:15 +0100 Subject: [PATCH 015/246] Small templating Former-commit-id: 4cc3c301ee2c9260f4125742b078e8fee40321e2 --- src/storage/dft/DFTElements.cpp | 13 ++++++++++--- src/storage/dft/DFTElements.h | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 699fe47e5..a9040eab0 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -38,15 +38,22 @@ namespace storm { void DFTElement::checkForSymmetricChildren() const { } - - template<> - bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + template + bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(DFTElement::checkDontCareAnymore(state, queues)) { state.beNoLongerFailable(mId); return true; } return false; } + + // Explicitly instantiate the class. + template class DFTBE; + +#ifdef STORM_HAVE_CARL + template class DFTBE; +#endif } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index e7a97e66c..7d3c6110c 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -308,8 +308,9 @@ namespace storm { } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; }; - - inline std::ostream& operator<<(std::ostream& os, DFTBE const& be) { + + template + inline std::ostream& operator<<(std::ostream& os, DFTBE const& be) { return os << "{" << be.name() << "} BE(" << be.activeFailureRate() << ", " << be.passiveFailureRate() << ")"; } From 6e2f5602e1406bc81d0a731a87c27eec320f0561 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 18 Dec 2015 14:00:02 +0100 Subject: [PATCH 016/246] Finished templating Former-commit-id: 7225717fdbc78fcdad9dbc3b7d4ff1fc14a6b318 --- src/builder/ExplicitDFTModelBuilder.cpp | 22 +- src/builder/ExplicitDFTModelBuilder.h | 7 +- src/storage/dft/DFT.cpp | 10 +- src/storage/dft/DFT.h | 42 +- src/storage/dft/DFTBuilder.cpp | 35 +- src/storage/dft/DFTBuilder.h | 20 +- src/storage/dft/DFTElements.cpp | 33 +- src/storage/dft/DFTElements.h | 438 +++++++++--------- src/storage/dft/DFTState.cpp | 96 ++-- src/storage/dft/DFTState.h | 17 +- .../dft/DFTStateSpaceGenerationQueues.h | 49 +- src/storage/dft/OrderDFTElementsById.cpp | 25 +- src/storage/dft/OrderDFTElementsById.h | 16 +- 13 files changed, 453 insertions(+), 357 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index fb1c5cd33..e039b389f 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -13,10 +13,10 @@ namespace storm { template std::shared_ptr> ExplicitDFTModelBuilder::buildCTMC() { // Initialize - storm::storage::DFTState state(mDft, newIndex++); + storm::storage::DFTState state(mDft, newIndex++); mStates.insert(state); - std::queue stateQueue; + std::queue> stateQueue; stateQueue.push(state); bool deterministicModel = true; @@ -46,7 +46,7 @@ namespace storm { modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); } - for (storm::storage::DFTState state : mStates) { + for (storm::storage::DFTState state : mStates) { if (mDft.hasFailed(state)) { modelComponents.stateLabeling.addLabelToState("failed", state.getId()); } @@ -72,7 +72,7 @@ namespace storm { } template - void ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { + void ExplicitDFTModelBuilder::exploreStates(std::queue>& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { std::vector> outgoingTransitions; @@ -82,7 +82,7 @@ namespace storm { ValueType sum = 0; // Consider next state - storm::storage::DFTState state = stateQueue.front(); + storm::storage::DFTState state = stateQueue.front(); stateQueue.pop(); size_t smallest = 0; @@ -99,7 +99,7 @@ namespace storm { while (smallest < state.nrFailableBEs()) { STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); - storm::storage::DFTState newState(state); + storm::storage::DFTState newState(state); std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); if (nextBE.first == nullptr) { std::cout << "break" << std::endl; @@ -108,26 +108,26 @@ namespace storm { } STORM_LOG_TRACE("with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]"); - storm::storage::DFTStateSpaceGenerationQueues queues; + storm::storage::DFTStateSpaceGenerationQueues queues; - for (std::shared_ptr parent : nextBE.first->parents()) { + for (DFTGatePointer parent : nextBE.first->parents()) { if (newState.isOperational(parent->id())) { queues.propagateFailure(parent); } } while (!queues.failurePropagationDone()) { - std::shared_ptr next = queues.nextFailurePropagation(); + DFTGatePointer next = queues.nextFailurePropagation(); next->checkFails(newState, queues); } while (!queues.failsafePropagationDone()) { - std::shared_ptr next = queues.nextFailsafePropagation(); + DFTGatePointer next = queues.nextFailsafePropagation(); next->checkFailsafe(newState, queues); } while (!queues.dontCarePropagationDone()) { - std::shared_ptr next = queues.nextDontCarePropagation(); + DFTElementPointer next = queues.nextDontCarePropagation(); next->checkDontCareAnymore(newState, queues); } diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index de3a94293..8148559c3 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -18,6 +18,9 @@ namespace storm { template, typename IndexType = uint32_t> class ExplicitDFTModelBuilder { + using DFTElementPointer = std::shared_ptr>; + using DFTGatePointer = std::shared_ptr>; + // A structure holding the individual components of a model. struct ModelComponents { ModelComponents(); @@ -36,7 +39,7 @@ namespace storm { }; storm::storage::DFT const &mDft; - std::unordered_set mStates; + std::unordered_set> mStates; size_t newIndex = 0; public: @@ -47,7 +50,7 @@ namespace storm { std::shared_ptr> buildCTMC(); private: - void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); + void exploreStates(std::queue>& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); }; } diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 719c59e26..0b8c99685 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -4,7 +4,7 @@ namespace storm { namespace storage { template - DFT::DFT(std::vector> const& elements, std::shared_ptr const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0) + DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0) { assert(elementIndicesCorrect()); @@ -19,7 +19,7 @@ namespace storm { } else if(elem->isSpareGate()) { ++mNrOfSpares; - for(auto const& spareReprs : std::static_pointer_cast(elem)->children()) { + for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { if(mActivationIndex.count(spareReprs->id()) == 0) { mActivationIndex[spareReprs->id()] = stateIndex++; } @@ -34,7 +34,7 @@ namespace storm { mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); } - std::static_pointer_cast(elem)->setUseIndex(stateIndex); + std::static_pointer_cast>(elem)->setUseIndex(stateIndex); mUsageIndex.insert(std::make_pair(elem->id(), stateIndex)); stateIndex += mUsageInfoBits; @@ -108,7 +108,7 @@ namespace storm { } template - std::string DFT::getElementsWithStateString(DFTState const& state) const{ + std::string DFT::getElementsWithStateString(DFTState const& state) const{ std::stringstream stream; for (auto const& elem : mElements) { stream << "[" << elem->id() << "]"; @@ -126,7 +126,7 @@ namespace storm { } template - std::string DFT::getStateString(DFTState const& state) const{ + std::string DFT::getStateString(DFTState const& state) const{ std::stringstream stream; stream << "(" << state.getId() << ") "; for (auto const& elem : mElements) { diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 068ea4ef1..0f39e3ddc 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -17,8 +17,9 @@ namespace storm { namespace storage { + template struct DFTElementSort { - bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const { + bool operator()(std::shared_ptr> const& a, std::shared_ptr> const& b) const { if (a->rank() == 0 && b->rank() == 0) { return a->isConstant(); } else { @@ -27,11 +28,18 @@ namespace storm { } }; + + template class DFT { + using DFTElementPointer = std::shared_ptr>; + using DFTElementVector = std::vector; + using DFTGatePointer = std::shared_ptr>; + using DFTGateVector = std::vector; + private: - std::vector> mElements; + DFTElementVector mElements; size_t mNrOfBEs; size_t mNrOfSpares; size_t mTopLevelIndex; @@ -44,9 +52,8 @@ namespace storm { std::map mUsageIndex; public: - DFT(std::vector> const& elements, std::shared_ptr const& tle); - - + DFT(DFTElementVector const& elements, DFTElementPointer const& tle); + size_t stateSize() const { return mStateSize; } @@ -72,15 +79,15 @@ namespace storm { return mIdToFailureIndex[id]; } - void initializeUses(DFTState& state) const { + void initializeUses(DFTState& state) const { for(auto const& elem : mElements) { if(elem->isSpareGate()) { - std::static_pointer_cast(elem)->initializeUses(state); + std::static_pointer_cast>(elem)->initializeUses(state); } } } - void initializeActivation(DFTState& state) const { + void initializeActivation(DFTState& state) const { state.activate(mTopLevelIndex); for(auto const& elem : mTopModule) { if(mElements[elem]->isSpareGate()) { @@ -108,8 +115,7 @@ namespace storm { } } - - void propagateActivation(DFTState& state, size_t representativeId) const { + void propagateActivation(DFTState& state, size_t representativeId) const { state.activate(representativeId); for(size_t id : module(representativeId)) { if(mElements[id]->isSpareGate()) { @@ -120,15 +126,15 @@ namespace storm { std::vector nonColdBEs() const { std::vector result; - for(std::shared_ptr elem : mElements) { + for(DFTElementPointer elem : mElements) { if(elem->isBasicElement() && !elem->isColdBasicElement()) { result.push_back(elem->id()); } } return result; } - - std::shared_ptr const& getElement(size_t index) const { + + DFTElementPointer const& getElement(size_t index) const { assert(index < nrElements()); return mElements[index]; } @@ -140,7 +146,7 @@ namespace storm { std::vector>> getBasicElements() const { std::vector>> elements; - for (std::shared_ptr elem : mElements) { + for (DFTElementPointer elem : mElements) { if (elem->isBasicElement()) { elements.push_back(std::static_pointer_cast>(elem)); } @@ -149,11 +155,11 @@ namespace storm { } - bool hasFailed(DFTState const& state) const { + bool hasFailed(DFTState const& state) const { return state.hasFailed(mTopLevelIndex); } - bool isFailsafe(DFTState const& state) const { + bool isFailsafe(DFTState const& state) const { return state.isFailsafe(mTopLevelIndex); } @@ -163,9 +169,9 @@ namespace storm { std::string getSpareModulesString() const; - std::string getElementsWithStateString(DFTState const& state) const; + std::string getElementsWithStateString(DFTState const& state) const; - std::string getStateString(DFTState const& state) const; + std::string getStateString(DFTState const& state) const; private: bool elementIndicesCorrect() const { diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index ee7676449..870b7f8bf 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -17,7 +17,7 @@ namespace storm { DFT DFTBuilder::build() { for(auto& elem : mChildNames) { for(auto const& child : elem.second) { - std::shared_ptr gate = std::static_pointer_cast(elem.first); + DFTGatePointer gate = std::static_pointer_cast>(elem.first); gate->pushBackChild(mElements[child]); mElements[child]->addParent(gate); } @@ -30,25 +30,25 @@ namespace storm { computeRank(elem.second); } - std::vector> elems = topoSort(); + DFTElementVector elems = topoSort(); size_t id = 0; - for(std::shared_ptr e : elems) { + for(DFTElementPointer e : elems) { e->setId(id++); } return DFT(elems, mElements[topLevelIdentifier]); } template - unsigned DFTBuilder::computeRank(std::shared_ptr const& elem) { + unsigned DFTBuilder::computeRank(DFTElementPointer const& elem) { if(elem->rank() == -1) { if(elem->nrChildren() == 0) { elem->setRank(0); } else { - std::shared_ptr gate = std::static_pointer_cast(elem); + DFTGatePointer gate = std::static_pointer_cast>(elem); unsigned maxrnk = 0; unsigned newrnk = 0; - for (std::shared_ptr const &child : gate->children()) { + for (DFTElementPointer const &child : gate->children()) { newrnk = computeRank(child); if (newrnk > maxrnk) { maxrnk = newrnk; @@ -68,22 +68,22 @@ namespace storm { // Element with that name already exists. return false; } - std::shared_ptr element; + DFTElementPointer element; switch(tp) { case DFTElementTypes::AND: - element = std::make_shared(mNextId++, name); + element = std::make_shared>(mNextId++, name); break; case DFTElementTypes::OR: - element = std::make_shared(mNextId++, name); + element = std::make_shared>(mNextId++, name); break; case DFTElementTypes::PAND: - element = std::make_shared(mNextId++, name); + element = std::make_shared>(mNextId++, name); break; case DFTElementTypes::POR: - element = std::make_shared(mNextId++, name); + element = std::make_shared>(mNextId++, name); break; case DFTElementTypes::SPARE: - element = std::make_shared(mNextId++, name); + element = std::make_shared>(mNextId++, name); break; case DFTElementTypes::BE: case DFTElementTypes::VOT: @@ -102,13 +102,13 @@ namespace storm { } template - void DFTBuilder::topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L) { + void DFTBuilder::topoVisit(DFTElementPointer const& n, std::map& visited, DFTElementVector& L) { if(visited[n] == topoSortColour::GREY) { throw storm::exceptions::WrongFormatException("DFT is cyclic"); } else if(visited[n] == topoSortColour::WHITE) { if(n->isGate()) { visited[n] = topoSortColour::GREY; - for(std::shared_ptr const& c : std::static_pointer_cast(n)->children()) { + for(DFTElementPointer const& c : std::static_pointer_cast>(n)->children()) { topoVisit(c, visited, L); } } @@ -117,14 +117,15 @@ namespace storm { } } + // TODO Matthias: use typedefs template - std::vector> DFTBuilder::topoSort() { - std::map, topoSortColour> visited; + std::vector>> DFTBuilder::topoSort() { + std::map>, topoSortColour> visited; for(auto const& e : mElements) { visited.insert(std::make_pair(e.second, topoSortColour::WHITE)); } - std::vector> L; + std::vector>> L; for(auto const& e : visited) { topoVisit(e.first, visited, L); } diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index f129afc0b..88fdc6ef0 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -14,11 +14,17 @@ namespace storm { template class DFTBuilder { - + + using DFTElementPointer = std::shared_ptr>; + using DFTElementVector = std::vector; + using DFTGatePointer = std::shared_ptr>; + using DFTGateVector = std::vector; + + private: std::size_t mNextId = 0; std::string topLevelIdentifier; - std::unordered_map> mElements; - std::unordered_map, std::vector> mChildNames; + std::unordered_map mElements; + std::unordered_map> mChildNames; public: DFTBuilder() { @@ -64,7 +70,7 @@ namespace storm { std::cerr << "Voting gates with threshold higher than the number of children is not supported." << std::endl; return false; } - std::shared_ptr element = std::make_shared(mNextId++, name, threshold); + DFTElementPointer element = std::make_shared>(mNextId++, name, threshold); mElements[name] = element; mChildNames[element] = children; @@ -96,15 +102,15 @@ namespace storm { private: - unsigned computeRank(std::shared_ptr const& elem); + unsigned computeRank(DFTElementPointer const& elem); bool addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp); enum class topoSortColour {WHITE, BLACK, GREY}; - void topoVisit(std::shared_ptr const& n, std::map, topoSortColour>& visited, std::vector>& L); + void topoVisit(DFTElementPointer const& n, std::map& visited, DFTElementVector& L); - std::vector> topoSort(); + DFTElementVector topoSort(); }; } diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index a9040eab0..0c18e3be6 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -1,11 +1,15 @@ +#include +#include #include "DFTElements.h" namespace storm { namespace storage { - bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + template + bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(!state.dontCare(mId)) { - for(std::shared_ptr const& parent : mParents) { + for(DFTGatePointer const& parent : mParents) { if(state.isOperational(parent->id())) { return false; } @@ -16,8 +20,9 @@ namespace storm { } return false; } - - void DFTElement::extendSpareModule(std::set& elementsInModule) const { + + template + void DFTElement::extendSpareModule(std::set& elementsInModule) const { for(auto const& parent : mParents) { if(elementsInModule.count(parent->id()) == 0 && !parent->isSpareGate()) { elementsInModule.insert(parent->id()); @@ -25,8 +30,9 @@ namespace storm { } } } - - void DFTElement::extendUnit(std::set& unit) const { + + template + void DFTElement::extendUnit(std::set& unit) const { unit.insert(mId); for(auto const& parent : mParents) { if(unit.count(parent->id()) != 0) { @@ -34,20 +40,23 @@ namespace storm { } } } - - void DFTElement::checkForSymmetricChildren() const { - + + template + void DFTElement::checkForSymmetricChildren() const { + STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Not implemented."); + assert(false); } template - bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(DFTElement::checkDontCareAnymore(state, queues)) { - state.beNoLongerFailable(mId); + bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(DFTElement::checkDontCareAnymore(state, queues)) { + state.beNoLongerFailable(this->mId); return true; } return false; } + // Explicitly instantiate the class. template class DFTBE; diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 7d3c6110c..6296a176f 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -16,21 +16,28 @@ using std::size_t; namespace storm { namespace storage { + + template class DFTGate; - + + template class DFTElement { + + using DFTGatePointer = std::shared_ptr>; + using DFTGateVector = std::vector; + + protected: size_t mId; std::string mName; size_t mRank = -1; - std::vector> mParents; - - - + DFTGateVector mParents; public: - DFTElement(size_t id, std::string const& name) : mId(id), mName(name) + DFTElement(size_t id, std::string const& name) : + mId(id), mName(name) {} + virtual ~DFTElement() {} @@ -74,7 +81,7 @@ namespace storm { return mName; } - bool addParent(std::shared_ptr const& e) { + bool addParent(DFTGatePointer const& e) { if(std::find(mParents.begin(), mParents.end(), e) != mParents.end()) { return false; } @@ -89,20 +96,21 @@ namespace storm { return !mParents.empty(); } - std::vector> const& parents() const { + DFTGateVector const& parents() const { return mParents; } virtual void extendSpareModule(std::set& elementsInModule) const; virtual size_t nrChildren() const = 0; + virtual std::string toString() const = 0; - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; virtual std::vector independentUnit() const = 0; - virtual void extendUnit(std::set& unit) const; + virtual void extendUnit(std::set& unit) const; void checkForSymmetricChildren() const; }; @@ -130,26 +138,34 @@ namespace storm { assert(false); } } - - class DFTGate : public DFTElement { + + + + template + class DFTGate : public DFTElement { + + using DFTElementPointer = std::shared_ptr>; + using DFTElementVector = std::vector; + protected: - std::vector> mChildren; + DFTElementVector mChildren; + public: - DFTGate(size_t id, std::string const& name, std::vector> const& children) : - DFTElement(id, name), mChildren(children) + DFTGate(size_t id, std::string const& name, DFTElementVector const& children) : + DFTElement(id, name), mChildren(children) {} virtual ~DFTGate() {} - void pushBackChild(std::shared_ptr elem) { + void pushBackChild(DFTElementPointer elem) { return mChildren.push_back(elem); } size_t nrChildren() const override { return mChildren.size(); } - - std::vector> const& children() const { + + DFTElementVector const& children() const { return mChildren; } @@ -159,11 +175,13 @@ namespace storm { virtual std::string typestring() const = 0; - virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; - virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; virtual void extendSpareModule(std::set& elementsInSpareModule) const override { - DFTElement::extendSpareModule(elementsInSpareModule); + DFTElement::extendSpareModule(elementsInSpareModule); for(auto const& child : mChildren) { if(elementsInSpareModule.count(child->id()) == 0) { elementsInSpareModule.insert(child->id()); @@ -173,24 +191,22 @@ namespace storm { } virtual std::vector independentUnit() const override { - std::set unit = {mId}; + std::set unit = {this->mId}; for(auto const& child : mChildren) { child->extendUnit(unit); } - for(auto const& parent : mParents) { + for(auto const& parent : this->mParents) { if(unit.count(parent->id()) != 0) { return {}; } } - return std::vector(unit.begin(), unit.end()); - } - - + return std::vector(unit.begin(), unit.end()); + } virtual std::string toString() const override { std::stringstream stream; - stream << "{" << name() << "} " << typestring() << "( "; - std::vector>::const_iterator it = mChildren.begin(); + stream << "{" << this->name() << "} " << typestring() << "( "; + typename DFTElementVector::const_iterator it = mChildren.begin(); stream << (*it)->name(); ++it; while(it != mChildren.end()) { @@ -199,10 +215,10 @@ namespace storm { } stream << ")"; return stream.str(); - } - - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(DFTElement::checkDontCareAnymore(state, queues)) { + } + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(DFTElement::checkDontCareAnymore(state, queues)) { childrenDontCare(state, queues); return true; } @@ -210,37 +226,37 @@ namespace storm { } virtual void extendUnit(std::set& unit) const override { - DFTElement::extendUnit(unit); + DFTElement::extendUnit(unit); for(auto const& child : mChildren) { child->extendUnit(unit); } } protected: - - void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - for(std::shared_ptr parent : mParents) { + + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + for(std::shared_ptr parent : this->mParents) { if(state.isOperational(parent->id())) { queues.propagateFailure(parent); } } - state.setFailed(mId); + state.setFailed(this->mId); } - - void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - for(std::shared_ptr parent : mParents) { + + void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + for(std::shared_ptr parent : this->mParents) { if(state.isOperational(parent->id())) { queues.propagateFailsafe(parent); } } - state.setFailsafe(mId); + state.setFailsafe(this->mId); } - - void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { queues.propagateDontCare(mChildren); } - - bool hasFailsafeChild(DFTState& state) const { + + bool hasFailsafeChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.isFailsafe(child->id())) { @@ -249,9 +265,8 @@ namespace storm { } return false; } - - - bool hasFailedChild(DFTState& state) const { + + bool hasFailedChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.hasFailed(child->id())) { return true; @@ -265,17 +280,15 @@ namespace storm { template - class DFTBE : public DFTElement { - + class DFTBE : public DFTElement { ValueType mActiveFailureRate; ValueType mPassiveFailureRate; + public: DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : - DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) - { - - } + DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) + {} virtual size_t nrChildren() const { return 0; @@ -304,9 +317,10 @@ namespace storm { } virtual std::vector independentUnit() const { - return {mId}; + return {this->mId}; } - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; }; template @@ -314,16 +328,17 @@ namespace storm { return os << "{" << be.name() << "} BE(" << be.activeFailureRate() << ", " << be.passiveFailureRate() << ")"; } - - - class DFTConst : public DFTElement { + + template + class DFTConst : public DFTElement { + bool mFailed; + public: - DFTConst(size_t id, std::string const& name, bool failed) : DFTElement(id, name), mFailed(failed) - { - - } + DFTConst(size_t id, std::string const& name, bool failed) : + DFTElement(id, name), mFailed(failed) + {} bool failed() const { return mFailed; @@ -339,96 +354,96 @@ namespace storm { }; - class DFTAnd : public DFTGate { + + + template + class DFTAnd : public DFTGate { public: - DFTAnd(size_t id, std::string const& name, std::vector> const& children = {}) : - DFTGate(id, name, children) + DFTAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - - if(state.isOperational(mId)) { - for(auto const& child : mChildren) + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(this->mId)) { + for(auto const& child : this->mChildren) { if(!state.hasFailed(child->id())) { - return;// false; + return; } } - fail(state, queues); - //return true; - } - //return false; + this->fail(state, queues); + } } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ - assert(hasFailsafeChild(state)); - if(state.isOperational(mId)) { - failsafe(state, queues); - childrenDontCare(state, queues); - //return true; + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(this->hasFailsafeChild(state)); + if(state.isOperational(this->mId)) { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); } - //return false; } std::string typestring() const { return "AND"; } }; - - inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { + + template + inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { return os << gate.toString(); } - + - class DFTOr : public DFTGate { + template + class DFTOr : public DFTGate { + public: - DFTOr(size_t id, std::string const& name, std::vector> const& children = {}) : - DFTGate(id, name, children) + DFTOr(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - assert(hasFailedChild(state)); - if(state.isOperational(mId)) { - fail(state, queues); - //return true; - } - // return false; + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + assert(this->hasFailedChild(state)); + if(state.isOperational(this->mId)) { + this->fail(state, queues); + } } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ - for(auto const& child : mChildren) { + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + for(auto const& child : this->mChildren) { if(!state.isFailsafe(child->id())) { - return;// false; + return; } } - failsafe(state, queues); - //return true; + this->failsafe(state, queues); } std::string typestring() const { return "OR"; } - private: - //static const std::string typestring = "or"; }; - - inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { + + template + inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { return os << gate.toString(); } - class DFTSeqAnd : public DFTGate { + + + template + class DFTSeqAnd : public DFTGate { + public: - DFTSeqAnd(size_t id, std::string const& name, std::vector> const& children = {}) : - DFTGate(id, name, children) + DFTSeqAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - - if(!state.hasFailed(mId)) { + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(!state.hasFailed(this->mId)) { bool childOperationalBefore = false; - for(auto const& child : mChildren) + for(auto const& child : this->mChildren) { if(!state.hasFailed(child->id())) { childOperationalBefore = true; @@ -436,22 +451,20 @@ namespace storm { else { if(childOperationalBefore) { state.markAsInvalid(); - return; //false; + return; } } } if(!childOperationalBefore) { fail(state, queues); - //return true; } } - //return false; } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(hasFailsafeChild(state)); - if(state.isOperational(mId)) { + if(state.isOperational(this->mId)) { failsafe(state, queues); //return true; } @@ -461,71 +474,74 @@ namespace storm { std::string typestring() const { return "SEQAND"; } - private: - //static const std::string typestring = "seqand"; }; - - inline std::ostream& operator<<(std::ostream& os, DFTSeqAnd const& gate) { + + template + inline std::ostream& operator<<(std::ostream& os, DFTSeqAnd const& gate) { return os << gate.toString(); } - - class DFTPand : public DFTGate { + + + + template + class DFTPand : public DFTGate { + public: - DFTPand(size_t id, std::string const& name, std::vector> const& children = {}) : - DFTGate(id, name, children) + DFTPand(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(state.isOperational(mId)) { + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(this->mId)) { bool childOperationalBefore = false; - for(auto const& child : mChildren) + for(auto const& child : this->mChildren) { if(!state.hasFailed(child->id())) { childOperationalBefore = true; } else if(childOperationalBefore && state.hasFailed(child->id())){ - failsafe(state, queues); - childrenDontCare(state, queues); - return; //false; + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + return; } } if(!childOperationalBefore) { - fail(state, queues); - //return true; + this->fail(state, queues); } } - // return false; } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ - assert(hasFailsafeChild(state)); - if(state.isOperational(mId)) { - failsafe(state, queues); - childrenDontCare(state, queues); - //return true; + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(this->hasFailsafeChild(state)); + if(state.isOperational(this->mId)) { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); } - //return false; - } + } std::string typestring() const { return "PAND"; } }; - inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { + template + inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { return os << gate.toString(); } - - class DFTPor : public DFTGate { + + + + template + class DFTPor : public DFTGate { public: - DFTPor(size_t id, std::string const& name, std::vector> const& children = {}) : - DFTGate(id, name, children) + DFTPor(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { assert(false); } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(false); } @@ -533,58 +549,60 @@ namespace storm { return "POR"; } }; - - inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { + + template + inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { return os << gate.toString(); } - class DFTVot : public DFTGate { + + + template + class DFTVot : public DFTGate { + private: unsigned mThreshold; + public: - DFTVot(size_t id, std::string const& name, unsigned threshold, std::vector> const& children = {}) : - DFTGate(id, name, children), mThreshold(threshold) + DFTVot(size_t id, std::string const& name, unsigned threshold, std::vector>> const& children = {}) : + DFTGate(id, name, children), mThreshold(threshold) {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - - if(state.isOperational(mId)) { + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(this->mId)) { unsigned nrFailedChildren = 0; - for(auto const& child : mChildren) + for(auto const& child : this->mChildren) { if(state.hasFailed(child->id())) { ++nrFailedChildren; if(nrFailedChildren >= mThreshold) { - fail(state, queues); - return;// true; + this->fail(state, queues); + return; } } } } - // return false; - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ - assert(hasFailsafeChild(state)); - if(state.isOperational(mId)) { + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + assert(this->hasFailsafeChild(state)); + if(state.isOperational(this->mId)) { unsigned nrFailsafeChildren = 0; - for(auto const& child : mChildren) + for(auto const& child : this->mChildren) { if(state.isFailsafe(child->id())) { ++nrFailsafeChildren; - if(nrFailsafeChildren > nrChildren() - mThreshold) + if(nrFailsafeChildren > this->nrChildren() - mThreshold) { - failsafe(state, queues); - childrenDontCare(state, queues); - return;// true; + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + return; } } } } - //return false; } std::string typestring() const { @@ -593,21 +611,24 @@ namespace storm { }; - inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { + template + inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { return os << gate.toString(); - } - - class DFTSpare : public DFTGate { + } + + + + template + class DFTSpare : public DFTGate { + + private: size_t mUseIndex; size_t mActiveIndex; public: - DFTSpare(size_t id, std::string const& name, std::vector> const& children = {}) : - DFTGate(id, name, children) - { - - } - + DFTSpare(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) + {} std::string typestring() const { return "SPARE"; @@ -624,39 +645,40 @@ namespace storm { void setActiveIndex(size_t activeIndex) { mActiveIndex = activeIndex; } - - void initializeUses(storm::storage::DFTState& state) { - assert(mChildren.size() > 0); - state.setUsesAtPosition(mUseIndex, mChildren[0]->id()); + + void initializeUses(storm::storage::DFTState& state) { + assert(this->mChildren.size() > 0); + state.setUsesAtPosition(mUseIndex, this->mChildren[0]->id()); } - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(state.isOperational(mId)) { + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(this->mId)) { size_t uses = state.extractUses(mUseIndex); if(!state.isOperational(uses)) { // TODO compute children ids before. std::vector childrenIds; - for(auto const& child : mChildren) { + for(auto const& child : this->mChildren) { childrenIds.push_back(child->id()); } - bool claimingSuccessful = state.claimNew(mId, mUseIndex, uses, childrenIds); + bool claimingSuccessful = state.claimNew(this->mId, mUseIndex, uses, childrenIds); if(!claimingSuccessful) { - fail(state, queues); + this->fail(state, queues); } } } } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(state.isOperational(mId)) { + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if(state.isOperational(this->mId)) { if(state.isFailsafe(state.extractUses((mUseIndex)))) { - failsafe(state, queues); - childrenDontCare(state, queues); + this->failsafe(state, queues); + this->childrenDontCare(state, queues); } } } }; + } } diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 87838b9a2..98cada93a 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -5,8 +5,8 @@ namespace storm { namespace storage { - // TODO Matthias: template - DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mId(id), mDft(dft) { + template + DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mId(id), mDft(dft) { mInactiveSpares = dft.getSpareIndices(); dft.initializeUses(*this); dft.initializeActivation(*this); @@ -14,70 +14,83 @@ namespace storm { mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); } - - DFTElementState DFTState::getElementState(size_t id) const { + + template + DFTElementState DFTState::getElementState(size_t id) const { return static_cast(getElementStateInt(id)); } - int DFTState::getElementStateInt(size_t id) const { + template + int DFTState::getElementStateInt(size_t id) const { return mStatus.getAsInt(mDft.failureIndex(id), 2); } - size_t DFTState::getId() const { + template + size_t DFTState::getId() const { return mId; } - void DFTState::setId(size_t id) { + template + void DFTState::setId(size_t id) { mId = id; } - bool DFTState::isOperational(size_t id) const { + template + bool DFTState::isOperational(size_t id) const { return getElementState(id) == DFTElementState::Operational; } - bool DFTState::hasFailed(size_t id) const { + template + bool DFTState::hasFailed(size_t id) const { return mStatus[mDft.failureIndex(id)]; } - bool DFTState::isFailsafe(size_t id) const { + template + bool DFTState::isFailsafe(size_t id) const { return mStatus[mDft.failureIndex(id)+1]; } - bool DFTState::dontCare(size_t id) const { + template + bool DFTState::dontCare(size_t id) const { return getElementState(id) == DFTElementState::DontCare; } - void DFTState::setFailed(size_t id) { + template + void DFTState::setFailed(size_t id) { mStatus.set(mDft.failureIndex(id)); } - void DFTState::setFailsafe(size_t id) { + template + void DFTState::setFailsafe(size_t id) { mStatus.set(mDft.failureIndex(id)+1); } - void DFTState::setDontCare(size_t id) { + template + void DFTState::setDontCare(size_t id) { mStatus.setFromInt(mDft.failureIndex(id), 2, static_cast(DFTElementState::DontCare) ); } - - void DFTState::beNoLongerFailable(size_t id) { + + template + void DFTState::beNoLongerFailable(size_t id) { auto it = std::find(mIsCurrentlyFailableBE.begin(), mIsCurrentlyFailableBE.end(), id); if(it != mIsCurrentlyFailableBE.end()) { mIsCurrentlyFailableBE.erase(it); } } - // TODO Matthias: template - std::pair>, bool> DFTState::letNextBEFail(size_t index) + template + std::pair>, bool> DFTState::letNextBEFail(size_t index) { assert(index < mIsCurrentlyFailableBE.size()); STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); - std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); + std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); setFailed(res.first->id()); return res; } - - void DFTState::activate(size_t repr) { + + template + void DFTState::activate(size_t repr) { std::vector const& module = mDft.module(repr); for(size_t elem : module) { if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { @@ -89,33 +102,37 @@ namespace storm { } } } - - - bool DFTState::isActiveSpare(size_t id) const { + + template + bool DFTState::isActiveSpare(size_t id) const { assert(mDft.getElement(id)->isSpareGate()); return (std::find(mInactiveSpares.begin(), mInactiveSpares.end(), id) == mInactiveSpares.end()); } - - uint_fast64_t DFTState::uses(size_t id) const { + + template + uint_fast64_t DFTState::uses(size_t id) const { return extractUses(mDft.usageIndex(id)); } - - uint_fast64_t DFTState::extractUses(size_t from) const { + + template + uint_fast64_t DFTState::extractUses(size_t from) const { assert(mDft.usageInfoBits() < 64); return mStatus.getAsInt(from, mDft.usageInfoBits()); } - - bool DFTState::isUsed(size_t child) { + + template + bool DFTState::isUsed(size_t child) { return (std::find(mUsedRepresentants.begin(), mUsedRepresentants.end(), child) != mUsedRepresentants.end()); - } - - void DFTState::setUsesAtPosition(size_t usageIndex, size_t child) { + + template + void DFTState::setUsesAtPosition(size_t usageIndex, size_t child) { mStatus.setFromInt(usageIndex, mDft.usageInfoBits(), child); mUsedRepresentants.push_back(child); } - - bool DFTState::claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds) { + + template + bool DFTState::claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds) { auto it = find(childIds.begin(), childIds.end(), currentlyUses); assert(it != childIds.end()); ++it; @@ -132,5 +149,12 @@ namespace storm { return false; } + // Explicitly instantiate the class. + template class DFTState; + +#ifdef STORM_HAVE_CARL + template class DFTState; +#endif + } -} +} \ No newline at end of file diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 1e8f8cb01..4f25550b0 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -14,7 +14,7 @@ namespace storm { template class DFTBE; - + template class DFTState { friend struct std::hash; private: @@ -24,12 +24,10 @@ namespace storm { std::vector mIsCurrentlyFailableBE; std::vector mUsedRepresentants; bool mValid = true; - // TODO Matthias: template - const DFT& mDft; + const DFT& mDft; public: - // TODO Matthias: template - DFTState(DFT const& dft, size_t id); + DFTState(DFT const& dft, size_t id); DFTElementState getElementState(size_t id) const; @@ -109,8 +107,7 @@ namespace storm { return mIsCurrentlyFailableBE.size(); } - // TODO Matthias: template - std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); + std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); std::string getCurrentlyFailableString() { std::stringstream stream; @@ -137,9 +134,9 @@ namespace storm { } namespace std { - template<> - struct hash { - size_t operator()(storm::storage::DFTState const& s) const { + template + struct hash> { + size_t operator()(storm::storage::DFTState const& s) const { return hash()(s.mStatus); } }; diff --git a/src/storage/dft/DFTStateSpaceGenerationQueues.h b/src/storage/dft/DFTStateSpaceGenerationQueues.h index ec0879d52..b881a220b 100644 --- a/src/storage/dft/DFTStateSpaceGenerationQueues.h +++ b/src/storage/dft/DFTStateSpaceGenerationQueues.h @@ -10,19 +10,28 @@ namespace storm { namespace storage { + + template class DFTGate; + template class DFTElement; - - - + + + template class DFTStateSpaceGenerationQueues { - std::priority_queue, std::vector>, OrderElementsByRank> failurePropagation; - std::vector> failsafePropagation; - std::vector> dontcarePropagation; - std::vector> activatePropagation; + + using DFTElementPointer = std::shared_ptr>; + using DFTElementVector = std::vector; + using DFTGatePointer = std::shared_ptr>; + using DFTGateVector = std::vector; + + std::priority_queue> failurePropagation; + DFTGateVector failsafePropagation; + DFTElementVector dontcarePropagation; + DFTElementVector activatePropagation; public: - void propagateFailure(std::shared_ptr const& elem) { + void propagateFailure(DFTGatePointer const& elem) { failurePropagation.push(elem); } @@ -30,8 +39,8 @@ namespace storm { return failurePropagation.empty(); } - std::shared_ptr nextFailurePropagation() { - std::shared_ptr next = failurePropagation.top(); + DFTGatePointer nextFailurePropagation() { + DFTGatePointer next = failurePropagation.top(); failurePropagation.pop(); return next; } @@ -40,12 +49,12 @@ namespace storm { return failsafePropagation.empty(); } - void propagateFailsafe(std::shared_ptr const& gate) { + void propagateFailsafe(DFTGatePointer const& gate) { failsafePropagation.push_back(gate); } - - std::shared_ptr nextFailsafePropagation() { - std::shared_ptr next = failsafePropagation.back(); + + DFTGatePointer nextFailsafePropagation() { + DFTGatePointer next = failsafePropagation.back(); failsafePropagation.pop_back(); return next; } @@ -54,25 +63,23 @@ namespace storm { return dontcarePropagation.empty(); } - void propagateDontCare(std::shared_ptr const& elem) { + void propagateDontCare(DFTElementPointer const& elem) { dontcarePropagation.push_back(elem); } - void propagateDontCare(std::vector> const& elems) { + void propagateDontCare(DFTElementVector const& elems) { dontcarePropagation.insert(dontcarePropagation.end(), elems.begin(), elems.end()); } - std::shared_ptr nextDontCarePropagation() { - std::shared_ptr next = dontcarePropagation.back(); + DFTElementPointer nextDontCarePropagation() { + DFTElementPointer next = dontcarePropagation.back(); dontcarePropagation.pop_back(); return next; } }; + } - } - - #endif /* DFTSTATESPACEGENERATIONQUEUES_H */ diff --git a/src/storage/dft/OrderDFTElementsById.cpp b/src/storage/dft/OrderDFTElementsById.cpp index 017969848..6c9493bee 100644 --- a/src/storage/dft/OrderDFTElementsById.cpp +++ b/src/storage/dft/OrderDFTElementsById.cpp @@ -3,16 +3,31 @@ namespace storm { namespace storage { - bool OrderElementsById::operator()(std::shared_ptr const& a , std::shared_ptr const& b) const { + + template + bool OrderElementsById::operator()(std::shared_ptr> const& a , std::shared_ptr> const& b) const { return a->id() < b->id(); } - bool OrderElementsById::operator ()(const std::shared_ptr& a, const std::shared_ptr& b) const { + + template + bool OrderElementsById::operator ()(const std::shared_ptr>& a, const std::shared_ptr>& b) const { return a->id() < b->id(); } - - - bool OrderElementsByRank::operator ()(const std::shared_ptr& a, const std::shared_ptr& b) const { + + + template + bool OrderElementsByRank::operator ()(const std::shared_ptr>& a, const std::shared_ptr>& b) const { return a->rank() < b->rank(); } + + + // Explicitly instantiate the class. + template class OrderElementsById; + template class OrderElementsByRank; + +#ifdef STORM_HAVE_CARL + template class OrderElementsById; + template class OrderElementsByRank; +#endif } } diff --git a/src/storage/dft/OrderDFTElementsById.h b/src/storage/dft/OrderDFTElementsById.h index 8dfc22da0..821a2de45 100644 --- a/src/storage/dft/OrderDFTElementsById.h +++ b/src/storage/dft/OrderDFTElementsById.h @@ -5,16 +5,22 @@ namespace storm { namespace storage { + + template class DFTGate; + template class DFTElement; - + + template struct OrderElementsById { - bool operator()(std::shared_ptr const& a , std::shared_ptr const& b) const; - bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const; + bool operator()(std::shared_ptr> const& a , std::shared_ptr> const& b) const; + + bool operator()(std::shared_ptr> const& a, std::shared_ptr> const& b) const; }; - + + template struct OrderElementsByRank { - bool operator()(std::shared_ptr const& a, std::shared_ptr const& b) const; + bool operator()(std::shared_ptr> const& a, std::shared_ptr> const& b) const; }; } From 4c09f9ce29c23532ca5a71fe473e0670bf2f19a9 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 4 Jan 2016 11:17:44 +0100 Subject: [PATCH 017/246] Minor improvements Former-commit-id: 63dfd49048df5ec636ca9dd163249e0ea3de76c3 --- src/parser/DFTGalileoParser.cpp | 12 +++++------- src/solver/Z3SmtSolver.cpp | 2 +- src/storm-dyftee.cpp | 1 + 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index e3368bbe3..97b095f22 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -41,7 +41,7 @@ namespace storm { template bool DFTGalileoParser::readFile(const std::string& filename) { // constants - std::string topleveltoken = "toplevel"; + std::string toplevelToken = "toplevel"; std::string toplevelId; std::ifstream file; @@ -57,23 +57,21 @@ namespace storm { std::string line; bool generalSuccess = true; - while(std::getline(file, line)) - { + while(std::getline(file, line)) { bool success = true; STORM_LOG_TRACE("Parsing: " << line); size_t commentstarts = line.find("//"); line = line.substr(0, commentstarts); size_t firstsemicolon = line.find(";"); line = line.substr(0, firstsemicolon); - if (line.find_first_not_of(' ') == std::string::npos) - { + if (line.find_first_not_of(' ') == std::string::npos) { // Only whitespace continue; } // Top level indicator. - if(boost::starts_with(line, topleveltoken)) { - toplevelId = stripQuotsFromName(line.substr(topleveltoken.size() + 1)); + if(boost::starts_with(line, toplevelToken)) { + toplevelId = stripQuotsFromName(line.substr(toplevelToken.size() + 1)); } else { diff --git a/src/solver/Z3SmtSolver.cpp b/src/solver/Z3SmtSolver.cpp index 1c3495335..eba059635 100644 --- a/src/solver/Z3SmtSolver.cpp +++ b/src/solver/Z3SmtSolver.cpp @@ -323,7 +323,7 @@ namespace storm { std::vector Z3SmtSolver::getUnsatAssumptions() { #ifdef STORM_HAVE_Z3 - STORM_LOG_THROW(lastResult == SmtSolver::CheckResult::Unsat, storm::exceptions::InvalidStateException, "Unable to generate unsatisfiable core of assumptions, because the last check did not determine the formulas to be unsatisfiable.") + STORM_LOG_THROW(lastResult == SmtSolver::CheckResult::Unsat, storm::exceptions::InvalidStateException, "Unable to generate unsatisfiable core of assumptions, because the last check did not determine the formulas to be unsatisfiable."); STORM_LOG_THROW(lastCheckAssumptions, storm::exceptions::InvalidStateException, "Unable to generate unsatisfiable core of assumptions, because the last check did not involve assumptions."); z3::expr_vector z3UnsatAssumptions = this->solver->unsat_core(); diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 7040db9ad..1d2696594 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -13,6 +13,7 @@ int main(int argc, char** argv) { if(argc < 2) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; + return 1; } storm::utility::setUp(); From 8271045b27f2cd9e53f80278b8eaae5062f18208 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 8 Jan 2016 18:12:37 +0100 Subject: [PATCH 018/246] ToString is const Former-commit-id: d512894cf4a5af371607da5b7d7805706783f350 --- src/storage/expressions/Expression.cpp | 2 +- src/storage/expressions/Expression.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storage/expressions/Expression.cpp b/src/storage/expressions/Expression.cpp index 96cf57a31..bc539c795 100644 --- a/src/storage/expressions/Expression.cpp +++ b/src/storage/expressions/Expression.cpp @@ -162,7 +162,7 @@ namespace storm { return this->getBaseExpression().accept(visitor); } - std::string Expression::toString() { + std::string Expression::toString() const { std::stringstream stream; stream << *this; return stream.str(); diff --git a/src/storage/expressions/Expression.h b/src/storage/expressions/Expression.h index e8fe0e60b..0c18f122a 100644 --- a/src/storage/expressions/Expression.h +++ b/src/storage/expressions/Expression.h @@ -297,7 +297,7 @@ namespace storm { * * @return The string representation of the expression. */ - std::string toString(); + std::string toString() const; friend std::ostream& operator<<(std::ostream& stream, Expression const& expression); From f38eeff1efe25fd11cee3d6796066c56790320cb Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 9 Jan 2016 11:19:34 +0100 Subject: [PATCH 019/246] First try on parsing of rational functions Former-commit-id: 63a6ae0d146bc81530ace58c314e5ed88b2ac01a --- src/builder/ExplicitDFTModelBuilder.cpp | 2 +- src/parser/DFTGalileoParser.cpp | 69 ++++++++++++++++--------- src/parser/DFTGalileoParser.h | 25 +++++++-- src/parser/ExpressionParser.cpp | 38 +++++++++++++- src/parser/ExpressionParser.h | 18 ++++++- src/storage/dft/DFTElements.h | 6 ++- src/storm-dyftee.cpp | 36 ++++++------- 7 files changed, 139 insertions(+), 55 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index e039b389f..b561bb716 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -79,7 +79,7 @@ namespace storm { while (!stateQueue.empty()) { // Initialization outgoingTransitions.clear(); - ValueType sum = 0; + ValueType sum = storm::utility::zero(); // Consider next state storm::storage::DFTState state = stateQueue.front(); diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 97b095f22..89ad18ff6 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -4,9 +4,10 @@ #include #include #include -#include -#include "../exceptions/FileIoException.h" -#include "../exceptions/NotSupportedException.h" +#include "src/storage/expressions/ExpressionManager.h" +#include "src/exceptions/NotImplementedException.h" +#include "src/exceptions/FileIoException.h" +#include "src/exceptions/NotSupportedException.h" #include "src/utility/macros.h" namespace storm { @@ -15,7 +16,7 @@ namespace storm { template storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { if(readFile(filename)) { - storm::storage::DFT dft = mBuilder.build(); + storm::storage::DFT dft = builder.build(); STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); return dft; @@ -43,6 +44,7 @@ namespace storm { // constants std::string toplevelToken = "toplevel"; std::string toplevelId; + std::string parametricToken = "param"; std::ifstream file; file.exceptions ( std::ifstream::failbit ); @@ -73,8 +75,16 @@ namespace storm { if(boost::starts_with(line, toplevelToken)) { toplevelId = stripQuotsFromName(line.substr(toplevelToken.size() + 1)); } - else - { + else if (boost::starts_with(line, parametricToken)) { + if (!std::is_same::value) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions."); + } + std::string parameter = stripQuotsFromName(line.substr(parametricToken.size() + 1)); + storm::expressions::Variable var = manager->declareRationalVariable(parameter); + identifierMapping.emplace(var.getName(), var); + parser.setIdentifierMapping(identifierMapping); + STORM_LOG_TRACE("Added parameter: " << var.getName()); + } else { std::vector tokens; boost::split(tokens, line, boost::is_any_of(" ")); std::string name(stripQuotsFromName(tokens[0])); @@ -84,28 +94,19 @@ namespace storm { childNames.push_back(stripQuotsFromName(tokens[i])); } if(tokens[1] == "and") { - success = mBuilder.addAndElement(name, childNames); + success = builder.addAndElement(name, childNames); } else if(tokens[1] == "or") { - success = mBuilder.addOrElement(name, childNames); + success = builder.addOrElement(name, childNames); } else if(boost::starts_with(tokens[1], "vot")) { - success = mBuilder.addVotElement(name, boost::lexical_cast(tokens[1].substr(3)), childNames); + success = builder.addVotElement(name, boost::lexical_cast(tokens[1].substr(3)), childNames); } else if(tokens[1] == "pand") { - success = mBuilder.addPandElement(name, childNames); + success = builder.addPandElement(name, childNames); } else if(tokens[1] == "wsp" || tokens[1] == "csp") { - success = mBuilder.addSpareElement(name, childNames); + success = builder.addSpareElement(name, childNames); } else if(boost::starts_with(tokens[1], "lambda=")) { - ValueType failureRate = 0; - ValueType dormancyFactor = 0; - if (std::is_same::value) { - failureRate = boost::lexical_cast(tokens[1].substr(7)); - dormancyFactor = boost::lexical_cast(tokens[2].substr(5)); - } else { - // TODO Matthias: Parse RationalFunction - failureRate; - dormancyFactor; - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Parsing into rational function not supported."); - } - success = mBuilder.addBasicElement(name, failureRate, dormancyFactor); + ValueType failureRate = parseRationalExpression(tokens[1].substr(7)); + ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); + success = builder.addBasicElement(name, failureRate, dormancyFactor); } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " + tokens[1] + " not recognized."); success = false; @@ -115,17 +116,37 @@ namespace storm { generalSuccess = success; } } - if(!mBuilder.setTopLevel(toplevelId)) { + if(!builder.setTopLevel(toplevelId)) { STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown."); } file.close(); return generalSuccess; } + template + ValueType DFTGalileoParser::parseRationalExpression(std::string const& expr) { + assert(false); + } + + template<> + double DFTGalileoParser::parseRationalExpression(std::string const& expr) { + return boost::lexical_cast(expr); + } + // Explicitly instantiate the class. template class DFTGalileoParser; #ifdef STORM_HAVE_CARL + template<> + storm::RationalFunction DFTGalileoParser::parseRationalExpression(std::string const& expr) { + STORM_LOG_TRACE("Translating expression: " << expr); + storm::expressions::Expression expression = parser.parseFromString(expr); + STORM_LOG_TRACE("Expression: " << expression); + storm::RationalFunction rationalFunction = evaluator.asRational(expression); + STORM_LOG_TRACE("Parsed expression: " << rationalFunction); + return rationalFunction; + } + template class DFTGalileoParser; #endif diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h index 4f7da1566..557803465 100644 --- a/src/parser/DFTGalileoParser.h +++ b/src/parser/DFTGalileoParser.h @@ -1,8 +1,11 @@ #ifndef DFTGALILEOPARSER_H #define DFTGALILEOPARSER_H -#include "../storage/dft/DFT.h" -#include "../storage/dft/DFTBuilder.h" +#include "src/storage/dft/DFT.h" +#include "src/storage/dft/DFTBuilder.h" +#include "src/storage/expressions/ExpressionManager.h" +#include "src/parser/ExpressionParser.h" +#include "src/storage/expressions/ExpressionEvaluator.h" #include @@ -11,16 +14,30 @@ namespace storm { template class DFTGalileoParser { - storm::storage::DFTBuilder mBuilder; + storm::storage::DFTBuilder builder; + + std::shared_ptr manager; + + storm::parser::ExpressionParser parser; + + storm::expressions::ExpressionEvaluator evaluator; + + std::unordered_map identifierMapping; + public: + DFTGalileoParser() : manager(new storm::expressions::ExpressionManager()), parser(*manager), evaluator(*manager) { + } + storm::storage::DFT parseDFT(std::string const& filename); private: bool readFile(std::string const& filename); std::string stripQuotsFromName(std::string const& name); + + ValueType parseRationalExpression(std::string const& expr); }; -} + } } #endif /* DFTGALILEOPARSER_H */ diff --git a/src/parser/ExpressionParser.cpp b/src/parser/ExpressionParser.cpp index c67f808e0..0e4d0fbb8 100644 --- a/src/parser/ExpressionParser.cpp +++ b/src/parser/ExpressionParser.cpp @@ -5,7 +5,7 @@ namespace storm { namespace parser { - ExpressionParser::ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols const& invalidIdentifiers_, bool allowBacktracking) : ExpressionParser::base_type(expression), orOperator_(), andOperator_(), equalityOperator_(), relationalOperator_(), plusOperator_(), multiplicationOperator_(), powerOperator_(), unaryOperator_(), floorCeilOperator_(), minMaxOperator_(), trueFalse_(manager), manager(manager.getSharedPointer()), createExpressions(false), acceptDoubleLiterals(true), identifiers_(nullptr), invalidIdentifiers_(invalidIdentifiers_) { + ExpressionParser::ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols const& invalidIdentifiers_, bool allowBacktracking) : ExpressionParser::base_type(expression), orOperator_(), andOperator_(), equalityOperator_(), relationalOperator_(), plusOperator_(), multiplicationOperator_(), powerOperator_(), unaryOperator_(), floorCeilOperator_(), minMaxOperator_(), trueFalse_(manager), manager(manager.getSharedPointer()), createExpressions(false), acceptDoubleLiterals(true), deleteIdentifierMapping(false), identifiers_(nullptr), invalidIdentifiers_(invalidIdentifiers_) { identifier %= qi::as_string[qi::raw[qi::lexeme[((qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')))]]][qi::_pass = phoenix::bind(&ExpressionParser::isValidIdentifier, phoenix::ref(*this), qi::_1)]; identifier.name("identifier"); @@ -126,9 +126,23 @@ namespace storm { this->identifiers_ = nullptr; } } - + + void ExpressionParser::setIdentifierMapping(std::unordered_map const& identifierMapping) { + unsetIdentifierMapping(); + this->createExpressions = true; + this->identifiers_ = new qi::symbols(); + for (auto const& identifierExpressionPair : identifierMapping) { + this->identifiers_->add(identifierExpressionPair.first, identifierExpressionPair.second); + } + deleteIdentifierMapping = true; + } + void ExpressionParser::unsetIdentifierMapping() { this->createExpressions = false; + if (deleteIdentifierMapping) { + delete this->identifiers_; + deleteIdentifierMapping = false; + } this->identifiers_ = nullptr; } @@ -346,5 +360,25 @@ namespace storm { } return true; } + + storm::expressions::Expression ExpressionParser::parseFromString(std::string const& expressionString) const { + PositionIteratorType first(expressionString.begin()); + PositionIteratorType iter = first; + PositionIteratorType last(expressionString.end()); + + // Create empty result; + storm::expressions::Expression result; + + try { + // Start parsing. + bool succeeded = qi::phrase_parse(iter, last, *this, boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi), result); + STORM_LOG_THROW(succeeded, storm::exceptions::WrongFormatException, "Could not parse expression."); + STORM_LOG_DEBUG("Parsed expression successfully."); + } catch (qi::expectation_failure const& e) { + STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, e.what_); + } + + return result; + } } } \ No newline at end of file diff --git a/src/parser/ExpressionParser.h b/src/parser/ExpressionParser.h index 19c129b4a..4d40467a0 100644 --- a/src/parser/ExpressionParser.h +++ b/src/parser/ExpressionParser.h @@ -25,7 +25,7 @@ namespace storm { * points it would typically allow. This can, for example, be used to prevent errors if the outer grammar * also parses boolean conjuncts that are erroneously consumed by the expression parser. */ - ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols const& invalidIdentifiers_, bool allowBacktracking = false); + ExpressionParser(storm::expressions::ExpressionManager const& manager, qi::symbols const& invalidIdentifiers_ = qi::symbols(), bool allowBacktracking = false); ExpressionParser(ExpressionParser const& other) = default; ExpressionParser& operator=(ExpressionParser const& other) = default; @@ -38,6 +38,15 @@ namespace storm { * @param identifiers_ A pointer to a mapping from identifiers to expressions. */ void setIdentifierMapping(qi::symbols const* identifiers_); + + /*! + * Sets an identifier mapping that is used to determine valid variables in the expression. The mapped-to + * expressions will be substituted wherever the key value appears in the parsed expression. After setting + * this, the parser will generate expressions. + * + * @param identifierMapping A mapping from identifiers to expressions. + */ + void setIdentifierMapping(std::unordered_map const& identifierMapping); /*! * Unsets a previously set identifier mapping. This will make the parser not generate expressions any more @@ -51,7 +60,9 @@ namespace storm { * @param flag If set to true, double literals are accepted. */ void setAcceptDoubleLiterals(bool flag); - + + storm::expressions::Expression parseFromString(std::string const& expressionString) const; + private: struct orOperatorStruct : qi::symbols { orOperatorStruct() { @@ -184,6 +195,9 @@ namespace storm { // A flag that indicates whether double literals are accepted. bool acceptDoubleLiterals; + // A flag that indicates whether the mapping must be deleted on unsetting. + bool deleteIdentifierMapping; + // The currently used mapping of identifiers to expressions. This is used if the parser is set to create // expressions. qi::symbols const* identifiers_; diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 6296a176f..daa1d3d54 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -11,6 +11,8 @@ #include "DFTState.h" #include "DFTStateSpaceGenerationQueues.h" +#include "src/utility/constants.h" +#include "src/adapters/CarlAdapter.h" using std::size_t; @@ -313,9 +315,9 @@ namespace storm { } bool isColdBasicElement() const { - return mPassiveFailureRate == 0; + return storm::utility::isZero(mPassiveFailureRate); } - + virtual std::vector independentUnit() const { return {this->mId}; } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 1d2696594..906e9df21 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -5,7 +5,7 @@ #include "modelchecker/results/CheckResult.h" #include "utility/storm.h" -#define VALUE_TYPE double +#define VALUE_TYPE storm::RationalFunction /* * Entry point for the DyFTeE backend. @@ -15,6 +15,15 @@ int main(int argc, char** argv) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; return 1; } + // Construct PCTL forumla + std::string inputFormula; + if (argc < 3) { + // Set explicit reachability formula + inputFormula = "Pmax=?[true U \"failed\"]"; + } else { + // Read formula from input + inputFormula = argv[2]; + } storm::utility::setUp(); log4cplus::LogLevel level = log4cplus::TRACE_LOG_LEVEL; @@ -24,33 +33,20 @@ int main(int argc, char** argv) { std::cout << "Parsing DFT file..." << std::endl; storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(argv[1]); - std::cout << "Built data structure" << std::endl; + // Verify the model as CTMC std::cout << "Building CTMC..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); std::shared_ptr> model = builder.buildCTMC(); std::cout << "Built CTMC" << std::endl; - std::cout << "Model checking..." << std::endl; - // Construct PCTL forumla - std::string inputFormula; - if (argc < 3) { - // Set explicit reachability formula - inputFormula = "Pmax=?[true U \"failed\"]"; - } else { - // Read formula from input - inputFormula = argv[2]; - } std::vector> formulas = storm::parseFormulasForExplicit(inputFormula); assert(formulas.size() == 1); - - // Verify the model - std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); - assert(result); + std::unique_ptr resultCtmc(storm::verifySparseModel(model, formulas[0])); + assert(resultCtmc); std::cout << "Result (initial states): "; - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); - std::cout << *result << std::endl; - - std::cout << "Checked model" << std::endl; + resultCtmc->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + std::cout << *resultCtmc << std::endl; + std::cout << "Checked CTMC" << std::endl; } From 20a5d8e96f025751cb0b31944b6f958a0465f4d8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 9 Jan 2016 11:20:18 +0100 Subject: [PATCH 020/246] Side conditions for rational functions cannot be checked directly Former-commit-id: c5e6d79c9d597e11b09c40cbadf1b3af0688ba5f --- src/storage/dft/DFTBuilder.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 88fdc6ef0..12d5e88c3 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -78,16 +78,10 @@ namespace storm { } bool addBasicElement(std::string const& name, ValueType failureRate, ValueType dormancyFactor) { - if(failureRate <= 0.0) { - std::cerr << "Failure rate must be positive." << std::endl; - return false; - } - - if(dormancyFactor < 0.0 || dormancyFactor > 1.0) { - std::cerr << "Dormancy factor must be between 0 and 1." << std::endl; - return false; - } - + //TODO Matthias: collect constraints for SMT solving + //failureRate > 0 + //0 <= dormancyFactor <= 1 + mElements[name] = std::make_shared>(mNextId++, name, failureRate, dormancyFactor); return true; } From c8d2cf17242d36e81ebe493d264b5ff93cba009b Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 9 Jan 2016 11:23:36 +0100 Subject: [PATCH 021/246] Better distinction between parametric and non-parametric DFTs Former-commit-id: 57ac698a3876d3f6fe1828469d4c7c6d2426aa41 --- src/storm-dyftee.cpp | 82 +++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 906e9df21..2e9e88bbf 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -5,24 +5,62 @@ #include "modelchecker/results/CheckResult.h" #include "utility/storm.h" -#define VALUE_TYPE storm::RationalFunction +/*! + * Load DFT from filename, build corresponding CTMC and check against given property. + * + * @param filename Path to DFT file in Galileo format. + * @param property PCTC formula capturing the property to check. + */ +template +void analyzeDFT(std::string filename, std::string property) { + // Parsing DFT + std::cout << "Parsing DFT file..." << std::endl; + storm::parser::DFTGalileoParser parser; + storm::storage::DFT dft = parser.parseDFT(filename); + std::cout << "Built data structure" << std::endl; + + // Building CTMC + std::cout << "Building CTMC..." << std::endl; + storm::builder::ExplicitDFTModelBuilder builder(dft); + std::shared_ptr> model = builder.buildCTMC(); + std::cout << "Built CTMC" << std::endl; + + // Model checking + std::cout << "Model checking..." << std::endl; + std::vector> formulas = storm::parseFormulasForExplicit(property); + assert(formulas.size() == 1); + std::unique_ptr resultCtmc(storm::verifySparseModel(model, formulas[0])); + assert(resultCtmc); + std::cout << "Result (initial states): "; + resultCtmc->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + std::cout << *resultCtmc << std::endl; + std::cout << "Checked CTMC" << std::endl; +} -/* +/*! * Entry point for the DyFTeE 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(int argc, char** argv) { if(argc < 2) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; return 1; } - // Construct PCTL forumla - std::string inputFormula; - if (argc < 3) { - // Set explicit reachability formula - inputFormula = "Pmax=?[true U \"failed\"]"; - } else { - // Read formula from input - inputFormula = argv[2]; + + // Parse cli arguments + bool parametric = false; + std::string filename = argv[1]; + std::string pctlFormula = "Pmax=?[true U \"failed\"]"; + for (int i = 2; i < argc; ++i) { + std::string option = argv[i]; + if (option == "--parametric") { + parametric = true; + } else { + pctlFormula = option; + } } storm::utility::setUp(); @@ -30,23 +68,11 @@ int main(int argc, char** argv) { logger.setLogLevel(level); logger.getAppender("mainConsoleAppender")->setThreshold(level); - std::cout << "Parsing DFT file..." << std::endl; - storm::parser::DFTGalileoParser parser; - storm::storage::DFT dft = parser.parseDFT(argv[1]); - std::cout << "Built data structure" << std::endl; + std::cout << "Running " << (parametric ? "parametric " : "") << "DFT analysis on file " << filename << " with property " << pctlFormula << std::endl; - // Verify the model as CTMC - std::cout << "Building CTMC..." << std::endl; - storm::builder::ExplicitDFTModelBuilder builder(dft); - std::shared_ptr> model = builder.buildCTMC(); - std::cout << "Built CTMC" << std::endl; - std::cout << "Model checking..." << std::endl; - std::vector> formulas = storm::parseFormulasForExplicit(inputFormula); - assert(formulas.size() == 1); - std::unique_ptr resultCtmc(storm::verifySparseModel(model, formulas[0])); - assert(resultCtmc); - std::cout << "Result (initial states): "; - resultCtmc->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); - std::cout << *resultCtmc << std::endl; - std::cout << "Checked CTMC" << std::endl; + if (parametric) { + analyzeDFT(filename, pctlFormula); + } else { + analyzeDFT(filename, pctlFormula); + } } From 3b9a48136c8192376839fd08c3e09ce77b77fdc3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 9 Jan 2016 11:53:46 +0100 Subject: [PATCH 022/246] Sort transitions before building them Former-commit-id: eba930f0b65ac3a44b3acf527f1836d21e576dce --- src/builder/ExplicitDFTModelBuilder.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index b561bb716..c0c596b02 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,6 +1,7 @@ #include "src/builder/ExplicitDFTModelBuilder.h" #include #include +#include namespace storm { namespace builder { @@ -74,7 +75,7 @@ namespace storm { template void ExplicitDFTModelBuilder::exploreStates(std::queue>& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { - std::vector> outgoingTransitions; + std::map outgoingTransitions; while (!stateQueue.empty()) { // Initialization @@ -149,7 +150,8 @@ namespace storm { // Set transition ValueType prob = nextBE.first->activeFailureRate(); - outgoingTransitions.push_back(std::make_pair(it->getId(), prob)); + auto resultInsert = outgoingTransitions.insert(std::make_pair(it->getId(), prob)); + assert(resultInsert.second); sum += prob; } // end while failing BE From e024f314eb2db11f02de7e2c6386523c1f85bd78 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 9 Jan 2016 11:59:30 +0100 Subject: [PATCH 023/246] Added dft examples Former-commit-id: 43e43c3846364c1b1c3cb0ef93d3ddc81d2b4ac8 --- examples/dft/and.dft | 4 ++++ examples/dft/and_param.dft | 5 +++++ examples/dft/or.dft | 4 ++++ examples/dft/pand.dft | 4 ++++ examples/dft/spare.dft | 5 +++++ examples/dft/spare2.dft | 8 ++++++++ examples/dft/spare3.dft | 10 ++++++++++ examples/dft/spare4.dft | 9 +++++++++ examples/dft/tripple_and1.dft | 8 ++++++++ examples/dft/tripple_and2.dft | 6 ++++++ examples/dft/voting.dft | 5 +++++ 11 files changed, 68 insertions(+) create mode 100644 examples/dft/and.dft create mode 100644 examples/dft/and_param.dft create mode 100644 examples/dft/or.dft create mode 100644 examples/dft/pand.dft create mode 100644 examples/dft/spare.dft create mode 100644 examples/dft/spare2.dft create mode 100644 examples/dft/spare3.dft create mode 100644 examples/dft/spare4.dft create mode 100644 examples/dft/tripple_and1.dft create mode 100644 examples/dft/tripple_and2.dft create mode 100644 examples/dft/voting.dft diff --git a/examples/dft/and.dft b/examples/dft/and.dft new file mode 100644 index 000000000..2b06cbe95 --- /dev/null +++ b/examples/dft/and.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" and "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/and_param.dft b/examples/dft/and_param.dft new file mode 100644 index 000000000..8c95a0f2a --- /dev/null +++ b/examples/dft/and_param.dft @@ -0,0 +1,5 @@ +param x; +toplevel "A"; +"A" and "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=x dorm=0.3; diff --git a/examples/dft/or.dft b/examples/dft/or.dft new file mode 100644 index 000000000..b1003da11 --- /dev/null +++ b/examples/dft/or.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" or "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/pand.dft b/examples/dft/pand.dft new file mode 100644 index 000000000..d752517b4 --- /dev/null +++ b/examples/dft/pand.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" pand "B" "C"; +"B" lambda=0.4 dorm=0.3; +"C" lambda=0.2 dorm=0.3; diff --git a/examples/dft/spare.dft b/examples/dft/spare.dft new file mode 100644 index 000000000..4c5d44ff4 --- /dev/null +++ b/examples/dft/spare.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" wsp "I" "M"; +"I" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare2.dft b/examples/dft/spare2.dft new file mode 100644 index 000000000..21b40cf73 --- /dev/null +++ b/examples/dft/spare2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" or "B" "C"; +"B" wsp "I" "J"; +"C" wsp "M" "J"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare3.dft b/examples/dft/spare3.dft new file mode 100644 index 000000000..ba0ac01d4 --- /dev/null +++ b/examples/dft/spare3.dft @@ -0,0 +1,10 @@ +toplevel "A"; +"A" or "B" "C" "D"; +"B" wsp "I" "M"; +"C" wsp "J" "M"; +"D" wsp "K" "M"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/spare4.dft b/examples/dft/spare4.dft new file mode 100644 index 000000000..a217c6e43 --- /dev/null +++ b/examples/dft/spare4.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" and "B" "C"; +"B" wsp "I" "J" "K"; +"C" wsp "M" "J"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; +"M" lambda=0.5 dorm=0.3; + diff --git a/examples/dft/tripple_and1.dft b/examples/dft/tripple_and1.dft new file mode 100644 index 000000000..b6f1c04b2 --- /dev/null +++ b/examples/dft/tripple_and1.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "C"; +"B" and "BE1" "BE2"; +"C" and "BE3" "BE4"; +"BE1" lambda=0.5 dorm=0.3; +"BE2" lambda=0.5 dorm=0.3; +"BE3" lambda=0.5 dorm=0.3; +"BE4" lambda=0.5 dorm=0.3; diff --git a/examples/dft/tripple_and2.dft b/examples/dft/tripple_and2.dft new file mode 100644 index 000000000..0f9d0e491 --- /dev/null +++ b/examples/dft/tripple_and2.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "B" "C"; +"B" and "BE1" "BE2"; +"BE1" lambda=0.5 dorm=0.3; +"BE2" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/voting.dft b/examples/dft/voting.dft new file mode 100644 index 000000000..18a54a7fa --- /dev/null +++ b/examples/dft/voting.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" vot2 "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; From d13aca1109cbad0c19020a15e31655dd98697d78 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 22 Jan 2016 11:37:19 +0100 Subject: [PATCH 024/246] Fixed problem with const initializer Former-commit-id: bcd1343169cd095f07e2725a2baa24e8bcde3371 --- src/parser/ExpressionParser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/ExpressionParser.h b/src/parser/ExpressionParser.h index 4d40467a0..262b9499c 100644 --- a/src/parser/ExpressionParser.h +++ b/src/parser/ExpressionParser.h @@ -203,7 +203,7 @@ namespace storm { qi::symbols const* identifiers_; // The symbol table of invalid identifiers. - qi::symbols const& invalidIdentifiers_; + qi::symbols invalidIdentifiers_; // Rules for parsing a composed expression. qi::rule expression; From 545dad861bdf941df9c2a60386a84b8308d101f5 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 25 Jan 2016 18:13:02 +0100 Subject: [PATCH 025/246] Mini change Former-commit-id: a24bd187a37ea077378a24761289df89277a4326 --- src/storm-dyftee.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 2e9e88bbf..cf9922c47 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -46,7 +46,8 @@ void analyzeDFT(std::string filename, std::string property) { */ int main(int argc, char** argv) { if(argc < 2) { - std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; + std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; + std::cout << "./storm-dft " << std::endl; return 1; } From 65bb496bb9fea63840c3746d753b103153b7f203 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 26 Jan 2016 10:40:49 +0100 Subject: [PATCH 026/246] Activate expected time in FormulaParser Former-commit-id: 6fff9e826958ed53ae6eb03516b87cd1dfbcfbb3 --- src/parser/FormulaParser.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/parser/FormulaParser.cpp b/src/parser/FormulaParser.cpp index 082474187..d6de95ace 100644 --- a/src/parser/FormulaParser.cpp +++ b/src/parser/FormulaParser.cpp @@ -270,8 +270,8 @@ namespace storm { booleanLiteralFormula = (qi::lit("true")[qi::_a = true] | qi::lit("false")[qi::_a = false])[qi::_val = phoenix::bind(&FormulaParserGrammar::createBooleanLiteralFormula, phoenix::ref(*this), qi::_a)]; booleanLiteralFormula.name("boolean literal formula"); - - operatorFormula = probabilityOperator | rewardOperator | steadyStateOperator; + + operatorFormula = probabilityOperator | rewardOperator | steadyStateOperator | expectedTimeOperator; operatorFormula.name("operator formulas"); atomicStateFormula = booleanLiteralFormula | labelFormula | expressionFormula | (qi::lit("(") > stateFormula > qi::lit(")")) | operatorFormula; @@ -334,8 +334,8 @@ namespace storm { start = qi::eps > (stateFormula % +(qi::char_("\n;"))) >> qi::skip(boost::spirit::ascii::space | qi::lit("//") >> *(qi::char_ - (qi::eol | qi::eoi)))[qi::eps] >> qi::eoi; start.name("start"); - /*! - * Enable the following lines to print debug output for most the rules. + //Enable the following lines to print debug output for most the rules. + /* debug(start); debug(stateFormula); debug(orStateFormula); @@ -343,6 +343,7 @@ namespace storm { debug(probabilityOperator); debug(rewardOperator); debug(steadyStateOperator); + debug(expectedTimeOperator); debug(pathFormulaWithoutUntil); debug(pathFormula); debug(conditionalFormula); @@ -357,7 +358,7 @@ namespace storm { debug(reachabilityRewardFormula); debug(cumulativeRewardFormula); debug(instantaneousRewardFormula); - */ + */ // Enable error reporting. qi::on_error(start, handler(qi::_1, qi::_2, qi::_3, qi::_4)); @@ -366,6 +367,7 @@ namespace storm { qi::on_error(andStateFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(probabilityOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(rewardOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error(expectedTimeOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(steadyStateOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(operatorInformation, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormulaWithoutUntil, handler(qi::_1, qi::_2, qi::_3, qi::_4)); From 71070cb2818784cc0b26620f84f487b5f27cb3cd Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 26 Jan 2016 16:19:32 +0100 Subject: [PATCH 027/246] Implemented expected time on CTMC by reduction to DTMC with rewards Former-commit-id: ebd3603069d846c5c4237287417f374816f8e8f0 --- .../csl/SparseCtmcCslModelChecker.cpp | 15 ++++++++++++--- src/modelchecker/csl/SparseCtmcCslModelChecker.h | 1 + .../csl/helper/SparseCtmcCslHelper.cpp | 12 +++++++++++- src/modelchecker/csl/helper/SparseCtmcCslHelper.h | 2 ++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 14631fba5..37eaaad52 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -31,7 +31,7 @@ namespace storm { template bool SparseCtmcCslModelChecker::canHandle(storm::logic::Formula const& formula) const { - return formula.isCslStateFormula() || formula.isCslPathFormula() || formula.isRewardPathFormula(); + return formula.isCslStateFormula() || formula.isCslPathFormula() || formula.isRewardPathFormula() || formula.isExpectedTimeOperatorFormula(); } template @@ -101,8 +101,17 @@ namespace storm { storm::storage::SparseMatrix probabilityMatrix = storm::modelchecker::helper::SparseCtmcCslHelper::computeProbabilityMatrix(this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector()); std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverage(probabilityMatrix, subResult.getTruthValuesVector(), &this->getModel().getExitRateVector(), qualitative, *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); - } - + } + + template + std::unique_ptr SparseCtmcCslModelChecker::computeExpectedTimes(storm::logic::EventuallyFormula const& eventuallyFormula, bool qualitative, boost::optional const& optimalityType) { + std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); + ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); + } + // Explicitly instantiate the model checker. template class SparseCtmcCslModelChecker>; diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.h b/src/modelchecker/csl/SparseCtmcCslModelChecker.h index 8423cac53..7e25376a1 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.h +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.h @@ -28,6 +28,7 @@ namespace storm { virtual std::unique_ptr computeInstantaneousRewards(storm::logic::InstantaneousRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeLongRunAverage(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual std::unique_ptr computeExpectedTimes(storm::logic::EventuallyFormula const& eventuallyFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; private: // An object that is used for solving linear equations and performing matrix-vector multiplication. diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index 453496ce2..51c58848c 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -650,11 +650,21 @@ namespace storm { return result; } + template + std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + // Compute expected time on CTMC by reduction to DTMC with rewards + storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); + std::vector totalRewardVector; + for (auto exitRate : exitRateVector) { + totalRewardVector.push_back(1 / exitRate); + } + return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); + } + template class SparseCtmcCslHelper; template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - } } } \ No newline at end of file diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h index fae4d8498..dfa0ef877 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -28,6 +28,8 @@ namespace storm { static std::vector computeLongRunAverage(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + /*! * Computes the matrix representing the transitions of the uniformized CTMC. * From 8b59a26fe07e47d962a6030ae18ad225a5e2ad94 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 26 Jan 2016 17:15:24 +0100 Subject: [PATCH 028/246] More dft files Former-commit-id: b1b7906604b0e8dfe5f443ce25175353c3df3fcb --- examples/dft/cm2.dft | 22 ++++++++++++++++++ examples/dft/cm4.dft | 41 +++++++++++++++++++++++++++++++++ examples/dft/cps.dft | 26 +++++++++++++++++++++ examples/dft/mdcs.dft | 26 +++++++++++++++++++++ examples/dft/mdcs2.dft | 19 +++++++++++++++ examples/dft/mp.dft | 7 ++++++ examples/dft/tripple_and2.dft | 8 ++++--- examples/dft/tripple_and2_c.dft | 6 +++++ examples/dft/tripple_and_c.dft | 7 ++++++ examples/dft/tripple_or.dft | 9 ++++++++ examples/dft/tripple_or2.dft | 8 +++++++ examples/dft/tripple_or2_c.dft | 6 +++++ examples/dft/tripple_or_c.dft | 7 ++++++ examples/dft/voting.dft | 8 +++---- examples/dft/voting2.dft | 5 ++++ 15 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 examples/dft/cm2.dft create mode 100644 examples/dft/cm4.dft create mode 100644 examples/dft/cps.dft create mode 100644 examples/dft/mdcs.dft create mode 100644 examples/dft/mdcs2.dft create mode 100644 examples/dft/mp.dft create mode 100644 examples/dft/tripple_and2_c.dft create mode 100644 examples/dft/tripple_and_c.dft create mode 100644 examples/dft/tripple_or.dft create mode 100644 examples/dft/tripple_or2.dft create mode 100644 examples/dft/tripple_or2_c.dft create mode 100644 examples/dft/tripple_or_c.dft create mode 100644 examples/dft/voting2.dft diff --git a/examples/dft/cm2.dft b/examples/dft/cm2.dft new file mode 100644 index 000000000..89a1a8eba --- /dev/null +++ b/examples/dft/cm2.dft @@ -0,0 +1,22 @@ +toplevel "System"; +"System" or "BUS" "CM"; +"CM" and "CM1" "CM2"; +"CM1" or "DISK1" "POWER1" "MEMORY1"; +"CM2" or "DISK2" "POWER2" "MEMORY2"; +"DISK1" wsp "D11" "D12"; +"DISK2" wsp "D21" "D22"; +"POWER1" or "P1" "PS"; +"POWER2" or "P2" "PS"; +"MEMORY1" wsp "M1" "M3"; +"MEMORY2" wsp "M2" "M3"; +"BUS" lambda=0.0002 dorm=0; +"P1" lambda=0.05 dorm=0; +"P2" lambda=0.05 dorm=0; +"PS" lambda=0.6 dorm=0; +"D11" lambda=8.0 dorm=0; +"D12" lambda=8.0 dorm=0.5; +"D21" lambda=8.0 dorm=0; +"D22" lambda=8.0 dorm=0.5; +"M1" lambda=0.003 dorm=0; +"M2" lambda=0.003 dorm=0; +"M3" lambda=0.003 dorm=0.5; diff --git a/examples/dft/cm4.dft b/examples/dft/cm4.dft new file mode 100644 index 000000000..deb8a7fb7 --- /dev/null +++ b/examples/dft/cm4.dft @@ -0,0 +1,41 @@ +toplevel "System"; +"System" or "BUS" "CM"; +"CM" and "CM1" "CM2" "CM3" "CM4"; +"CM1" or "DISK1" "POWER1" "MEMORY1"; +"CM2" or "DISK2" "POWER2" "MEMORY2"; +"CM3" or "DISK3" "POWER3" "MEMORY3"; +"CM4" or "DISK4" "POWER4" "MEMORY4"; +"DISK1" wsp "D11" "D12"; +"DISK2" wsp "D21" "D22"; +"DISK3" wsp "D31" "D32"; +"DISK4" wsp "D41" "D42"; +"POWER1" or "P1" "PS"; +"POWER2" or "P2" "PS"; +"POWER3" or "P3" "PS2"; +"POWER4" or "P4" "PS2"; +"MEMORY1" wsp "M1" "M3" "M4"; +"MEMORY2" wsp "M2" "M3" "M4"; +"MEMORY3" wsp "M31" "M3"; +"MEMORY4" wsp "M41" "M4"; +"BUS" lambda=0.0002 dorm=0; +"P1" lambda=0.05 dorm=0; +"P2" lambda=0.05 dorm=0; +"P3" lambda=0.05 dorm=0; +"P4" lambda=0.05 dorm=0; +"PS" lambda=0.6 dorm=0; +"PS2" lambda=0.6 dorm=0; +"D11" lambda=8.0 dorm=0; +"D12" lambda=8.0 dorm=0.5; +"D21" lambda=8.0 dorm=0; +"D22" lambda=8.0 dorm=0.5; +"D31" lambda=8.0 dorm=0; +"D32" lambda=8.0 dorm=0.5; +"D41" lambda=8.0 dorm=0; +"D42" lambda=8.0 dorm=0.5; +"M1" lambda=0.003 dorm=0; +"M2" lambda=0.003 dorm=0; +"M31" lambda=0.003 dorm=0; +"M41" lambda=0.003 dorm=0; +"M3" lambda=0.003 dorm=0.5; +"M4" lambda=0.003 dorm=0.5; + diff --git a/examples/dft/cps.dft b/examples/dft/cps.dft new file mode 100644 index 000000000..9ee386740 --- /dev/null +++ b/examples/dft/cps.dft @@ -0,0 +1,26 @@ +toplevel "System"; + +"System" pand "A" "B"; + +"A" and "AA" "AB" "AC" "AD"; + +"B" pand "C" "D"; + +"C" and "CA" "CB" "CC" "CD"; + +"D" and "DA" "DB" "DC" "DD"; + +"AA" lambda=1 dorm=0; +"AB" lambda=1 dorm=0; +"AC" lambda=1 dorm=0; +"AD" lambda=1 dorm=0; + +"CA" lambda=1 dorm=0; +"CB" lambda=1 dorm=0; +"CC" lambda=1 dorm=0; +"CD" lambda=1 dorm=0; + +"DA" lambda=1 dorm=0; +"DB" lambda=1 dorm=0; +"DC" lambda=1 dorm=0; +"DD" lambda=1 dorm=0; diff --git a/examples/dft/mdcs.dft b/examples/dft/mdcs.dft new file mode 100644 index 000000000..450217a4c --- /dev/null +++ b/examples/dft/mdcs.dft @@ -0,0 +1,26 @@ +toplevel "System"; + +"System" or "S" "N"; + +"N" lambda=2e-5 dorm=0; + +"S" and "CMA" "CMB"; + +"CMA" or "DiskA" "PA" "MemA"; +"DiskA" wsp "DAA" "DAB"; +"PA" lambda=500e-5 dorm=0; +"MemA" wsp "MA" "MC"; +"DAA" lambda=80000e-5 dorm=0.5; +"DAB" lambda=80000e-5 dorm=0.5; +"MA" lambda=30e-5 dorm=0; + +"CMB" or "DiskB" "PB" "MemB"; +"DiskB" wsp "DBA" "DBB"; +"PB" lambda=500e-5 dorm=0; +"MemB" wsp "MB" "MC"; +"DBA" lambda=80000e-5 dorm=0.5; +"DBB" lambda=80000e-5 dorm=0.5; +"MB" lambda=30e-5 dorm=0; + +"MC" lambda=30e-5 dorm=0.5; + diff --git a/examples/dft/mdcs2.dft b/examples/dft/mdcs2.dft new file mode 100644 index 000000000..5a376a7b8 --- /dev/null +++ b/examples/dft/mdcs2.dft @@ -0,0 +1,19 @@ +toplevel "System"; +"System" or "S" "N"; +"N" lambda=0.0000200000 dorm=0.0000000000; +"S" and "CMA" "CMB"; +"CMA" or "DiskA" "PA" "MemA"; +"DiskA" wsp "DAA" "DAB"; +"PA" lambda=0.0049999999 dorm=0.0000000000; +"MemA" wsp "MA" "MC"; +"DAA" lambda=0.8000000119 dorm=0.5000000000; +"DAB" lambda=0.8000000119 dorm=0.5000000000; +"MA" lambda=0.0003000000 dorm=0.0000000000; +"CMB" or "DiskB" "PB" "MemB"; +"DiskB" wsp "DBA" "DBB"; +"PB" lambda=0.0049999999 dorm=0.0000000000; +"MemB" wsp "MB" "MC"; +"DBA" lambda=0.8000000119 dorm=0.5000000000; +"DBB" lambda=0.8000000119 dorm=0.5000000000; +"MB" lambda=0.0003000000 dorm=0.0000000000; +"MC" lambda=0.0003000000 dorm=0.5000000000; diff --git a/examples/dft/mp.dft b/examples/dft/mp.dft new file mode 100644 index 000000000..a2e769420 --- /dev/null +++ b/examples/dft/mp.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" or "B" "C"; +"B" or "D" "E"; +"C" or "F" "E"; +"D" lambda=0.1 dorm=0; +"E" lambda=0.2 dorm=0; +"F" lambda=0.3 dorm=0; diff --git a/examples/dft/tripple_and2.dft b/examples/dft/tripple_and2.dft index 0f9d0e491..9e02d88e7 100644 --- a/examples/dft/tripple_and2.dft +++ b/examples/dft/tripple_and2.dft @@ -1,6 +1,8 @@ toplevel "A"; "A" and "B" "C"; "B" and "BE1" "BE2"; -"BE1" lambda=0.5 dorm=0.3; -"BE2" lambda=0.5 dorm=0.3; -"C" lambda=0.5 dorm=0.3; +"C" and "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_and2_c.dft b/examples/dft/tripple_and2_c.dft new file mode 100644 index 000000000..edfde4144 --- /dev/null +++ b/examples/dft/tripple_and2_c.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "BE1" "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_and_c.dft b/examples/dft/tripple_and_c.dft new file mode 100644 index 000000000..72b384c98 --- /dev/null +++ b/examples/dft/tripple_and_c.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" and "BE1" "BE2" "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or.dft b/examples/dft/tripple_or.dft new file mode 100644 index 000000000..9dbd0e377 --- /dev/null +++ b/examples/dft/tripple_or.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" or "B" "C"; +"B" or "BE1" "BE2"; +"C" or "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or2.dft b/examples/dft/tripple_or2.dft new file mode 100644 index 000000000..32bc0ff8f --- /dev/null +++ b/examples/dft/tripple_or2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" or "B" "C"; +"B" or "BE1" "BE2"; +"C" or "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or2_c.dft b/examples/dft/tripple_or2_c.dft new file mode 100644 index 000000000..40747fbc8 --- /dev/null +++ b/examples/dft/tripple_or2_c.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" or "BE1" "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_or_c.dft b/examples/dft/tripple_or_c.dft new file mode 100644 index 000000000..378b29630 --- /dev/null +++ b/examples/dft/tripple_or_c.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" or "BE1" "BE2" "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/voting.dft b/examples/dft/voting.dft index 18a54a7fa..6a5e82b3e 100644 --- a/examples/dft/voting.dft +++ b/examples/dft/voting.dft @@ -1,5 +1,5 @@ toplevel "A"; -"A" vot2 "B" "C" "D"; -"B" lambda=0.5 dorm=0.3; -"C" lambda=0.5 dorm=0.3; -"D" lambda=0.5 dorm=0.3; +"A" vot1 "B" "C" "D"; +"B" lambda=0.1 dorm=0; +"C" lambda=0.2 dorm=0; +"D" lambda=0.3 dorm=0; diff --git a/examples/dft/voting2.dft b/examples/dft/voting2.dft new file mode 100644 index 000000000..9cdf299f3 --- /dev/null +++ b/examples/dft/voting2.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" 1of3 "B" "C" "D"; +"B" lambda=0.3 dorm=0; +"C" lambda=0.4 dorm=0; +"D" lambda=1 dorm=0; From 9c1edef4a778f03474d033c3e2f3a6aa38e23f21 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 26 Jan 2016 17:17:46 +0100 Subject: [PATCH 029/246] Parse Galileo representation of voting gate as '1of3' Former-commit-id: 972869e661abe1c18a8552842fba44c4192d26b3 --- src/parser/DFTGalileoParser.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 89ad18ff6..05dc5773a 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -32,9 +32,8 @@ namespace storm { if(firstQuots == std::string::npos) { return name; - } else if (secondQuots == std::string::npos) { - STORM_LOG_THROW(false, storm::exceptions::FileIoException, "No ending quotation mark found in " << name); } else { + STORM_LOG_THROW(secondQuots != std::string::npos, storm::exceptions::FileIoException, "No ending quotation mark found in " << name); return name.substr(firstQuots+1,secondQuots-1); } } @@ -76,9 +75,7 @@ namespace storm { toplevelId = stripQuotsFromName(line.substr(toplevelToken.size() + 1)); } else if (boost::starts_with(line, parametricToken)) { - if (!std::is_same::value) { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions."); - } + STORM_LOG_THROW((!std::is_same::value), storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions."); std::string parameter = stripQuotsFromName(line.substr(parametricToken.size() + 1)); storm::expressions::Variable var = manager->declareRationalVariable(parameter); identifierMapping.emplace(var.getName(), var); @@ -95,15 +92,23 @@ namespace storm { } if(tokens[1] == "and") { success = builder.addAndElement(name, childNames); - } else if(tokens[1] == "or") { + } else if (tokens[1] == "or") { success = builder.addOrElement(name, childNames); - } else if(boost::starts_with(tokens[1], "vot")) { + } else if (boost::starts_with(tokens[1], "vot")) { success = builder.addVotElement(name, boost::lexical_cast(tokens[1].substr(3)), childNames); - } else if(tokens[1] == "pand") { + } else if (tokens[1].find("of") != std::string::npos) { + size_t pos = tokens[1].find("of"); + unsigned threshold = boost::lexical_cast(tokens[1].substr(0, pos)); + unsigned count = boost::lexical_cast(tokens[1].substr(pos + 2)); + STORM_LOG_THROW(count == childNames.size(), storm::exceptions::FileIoException, "Voting gate does not correspond to number of children."); + success = builder.addVotElement(name, threshold, childNames); + } else if (tokens[1] == "pand") { success = builder.addPandElement(name, childNames); - } else if(tokens[1] == "wsp" || tokens[1] == "csp") { + } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); - } else if(boost::starts_with(tokens[1], "lambda=")) { + } else if (boost::starts_with(tokens[1], "fdep")) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Functional dependencies currently not supported"); + } else if (boost::starts_with(tokens[1], "lambda=")) { ValueType failureRate = parseRationalExpression(tokens[1].substr(7)); ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); success = builder.addBasicElement(name, failureRate, dormancyFactor); From c26cdc90122915a00dfa0942b0bd3958efd865a3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 26 Jan 2016 17:20:01 +0100 Subject: [PATCH 030/246] Wrong assertion Former-commit-id: e6b64dcb8aeaeaff1348697de4dfcf18c9c5ec10 --- src/parser/DFTGalileoParser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 05dc5773a..57dec65d1 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -75,7 +75,7 @@ namespace storm { toplevelId = stripQuotsFromName(line.substr(toplevelToken.size() + 1)); } else if (boost::starts_with(line, parametricToken)) { - STORM_LOG_THROW((!std::is_same::value), storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions."); + STORM_LOG_THROW((std::is_same::value), storm::exceptions::NotSupportedException, "Parameters only allowed when using rational functions."); std::string parameter = stripQuotsFromName(line.substr(parametricToken.size() + 1)); storm::expressions::Variable var = manager->declareRationalVariable(parameter); identifierMapping.emplace(var.getName(), var); From 0a1ebc2f73d0cb1bd5d80a84ba4e9d267465be3d Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 26 Jan 2016 17:50:40 +0100 Subject: [PATCH 031/246] Distinct error message for parametric model checking Former-commit-id: 7c1eacb9c28fdf459583f840e46d32ccd9498b8e --- src/parser/DFTGalileoParser.cpp | 2 +- src/utility/storm.h | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 57dec65d1..163bc1488 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -113,7 +113,7 @@ namespace storm { ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); success = builder.addBasicElement(name, failureRate, dormancyFactor); } else { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " + tokens[1] + " not recognized."); + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " << tokens[1] << " not recognized."); success = false; } } diff --git a/src/utility/storm.h b/src/utility/storm.h index d1e32f839..c3d7a891a 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -70,6 +70,7 @@ #include "src/exceptions/InvalidSettingsException.h" #include "src/exceptions/InvalidTypeException.h" #include "src/exceptions/NotImplementedException.h" +#include "src/exceptions/NotSupportedException.h" namespace storm { @@ -289,13 +290,22 @@ namespace storm { template<> inline std::unique_ptr verifySparseModel(std::shared_ptr> model, std::shared_ptr const& formula) { std::unique_ptr result; - std::shared_ptr> dtmc = model->template as>(); - - storm::modelchecker::SparseDtmcEliminationModelChecker> modelchecker(*dtmc); - if (modelchecker.canHandle(*formula)) { - result = modelchecker.check(*formula); + if (model->getType() == storm::models::ModelType::Dtmc) { + std::shared_ptr> dtmc = model->template as>(); + storm::modelchecker::SparseDtmcEliminationModelChecker> modelchecker(*dtmc); + if (modelchecker.canHandle(*formula)) { + result = modelchecker.check(*formula); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support this property on DTMCs."); + } + } else if (model->getType() == storm::models::ModelType::Mdp) { + std::shared_ptr> mdp = model->template as>(); + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support MDPs."); + } else if (model->getType() == storm::models::ModelType::Ctmc) { + std::shared_ptr> ctmc = model->template as>(); + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support CTMCs."); } else { - STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "The parametric engine currently does not support this property."); + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support " << model->getType()); } return result; } From 3e4ddbea8c285e0b7cfa943e1618b7f53ff4d060 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 28 Jan 2016 14:27:24 +0100 Subject: [PATCH 032/246] Integrated expected time on parametric CTMCs Former-commit-id: 2f892ad8db092a0db585d13c40aacec1b354e8ee --- .../csl/SparseCtmcCslModelChecker.cpp | 2 +- .../csl/helper/SparseCtmcCslHelper.cpp | 16 +++++- .../csl/helper/SparseCtmcCslHelper.h | 2 +- .../SparseDtmcEliminationModelChecker.cpp | 56 +++++++++++-------- .../SparseDtmcEliminationModelChecker.h | 1 + src/utility/storm.h | 19 ++++++- 6 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp index 16ab12244..a9b86d8c8 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -108,7 +108,7 @@ namespace storm { std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), this->getModel().getInitialStates(), subResult.getTruthValuesVector(), qualitative/*, *linearEquationSolverFactory*/); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index 5cf10fd84..145eed1b1 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -1,6 +1,7 @@ #include "src/modelchecker/csl/helper/SparseCtmcCslHelper.h" #include "src/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h" +#include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" #include "src/models/sparse/StandardRewardModel.h" @@ -11,6 +12,8 @@ #include "src/storage/StronglyConnectedComponentDecomposition.h" +#include "src/adapters/CarlAdapter.h" + #include "src/utility/macros.h" #include "src/utility/vector.h" #include "src/utility/graph.h" @@ -647,20 +650,27 @@ namespace storm { } template - std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory*/) { // Compute expected time on CTMC by reduction to DTMC with rewards storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); std::vector totalRewardVector; for (auto exitRate : exitRateVector) { - totalRewardVector.push_back(1 / exitRate); + totalRewardVector.push_back(storm::utility::one() / exitRate); } - return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); + + return storm::modelchecker::SparseDtmcEliminationModelChecker>::computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates, totalRewardVector, false, qualitative); + // Enable again, if RationalFunction finally is supported + //return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); } template class SparseCtmcCslHelper; template std::vector SparseCtmcCslHelper::computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeCumulativeRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + +#ifdef STORM_HAVE_CARL + template std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory*/); +#endif } } } \ No newline at end of file diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h index ef744045e..94752a974 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -28,7 +28,7 @@ namespace storm { static std::vector computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory*/); /*! * Computes the matrix representing the transitions of the uniformized CTMC. diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 6ec1e6d86..41324957b 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -578,27 +578,40 @@ namespace storm { std::unique_ptr SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName, bool qualitative, boost::optional const& optimalityType) { // Retrieve the appropriate bitvectors by model checking the subformulas. std::unique_ptr subResultPointer = this->check(rewardPathFormula.getSubformula()); - storm::storage::BitVector phiStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector const& psiStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(rewardModelName ? rewardModelName.get() : ""); + std::vector stateRewardValues = rewardModel.getTotalRewardVector(trueStates.getNumberOfSetBits(), this->getModel().getTransitionMatrix(), trueStates); + STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model."); + std::vector result = computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates, stateRewardValues, this->computeResultsForInitialStatesOnly, qualitative, optimalityType); + + // Construct check result + std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); + return checkResult; + } + + template + std::vector SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector const& stateRewardValues, bool computeForInitialStatesOnly, bool qualitative, boost::optional const& optimalityType) { + + uint_fast64_t numberOfStates = probabilityMatrix.getRowCount(); - // Then, compute the subset of states that has a reachability reward less than infinity. - storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true); - storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(this->getModel().getBackwardTransitions(), trueStates, psiStates); + // Compute the subset of states that has a reachability reward less than infinity. + storm::storage::BitVector trueStates(numberOfStates, true); + storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(backwardTransitions, trueStates, targetStates); infinityStates.complement(); - storm::storage::BitVector maybeStates = ~psiStates & ~infinityStates; + storm::storage::BitVector maybeStates = ~targetStates & ~infinityStates; // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly) { - if (this->getModel().getInitialStates().isSubsetOf(infinityStates)) { + if (computeForInitialStatesOnly) { + if (initialStates.isSubsetOf(infinityStates)) { STORM_LOG_DEBUG("The reward of all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } - if (this->getModel().getInitialStates().isSubsetOf(psiStates)) { + if (initialStates.isSubsetOf(targetStates)) { STORM_LOG_DEBUG("The reward of all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } @@ -608,40 +621,37 @@ namespace storm { if (furtherComputationNeeded) { // If we compute the results for the initial states only, we can cut off all maybe state that are not // reachable from them. - if (computeResultsForInitialStatesOnly) { + if (computeForInitialStatesOnly) { // Determine the set of states that is reachable from the initial state without jumping over a target state. - storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, psiStates); + storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(probabilityMatrix, initialStates, maybeStates, targetStates); // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state). maybeStates &= reachableStates; } // Determine the set of initial states of the sub-model. - storm::storage::BitVector newInitialStates = this->getModel().getInitialStates() % maybeStates; + storm::storage::BitVector newInitialStates = initialStates % maybeStates; // We then build the submatrix that only has the transitions of the maybe states. - storm::storage::SparseMatrix submatrix = this->getModel().getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates); + storm::storage::SparseMatrix submatrix = probabilityMatrix.getSubmatrix(false, maybeStates, maybeStates); storm::storage::SparseMatrix submatrixTransposed = submatrix.transpose(); // Project the state reward vector to all maybe-states. - std::vector stateRewardValues = rewardModel.getTotalRewardVector(maybeStates.getNumberOfSetBits(), this->getModel().getTransitionMatrix(), maybeStates); - - std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeResultsForInitialStatesOnly, phiStates, psiStates, this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, psiStates)); + std::vector rewardValues = storm::utility::vector::filterVector(stateRewardValues, maybeStates); + storm::storage::BitVector phiStates(numberOfStates, true); + std::vector subresult = computeReachabilityValues(submatrix, rewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, phiStates, targetStates, probabilityMatrix.getConstrainedRowSumVector(maybeStates, targetStates)); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } // Construct full result. storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity()); - storm::utility::vector::setVectorValues(result, psiStates, storm::utility::zero()); - - // Construct check result based on whether we have computed values for all states or just the initial states. - std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + storm::utility::vector::setVectorValues(result, targetStates, storm::utility::zero()); + if (computeForInitialStatesOnly) { // If we computed the results for the initial (and inf) states only, we need to filter the result to // only communicate these results. - checkResult->filter(ExplicitQualitativeCheckResult(~maybeStates | this->getModel().getInitialStates())); + result = storm::utility::vector::filterVector(result, ~maybeStates | initialStates); } - return checkResult; + return result; } template diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 692a6be57..a840cef88 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -28,6 +28,7 @@ namespace storm { virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector const& stateRewardValues, bool computeForInitialStatesOnly, bool qualitative, boost::optional const& optimalityType = boost::optional()); virtual std::unique_ptr computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; diff --git a/src/utility/storm.h b/src/utility/storm.h index a3d2e58ca..4bdf22556 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -58,6 +58,7 @@ #include "src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h" #include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" #include "src/modelchecker/csl/SparseCtmcCslModelChecker.h" +#include "src/modelchecker/csl/helper/SparseCtmcCslHelper.h" #include "src/modelchecker/csl/HybridCtmcCslModelChecker.h" #include "src/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "src/modelchecker/results/SymbolicQualitativeCheckResult.h" @@ -329,8 +330,22 @@ namespace storm { std::shared_ptr> mdp = model->template as>(); STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support MDPs."); } else if (model->getType() == storm::models::ModelType::Ctmc) { - std::shared_ptr> ctmc = model->template as>(); - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support CTMCs."); + // Hack to avoid instantiating the CTMC Model Checker which currently does not work for rational functions + if (formula->isExpectedTimeOperatorFormula()) { + // We can only solve expected time for pCTMCs at the moment + std::shared_ptr> ctmc = model->template as>(); + + // Compute goal states + storm::logic::EventuallyFormula eventuallyFormula = formula->asExpectedTimeOperatorFormula().getSubformula().asEventuallyFormula(); + storm::modelchecker::SparsePropositionalModelChecker> propositionalModelchecker(*ctmc); + std::unique_ptr subResultPointer = propositionalModelchecker.check(eventuallyFormula.getSubformula()); + storm::modelchecker::ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(ctmc->getTransitionMatrix(), ctmc->getBackwardTransitions(), ctmc->getExitRateVector(), ctmc->getInitialStates(), subResult.getTruthValuesVector(), false); + result = std::unique_ptr(new storm::modelchecker::ExplicitQuantitativeCheckResult(std::move(numericResult))); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support this property on CTMCs."); + } } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support " << model->getType()); } From 62f7305bea9d30eabe053886c513110357fac5f8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 28 Jan 2016 18:07:19 +0100 Subject: [PATCH 033/246] No rewards for target states Former-commit-id: 98e0139840e5034f55f7f4a06dc4e00ee8496341 --- .../csl/helper/SparseCtmcCslHelper.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index 145eed1b1..78f48a173 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -651,15 +651,24 @@ namespace storm { template std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory*/) { - // Compute expected time on CTMC by reduction to DTMC with rewards + // Compute expected time on CTMC by reduction to DTMC with rewards. storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); + + // Initialize rewards. std::vector totalRewardVector; - for (auto exitRate : exitRateVector) { - totalRewardVector.push_back(storm::utility::one() / exitRate); + for (size_t i = 0; i < exitRateVector.size(); ++i) { + std::cout << i << std::endl; + if (targetStates[i]) { + // Set reward for target states to 0. + totalRewardVector.push_back(storm::utility::zero()); + } else { + // Reward is (1 / exitRate). + totalRewardVector.push_back(storm::utility::one() / exitRateVector[i]); + } } return storm::modelchecker::SparseDtmcEliminationModelChecker>::computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates, totalRewardVector, false, qualitative); - // Enable again, if RationalFunction finally is supported + // Enable again, if RationalFunction finally is supported. //return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); } From d6b7331a5c00b3b28f603e8967551d380f7bfe6e Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 29 Jan 2016 10:28:20 +0100 Subject: [PATCH 034/246] Fixed problem with multiple transitions to one state Former-commit-id: 2fe612028ea89b1fde6e7b68955a3761eb6fdf45 --- examples/dft/pand_param.dft | 6 ++++++ examples/dft/tripple_pand.dft | 9 +++++++++ examples/dft/tripple_pand2.dft | 8 ++++++++ examples/dft/tripple_pand2_c.dft | 6 ++++++ examples/dft/tripple_pand_c.dft | 7 +++++++ src/builder/ExplicitDFTModelBuilder.cpp | 20 +++++++++++--------- 6 files changed, 47 insertions(+), 9 deletions(-) create mode 100644 examples/dft/pand_param.dft create mode 100644 examples/dft/tripple_pand.dft create mode 100644 examples/dft/tripple_pand2.dft create mode 100644 examples/dft/tripple_pand2_c.dft create mode 100644 examples/dft/tripple_pand_c.dft diff --git a/examples/dft/pand_param.dft b/examples/dft/pand_param.dft new file mode 100644 index 000000000..9a0b3d211 --- /dev/null +++ b/examples/dft/pand_param.dft @@ -0,0 +1,6 @@ +param x; +param y; +toplevel "A"; +"A" pand "B" "C"; +"B" lambda=x dorm=0.3; +"C" lambda=y dorm=0.3; diff --git a/examples/dft/tripple_pand.dft b/examples/dft/tripple_pand.dft new file mode 100644 index 000000000..7b38cf0f1 --- /dev/null +++ b/examples/dft/tripple_pand.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" pand "B" "BE4"; +"B" pand "C" "BE3"; +"C" pand "BE1" "BE2"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand2.dft b/examples/dft/tripple_pand2.dft new file mode 100644 index 000000000..4e6ef460f --- /dev/null +++ b/examples/dft/tripple_pand2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" pand "B" "C"; +"B" pand "BE1" "BE2"; +"C" pand "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand2_c.dft b/examples/dft/tripple_pand2_c.dft new file mode 100644 index 000000000..1c6001ea4 --- /dev/null +++ b/examples/dft/tripple_pand2_c.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" pand "BE1" "BE2" "BE3"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; + diff --git a/examples/dft/tripple_pand_c.dft b/examples/dft/tripple_pand_c.dft new file mode 100644 index 000000000..bfb8daa1c --- /dev/null +++ b/examples/dft/tripple_pand_c.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" pand "BE1" "BE2" "BE3" "BE4"; +"BE1" lambda=0.5 dorm=3; +"BE2" lambda=0.5 dorm=3; +"BE3" lambda=0.5 dorm=3; +"BE4" lambda=0.5 dorm=3; + diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index c0c596b02..0d37e795f 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -62,12 +62,8 @@ namespace storm { } } - // TODO Matthias: initialize - modelComponents.rewardModels; - modelComponents.choiceLabeling; - std::shared_ptr> model; - model = std::shared_ptr>(new storm::models::sparse::Ctmc(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.rewardModels), std::move(modelComponents.choiceLabeling))); + model = std::shared_ptr>(new storm::models::sparse::Ctmc(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling))); model->printModelInformationToStream(std::cout); return model; } @@ -149,10 +145,16 @@ namespace storm { } // Set transition - ValueType prob = nextBE.first->activeFailureRate(); - auto resultInsert = outgoingTransitions.insert(std::make_pair(it->getId(), prob)); - assert(resultInsert.second); - sum += prob; + ValueType rate = nextBE.first->activeFailureRate(); + auto resultFind = outgoingTransitions.find(it->getId()); + if (resultFind != outgoingTransitions.end()) { + // Add to existing transition + resultFind->second += rate; + } else { + // Insert new transition + outgoingTransitions.insert(std::make_pair(it->getId(), rate)); + } + sum += rate; } // end while failing BE // Add all transitions From e04cc99931728084194c2850641da1e41b6cc6a5 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 29 Jan 2016 10:28:38 +0100 Subject: [PATCH 035/246] Removed debug output Former-commit-id: ca149a082fc89dfdecfafe6514acd8f9e4f401da --- src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index 78f48a173..a8471c990 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -657,7 +657,6 @@ namespace storm { // Initialize rewards. std::vector totalRewardVector; for (size_t i = 0; i < exitRateVector.size(); ++i) { - std::cout << i << std::endl; if (targetStates[i]) { // Set reward for target states to 0. totalRewardVector.push_back(storm::utility::zero()); From 0775bdf549079030aa0b80de3cc4eb7357955e7c Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 29 Jan 2016 12:11:32 +0100 Subject: [PATCH 036/246] Disabled some debug output Former-commit-id: 31ae65f255efc625441e1f0a98ba08bdd00a3d14 --- examples/dft/voting.dft | 2 +- src/builder/ExplicitDFTModelBuilder.cpp | 1 - src/storm-dyftee.cpp | 5 ++--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/dft/voting.dft b/examples/dft/voting.dft index 6a5e82b3e..5c648d424 100644 --- a/examples/dft/voting.dft +++ b/examples/dft/voting.dft @@ -1,5 +1,5 @@ toplevel "A"; -"A" vot1 "B" "C" "D"; +"A" 1of3 "B" "C" "D"; "B" lambda=0.1 dorm=0; "C" lambda=0.2 dorm=0; "D" lambda=0.3 dorm=0; diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 0d37e795f..a203c93e8 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -99,7 +99,6 @@ namespace storm { storm::storage::DFTState newState(state); std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); if (nextBE.first == nullptr) { - std::cout << "break" << std::endl; break; } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index cf9922c47..c187e5057 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -31,10 +31,9 @@ void analyzeDFT(std::string filename, std::string property) { assert(formulas.size() == 1); std::unique_ptr resultCtmc(storm::verifySparseModel(model, formulas[0])); assert(resultCtmc); - std::cout << "Result (initial states): "; + std::cout << "Result: "; resultCtmc->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); std::cout << *resultCtmc << std::endl; - std::cout << "Checked CTMC" << std::endl; } /*! @@ -65,7 +64,7 @@ int main(int argc, char** argv) { } storm::utility::setUp(); - log4cplus::LogLevel level = log4cplus::TRACE_LOG_LEVEL; + log4cplus::LogLevel level = log4cplus::WARN_LOG_LEVEL; logger.setLogLevel(level); logger.getAppender("mainConsoleAppender")->setThreshold(level); From 8211b8091dadc355f7d380b4f88c8ad150b5d500 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 29 Jan 2016 13:31:17 +0100 Subject: [PATCH 037/246] Helpful comment Former-commit-id: 96bef1efb476b46b55422f99750644af54b269da --- src/storage/dft/DFTState.cpp | 4 +++- src/storage/dft/DFTState.h | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 98cada93a..e6e410760 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -83,7 +83,9 @@ namespace storm { { assert(index < mIsCurrentlyFailableBE.size()); STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); - std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); + // TODO set when implementing functional dependencies + bool dueToFdep = false; + std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), dueToFdep); mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); setFailed(res.first->id()); return res; diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 4f25550b0..b084e1a82 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -107,6 +107,11 @@ namespace storm { return mIsCurrentlyFailableBE.size(); } + /** + * Sets the next BE as failed + * @param smallestIndex Index in currentlyFailableBE of BE to fail + * @return Pair of BE which fails and flag indicating if the failure was due to functional dependencies + */ std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); std::string getCurrentlyFailableString() { From 4079a3f9cc2c228ae2730b3c7b80b1479f4506bc Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 29 Jan 2016 13:50:49 +0100 Subject: [PATCH 038/246] Refactoring Former-commit-id: ef3aa2c516c474f4e9d3444addc16a1887840c64 --- src/builder/ExplicitDFTModelBuilder.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index a203c93e8..107baa4bb 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -97,16 +97,16 @@ namespace storm { STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); storm::storage::DFTState newState(state); - std::pair>, bool> nextBE = newState.letNextBEFail(smallest++); - if (nextBE.first == nullptr) { + std::pair>, bool> nextBEPair = newState.letNextBEFail(smallest++); + std::shared_ptr> nextBE = nextBEPair.first; + if (nextBE == nullptr) { break; - } - STORM_LOG_TRACE("with the failure of: " << nextBE.first->name() << " [" << nextBE.first->id() << "]"); + STORM_LOG_TRACE("with the failure of: " << nextBE->name() << " [" << nextBE->id() << "]"); storm::storage::DFTStateSpaceGenerationQueues queues; - for (DFTGatePointer parent : nextBE.first->parents()) { + for (DFTGatePointer parent : nextBE->parents()) { if (newState.isOperational(parent->id())) { queues.propagateFailure(parent); } @@ -144,7 +144,7 @@ namespace storm { } // Set transition - ValueType rate = nextBE.first->activeFailureRate(); + ValueType rate = nextBE->activeFailureRate(); auto resultFind = outgoingTransitions.find(it->getId()); if (resultFind != outgoingTransitions.end()) { // Add to existing transition From a781df35c291e34c52ff443456fb65f7c76b73c2 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sun, 31 Jan 2016 17:21:13 +0100 Subject: [PATCH 039/246] Use passive failure rate if BE is not used Former-commit-id: fdc4a6687bb658f26585391e6d5ce7f811dabea0 --- src/builder/ExplicitDFTModelBuilder.cpp | 21 +++++++++++++-------- src/storage/dft/DFT.cpp | 9 +++++---- src/storage/dft/DFT.h | 9 +++++++++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 107baa4bb..811d0fdcb 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -127,31 +127,36 @@ namespace storm { next->checkDontCareAnymore(newState, queues); } - auto it = mStates.find(newState); - if (it == mStates.end()) { + auto itState = mStates.find(newState); + if (itState == mStates.end()) { // New state newState.setId(newIndex++); auto itInsert = mStates.insert(newState); assert(itInsert.second); - it = itInsert.first; + itState = itInsert.first; STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); // Add state to search stateQueue.push(newState); } else { // State already exists - STORM_LOG_TRACE("State " << mDft.getStateString(*it) << " already exists"); + STORM_LOG_TRACE("State " << mDft.getStateString(*itState) << " already exists"); } - // Set transition - ValueType rate = nextBE->activeFailureRate(); - auto resultFind = outgoingTransitions.find(it->getId()); + // Set failure rate according to usage + bool isUsed = true; + if (mDft.hasRepresentant(nextBE->id())) { + isUsed = newState.isUsed(nextBE->id()); + } + STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); + ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); + auto resultFind = outgoingTransitions.find(itState->getId()); if (resultFind != outgoingTransitions.end()) { // Add to existing transition resultFind->second += rate; } else { // Insert new transition - outgoingTransitions.insert(std::make_pair(it->getId(), rate)); + outgoingTransitions.insert(std::make_pair(itState->getId(), rate)); } sum += rate; } // end while failing BE diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 0b8c99685..ae4ec62eb 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -29,6 +29,7 @@ namespace storm { for(auto const& modelem : module) { if(mElements[modelem]->isSpareGate() || mElements[modelem]->isBasicElement()) { sparesAndBes.push_back(modelem); + mRepresentants.insert(std::make_pair(modelem, spareReprs->id())); } } mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); @@ -131,12 +132,12 @@ namespace storm { stream << "(" << state.getId() << ") "; for (auto const& elem : mElements) { stream << state.getElementStateInt(elem->id()); - /*if(elem->isSpareGate()) { + if(elem->isSpareGate()) { if(state.isActiveSpare(elem->id())) { - os << " actively"; + stream << " actively"; } - os << " using " << state.uses(elem->id()); - }*/ + stream << " using " << state.uses(elem->id()); + } } return stream.str(); } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 0f39e3ddc..17d6c7fd5 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -50,6 +50,7 @@ namespace storm { std::vector mTopModule; std::vector mIdToFailureIndex; std::map mUsageIndex; + std::map mRepresentants; public: DFT(DFTElementVector const& elements, DFTElementPointer const& tle); @@ -154,6 +155,14 @@ namespace storm { return elements; } + bool hasRepresentant(size_t id) const { + return mRepresentants.find(id) != mRepresentants.end(); + } + + DFTElementPointer getRepresentant(size_t id) const { + assert(hasRepresentant(id)); + return getElement(mRepresentants.find(id)->second); + } bool hasFailed(DFTState const& state) const { return state.hasFailed(mTopLevelIndex); From ed6d299d464d01345fedcf5e2def7b2a6db3b360 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 1 Feb 2016 10:57:40 +0100 Subject: [PATCH 040/246] Benchmark script for DFTs Former-commit-id: 574c46528ec97bfd5883e51246e6c7a2d93f3c85 --- benchmark_dft.py | 107 ++++++++++++++++++++++++++++++++++ examples/dft/spare5.dft | 9 +++ examples/dft/spare6.dft | 7 +++ examples/dft/tripple_and2.dft | 6 +- 4 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 benchmark_dft.py create mode 100644 examples/dft/spare5.dft create mode 100644 examples/dft/spare6.dft diff --git a/benchmark_dft.py b/benchmark_dft.py new file mode 100644 index 000000000..54fb06593 --- /dev/null +++ b/benchmark_dft.py @@ -0,0 +1,107 @@ +import os +import os.path +import subprocess +import re +import time +import math + +STORM_PATH= "/Users/mvolk/develop/storm/build/src/storm-dft" +EXAMPLE_DIR= "/Users/mvolk/develop/storm/examples/dft/" + + +benchmarks = [ + ("and", False, 3), + ("and_param", True, "(4*x^2+2*x+1)/((x) * (2*x+1))"), + ("cm2", False, 0.256272), + #("cm4", False, 0), + ("cps", False, "inf"), + #("fdep", False, 0), + ("mdcs", False, 2.85414), + ("mdcs2", False, 2.85414), + ("mp", False, 1.66667), + ("or", False, 1), + ("pand", False, "inf"), + ("pand_param", True, "-1"), + ("spare", False, 3.53846), + ("spare2", False, 1.86957), + ("spare3", False, 1.27273), + ("spare4", False, 4.8459), + ("spare5", False, 2.16667), + ("spare6", False, 1.4), + ("tripple_and1", False, 4.16667), + ("tripple_and2", False, 3.66667), + ("tripple_and2_c", False, 3.6667), + ("tripple_and_c", False, 4.16667), + ("tripple_or", False, 0.5), + ("tripple_or2", False, 0.666667), + ("tripple_or2_c", False, 0.66667), + ("tripple_or_c", False, 0.5), + ("tripple_pand", False, "inf"), + ("tripple_pand2", False, "inf"), + ("tripple_pand2_c", False, "inf"), + ("tripple_pand_c", False, "inf"), + ("voting", False, 1.66667), + ("voting2", False, 0.588235) +] + +def run_storm_dft(filename, parametric, quiet): + # Run storm-dft on filename and return result + prop = "ET=? [F \"failed\"]" + dft_file = os.path.join(EXAMPLE_DIR, filename + ".dft") + args = [STORM_PATH, + dft_file, + '--prop', prop] + if parametric: + args.append('--parametric') + + output = run_tool(args, quiet) + # Get result + match = re.search(r'Result: \[(.*)\]', output) + if not match: + print("No valid result found in: " + output) + return + + result = match.group(1) + return result + +def run_tool(args, quiet=False): + """ + Executes a process, + :returns: the `stdout` + """ + pipe = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + result = ""; + for line in iter(pipe.stdout.readline, ""): + if not line and pipe.poll() is not None: + break + output = line.decode(encoding='UTF-8').rstrip() + if output != "": + if not quiet: + print("\t * " + output) + result = output + return result + +if __name__ == "__main__": + count = 0 + correct = 0 + start = time.time() + for (benchmark, parametric, result_original) in benchmarks: + # Run benchmark and check result + count += 1; + print("Running '{}'".format(benchmark)) + result = run_storm_dft(benchmark, parametric, True) + if not parametric: + # Float + result = float(result) + if not math.isclose(result, float(result_original), rel_tol=1e-05): + print("!!! File '{}': result: {}, Expected: {}".format(benchmark, result, result_original)) + else: + correct += 1 + else: + # Parametric + if result != result_original: + print("!!! File {}: result: {}, Expected: {}".format(benchmark, result, result_original)) + else: + correct += 1 + end = time.time() + print("Correct results for {} of {} DFTs in {}s".format(correct, count, end-start)) diff --git a/examples/dft/spare5.dft b/examples/dft/spare5.dft new file mode 100644 index 000000000..dcb4d80a4 --- /dev/null +++ b/examples/dft/spare5.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" wsp "I" "B"; +"B" or "K" "J"; +"C" or "K" "L"; +"I" lambda=0.5 dorm=0; +"J" lambda=0.5 dorm=0; +"K" lambda=0.5 dorm=0; +"L" lambda=0.5 dorm=0; + diff --git a/examples/dft/spare6.dft b/examples/dft/spare6.dft new file mode 100644 index 000000000..d5f2b270b --- /dev/null +++ b/examples/dft/spare6.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" or "I" "B"; +"B" wsp "J" "M"; +"I" lambda=0.5 dorm=0.5; +"J" lambda=0.5 dorm=0.5; +"M" lambda=0.5 dorm=0.5; + diff --git a/examples/dft/tripple_and2.dft b/examples/dft/tripple_and2.dft index 9e02d88e7..382c1657d 100644 --- a/examples/dft/tripple_and2.dft +++ b/examples/dft/tripple_and2.dft @@ -2,7 +2,7 @@ toplevel "A"; "A" and "B" "C"; "B" and "BE1" "BE2"; "C" and "BE2" "BE3"; -"BE1" lambda=0.5 dorm=3; -"BE2" lambda=0.5 dorm=3; -"BE3" lambda=0.5 dorm=3; +"BE1" lambda=0.5 dorm=0.3; +"BE2" lambda=0.5 dorm=0.3; +"BE3" lambda=0.5 dorm=0.3; From 0a21431c075caff5d51a487673cfaf7a598e7eff Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 1 Feb 2016 11:00:00 +0100 Subject: [PATCH 041/246] Use representant for usage flag in DFTBuilder Former-commit-id: 9084ce2f2f43492f60527f9ea66b0c60feed35bd --- src/builder/ExplicitDFTModelBuilder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 811d0fdcb..10534d0a5 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -146,7 +146,8 @@ namespace storm { // Set failure rate according to usage bool isUsed = true; if (mDft.hasRepresentant(nextBE->id())) { - isUsed = newState.isUsed(nextBE->id()); + DFTElementPointer representant = mDft.getRepresentant(nextBE->id()); + isUsed = newState.isUsed(representant->id()); } STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); From 2e8f74a70090ac7754de88845bb762a6158abf80 Mon Sep 17 00:00:00 2001 From: dehnert Date: Mon, 1 Feb 2016 14:51:34 +0100 Subject: [PATCH 042/246] First steps toward exact linear equation solver Former-commit-id: 669af13b84574d35c6df40e16ca8a007ed303dc4 --- src/adapters/CarlAdapter.h | 9 +- .../EliminationLinearEquationSolver.cpp | 62 +++++++++++++ src/solver/EliminationLinearEquationSolver.h | 34 +++++++ src/solver/NativeLinearEquationSolver.h | 2 +- src/storage/FlexibleSparseMatrix.cpp | 88 +++++++++++++++++++ src/storage/FlexibleSparseMatrix.h | 65 ++++++++++++++ .../expressions/ToRationalFunctionVisitor.cpp | 4 +- src/utility/vector.h | 2 +- 8 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 src/solver/EliminationLinearEquationSolver.cpp create mode 100644 src/solver/EliminationLinearEquationSolver.h create mode 100644 src/storage/FlexibleSparseMatrix.cpp create mode 100644 src/storage/FlexibleSparseMatrix.h diff --git a/src/adapters/CarlAdapter.h b/src/adapters/CarlAdapter.h index 2ed172cde..093ea6ae7 100644 --- a/src/adapters/CarlAdapter.h +++ b/src/adapters/CarlAdapter.h @@ -4,6 +4,8 @@ // Include config to know whether CARL is available or not. #include "storm-config.h" +#include + #ifdef STORM_HAVE_CARL #include @@ -42,9 +44,12 @@ namespace carl { } namespace storm { - typedef cln::cl_RA RationalNumber; +// typedef boost::multiprecision::gmp_rational RationalNumber; + typedef mpq_class RationalNumber; + + typedef cln::cl_RA CarlRationalNumber; typedef carl::Variable Variable; - typedef carl::MultivariatePolynomial RawPolynomial; + typedef carl::MultivariatePolynomial RawPolynomial; typedef carl::FactorizedPolynomial Polynomial; typedef carl::Relation CompareRelation; diff --git a/src/solver/EliminationLinearEquationSolver.cpp b/src/solver/EliminationLinearEquationSolver.cpp new file mode 100644 index 000000000..67a281b70 --- /dev/null +++ b/src/solver/EliminationLinearEquationSolver.cpp @@ -0,0 +1,62 @@ +#include "src/solver/EliminationLinearEquationSolver.h" + +#include "src/utility/vector.h" + +namespace storm { + namespace solver { + template + EliminationLinearEquationSolver::EliminationLinearEquationSolver(storm::storage::SparseMatrix const& A) : A(A) { + // Intentionally left empty. + } + + template + void EliminationLinearEquationSolver::solveEquationSystem(std::vector& x, std::vector const& b, std::vector* multiplyResult) const { + // TODO: implement state-elimination here. + } + + template + void EliminationLinearEquationSolver::performMatrixVectorMultiplication(std::vector& x, std::vector const* b, uint_fast64_t n, std::vector* multiplyResult) const { + // Set up some temporary variables so that we can just swap pointers instead of copying the result after + // each iteration. + std::vector* currentX = &x; + + bool multiplyResultProvided = true; + std::vector* nextX = multiplyResult; + if (nextX == nullptr) { + nextX = new std::vector(x.size()); + multiplyResultProvided = false; + } + std::vector const* copyX = nextX; + + // Now perform matrix-vector multiplication as long as we meet the bound. + for (uint_fast64_t i = 0; i < n; ++i) { + A.multiplyWithVector(*currentX, *nextX); + std::swap(nextX, currentX); + + // If requested, add an offset to the current result vector. + if (b != nullptr) { + storm::utility::vector::addVectors(*currentX, *b, *currentX); + } + } + + // If we performed an odd number of repetitions, we need to swap the contents of currentVector and x, + // because the output is supposed to be stored in the input vector x. + if (currentX == copyX) { + std::swap(x, *currentX); + } + + // If the vector for the temporary multiplication result was not provided, we need to delete it. + if (!multiplyResultProvided) { + delete copyX; + } + } + + template class EliminationLinearEquationSolver; + + // TODO: make this work with the proper implementation of solveEquationSystem. + template class EliminationLinearEquationSolver; + template class EliminationLinearEquationSolver; + + } +} + diff --git a/src/solver/EliminationLinearEquationSolver.h b/src/solver/EliminationLinearEquationSolver.h new file mode 100644 index 000000000..25dffa651 --- /dev/null +++ b/src/solver/EliminationLinearEquationSolver.h @@ -0,0 +1,34 @@ +#ifndef STORM_SOLVER_ELIMINATIONLINEAREQUATIONSOLVER_H_ +#define STORM_SOLVER_ELIMINATIONLINEAREQUATIONSOLVER_H_ + +#include "src/solver/LinearEquationSolver.h" + +namespace storm { + namespace solver { + /*! + * A class that uses gaussian elimination to implement the LinearEquationSolver interface. In particular + */ + template + class EliminationLinearEquationSolver : public LinearEquationSolver { + public: + + /*! + * Constructs a linear equation solver. + * + * @param A The matrix defining the coefficients of the linear equation system. + */ + EliminationLinearEquationSolver(storm::storage::SparseMatrix const& A); + + virtual void solveEquationSystem(std::vector& x, std::vector const& b, std::vector* multiplyResult = nullptr) const override; + + virtual void performMatrixVectorMultiplication(std::vector& x, std::vector const* b, uint_fast64_t n = 1, std::vector* multiplyResult = nullptr) const override; + + private: + // A reference to the original matrix used for this equation solver. + storm::storage::SparseMatrix const& A; + + }; + } +} + +#endif /* STORM_SOLVER_ELIMINATIONLINEAREQUATIONSOLVER_H_ */ \ No newline at end of file diff --git a/src/solver/NativeLinearEquationSolver.h b/src/solver/NativeLinearEquationSolver.h index 6fa972f05..42dbbd3d9 100644 --- a/src/solver/NativeLinearEquationSolver.h +++ b/src/solver/NativeLinearEquationSolver.h @@ -10,6 +10,7 @@ namespace storm { enum class NativeLinearEquationSolverSolutionMethod { Jacobi, GaussSeidel, SOR }; + /*! * A class that uses StoRM's native matrix operations to implement the LinearEquationSolver interface. */ @@ -17,7 +18,6 @@ namespace storm { class NativeLinearEquationSolver : public LinearEquationSolver { public: - /*! * Constructs a linear equation solver with parameters being set according to the settings object. * diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp new file mode 100644 index 000000000..b77f59736 --- /dev/null +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -0,0 +1,88 @@ +#include "src/storage/FlexibleSparseMatrix.h" + +#include "src/storage/SparseMatrix.h" +#include "src/storage/BitVector.h" + +namespace storm { + namespace storage { + template + FlexibleSparseMatrix::FlexibleSparseMatrix(index_type rows) : data(rows) { + // Intentionally left empty. + } + + template + void FlexibleSparseMatrix::reserveInRow(index_type row, index_type numberOfElements) { + this->data[row].reserve(numberOfElements); + } + + template + typename FlexibleSparseMatrix::row_type& FlexibleSparseMatrix::getRow(index_type index) { + return this->data[index]; + } + + template + typename FlexibleSparseMatrix::row_type const& FlexibleSparseMatrix::getRow(index_type index) const { + return this->data[index]; + } + + template + typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getNumberOfRows() const { + return this->data.size(); + } + + template + bool FlexibleSparseMatrix::hasSelfLoop(storm::storage::sparse::state_type state) { + for (auto const& entry : this->getRow(state)) { + if (entry.getColumn() < state) { + continue; + } else if (entry.getColumn() > state) { + return false; + } else if (entry.getColumn() == state) { + return true; + } + } + return false; + } + + template + void FlexibleSparseMatrix::print() const { + for (uint_fast64_t index = 0; index < this->data.size(); ++index) { + std::cout << index << " - "; + for (auto const& element : this->getRow(index)) { + std::cout << "(" << element.getColumn() << ", " << element.getValue() << ") "; + } + std::cout << std::endl; + } + } + + template + bool FlexibleSparseMatrix::empty() const { + for (auto const& row : this->data) { + if (!row.empty()) { + return false; + } + } + return true; + } + + template + void FlexibleSparseMatrix::filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter) { + for (uint_fast64_t rowIndex = 0; rowIndex < this->data.size(); ++rowIndex) { + auto& row = this->data[rowIndex]; + if (!rowFilter.get(rowIndex)) { + row.clear(); + row.shrink_to_fit(); + continue; + } + row_type newRow; + for (auto const& element : row) { + if (columnFilter.get(element.getColumn())) { + newRow.push_back(element); + } + } + row = std::move(newRow); + } + } + + } +} \ No newline at end of file diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h new file mode 100644 index 000000000..6a30109ac --- /dev/null +++ b/src/storage/FlexibleSparseMatrix.h @@ -0,0 +1,65 @@ +#ifndef STORM_STORAGE_FLEXIBLESPARSEMATRIX_H_ +#define STORM_STORAGE_FLEXIBLESPARSEMATRIX_H_ + +#include +#include + +#include "src/storage/sparse/StateType.h" + +namespace storm { + namespace storage { + template + class MatrixEntry; + + class BitVector; + + template + class FlexibleSparseMatrix { + public: + // TODO: make this class a bit more consistent with the big sparse matrix and improve it: + // * rename getNumberOfRows -> getRowCount + // * store number of columns to also provide getColumnCount + // * rename hasSelfLoop -> rowHasDiagonalElement + // * add output iterator and improve the way the matrix is printed + // * add conversion functionality from/to sparse matrix + // * add documentation + // * rename filter to something more appropriate (getSubmatrix?) + // * add stuff like clearRow, multiplyRowWithScalar + + typedef uint_fast64_t index_type; + typedef ValueType value_type; + typedef std::vector> row_type; + typedef typename row_type::iterator iterator; + typedef typename row_type::const_iterator const_iterator; + + FlexibleSparseMatrix() = default; + FlexibleSparseMatrix(index_type rows); + + void reserveInRow(index_type row, index_type numberOfElements); + + row_type& getRow(index_type); + row_type const& getRow(index_type) const; + + index_type getNumberOfRows() const; + + void print() const; + + bool empty() const; + + void filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter); + + /*! + * Checks whether the given state has a self-loop with an arbitrary probability in the probability matrix. + * + * @param state The state for which to check whether it possesses a self-loop. + * @return True iff the given state has a self-loop with an arbitrary probability in the probability matrix. + */ + bool hasSelfLoop(storm::storage::sparse::state_type state); + + private: + std::vector data; + }; + } +} + +#endif /* STORM_STORAGE_FLEXIBLESPARSEMATRIX_H_ */ \ No newline at end of file diff --git a/src/storage/expressions/ToRationalFunctionVisitor.cpp b/src/storage/expressions/ToRationalFunctionVisitor.cpp index 97501aa1b..5e0ebcd64 100644 --- a/src/storage/expressions/ToRationalFunctionVisitor.cpp +++ b/src/storage/expressions/ToRationalFunctionVisitor.cpp @@ -88,12 +88,12 @@ namespace storm { template boost::any ToRationalFunctionVisitor::visit(IntegerLiteralExpression const& expression) { - return RationalFunctionType(carl::rationalize(static_cast(expression.getValue()))); + return RationalFunctionType(carl::rationalize(static_cast(expression.getValue()))); } template boost::any ToRationalFunctionVisitor::visit(DoubleLiteralExpression const& expression) { - return RationalFunctionType(carl::rationalize(expression.getValue())); + return RationalFunctionType(carl::rationalize(expression.getValue())); } template class ToRationalFunctionVisitor; diff --git a/src/utility/vector.h b/src/utility/vector.h index 665569645..a4e551efa 100644 --- a/src/utility/vector.h +++ b/src/utility/vector.h @@ -269,7 +269,7 @@ namespace storm { * @param target The target vector. */ template - void applyPointwise(std::vector const& firstOperand, std::vector const& secondOperand, std::vector& target, std::function function) { + void applyPointwise(std::vector const& firstOperand, std::vector const& secondOperand, std::vector& target, std::function const& function) { #ifdef STORM_HAVE_INTELTBB tbb::parallel_for(tbb::blocked_range(0, target.size()), [&](tbb::blocked_range const& range) { From 4eaf8f84433f521d2fbf72d97ae46d1577a8058f Mon Sep 17 00:00:00 2001 From: dehnert Date: Mon, 1 Feb 2016 16:18:11 +0100 Subject: [PATCH 043/246] changed ration number to the boost version again (this time in the correct version) Former-commit-id: 2c97e6e43ecc52dc93bd9e0c525a6689fd56f9c2 --- src/adapters/CarlAdapter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/CarlAdapter.h b/src/adapters/CarlAdapter.h index 093ea6ae7..4fd2a98a0 100644 --- a/src/adapters/CarlAdapter.h +++ b/src/adapters/CarlAdapter.h @@ -45,7 +45,7 @@ namespace carl { namespace storm { // typedef boost::multiprecision::gmp_rational RationalNumber; - typedef mpq_class RationalNumber; + typedef boost::multiprecision::number RationalNumber; typedef cln::cl_RA CarlRationalNumber; typedef carl::Variable Variable; From dd17955a3e752f219a2d432d8f5d71b564ff29e0 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 1 Feb 2016 18:36:43 +0100 Subject: [PATCH 044/246] Added functionality to BitVectorHashMap Former-commit-id: 0d1fa18d16f5a5c9459de99d7516e24a04654961 --- src/storage/BitVectorHashMap.cpp | 5 +++++ src/storage/BitVectorHashMap.h | 8 ++++++++ src/storage/dft/DFTState.cpp | 2 +- src/storage/dft/DFTState.h | 6 +++--- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/storage/BitVectorHashMap.cpp b/src/storage/BitVectorHashMap.cpp index c184b764b..9237dfde3 100644 --- a/src/storage/BitVectorHashMap.cpp +++ b/src/storage/BitVectorHashMap.cpp @@ -168,6 +168,11 @@ namespace storm { return values[flagBucketPair.second]; } + template + bool BitVectorHashMap::contains(storm::storage::BitVector const& key) const { + return findBucket(key).first; + } + template typename BitVectorHashMap::const_iterator BitVectorHashMap::begin() const { return const_iterator(*this, occupied.begin()); diff --git a/src/storage/BitVectorHashMap.h b/src/storage/BitVectorHashMap.h index 3b0c7aa70..d50dac59e 100644 --- a/src/storage/BitVectorHashMap.h +++ b/src/storage/BitVectorHashMap.h @@ -95,6 +95,14 @@ namespace storm { */ ValueType getValue(storm::storage::BitVector const& key) const; + /*! + * Checks if the given key is already contained in the map. + * + * @param key The key to search + * @return True if the key is already contained in the map + */ + bool contains(storm::storage::BitVector const& key) const; + /*! * Retrieves an iterator to the elements of the map. * diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index e6e410760..ebf3c770b 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -123,7 +123,7 @@ namespace storm { } template - bool DFTState::isUsed(size_t child) { + bool DFTState::isUsed(size_t child) const { return (std::find(mUsedRepresentants.begin(), mUsedRepresentants.end(), child) != mUsedRepresentants.end()); } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index b084e1a82..4ea11a991 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -61,7 +61,7 @@ namespace storm { mValid = false; } - bool isInvalid() { + bool isInvalid() const { return !mValid; } @@ -88,7 +88,7 @@ namespace storm { * @param child The id of the child for which we want to know whether it is currently used. * @return true iff it is currently used by any of the spares. */ - bool isUsed(size_t child); + bool isUsed(size_t child) const; /** * Sets to to the usageIndex which child is now used. @@ -114,7 +114,7 @@ namespace storm { */ std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); - std::string getCurrentlyFailableString() { + std::string getCurrentlyFailableString() const { std::stringstream stream; auto it = mIsCurrentlyFailableBE.begin(); stream << "{"; From 69a464d5ef6d3ed3187b3291f8acfd25560e9c5a Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 1 Feb 2016 18:45:18 +0100 Subject: [PATCH 045/246] Changed unordered_set to BitVectorHashMap for DFTState Former-commit-id: 35f57aa25040796690fadc21d764f53efb103be4 --- src/builder/ExplicitDFTModelBuilder.cpp | 66 ++++++++++++------------- src/builder/ExplicitDFTModelBuilder.h | 11 +++-- src/storage/BitVectorHashMap.cpp | 7 +++ src/storage/dft/DFT.cpp | 18 +++---- src/storage/dft/DFT.h | 13 ++--- 5 files changed, 63 insertions(+), 52 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 10534d0a5..1b777fb54 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -14,10 +14,10 @@ namespace storm { template std::shared_ptr> ExplicitDFTModelBuilder::buildCTMC() { // Initialize - storm::storage::DFTState state(mDft, newIndex++); - mStates.insert(state); + DFTStatePointer state = std::make_shared>(mDft, newIndex++); + mStates.findOrAdd(state->status(), state); - std::queue> stateQueue; + std::queue stateQueue; stateQueue.push(state); bool deterministicModel = true; @@ -47,17 +47,18 @@ namespace storm { modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); } - for (storm::storage::DFTState state : mStates) { + for (auto const& stateVectorPair : mStates) { + DFTStatePointer state = stateVectorPair.second; if (mDft.hasFailed(state)) { - modelComponents.stateLabeling.addLabelToState("failed", state.getId()); + modelComponents.stateLabeling.addLabelToState("failed", state->getId()); } if (mDft.isFailsafe(state)) { - modelComponents.stateLabeling.addLabelToState("failsafe", state.getId()); + modelComponents.stateLabeling.addLabelToState("failsafe", state->getId()); }; // Set fail status for each BE for (std::shared_ptr> elem : basicElements) { - if (state.hasFailed(elem->id())) { - modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", state.getId()); + if (state->hasFailed(elem->id())) { + modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", state->getId()); } } } @@ -69,7 +70,7 @@ namespace storm { } template - void ExplicitDFTModelBuilder::exploreStates(std::queue>& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { + void ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { std::map outgoingTransitions; @@ -79,25 +80,26 @@ namespace storm { ValueType sum = storm::utility::zero(); // Consider next state - storm::storage::DFTState state = stateQueue.front(); + DFTStatePointer state = stateQueue.front(); stateQueue.pop(); size_t smallest = 0; // Add self loop for target states if (mDft.hasFailed(state) || mDft.isFailsafe(state)) { - transitionMatrixBuilder.addNextValue(state.getId(), state.getId(), storm::utility::one()); - STORM_LOG_TRACE("Added self loop for " << state.getId()); + transitionMatrixBuilder.addNextValue(state->getId(), state->getId(), storm::utility::one()); + STORM_LOG_TRACE("Added self loop for " << state->getId()); // No further exploration required continue; } // Let BE fail - while (smallest < state.nrFailableBEs()) { + while (smallest < state->nrFailableBEs()) { STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); - storm::storage::DFTState newState(state); - std::pair>, bool> nextBEPair = newState.letNextBEFail(smallest++); + // Construct new state as copy from original one + DFTStatePointer newState = std::make_shared>(*state); + std::pair>, bool> nextBEPair = newState->letNextBEFail(smallest++); std::shared_ptr> nextBE = nextBEPair.first; if (nextBE == nullptr) { break; @@ -107,57 +109,55 @@ namespace storm { storm::storage::DFTStateSpaceGenerationQueues queues; for (DFTGatePointer parent : nextBE->parents()) { - if (newState.isOperational(parent->id())) { + if (newState->isOperational(parent->id())) { queues.propagateFailure(parent); } } while (!queues.failurePropagationDone()) { DFTGatePointer next = queues.nextFailurePropagation(); - next->checkFails(newState, queues); + next->checkFails(*newState, queues); } while (!queues.failsafePropagationDone()) { DFTGatePointer next = queues.nextFailsafePropagation(); - next->checkFailsafe(newState, queues); + next->checkFailsafe(*newState, queues); } while (!queues.dontCarePropagationDone()) { DFTElementPointer next = queues.nextDontCarePropagation(); - next->checkDontCareAnymore(newState, queues); + next->checkDontCareAnymore(*newState, queues); } - auto itState = mStates.find(newState); - if (itState == mStates.end()) { + if (mStates.contains(newState->status())) { + // State already exists + newState = mStates.findOrAdd(newState->status(), newState); + STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " already exists"); + } else { // New state - newState.setId(newIndex++); - auto itInsert = mStates.insert(newState); - assert(itInsert.second); - itState = itInsert.first; + newState->setId(newIndex++); + mStates.findOrAdd(newState->status(), newState); STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); // Add state to search stateQueue.push(newState); - } else { - // State already exists - STORM_LOG_TRACE("State " << mDft.getStateString(*itState) << " already exists"); } // Set failure rate according to usage bool isUsed = true; if (mDft.hasRepresentant(nextBE->id())) { DFTElementPointer representant = mDft.getRepresentant(nextBE->id()); - isUsed = newState.isUsed(representant->id()); + isUsed = newState->isUsed(representant->id()); } STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); - auto resultFind = outgoingTransitions.find(itState->getId()); + auto resultFind = outgoingTransitions.find(newState->getId()); if (resultFind != outgoingTransitions.end()) { // Add to existing transition resultFind->second += rate; } else { // Insert new transition - outgoingTransitions.insert(std::make_pair(itState->getId(), rate)); + outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); } sum += rate; } // end while failing BE @@ -167,8 +167,8 @@ namespace storm { { // TODO Matthias: correct? ValueType rate = it->second;// / sum; - transitionMatrixBuilder.addNextValue(state.getId(), it->first, rate); - STORM_LOG_TRACE("Added transition from " << state.getId() << " to " << it->first << " with " << rate); + transitionMatrixBuilder.addNextValue(state->getId(), it->first, rate); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << it->first << " with " << rate); } } // end while queue diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 8148559c3..ed02e60d4 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ namespace storm { using DFTElementPointer = std::shared_ptr>; using DFTGatePointer = std::shared_ptr>; + using DFTStatePointer = std::shared_ptr>; // A structure holding the individual components of a model. struct ModelComponents { @@ -39,18 +41,19 @@ namespace storm { }; storm::storage::DFT const &mDft; - std::unordered_set> mStates; + storm::storage::BitVectorHashMap mStates; size_t newIndex = 0; public: - ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft) { - + ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft), mStates(((mDft.stateSize() / 64) + 1) * 64, std::pow(2, mDft.nrBasicElements())) { + // stateSize is bound for size of bitvector + // 2^nrBE is upper bound for state space } std::shared_ptr> buildCTMC(); private: - void exploreStates(std::queue>& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); + void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); }; } diff --git a/src/storage/BitVectorHashMap.cpp b/src/storage/BitVectorHashMap.cpp index 9237dfde3..be0e32325 100644 --- a/src/storage/BitVectorHashMap.cpp +++ b/src/storage/BitVectorHashMap.cpp @@ -4,6 +4,9 @@ #include "src/utility/macros.h" +#include "src/storage/dft/DFTState.h" +#include "src/adapters/CarlAdapter.h" + namespace storm { namespace storage { template @@ -240,5 +243,9 @@ namespace storm { template class BitVectorHashMap; template class BitVectorHashMap; + template class BitVectorHashMap>>; +#ifdef STORM_HAVE_CARL + template class BitVectorHashMap>>; +#endif } } diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index ae4ec62eb..c36f0a9e0 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -109,17 +109,17 @@ namespace storm { } template - std::string DFT::getElementsWithStateString(DFTState const& state) const{ + std::string DFT::getElementsWithStateString(DFTStatePointer const& state) const{ std::stringstream stream; for (auto const& elem : mElements) { stream << "[" << elem->id() << "]"; stream << elem->toString(); - stream << "\t** " << state.getElementState(elem->id()); + stream << "\t** " << state->getElementState(elem->id()); if(elem->isSpareGate()) { - if(state.isActiveSpare(elem->id())) { + if(state->isActiveSpare(elem->id())) { stream << " actively"; } - stream << " using " << state.uses(elem->id()); + stream << " using " << state->uses(elem->id()); } stream << std::endl; } @@ -127,16 +127,16 @@ namespace storm { } template - std::string DFT::getStateString(DFTState const& state) const{ + std::string DFT::getStateString(DFTStatePointer const& state) const{ std::stringstream stream; - stream << "(" << state.getId() << ") "; + stream << "(" << state->getId() << ") "; for (auto const& elem : mElements) { - stream << state.getElementStateInt(elem->id()); + stream << state->getElementStateInt(elem->id()); if(elem->isSpareGate()) { - if(state.isActiveSpare(elem->id())) { + if(state->isActiveSpare(elem->id())) { stream << " actively"; } - stream << " using " << state.uses(elem->id()); + stream << " using " << state->uses(elem->id()); } } return stream.str(); diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 17d6c7fd5..81cfdf99b 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -37,6 +37,7 @@ namespace storm { using DFTElementVector = std::vector; using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; + using DFTStatePointer = std::shared_ptr>; private: DFTElementVector mElements; @@ -164,12 +165,12 @@ namespace storm { return getElement(mRepresentants.find(id)->second); } - bool hasFailed(DFTState const& state) const { - return state.hasFailed(mTopLevelIndex); + bool hasFailed(DFTStatePointer const& state) const { + return state->hasFailed(mTopLevelIndex); } - bool isFailsafe(DFTState const& state) const { - return state.isFailsafe(mTopLevelIndex); + bool isFailsafe(DFTStatePointer const& state) const { + return state->isFailsafe(mTopLevelIndex); } std::string getElementsString() const; @@ -178,9 +179,9 @@ namespace storm { std::string getSpareModulesString() const; - std::string getElementsWithStateString(DFTState const& state) const; + std::string getElementsWithStateString(DFTStatePointer const& state) const; - std::string getStateString(DFTState const& state) const; + std::string getStateString(DFTStatePointer const& state) const; private: bool elementIndicesCorrect() const { From b55cc3276e245e5b77d784074054e251723589df Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 3 Feb 2016 18:04:14 +0100 Subject: [PATCH 046/246] Reachability probabilities for CTMCs Former-commit-id: fad855c59abe578f6945e2adc3fc553d3a332016 --- .../csl/SparseCtmcCslModelChecker.cpp | 2 +- .../csl/helper/SparseCtmcCslHelper.cpp | 35 +++++++++++-- .../csl/helper/SparseCtmcCslHelper.h | 4 +- .../SparseDtmcEliminationModelChecker.cpp | 50 +++++++++++-------- .../SparseDtmcEliminationModelChecker.h | 7 +++ src/utility/storm.h | 44 ++++++++++++++-- 6 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp index a9b86d8c8..b7e42e1db 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -108,7 +108,7 @@ namespace storm { std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), this->getModel().getInitialStates(), subResult.getTruthValuesVector(), qualitative/*, *linearEquationSolverFactory*/); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), this->getModel().getInitialStates(), subResult.getTruthValuesVector(), qualitative, *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index a8471c990..ae656b5ee 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -195,6 +195,12 @@ namespace storm { return SparseDtmcPrctlHelper::computeUntilProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, phiStates, psiStates, qualitative, linearEquationSolverFactory); } + template + std::vector SparseCtmcCslHelper::computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative) { + // Use "normal" function again, if RationalFunction finally is supported. + return storm::modelchecker::SparseDtmcEliminationModelChecker>::computeUntilProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), backwardTransitions, initialStates, phiStates, psiStates, false); + } + template std::vector SparseCtmcCslHelper::computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { return SparseDtmcPrctlHelper::computeNextProbabilities(computeProbabilityMatrix(rateMatrix, exitRateVector), nextStates, linearEquationSolverFactory); @@ -648,9 +654,31 @@ namespace storm { return result; } + + template + std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + // Compute expected time on CTMC by reduction to DTMC with rewards. + storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); + + // Initialize rewards. + std::vector totalRewardVector; + for (size_t i = 0; i < exitRateVector.size(); ++i) { + if (targetStates[i]) { + // Set reward for target states to 0. + totalRewardVector.push_back(storm::utility::zero()); + } else { + // Reward is (1 / exitRate). + totalRewardVector.push_back(storm::utility::one() / exitRateVector[i]); + } + } + + return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); + } + template - std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory*/) { + std::vector SparseCtmcCslHelper::computeExpectedTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative) { + // Use "normal" function again, if RationalFunction finally is supported. // Compute expected time on CTMC by reduction to DTMC with rewards. storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); @@ -667,8 +695,6 @@ namespace storm { } return storm::modelchecker::SparseDtmcEliminationModelChecker>::computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates, totalRewardVector, false, qualitative); - // Enable again, if RationalFunction finally is supported. - //return storm::modelchecker::helper::SparseDtmcPrctlHelper::computeReachabilityRewards(probabilityMatrix, backwardTransitions, totalRewardVector, targetStates, qualitative, linearEquationSolverFactory); } template class SparseCtmcCslHelper; @@ -677,7 +703,8 @@ namespace storm { template std::vector SparseCtmcCslHelper::computeReachabilityRewards(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::models::sparse::StandardRewardModel const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); #ifdef STORM_HAVE_CARL - template std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory*/); + template std::vector SparseCtmcCslHelper::computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); + template std::vector SparseCtmcCslHelper::computeExpectedTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); #endif } } diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h index 94752a974..14a98f752 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -16,6 +16,7 @@ namespace storm { static std::vector computeNextProbabilities(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& nextStates, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); static std::vector computeUntilProbabilities(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); + static std::vector computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); template static std::vector computeInstantaneousRewards(storm::storage::SparseMatrix const& rateMatrix, std::vector const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); @@ -28,7 +29,8 @@ namespace storm { static std::vector computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative/*, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory*/); + static std::vector computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeExpectedTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); /*! * Computes the matrix representing the transitions of the uniformized CTMC. diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 41324957b..279ef5089 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -512,66 +512,74 @@ namespace storm { template std::unique_ptr SparseDtmcEliminationModelChecker::computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative, boost::optional const& optimalityType) { + // Retrieve the appropriate bitvectors by model checking the subformulas. std::unique_ptr leftResultPointer = this->check(pathFormula.getLeftSubformula()); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - + + std::vector result = computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), phiStates, psiStates, this->computeResultsForInitialStatesOnly); + + // Construct check result. + std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); + return checkResult; + } + + template + std::vector SparseDtmcEliminationModelChecker::computeUntilProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool computeForInitialStatesOnly) { + // Then, compute the subset of states that has a probability of 0 or 1, respectively. - std::pair statesWithProbability01 = storm::utility::graph::performProb01(this->getModel(), phiStates, psiStates); + std::pair statesWithProbability01 = storm::utility::graph::performProb01(backwardTransitions, phiStates, psiStates); storm::storage::BitVector statesWithProbability0 = statesWithProbability01.first; storm::storage::BitVector statesWithProbability1 = statesWithProbability01.second; storm::storage::BitVector maybeStates = ~(statesWithProbability0 | statesWithProbability1); // Determine whether we need to perform some further computation. bool furtherComputationNeeded = true; - if (computeResultsForInitialStatesOnly && this->getModel().getInitialStates().isDisjointFrom(maybeStates)) { + if (computeForInitialStatesOnly && initialStates.isDisjointFrom(maybeStates)) { STORM_LOG_DEBUG("The probability for all initial states was found in a preprocessing step."); furtherComputationNeeded = false; } else if (maybeStates.empty()) { STORM_LOG_DEBUG("The probability for all states was found in a preprocessing step."); furtherComputationNeeded = false; } - + std::vector result(maybeStates.size()); if (furtherComputationNeeded) { // If we compute the results for the initial states only, we can cut off all maybe state that are not // reachable from them. - if (computeResultsForInitialStatesOnly) { + if (computeForInitialStatesOnly) { // Determine the set of states that is reachable from the initial state without jumping over a target state. - storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), maybeStates, statesWithProbability1); + storm::storage::BitVector reachableStates = storm::utility::graph::getReachableStates(probabilityMatrix, initialStates, maybeStates, statesWithProbability1); // Subtract from the maybe states the set of states that is not reachable (on a path from the initial to a target state). maybeStates &= reachableStates; } - + // Create a vector for the probabilities to go to a state with probability 1 in one step. - std::vector oneStepProbabilities = this->getModel().getTransitionMatrix().getConstrainedRowSumVector(maybeStates, statesWithProbability1); - + std::vector oneStepProbabilities = probabilityMatrix.getConstrainedRowSumVector(maybeStates, statesWithProbability1); + // Determine the set of initial states of the sub-model. - storm::storage::BitVector newInitialStates = this->getModel().getInitialStates() % maybeStates; - + storm::storage::BitVector newInitialStates = initialStates % maybeStates; + // We then build the submatrix that only has the transitions of the maybe states. - storm::storage::SparseMatrix submatrix = this->getModel().getTransitionMatrix().getSubmatrix(false, maybeStates, maybeStates); + storm::storage::SparseMatrix submatrix = probabilityMatrix.getSubmatrix(false, maybeStates, maybeStates); storm::storage::SparseMatrix submatrixTransposed = submatrix.transpose(); - - std::vector subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, computeResultsForInitialStatesOnly, phiStates, psiStates, oneStepProbabilities); + + std::vector subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, phiStates, psiStates, oneStepProbabilities); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } // Construct full result. storm::utility::vector::setVectorValues(result, statesWithProbability0, storm::utility::zero()); storm::utility::vector::setVectorValues(result, statesWithProbability1, storm::utility::one()); - - // Construct check result based on whether we have computed values for all states or just the initial states. - std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); - if (computeResultsForInitialStatesOnly) { + if (computeForInitialStatesOnly) { // If we computed the results for the initial (and prob 0 and prob1) states only, we need to filter the // result to only communicate these results. - checkResult->filter(ExplicitQualitativeCheckResult(~maybeStates | this->getModel().getInitialStates())); + result = storm::utility::vector::filterVector(result, ~maybeStates | initialStates); } - return checkResult; + return result; } template @@ -588,7 +596,7 @@ namespace storm { STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model."); std::vector result = computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates, stateRewardValues, this->computeResultsForInitialStatesOnly, qualitative, optimalityType); - // Construct check result + // Construct check result. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); return checkResult; } diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index a840cef88..5b000b4f2 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -25,12 +25,19 @@ namespace storm { // The implemented methods of the AbstractModelChecker interface. virtual bool canHandle(storm::logic::Formula const& formula) const override; + virtual std::unique_ptr computeBoundedUntilProbabilities(storm::logic::BoundedUntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual std::unique_ptr computeUntilProbabilities(storm::logic::UntilFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + static std::vector computeUntilProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool computeForInitialStatesOnly); + virtual std::unique_ptr computeReachabilityRewards(storm::logic::ReachabilityRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector const& stateRewardValues, bool computeForInitialStatesOnly, bool qualitative, boost::optional const& optimalityType = boost::optional()); + virtual std::unique_ptr computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; + virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; private: diff --git a/src/utility/storm.h b/src/utility/storm.h index 4bdf22556..2b08aa6ae 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -332,17 +332,51 @@ namespace storm { } else if (model->getType() == storm::models::ModelType::Ctmc) { // Hack to avoid instantiating the CTMC Model Checker which currently does not work for rational functions if (formula->isExpectedTimeOperatorFormula()) { - // We can only solve expected time for pCTMCs at the moment - std::shared_ptr> ctmc = model->template as>(); + // Compute expected time for pCTMCs + STORM_LOG_THROW(formula->asExpectedTimeOperatorFormula().getSubformula().isEventuallyFormula(), storm::exceptions::NotSupportedException, "The parametric engine only supports Eventually formulas for this property"); + storm::logic::EventuallyFormula eventuallyFormula = formula->asExpectedTimeOperatorFormula().getSubformula().asEventuallyFormula(); + STORM_LOG_THROW(eventuallyFormula.getSubformula().isPropositionalFormula(), storm::exceptions::NotSupportedException, "The parametric engine does not support nested formulas on CTMCs"); // Compute goal states - storm::logic::EventuallyFormula eventuallyFormula = formula->asExpectedTimeOperatorFormula().getSubformula().asEventuallyFormula(); + std::shared_ptr> ctmc = model->template as>(); storm::modelchecker::SparsePropositionalModelChecker> propositionalModelchecker(*ctmc); std::unique_ptr subResultPointer = propositionalModelchecker.check(eventuallyFormula.getSubformula()); - storm::modelchecker::ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); + storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(ctmc->getTransitionMatrix(), ctmc->getBackwardTransitions(), ctmc->getExitRateVector(), ctmc->getInitialStates(), subResult.getTruthValuesVector(), false); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimesElimination(ctmc->getTransitionMatrix(), ctmc->getBackwardTransitions(), ctmc->getExitRateVector(), ctmc->getInitialStates(), targetStates, false); result = std::unique_ptr(new storm::modelchecker::ExplicitQuantitativeCheckResult(std::move(numericResult))); + + } else if (formula->isProbabilityOperatorFormula()) { + // Compute reachability probability for pCTMCs + storm::logic::ProbabilityOperatorFormula probOpFormula = formula->asProbabilityOperatorFormula(); + STORM_LOG_THROW(probOpFormula.getSubformula().isUntilFormula() || probOpFormula.getSubformula().isEventuallyFormula(), storm::exceptions::NotSupportedException, "The parametric engine only supports Until formulas for this property"); + + // Compute phi and psi states + std::shared_ptr> ctmc = model->template as>(); + storm::modelchecker::SparsePropositionalModelChecker> propositionalModelchecker(*ctmc); + storm::storage::BitVector phiStates(model->getNumberOfStates(), true); + storm::storage::BitVector psiStates; + if (probOpFormula.getSubformula().isUntilFormula()) { + // Until formula + storm::logic::UntilFormula untilFormula = formula->asProbabilityOperatorFormula().getSubformula().asUntilFormula(); + STORM_LOG_THROW(untilFormula.getLeftSubformula().isPropositionalFormula(), storm::exceptions::NotSupportedException, "The parametric engine does not support nested formulas on CTMCs"); + STORM_LOG_THROW(untilFormula.getRightSubformula().isPropositionalFormula(), storm::exceptions::NotSupportedException, "The parametric engine does not support nested formulas on CTMCs"); + std::unique_ptr leftResultPointer = propositionalModelchecker.check(untilFormula.getLeftSubformula()); + std::unique_ptr rightResultPointer = propositionalModelchecker.check(untilFormula.getRightSubformula()); + phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + } else { + // Eventually formula + assert(probOpFormula.getSubformula().isEventuallyFormula()); + storm::logic::EventuallyFormula eventuallyFormula = probOpFormula.getSubformula().asEventuallyFormula(); + STORM_LOG_THROW(eventuallyFormula.getSubformula().isPropositionalFormula(), storm::exceptions::NotSupportedException, "The parametric engine does not support nested formulas on CTMCs"); + std::unique_ptr resultPointer = propositionalModelchecker.check(eventuallyFormula.getSubformula()); + psiStates = resultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); + } + + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilitiesElimination(ctmc->getTransitionMatrix(), ctmc->getBackwardTransitions(), ctmc->getExitRateVector(), ctmc->getInitialStates(), phiStates, psiStates, false); + result = std::unique_ptr(new storm::modelchecker::ExplicitQuantitativeCheckResult(std::move(numericResult))); + } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support this property on CTMCs."); } From 2c969eff3b1d60a19c95f93ab71d6c217b98fae7 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 3 Feb 2016 18:04:45 +0100 Subject: [PATCH 047/246] Updated benchmark script for reachability probabilities Former-commit-id: 717c099ae1cdc4fcd81afcd4a3201fc7a4a4d062 --- benchmark_dft.py | 106 ++++++++++++++++++++++++----------------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index 54fb06593..a6109ff45 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -10,43 +10,42 @@ EXAMPLE_DIR= "/Users/mvolk/develop/storm/examples/dft/" benchmarks = [ - ("and", False, 3), - ("and_param", True, "(4*x^2+2*x+1)/((x) * (2*x+1))"), - ("cm2", False, 0.256272), - #("cm4", False, 0), - ("cps", False, "inf"), - #("fdep", False, 0), - ("mdcs", False, 2.85414), - ("mdcs2", False, 2.85414), - ("mp", False, 1.66667), - ("or", False, 1), - ("pand", False, "inf"), - ("pand_param", True, "-1"), - ("spare", False, 3.53846), - ("spare2", False, 1.86957), - ("spare3", False, 1.27273), - ("spare4", False, 4.8459), - ("spare5", False, 2.16667), - ("spare6", False, 1.4), - ("tripple_and1", False, 4.16667), - ("tripple_and2", False, 3.66667), - ("tripple_and2_c", False, 3.6667), - ("tripple_and_c", False, 4.16667), - ("tripple_or", False, 0.5), - ("tripple_or2", False, 0.666667), - ("tripple_or2_c", False, 0.66667), - ("tripple_or_c", False, 0.5), - ("tripple_pand", False, "inf"), - ("tripple_pand2", False, "inf"), - ("tripple_pand2_c", False, "inf"), - ("tripple_pand_c", False, "inf"), - ("voting", False, 1.66667), - ("voting2", False, 0.588235) + ("and", False, [3, 1]), + ("and_param", True, ["(4*x^2+2*x+1)/((x) * (2*x+1))", "1"]), + ("cm2", False, [0.256272, 1]), + #("cm4", False, [0, 1]), + ("cps", False, ["inf", 0.333333]), + #("fdep", False, [0, 1]), + ("mdcs", False, [2.85414, 1]), + ("mdcs2", False, [2.85414, 1]), + ("mp", False, [1.66667, 1]), + ("or", False, [1, 1]), + ("pand", False, ["inf", 0.666667]), + ("pand_param", True, ["-1", "(x)/(y+x)"]), + ("spare", False, [3.53846, 1]), + ("spare2", False, [1.86957, 1]), + ("spare3", False, [1.27273, 1]), + ("spare4", False, [4.8459, 1]), + ("spare5", False, [2.16667, 1]), + ("spare6", False, [1.4, 1]), + ("tripple_and1", False, [4.16667, 1]), + ("tripple_and2", False, [3.66667, 1]), + ("tripple_and2_c", False, [3.6667, 1]), + ("tripple_and_c", False, [4.16667, 1]), + ("tripple_or", False, [0.5, 1]), + ("tripple_or2", False, [0.666667, 1]), + ("tripple_or2_c", False, [0.66667, 1]), + ("tripple_or_c", False, [0.5, 1]), + ("tripple_pand", False, ["inf", 0.0416667]), + ("tripple_pand2", False, ["inf", 0.166667]), + ("tripple_pand2_c", False, ["inf", 0.166667]), + ("tripple_pand_c", False, ["inf", 0.0416667]), + ("voting", False, [1.66667, 1]), + ("voting2", False, [0.588235, 1]) ] -def run_storm_dft(filename, parametric, quiet): +def run_storm_dft(filename, prop, parametric, quiet): # Run storm-dft on filename and return result - prop = "ET=? [F \"failed\"]" dft_file = os.path.join(EXAMPLE_DIR, filename + ".dft") args = [STORM_PATH, dft_file, @@ -84,24 +83,27 @@ def run_tool(args, quiet=False): if __name__ == "__main__": count = 0 correct = 0 + properties = ["ET=? [F \"failed\"]", "P=? [F \"failed\"]"] start = time.time() - for (benchmark, parametric, result_original) in benchmarks: - # Run benchmark and check result - count += 1; - print("Running '{}'".format(benchmark)) - result = run_storm_dft(benchmark, parametric, True) - if not parametric: - # Float - result = float(result) - if not math.isclose(result, float(result_original), rel_tol=1e-05): - print("!!! File '{}': result: {}, Expected: {}".format(benchmark, result, result_original)) + for index, prop in enumerate(properties): + for (benchmark, parametric, result_original) in benchmarks: + expected_result = result_original[index] + # Run benchmark and check result + count += 1; + print("Running '{}' with property '{}'".format(benchmark, prop)) + result = run_storm_dft(benchmark, prop, parametric, True) + if not parametric: + # Float + result = float(result) + if not math.isclose(result, float(expected_result), rel_tol=1e-05): + print("!!! File '{}': result: {}, Expected: {}".format(benchmark, result, expected_result)) + else: + correct += 1 else: - correct += 1 - else: - # Parametric - if result != result_original: - print("!!! File {}: result: {}, Expected: {}".format(benchmark, result, result_original)) - else: - correct += 1 + # Parametric + if result != expected_result: + print("!!! File {}: result: {}, Expected: {}".format(benchmark, result, expected_result)) + else: + correct += 1 end = time.time() - print("Correct results for {} of {} DFTs in {}s".format(correct, count, end-start)) + print("Correct results for {} of {} DFT checks in {}s".format(correct, count, end-start)) From 7dd1bb67ea2d488e1f291c12698fce9fd8ef8303 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 4 Feb 2016 13:38:02 +0100 Subject: [PATCH 048/246] Some refactoring Former-commit-id: 95441da721315691ef2b9e57b0c418218edf0e26 --- src/builder/ExplicitDFTModelBuilder.cpp | 13 ++++++------- src/storage/dft/DFTBuilder.cpp | 3 +-- src/storage/dft/DFTElements.h | 8 +------- src/storage/dft/DFTState.cpp | 18 +++++++++++------- src/storage/dft/DFTState.h | 4 +++- 5 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 1b777fb54..9332044f2 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -77,7 +77,6 @@ namespace storm { while (!stateQueue.empty()) { // Initialization outgoingTransitions.clear(); - ValueType sum = storm::utility::zero(); // Consider next state DFTStatePointer state = stateQueue.front(); @@ -147,7 +146,9 @@ namespace storm { bool isUsed = true; if (mDft.hasRepresentant(nextBE->id())) { DFTElementPointer representant = mDft.getRepresentant(nextBE->id()); - isUsed = newState->isUsed(representant->id()); + // Used must be checked for the state we are coming from as this state is responsible for the + // rate and not the new state we are going to + isUsed = state->isUsed(representant->id()); } STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); @@ -155,20 +156,18 @@ namespace storm { if (resultFind != outgoingTransitions.end()) { // Add to existing transition resultFind->second += rate; + STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with " << rate << " to " << resultFind->second); } else { // Insert new transition outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with " << rate); } - sum += rate; } // end while failing BE // Add all transitions for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) { - // TODO Matthias: correct? - ValueType rate = it->second;// / sum; - transitionMatrixBuilder.addNextValue(state->getId(), it->first, rate); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << it->first << " with " << rate); + transitionMatrixBuilder.addNextValue(state->getId(), it->first, it->second); } } // end while queue diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 870b7f8bf..fd068bf7c 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -16,15 +16,14 @@ namespace storm { template DFT DFTBuilder::build() { for(auto& elem : mChildNames) { + DFTGatePointer gate = std::static_pointer_cast>(elem.first); for(auto const& child : elem.second) { - DFTGatePointer gate = std::static_pointer_cast>(elem.first); gate->pushBackChild(mElements[child]); mElements[child]->addParent(gate); } } // Sort elements topologically - // compute rank for (auto& elem : mElements) { computeRank(elem.second); diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index daa1d3d54..7f92ebb19 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -657,13 +657,7 @@ namespace storm { if(state.isOperational(this->mId)) { size_t uses = state.extractUses(mUseIndex); if(!state.isOperational(uses)) { - // TODO compute children ids before. - std::vector childrenIds; - for(auto const& child : this->mChildren) { - childrenIds.push_back(child->id()); - } - - bool claimingSuccessful = state.claimNew(this->mId, mUseIndex, uses, childrenIds); + bool claimingSuccessful = state.claimNew(this->mId, mUseIndex, uses, this->mChildren); if(!claimingSuccessful) { this->fail(state, queues); } diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index ebf3c770b..d760129e0 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -134,15 +134,19 @@ namespace storm { } template - bool DFTState::claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds) { - auto it = find(childIds.begin(), childIds.end(), currentlyUses); - assert(it != childIds.end()); + bool DFTState::claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector>> const& children) { + auto it = children.begin(); + while ((*it)->id() != currentlyUses) { + assert(it != children.end()); + ++it; + } ++it; - while(it != childIds.end()) { - if(!hasFailed(*it) && !isUsed(*it)) { - setUsesAtPosition(usageIndex, *it); + while(it != children.end()) { + size_t childId = (*it)->id(); + if(!hasFailed(childId) && !isUsed(childId)) { + setUsesAtPosition(usageIndex, childId); if(isActiveSpare(spareId)) { - mDft.propagateActivation(*this,*it); + mDft.propagateActivation(*this, childId); } return true; } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 4ea11a991..7cb5eaf4a 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -13,6 +13,8 @@ namespace storm { class DFT; template class DFTBE; + template + class DFTElement; template class DFTState { @@ -97,7 +99,7 @@ namespace storm { */ void setUsesAtPosition(size_t usageIndex, size_t child); - bool claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector const& childIds); + bool claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector>> const& children); bool hasOutgoingEdges() const { return !mIsCurrentlyFailableBE.empty(); From d7e3d10272b3f4fc74839f25cc59029c9f4e0f9c Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 4 Feb 2016 13:45:08 +0100 Subject: [PATCH 049/246] Small refactoring Former-commit-id: c800918d3e8f1a62d2df0419089cae591cfa858e --- src/storage/dft/DFTBuilder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index fd068bf7c..d49bfd067 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -119,12 +119,12 @@ namespace storm { // TODO Matthias: use typedefs template std::vector>> DFTBuilder::topoSort() { - std::map>, topoSortColour> visited; + std::map visited; for(auto const& e : mElements) { visited.insert(std::make_pair(e.second, topoSortColour::WHITE)); } - std::vector>> L; + DFTElementVector L; for(auto const& e : visited) { topoVisit(e.first, visited, L); } From efdd9f25ae80e0c98b00a554f0e6098b9fc0ff61 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 4 Feb 2016 14:00:18 +0100 Subject: [PATCH 050/246] Changed expected result Former-commit-id: 0fb88af944862ce83804cd3fc14d989816d031cb --- benchmark_dft.py | 2 +- examples/dft/spare5.dft | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index a6109ff45..425d8ae80 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -26,7 +26,7 @@ benchmarks = [ ("spare2", False, [1.86957, 1]), ("spare3", False, [1.27273, 1]), ("spare4", False, [4.8459, 1]), - ("spare5", False, [2.16667, 1]), + ("spare5", False, [2.66667, 1]), # We discard the result 2.16667 from DFTCalc ("spare6", False, [1.4, 1]), ("tripple_and1", False, [4.16667, 1]), ("tripple_and2", False, [3.66667, 1]), diff --git a/examples/dft/spare5.dft b/examples/dft/spare5.dft index dcb4d80a4..0cd15bf0e 100644 --- a/examples/dft/spare5.dft +++ b/examples/dft/spare5.dft @@ -1,6 +1,6 @@ toplevel "A"; "A" wsp "I" "B"; -"B" or "K" "J"; +"B" or "C" "J"; "C" or "K" "L"; "I" lambda=0.5 dorm=0; "J" lambda=0.5 dorm=0; From 957ce0193fa9cf25f3a09410bb64fa6436c37c06 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 4 Feb 2016 14:00:39 +0100 Subject: [PATCH 051/246] Set log level from commandline Former-commit-id: b86a4d4e35b49bdd56f798201f04b04ed75e9a49 --- src/storm-dyftee.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index c187e5057..fc113e438 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -52,19 +52,23 @@ int main(int argc, char** argv) { // Parse cli arguments bool parametric = false; + log4cplus::LogLevel level = log4cplus::WARN_LOG_LEVEL; std::string filename = argv[1]; std::string pctlFormula = "Pmax=?[true U \"failed\"]"; for (int i = 2; i < argc; ++i) { std::string option = argv[i]; if (option == "--parametric") { parametric = true; + } else if (option == "--trace") { + level = log4cplus::TRACE_LOG_LEVEL; + } else if (option == "--debug") { + level = log4cplus::DEBUG_LOG_LEVEL; } else { pctlFormula = option; } } storm::utility::setUp(); - log4cplus::LogLevel level = log4cplus::WARN_LOG_LEVEL; logger.setLogLevel(level); logger.getAppender("mainConsoleAppender")->setThreshold(level); From 933194c155f946803204e846d768c79da4029240 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 4 Feb 2016 14:16:46 +0100 Subject: [PATCH 052/246] Added debuglevel to benchmark script Former-commit-id: 79040662612db50bce0fe7bb2b4db7593cfe26d9 --- benchmark_dft.py | 14 ++++++++++---- examples/dft/spare7.dft | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 examples/dft/spare7.dft diff --git a/benchmark_dft.py b/benchmark_dft.py index 425d8ae80..b12d4f185 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -4,6 +4,7 @@ import subprocess import re import time import math +import argparse STORM_PATH= "/Users/mvolk/develop/storm/build/src/storm-dft" EXAMPLE_DIR= "/Users/mvolk/develop/storm/examples/dft/" @@ -28,6 +29,7 @@ benchmarks = [ ("spare4", False, [4.8459, 1]), ("spare5", False, [2.66667, 1]), # We discard the result 2.16667 from DFTCalc ("spare6", False, [1.4, 1]), + ("spare7", False, [3.67333, 1]), ("tripple_and1", False, [4.16667, 1]), ("tripple_and2", False, [3.66667, 1]), ("tripple_and2_c", False, [3.6667, 1]), @@ -81,6 +83,9 @@ def run_tool(args, quiet=False): return result if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Benchmarking DFTs via Storm') + parser.add_argument('--debuglevel', type=int, default=0, help='the debug level (0=silent, 1=print benchmarks, 2=print output from storm') + args = parser.parse_args() count = 0 correct = 0 properties = ["ET=? [F \"failed\"]", "P=? [F \"failed\"]"] @@ -90,19 +95,20 @@ if __name__ == "__main__": expected_result = result_original[index] # Run benchmark and check result count += 1; - print("Running '{}' with property '{}'".format(benchmark, prop)) - result = run_storm_dft(benchmark, prop, parametric, True) + if args.debuglevel > 0: + print("Running '{}' with property '{}'".format(benchmark, prop)) + result = run_storm_dft(benchmark, prop, parametric, args.debuglevel<2) if not parametric: # Float result = float(result) if not math.isclose(result, float(expected_result), rel_tol=1e-05): - print("!!! File '{}': result: {}, Expected: {}".format(benchmark, result, expected_result)) + print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result)) else: correct += 1 else: # Parametric if result != expected_result: - print("!!! File {}: result: {}, Expected: {}".format(benchmark, result, expected_result)) + print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result)) else: correct += 1 end = time.time() diff --git a/examples/dft/spare7.dft b/examples/dft/spare7.dft new file mode 100644 index 000000000..a16429e6f --- /dev/null +++ b/examples/dft/spare7.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" wsp "K" "J" "I"; +"I" lambda=0.5 dorm=0.5; +"J" lambda=1 dorm=0.5; +"K" lambda=0.5 dorm=0.5; From d88bc115c46884277d66eb10454ffe494d7dd13b Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 4 Feb 2016 14:23:57 +0100 Subject: [PATCH 053/246] Use keywords for pctl properties Former-commit-id: c0217aacb6b8a5fcafc409b4050cc8280ff208ed --- src/storm-dyftee.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index fc113e438..fd9d67c12 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -54,19 +54,27 @@ int main(int argc, char** argv) { bool parametric = false; log4cplus::LogLevel level = log4cplus::WARN_LOG_LEVEL; std::string filename = argv[1]; - std::string pctlFormula = "Pmax=?[true U \"failed\"]"; + std::string pctlFormula = ""; for (int i = 2; i < argc; ++i) { std::string option = argv[i]; if (option == "--parametric") { parametric = true; + } else if (option == "--expectedtime") { + assert(pctlFormula.empty()); + pctlFormula = "ET=?[F \"failed\"]"; + } else if (option == "--probability") { + assert(pctlFormula.empty()); + pctlFormula = "P=? [F \"failed\"]"; } else if (option == "--trace") { level = log4cplus::TRACE_LOG_LEVEL; } else if (option == "--debug") { level = log4cplus::DEBUG_LOG_LEVEL; } else { + assert(pctlFormula.empty()); pctlFormula = option; } } + assert(!pctlFormula.empty()); storm::utility::setUp(); logger.setLogLevel(level); From ed9ac339e69d73153c31d53a73e3b312165d0490 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 5 Feb 2016 13:14:48 +0100 Subject: [PATCH 054/246] dft isomorphism Former-commit-id: 1404390f5a2fbdac56705132a2ed9558085ef7d9 --- src/storage/dft/DFT.cpp | 2 ++ src/storage/dft/DFT.h | 23 ++++++++++++++++------- src/storage/dft/DFTIsomorphism.h | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 src/storage/dft/DFTIsomorphism.h diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c36f0a9e0..29f97d77c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -142,6 +142,8 @@ namespace storm { return stream.str(); } + + // Explicitly instantiate the class. template class DFT; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 81cfdf99b..2cfbf6422 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -2,17 +2,19 @@ #ifndef DFT_H #define DFT_H - -#include "DFTElements.h" -#include "../BitVector.h" #include #include #include #include +#include + +#include "DFTIsomorphism.h" +#include "DFTElements.h" +#include "../BitVector.h" + #include "../../utility/math.h" #include "src/utility/macros.h" -#include namespace storm { namespace storage { @@ -28,8 +30,9 @@ namespace storm { } }; - - + /** + * Represents a Dynamic Fault Tree + */ template class DFT { @@ -136,12 +139,17 @@ namespace storm { return result; } + /** + * Get a pointer to an element in the DFT + * @param index The id of the element + */ DFTElementPointer const& getElement(size_t index) const { assert(index < nrElements()); return mElements[index]; } std::shared_ptr> getBasicElement(size_t index) const { + assert(index < nrElements()); assert(mElements[index]->isBasicElement()); return std::static_pointer_cast>(mElements[index]); } @@ -182,7 +190,8 @@ namespace storm { std::string getElementsWithStateString(DFTStatePointer const& state) const; std::string getStateString(DFTStatePointer const& state) const; - + + DFTIsomorphisms detectIsomorphicChildren() const; private: bool elementIndicesCorrect() const { for(size_t i = 0; i < mElements.size(); ++i) { diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h new file mode 100644 index 000000000..2b6016ca4 --- /dev/null +++ b/src/storage/dft/DFTIsomorphism.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace storm { +namespace storage { + /** + * Saves isomorphism between subtrees + */ + class DFTIsomorphism { + std::vector> classes; + }; + + /** + * Saves sets of isomorphic subtrees + */ + class DFTIsomorphisms { + std::vector isomorphisms; + + void addIsomorphismClass(DFTIsomorphism const &) { + + } + }; +} // namespace storm::dft +} // namespace storm From 50e37217de2dfc9b09b6e55f4e762817d3a16f63 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 5 Feb 2016 13:59:21 +0100 Subject: [PATCH 055/246] Fixed compile problem Former-commit-id: 718456a293ed121ad644718453505dfa01c6233c --- src/parser/DFTGalileoParser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 163bc1488..8bc96ed78 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -54,7 +54,7 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Exception during file opening on " << filename << "."); return false; } - file.exceptions( 0 ); + file.exceptions( std::ifstream::goodbit ); std::string line; bool generalSuccess = true; @@ -156,4 +156,4 @@ namespace storm { #endif } -} \ No newline at end of file +} From 739963cfe1e022852f419439ed71207f9d910d52 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 5 Feb 2016 16:28:36 +0100 Subject: [PATCH 056/246] find independent subdfts Former-commit-id: fca8c8fab3992c2982fa085e94ec27509483bcfa --- src/storage/dft/DFT.cpp | 8 +++ src/storage/dft/DFT.h | 2 +- src/storage/dft/DFTElements.cpp | 25 ++++++- src/storage/dft/DFTElements.h | 112 ++++++++++++++++++++++++++------ 4 files changed, 124 insertions(+), 23 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 29f97d77c..b05e57eda 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -1,3 +1,5 @@ +#include + #include "DFT.h" namespace storm { @@ -142,7 +144,13 @@ namespace storm { return stream.str(); } + template + bool DFT::rootOfClosedSubDFT(size_t index) const { + //boost::container::flat_set marked; + //DFTElementPointer elem = getElement(index); + + } // Explicitly instantiate the class. template class DFT; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 2cfbf6422..ec68e1f30 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -191,7 +191,7 @@ namespace storm { std::string getStateString(DFTStatePointer const& state) const; - DFTIsomorphisms detectIsomorphicChildren() const; + bool rootOfClosedSubDFT(size_t id) const; private: bool elementIndicesCorrect() const { for(size_t i = 0; i < mElements.size(); ++i) { diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 0c18e3be6..761975762 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -34,9 +34,30 @@ namespace storm { template void DFTElement::extendUnit(std::set& unit) const { unit.insert(mId); + } + + template + std::vector DFTElement::independentSubDft() const { + std::vector res; + res.push_back(this->id()); + // Extend for pdeps. + return res; + } + + template + void DFTElement::extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const { + if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { + // This is a parent of the suspected root, thus it is not a subdft. + elemsInSubtree.clear(); + return; + } + elemsInSubtree.insert(mId); for(auto const& parent : mParents) { - if(unit.count(parent->id()) != 0) { - parent->extendUnit(unit); + if(elemsInSubtree.count(parent->id()) != 0) { + parent->extendUnit(elemsInSubtree); + if(elemsInSubtree.empty()) { + return; + } } } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 7f92ebb19..b047ddbd1 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -42,11 +42,13 @@ namespace storm { virtual ~DFTElement() {} - + /** + * Returns the id + */ virtual size_t id() const { return mId; } - + virtual void setRank(size_t rank) { mRank = rank; } @@ -62,7 +64,10 @@ namespace storm { virtual bool isGate() const { return false; } - + + /** + * Returns true if the element is a BE + */ virtual bool isBasicElement() const { return false; } @@ -70,7 +75,10 @@ namespace storm { virtual bool isColdBasicElement() const { return false; } - + + /** + * Returns true if the element is a spare gate + */ virtual bool isSpareGate() const { return false; } @@ -78,7 +86,10 @@ namespace storm { virtual void setId(size_t newId) { mId = newId; } - + + /** + * Returns the name + */ virtual std::string const& name() const { return mName; } @@ -101,7 +112,15 @@ namespace storm { DFTGateVector const& parents() const { return mParents; } - + + std::vector parentIds() const { + std::vector res; + for(auto parent : parents()) { + res.push_back(parent->id()); + } + return res; + } + virtual void extendSpareModule(std::set& elementsInModule) const; virtual size_t nrChildren() const = 0; @@ -109,12 +128,33 @@ namespace storm { virtual std::string toString() const = 0; virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; - + + /** + * Computes the independent unit of this element, that is, all elements which are direct or indirect successors of an element. + */ virtual std::vector independentUnit() const = 0; - + + /** + * Helper to independent unit computation + * @see independentUnit + */ virtual void extendUnit(std::set& unit) const; + /** + * Computes independent subtrees starting with this element (this), that is, all elements (x) which are connected to either + * - one of the children of the element, + * - a propabilisistic dependency + * such that there exists a path from x to a child of this does not go through this. + */ + virtual std::vector independentSubDft() const; + /** + * Helper to the independent subtree computation + * @see independentSubDft + */ + virtual void extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const; + void checkForSymmetricChildren() const; + }; @@ -197,13 +237,50 @@ namespace storm { for(auto const& child : mChildren) { child->extendUnit(unit); } - for(auto const& parent : this->mParents) { - if(unit.count(parent->id()) != 0) { - return {}; - } + return std::vector(unit.begin(), unit.end()); + } + + virtual void extendUnit(std::set& unit) const override { + DFTElement::extendUnit(unit); + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + } + + virtual std::vector independentSubDft() const override { + auto prelRes = DFTElement::independentSubDft(); + if(prelRes.empty()) { + // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. + return prelRes; + } + std::set unit(prelRes.begin(), prelRes.end()); + std::vector pids = this->parentIds(); + for(auto const& child : mChildren) { + child->extendSubDft(unit, pids); + if(unit.empty()) { + // Parent in the subdft, ie it is *not* a subdft + break; + } } return std::vector(unit.begin(), unit.end()); } + + virtual void extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(!elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + for(auto const& child : mChildren) { + child->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + break; + } + } + } + + virtual std::string toString() const override { std::stringstream stream; @@ -226,13 +303,7 @@ namespace storm { } return false; } - - virtual void extendUnit(std::set& unit) const override { - DFTElement::extendUnit(unit); - for(auto const& child : mChildren) { - child->extendUnit(unit); - } - } + protected: @@ -318,10 +389,11 @@ namespace storm { return storm::utility::isZero(mPassiveFailureRate); } - virtual std::vector independentUnit() const { + virtual std::vector independentUnit() const override { return {this->mId}; } + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; }; From 3b1c695b5d2c4b7f9b4c3b05249addcd24e76dae Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 5 Feb 2016 16:33:57 +0100 Subject: [PATCH 057/246] Another compile fix Former-commit-id: 6bb97a0505e07d4952fad582c75e9d04d2f16481 --- src/storage/dft/DFTState.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 7cb5eaf4a..fed33eee3 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -5,6 +5,7 @@ #include "DFTElementState.h" #include +#include namespace storm { namespace storage { From da90b5fcd077ff78082b0d50375b54d812e681bc Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 5 Feb 2016 20:31:43 +0100 Subject: [PATCH 058/246] Fixed benchmark script for new command line options Former-commit-id: d2df6bd5a4c70914b44bbb23bc96e2edbedd9c92 --- benchmark_dft.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index b12d4f185..1b8e29972 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -51,7 +51,7 @@ def run_storm_dft(filename, prop, parametric, quiet): dft_file = os.path.join(EXAMPLE_DIR, filename + ".dft") args = [STORM_PATH, dft_file, - '--prop', prop] + prop] if parametric: args.append('--parametric') @@ -88,7 +88,7 @@ if __name__ == "__main__": args = parser.parse_args() count = 0 correct = 0 - properties = ["ET=? [F \"failed\"]", "P=? [F \"failed\"]"] + properties = ['--expectedtime', '--probability'] start = time.time() for index, prop in enumerate(properties): for (benchmark, parametric, result_original) in benchmarks: From ff69fcab98627c2b5ec61083e748ff587704d8e2 Mon Sep 17 00:00:00 2001 From: sjunges Date: Sat, 6 Feb 2016 18:30:37 +0100 Subject: [PATCH 059/246] refactored DFTElementType, fixed some minor things Former-commit-id: d147e03bd74e5965e0cd27d177e3642e222a2989 --- src/storage/dft/DFTBuilder.cpp | 22 ++++++++--------- src/storage/dft/DFTBuilder.h | 12 +++++----- src/storage/dft/DFTElementType.h | 32 +++++++++++++++++++++++++ src/storage/dft/DFTElements.cpp | 13 ++++++---- src/storage/dft/DFTElements.h | 41 +++++++------------------------- 5 files changed, 66 insertions(+), 54 deletions(-) create mode 100644 src/storage/dft/DFTElementType.h diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index d49bfd067..f6fff39ff 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -61,7 +61,7 @@ namespace storm { } template - bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp) { + bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementType tp) { assert(children.size() > 0); if(mElements.count(name) != 0) { // Element with that name already exists. @@ -69,28 +69,28 @@ namespace storm { } DFTElementPointer element; switch(tp) { - case DFTElementTypes::AND: + case DFTElementType::AND: element = std::make_shared>(mNextId++, name); break; - case DFTElementTypes::OR: + case DFTElementType::OR: element = std::make_shared>(mNextId++, name); break; - case DFTElementTypes::PAND: + case DFTElementType::PAND: element = std::make_shared>(mNextId++, name); break; - case DFTElementTypes::POR: + case DFTElementType::POR: element = std::make_shared>(mNextId++, name); break; - case DFTElementTypes::SPARE: + case DFTElementType::SPARE: element = std::make_shared>(mNextId++, name); break; - case DFTElementTypes::BE: - case DFTElementTypes::VOT: + case DFTElementType::BE: + case DFTElementType::VOT: // Handled separately STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type handled separately."); - case DFTElementTypes::CONSTF: - case DFTElementTypes::CONSTS: - case DFTElementTypes::FDEP: + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + case DFTElementType::FDEP: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); default: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not known."); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 12d5e88c3..0cb0efab5 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -32,23 +32,23 @@ namespace storm { } bool addAndElement(std::string const& name, std::vector const& children) { - return addStandardGate(name, children, DFTElementTypes::AND); + return addStandardGate(name, children, DFTElementType::AND); } bool addOrElement(std::string const& name, std::vector const& children) { - return addStandardGate(name, children, DFTElementTypes::OR); + return addStandardGate(name, children, DFTElementType::OR); } bool addPandElement(std::string const& name, std::vector const& children) { - return addStandardGate(name, children, DFTElementTypes::PAND); + return addStandardGate(name, children, DFTElementType::PAND); } bool addPorElement(std::string const& name, std::vector const& children) { - return addStandardGate(name, children, DFTElementTypes::POR); + return addStandardGate(name, children, DFTElementType::POR); } bool addSpareElement(std::string const& name, std::vector const& children) { - return addStandardGate(name, children, DFTElementTypes::SPARE); + return addStandardGate(name, children, DFTElementType::SPARE); } bool addVotElement(std::string const& name, unsigned threshold, std::vector const& children) { @@ -98,7 +98,7 @@ namespace storm { unsigned computeRank(DFTElementPointer const& elem); - bool addStandardGate(std::string const& name, std::vector const& children, DFTElementTypes tp); + bool addStandardGate(std::string const& name, std::vector const& children, DFTElementType tp); enum class topoSortColour {WHITE, BLACK, GREY}; diff --git a/src/storage/dft/DFTElementType.h b/src/storage/dft/DFTElementType.h new file mode 100644 index 000000000..9aba9fa54 --- /dev/null +++ b/src/storage/dft/DFTElementType.h @@ -0,0 +1,32 @@ +#pragma once + +#include +namespace storm { + namespace storage { + + enum class DFTElementType : int {AND = 0, COUNTING = 1, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, FDEP = 10, SEQAND = 11}; + + inline bool isGateType(DFTElementType const& tp) { + switch(tp) { + case DFTElementType::AND: + case DFTElementType::COUNTING: + case DFTElementType::OR: + case DFTElementType::VOT: + case DFTElementType::PAND: + case DFTElementType::SPARE: + case DFTElementType::POR: + case DFTElementType::SEQAND: + return true; + case DFTElementType::BE: + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + case DFTElementType::FDEP: + return false; + default: + assert(false); + } + } + + } +} + diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 761975762..d5b089c84 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -31,6 +31,14 @@ namespace storm { } } + template + std::vector DFTElement::independentUnit() const { + std::vector res; + res.push_back(this->id()); + // Extend for pdeps. + return res; + } + template void DFTElement::extendUnit(std::set& unit) const { unit.insert(mId); @@ -62,11 +70,6 @@ namespace storm { } } - template - void DFTElement::checkForSymmetricChildren() const { - STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Not implemented."); - assert(false); - } template bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index b047ddbd1..663c5b230 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -8,7 +8,9 @@ #include #include #include +#include +#include "DFTElementType.h" #include "DFTState.h" #include "DFTStateSpaceGenerationQueues.h" #include "src/utility/constants.h" @@ -132,7 +134,7 @@ namespace storm { /** * Computes the independent unit of this element, that is, all elements which are direct or indirect successors of an element. */ - virtual std::vector independentUnit() const = 0; + virtual std::vector independentUnit() const; /** * Helper to independent unit computation @@ -153,33 +155,15 @@ namespace storm { */ virtual void extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const; - void checkForSymmetricChildren() const; - }; - enum class DFTElementTypes {AND, COUNTING, OR, VOT, BE, CONSTF, CONSTS, PAND, SPARE, POR, FDEP, SEQAND}; - inline bool isGateType(DFTElementTypes const& tp) { - switch(tp) { - case DFTElementTypes::AND: - case DFTElementTypes::COUNTING: - case DFTElementTypes::OR: - case DFTElementTypes::VOT: - case DFTElementTypes::PAND: - case DFTElementTypes::SPARE: - case DFTElementTypes::POR: - case DFTElementTypes::SEQAND: - return true; - case DFTElementTypes::BE: - case DFTElementTypes::CONSTF: - case DFTElementTypes::CONSTS: - case DFTElementTypes::FDEP: - return false; - default: - assert(false); - } - } + protected: + // virtual bool checkIsomorphicSubDftHelper(DFTElement const& otherElem, std::vector>& mapping, std::vector const& order ) const = 0; + + }; + @@ -281,7 +265,6 @@ namespace storm { } - virtual std::string toString() const override { std::stringstream stream; stream << "{" << this->name() << "} " << typestring() << "( "; @@ -304,7 +287,7 @@ namespace storm { return false; } - + protected: void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { @@ -388,12 +371,6 @@ namespace storm { bool isColdBasicElement() const { return storm::utility::isZero(mPassiveFailureRate); } - - virtual std::vector independentUnit() const override { - return {this->mId}; - } - - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; }; From e38648f6a7331fe31475a789b1503d15c90d04e2 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 8 Feb 2016 16:26:07 +0100 Subject: [PATCH 060/246] FDeps are parsed and constructed but not used yet Former-commit-id: fbd2a95f9c8e4236841f137bc63c58c53221517f --- src/parser/DFTGalileoParser.cpp | 2 +- src/storage/dft/DFTBuilder.cpp | 25 +++++++++-- src/storage/dft/DFTBuilder.h | 25 +++++++++++ src/storage/dft/DFTElements.h | 79 ++++++++++++++++++++++++++++++++- 4 files changed, 126 insertions(+), 5 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 163bc1488..d623821e6 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -107,7 +107,7 @@ namespace storm { } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); } else if (boost::starts_with(tokens[1], "fdep")) { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Functional dependencies currently not supported"); + success = builder.addFDepElement(name, childNames); } else if (boost::starts_with(tokens[1], "lambda=")) { ValueType failureRate = parseRationalExpression(tokens[1].substr(7)); ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index d49bfd067..4ee258dd1 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -18,11 +18,30 @@ namespace storm { for(auto& elem : mChildNames) { DFTGatePointer gate = std::static_pointer_cast>(elem.first); for(auto const& child : elem.second) { - gate->pushBackChild(mElements[child]); - mElements[child]->addParent(gate); + auto itFind = mElements.find(child); + if (itFind != mElements.end()) { + // Child found + DFTElementPointer childElement = itFind->second; + assert(!childElement->isDependency()); + gate->pushBackChild(childElement); + childElement->addParent(gate); + } else { + // Child not found -> find first dependent event to assure that child is dependency + auto itFind = mElements.find(child + "_1"); + assert(itFind != mElements.end()); + assert(itFind->second->isDependency()); + STORM_LOG_TRACE("Ignore functional dependency " << child << " in gate " << gate->name()); + } } } + // Initialize dependencies + for (auto& dependency : mDependencies) { + DFTGatePointer triggerEvent = std::static_pointer_cast>(mElements[dependency->nameTrigger()]); + std::shared_ptr> dependentEvent = std::static_pointer_cast>(mElements[dependency->nameDependent()]); + dependency->initialize(triggerEvent, dependentEvent); + } + // Sort elements topologically // compute rank for (auto& elem : mElements) { @@ -40,7 +59,7 @@ namespace storm { template unsigned DFTBuilder::computeRank(DFTElementPointer const& elem) { if(elem->rank() == -1) { - if(elem->nrChildren() == 0) { + if(elem->nrChildren() == 0 || elem->isDependency()) { elem->setRank(0); } else { DFTGatePointer gate = std::static_pointer_cast>(elem); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 12d5e88c3..9dfb80ac2 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -19,12 +19,14 @@ namespace storm { using DFTElementVector = std::vector; using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; + using DFTDependencyPointer = std::shared_ptr>; private: std::size_t mNextId = 0; std::string topLevelIdentifier; std::unordered_map mElements; std::unordered_map> mChildNames; + std::vector mDependencies; public: DFTBuilder() { @@ -51,6 +53,29 @@ namespace storm { return addStandardGate(name, children, DFTElementTypes::SPARE); } + bool addFDepElement(std::string const& name, std::vector const& children) { + assert(children.size() > 1); + if(mElements.count(name) != 0) { + // Element with that name already exists. + return false; + } + std::string trigger = children[0]; + for (size_t i = 1; i < children.size(); ++i) { + // TODO Matthias: better code + std::stringstream stream; + stream << name << "_" << i; + std::string s = stream.str(); + if(mElements.count(s) != 0) { + // Element with that name already exists. + return false; + } + DFTDependencyPointer element = std::make_shared>(mNextId++, s, trigger, children[i]); + mElements[element->name()] = element; + mDependencies.push_back(element); + } + return true; + } + bool addVotElement(std::string const& name, unsigned threshold, std::vector const& children) { assert(children.size() > 0); if(mElements.count(name) != 0) { diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 7f92ebb19..d8f9e19b1 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -74,7 +74,11 @@ namespace storm { virtual bool isSpareGate() const { return false; } - + + virtual bool isDependency() const { + return false; + } + virtual void setId(size_t newId) { mId = newId; } @@ -357,6 +361,79 @@ namespace storm { }; + template + class DFTDependency : public DFTElement { + + using DFTGatePointer = std::shared_ptr>; + using DFTBEPointer = std::shared_ptr>; + using DFTBEVector = std::vector; + + protected: + std::string mNameTrigger; + std::string mNameDependent; + DFTGatePointer mTriggerEvent; + DFTBEPointer mDependentEvent; + + public: + DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent) : + DFTElement(id, name), mNameTrigger(trigger), mNameDependent(dependent) + { + } + + virtual ~DFTDependency() {} + + void initialize(DFTGatePointer triggerEvent, DFTBEPointer dependentEvent) { + assert(triggerEvent->name() == mNameTrigger); + assert(dependentEvent->name() == mNameDependent); + mTriggerEvent = triggerEvent; + mDependentEvent = dependentEvent; + } + + std::string nameTrigger() { + return mNameTrigger; + } + + std::string nameDependent() { + return mNameDependent; + } + + DFTGatePointer const& triggerEvent() const { + assert(mTriggerEvent); + return mTriggerEvent; + } + + DFTBEPointer const& dependentEvent() const { + assert(mDependentEvent); + return mDependentEvent; + } + + virtual size_t nrChildren() const override { + return 1; + } + + virtual bool isDependency() const override { + return true; + } + + virtual std::vector independentUnit() const override { + std::set unit = {this->mId}; + mDependentEvent->extendUnit(unit); + if(unit.count(mTriggerEvent->id()) != 0) { + return {}; + } + return std::vector(unit.begin(), unit.end()); + } + + virtual std::string toString() const override { + std::stringstream stream; + stream << "{" << this->name() << "} FDEP(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; + return stream.str(); + } + + protected: + + }; + template class DFTAnd : public DFTGate { From d45ea9cbdeb17fc199a7608f07d8056c4d8ff9ff Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 8 Feb 2016 16:27:08 +0100 Subject: [PATCH 061/246] Improved cmdl options Former-commit-id: b2ecba9ea10e8123683b3860d7bad6bac02a46ae --- src/storm-dyftee.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index fd9d67c12..4986469e7 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -46,7 +46,7 @@ void analyzeDFT(std::string filename, std::string property) { int main(int argc, char** argv) { if(argc < 2) { std::cout << "Storm-DyFTeE should be called with a filename as argument." << std::endl; - std::cout << "./storm-dft " << std::endl; + std::cout << "./storm-dft <--prop pctl-formula> <--parametric>" << std::endl; return 1; } @@ -69,9 +69,14 @@ int main(int argc, char** argv) { level = log4cplus::TRACE_LOG_LEVEL; } else if (option == "--debug") { level = log4cplus::DEBUG_LOG_LEVEL; - } else { + } else if (option == "--prop") { assert(pctlFormula.empty()); - pctlFormula = option; + ++i; + assert(i < argc); + pctlFormula = argv[i]; + } else { + std::cout << "Option '" << option << "' not recognized." << std::endl; + return 1; } } assert(!pctlFormula.empty()); From c6663ba74a66e34ae008f2e264793c9e86a5d5a8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 8 Feb 2016 17:11:47 +0100 Subject: [PATCH 062/246] Added FDep bechmarks Former-commit-id: 885b7a9531aa0146b52708ff0ffb0067486e9011 --- examples/dft/cardiac.dft | 21 ++++++ examples/dft/cas.dft | 24 ++++++ examples/dft/deathegg.dft | 16 ++++ examples/dft/fdep.dft | 8 ++ examples/dft/ftpp_complex.dft | 129 +++++++++++++++++++++++++++++++++ examples/dft/ftpp_large.dft | 63 ++++++++++++++++ examples/dft/ftpp_standard.dft | 53 ++++++++++++++ 7 files changed, 314 insertions(+) create mode 100644 examples/dft/cardiac.dft create mode 100644 examples/dft/cas.dft create mode 100644 examples/dft/deathegg.dft create mode 100644 examples/dft/fdep.dft create mode 100644 examples/dft/ftpp_complex.dft create mode 100644 examples/dft/ftpp_large.dft create mode 100644 examples/dft/ftpp_standard.dft diff --git a/examples/dft/cardiac.dft b/examples/dft/cardiac.dft new file mode 100644 index 000000000..505f002b1 --- /dev/null +++ b/examples/dft/cardiac.dft @@ -0,0 +1,21 @@ +toplevel "SYSTEM"; +"SYSTEM" or "FDEP" "CPU" "MOTOR" "PUMPS"; +"FDEP" fdep "TRIGGER" "P" "B"; +"TRIGGER" or "CS" "SS"; +"CPU" wsp "P" "B"; +"MOTOR" or "SWITCH" "MOTORS"; +"SWITCH" pand "MS" "MA"; +"MOTORS" csp "MA" "MB"; +"PUMPS" and "PUMP1" "PUMP2"; +"PUMP1" csp "PA" "PS"; +"PUMP2" csp "PB" "PS"; +"P" lambda=5.0e-5 dorm=0; +"B" lambda=5.0e-5 dorm=0.5; +"CS" lambda=2.0e-5 dorm=0; +"SS" lambda=2.0e-5 dorm=0; +"MS" lambda=1.0e-6 dorm=0; +"MA" lambda=1.0e-4 dorm=0; +"MB" lambda=1.0e-4 dorm=0; +"PA" lambda=1.0e-4 dorm=0; +"PB" lambda=1.0e-4 dorm=0; +"PS" lambda=1.0e-4 dorm=0; diff --git a/examples/dft/cas.dft b/examples/dft/cas.dft new file mode 100644 index 000000000..812a3f30a --- /dev/null +++ b/examples/dft/cas.dft @@ -0,0 +1,24 @@ +toplevel "System"; +"System" or "CPUfdep" "CPUunit" "Motorunit" "Pumpunit"; + +"CPUfdep" fdep "trigger" "P" "B"; +"trigger" or "CS" "SS"; +"CS" lambda=0.2 dorm=0; +"SS" lambda=0.2 dorm=0; +"CPUunit" wsp "P" "B"; +"P" lambda=0.5 dorm=0; +"B" lambda=0.5 dorm=0.5; + +"Motorunit" or "MP" "Motors"; +"MP" pand "MS" "MA"; +"Motors" csp "MA" "MB"; +"MS" lambda=0.01 dorm=0; +"MA" lambda=1 dorm=0; +"MB" lambda=1 dorm=0; + +"Pumpunit" and "PumpA" "PumpB"; +"PumpA" csp "PA" "PS"; +"PumpB" csp "PB" "PS"; +"PA" lambda=1 dorm=0; +"PB" lambda=1 dorm=0; +"PS" lambda=1 dorm=0; diff --git a/examples/dft/deathegg.dft b/examples/dft/deathegg.dft new file mode 100644 index 000000000..618684c4e --- /dev/null +++ b/examples/dft/deathegg.dft @@ -0,0 +1,16 @@ +toplevel "DeathEgg"; +"DeathEgg" or "DeathEggProxy" "DeathEggServer" "CampusPowerDependency" "ProxyPowerDependency"; +"DeathEggServer" or "CampusNET" "DES_Disks"; +"DES_Disks" and "DES_Disks_RAID1" "DES_Disks_RAID2"; +"DES_Disks_RAID1" and "DES_Disk_1" "DES_Disk_2"; +"DES_Disks_RAID2" and "DES_Disk_3" "DES_Disk_4"; +"DeathEggProxy" lambda=0.01 dorm=0; +"DES_Disk_1" lambda=0.01 dorm=0; +"DES_Disk_2" lambda=0.01 dorm=0; +"DES_Disk_3" lambda=0.01 dorm=0; +"DES_Disk_4" lambda=0.01 dorm=0; +"CampusPowerDependency" fdep "CampusPower" "DeathEggServer"; +"ProxyPowerDependency" fdep "ProxyPower" "DeathEggProxy"; +"CampusPower" lambda=0.01 dorm=0; +"CampusNET" lambda=0.01 dorm=0; +"ProxyPower" lambda=0.01 dorm=0; \ No newline at end of file diff --git a/examples/dft/fdep.dft b/examples/dft/fdep.dft new file mode 100644 index 000000000..e597c46ce --- /dev/null +++ b/examples/dft/fdep.dft @@ -0,0 +1,8 @@ +toplevel "System"; +"System" or "Power" "Machine"; +"Power" fdep "B_Power" "P" "B"; +"Machine" or "P" "B"; + +"B_Power" lambda=0.5 dorm=0; +"P" lambda=0.5 dorm=0; +"B" lambda=0.5 dorm=0.5; diff --git a/examples/dft/ftpp_complex.dft b/examples/dft/ftpp_complex.dft new file mode 100644 index 000000000..1b836ee6b --- /dev/null +++ b/examples/dft/ftpp_complex.dft @@ -0,0 +1,129 @@ +toplevel "System"; +"System" or "triadA" "triadB" "triadC" "triadD" "fA" "fB" "fC" "fD"; + +"triadA" 2of3 "aA" "bA" "cA"; +"aA" csp "TAA" "TAS"; +"bA" csp "TAB" "TAS"; +"cA" csp "TAC" "TAS"; + +"triadB" 2of3 "aB" "bB" "cB"; +"aB" csp "TBA" "TBS"; +"bB" csp "TBB" "TBS"; +"cB" csp "TBC" "TBS"; + +"triadC" 2of3 "aC" "bC" "cC"; +"aC" csp "TCA" "TCS"; +"bC" csp "TCB" "TCS"; +"cC" csp "TCC" "TCS"; + +"triadD" 2of3 "aD" "bD" "cD"; +"aD" csp "TDA" "TDS"; +"bD" csp "TDB" "TDS"; +"cD" csp "TDC" "TDS"; + +"fA" fdep "NEA" "TAA" "TBA" "TCA" "TDA"; +"fB" fdep "NEB" "TAB" "TBB" "TCB" "TDB"; +"fC" fdep "NEC" "TAC" "TBC" "TCC" "TDC"; +"fD" fdep "NED" "TAS" "TBS" "TCS" "TDS"; + + +"NEA" lambda=0.017 dorm=1; +"NEB" lambda=0.017 dorm=1; +"NEC" lambda=0.017 dorm=1; +"NED" lambda=0.017 dorm=1; + +"TAA" or "cpuAA" "memAA"; +"memAA" csp "memAA1" "memAA2"; +"cpuAA" lambda=0.11 dorm=0; +"memAA1" lambda=0.11 dorm=0; +"memAA2" lambda=0.11 dorm=0; + +"TAB" or "cpuAB" "memAB"; +"memAB" csp "memAB1" "memAB2"; +"cpuAB" lambda=0.11 dorm=0; +"memAB1" lambda=0.11 dorm=0; +"memAB2" lambda=0.11 dorm=0; + +"TAC" or "cpuAC" "memAC"; +"memAC" csp "memAC1" "memAC2"; +"cpuAC" lambda=0.11 dorm=0; +"memAC1" lambda=0.11 dorm=0; +"memAC2" lambda=0.11 dorm=0; + +"TAS" or "cpuAS" "memAS"; +"memAS" csp "memAS1" "memAS2"; +"cpuAS" lambda=0.11 dorm=0; +"memAS1" lambda=0.11 dorm=0; +"memAS2" lambda=0.11 dorm=0; + +"TBA" or "cpuBA" "memBA"; +"memBA" csp "memBA1" "memBA2"; +"cpuBA" lambda=0.11 dorm=0; +"memBA1" lambda=0.11 dorm=0; +"memBA2" lambda=0.11 dorm=0; + +"TBB" or "cpuBB" "memBB"; +"memBB" csp "memBB1" "memBB2"; +"cpuBB" lambda=0.11 dorm=0; +"memBB1" lambda=0.11 dorm=0; +"memBB2" lambda=0.11 dorm=0; + +"TBC" or "cpuBC" "memBC"; +"memBC" csp "memBC1" "memBC2"; +"cpuBC" lambda=0.11 dorm=0; +"memBC1" lambda=0.11 dorm=0; +"memBC2" lambda=0.11 dorm=0; + +"TBS" or "cpuBS" "memBS"; +"memBS" csp "memBS1" "memBS2"; +"cpuBS" lambda=0.11 dorm=0; +"memBS1" lambda=0.11 dorm=0; +"memBS2" lambda=0.11 dorm=0; + +"TCA" or "cpuCA" "memCA"; +"memCA" csp "memCA1" "memCA2"; +"cpuCA" lambda=0.11 dorm=0; +"memCA1" lambda=0.11 dorm=0; +"memCA2" lambda=0.11 dorm=0; + +"TCB" or "cpuCB" "memCB"; +"memCB" csp "memCB1" "memCB2"; +"cpuCB" lambda=0.11 dorm=0; +"memCB1" lambda=0.11 dorm=0; +"memCB2" lambda=0.11 dorm=0; + +"TCC" or "cpuCC" "memCC"; +"memCC" csp "memCC1" "memCC2"; +"cpuCC" lambda=0.11 dorm=0; +"memCC1" lambda=0.11 dorm=0; +"memCC2" lambda=0.11 dorm=0; + +"TCS" or "cpuCS" "memCS"; +"memCS" csp "memCS1" "memCS2"; +"cpuCS" lambda=0.11 dorm=0; +"memCS1" lambda=0.11 dorm=0; +"memCS2" lambda=0.11 dorm=0; + +"TDA" or "cpuDA" "memDA"; +"memDA" csp "memDA1" "memDA2"; +"cpuDA" lambda=0.11 dorm=0; +"memDA1" lambda=0.11 dorm=0; +"memDA2" lambda=0.11 dorm=0; + +"TDB" or "cpuDB" "memDB"; +"memDB" csp "memDB1" "memDB2"; +"cpuDB" lambda=0.11 dorm=0; +"memDB1" lambda=0.11 dorm=0; +"memDB2" lambda=0.11 dorm=0; + +"TDC" or "cpuDC" "memDC"; +"memDC" csp "memDC1" "memDC2"; +"cpuDC" lambda=0.11 dorm=0; +"memDC1" lambda=0.11 dorm=0; +"memDC2" lambda=0.11 dorm=0; + +"TDS" or "cpuDS" "memDS"; +"memDS" csp "memDS1" "memDS2"; +"cpuDS" lambda=0.11 dorm=0; +"memDS1" lambda=0.11 dorm=0; +"memDS2" lambda=0.11 dorm=0; diff --git a/examples/dft/ftpp_large.dft b/examples/dft/ftpp_large.dft new file mode 100644 index 000000000..cdc8032e7 --- /dev/null +++ b/examples/dft/ftpp_large.dft @@ -0,0 +1,63 @@ +toplevel "System"; +"System" or "triadA" "triadB" "triadC" "triadD" "fA" "fB" "fC" "fD" "fE"; + +"triadA" 3of4 "aA" "bA" "cA" "dA"; +"aA" csp "TAA" "TAS"; +"bA" csp "TAB" "TAS"; +"cA" csp "TAC" "TAS"; +"dA" csp "TAD" "TAS"; + +"triadB" 3of4 "aB" "bB" "cB" "dB"; +"aB" csp "TBA" "TBS"; +"bB" csp "TBB" "TBS"; +"cB" csp "TBC" "TBS"; +"dB" csp "TBD" "TBS"; + +"triadC" 3of4 "aC" "bC" "cC" "dC"; +"aC" csp "TCA" "TCS"; +"bC" csp "TCB" "TCS"; +"cC" csp "TCC" "TCS"; +"dC" csp "TCD" "TCS"; + +"triadD" 3of4 "aD" "bD" "cD" "dD"; +"aD" csp "TDA" "TDS"; +"bD" csp "TDB" "TDS"; +"cD" csp "TDC" "TDS"; +"dD" csp "TDD" "TDS"; + +"fA" fdep "NEA" "TAA" "TBA" "TCA" "TDA"; +"fB" fdep "NEB" "TAB" "TBB" "TCB" "TDB"; +"fC" fdep "NEC" "TAC" "TBC" "TCC" "TDC"; +"fD" fdep "NED" "TAD" "TBD" "TCD" "TDD"; +"fE" fdep "NEE" "TAS" "TBS" "TCS" "TDS"; + + +"NEA" lambda=0.017 dorm=1; +"NEB" lambda=0.017 dorm=1; +"NEC" lambda=0.017 dorm=1; +"NED" lambda=0.017 dorm=1; +"NEE" lambda=0.017 dorm=1; + +"TAA" lambda=0.11 dorm=0; +"TAB" lambda=0.11 dorm=0; +"TAC" lambda=0.11 dorm=0; +"TAD" lambda=0.11 dorm=0; +"TAS" lambda=0.11 dorm=0; + +"TBA" lambda=0.11 dorm=0; +"TBB" lambda=0.11 dorm=0; +"TBC" lambda=0.11 dorm=0; +"TBD" lambda=0.11 dorm=0; +"TBS" lambda=0.11 dorm=0; + +"TCA" lambda=0.11 dorm=0; +"TCB" lambda=0.11 dorm=0; +"TCC" lambda=0.11 dorm=0; +"TCD" lambda=0.11 dorm=0; +"TCS" lambda=0.11 dorm=0; + +"TDA" lambda=0.11 dorm=0; +"TDB" lambda=0.11 dorm=0; +"TDC" lambda=0.11 dorm=0; +"TDD" lambda=0.11 dorm=0; +"TDS" lambda=0.11 dorm=0; diff --git a/examples/dft/ftpp_standard.dft b/examples/dft/ftpp_standard.dft new file mode 100644 index 000000000..9eaa7720e --- /dev/null +++ b/examples/dft/ftpp_standard.dft @@ -0,0 +1,53 @@ +toplevel "System"; +"System" or "triadA" "triadB" "triadC" "triadD" "fA" "fB" "fC" "fD"; + +"triadA" 2of3 "aA" "bA" "cA"; +"aA" csp "TAA" "TAS"; +"bA" csp "TAB" "TAS"; +"cA" csp "TAC" "TAS"; + +"triadB" 2of3 "aB" "bB" "cB"; +"aB" csp "TBA" "TBS"; +"bB" csp "TBB" "TBS"; +"cB" csp "TBC" "TBS"; + +"triadC" 2of3 "aC" "bC" "cC"; +"aC" csp "TCA" "TCS"; +"bC" csp "TCB" "TCS"; +"cC" csp "TCC" "TCS"; + +"triadD" 2of3 "aD" "bD" "cD"; +"aD" csp "TDA" "TDS"; +"bD" csp "TDB" "TDS"; +"cD" csp "TDC" "TDS"; + +"fA" fdep "NEA" "TAA" "TBA" "TCA" "TDA"; +"fB" fdep "NEB" "TAB" "TBB" "TCB" "TDB"; +"fC" fdep "NEC" "TAC" "TBC" "TCC" "TDC"; +"fD" fdep "NED" "TAS" "TBS" "TCS" "TDS"; + + +"NEA" lambda=0.017 dorm=1; +"NEB" lambda=0.017 dorm=1; +"NEC" lambda=0.017 dorm=1; +"NED" lambda=0.017 dorm=1; + +"TAA" lambda=0.11 dorm=0; +"TAB" lambda=0.11 dorm=0; +"TAC" lambda=0.11 dorm=0; +"TAS" lambda=0.11 dorm=0; + +"TBA" lambda=0.11 dorm=0; +"TBB" lambda=0.11 dorm=0; +"TBC" lambda=0.11 dorm=0; +"TBS" lambda=0.11 dorm=0; + +"TCA" lambda=0.11 dorm=0; +"TCB" lambda=0.11 dorm=0; +"TCC" lambda=0.11 dorm=0; +"TCS" lambda=0.11 dorm=0; + +"TDA" lambda=0.11 dorm=0; +"TDB" lambda=0.11 dorm=0; +"TDC" lambda=0.11 dorm=0; +"TDS" lambda=0.11 dorm=0; From 4ece7e45a9a02f3f3b1388cd6a3b63662f6a645f Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 8 Feb 2016 17:15:09 +0100 Subject: [PATCH 063/246] Added assertions Former-commit-id: c84ad697299c03af471654a2f71431cf9365d136 --- src/builder/ExplicitDFTModelBuilder.cpp | 4 ++++ src/storage/dft/DFT.cpp | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 9332044f2..8fab93b8b 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,6 +1,7 @@ #include "src/builder/ExplicitDFTModelBuilder.h" #include #include +#include #include namespace storm { @@ -32,6 +33,7 @@ namespace storm { // Build transition matrix modelComponents.transitionMatrix = transitionMatrixBuilder.build(); STORM_LOG_DEBUG("TransitionMatrix: " << std::endl << modelComponents.transitionMatrix); + assert(modelComponents.transitionMatrix.getRowCount() == modelComponents.transitionMatrix.getColumnCount()); // Build state labeling modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size()); @@ -90,6 +92,8 @@ namespace storm { STORM_LOG_TRACE("Added self loop for " << state->getId()); // No further exploration required continue; + } else { + STORM_LOG_THROW(state->nrFailableBEs() > 0, storm::exceptions::UnexpectedException, "State " << state->getId() << " is no target state but behaves like one"); } // Let BE fail diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c36f0a9e0..49c92e05a 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -133,10 +133,11 @@ namespace storm { for (auto const& elem : mElements) { stream << state->getElementStateInt(elem->id()); if(elem->isSpareGate()) { + stream << "["; if(state->isActiveSpare(elem->id())) { - stream << " actively"; + stream << "actively "; } - stream << " using " << state->uses(elem->id()); + stream << "using " << state->uses(elem->id()) << "]"; } } return stream.str(); From 8896bc55ddd11bb3b52dd4134e34e75df8257c02 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 8 Feb 2016 17:50:59 +0100 Subject: [PATCH 064/246] Added probabilities for FDeps Former-commit-id: c679ebb321d742dea13ceb88cea687e46e48fc75 --- src/parser/DFTGalileoParser.cpp | 2 +- src/storage/dft/DFTBuilder.h | 12 ++++++++++-- src/storage/dft/DFTElements.h | 12 ++++++++++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index d623821e6..d56899d20 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -107,7 +107,7 @@ namespace storm { } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); } else if (boost::starts_with(tokens[1], "fdep")) { - success = builder.addFDepElement(name, childNames); + success = builder.addFDepElement(name, childNames, storm::utility::one()); } else if (boost::starts_with(tokens[1], "lambda=")) { ValueType failureRate = parseRationalExpression(tokens[1].substr(7)); ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 9dfb80ac2..8fc65b0b5 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -53,13 +53,21 @@ namespace storm { return addStandardGate(name, children, DFTElementTypes::SPARE); } - bool addFDepElement(std::string const& name, std::vector const& children) { + bool addFDepElement(std::string const& name, std::vector const& children, ValueType probability) { assert(children.size() > 1); if(mElements.count(name) != 0) { // Element with that name already exists. return false; } std::string trigger = children[0]; + + //TODO Matthias: collect constraints for SMT solving + //0 <= probability <= 1 + if (!storm::utility::isOne(probability) && children.size() > 2) { + //TODO Matthias: introduce additional element for probability and then add fdeps with probability 1 to children + std::cerr << "Probability != 1 currently not supported." << std::endl; + } + for (size_t i = 1; i < children.size(); ++i) { // TODO Matthias: better code std::stringstream stream; @@ -69,7 +77,7 @@ namespace storm { // Element with that name already exists. return false; } - DFTDependencyPointer element = std::make_shared>(mNextId++, s, trigger, children[i]); + DFTDependencyPointer element = std::make_shared>(mNextId++, s, trigger, children[i], storm::utility::one()); mElements[element->name()] = element; mDependencies.push_back(element); } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index d8f9e19b1..063a8a414 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -371,12 +371,13 @@ namespace storm { protected: std::string mNameTrigger; std::string mNameDependent; + ValueType mProbability; DFTGatePointer mTriggerEvent; DFTBEPointer mDependentEvent; public: - DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent) : - DFTElement(id, name), mNameTrigger(trigger), mNameDependent(dependent) + DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent, ValueType probability) : + DFTElement(id, name), mNameTrigger(trigger), mNameDependent(dependent), mProbability(probability) { } @@ -397,6 +398,10 @@ namespace storm { return mNameDependent; } + ValueType probability() { + return mProbability; + } + DFTGatePointer const& triggerEvent() const { assert(mTriggerEvent); return mTriggerEvent; @@ -427,6 +432,9 @@ namespace storm { virtual std::string toString() const override { std::stringstream stream; stream << "{" << this->name() << "} FDEP(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; + if (!storm::utility::isOne(mProbability)) { + stream << " with probability " << mProbability; + } return stream.str(); } From d507eab7f38003d652c17e18ec5eccd86a87645a Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 09:42:57 +0100 Subject: [PATCH 065/246] Build Markov Automaton instead of CTMC Former-commit-id: 26c299ad345d562542841ae288c80cdc693e238c --- src/builder/ExplicitDFTModelBuilder.cpp | 41 +++++++++++++++---------- src/builder/ExplicitDFTModelBuilder.h | 13 +++++--- src/storage/dft/DFTBuilder.h | 9 ++---- src/storm-dyftee.cpp | 18 +++++------ 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 8fab93b8b..d4de53d64 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,5 +1,5 @@ #include "src/builder/ExplicitDFTModelBuilder.h" -#include +#include #include #include #include @@ -7,13 +7,13 @@ namespace storm { namespace builder { - template - ExplicitDFTModelBuilder::ModelComponents::ModelComponents() : transitionMatrix(), stateLabeling(), rewardModels(), choiceLabeling() { + template + ExplicitDFTModelBuilder::ModelComponents::ModelComponents() : transitionMatrix(), stateLabeling(), markovianStates(), exitRates(), choiceLabeling() { // Intentionally left empty. } - template - std::shared_ptr> ExplicitDFTModelBuilder::buildCTMC() { + template + std::shared_ptr> ExplicitDFTModelBuilder::buildMA() { // Initialize DFTStatePointer state = std::make_shared>(mDft, newIndex++); mStates.findOrAdd(state->status(), state); @@ -21,15 +21,17 @@ namespace storm { std::queue stateQueue; stateQueue.push(state); - bool deterministicModel = true; + bool deterministicModel = false; + ModelComponents modelComponents; + std::vector tmpMarkovianStates; storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, !deterministicModel, 0); // Begin model generation - exploreStates(stateQueue, transitionMatrixBuilder); + exploreStates(stateQueue, transitionMatrixBuilder, tmpMarkovianStates, modelComponents.exitRates); STORM_LOG_DEBUG("Generated " << mStates.size() << " states"); - // Build CTMC - ModelComponents modelComponents; + // Build Markov Automaton + modelComponents.markovianStates = storm::storage::BitVector(mStates.size(), tmpMarkovianStates); // Build transition matrix modelComponents.transitionMatrix = transitionMatrixBuilder.build(); STORM_LOG_DEBUG("TransitionMatrix: " << std::endl << modelComponents.transitionMatrix); @@ -65,15 +67,17 @@ namespace storm { } } - std::shared_ptr> model; - model = std::shared_ptr>(new storm::models::sparse::Ctmc(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling))); + std::shared_ptr> model = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); model->printModelInformationToStream(std::cout); return model; } - template - void ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder) { + template + void ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates) { + assert(exitRates.empty()); + assert(markovianStates.empty()); + // TODO Matthias: set Markovian states std::map outgoingTransitions; while (!stateQueue.empty()) { @@ -90,6 +94,8 @@ namespace storm { if (mDft.hasFailed(state) || mDft.isFailsafe(state)) { transitionMatrixBuilder.addNextValue(state->getId(), state->getId(), storm::utility::one()); STORM_LOG_TRACE("Added self loop for " << state->getId()); + exitRates.push_back(storm::utility::one()); + assert(exitRates.size()-1 == state->getId()); // No further exploration required continue; } else { @@ -169,20 +175,23 @@ namespace storm { } // end while failing BE // Add all transitions + ValueType exitRate = storm::utility::zero(); for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) { transitionMatrixBuilder.addNextValue(state->getId(), it->first, it->second); + exitRate += it->second; } + exitRates.push_back(exitRate); + assert(exitRates.size()-1 == state->getId()); } // end while queue } // Explicitly instantiate the class. - template class ExplicitDFTModelBuilder, uint32_t>; + template class ExplicitDFTModelBuilder; #ifdef STORM_HAVE_CARL - template class ExplicitDFTModelBuilder, uint32_t>; - template class ExplicitDFTModelBuilder, uint32_t>; + template class ExplicitDFTModelBuilder; #endif } // namespace builder diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index ed02e60d4..edb2e1a94 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -16,7 +16,7 @@ namespace storm { namespace builder { - template, typename IndexType = uint32_t> + template class ExplicitDFTModelBuilder { using DFTElementPointer = std::shared_ptr>; @@ -33,8 +33,11 @@ namespace storm { // The state labeling. storm::models::sparse::StateLabeling stateLabeling; - // The reward models associated with the model. - std::unordered_map> rewardModels; + // The Markovian states. + storm::storage::BitVector markovianStates; + + // The exit rates. + std::vector exitRates; // A vector that stores a labeling for each choice. boost::optional>> choiceLabeling; @@ -50,10 +53,10 @@ namespace storm { // 2^nrBE is upper bound for state space } - std::shared_ptr> buildCTMC(); + std::shared_ptr> buildMA(); private: - void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder); + void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); }; } diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 8fc65b0b5..9297d90cf 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -69,15 +69,12 @@ namespace storm { } for (size_t i = 1; i < children.size(); ++i) { - // TODO Matthias: better code - std::stringstream stream; - stream << name << "_" << i; - std::string s = stream.str(); - if(mElements.count(s) != 0) { + std::string nameFdep = name + "_" + std::to_string(i); + if(mElements.count(nameFdep) != 0) { // Element with that name already exists. return false; } - DFTDependencyPointer element = std::make_shared>(mNextId++, s, trigger, children[i], storm::utility::one()); + DFTDependencyPointer element = std::make_shared>(mNextId++, nameFdep, trigger, children[i], storm::utility::one()); mElements[element->name()] = element; mDependencies.push_back(element); } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 4986469e7..a86347e3b 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -6,7 +6,7 @@ #include "utility/storm.h" /*! - * Load DFT from filename, build corresponding CTMC and check against given property. + * Load DFT from filename, build corresponding Markov Automaton and check against given property. * * @param filename Path to DFT file in Galileo format. * @param property PCTC formula capturing the property to check. @@ -19,21 +19,21 @@ void analyzeDFT(std::string filename, std::string property) { storm::storage::DFT dft = parser.parseDFT(filename); std::cout << "Built data structure" << std::endl; - // Building CTMC - std::cout << "Building CTMC..." << std::endl; + // Building Markov Automaton + std::cout << "Building Markov Automaton..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); - std::shared_ptr> model = builder.buildCTMC(); - std::cout << "Built CTMC" << std::endl; + std::shared_ptr> model = builder.buildMA(); + std::cout << "Built Markov Automaton" << std::endl; // Model checking std::cout << "Model checking..." << std::endl; std::vector> formulas = storm::parseFormulasForExplicit(property); assert(formulas.size() == 1); - std::unique_ptr resultCtmc(storm::verifySparseModel(model, formulas[0])); - assert(resultCtmc); + std::unique_ptr resultMA(storm::verifySparseModel(model, formulas[0])); + assert(resultMA); std::cout << "Result: "; - resultCtmc->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); - std::cout << *resultCtmc << std::endl; + resultMA->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + std::cout << *resultMA << std::endl; } /*! From 32c52d227141fa5caf37b26ae816730722db5e0a Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 11:12:20 +0100 Subject: [PATCH 066/246] Parse PDEPs Former-commit-id: 623afd494f3b5ba6ce0453416922bf4bd2dc1daa --- examples/dft/pdep.dft | 12 ++++++++++++ src/parser/DFTGalileoParser.cpp | 7 +++++-- src/storage/dft/DFTBuilder.h | 20 ++++++++++++++------ src/storage/dft/DFTElements.h | 5 +++-- 4 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 examples/dft/pdep.dft diff --git a/examples/dft/pdep.dft b/examples/dft/pdep.dft new file mode 100644 index 000000000..f8cb0382b --- /dev/null +++ b/examples/dft/pdep.dft @@ -0,0 +1,12 @@ +// From Junges2015 +// Example 3.19 + +toplevel "SF"; +"SF" or "A" "B" "PDEP"; +"A" pand "S" "MA"; +"B" and "MA" "MB"; +"PDEP" pdep=0.2 "MA" "S"; + +"S" lambda=0.5 dorm=0; +"MA" lambda=0.5 dorm=0; +"MB" lambda=0.5 dorm=0; diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 262098a68..c8639ae30 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -106,8 +106,11 @@ namespace storm { success = builder.addPandElement(name, childNames); } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); - } else if (boost::starts_with(tokens[1], "fdep")) { - success = builder.addFDepElement(name, childNames, storm::utility::one()); + } else if (tokens[1] == "fdep") { + success = builder.addDepElement(name, childNames, storm::utility::one()); + } else if (boost::starts_with(tokens[1], "pdep=")) { + ValueType probability = parseRationalExpression(tokens[1].substr(5)); + success = builder.addDepElement(name, childNames, probability); } else if (boost::starts_with(tokens[1], "lambda=")) { ValueType failureRate = parseRationalExpression(tokens[1].substr(7)); ValueType dormancyFactor = parseRationalExpression(tokens[2].substr(5)); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 9297d90cf..a2422522c 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -53,28 +53,36 @@ namespace storm { return addStandardGate(name, children, DFTElementTypes::SPARE); } - bool addFDepElement(std::string const& name, std::vector const& children, ValueType probability) { + bool addDepElement(std::string const& name, std::vector const& children, ValueType probability) { assert(children.size() > 1); if(mElements.count(name) != 0) { // Element with that name already exists. return false; } + + if (storm::utility::isZero(probability)) { + // Element is superfluous + return true; + } std::string trigger = children[0]; //TODO Matthias: collect constraints for SMT solving //0 <= probability <= 1 if (!storm::utility::isOne(probability) && children.size() > 2) { - //TODO Matthias: introduce additional element for probability and then add fdeps with probability 1 to children - std::cerr << "Probability != 1 currently not supported." << std::endl; + //TODO Matthias: introduce additional element for probability and then add pdeps with probability 1 to children + std::cerr << "Probability != 1 for more than one child currently not supported." << std::endl; + return false; } for (size_t i = 1; i < children.size(); ++i) { - std::string nameFdep = name + "_" + std::to_string(i); - if(mElements.count(nameFdep) != 0) { + std::string nameDep = name + "_" + std::to_string(i); + if(mElements.count(nameDep) != 0) { // Element with that name already exists. + std::cerr << "Element with name: " << nameDep << " already exists." << std::endl; return false; } - DFTDependencyPointer element = std::make_shared>(mNextId++, nameFdep, trigger, children[i], storm::utility::one()); + assert(storm::utility::isOne(probability) || children.size() == 2); + DFTDependencyPointer element = std::make_shared>(mNextId++, nameDep, trigger, children[i], probability); mElements[element->name()] = element; mDependencies.push_back(element); } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 063a8a414..9dcc42b8d 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -431,8 +431,9 @@ namespace storm { virtual std::string toString() const override { std::stringstream stream; - stream << "{" << this->name() << "} FDEP(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; - if (!storm::utility::isOne(mProbability)) { + bool fdep = storm::utility::isOne(mProbability); + stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; + if (!fdep) { stream << " with probability " << mProbability; } return stream.str(); From 35f5f9de1529b780a2c21b00b695d80f2de0dc72 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 11:42:07 +0100 Subject: [PATCH 067/246] Small refactoring Former-commit-id: 102054c6043d08de0caf3db6db0ee85684aa1c98 --- src/builder/ExplicitDFTModelBuilder.cpp | 3 ++- src/builder/ExplicitDFTModelBuilder.h | 2 +- src/storm-dyftee.cpp | 16 ++++++++-------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index d4de53d64..1bfc445e7 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,5 +1,6 @@ #include "src/builder/ExplicitDFTModelBuilder.h" #include +#include #include #include #include @@ -13,7 +14,7 @@ namespace storm { } template - std::shared_ptr> ExplicitDFTModelBuilder::buildMA() { + std::shared_ptr> ExplicitDFTModelBuilder::buildModel() { // Initialize DFTStatePointer state = std::make_shared>(mDft, newIndex++); mStates.findOrAdd(state->status(), state); diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index edb2e1a94..b2d27aadd 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -53,7 +53,7 @@ namespace storm { // 2^nrBE is upper bound for state space } - std::shared_ptr> buildMA(); + std::shared_ptr> buildModel(); private: void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index a86347e3b..a8122f2bd 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -6,7 +6,7 @@ #include "utility/storm.h" /*! - * Load DFT from filename, build corresponding Markov Automaton and check against given property. + * Load DFT from filename, build corresponding Model and check against given property. * * @param filename Path to DFT file in Galileo format. * @param property PCTC formula capturing the property to check. @@ -20,20 +20,20 @@ void analyzeDFT(std::string filename, std::string property) { std::cout << "Built data structure" << std::endl; // Building Markov Automaton - std::cout << "Building Markov Automaton..." << std::endl; + std::cout << "Building Model..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); - std::shared_ptr> model = builder.buildMA(); - std::cout << "Built Markov Automaton" << std::endl; + std::shared_ptr> model = builder.buildModel(); + std::cout << "Built Model" << std::endl; // Model checking std::cout << "Model checking..." << std::endl; std::vector> formulas = storm::parseFormulasForExplicit(property); assert(formulas.size() == 1); - std::unique_ptr resultMA(storm::verifySparseModel(model, formulas[0])); - assert(resultMA); + std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); + assert(result); std::cout << "Result: "; - resultMA->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); - std::cout << *resultMA << std::endl; + result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + std::cout << *result << std::endl; } /*! From 46642f2bcad04e386e16bc6e5503ec585936ee28 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 13:11:57 +0100 Subject: [PATCH 068/246] CTMCs are working again Former-commit-id: 259bfefa547dec09cf82849b9a1bbc525aff4c4b --- src/builder/ExplicitDFTModelBuilder.cpp | 53 ++++++++++++++++++++----- src/builder/ExplicitDFTModelBuilder.h | 2 +- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 1bfc445e7..30ed5fcbe 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -28,14 +28,23 @@ namespace storm { storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, !deterministicModel, 0); // Begin model generation - exploreStates(stateQueue, transitionMatrixBuilder, tmpMarkovianStates, modelComponents.exitRates); + bool deterministic = exploreStates(stateQueue, transitionMatrixBuilder, tmpMarkovianStates, modelComponents.exitRates); STORM_LOG_DEBUG("Generated " << mStates.size() << " states"); + STORM_LOG_DEBUG("Model is " << (deterministic ? "deterministic" : "non-deterministic")); // Build Markov Automaton modelComponents.markovianStates = storm::storage::BitVector(mStates.size(), tmpMarkovianStates); // Build transition matrix modelComponents.transitionMatrix = transitionMatrixBuilder.build(); - STORM_LOG_DEBUG("TransitionMatrix: " << std::endl << modelComponents.transitionMatrix); + STORM_LOG_DEBUG("Transition matrix: " << std::endl << modelComponents.transitionMatrix); + // TODO: easier output for vectors + std::stringstream stream; + for (uint_fast64_t i = 0; i < modelComponents.exitRates.size() - 1; ++i) { + stream << modelComponents.exitRates[i] << ", "; + } + stream << modelComponents.exitRates.back(); + STORM_LOG_DEBUG("Exit rates: " << stream.str()); + STORM_LOG_DEBUG("Markovian states: " << modelComponents.markovianStates); assert(modelComponents.transitionMatrix.getRowCount() == modelComponents.transitionMatrix.getColumnCount()); // Build state labeling @@ -68,22 +77,42 @@ namespace storm { } } - std::shared_ptr> model = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); + std::shared_ptr> model; + if (deterministic) { + // Turn the probabilities into rates by multiplying each row with the exit rate of the state. + // TODO Matthias: avoid transforming back and forth + storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); + for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { + for (auto& entry : rateMatrix.getRow(row)) { + entry.setValue(entry.getValue() * modelComponents.exitRates[row]); + } + } + + model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling)); + } else { + model = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); + + } model->printModelInformationToStream(std::cout); return model; } template - void ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates) { + bool ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates) { assert(exitRates.empty()); assert(markovianStates.empty()); - // TODO Matthias: set Markovian states + // TODO Matthias: set Markovian states directly as bitvector? std::map outgoingTransitions; + size_t rowOffset = 0; // Captures number of non-deterministic choices + ValueType exitRate; + bool deterministic = true; + //TODO Matthias: Handle dependencies! while (!stateQueue.empty()) { // Initialization outgoingTransitions.clear(); + exitRate = storm::utility::zero(); // Consider next state DFTStatePointer state = stateQueue.front(); @@ -93,10 +122,12 @@ namespace storm { // Add self loop for target states if (mDft.hasFailed(state) || mDft.isFailsafe(state)) { - transitionMatrixBuilder.addNextValue(state->getId(), state->getId(), storm::utility::one()); + transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, state->getId(), storm::utility::one()); STORM_LOG_TRACE("Added self loop for " << state->getId()); exitRates.push_back(storm::utility::one()); assert(exitRates.size()-1 == state->getId()); + markovianStates.push_back(state->getId()); // No further exploration required continue; } else { @@ -173,19 +204,23 @@ namespace storm { outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with " << rate); } + exitRate += rate; + } // end while failing BE // Add all transitions - ValueType exitRate = storm::utility::zero(); + transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) { - transitionMatrixBuilder.addNextValue(state->getId(), it->first, it->second); - exitRate += it->second; + ValueType probability = it->second / exitRate; // Transform rate to probability + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, it->first, probability); } exitRates.push_back(exitRate); assert(exitRates.size()-1 == state->getId()); + markovianStates.push_back(state->getId()); } // end while queue + return deterministic; } // Explicitly instantiate the class. diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index b2d27aadd..6125b6fa1 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -56,7 +56,7 @@ namespace storm { std::shared_ptr> buildModel(); private: - void exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); + bool exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); }; } From 24cd1ec597be2d81bd7566cf3c2beeddf9e9234d Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 14:01:04 +0100 Subject: [PATCH 069/246] Vector output without template seems to work Former-commit-id: 3627729e256d2d14ebd20781fa89a86d2b350776 --- src/builder/ExplicitDFTModelBuilder.cpp | 9 ++------- src/utility/vector.cpp | 9 +++++---- src/utility/vector.h | 6 ++++-- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 30ed5fcbe..0bd92b069 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -37,13 +38,7 @@ namespace storm { // Build transition matrix modelComponents.transitionMatrix = transitionMatrixBuilder.build(); STORM_LOG_DEBUG("Transition matrix: " << std::endl << modelComponents.transitionMatrix); - // TODO: easier output for vectors - std::stringstream stream; - for (uint_fast64_t i = 0; i < modelComponents.exitRates.size() - 1; ++i) { - stream << modelComponents.exitRates[i] << ", "; - } - stream << modelComponents.exitRates.back(); - STORM_LOG_DEBUG("Exit rates: " << stream.str()); + STORM_LOG_DEBUG("Exit rates: " << modelComponents.exitRates); STORM_LOG_DEBUG("Markovian states: " << modelComponents.markovianStates); assert(modelComponents.transitionMatrix.getRowCount() == modelComponents.transitionMatrix.getColumnCount()); diff --git a/src/utility/vector.cpp b/src/utility/vector.cpp index e4a1dd05c..20af3c628 100644 --- a/src/utility/vector.cpp +++ b/src/utility/vector.cpp @@ -1,7 +1,8 @@ #include "src/utility/vector.h" -template -std::ostream& operator<<(std::ostream& out, std::vector const& vector) { +//template +//std::ostream& operator<<(std::ostream& out, std::vector const& vector) { +std::ostream& operator<<(std::ostream& out, std::vector const& vector) { out << "vector (" << vector.size() << ") [ "; for (uint_fast64_t i = 0; i < vector.size() - 1; ++i) { out << vector[i] << ", "; @@ -12,5 +13,5 @@ std::ostream& operator<<(std::ostream& out, std::vector const& vector } // Explicitly instantiate functions. -template std::ostream& operator<<(std::ostream& out, std::vector const& vector); -template std::ostream& operator<<(std::ostream& out, std::vector const& vector); +//template std::ostream& operator<<(std::ostream& out, std::vector const& vector); +//template std::ostream& operator<<(std::ostream& out, std::vector const& vector); \ No newline at end of file diff --git a/src/utility/vector.h b/src/utility/vector.h index 665569645..6b09f0467 100644 --- a/src/utility/vector.h +++ b/src/utility/vector.h @@ -15,8 +15,10 @@ #include "src/utility/macros.h" #include "src/solver/OptimizationDirection.h" -template -std::ostream& operator<<(std::ostream& out, std::vector const& vector); +// Template was causing problems as Carl has the same function +//template +//std::ostream& operator<<(std::ostream& out, std::vector const& vector); +std::ostream& operator<<(std::ostream& out, std::vector const& vector); namespace storm { namespace utility { From 87e51e04b5ea492af71df15544f66b2ee398f7af Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 14:01:35 +0100 Subject: [PATCH 070/246] Improved benchmark script Former-commit-id: 78f0d49a03b3f6157e7c56577dfe0bd58d00bb0f --- benchmark_dft.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index 1b8e29972..7fe59a276 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -13,10 +13,16 @@ EXAMPLE_DIR= "/Users/mvolk/develop/storm/examples/dft/" benchmarks = [ ("and", False, [3, 1]), ("and_param", True, ["(4*x^2+2*x+1)/((x) * (2*x+1))", "1"]), + ("cardiac", False, [11378, 1]), + ("cas", False, [0.859736, 1]), ("cm2", False, [0.256272, 1]), #("cm4", False, [0, 1]), ("cps", False, ["inf", 0.333333]), - #("fdep", False, [0, 1]), + ("deathegg", False, [46.667, 1]), + ("fdep", False, [0.666667, 1]), + #("ftpp_complex", False, [0, 1]), # Compute + #("ftpp_large", False, [0, 1]), # Compute + #("ftpp_standard", False, [0, 1]), # Compute ("mdcs", False, [2.85414, 1]), ("mdcs2", False, [2.85414, 1]), ("mp", False, [1.66667, 1]), @@ -59,8 +65,7 @@ def run_storm_dft(filename, prop, parametric, quiet): # Get result match = re.search(r'Result: \[(.*)\]', output) if not match: - print("No valid result found in: " + output) - return + return None result = match.group(1) return result @@ -98,6 +103,10 @@ if __name__ == "__main__": if args.debuglevel > 0: print("Running '{}' with property '{}'".format(benchmark, prop)) result = run_storm_dft(benchmark, prop, parametric, args.debuglevel<2) + if result is None: + print("Error occurred on example '{}' with property '{}'".format(benchmark, prop)) + continue + if not parametric: # Float result = float(result) From 64b24043c57c30efccac7892fb53e2f96071adaf Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 18:08:20 +0100 Subject: [PATCH 071/246] Dependencies working Former-commit-id: e262bfc5aa6631ce9c2b4c795b80922977faa90c --- src/builder/ExplicitDFTModelBuilder.cpp | 86 +++++++++++++++---------- src/storage/dft/DFT.cpp | 6 +- src/storage/dft/DFT.h | 5 ++ src/storage/dft/DFTState.cpp | 38 +++++++++-- src/storage/dft/DFTState.h | 44 ++++++++++--- 5 files changed, 126 insertions(+), 53 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 0bd92b069..817295346 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -40,7 +40,7 @@ namespace storm { STORM_LOG_DEBUG("Transition matrix: " << std::endl << modelComponents.transitionMatrix); STORM_LOG_DEBUG("Exit rates: " << modelComponents.exitRates); STORM_LOG_DEBUG("Markovian states: " << modelComponents.markovianStates); - assert(modelComponents.transitionMatrix.getRowCount() == modelComponents.transitionMatrix.getColumnCount()); + assert(!deterministic || modelComponents.transitionMatrix.getRowCount() == modelComponents.transitionMatrix.getColumnCount()); // Build state labeling modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size()); @@ -100,24 +100,26 @@ namespace storm { // TODO Matthias: set Markovian states directly as bitvector? std::map outgoingTransitions; size_t rowOffset = 0; // Captures number of non-deterministic choices - ValueType exitRate; bool deterministic = true; - //TODO Matthias: Handle dependencies! while (!stateQueue.empty()) { // Initialization outgoingTransitions.clear(); - exitRate = storm::utility::zero(); + ValueType exitRate = storm::utility::zero(); // Consider next state DFTStatePointer state = stateQueue.front(); stateQueue.pop(); + bool hasDependencies = state->nrFailableDependencies() > 0; + deterministic &= !hasDependencies; + size_t failableCount = hasDependencies ? state->nrFailableDependencies() : state->nrFailableBEs(); size_t smallest = 0; + transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); + // Add self loop for target states if (mDft.hasFailed(state) || mDft.isFailsafe(state)) { - transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, state->getId(), storm::utility::one()); STORM_LOG_TRACE("Added self loop for " << state->getId()); exitRates.push_back(storm::utility::one()); @@ -130,18 +132,21 @@ namespace storm { } // Let BE fail - while (smallest < state->nrFailableBEs()) { + while (smallest < failableCount) { STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); // Construct new state as copy from original one DFTStatePointer newState = std::make_shared>(*state); std::pair>, bool> nextBEPair = newState->letNextBEFail(smallest++); std::shared_ptr> nextBE = nextBEPair.first; - if (nextBE == nullptr) { - break; - } + assert(nextBE); + assert(nextBEPair.second == hasDependencies); STORM_LOG_TRACE("with the failure of: " << nextBE->name() << " [" << nextBE->id() << "]"); + // Update failable dependencies + newState->updateFailableDependencies(nextBE->id()); + + // Propagate failures storm::storage::DFTStateSpaceGenerationQueues queues; for (DFTGatePointer parent : nextBE->parents()) { @@ -179,42 +184,53 @@ namespace storm { stateQueue.push(newState); } - // Set failure rate according to usage - bool isUsed = true; - if (mDft.hasRepresentant(nextBE->id())) { - DFTElementPointer representant = mDft.getRepresentant(nextBE->id()); - // Used must be checked for the state we are coming from as this state is responsible for the - // rate and not the new state we are going to - isUsed = state->isUsed(representant->id()); - } - STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); - ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); - auto resultFind = outgoingTransitions.find(newState->getId()); - if (resultFind != outgoingTransitions.end()) { - // Add to existing transition - resultFind->second += rate; - STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with " << rate << " to " << resultFind->second); + // Set transitions + if (hasDependencies) { + // Failure is due to dependency -> add non-deterministic choice + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset++, newState->getId(), storm::utility::one()); } else { - // Insert new transition - outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with " << rate); + // Set failure rate according to usage + bool isUsed = true; + if (mDft.hasRepresentant(nextBE->id())) { + DFTElementPointer representant = mDft.getRepresentant(nextBE->id()); + // Used must be checked for the state we are coming from as this state is responsible for the + // rate and not the new state we are going to + isUsed = state->isUsed(representant->id()); + } + STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); + ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); + auto resultFind = outgoingTransitions.find(newState->getId()); + if (resultFind != outgoingTransitions.end()) { + // Add to existing transition + resultFind->second += rate; + STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with " << rate << " to " << resultFind->second); + } else { + // Insert new transition + outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with " << rate); + } + exitRate += rate; } - exitRate += rate; } // end while failing BE - // Add all transitions - transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); - for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) - { - ValueType probability = it->second / exitRate; // Transform rate to probability - transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, it->first, probability); + if (hasDependencies) { + rowOffset--; // One increment to many + } else { + // Add all probability transitions + for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) + { + ValueType probability = it->second / exitRate; // Transform rate to probability + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, it->first, probability); + } + + markovianStates.push_back(state->getId()); } exitRates.push_back(exitRate); assert(exitRates.size()-1 == state->getId()); - markovianStates.push_back(state->getId()); } // end while queue + assert(!deterministic || rowOffset == 0); return deterministic; } diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 112a9273b..1329cab38 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -11,13 +11,13 @@ namespace storm { size_t stateIndex = 0; mUsageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; - for(auto& elem : mElements) { + for (auto& elem : mElements) { mIdToFailureIndex.push_back(stateIndex); stateIndex += 2; if(elem->isBasicElement()) { ++mNrOfBEs; } - else if(elem->isSpareGate()) { + else if (elem->isSpareGate()) { ++mNrOfSpares; for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { if(mActivationIndex.count(spareReprs->id()) == 0) { @@ -39,6 +39,8 @@ namespace storm { mUsageIndex.insert(std::make_pair(elem->id(), stateIndex)); stateIndex += mUsageInfoBits; + } else if (elem->isDependency()) { + mDependencies.push_back(elem->id()); } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 2cfbf6422..cff6db0cb 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -51,6 +51,7 @@ namespace storm { size_t mStateSize; std::map mActivationIndex; std::map> mSpareModules; + std::vector mDependencies; std::vector mTopModule; std::vector mIdToFailureIndex; std::map mUsageIndex; @@ -120,6 +121,10 @@ namespace storm { } } + std::vector const& getDependencies() const { + return mDependencies; + } + void propagateActivation(DFTState& state, size_t representativeId) const { state.activate(representativeId); for(size_t id : module(representativeId)) { diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index d760129e0..17bb4aee8 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -78,17 +78,41 @@ namespace storm { } } + template + bool DFTState::updateFailableDependencies(size_t id) { + assert(hasFailed(id)); + for (size_t i = 0; i < mDft.getDependencies().size(); ++i) { + std::shared_ptr> dependency = std::static_pointer_cast>(mDft.getElement(mDft.getDependencies()[i])); + if (dependency->triggerEvent()->id() == id) { + if (!hasFailed(dependency->dependentEvent()->id())) { + mFailableDependencies.push_back(dependency->id()); + STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); + } + } + } + return nrFailableDependencies() > 0; + } + template std::pair>, bool> DFTState::letNextBEFail(size_t index) { - assert(index < mIsCurrentlyFailableBE.size()); STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); - // TODO set when implementing functional dependencies - bool dueToFdep = false; - std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), dueToFdep); - mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); - setFailed(res.first->id()); - return res; + if (nrFailableDependencies() > 0) { + // Consider failure due to dependency + assert(index < nrFailableDependencies()); + std::shared_ptr> dependency = std::static_pointer_cast>(mDft.getElement(mFailableDependencies[index])); + std::pair>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true); + mFailableDependencies.erase(mFailableDependencies.begin() + index); + setFailed(res.first->id()); + return res; + } else { + // Consider "normal" failure + assert(index < nrFailableBEs()); + std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); + mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); + setFailed(res.first->id()); + return res; + } } template diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index fed33eee3..a1bab2583 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -25,6 +25,7 @@ namespace storm { size_t mId; std::vector mInactiveSpares; std::vector mIsCurrentlyFailableBE; + std::vector mFailableDependencies; std::vector mUsedRepresentants; bool mValid = true; const DFT& mDft; @@ -110,6 +111,17 @@ namespace storm { return mIsCurrentlyFailableBE.size(); } + size_t nrFailableDependencies() const { + return mFailableDependencies.size(); + } + + /** + * Sets all failable BEs due to dependencies from newly failed element + * @param id Id of the newly failed element + * @return true if failable dependent events exist + */ + bool updateFailableDependencies(size_t id); + /** * Sets the next BE as failed * @param smallestIndex Index in currentlyFailableBE of BE to fail @@ -119,17 +131,31 @@ namespace storm { std::string getCurrentlyFailableString() const { std::stringstream stream; - auto it = mIsCurrentlyFailableBE.begin(); - stream << "{"; - if(it != mIsCurrentlyFailableBE.end()) { - stream << *it; - } - ++it; - while(it != mIsCurrentlyFailableBE.end()) { - stream << ", " << *it; + if (nrFailableDependencies() > 0) { + auto it = mFailableDependencies.begin(); + stream << "{Dependencies: "; + if (it != mFailableDependencies.end()) { + stream << *it; + } + ++it; + while(it != mFailableDependencies.end()) { + stream << ", " << *it; + ++it; + } + stream << "} "; + } else { + auto it = mIsCurrentlyFailableBE.begin(); + stream << "{"; + if(it != mIsCurrentlyFailableBE.end()) { + stream << *it; + } ++it; + while(it != mIsCurrentlyFailableBE.end()) { + stream << ", " << *it; + ++it; + } + stream << "}"; } - stream << "}"; return stream.str(); } From 72b09a693c37bf01cefc63af108eaefd5e197b40 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 9 Feb 2016 18:09:06 +0100 Subject: [PATCH 072/246] More examples Former-commit-id: e4ea9cf5dc3bd60844d91fae4c6a8a5d9da71188 --- benchmark_dft.py | 1 + examples/dft/fdep2.dft | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 examples/dft/fdep2.dft diff --git a/benchmark_dft.py b/benchmark_dft.py index 7fe59a276..54dadeacc 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -20,6 +20,7 @@ benchmarks = [ ("cps", False, ["inf", 0.333333]), ("deathegg", False, [46.667, 1]), ("fdep", False, [0.666667, 1]), + ("fdep2", False, [2, 1]), #("ftpp_complex", False, [0, 1]), # Compute #("ftpp_large", False, [0, 1]), # Compute #("ftpp_standard", False, [0, 1]), # Compute diff --git a/examples/dft/fdep2.dft b/examples/dft/fdep2.dft new file mode 100644 index 000000000..a444ed4be --- /dev/null +++ b/examples/dft/fdep2.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C"; +"F" fdep "B" "C"; +"B" lambda=0.5 dorm=0; +"C" lambda=0.5 dorm=0; From 64d3273630181d7fedeef91f6987d7be1fea4126 Mon Sep 17 00:00:00 2001 From: sjunges Date: Tue, 9 Feb 2016 23:40:03 +0100 Subject: [PATCH 073/246] updates on isomorphism Former-commit-id: 7bc9a91eab0a2c9906cf17e00a9d5bbd03e73722 --- src/storage/dft/DFTElements.h | 1 - src/storage/dft/DFTIsomorphism.h | 190 +++++++++++++++++++++++++++++-- 2 files changed, 183 insertions(+), 8 deletions(-) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 663c5b230..fe340a43a 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -158,7 +158,6 @@ namespace storm { - protected: // virtual bool checkIsomorphicSubDftHelper(DFTElement const& otherElem, std::vector>& mapping, std::vector const& order ) const = 0; diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 2b6016ca4..e9a58d559 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -1,25 +1,201 @@ #pragma once #include +#include +#include "DFTElementType.h" +#include "DFTElements.h" namespace storm { namespace storage { + + + struct GateGroupToHash { + static constexpr uint_fast64_t fivebitmask = (1 << 6) - 1; + static constexpr uint_fast64_t eightbitmaks = (1 << 8) - 1; + + /** + * Hash function, which ensures that the colours are sorted according to their rank. + */ + uint_fast64_t operator()(DFTElementType type, size_t nrChildren, size_t nrParents, size_t nrPDEPs, size_t rank) const { + // Sets first bit to 1 + uint_fast64_t groupHash = static_cast(1) << 63; + //Assumes 5 bits for the rank, + groupHash |= (static_cast(rank) & fivebitmask) << (62 - 5); + // 8 bits for the nrChildren, + groupHash |= (static_cast(nrChildren) & eightbitmaks) << (62 - 5 - 8); + // 5 bits for nrParents, + groupHash |= (static_cast(nrParents) & fivebitmask) << (62 - 5 - 8 - 5); + // 5 bits for nrPDEPs, + groupHash |= (static_cast(nrPDEPs) & fivebitmask) << (62 - 5 - 8 - 5 - 5); + // 5 bits for the type + groupHash |= (static_cast(type) & fivebitmask) << (62 - 5 - 8 - 5 - 5 - 5); + return groupHash; + } + + }; + /** - * Saves isomorphism between subtrees + * */ - class DFTIsomorphism { - std::vector> classes; + template + class BijectionCandidates { + std::unordered_map> groupCandidates; + std::unordered_map, std::vector> beCandidates; + }; + + + /** - * Saves sets of isomorphic subtrees + * Saves isomorphism between subtrees */ - class DFTIsomorphisms { - std::vector isomorphisms; + template + class DFTIsomorphismCheck { + /// Coloured nodes as provided by the input: left hand side + BijectionCandidates const& bleft; + /// Coloured nodes as provided by the input: right hand side. + BijectionCandidates const& bright; + /// Whether the colourings are compatible + bool candidatesCompatible = true; + /// Current bijection + std::map bijection; + /// Current permutations of right hand side groups which lead to the homomorphism. + /// Contains only colours with more than one member. + BijectionCandidates currentPermutations; + + public: + DFTIsomorphismCheck(BijectionCandidates const& left, BijectionCandidates const& right) : bleft(left), bright(right) + { + checkCompatibility(); + } + + /** + * Checks whether the candidates are compatible, that is, checks the colours and the number of members for each colour. + * @return True iff compatible, ie if the preliminary check allows for a isomorphism. + */ + bool compatible() { + return candidatesCompatible; + } + + + /** + * Returns the isomorphism + * Can only be called after the findIsomorphism procedure returned that an isomorphism has found. + * @see findIsomorphism + */ + std::vector> getIsomorphism() const { + + } - void addIsomorphismClass(DFTIsomorphism const &) { + /** + * Check whether an isomorphism exists. + * + * @return true iff an isomorphism exists. + */ + bool findIsomorphism() { + if(!candidatesCompatible) return false; + constructInitialBijection(); + while(!check()) { + // continue our search + if(!findNextBijection()) { + // No further bijections to check, no is + return false; + } + } + return true; + } + + protected: + + void constructInitialBijection() { + assert(candidatesCompatible); + // We first construct the currentPermutations, which helps to determine the current state of the check. + for(auto const& colour : bright.beCandidates) { + if(colour.second.size()>1) { + currentPermutations.beCandidates.insert(colour); + } + } + + for(auto const& colour : bright.groupCandidates) { + if(colour.second.size()>1) { + currentPermutations.groupCandidates.insert(colour); + } + } + + // Constructing the initial homomorphism based on the right hand side instead of the current permutations allows us + // to treat trivial and non-trivial classes in one go. + for(auto const& colour : bleft.beCandidates) { + zipVectorsIntoMap(colour.second, bright.beCandidates.find(colour.first)->second, bijection); + } + + for(auto const& colour : bleft.groupCandidates) { + zipVectorsIntoMap(colour.second, bright.groupCandidates.find(colour.first)->second, bijection); + } } + + bool findNextBijection() { + return false; + } + + + /** + * + */ + bool check() { + + } + + private: + /** + * Returns true if the colours are compatible. + */ + bool checkCompatibility() { + if(bleft.groupCandidates.size() != bright.groupCandidates.size()) { + candidatesCompatible = false; + } + else if(bleft.beCandidates.size() != bright.beCandidates.size()) { + candidatesCompatible = false; + } + else { + for (auto const &gc : bleft.groupCandidates) { + if (bright.groupCandidates.count(gc.first) == 0) { + candidatesCompatible = false; + break; + } + } + if(candidatesCompatible) { + for(auto const& bc : bleft.groupCandidates) { + if(bright.beCandidates.count(bc.first) == 0) { + candidatesCompatible = false; + break; + } + } + } + } + } + + /** + * Local helper function for the creation of bijections, should be hidden from api. + */ + void zipVectorsIntoMap(std::vector const& a, std::vector const& b, std::map& map) const { + // Assert should pass due to compatibility check + assert(a.size() == b.size()); + auto it = b.cbegin(); + for(size_t lIndex : a) { + assert(map.count(lIndex) == 0); + map[lIndex] = *it; + ++it; + } + } + + + //std::vector> computeNextCandidate(){ + + //} }; + + } // namespace storm::dft } // namespace storm From 3636b9ac0d1483ba5731230fba3cd3bd1250fba3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 10 Feb 2016 09:49:09 +0100 Subject: [PATCH 074/246] Added more benchmarks Former-commit-id: b6936dfb7b8f0095aaa9678e9cae2f26ee8cd8b3 --- benchmark_dft.py | 8 ++++++-- examples/dft/pdep2.dft | 9 +++++++++ examples/dft/symmetry.dft | 8 ++++++++ examples/dft/symmetry2.dft | 8 ++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 examples/dft/pdep2.dft create mode 100644 examples/dft/symmetry.dft create mode 100644 examples/dft/symmetry2.dft diff --git a/benchmark_dft.py b/benchmark_dft.py index 54dadeacc..d2c43bf80 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -6,8 +6,8 @@ import time import math import argparse -STORM_PATH= "/Users/mvolk/develop/storm/build/src/storm-dft" -EXAMPLE_DIR= "/Users/mvolk/develop/storm/examples/dft/" +STORM_PATH= "/Users/mvolk/develop/dft-storm/build/src/storm-dft" +EXAMPLE_DIR= "/Users/mvolk/develop/dft-storm/examples/dft/" benchmarks = [ @@ -30,6 +30,8 @@ benchmarks = [ ("or", False, [1, 1]), ("pand", False, ["inf", 0.666667]), ("pand_param", True, ["-1", "(x)/(y+x)"]), + ("pdep", False, [0, 1]), #Compute + ("pdep2", False, [0, 1]), #Compute ("spare", False, [3.53846, 1]), ("spare2", False, [1.86957, 1]), ("spare3", False, [1.27273, 1]), @@ -37,6 +39,8 @@ benchmarks = [ ("spare5", False, [2.66667, 1]), # We discard the result 2.16667 from DFTCalc ("spare6", False, [1.4, 1]), ("spare7", False, [3.67333, 1]), + ("symmetry", False, [4.16667, 1]), + ("symmetry2", False, [3.06111, 1]), ("tripple_and1", False, [4.16667, 1]), ("tripple_and2", False, [3.66667, 1]), ("tripple_and2_c", False, [3.6667, 1]), diff --git a/examples/dft/pdep2.dft b/examples/dft/pdep2.dft new file mode 100644 index 000000000..ab1c7a9b8 --- /dev/null +++ b/examples/dft/pdep2.dft @@ -0,0 +1,9 @@ +toplevel "SF"; +"SF" or "A" "B" "PDEP"; +"A" pand "S" "MA"; +"B" and "MA" "MB"; +"PDEP" pdep=0.2 "MA" "S" "MB"; + +"S" lambda=0.5 dorm=0; +"MA" lambda=0.5 dorm=0; +"MB" lambda=0.5 dorm=0; diff --git a/examples/dft/symmetry.dft b/examples/dft/symmetry.dft new file mode 100644 index 000000000..6f4031d0b --- /dev/null +++ b/examples/dft/symmetry.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; diff --git a/examples/dft/symmetry2.dft b/examples/dft/symmetry2.dft new file mode 100644 index 000000000..6d04021bb --- /dev/null +++ b/examples/dft/symmetry2.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"C" lambda=0.5 dorm=0; +"D" lambda=2 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=2 dorm=0; From f67c92b526b4a618e8e2d75b7f2a339182496e0e Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 10 Feb 2016 16:36:54 +0100 Subject: [PATCH 075/246] FlexibleSparseMatrix is in own class now Former-commit-id: fdc569e4438bb1ae9687c7fe7db3de51d015d8cb --- .../SparseDtmcEliminationModelChecker.cpp | 205 +++++------------- .../SparseDtmcEliminationModelChecker.h | 70 ++---- src/storage/FlexibleSparseMatrix.cpp | 114 +++++++--- src/storage/FlexibleSparseMatrix.h | 115 ++++++++-- 4 files changed, 252 insertions(+), 252 deletions(-) diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 6ec1e6d86..0b520c168 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -260,10 +260,10 @@ namespace storm { std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. - FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(transitionMatrix); - flexibleMatrix.filter(maybeStates, maybeStates); - FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(backwardTransitions); - flexibleBackwardTransitions.filter(maybeStates, maybeStates); + storm::storage::FlexibleSparseMatrix flexibleMatrix(transitionMatrix); + flexibleMatrix.createSubmatrix(maybeStates, maybeStates); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(backwardTransitions); + flexibleBackwardTransitions.createSubmatrix(maybeStates, maybeStates); auto conversionEnd = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); @@ -345,11 +345,11 @@ namespace storm { stateValues[*representativeIt] = bsccValue; } - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type& representativeForwardRow = flexibleMatrix.getRow(*representativeIt); + FlexibleRowType& representativeForwardRow = flexibleMatrix.getRow(*representativeIt); representativeForwardRow.clear(); representativeForwardRow.shrink_to_fit(); - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt); + FlexibleRowType& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt); auto it = representativeBackwardRow.begin(), ite = representativeBackwardRow.end(); for (; it != ite; ++it) { if (it->getColumn() == *representativeIt) { @@ -739,8 +739,8 @@ namespace storm { } std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); - FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(submatrix); - FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(submatrixTransposed, true); + storm::storage::FlexibleSparseMatrix flexibleMatrix(submatrix); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(submatrixTransposed, true); std::chrono::high_resolution_clock::time_point conversionEnd = std::chrono::high_resolution_clock::now(); std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); @@ -791,7 +791,7 @@ namespace storm { for (auto const& element : currentRow) { // If any of the successors is a phi state, we eliminate it (wrt. all its phi predecessors). if (!psiStates.get(element.getColumn())) { - typename FlexibleSparseMatrix::row_type const& successorRow = flexibleMatrix.getRow(element.getColumn()); + FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn()); // Eliminate the successor only if there possibly is a psi state reachable through it. if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) { STORM_LOG_TRACE("Found non-psi successor " << element.getColumn() << " that needs to be eliminated."); @@ -821,7 +821,7 @@ namespace storm { for (auto const& element : currentRow) { // If any of the successors is a psi state, we eliminate it (wrt. all its psi predecessors). if (!phiStates.get(element.getColumn())) { - typename FlexibleSparseMatrix::row_type const& successorRow = flexibleMatrix.getRow(element.getColumn()); + FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn()); if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) { STORM_LOG_TRACE("Found non-phi successor " << element.getColumn() << " that needs to be eliminated."); eliminateState(element.getColumn(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, psiFilterCallback, false); @@ -890,7 +890,7 @@ namespace storm { } template - std::unique_ptr::StatePriorityQueue> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { + std::unique_ptr::StatePriorityQueue> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { STORM_LOG_TRACE("Creating state priority queue for states " << states); @@ -940,7 +940,7 @@ namespace storm { } template - void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::unique_ptr& priorityQueue, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { + void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::unique_ptr& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { ValueUpdateCallback valueUpdateCallback = [&values] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { values[state] = storm::utility::simplify(loopProbability * values[state]); }; PredecessorUpdateCallback predecessorCallback = [&values] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { values[predecessor] = storm::utility::simplify(values[predecessor] + storm::utility::simplify(probability * values[state])); }; @@ -959,7 +959,7 @@ namespace storm { } template - void SparseDtmcEliminationModelChecker::performOrdinaryStateElimination(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { + void SparseDtmcEliminationModelChecker::performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); std::size_t numberOfStatesToEliminate = statePriorities->size(); @@ -969,7 +969,7 @@ namespace storm { } template - uint_fast64_t SparseDtmcEliminationModelChecker::performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { + uint_fast64_t SparseDtmcEliminationModelChecker::performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { // When using the hybrid technique, we recursively treat the SCCs up to some size. std::vector entryStateQueue; STORM_LOG_DEBUG("Eliminating " << subsystem.size() << " states using the hybrid elimination technique." << std::endl); @@ -992,8 +992,8 @@ namespace storm { std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. - FlexibleSparseMatrix flexibleMatrix = getFlexibleSparseMatrix(transitionMatrix); - FlexibleSparseMatrix flexibleBackwardTransitions = getFlexibleSparseMatrix(backwardTransitions); + storm::storage::FlexibleSparseMatrix flexibleMatrix(transitionMatrix); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(backwardTransitions); auto conversionEnd = std::chrono::high_resolution_clock::now(); std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); @@ -1052,7 +1052,7 @@ namespace storm { } template - uint_fast64_t SparseDtmcEliminationModelChecker::treatScc(FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities) { + uint_fast64_t SparseDtmcEliminationModelChecker::treatScc(storm::storage::FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities) { uint_fast64_t maximalDepth = level; // If the SCCs are large enough, we try to split them further. @@ -1068,7 +1068,7 @@ namespace storm { storm::storage::BitVector remainingSccs(decomposition.size(), true); // First, get rid of the trivial SCCs. - storm::storage::BitVector statesInTrivialSccs(matrix.getNumberOfRows()); + storm::storage::BitVector statesInTrivialSccs(matrix.getRowCount()); for (uint_fast64_t sccIndex = 0; sccIndex < decomposition.size(); ++sccIndex) { storm::storage::StronglyConnectedComponent const& scc = decomposition.getBlock(sccIndex); if (scc.isTrivial()) { @@ -1130,17 +1130,14 @@ namespace storm { } template - void SparseDtmcEliminationModelChecker::eliminateState(storm::storage::sparse::state_type state, FlexibleSparseMatrix& matrix, FlexibleSparseMatrix& backwardTransitions, - ValueUpdateCallback const& callback, PredecessorUpdateCallback const& predecessorCallback, - boost::optional const& priorityUpdateCallback, - boost::optional const& predecessorFilterCallback, bool removeForwardTransitions) { + void SparseDtmcEliminationModelChecker::eliminateState(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix& matrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, ValueUpdateCallback const& callback, PredecessorUpdateCallback const& predecessorCallback, boost::optional const& priorityUpdateCallback, boost::optional const& predecessorFilterCallback, bool removeForwardTransitions) { STORM_LOG_TRACE("Eliminating state " << state << "."); // Start by finding loop probability. bool hasSelfLoop = false; ValueType loopProbability = storm::utility::zero(); - typename FlexibleSparseMatrix::row_type& currentStateSuccessors = matrix.getRow(state); + FlexibleRowType& currentStateSuccessors = matrix.getRow(state); for (auto entryIt = currentStateSuccessors.begin(), entryIte = currentStateSuccessors.end(); entryIt != entryIte; ++entryIt) { if (entryIt->getColumn() >= state) { if (entryIt->getColumn() == state) { @@ -1172,12 +1169,12 @@ namespace storm { } // Now connect the predecessors of the state being eliminated with its successors. - typename FlexibleSparseMatrix::row_type& currentStatePredecessors = backwardTransitions.getRow(state); + FlexibleRowType& currentStatePredecessors = backwardTransitions.getRow(state); // In case we have a constrained elimination, we need to keep track of the new predecessors. - typename FlexibleSparseMatrix::row_type newCurrentStatePredecessors; + FlexibleRowType newCurrentStatePredecessors; - std::vector newBackwardProbabilities(currentStateSuccessors.size()); + std::vector newBackwardProbabilities(currentStateSuccessors.size()); for (auto& backwardProbabilities : newBackwardProbabilities) { backwardProbabilities.reserve(currentStatePredecessors.size()); } @@ -1203,8 +1200,8 @@ namespace storm { // First, find the probability with which the predecessor can move to the current state, because // the forward probabilities of the state to be eliminated need to be scaled with this factor. - typename FlexibleSparseMatrix::row_type& predecessorForwardTransitions = matrix.getRow(predecessor); - typename FlexibleSparseMatrix::row_type::iterator multiplyElement = std::find_if(predecessorForwardTransitions.begin(), predecessorForwardTransitions.end(), [&](storm::storage::MatrixEntry const& a) { return a.getColumn() == state; }); + FlexibleRowType& predecessorForwardTransitions = matrix.getRow(predecessor); + FlexibleRowIterator multiplyElement = std::find_if(predecessorForwardTransitions.begin(), predecessorForwardTransitions.end(), [&](storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() == state; }); // Make sure we have found the probability and set it to zero. STORM_LOG_THROW(multiplyElement != predecessorForwardTransitions.end(), storm::exceptions::InvalidStateException, "No probability for successor found."); @@ -1212,14 +1209,14 @@ namespace storm { multiplyElement->setValue(storm::utility::zero()); // At this point, we need to update the (forward) transitions of the predecessor. - typename FlexibleSparseMatrix::row_type::iterator first1 = predecessorForwardTransitions.begin(); - typename FlexibleSparseMatrix::row_type::iterator last1 = predecessorForwardTransitions.end(); - typename FlexibleSparseMatrix::row_type::iterator first2 = currentStateSuccessors.begin(); - typename FlexibleSparseMatrix::row_type::iterator last2 = currentStateSuccessors.end(); + FlexibleRowIterator first1 = predecessorForwardTransitions.begin(); + FlexibleRowIterator last1 = predecessorForwardTransitions.end(); + FlexibleRowIterator first2 = currentStateSuccessors.begin(); + FlexibleRowIterator last2 = currentStateSuccessors.end(); - typename FlexibleSparseMatrix::row_type newSuccessors; + FlexibleRowType newSuccessors; newSuccessors.reserve((last1 - first1) + (last2 - first2)); - std::insert_iterator result(newSuccessors, newSuccessors.end()); + std::insert_iterator result(newSuccessors, newSuccessors.end()); uint_fast64_t successorOffsetInNewBackwardTransitions = 0; // Now we merge the two successor lists. (Code taken from std::set_union and modified to suit our needs). @@ -1236,7 +1233,7 @@ namespace storm { } if (first2 == last2) { - std::copy_if(first1, last1, result, [&] (storm::storage::MatrixEntry const& a) { return a.getColumn() != state; } ); + std::copy_if(first1, last1, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state; } ); break; } if (first2->getColumn() < first1->getColumn()) { @@ -1251,7 +1248,7 @@ namespace storm { ++first1; } else { auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue())); - *result = storm::storage::MatrixEntry(first1->getColumn(), probability); + *result = storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type>(first1->getColumn(), probability); newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability); // std::cout << "(2) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; ++first1; @@ -1288,7 +1285,7 @@ namespace storm { continue; } - typename FlexibleSparseMatrix::row_type& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn()); + FlexibleRowType& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn()); // std::cout << "old backward trans of " << successorEntry.getColumn() << std::endl; // for (auto const& trans : successorBackwardTransitions) { // std::cout << trans << std::endl; @@ -1297,24 +1294,24 @@ namespace storm { // Delete the current state as a predecessor of the successor state only if we are going to remove the // current state's forward transitions. if (removeForwardTransitions) { - typename FlexibleSparseMatrix::row_type::iterator elimIt = std::find_if(successorBackwardTransitions.begin(), successorBackwardTransitions.end(), [&](storm::storage::MatrixEntry const& a) { return a.getColumn() == state; }); + FlexibleRowIterator elimIt = std::find_if(successorBackwardTransitions.begin(), successorBackwardTransitions.end(), [&](storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() == state; }); STORM_LOG_ASSERT(elimIt != successorBackwardTransitions.end(), "Expected a proper backward transition from " << successorEntry.getColumn() << " to " << state << ", but found none."); successorBackwardTransitions.erase(elimIt); } - typename FlexibleSparseMatrix::row_type::iterator first1 = successorBackwardTransitions.begin(); - typename FlexibleSparseMatrix::row_type::iterator last1 = successorBackwardTransitions.end(); - typename FlexibleSparseMatrix::row_type::iterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin(); - typename FlexibleSparseMatrix::row_type::iterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end(); + FlexibleRowIterator first1 = successorBackwardTransitions.begin(); + FlexibleRowIterator last1 = successorBackwardTransitions.end(); + FlexibleRowIterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin(); + FlexibleRowIterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end(); // std::cout << "adding backward trans " << successorEntry.getColumn() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; // for (auto const& trans : newBackwardProbabilities[successorOffsetInNewBackwardTransitions]) { // std::cout << trans << std::endl; // } - typename FlexibleSparseMatrix::row_type newPredecessors; + FlexibleRowType newPredecessors; newPredecessors.reserve((last1 - first1) + (last2 - first2)); - std::insert_iterator result(newPredecessors, newPredecessors.end()); + std::insert_iterator result(newPredecessors, newPredecessors.end()); for (; first1 != last1; ++result) { if (first2 == last2) { @@ -1340,9 +1337,9 @@ namespace storm { } } if (predecessorFilterCallback) { - std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry const& a) { return a.getColumn() != state && predecessorFilterCallback.get()(a.getColumn()); }); + std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state && predecessorFilterCallback.get()(a.getColumn()); }); } else { - std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry const& a) { return a.getColumn() != state; }); + std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state; }); } // Now move the new predecessors in place. @@ -1416,111 +1413,7 @@ namespace storm { } template - SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::FlexibleSparseMatrix(index_type rows) : data(rows) { - // Intentionally left empty. - } - - template - void SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::reserveInRow(index_type row, index_type numberOfElements) { - this->data[row].reserve(numberOfElements); - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type& SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::getRow(index_type index) { - return this->data[index]; - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::row_type const& SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::getRow(index_type index) const { - return this->data[index]; - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::index_type SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::getNumberOfRows() const { - return this->data.size(); - } - - template - bool SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::hasSelfLoop(storm::storage::sparse::state_type state) { - for (auto const& entry : this->getRow(state)) { - if (entry.getColumn() < state) { - continue; - } else if (entry.getColumn() > state) { - return false; - } else if (entry.getColumn() == state) { - return true; - } - } - return false; - } - - template - void SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::print() const { - for (uint_fast64_t index = 0; index < this->data.size(); ++index) { - std::cout << index << " - "; - for (auto const& element : this->getRow(index)) { - std::cout << "(" << element.getColumn() << ", " << element.getValue() << ") "; - } - std::cout << std::endl; - } - } - - template - bool SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::empty() const { - for (auto const& row : this->data) { - if (!row.empty()) { - return false; - } - } - return true; - } - - template - void SparseDtmcEliminationModelChecker::FlexibleSparseMatrix::filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter) { - for (uint_fast64_t rowIndex = 0; rowIndex < this->data.size(); ++rowIndex) { - auto& row = this->data[rowIndex]; - if (!rowFilter.get(rowIndex)) { - row.clear(); - row.shrink_to_fit(); - continue; - } - row_type newRow; - for (auto const& element : row) { - if (columnFilter.get(element.getColumn())) { - newRow.push_back(element); - } - } - row = std::move(newRow); - } - } - - template - typename SparseDtmcEliminationModelChecker::FlexibleSparseMatrix SparseDtmcEliminationModelChecker::getFlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) { - FlexibleSparseMatrix flexibleMatrix(matrix.getRowCount()); - - for (typename FlexibleSparseMatrix::index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { - typename storm::storage::SparseMatrix::const_rows row = matrix.getRow(rowIndex); - flexibleMatrix.reserveInRow(rowIndex, row.getNumberOfEntries()); - - for (auto const& element : row) { - // If the probability is zero, we skip this entry. - if (storm::utility::isZero(element.getValue())) { - continue; - } - - if (setAllValuesToOne) { - flexibleMatrix.getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one()); - } else { - flexibleMatrix.getRow(rowIndex).emplace_back(element); - } - } - } - - return flexibleMatrix; - } - - template - uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenalty(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { uint_fast64_t penalty = 0; bool hasParametricSelfLoop = false; @@ -1547,12 +1440,12 @@ namespace storm { } template - uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + uint_fast64_t SparseDtmcEliminationModelChecker::computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size(); } template - void SparseDtmcEliminationModelChecker::StatePriorityQueue::update(storm::storage::sparse::state_type, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + void SparseDtmcEliminationModelChecker::StatePriorityQueue::update(storm::storage::sparse::state_type, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { // Intentionally left empty. } @@ -1605,7 +1498,7 @@ namespace storm { } template - void SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::update(storm::storage::sparse::state_type state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + void SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { // First, we need to find the priority until now. auto priorityIt = stateToPriorityMapping.find(state); @@ -1634,8 +1527,8 @@ namespace storm { } template - bool SparseDtmcEliminationModelChecker::checkConsistent(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions) { - for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.getNumberOfRows(); ++forwardIndex) { + bool SparseDtmcEliminationModelChecker::checkConsistent(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions) { + for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.getRowCount(); ++forwardIndex) { for (auto const& forwardEntry : transitionMatrix.getRow(forwardIndex)) { if (forwardEntry.getColumn() == forwardIndex) { continue; diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 692a6be57..30c8e528a 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -2,6 +2,7 @@ #define STORM_MODELCHECKER_REACHABILITY_SPARSEDTMCELIMINATIONMODELCHECKER_H_ #include "src/storage/sparse/StateType.h" +#include "src/storage/FlexibleSparseMatrix.h" #include "src/models/sparse/Dtmc.h" #include "src/modelchecker/propositional/SparsePropositionalModelChecker.h" #include "src/utility/constants.h" @@ -14,7 +15,9 @@ namespace storm { public: typedef typename SparseDtmcModelType::ValueType ValueType; typedef typename SparseDtmcModelType::RewardModelType RewardModelType; - + typedef typename storm::storage::FlexibleSparseMatrix::row_type FlexibleRowType; + typedef typename FlexibleRowType::iterator FlexibleRowIterator; + /*! * Creates an elimination-based model checker for the given model. * @@ -33,47 +36,12 @@ namespace storm { virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; private: - class FlexibleSparseMatrix { - public: - typedef uint_fast64_t index_type; - typedef ValueType value_type; - typedef std::vector> row_type; - typedef typename row_type::iterator iterator; - typedef typename row_type::const_iterator const_iterator; - - FlexibleSparseMatrix() = default; - FlexibleSparseMatrix(index_type rows); - - void reserveInRow(index_type row, index_type numberOfElements); - - row_type& getRow(index_type); - row_type const& getRow(index_type) const; - - index_type getNumberOfRows() const; - - void print() const; - - bool empty() const; - - void filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter); - - /*! - * Checks whether the given state has a self-loop with an arbitrary probability in the probability matrix. - * - * @param state The state for which to check whether it possesses a self-loop. - * @return True iff the given state has a self-loop with an arbitrary probability in the probability matrix. - */ - bool hasSelfLoop(storm::storage::sparse::state_type state); - - private: - std::vector data; - }; - + class StatePriorityQueue { public: virtual bool hasNextState() const = 0; virtual storm::storage::sparse::state_type popNextState() = 0; - virtual void update(storm::storage::sparse::state_type state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); virtual std::size_t size() const = 0; }; @@ -96,7 +64,7 @@ namespace storm { } }; - typedef std::function const& oneStepProbabilities)> PenaltyFunctionType; + typedef std::function const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities)> PenaltyFunctionType; class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue { public: @@ -104,7 +72,7 @@ namespace storm { virtual bool hasNextState() const override; virtual storm::storage::sparse::state_type popNextState() override; - virtual void update(storm::storage::sparse::state_type state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) override; + virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) override; virtual std::size_t size() const override; private: @@ -117,38 +85,36 @@ namespace storm { static std::vector computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget); - static std::unique_ptr createStatePriorityQueue(boost::optional> const& stateDistances, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); + static std::unique_ptr createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); static std::unique_ptr createNaivePriorityQueue(storm::storage::BitVector const& states); - static void performPrioritizedStateElimination(std::unique_ptr& priorityQueue, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); + static void performPrioritizedStateElimination(std::unique_ptr& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); - static void performOrdinaryStateElimination(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional>& additionalStateValues, boost::optional> const& distanceBasedPriorities); + static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional>& additionalStateValues, boost::optional> const& distanceBasedPriorities); - static void performOrdinaryStateElimination(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); + static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); - static uint_fast64_t performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); + static uint_fast64_t performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); - static uint_fast64_t treatScc(FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities = boost::none); + static uint_fast64_t treatScc(storm::storage::FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities = boost::none); - static FlexibleSparseMatrix getFlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne = false); - typedef std::function ValueUpdateCallback; typedef std::function PredecessorUpdateCallback; typedef std::function PriorityUpdateCallback; typedef std::function PredecessorFilterCallback; - static void eliminateState(storm::storage::sparse::state_type state, FlexibleSparseMatrix& matrix, FlexibleSparseMatrix& backwardTransitions, ValueUpdateCallback const& valueUpdateCallback, PredecessorUpdateCallback const& predecessorCallback, boost::optional const& priorityUpdateCallback = boost::none, boost::optional const& predecessorFilterCallback = boost::none, bool removeForwardTransitions = true); + static void eliminateState(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix& matrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, ValueUpdateCallback const& valueUpdateCallback, PredecessorUpdateCallback const& predecessorCallback, boost::optional const& priorityUpdateCallback = boost::none, boost::optional const& predecessorFilterCallback = boost::none, bool removeForwardTransitions = true); static std::vector getDistanceBasedPriorities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward, bool reverse); static std::vector getStateDistances(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward); - static uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + static uint_fast64_t computeStatePenalty(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); - static uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, FlexibleSparseMatrix const& transitionMatrix, FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + static uint_fast64_t computeStatePenaltyRegularExpression(storm::storage::sparse::state_type const& state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); - static bool checkConsistent(FlexibleSparseMatrix& transitionMatrix, FlexibleSparseMatrix& backwardTransitions); + static bool checkConsistent(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions); // A flag that indicates whether this model checker is supposed to produce results for all states or just for the initial states. bool computeResultsForInitialStatesOnly; diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp index b77f59736..10cda2ab2 100644 --- a/src/storage/FlexibleSparseMatrix.cpp +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -2,14 +2,35 @@ #include "src/storage/SparseMatrix.h" #include "src/storage/BitVector.h" +#include "src/adapters/CarlAdapter.h" +#include "src/utility/constants.h" namespace storm { namespace storage { template - FlexibleSparseMatrix::FlexibleSparseMatrix(index_type rows) : data(rows) { + FlexibleSparseMatrix::FlexibleSparseMatrix(index_type rows) : data(rows), columnCount(0), nonzeroEntryCount(0) { // Intentionally left empty. } + template + FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()) { + for (index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { + typename storm::storage::SparseMatrix::const_rows row = matrix.getRow(rowIndex); + reserveInRow(rowIndex, row.getNumberOfEntries()); + for (auto const& element : row) { + // If the probability is zero, we skip this entry. + if (storm::utility::isZero(element.getValue())) { + continue; + } + if (setAllValuesToOne) { + getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one()); + } else { + getRow(rowIndex).emplace_back(element); + } + } + } + } + template void FlexibleSparseMatrix::reserveInRow(index_type row, index_type numberOfElements) { this->data[row].reserve(numberOfElements); @@ -26,35 +47,33 @@ namespace storm { } template - typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getNumberOfRows() const { + typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowCount() const { return this->data.size(); } template - bool FlexibleSparseMatrix::hasSelfLoop(storm::storage::sparse::state_type state) { - for (auto const& entry : this->getRow(state)) { - if (entry.getColumn() < state) { - continue; - } else if (entry.getColumn() > state) { - return false; - } else if (entry.getColumn() == state) { - return true; - } - } - return false; + typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getColumnCount() const { + return columnCount; } template - void FlexibleSparseMatrix::print() const { - for (uint_fast64_t index = 0; index < this->data.size(); ++index) { - std::cout << index << " - "; - for (auto const& element : this->getRow(index)) { - std::cout << "(" << element.getColumn() << ", " << element.getValue() << ") "; + typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getNonzeroEntryCount() const { + return nonzeroEntryCount; + } + + template + void FlexibleSparseMatrix::updateDimensions() { + this->nonzeroEntryCount = 0; + this->columnCount = 0; + for (auto const& row : this->data) { + for (auto const& element : row) { + assert(!storm::utility::isZero(element.getValue())); + ++this->nonzeroEntryCount; + this->columnCount = std::max(element.getColumn() + 1, this->columnCount); } - std::cout << std::endl; } } - + template bool FlexibleSparseMatrix::empty() const { for (auto const& row : this->data) { @@ -64,25 +83,68 @@ namespace storm { } return true; } - + template - void FlexibleSparseMatrix::filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter) { + void FlexibleSparseMatrix::createSubmatrix(storm::storage::BitVector const& rowConstraint, storm::storage::BitVector const& columnConstraint) { for (uint_fast64_t rowIndex = 0; rowIndex < this->data.size(); ++rowIndex) { auto& row = this->data[rowIndex]; - if (!rowFilter.get(rowIndex)) { + if (!rowConstraint.get(rowIndex)) { row.clear(); row.shrink_to_fit(); continue; } row_type newRow; for (auto const& element : row) { - if (columnFilter.get(element.getColumn())) { + if (columnConstraint.get(element.getColumn())) { newRow.push_back(element); } } row = std::move(newRow); } } + + template + storm::storage::SparseMatrix FlexibleSparseMatrix::createSparseMatrix() { + storm::storage::SparseMatrixBuilder matrixBuilder(getRowCount(), getColumnCount()); + for (uint_fast64_t rowIndex = 0; rowIndex < getRowCount(); ++rowIndex) { + auto& row = this->data[rowIndex]; + for (auto const& entry : row) { + matrixBuilder.addNextValue(rowIndex, entry.getColumn(), entry.getValue()); + } + } + return matrixBuilder.build(); + } + + template + bool FlexibleSparseMatrix::rowHasDiagonalElement(storm::storage::sparse::state_type state) { + for (auto const& entry : this->getRow(state)) { + if (entry.getColumn() < state) { + continue; + } else if (entry.getColumn() > state) { + return false; + } else if (entry.getColumn() == state) { + return true; + } + } + return false; + } + + template + std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix) { + for (uint_fast64_t index = 0; index < matrix->data.size(); ++index) { + out << index << " - "; + for (auto const& element : matrix->getRow(index)) { + out << "(" << element.getColumn() << ", " << element.getValue() << ") "; + } + return out; + } + } + + // Explicitly instantiate the matrix. + template class FlexibleSparseMatrix; +#ifdef STORM_HAVE_CARL + template class FlexibleSparseMatrix; +#endif - } -} \ No newline at end of file + } // namespace storage +} // namespace storm \ No newline at end of file diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index 6a30109ac..e6ac6c97d 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -5,6 +5,7 @@ #include #include "src/storage/sparse/StateType.h" +#include "src/storage/SparseMatrix.h" namespace storm { namespace storage { @@ -13,17 +14,14 @@ namespace storm { class BitVector; + /*! + * The flexible sparse matrix is used during state elimination. + */ template class FlexibleSparseMatrix { public: // TODO: make this class a bit more consistent with the big sparse matrix and improve it: - // * rename getNumberOfRows -> getRowCount - // * store number of columns to also provide getColumnCount - // * rename hasSelfLoop -> rowHasDiagonalElement // * add output iterator and improve the way the matrix is printed - // * add conversion functionality from/to sparse matrix - // * add documentation - // * rename filter to something more appropriate (getSubmatrix?) // * add stuff like clearRow, multiplyRowWithScalar typedef uint_fast64_t index_type; @@ -32,32 +30,113 @@ namespace storm { typedef typename row_type::iterator iterator; typedef typename row_type::const_iterator const_iterator; + /*! + * Constructs an empty flexible sparse matrix. + */ FlexibleSparseMatrix() = default; + + /*! + * Constructs a flexible sparse matrix with rows many rows. + * @param rows number of rows. + */ FlexibleSparseMatrix(index_type rows); - + + /*! + * Constructs a flexible sparse matrix from a sparse matrix. + * @param matrix Sparse matrix to construct from. + * @param setAllValuesToOne If true, all set entries are set to one. Default is false. + */ + FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne = false); + + /*! + * Reserves space for elements in row. + * @param row Row to reserve in. + * @param numberOfElements Number of elements to reserve space for. + */ void reserveInRow(index_type row, index_type numberOfElements); - + + /*! + * Returns an object representing the given row. + * + * @param row The row to get. + * @return An object representing the given row. + */ row_type& getRow(index_type); + + /*! + * Returns an object representing the given row. + * + * @param row The row to get. + * @return An object representing the given row. + */ row_type const& getRow(index_type) const; - - index_type getNumberOfRows() const; - - void print() const; - + + /*! + * Returns the number of rows of the matrix. + * + * @return The number of rows of the matrix. + */ + index_type getRowCount() const; + + /*! + * Returns the number of columns of the matrix. + * + * @return The number of columns of the matrix. + */ + index_type getColumnCount() const; + + /*! + * Returns the cached number of nonzero entries in the matrix. + * + * @return The number of nonzero entries in the matrix. + */ + index_type getNonzeroEntryCount() const; + + /*! + * Recomputes the number of columns and the number of non-zero entries. + */ + void updateDimensions(); + + /*! + * Checks if the matrix has no elements. + * @return True, if the matrix is empty. + */ bool empty() const; - - void filter(storm::storage::BitVector const& rowFilter, storm::storage::BitVector const& columnFilter); - + + /*! + * Creates a submatrix of the current matrix in place by dropping all rows and columns whose bits are not + * set to one in the given bit vector. + * + * @param rowConstraint A bit vector indicating which rows to keep. + * @param columnConstraint A bit vector indicating which columns to keep. + */ + void createSubmatrix(storm::storage::BitVector const& rowConstraint, storm::storage::BitVector const& columnConstraint); + + /*! + * Creates a sparse matrix from the flexible sparse matrix. + * @return The sparse matrix. + */ + storm::storage::SparseMatrix createSparseMatrix(); + /*! * Checks whether the given state has a self-loop with an arbitrary probability in the probability matrix. * * @param state The state for which to check whether it possesses a self-loop. * @return True iff the given state has a self-loop with an arbitrary probability in the probability matrix. */ - bool hasSelfLoop(storm::storage::sparse::state_type state); - + bool rowHasDiagonalElement(storm::storage::sparse::state_type state); + + template + friend std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix); + private: std::vector data; + + // The number of columns of the matrix. + index_type columnCount; + + // The number of entries in the matrix. + index_type nonzeroEntryCount; }; } } From 49dc27077c2d3e5546456cfb13da65af6015a206 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 10 Feb 2016 17:23:38 +0100 Subject: [PATCH 076/246] Added row grouping members (but not the needed logic) Former-commit-id: c4f7319e854fdc39e8a6d08caaa5099a923088ed --- src/storage/FlexibleSparseMatrix.cpp | 13 ++++++++++++- src/storage/FlexibleSparseMatrix.h | 19 +++++++++++++++++++ src/storage/SparseMatrix.cpp | 5 +++++ src/storage/SparseMatrix.h | 7 +++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp index 10cda2ab2..81e87ce20 100644 --- a/src/storage/FlexibleSparseMatrix.cpp +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -13,7 +13,13 @@ namespace storm { } template - FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()) { + FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()), nontrivialRowGrouping(matrix.hasNontrivialRowGrouping()) { + if (nontrivialRowGrouping) { + rowGroupIndices = matrix.getRowGroupIndices(); + rowIndications = matrix.getRowIndications(); + // Not fully implemented yet + assert(false); + } for (index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { typename storm::storage::SparseMatrix::const_rows row = matrix.getRow(rowIndex); reserveInRow(rowIndex, row.getNumberOfEntries()); @@ -83,6 +89,11 @@ namespace storm { } return true; } + + template + bool SparseMatrix::hasNontrivialRowGrouping() const { + return nontrivialRowGrouping; + } template void FlexibleSparseMatrix::createSubmatrix(storm::storage::BitVector const& rowConstraint, storm::storage::BitVector const& columnConstraint) { diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index e6ac6c97d..295b0337b 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -23,6 +23,7 @@ namespace storm { // TODO: make this class a bit more consistent with the big sparse matrix and improve it: // * add output iterator and improve the way the matrix is printed // * add stuff like clearRow, multiplyRowWithScalar + // * implement row grouping typedef uint_fast64_t index_type; typedef ValueType value_type; @@ -102,6 +103,13 @@ namespace storm { * @return True, if the matrix is empty. */ bool empty() const; + + /*! + * Retrieves whether the matrix has a (possibly) non-trivial row grouping. + * + * @return True iff the matrix has a (possibly) non-trivial row grouping. + */ + bool hasNontrivialRowGrouping() const; /*! * Creates a submatrix of the current matrix in place by dropping all rows and columns whose bits are not @@ -137,6 +145,17 @@ namespace storm { // The number of entries in the matrix. index_type nonzeroEntryCount; + + // A vector containing the indices at which each given row begins. The values of the entries in row i are + // data[rowIndications[i]] to data[rowIndications[i + 1]] where the last entry is not included anymore. + std::vector rowIndications; + + // A flag that indicates whether the matrix has a non-trivial row-grouping, i.e. (possibly) more than one + // row per row group. + bool nontrivialRowGrouping; + + // A vector indicating the row groups of the matrix. + std::vector rowGroupIndices; }; } } diff --git a/src/storage/SparseMatrix.cpp b/src/storage/SparseMatrix.cpp index 253609210..04e941561 100644 --- a/src/storage/SparseMatrix.cpp +++ b/src/storage/SparseMatrix.cpp @@ -451,6 +451,11 @@ namespace storm { std::vector::index_type> const& SparseMatrix::getRowGroupIndices() const { return rowGroupIndices; } + + template + std::vector::index_type> const& SparseMatrix::getRowIndications() const { + return rowIndications; + } template void SparseMatrix::makeRowsAbsorbing(storm::storage::BitVector const& rows) { diff --git a/src/storage/SparseMatrix.h b/src/storage/SparseMatrix.h index f9d9916c4..94defdfa5 100644 --- a/src/storage/SparseMatrix.h +++ b/src/storage/SparseMatrix.h @@ -549,6 +549,13 @@ namespace storm { */ std::vector const& getRowGroupIndices() const; + /*! + * Returns the indices where new row groups start. + * + * @return The indices where new row groups start. + */ + std::vector const& getRowIndications() const; + /*! * This function makes the given rows absorbing. * From c319a997dad06c0deb8a156ebf278483ac569be0 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 10 Feb 2016 18:10:44 +0100 Subject: [PATCH 077/246] cmake lists from future Former-commit-id: b3bc2f1bfb37a28baa6fbf503db1909a4c21c93d --- CMakeLists.txt | 4 ++-- resources/3rdparty/cudd-2.5.0/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f6a50f70..76d554806 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,7 +132,7 @@ else(CLANG) endif() add_definitions(-DBOOST_RESULT_OF_USE_DECLTYPE) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -stdlib=${CLANG_STDLIB} -Wall -pedantic -Wno-newline-eof -Wno-mismatched-tags -Wno-unused-local-typedefs -ftemplate-depth=1024") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -stdlib=${CLANG_STDLIB} -Wall -pedantic -Wno-newline-eof -Wno-mismatched-tags -Wno-unused-local-typedefs -ftemplate-depth=1024 -Wno-parentheses-equality") if(FORCE_COLOR) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcolor-diagnostics") @@ -188,7 +188,7 @@ if(CUSTOM_BOOST_ROOT) set(BOOST_ROOT "${CUSTOM_BOOST_ROOT}") endif(CUSTOM_BOOST_ROOT) -find_package(Boost REQUIRED) +find_package(Boost 1.56.0 REQUIRED) if ((NOT Boost_LIBRARY_DIRS) OR ("${Boost_LIBRARY_DIRS}" STREQUAL "")) set(Boost_LIBRARY_DIRS "${Boost_INCLUDE_DIRS}/stage/lib") diff --git a/resources/3rdparty/cudd-2.5.0/CMakeLists.txt b/resources/3rdparty/cudd-2.5.0/CMakeLists.txt index 4a39bd5da..5df298c34 100644 --- a/resources/3rdparty/cudd-2.5.0/CMakeLists.txt +++ b/resources/3rdparty/cudd-2.5.0/CMakeLists.txt @@ -26,7 +26,7 @@ elseif(MSVC) # required for GMM to compile, ugly error directive in their code add_definitions(/D_SCL_SECURE_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS) else(CLANG) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-newline-eof -Wno-unneeded-internal-declaration -Wno-unused-variable -Wno-unused-const-variable") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-newline-eof -Wno-unneeded-internal-declaration -Wno-unused-variable -Wno-unused-const-variable -Wno-parentheses-equality") endif() # Since we do not target Alphas, this symbol is always set From 42eb6714358d412d74590dc256d6bbab4b18ef13 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 10 Feb 2016 21:48:26 +0100 Subject: [PATCH 078/246] work towards const correctness and additional methods Former-commit-id: 2c4667412c5b690e187a9f299b48c698e0ccf91c --- src/builder/ExplicitDFTModelBuilder.cpp | 6 ++-- src/builder/ExplicitDFTModelBuilder.h | 1 + src/storage/dft/DFT.cpp | 9 +++--- src/storage/dft/DFT.h | 41 ++++++++++++++++++++----- src/storage/dft/DFTState.cpp | 10 +++--- src/storage/dft/DFTState.h | 2 +- 6 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 817295346..084b5fe7a 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -137,8 +137,8 @@ namespace storm { // Construct new state as copy from original one DFTStatePointer newState = std::make_shared>(*state); - std::pair>, bool> nextBEPair = newState->letNextBEFail(smallest++); - std::shared_ptr> nextBE = nextBEPair.first; + std::pair const>, bool> nextBEPair = newState->letNextBEFail(smallest++); + std::shared_ptr const>& nextBE = nextBEPair.first; assert(nextBE); assert(nextBEPair.second == hasDependencies); STORM_LOG_TRACE("with the failure of: " << nextBE->name() << " [" << nextBE->id() << "]"); @@ -192,7 +192,7 @@ namespace storm { // Set failure rate according to usage bool isUsed = true; if (mDft.hasRepresentant(nextBE->id())) { - DFTElementPointer representant = mDft.getRepresentant(nextBE->id()); + DFTElementCPointer representant = mDft.getRepresentant(nextBE->id()); // Used must be checked for the state we are coming from as this state is responsible for the // rate and not the new state we are going to isUsed = state->isUsed(representant->id()); diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 6125b6fa1..67dec3dc4 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -20,6 +20,7 @@ namespace storm { class ExplicitDFTModelBuilder { using DFTElementPointer = std::shared_ptr>; + using DFTElementCPointer = std::shared_ptr const>; using DFTGatePointer = std::shared_ptr>; using DFTStatePointer = std::shared_ptr>; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 319a08925..b3f0dce7a 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -148,11 +148,10 @@ namespace storm { } template - bool DFT::rootOfClosedSubDFT(size_t index) const { - //boost::container::flat_set marked; - //DFTElementPointer elem = getElement(index); - - + std::vector DFT::getIndependentSubDftRoots(size_t index) const { + auto elem = getElement(index); + auto ISD = elem->independentSubDft(); + return ISD; } // Explicitly instantiate the class. diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 92f1c0531..ecea467e4 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -9,7 +9,6 @@ #include -#include "DFTIsomorphism.h" #include "DFTElements.h" #include "../BitVector.h" @@ -37,6 +36,7 @@ namespace storm { class DFT { using DFTElementPointer = std::shared_ptr>; + using DFTElementCPointer = std::shared_ptr const>; using DFTElementVector = std::vector; using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; @@ -148,15 +148,40 @@ namespace storm { * Get a pointer to an element in the DFT * @param index The id of the element */ - DFTElementPointer const& getElement(size_t index) const { + DFTElementCPointer getElement(size_t index) const { assert(index < nrElements()); return mElements[index]; } - std::shared_ptr> getBasicElement(size_t index) const { - assert(index < nrElements()); - assert(mElements[index]->isBasicElement()); - return std::static_pointer_cast>(mElements[index]); + bool isBasicElement(size_t index) const { + return getElement(index)->isBasicElement(); + } + + bool isGate(size_t index) const { + return getElement(index)->isGate(); + } + + bool isDependency(size_t index) const { + return getElement(index)->isDependency(); + } + +// std::shared_ptr const> getGate(size_t index) const { +// return +// } + + std::shared_ptr const> getBasicElement(size_t index) const { + assert(isBasicElement(index)); + return std::static_pointer_cast const>(mElements[index]); + } + + std::shared_ptr const> getGate(size_t index) const { + assert(isGate(index)); + return std::static_pointer_cast const>(mElements[index]); + } + + std::shared_ptr const> getDependency(size_t index) const { + assert(isDependency(index)); + return std::static_pointer_cast const>(mElements[index]); } std::vector>> getBasicElements() const { @@ -173,7 +198,7 @@ namespace storm { return mRepresentants.find(id) != mRepresentants.end(); } - DFTElementPointer getRepresentant(size_t id) const { + DFTElementCPointer getRepresentant(size_t id) const { assert(hasRepresentant(id)); return getElement(mRepresentants.find(id)->second); } @@ -196,7 +221,7 @@ namespace storm { std::string getStateString(DFTStatePointer const& state) const; - bool rootOfClosedSubDFT(size_t id) const; + std::vector getIndependentSubDftRoots(size_t index) const; private: bool elementIndicesCorrect() const { for(size_t i = 0; i < mElements.size(); ++i) { diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 17bb4aee8..672ca14a7 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -82,7 +82,7 @@ namespace storm { bool DFTState::updateFailableDependencies(size_t id) { assert(hasFailed(id)); for (size_t i = 0; i < mDft.getDependencies().size(); ++i) { - std::shared_ptr> dependency = std::static_pointer_cast>(mDft.getElement(mDft.getDependencies()[i])); + std::shared_ptr const> dependency = mDft.getDependency(mDft.getDependencies()[i]); if (dependency->triggerEvent()->id() == id) { if (!hasFailed(dependency->dependentEvent()->id())) { mFailableDependencies.push_back(dependency->id()); @@ -94,21 +94,21 @@ namespace storm { } template - std::pair>, bool> DFTState::letNextBEFail(size_t index) + std::pair const>, bool> DFTState::letNextBEFail(size_t index) { STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); if (nrFailableDependencies() > 0) { // Consider failure due to dependency assert(index < nrFailableDependencies()); - std::shared_ptr> dependency = std::static_pointer_cast>(mDft.getElement(mFailableDependencies[index])); - std::pair>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true); + std::shared_ptr const> dependency = mDft.getDependency(mFailableDependencies[index]); + std::pair const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true); mFailableDependencies.erase(mFailableDependencies.begin() + index); setFailed(res.first->id()); return res; } else { // Consider "normal" failure assert(index < nrFailableBEs()); - std::pair>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); + std::pair const>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); setFailed(res.first->id()); return res; diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index a1bab2583..17a9c2d3b 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -127,7 +127,7 @@ namespace storm { * @param smallestIndex Index in currentlyFailableBE of BE to fail * @return Pair of BE which fails and flag indicating if the failure was due to functional dependencies */ - std::pair>, bool> letNextBEFail(size_t smallestIndex = 0); + std::pair const>, bool> letNextBEFail(size_t smallestIndex = 0); std::string getCurrentlyFailableString() const { std::stringstream stream; From 0e38738e099de659707bc17fac9d51051a1afa7a Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 11 Feb 2016 00:16:12 +0100 Subject: [PATCH 079/246] DFT element types and some extensions to the elements API Former-commit-id: cb70dee35af68d359e3f011cc4ff962813fdc508 --- src/storage/dft/DFTBuilder.cpp | 2 +- src/storage/dft/DFTElementType.h | 4 +- src/storage/dft/DFTElements.h | 77 ++++++++++++++++++++++++++------ 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index fffd33946..00e416d54 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -109,7 +109,7 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type handled separately."); case DFTElementType::CONSTF: case DFTElementType::CONSTS: - case DFTElementType::FDEP: + case DFTElementType::PDEP: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); default: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not known."); diff --git a/src/storage/dft/DFTElementType.h b/src/storage/dft/DFTElementType.h index 9aba9fa54..98d58df5c 100644 --- a/src/storage/dft/DFTElementType.h +++ b/src/storage/dft/DFTElementType.h @@ -4,7 +4,7 @@ namespace storm { namespace storage { - enum class DFTElementType : int {AND = 0, COUNTING = 1, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, FDEP = 10, SEQAND = 11}; + enum class DFTElementType : int {AND = 0, COUNTING = 1, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, PDEP = 10, SEQAND = 11}; inline bool isGateType(DFTElementType const& tp) { switch(tp) { @@ -20,7 +20,7 @@ namespace storm { case DFTElementType::BE: case DFTElementType::CONSTF: case DFTElementType::CONSTS: - case DFTElementType::FDEP: + case DFTElementType::PDEP: return false; default: assert(false); diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index fb5123180..a6ee87ea5 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -51,6 +51,8 @@ namespace storm { return mId; } + virtual DFTElementType type() const = 0; + virtual void setRank(size_t rank) { mRank = rank; } @@ -114,7 +116,11 @@ namespace storm { bool hasParents() const { return !mParents.empty(); } - + + size_t nrParents() const { + return mParents.size(); + } + DFTGateVector const& parents() const { return mParents; } @@ -348,7 +354,11 @@ namespace storm { DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) {} - + + DFTElementType type() const override { + return DFTElementType::BE; + } + virtual size_t nrChildren() const { return 0; } @@ -393,7 +403,16 @@ namespace storm { DFTConst(size_t id, std::string const& name, bool failed) : DFTElement(id, name), mFailed(failed) {} - + + DFTElementType type() const override { + if(mFailed) { + return DFTElementType::CONSTF; + } else { + return DFTElementType::CONSTS; + } + } + + bool failed() const { return mFailed; } @@ -438,15 +457,15 @@ namespace storm { mDependentEvent = dependentEvent; } - std::string nameTrigger() { + std::string nameTrigger() const { return mNameTrigger; } - std::string nameDependent() { + std::string nameDependent() const { return mNameDependent; } - ValueType probability() { + ValueType const& probability() const { return mProbability; } @@ -460,6 +479,10 @@ namespace storm { return mDependentEvent; } + DFTElementType type() const override { + return DFTElementType::PDEP; + } + virtual size_t nrChildren() const override { return 1; } @@ -519,6 +542,10 @@ namespace storm { this->childrenDontCare(state, queues); } } + + virtual DFTElementType type() const override { + return DFTElementType::AND; + } std::string typestring() const { return "AND"; @@ -555,6 +582,10 @@ namespace storm { } this->failsafe(state, queues); } + + virtual DFTElementType type() const override { + return DFTElementType::OR; + } std::string typestring() const { return "OR"; @@ -606,8 +637,12 @@ namespace storm { } //return false; } - - std::string typestring() const { + + virtual DFTElementType type() const override { + return DFTElementType::SEQAND; + } + + std::string typestring() const override { return "SEQAND"; } }; @@ -653,8 +688,12 @@ namespace storm { this->childrenDontCare(state, queues); } } + + virtual DFTElementType type() const override { + return DFTElementType::PAND; + } - std::string typestring() const { + std::string typestring() const override { return "PAND"; } }; @@ -680,8 +719,12 @@ namespace storm { void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(false); } + + virtual DFTElementType type() const override { + return DFTElementType::POR; + } - std::string typestring() const { + std::string typestring() const override { return "POR"; } }; @@ -740,6 +783,10 @@ namespace storm { } } } + + virtual DFTElementType type() const override { + return DFTElementType::VOT; + } std::string typestring() const { return "VOT (" + std::to_string(mThreshold) + ")"; @@ -766,11 +813,15 @@ namespace storm { DFTGate(id, name, children) {} - std::string typestring() const { + std::string typestring() const override { return "SPARE"; } - - bool isSpareGate() const { + + virtual DFTElementType type() const override { + return DFTElementType::SPARE; + } + + bool isSpareGate() const override { return true; } From 27521fc0272ef031a60ec0f7fa2e4114d414fc5a Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 11 Feb 2016 00:19:29 +0100 Subject: [PATCH 080/246] fixed some warnings Former-commit-id: ed6fbfc6bae8ac7aeb51faba30e539425109857f --- src/storage/dft/DFTElements.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index a6ee87ea5..a1f4a5819 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -359,7 +359,7 @@ namespace storm { return DFTElementType::BE; } - virtual size_t nrChildren() const { + virtual size_t nrChildren() const override { return 0; } @@ -371,17 +371,17 @@ namespace storm { return mPassiveFailureRate; } - std::string toString() const { + std::string toString() const override { std::stringstream stream; stream << *this; return stream.str(); } - bool isBasicElement() const { + bool isBasicElement() const override{ return true; } - bool isColdBasicElement() const { + bool isColdBasicElement() const override{ return storm::utility::isZero(mPassiveFailureRate); } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; @@ -421,7 +421,7 @@ namespace storm { return true; } - virtual size_t nrChildren() const { + virtual size_t nrChildren() const override { return 0; } @@ -547,7 +547,7 @@ namespace storm { return DFTElementType::AND; } - std::string typestring() const { + std::string typestring() const override { return "AND"; } }; @@ -587,7 +587,7 @@ namespace storm { return DFTElementType::OR; } - std::string typestring() const { + std::string typestring() const override { return "OR"; } }; @@ -788,7 +788,7 @@ namespace storm { return DFTElementType::VOT; } - std::string typestring() const { + std::string typestring() const override{ return "VOT (" + std::to_string(mThreshold) + ")"; } From a1f05b185336bb8638c8d5eb24142dc517697c93 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 11 Feb 2016 10:38:26 +0100 Subject: [PATCH 081/246] Set override Former-commit-id: c8e7c5b690848caf5afbb3fbc15e7301f47e151a --- src/storage/dft/DFTElements.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index a1f4a5819..9778d9146 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -384,7 +384,7 @@ namespace storm { bool isColdBasicElement() const override{ return storm::utility::isZero(mPassiveFailureRate); } - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override; }; template @@ -523,7 +523,7 @@ namespace storm { DFTGate(id, name, children) {} - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { for(auto const& child : this->mChildren) { @@ -535,7 +535,7 @@ namespace storm { } } - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(this->hasFailsafeChild(state)); if(state.isOperational(this->mId)) { this->failsafe(state, queues); @@ -567,14 +567,14 @@ namespace storm { DFTGate(id, name, children) {} - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(this->hasFailedChild(state)); if(state.isOperational(this->mId)) { this->fail(state, queues); } } - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { for(auto const& child : this->mChildren) { if(!state.isFailsafe(child->id())) { return; @@ -662,7 +662,7 @@ namespace storm { DFTGate(id, name, children) {} - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { bool childOperationalBefore = false; for(auto const& child : this->mChildren) @@ -681,7 +681,7 @@ namespace storm { } } - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(this->hasFailsafeChild(state)); if(state.isOperational(this->mId)) { this->failsafe(state, queues); @@ -712,11 +712,11 @@ namespace storm { DFTGate(id, name, children) {} - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(false); } - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(false); } @@ -747,7 +747,7 @@ namespace storm { DFTGate(id, name, children), mThreshold(threshold) {} - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { unsigned nrFailedChildren = 0; for(auto const& child : this->mChildren) @@ -765,7 +765,7 @@ namespace storm { } } - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(this->hasFailsafeChild(state)); if(state.isOperational(this->mId)) { unsigned nrFailsafeChildren = 0; @@ -838,7 +838,7 @@ namespace storm { state.setUsesAtPosition(mUseIndex, this->mChildren[0]->id()); } - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { size_t uses = state.extractUses(mUseIndex); if(!state.isOperational(uses)) { @@ -850,7 +850,7 @@ namespace storm { } } - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { if(state.isFailsafe(state.extractUses((mUseIndex)))) { this->failsafe(state, queues); From d60afed273dcef7be7ac6de77c35941ca276c745 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 11 Feb 2016 10:45:20 +0100 Subject: [PATCH 082/246] MA model checking can be called now for doubles Former-commit-id: a20f2babc4e950e720a8e5f346de5921d6843592 --- src/utility/storm.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/utility/storm.h b/src/utility/storm.h index 11dfe6d91..f297d9e41 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -59,6 +59,7 @@ #include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" #include "src/modelchecker/csl/SparseCtmcCslModelChecker.h" #include "src/modelchecker/csl/helper/SparseCtmcCslHelper.h" +#include "src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.h" #include "src/modelchecker/csl/HybridCtmcCslModelChecker.h" #include "src/modelchecker/results/ExplicitQualitativeCheckResult.h" #include "src/modelchecker/results/SymbolicQualitativeCheckResult.h" @@ -297,6 +298,13 @@ namespace storm { storm::modelchecker::SparseCtmcCslModelChecker> modelchecker(*ctmc); result = modelchecker.check(task); + } else if (model->getType() == storm::models::ModelType::MarkovAutomaton) { + std::shared_ptr> ma = model->template as>(); + + storm::modelchecker::SparseMarkovAutomatonCslModelChecker> modelchecker(*ma); + result = modelchecker.check(task); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The model type " << model->getType() << " is not supported."); } return result; From 7a10a04cde5e8a9f8ada836449b08ae4462eff2a Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 12 Feb 2016 13:18:04 +0100 Subject: [PATCH 083/246] Created StateEliminator with specialized subclasses Former-commit-id: 991e3fcfcdb061fbd1f9689692ea60faf48a1958 --- .../SparseDtmcEliminationModelChecker.cpp | 326 ++---------------- .../SparseDtmcEliminationModelChecker.h | 41 +-- .../ConditionalEliminator.cpp | 53 +++ .../stateelimination/ConditionalEliminator.h | 53 +++ .../LongRunAverageEliminator.cpp | 47 +++ .../LongRunAverageEliminator.h | 36 ++ .../PrioritizedEliminator.cpp | 45 +++ .../stateelimination/PrioritizedEliminator.h | 34 ++ .../stateelimination/StateEliminator.cpp | 259 ++++++++++++++ src/solver/stateelimination/StateEliminator.h | 42 +++ 10 files changed, 626 insertions(+), 310 deletions(-) create mode 100644 src/solver/stateelimination/ConditionalEliminator.cpp create mode 100644 src/solver/stateelimination/ConditionalEliminator.h create mode 100644 src/solver/stateelimination/LongRunAverageEliminator.cpp create mode 100644 src/solver/stateelimination/LongRunAverageEliminator.h create mode 100644 src/solver/stateelimination/PrioritizedEliminator.cpp create mode 100644 src/solver/stateelimination/PrioritizedEliminator.h create mode 100644 src/solver/stateelimination/StateEliminator.cpp create mode 100644 src/solver/stateelimination/StateEliminator.h diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 0b520c168..e01987f3f 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -25,6 +25,10 @@ #include "src/exceptions/InvalidSettingsException.h" #include "src/exceptions/IllegalArgumentException.h" +#include "src/solver/stateelimination/LongRunAverageEliminator.h" +#include "src/solver/stateelimination/ConditionalEliminator.h" +#include "src/solver/stateelimination/PrioritizedEliminator.h" + namespace storm { namespace modelchecker { @@ -300,30 +304,13 @@ namespace storm { std::vector averageTimeInStates(stateValues.size(), storm::utility::one()); // First, we eliminate all states in BSCCs (except for the representative states). - { - std::unique_ptr priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs); - - ValueUpdateCallback valueUpdateCallback = [&stateValues,&averageTimeInStates] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { - stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]); - averageTimeInStates[state] = storm::utility::simplify(loopProbability * averageTimeInStates[state]); - }; - - PredecessorUpdateCallback predecessorCallback = [&stateValues,&averageTimeInStates] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { - stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state])); - averageTimeInStates[predecessor] = storm::utility::simplify(averageTimeInStates[predecessor] + storm::utility::simplify(probability * averageTimeInStates[state])); - }; - - boost::optional priorityUpdateCallback = PriorityUpdateCallback([&flexibleMatrix,&flexibleBackwardTransitions,&stateValues,&priorityQueue] (storm::storage::sparse::state_type const& state) { - priorityQueue->update(state, flexibleMatrix, flexibleBackwardTransitions, stateValues); - }); - - boost::optional predecessorFilterCallback = boost::none; - - while (priorityQueue->hasNextState()) { - storm::storage::sparse::state_type state = priorityQueue->popNextState(); - eliminateState(state, flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorCallback, priorityUpdateCallback, predecessorFilterCallback, true); - STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions), "The forward and backward transition matrices became inconsistent."); - } + std::unique_ptr> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs); + storm::solver::stateelimination::LongRunAverageEliminator stateEliminator(flexibleMatrix, flexibleBackwardTransitions, *priorityQueue, stateValues, averageTimeInStates); + + while (priorityQueue->hasNextState()) { + storm::storage::sparse::state_type state = priorityQueue->popNextState(); + stateEliminator.eliminateState(state, true); + STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions), "The forward and backward transition matrices became inconsistent."); } // Now, we set the values of all states in BSCCs to that of the representative value (and clear the @@ -743,7 +730,7 @@ namespace storm { storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(submatrixTransposed, true); std::chrono::high_resolution_clock::time_point conversionEnd = std::chrono::high_resolution_clock::now(); - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); + std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); STORM_LOG_INFO("Computing conditional probilities." << std::endl); std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); @@ -752,15 +739,11 @@ namespace storm { performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(), true); STORM_LOG_INFO("Eliminated " << numberOfStatesToEliminate << " states." << std::endl); - // Prepare some callbacks for the elimination procedure. - ValueUpdateCallback valueUpdateCallback = [&oneStepProbabilities] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { oneStepProbabilities[state] = storm::utility::simplify(loopProbability * oneStepProbabilities[state]); }; - PredecessorUpdateCallback predecessorUpdateCallback = [&oneStepProbabilities] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { oneStepProbabilities[predecessor] = storm::utility::simplify(oneStepProbabilities[predecessor] * storm::utility::simplify(probability * oneStepProbabilities[state])); }; - boost::optional phiFilterCallback = PredecessorFilterCallback([&phiStates] (storm::storage::sparse::state_type const& state) { return phiStates.get(state); }); - boost::optional psiFilterCallback = PredecessorFilterCallback([&psiStates] (storm::storage::sparse::state_type const& state) { return psiStates.get(state); }); + storm::solver::stateelimination::ConditionalEliminator stateEliminator = storm::solver::stateelimination::ConditionalEliminator(flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, phiStates, psiStates); // Eliminate the transitions going into the initial state (if there are any). if (!flexibleBackwardTransitions.getRow(*newInitialStates.begin()).empty()) { - eliminateState(*newInitialStates.begin(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, boost::none, false); + stateEliminator.eliminateState(*newInitialStates.begin(), false); } // Now we need to basically eliminate all chains of not-psi states after phi states and chains of not-phi @@ -795,7 +778,9 @@ namespace storm { // Eliminate the successor only if there possibly is a psi state reachable through it. if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) { STORM_LOG_TRACE("Found non-psi successor " << element.getColumn() << " that needs to be eliminated."); - eliminateState(element.getColumn(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, phiFilterCallback, false); + stateEliminator.setStatePhi(); + stateEliminator.eliminateState(element.getColumn(), false); + stateEliminator.clearState(); hasNonPsiSuccessor = true; } } @@ -824,7 +809,9 @@ namespace storm { FlexibleRowType const& successorRow = flexibleMatrix.getRow(element.getColumn()); if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) { STORM_LOG_TRACE("Found non-phi successor " << element.getColumn() << " that needs to be eliminated."); - eliminateState(element.getColumn(), flexibleMatrix, flexibleBackwardTransitions, valueUpdateCallback, predecessorUpdateCallback, boost::none, psiFilterCallback, false); + stateEliminator.setStatePsi(); + stateEliminator.eliminateState(element.getColumn(), false); + stateEliminator.clearState(); hasNonPhiSuccessor = true; } } @@ -890,7 +877,7 @@ namespace storm { } template - std::unique_ptr::StatePriorityQueue> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { + std::unique_ptr> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { STORM_LOG_TRACE("Creating state priority queue for states " << states); @@ -934,23 +921,20 @@ namespace storm { } template - std::unique_ptr::StatePriorityQueue> SparseDtmcEliminationModelChecker::createNaivePriorityQueue(storm::storage::BitVector const& states) { + std::unique_ptr> SparseDtmcEliminationModelChecker::createNaivePriorityQueue(storm::storage::BitVector const& states) { std::vector sortedStates(states.begin(), states.end()); - return std::unique_ptr(new StaticStatePriorityQueue(sortedStates)); + return std::unique_ptr>(new StaticStatePriorityQueue(sortedStates)); } template - void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::unique_ptr& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { + void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::unique_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { - ValueUpdateCallback valueUpdateCallback = [&values] (storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { values[state] = storm::utility::simplify(loopProbability * values[state]); }; - PredecessorUpdateCallback predecessorCallback = [&values] (storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { values[predecessor] = storm::utility::simplify(values[predecessor] + storm::utility::simplify(probability * values[state])); }; - boost::optional priorityUpdateCallback = PriorityUpdateCallback([&transitionMatrix,&backwardTransitions,&values,&priorityQueue] (storm::storage::sparse::state_type const& state) { priorityQueue->update(state, transitionMatrix, backwardTransitions, values); }); - boost::optional predecessorFilterCallback = boost::none; + storm::solver::stateelimination::PrioritizedEliminator stateEliminator(transitionMatrix, backwardTransitions, *priorityQueue, values); while (priorityQueue->hasNextState()) { storm::storage::sparse::state_type state = priorityQueue->popNextState(); bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.get(state); - eliminateState(state, transitionMatrix, backwardTransitions, valueUpdateCallback, predecessorCallback, priorityUpdateCallback, predecessorFilterCallback, removeForwardTransitions); + stateEliminator.eliminateState(state, removeForwardTransitions); if (removeForwardTransitions) { values[state] = storm::utility::zero(); } @@ -960,7 +944,7 @@ namespace storm { template void SparseDtmcEliminationModelChecker::performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); + std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); std::size_t numberOfStatesToEliminate = statePriorities->size(); STORM_LOG_DEBUG("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl); @@ -979,7 +963,7 @@ namespace storm { if (storm::settings::sparseDtmcEliminationModelCheckerSettings().isEliminateEntryStatesLastSet()) { STORM_LOG_DEBUG("Eliminating " << entryStateQueue.size() << " entry states as a last step."); std::vector sortedStates(entryStateQueue.begin(), entryStateQueue.end()); - std::unique_ptr queuePriorities = std::unique_ptr(new StaticStatePriorityQueue(sortedStates)); + std::unique_ptr> queuePriorities = std::unique_ptr>(new StaticStatePriorityQueue(sortedStates)); performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); } STORM_LOG_DEBUG("Eliminated " << subsystem.size() << " states." << std::endl); @@ -1078,7 +1062,7 @@ namespace storm { } } - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs); + std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs); STORM_LOG_TRACE("Eliminating " << statePriorities->size() << " trivial SCCs."); performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated all trivial SCCs."); @@ -1108,7 +1092,7 @@ namespace storm { } else { // In this case, we perform simple state elimination in the current SCC. STORM_LOG_TRACE("SCC of size " << scc.getNumberOfSetBits() << " is small enough to be eliminated directly."); - std::unique_ptr statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates); + std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates); performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated all states of SCC."); } @@ -1116,7 +1100,7 @@ namespace storm { // Finally, eliminate the entry states (if we are required to do so). if (eliminateEntryStates) { STORM_LOG_TRACE("Finally, eliminating entry states."); - std::unique_ptr naivePriorities = createNaivePriorityQueue(entryStates); + std::unique_ptr> naivePriorities = createNaivePriorityQueue(entryStates); performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated/added entry states."); } else { @@ -1129,242 +1113,6 @@ namespace storm { return maximalDepth; } - template - void SparseDtmcEliminationModelChecker::eliminateState(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix& matrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, ValueUpdateCallback const& callback, PredecessorUpdateCallback const& predecessorCallback, boost::optional const& priorityUpdateCallback, boost::optional const& predecessorFilterCallback, bool removeForwardTransitions) { - - STORM_LOG_TRACE("Eliminating state " << state << "."); - - // Start by finding loop probability. - bool hasSelfLoop = false; - ValueType loopProbability = storm::utility::zero(); - FlexibleRowType& currentStateSuccessors = matrix.getRow(state); - for (auto entryIt = currentStateSuccessors.begin(), entryIte = currentStateSuccessors.end(); entryIt != entryIte; ++entryIt) { - if (entryIt->getColumn() >= state) { - if (entryIt->getColumn() == state) { - loopProbability = entryIt->getValue(); - hasSelfLoop = true; - - // If we do not clear the forward transitions completely, we need to remove the self-loop, - // because we scale all the other outgoing transitions with it anyway. - if (!removeForwardTransitions) { - currentStateSuccessors.erase(entryIt); - } - } - break; - } - } - - // Scale all entries in this row with (1 / (1 - loopProbability)) only in case there was a self-loop. - STORM_LOG_TRACE((hasSelfLoop ? "State has self-loop." : "State does not have a self-loop.")); - if (hasSelfLoop) { - STORM_LOG_ASSERT(loopProbability != storm::utility::one(), "Must not eliminate state with probability 1 self-loop."); - loopProbability = storm::utility::simplify(storm::utility::one() / (storm::utility::one() - loopProbability)); - for (auto& entry : matrix.getRow(state)) { - // Only scale the non-diagonal entries. - if (entry.getColumn() != state) { - entry.setValue(storm::utility::simplify(entry.getValue() * loopProbability)); - } - } - callback(state, loopProbability); - } - - // Now connect the predecessors of the state being eliminated with its successors. - FlexibleRowType& currentStatePredecessors = backwardTransitions.getRow(state); - - // In case we have a constrained elimination, we need to keep track of the new predecessors. - FlexibleRowType newCurrentStatePredecessors; - - std::vector newBackwardProbabilities(currentStateSuccessors.size()); - for (auto& backwardProbabilities : newBackwardProbabilities) { - backwardProbabilities.reserve(currentStatePredecessors.size()); - } - - // Now go through the predecessors and eliminate the ones (satisfying the constraint if given). - for (auto const& predecessorEntry : currentStatePredecessors) { - uint_fast64_t predecessor = predecessorEntry.getColumn(); - STORM_LOG_TRACE("Found predecessor " << predecessor << "."); - - // Skip the state itself as one of its predecessors. - if (predecessor == state) { - assert(hasSelfLoop); - continue; - } - - // Skip the state if the elimination is constrained, but the predecessor is not in the constraint. - if (predecessorFilterCallback && !predecessorFilterCallback.get()(predecessor)) { - newCurrentStatePredecessors.emplace_back(predecessorEntry); - STORM_LOG_TRACE("Not eliminating predecessor " << predecessor << ", because it does not fit the filter."); - continue; - } - STORM_LOG_TRACE("Eliminating predecessor " << predecessor << "."); - - // First, find the probability with which the predecessor can move to the current state, because - // the forward probabilities of the state to be eliminated need to be scaled with this factor. - FlexibleRowType& predecessorForwardTransitions = matrix.getRow(predecessor); - FlexibleRowIterator multiplyElement = std::find_if(predecessorForwardTransitions.begin(), predecessorForwardTransitions.end(), [&](storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() == state; }); - - // Make sure we have found the probability and set it to zero. - STORM_LOG_THROW(multiplyElement != predecessorForwardTransitions.end(), storm::exceptions::InvalidStateException, "No probability for successor found."); - ValueType multiplyFactor = multiplyElement->getValue(); - multiplyElement->setValue(storm::utility::zero()); - - // At this point, we need to update the (forward) transitions of the predecessor. - FlexibleRowIterator first1 = predecessorForwardTransitions.begin(); - FlexibleRowIterator last1 = predecessorForwardTransitions.end(); - FlexibleRowIterator first2 = currentStateSuccessors.begin(); - FlexibleRowIterator last2 = currentStateSuccessors.end(); - - FlexibleRowType newSuccessors; - newSuccessors.reserve((last1 - first1) + (last2 - first2)); - std::insert_iterator result(newSuccessors, newSuccessors.end()); - - uint_fast64_t successorOffsetInNewBackwardTransitions = 0; - // Now we merge the two successor lists. (Code taken from std::set_union and modified to suit our needs). - for (; first1 != last1; ++result) { - // Skip the transitions to the state that is currently being eliminated. - if (first1->getColumn() == state || (first2 != last2 && first2->getColumn() == state)) { - if (first1->getColumn() == state) { - ++first1; - } - if (first2 != last2 && first2->getColumn() == state) { - ++first2; - } - continue; - } - - if (first2 == last2) { - std::copy_if(first1, last1, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state; } ); - break; - } - if (first2->getColumn() < first1->getColumn()) { - auto successorEntry = storm::utility::simplify(std::move(*first2 * multiplyFactor)); - *result = successorEntry; - newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, successorEntry.getValue()); -// std::cout << "(1) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; - ++first2; - ++successorOffsetInNewBackwardTransitions; - } else if (first1->getColumn() < first2->getColumn()) { - *result = *first1; - ++first1; - } else { - auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue())); - *result = storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type>(first1->getColumn(), probability); - newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability); -// std::cout << "(2) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; - ++first1; - ++first2; - ++successorOffsetInNewBackwardTransitions; - } - } - for (; first2 != last2; ++first2) { - if (first2->getColumn() != state) { - auto stateProbability = storm::utility::simplify(std::move(*first2 * multiplyFactor)); - *result = stateProbability; - newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, stateProbability.getValue()); -// std::cout << "(3) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; - ++successorOffsetInNewBackwardTransitions; - } - } - - // Now move the new transitions in place. - predecessorForwardTransitions = std::move(newSuccessors); - STORM_LOG_TRACE("Fixed new next-state probabilities of predecessor state " << predecessor << "."); - - predecessorCallback(predecessor, multiplyFactor, state); - - if (priorityUpdateCallback) { - STORM_LOG_TRACE("Updating priority of predecessor."); - priorityUpdateCallback.get()(predecessor); - } - } - - // Finally, we need to add the predecessor to the set of predecessors of every successor. - uint_fast64_t successorOffsetInNewBackwardTransitions = 0; - for (auto const& successorEntry : currentStateSuccessors) { - if (successorEntry.getColumn() == state) { - continue; - } - - FlexibleRowType& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn()); -// std::cout << "old backward trans of " << successorEntry.getColumn() << std::endl; -// for (auto const& trans : successorBackwardTransitions) { -// std::cout << trans << std::endl; -// } - - // Delete the current state as a predecessor of the successor state only if we are going to remove the - // current state's forward transitions. - if (removeForwardTransitions) { - FlexibleRowIterator elimIt = std::find_if(successorBackwardTransitions.begin(), successorBackwardTransitions.end(), [&](storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() == state; }); - STORM_LOG_ASSERT(elimIt != successorBackwardTransitions.end(), "Expected a proper backward transition from " << successorEntry.getColumn() << " to " << state << ", but found none."); - successorBackwardTransitions.erase(elimIt); - } - - FlexibleRowIterator first1 = successorBackwardTransitions.begin(); - FlexibleRowIterator last1 = successorBackwardTransitions.end(); - FlexibleRowIterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin(); - FlexibleRowIterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end(); - -// std::cout << "adding backward trans " << successorEntry.getColumn() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; -// for (auto const& trans : newBackwardProbabilities[successorOffsetInNewBackwardTransitions]) { -// std::cout << trans << std::endl; -// } - - FlexibleRowType newPredecessors; - newPredecessors.reserve((last1 - first1) + (last2 - first2)); - std::insert_iterator result(newPredecessors, newPredecessors.end()); - - for (; first1 != last1; ++result) { - if (first2 == last2) { - std::copy(first1, last1, result); - break; - } - if (first2->getColumn() < first1->getColumn()) { - if (first2->getColumn() != state) { - *result = *first2; - } - ++first2; - } else if (first1->getColumn() == first2->getColumn()) { - if (estimateComplexity(first1->getValue()) > estimateComplexity(first2->getValue())) { - *result = *first1; - } else { - *result = *first2; - } - ++first1; - ++first2; - } else { - *result = *first1; - ++first1; - } - } - if (predecessorFilterCallback) { - std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state && predecessorFilterCallback.get()(a.getColumn()); }); - } else { - std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state; }); - } - - // Now move the new predecessors in place. - successorBackwardTransitions = std::move(newPredecessors); -// std::cout << "new backward trans of " << successorEntry.getColumn() << std::endl; -// for (auto const& trans : successorBackwardTransitions) { -// std::cout << trans << std::endl; -// } - ++successorOffsetInNewBackwardTransitions; - } - STORM_LOG_TRACE("Fixed predecessor lists of successor states."); - - if (removeForwardTransitions) { - // Clear the eliminated row to reduce memory consumption. - currentStateSuccessors.clear(); - currentStateSuccessors.shrink_to_fit(); - } - if (predecessorFilterCallback) { - currentStatePredecessors = std::move(newCurrentStatePredecessors); - } else { - currentStatePredecessors.clear(); - currentStatePredecessors.shrink_to_fit(); - } - } - template std::vector SparseDtmcEliminationModelChecker::getDistanceBasedPriorities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward, bool reverse) { std::vector statePriorities(transitionMatrix.getRowCount()); @@ -1444,13 +1192,13 @@ namespace storm { return backwardTransitions.getRow(state).size() * transitionMatrix.getRow(state).size(); } - template - void SparseDtmcEliminationModelChecker::StatePriorityQueue::update(storm::storage::sparse::state_type, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { + template + void StatePriorityQueue::update(storm::storage::sparse::state_type, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities) { // Intentionally left empty. } template - SparseDtmcEliminationModelChecker::StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector const& sortedStates) : StatePriorityQueue(), sortedStates(sortedStates), currentPosition(0) { + SparseDtmcEliminationModelChecker::StaticStatePriorityQueue::StaticStatePriorityQueue(std::vector const& sortedStates) : StatePriorityQueue(), sortedStates(sortedStates), currentPosition(0) { // Intentionally left empty. } @@ -1471,7 +1219,7 @@ namespace storm { } template - SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::DynamicPenaltyStatePriorityQueue(std::vector> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue(), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) { + SparseDtmcEliminationModelChecker::DynamicPenaltyStatePriorityQueue::DynamicPenaltyStatePriorityQueue(std::vector> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction) : StatePriorityQueue(), priorityQueue(), stateToPriorityMapping(), penaltyFunction(penaltyFunction) { // Insert all state-penalty pairs into our priority queue. for (auto const& statePenalty : sortedStatePenaltyPairs) { priorityQueue.insert(priorityQueue.end(), statePenalty); @@ -1552,9 +1300,11 @@ namespace storm { return true; } + template class StatePriorityQueue; template class SparseDtmcEliminationModelChecker>; - + #ifdef STORM_HAVE_CARL + template class StatePriorityQueue; template class SparseDtmcEliminationModelChecker>; #endif } // namespace modelchecker diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 30c8e528a..bfcfbcd31 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -10,6 +10,18 @@ namespace storm { namespace modelchecker { + template + uint_fast64_t estimateComplexity(ValueType const& value); + + template + class StatePriorityQueue { + public: + virtual bool hasNextState() const = 0; + virtual storm::storage::sparse::state_type popNextState() = 0; + virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); + virtual std::size_t size() const = 0; + }; + template class SparseDtmcEliminationModelChecker : public SparsePropositionalModelChecker { public: @@ -34,18 +46,10 @@ namespace storm { virtual std::unique_ptr computeLongRunAverageRewards(storm::logic::LongRunAverageRewardFormula const& rewardPathFormula, boost::optional const& rewardModelName = boost::optional(), bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeConditionalProbabilities(storm::logic::ConditionalPathFormula const& pathFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; virtual std::unique_ptr computeLongRunAverageProbabilities(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional const& optimalityType = boost::optional()) override; - + private: - - class StatePriorityQueue { - public: - virtual bool hasNextState() const = 0; - virtual storm::storage::sparse::state_type popNextState() = 0; - virtual void update(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities); - virtual std::size_t size() const = 0; - }; - class StaticStatePriorityQueue : public StatePriorityQueue { + class StaticStatePriorityQueue : public StatePriorityQueue { public: StaticStatePriorityQueue(std::vector const& sortedStates); @@ -66,7 +70,7 @@ namespace storm { typedef std::function const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector const& oneStepProbabilities)> PenaltyFunctionType; - class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue { + class DynamicPenaltyStatePriorityQueue : public StatePriorityQueue { public: DynamicPenaltyStatePriorityQueue(std::vector> const& sortedStatePenaltyPairs, PenaltyFunctionType const& penaltyFunction); @@ -85,11 +89,11 @@ namespace storm { static std::vector computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget); - static std::unique_ptr createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); + static std::unique_ptr> createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); - static std::unique_ptr createNaivePriorityQueue(storm::storage::BitVector const& states); + static std::unique_ptr> createNaivePriorityQueue(storm::storage::BitVector const& states); - static void performPrioritizedStateElimination(std::unique_ptr& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); + static void performPrioritizedStateElimination(std::unique_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional>& additionalStateValues, boost::optional> const& distanceBasedPriorities); @@ -98,14 +102,7 @@ namespace storm { static uint_fast64_t performHybridStateElimination(storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities); static uint_fast64_t treatScc(storm::storage::FlexibleSparseMatrix& matrix, std::vector& values, storm::storage::BitVector const& entryStates, storm::storage::BitVector const& scc, storm::storage::BitVector const& initialStates, storm::storage::SparseMatrix const& forwardTransitions, storm::storage::FlexibleSparseMatrix& backwardTransitions, bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector& entryStateQueue, bool computeResultsForInitialStatesOnly, boost::optional> const& distanceBasedPriorities = boost::none); - - typedef std::function ValueUpdateCallback; - typedef std::function PredecessorUpdateCallback; - typedef std::function PriorityUpdateCallback; - typedef std::function PredecessorFilterCallback; - - static void eliminateState(storm::storage::sparse::state_type state, storm::storage::FlexibleSparseMatrix& matrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, ValueUpdateCallback const& valueUpdateCallback, PredecessorUpdateCallback const& predecessorCallback, boost::optional const& priorityUpdateCallback = boost::none, boost::optional const& predecessorFilterCallback = boost::none, bool removeForwardTransitions = true); - + static std::vector getDistanceBasedPriorities(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward, bool reverse); static std::vector getStateDistances(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& transitionMatrixTransposed, storm::storage::BitVector const& initialStates, std::vector const& oneStepProbabilities, bool forward); diff --git a/src/solver/stateelimination/ConditionalEliminator.cpp b/src/solver/stateelimination/ConditionalEliminator.cpp new file mode 100644 index 000000000..bba964596 --- /dev/null +++ b/src/solver/stateelimination/ConditionalEliminator.cpp @@ -0,0 +1,53 @@ +#include "src/solver/stateelimination/ConditionalEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + ConditionalEliminator::ConditionalEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates) : StateEliminator(transitionMatrix, backwardTransitions), oneStepProbabilities(oneStepProbabilities), phiStates(phiStates), psiStates(psiStates), specificState(NONE) { + } + + template + void ConditionalEliminator::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { + oneStepProbabilities[state] = storm::utility::simplify(loopProbability * oneStepProbabilities[state]); + } + + template + void ConditionalEliminator::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { + oneStepProbabilities[predecessor] = storm::utility::simplify(oneStepProbabilities[predecessor] * storm::utility::simplify(probability * oneStepProbabilities[state])); + } + + template + void ConditionalEliminator::updatePriority(storm::storage::sparse::state_type const& state) { + // Do nothing + } + + template + bool ConditionalEliminator::filterPredecessor(storm::storage::sparse::state_type const& state) { + // TODO find better solution than flag + switch (specificState) { + case PHI: + return phiStates.get(state); + case PSI: + return psiStates.get(state); + case NONE: + assert(false); + } + } + + template + bool ConditionalEliminator::isFilterPredecessor() const { + return true; + } + + + template class ConditionalEliminator>; + +#ifdef STORM_HAVE_CARL + template class ConditionalEliminator>; +#endif + + } // namespace stateelimination + } // namespace storage +} // namespace storm diff --git a/src/solver/stateelimination/ConditionalEliminator.h b/src/solver/stateelimination/ConditionalEliminator.h new file mode 100644 index 000000000..b98066d3f --- /dev/null +++ b/src/solver/stateelimination/ConditionalEliminator.h @@ -0,0 +1,53 @@ +#ifndef STORM_SOLVER_STATEELIMINATION_CONDITIONALELIMINATOR_H_ +#define STORM_SOLVER_STATEELIMINATION_CONDITIONALELIMINATOR_H_ + +#include "src/solver/stateelimination/StateEliminator.h" + +#include "src/storage/BitVector.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + class ConditionalEliminator : public StateEliminator { + + typedef typename SparseModelType::ValueType ValueType; + + enum SpecificState { NONE, PHI, PSI}; + + public: + ConditionalEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector& phiStates, storm::storage::BitVector& psiStates); + + // Instantiaton of Virtual methods + void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override; + void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override; + void updatePriority(storm::storage::sparse::state_type const& state) override; + bool filterPredecessor(storm::storage::sparse::state_type const& state) override; + bool isFilterPredecessor() const override; + + void setStatePsi() { + specificState = PSI; + } + + void setStatePhi() { + specificState = PHI; + } + + void clearState() { + specificState = NONE; + } + + private: + std::vector& oneStepProbabilities; + storm::storage::BitVector& phiStates; + storm::storage::BitVector& psiStates; + SpecificState specificState; + + }; + + } // namespace stateelimination + } // namespace storage +} // namespace storm + +#endif // STORM_SOLVER_STATEELIMINATION_CONDITIONALELIMINATOR_H_ diff --git a/src/solver/stateelimination/LongRunAverageEliminator.cpp b/src/solver/stateelimination/LongRunAverageEliminator.cpp new file mode 100644 index 000000000..250030c54 --- /dev/null +++ b/src/solver/stateelimination/LongRunAverageEliminator.cpp @@ -0,0 +1,47 @@ +#include "src/solver/stateelimination/LongRunAverageEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + LongRunAverageEliminator::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue& priorityQueue, std::vector& stateValues, std::vector& averageTimeInStates) : StateEliminator(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues), averageTimeInStates(averageTimeInStates) { + } + + template + void LongRunAverageEliminator::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { + stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]); + averageTimeInStates[state] = storm::utility::simplify(loopProbability * averageTimeInStates[state]); + } + + template + void LongRunAverageEliminator::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { + stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state])); + averageTimeInStates[predecessor] = storm::utility::simplify(averageTimeInStates[predecessor] + storm::utility::simplify(probability * averageTimeInStates[state])); + } + + template + void LongRunAverageEliminator::updatePriority(storm::storage::sparse::state_type const& state) { + priorityQueue.update(state, StateEliminator::transitionMatrix, StateEliminator::backwardTransitions, stateValues); + } + + template + bool LongRunAverageEliminator::filterPredecessor(storm::storage::sparse::state_type const& state) { + assert(false); + } + + template + bool LongRunAverageEliminator::isFilterPredecessor() const { + return false; + } + + + template class LongRunAverageEliminator>; + +#ifdef STORM_HAVE_CARL + template class LongRunAverageEliminator>; +#endif + + } // namespace stateelimination + } // namespace storage +} // namespace storm diff --git a/src/solver/stateelimination/LongRunAverageEliminator.h b/src/solver/stateelimination/LongRunAverageEliminator.h new file mode 100644 index 000000000..0e5522fef --- /dev/null +++ b/src/solver/stateelimination/LongRunAverageEliminator.h @@ -0,0 +1,36 @@ +#ifndef STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_ +#define STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_ + +#include "src/solver/stateelimination/StateEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + class LongRunAverageEliminator : public StateEliminator { + + typedef typename SparseModelType::ValueType ValueType; + + public: + LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue& priorityQueue, std::vector& stateValues, std::vector& averageTimeInStates); + + // Instantiaton of Virtual methods + void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override; + void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override; + void updatePriority(storm::storage::sparse::state_type const& state) override; + bool filterPredecessor(storm::storage::sparse::state_type const& state) override; + bool isFilterPredecessor() const override; + + private: + + storm::modelchecker::StatePriorityQueue& priorityQueue; + std::vector& stateValues; + std::vector& averageTimeInStates; + }; + + } // namespace stateelimination + } // namespace storage +} // namespace storm + +#endif // STORM_SOLVER_STATEELIMINATION_LONGRUNAVERAGEELIMINATOR_H_ diff --git a/src/solver/stateelimination/PrioritizedEliminator.cpp b/src/solver/stateelimination/PrioritizedEliminator.cpp new file mode 100644 index 000000000..de760e66b --- /dev/null +++ b/src/solver/stateelimination/PrioritizedEliminator.cpp @@ -0,0 +1,45 @@ +#include "src/solver/stateelimination/PrioritizedEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + PrioritizedEliminator::PrioritizedEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue priorityQueue, std::vector& stateValues) : StateEliminator(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) { + } + + template + void PrioritizedEliminator::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { + stateValues[state] = storm::utility::simplify(loopProbability * stateValues[state]); + } + + template + void PrioritizedEliminator::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { + stateValues[predecessor] = storm::utility::simplify(stateValues[predecessor] + storm::utility::simplify(probability * stateValues[state])); + } + + template + void PrioritizedEliminator::updatePriority(storm::storage::sparse::state_type const& state) { + priorityQueue.update(state, StateEliminator::transitionMatrix, StateEliminator::backwardTransitions, stateValues); + } + + template + bool PrioritizedEliminator::filterPredecessor(storm::storage::sparse::state_type const& state) { + assert(false); + } + + template + bool PrioritizedEliminator::isFilterPredecessor() const { + return false; + } + + + template class PrioritizedEliminator>; + +#ifdef STORM_HAVE_CARL + template class PrioritizedEliminator>; +#endif + + } // namespace stateelimination + } // namespace storage +} // namespace storm diff --git a/src/solver/stateelimination/PrioritizedEliminator.h b/src/solver/stateelimination/PrioritizedEliminator.h new file mode 100644 index 000000000..7a242ebdf --- /dev/null +++ b/src/solver/stateelimination/PrioritizedEliminator.h @@ -0,0 +1,34 @@ +#ifndef STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_ +#define STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_ + +#include "src/solver/stateelimination/StateEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + class PrioritizedEliminator : public StateEliminator { + + typedef typename SparseModelType::ValueType ValueType; + + public: + PrioritizedEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue priorityQueue, std::vector& stateValues); + + // Instantiaton of Virtual methods + void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override; + void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override; + void updatePriority(storm::storage::sparse::state_type const& state) override; + bool filterPredecessor(storm::storage::sparse::state_type const& state) override; + bool isFilterPredecessor() const override; + + private: + storm::modelchecker::StatePriorityQueue& priorityQueue; + std::vector& stateValues; + }; + + } // namespace stateelimination + } // namespace storage +} // namespace storm + +#endif // STORM_SOLVER_STATEELIMINATION_PRIORITIZEDELIMINATOR_H_ diff --git a/src/solver/stateelimination/StateEliminator.cpp b/src/solver/stateelimination/StateEliminator.cpp new file mode 100644 index 000000000..3e3d8c53a --- /dev/null +++ b/src/solver/stateelimination/StateEliminator.cpp @@ -0,0 +1,259 @@ +#include "src/solver/stateelimination/StateEliminator.h" + +#include "src/storage/BitVector.h" +#include "src/adapters/CarlAdapter.h" +#include "src/utility/constants.h" +#include "src/utility/macros.h" +#include "src/exceptions/InvalidStateException.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + StateEliminator::StateEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions) : transitionMatrix(transitionMatrix), backwardTransitions(backwardTransitions) { + } + + template + void StateEliminator::eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint) { + + STORM_LOG_TRACE("Eliminating state " << state << "."); + + // Start by finding loop probability. + bool hasSelfLoop = false; + ValueType loopProbability = storm::utility::zero(); + FlexibleRowType& currentStateSuccessors = transitionMatrix.getRow(state); + for (auto entryIt = currentStateSuccessors.begin(), entryIte = currentStateSuccessors.end(); entryIt != entryIte; ++entryIt) { + if (entryIt->getColumn() >= state) { + if (entryIt->getColumn() == state) { + loopProbability = entryIt->getValue(); + hasSelfLoop = true; + + // If we do not clear the forward transitions completely, we need to remove the self-loop, + // because we scale all the other outgoing transitions with it anyway. + if (!removeForwardTransitions) { + currentStateSuccessors.erase(entryIt); + } + } + break; + } + } + + // Scale all entries in this row with (1 / (1 - loopProbability)) only in case there was a self-loop. + STORM_LOG_TRACE((hasSelfLoop ? "State has self-loop." : "State does not have a self-loop.")); + if (hasSelfLoop) { + STORM_LOG_ASSERT(loopProbability != storm::utility::one(), "Must not eliminate state with probability 1 self-loop."); + loopProbability = storm::utility::simplify(storm::utility::one() / (storm::utility::one() - loopProbability)); + for (auto& entry : transitionMatrix.getRow(state)) { + // Only scale the non-diagonal entries. + if (entry.getColumn() != state) { + entry.setValue(storm::utility::simplify(entry.getValue() * loopProbability)); + } + } + updateValue(state, loopProbability); + } + + // Now connect the predecessors of the state being eliminated with its successors. + FlexibleRowType& currentStatePredecessors = backwardTransitions.getRow(state); + + // In case we have a constrained elimination, we need to keep track of the new predecessors. + FlexibleRowType newCurrentStatePredecessors; + + std::vector newBackwardProbabilities(currentStateSuccessors.size()); + for (auto& backwardProbabilities : newBackwardProbabilities) { + backwardProbabilities.reserve(currentStatePredecessors.size()); + } + + // Now go through the predecessors and eliminate the ones (satisfying the constraint if given). + for (auto const& predecessorEntry : currentStatePredecessors) { + uint_fast64_t predecessor = predecessorEntry.getColumn(); + STORM_LOG_TRACE("Found predecessor " << predecessor << "."); + + // Skip the state itself as one of its predecessors. + if (predecessor == state) { + assert(hasSelfLoop); + continue; + } + + // Skip the state if the elimination is constrained, but the predecessor is not in the constraint. + if (isFilterPredecessor() && !filterPredecessor(predecessor)) { + newCurrentStatePredecessors.emplace_back(predecessorEntry); + STORM_LOG_TRACE("Not eliminating predecessor " << predecessor << ", because it does not fit the filter."); + continue; + } + STORM_LOG_TRACE("Eliminating predecessor " << predecessor << "."); + + // First, find the probability with which the predecessor can move to the current state, because + // the forward probabilities of the state to be eliminated need to be scaled with this factor. + FlexibleRowType& predecessorForwardTransitions = transitionMatrix.getRow(predecessor); + FlexibleRowIterator multiplyElement = std::find_if(predecessorForwardTransitions.begin(), predecessorForwardTransitions.end(), [&](storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() == state; }); + + // Make sure we have found the probability and set it to zero. + STORM_LOG_THROW(multiplyElement != predecessorForwardTransitions.end(), storm::exceptions::InvalidStateException, "No probability for successor found."); + ValueType multiplyFactor = multiplyElement->getValue(); + multiplyElement->setValue(storm::utility::zero()); + + // At this point, we need to update the (forward) transitions of the predecessor. + FlexibleRowIterator first1 = predecessorForwardTransitions.begin(); + FlexibleRowIterator last1 = predecessorForwardTransitions.end(); + FlexibleRowIterator first2 = currentStateSuccessors.begin(); + FlexibleRowIterator last2 = currentStateSuccessors.end(); + + FlexibleRowType newSuccessors; + newSuccessors.reserve((last1 - first1) + (last2 - first2)); + std::insert_iterator result(newSuccessors, newSuccessors.end()); + + uint_fast64_t successorOffsetInNewBackwardTransitions = 0; + // Now we merge the two successor lists. (Code taken from std::set_union and modified to suit our needs). + for (; first1 != last1; ++result) { + // Skip the transitions to the state that is currently being eliminated. + if (first1->getColumn() == state || (first2 != last2 && first2->getColumn() == state)) { + if (first1->getColumn() == state) { + ++first1; + } + if (first2 != last2 && first2->getColumn() == state) { + ++first2; + } + continue; + } + + if (first2 == last2) { + std::copy_if(first1, last1, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state; } ); + break; + } + if (first2->getColumn() < first1->getColumn()) { + auto successorEntry = storm::utility::simplify(std::move(*first2 * multiplyFactor)); + *result = successorEntry; + newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, successorEntry.getValue()); + // std::cout << "(1) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; + ++first2; + ++successorOffsetInNewBackwardTransitions; + } else if (first1->getColumn() < first2->getColumn()) { + *result = *first1; + ++first1; + } else { + auto probability = storm::utility::simplify(first1->getValue() + storm::utility::simplify(multiplyFactor * first2->getValue())); + *result = storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type>(first1->getColumn(), probability); + newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, probability); + // std::cout << "(2) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; + ++first1; + ++first2; + ++successorOffsetInNewBackwardTransitions; + } + } + for (; first2 != last2; ++first2) { + if (first2->getColumn() != state) { + auto stateProbability = storm::utility::simplify(std::move(*first2 * multiplyFactor)); + *result = stateProbability; + newBackwardProbabilities[successorOffsetInNewBackwardTransitions].emplace_back(predecessor, stateProbability.getValue()); + // std::cout << "(3) adding " << first2->getColumn() << " -> " << newBackwardProbabilities[successorOffsetInNewBackwardTransitions].back() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; + ++successorOffsetInNewBackwardTransitions; + } + } + + // Now move the new transitions in place. + predecessorForwardTransitions = std::move(newSuccessors); + STORM_LOG_TRACE("Fixed new next-state probabilities of predecessor state " << predecessor << "."); + + updatePredecessor(predecessor, multiplyFactor, state); + + STORM_LOG_TRACE("Updating priority of predecessor."); + updatePriority(predecessor); + } + + // Finally, we need to add the predecessor to the set of predecessors of every successor. + uint_fast64_t successorOffsetInNewBackwardTransitions = 0; + for (auto const& successorEntry : currentStateSuccessors) { + if (successorEntry.getColumn() == state) { + continue; + } + + FlexibleRowType& successorBackwardTransitions = backwardTransitions.getRow(successorEntry.getColumn()); + // std::cout << "old backward trans of " << successorEntry.getColumn() << std::endl; + // for (auto const& trans : successorBackwardTransitions) { + // std::cout << trans << std::endl; + // } + + // Delete the current state as a predecessor of the successor state only if we are going to remove the + // current state's forward transitions. + if (removeForwardTransitions) { + FlexibleRowIterator elimIt = std::find_if(successorBackwardTransitions.begin(), successorBackwardTransitions.end(), [&](storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() == state; }); + STORM_LOG_ASSERT(elimIt != successorBackwardTransitions.end(), "Expected a proper backward transition from " << successorEntry.getColumn() << " to " << state << ", but found none."); + successorBackwardTransitions.erase(elimIt); + } + + FlexibleRowIterator first1 = successorBackwardTransitions.begin(); + FlexibleRowIterator last1 = successorBackwardTransitions.end(); + FlexibleRowIterator first2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].begin(); + FlexibleRowIterator last2 = newBackwardProbabilities[successorOffsetInNewBackwardTransitions].end(); + + // std::cout << "adding backward trans " << successorEntry.getColumn() << "[" << successorOffsetInNewBackwardTransitions << "]" << std::endl; + // for (auto const& trans : newBackwardProbabilities[successorOffsetInNewBackwardTransitions]) { + // std::cout << trans << std::endl; + // } + + FlexibleRowType newPredecessors; + newPredecessors.reserve((last1 - first1) + (last2 - first2)); + std::insert_iterator result(newPredecessors, newPredecessors.end()); + + for (; first1 != last1; ++result) { + if (first2 == last2) { + std::copy(first1, last1, result); + break; + } + if (first2->getColumn() < first1->getColumn()) { + if (first2->getColumn() != state) { + *result = *first2; + } + ++first2; + } else if (first1->getColumn() == first2->getColumn()) { + if (storm::modelchecker::estimateComplexity(first1->getValue()) > storm::modelchecker::estimateComplexity(first2->getValue())) { + *result = *first1; + } else { + *result = *first2; + } + ++first1; + ++first2; + } else { + *result = *first1; + ++first1; + } + } + if (isFilterPredecessor()) { + std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state && filterPredecessor(a.getColumn()); }); + } else { + std::copy_if(first2, last2, result, [&] (storm::storage::MatrixEntry::index_type, typename storm::storage::FlexibleSparseMatrix::value_type> const& a) { return a.getColumn() != state; }); + } + // Now move the new predecessors in place. + successorBackwardTransitions = std::move(newPredecessors); + // std::cout << "new backward trans of " << successorEntry.getColumn() << std::endl; + // for (auto const& trans : successorBackwardTransitions) { + // std::cout << trans << std::endl; + // } + ++successorOffsetInNewBackwardTransitions; + } + STORM_LOG_TRACE("Fixed predecessor lists of successor states."); + + if (removeForwardTransitions) { + // Clear the eliminated row to reduce memory consumption. + currentStateSuccessors.clear(); + currentStateSuccessors.shrink_to_fit(); + } + if (isFilterPredecessor()) { + currentStatePredecessors = std::move(newCurrentStatePredecessors); + } else { + currentStatePredecessors.clear(); + currentStatePredecessors.shrink_to_fit(); + } + + } + + template class StateEliminator>; + +#ifdef STORM_HAVE_CARL + template class StateEliminator>; +#endif + + } // namespace stateelimination + } // namespace storage +} // namespace storm \ No newline at end of file diff --git a/src/solver/stateelimination/StateEliminator.h b/src/solver/stateelimination/StateEliminator.h new file mode 100644 index 000000000..2a58912e8 --- /dev/null +++ b/src/solver/stateelimination/StateEliminator.h @@ -0,0 +1,42 @@ +#ifndef STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ +#define STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ + +#include "src/storage/FlexibleSparseMatrix.h" +#include "src/storage/SparseMatrix.h" +#include "src/storage/sparse/StateType.h" +#include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + class StateEliminator { + typedef typename SparseModelType::ValueType ValueType; + typedef typename storm::storage::FlexibleSparseMatrix::row_type FlexibleRowType; + typedef typename FlexibleRowType::iterator FlexibleRowIterator; + + public: + StateEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions); + + void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions, storm::storage::BitVector predecessorConstraint = storm::storage::BitVector()); + + // Virtual methods for base classes to distinguish between different state elimination approaches + virtual void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) = 0; + virtual void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) = 0; + virtual void updatePriority(storm::storage::sparse::state_type const& state) = 0; + virtual bool filterPredecessor(storm::storage::sparse::state_type const& state) = 0; + virtual bool isFilterPredecessor() const = 0; + + + protected: + storm::storage::FlexibleSparseMatrix& transitionMatrix; + storm::storage::FlexibleSparseMatrix& backwardTransitions; + + }; + + } // namespace stateelimination + } // namespace storage +} // namespace storm + +#endif // STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ \ No newline at end of file From 6d84d030bdbf76b7043e1c80c8035b5bc79efe96 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 12 Feb 2016 14:20:45 +0100 Subject: [PATCH 084/246] Fixed lowercase Former-commit-id: fd323c1e1c5b3025aaad326e7749538d507df779 --- src/builder/ExplicitDFTModelBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 817295346..74c3db23d 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -1,6 +1,6 @@ #include "src/builder/ExplicitDFTModelBuilder.h" #include -#include +#include #include #include #include From acab78ba0e8fee8fb19c2aaa9475e2a2b31a6e63 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 12 Feb 2016 19:01:24 +0100 Subject: [PATCH 085/246] Added row groups to flexible matrix Former-commit-id: 85c7dc944b7e74b95da48b60c0ce67e66e909097 --- src/storage/FlexibleSparseMatrix.cpp | 80 ++++++++++++++++++++++++---- src/storage/FlexibleSparseMatrix.h | 35 ++++++++++-- src/storage/SparseMatrix.cpp | 5 -- src/storage/SparseMatrix.h | 7 --- 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp index 81e87ce20..99ed68337 100644 --- a/src/storage/FlexibleSparseMatrix.cpp +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -16,9 +16,6 @@ namespace storm { FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()), nontrivialRowGrouping(matrix.hasNontrivialRowGrouping()) { if (nontrivialRowGrouping) { rowGroupIndices = matrix.getRowGroupIndices(); - rowIndications = matrix.getRowIndications(); - // Not fully implemented yet - assert(false); } for (index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { typename storm::storage::SparseMatrix::const_rows row = matrix.getRow(rowIndex); @@ -52,6 +49,20 @@ namespace storm { return this->data[index]; } + template + typename FlexibleSparseMatrix::row_type& FlexibleSparseMatrix::getRow(index_type rowGroup, index_type offset) { + assert(rowGroup < this->getRowGroupCount()); + assert(offset < this->getRowGroupSize(rowGroup)); + return getRow(rowGroupIndices[rowGroup] + offset); + } + + template + typename FlexibleSparseMatrix::row_type const& FlexibleSparseMatrix::getRow(index_type rowGroup, index_type offset) const { + assert(rowGroup < this->getRowGroupCount()); + assert(offset < this->getRowGroupSize(rowGroup)); + return getRow(rowGroupIndices[rowGroup] + offset); + } + template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowCount() const { return this->data.size(); @@ -66,6 +77,20 @@ namespace storm { typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getNonzeroEntryCount() const { return nonzeroEntryCount; } + + template + typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowGroupCount() const { + return rowGroupIndices.size(); + } + + template + typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowGroupSize(index_type group) const { + if (group == getRowGroupCount() - 1) { + return getRowCount() - rowGroupIndices[group]; + } else { + return rowGroupIndices[group + 1] - rowGroupIndices[group]; + } + } template void FlexibleSparseMatrix::updateDimensions() { @@ -91,7 +116,7 @@ namespace storm { } template - bool SparseMatrix::hasNontrivialRowGrouping() const { + bool FlexibleSparseMatrix::hasNontrivialRowGrouping() const { return nontrivialRowGrouping; } @@ -142,13 +167,50 @@ namespace storm { template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix) { - for (uint_fast64_t index = 0; index < matrix->data.size(); ++index) { - out << index << " - "; - for (auto const& element : matrix->getRow(index)) { - out << "(" << element.getColumn() << ", " << element.getValue() << ") "; + // Print column numbers in header. + out << "\t\t"; + for (typename FlexibleSparseMatrix::index_type i = 0; i < matrix.getColumnCount(); ++i) { + out << i << "\t"; + } + out << std::endl; + + typename FlexibleSparseMatrix::index_type endIndex = matrix.hasNontrivialRowGrouping() ? matrix.getRowGroupCount() : matrix.getRowCount(); + // Iterate over all rows. + for (typename SparseMatrix::index_type i = 0; i < endIndex; ++i) { + if (matrix.hasNontrivialRowGrouping()) { + out << "\t---- group " << i << "/" << (matrix.getRowGroupCount() - 1) << " ---- " << std::endl; } - return out; + typename FlexibleSparseMatrix::index_type startRow = matrix.hasNontrivialRowGrouping() ? matrix.rowGroupIndices[i] : i; + typename FlexibleSparseMatrix::index_type endRow = matrix.hasNontrivialRowGrouping() ? matrix.rowGroupIndices[i + 1] : i+1; + for (typename FlexibleSparseMatrix::index_type rowIndex = startRow; rowIndex < endRow; ++rowIndex) { + // Print the actual row. + out << i << "\t(\t"; + typename FlexibleSparseMatrix::row_type row = matrix.getRow(rowIndex); + typename FlexibleSparseMatrix::index_type columnIndex = 0; + for (auto const& entry : row) { + //Insert zero between entries. + while (columnIndex < entry.getColumn()) { + out << "0\t"; + ++columnIndex; + } + ++columnIndex; + out << entry.getValue() << "\t"; + } + //Insert remaining zeros. + while (columnIndex++ <= matrix.getColumnCount()) { + out << "0\t"; + } + out << "\t)\t" << i << std::endl; + } + } + + // Print column numbers in footer. + out << "\t\t"; + for (typename FlexibleSparseMatrix::index_type i = 0; i < matrix.getColumnCount(); ++i) { + out << i << "\t"; } + out << std::endl; + return out; } // Explicitly instantiate the matrix. diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index 295b0337b..5ab573057 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -71,6 +71,22 @@ namespace storm { * @return An object representing the given row. */ row_type const& getRow(index_type) const; + + /*! + * Returns an object representing the offset'th row in the rowgroup + * @param rowGroup the row group + * @param offset which row in the group + * @return An object representing the given row. + */ + row_type& getRow(index_type rowGroup, index_type offset); + + /*! + * Returns an object representing the offset'th row in the rowgroup + * @param rowGroup the row group + * @param offset which row in the group + * @return An object representing the given row. + */ + row_type const& getRow(index_type rowGroup, index_type entryInGroup) const; /*! * Returns the number of rows of the matrix. @@ -92,6 +108,21 @@ namespace storm { * @return The number of nonzero entries in the matrix. */ index_type getNonzeroEntryCount() const; + + /*! + * Returns the number of row groups in the matrix. + * + * @return The number of row groups in the matrix. + */ + index_type getRowGroupCount() const; + + /*! + * Returns the size of the given row group. + * + * @param group The group whose size to retrieve. + * @return The number of rows that belong to the given row group. + */ + index_type getRowGroupSize(index_type group) const; /*! * Recomputes the number of columns and the number of non-zero entries. @@ -146,10 +177,6 @@ namespace storm { // The number of entries in the matrix. index_type nonzeroEntryCount; - // A vector containing the indices at which each given row begins. The values of the entries in row i are - // data[rowIndications[i]] to data[rowIndications[i + 1]] where the last entry is not included anymore. - std::vector rowIndications; - // A flag that indicates whether the matrix has a non-trivial row-grouping, i.e. (possibly) more than one // row per row group. bool nontrivialRowGrouping; diff --git a/src/storage/SparseMatrix.cpp b/src/storage/SparseMatrix.cpp index 04e941561..65f74d874 100644 --- a/src/storage/SparseMatrix.cpp +++ b/src/storage/SparseMatrix.cpp @@ -452,11 +452,6 @@ namespace storm { return rowGroupIndices; } - template - std::vector::index_type> const& SparseMatrix::getRowIndications() const { - return rowIndications; - } - template void SparseMatrix::makeRowsAbsorbing(storm::storage::BitVector const& rows) { for (auto row : rows) { diff --git a/src/storage/SparseMatrix.h b/src/storage/SparseMatrix.h index 94defdfa5..f9d9916c4 100644 --- a/src/storage/SparseMatrix.h +++ b/src/storage/SparseMatrix.h @@ -549,13 +549,6 @@ namespace storm { */ std::vector const& getRowGroupIndices() const; - /*! - * Returns the indices where new row groups start. - * - * @return The indices where new row groups start. - */ - std::vector const& getRowIndications() const; - /*! * This function makes the given rows absorbing. * From 56bcdcc8078c2fed7677577e00da686e116311c0 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 10:06:40 +0100 Subject: [PATCH 086/246] Priority queue as pointer Former-commit-id: 7e0d0f8c8c16a8035cabe50eba324d6ee930931c --- .../SparseDtmcEliminationModelChecker.cpp | 26 +++++++++---------- .../SparseDtmcEliminationModelChecker.h | 6 ++--- .../LongRunAverageEliminator.cpp | 4 +-- .../LongRunAverageEliminator.h | 5 ++-- .../PrioritizedEliminator.cpp | 4 +-- .../stateelimination/PrioritizedEliminator.h | 5 ++-- src/storage/FlexibleSparseMatrix.h | 4 +-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index bec0e7d3a..c969a639f 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -304,8 +304,8 @@ namespace storm { std::vector averageTimeInStates(stateValues.size(), storm::utility::one()); // First, we eliminate all states in BSCCs (except for the representative states). - std::unique_ptr> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs); - storm::solver::stateelimination::LongRunAverageEliminator stateEliminator(flexibleMatrix, flexibleBackwardTransitions, *priorityQueue, stateValues, averageTimeInStates); + std::shared_ptr> priorityQueue = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs); + storm::solver::stateelimination::LongRunAverageEliminator stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue, stateValues, averageTimeInStates); while (priorityQueue->hasNextState()) { storm::storage::sparse::state_type state = priorityQueue->popNextState(); @@ -725,7 +725,7 @@ namespace storm { storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(submatrixTransposed, true); std::chrono::high_resolution_clock::time_point conversionEnd = std::chrono::high_resolution_clock::now(); - std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); STORM_LOG_INFO("Computing conditional probilities." << std::endl); std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); @@ -852,7 +852,7 @@ namespace storm { } template - std::unique_ptr> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { + std::shared_ptr> SparseDtmcEliminationModelChecker::createStatePriorityQueue(boost::optional> const& distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states) { STORM_LOG_TRACE("Creating state priority queue for states " << states); @@ -896,15 +896,15 @@ namespace storm { } template - std::unique_ptr> SparseDtmcEliminationModelChecker::createNaivePriorityQueue(storm::storage::BitVector const& states) { + std::shared_ptr> SparseDtmcEliminationModelChecker::createNaivePriorityQueue(storm::storage::BitVector const& states) { std::vector sortedStates(states.begin(), states.end()); - return std::unique_ptr>(new StaticStatePriorityQueue(sortedStates)); + return std::shared_ptr>(new StaticStatePriorityQueue(sortedStates)); } template - void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::unique_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { + void SparseDtmcEliminationModelChecker::performPrioritizedStateElimination(std::shared_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly) { - storm::solver::stateelimination::PrioritizedEliminator stateEliminator(transitionMatrix, backwardTransitions, *priorityQueue, values); + storm::solver::stateelimination::PrioritizedEliminator stateEliminator(transitionMatrix, backwardTransitions, priorityQueue, values); while (priorityQueue->hasNextState()) { storm::storage::sparse::state_type state = priorityQueue->popNextState(); @@ -919,7 +919,7 @@ namespace storm { template void SparseDtmcEliminationModelChecker::performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional> const& distanceBasedPriorities) { - std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem); std::size_t numberOfStatesToEliminate = statePriorities->size(); STORM_LOG_DEBUG("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl); @@ -938,7 +938,7 @@ namespace storm { if (storm::settings::sparseDtmcEliminationModelCheckerSettings().isEliminateEntryStatesLastSet()) { STORM_LOG_DEBUG("Eliminating " << entryStateQueue.size() << " entry states as a last step."); std::vector sortedStates(entryStateQueue.begin(), entryStateQueue.end()); - std::unique_ptr> queuePriorities = std::unique_ptr>(new StaticStatePriorityQueue(sortedStates)); + std::shared_ptr> queuePriorities = std::shared_ptr>(new StaticStatePriorityQueue(sortedStates)); performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); } STORM_LOG_DEBUG("Eliminated " << subsystem.size() << " states." << std::endl); @@ -1009,7 +1009,7 @@ namespace storm { } } - std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs); STORM_LOG_TRACE("Eliminating " << statePriorities->size() << " trivial SCCs."); performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated all trivial SCCs."); @@ -1039,7 +1039,7 @@ namespace storm { } else { // In this case, we perform simple state elimination in the current SCC. STORM_LOG_TRACE("SCC of size " << scc.getNumberOfSetBits() << " is small enough to be eliminated directly."); - std::unique_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates); + std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates); performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated all states of SCC."); } @@ -1047,7 +1047,7 @@ namespace storm { // Finally, eliminate the entry states (if we are required to do so). if (eliminateEntryStates) { STORM_LOG_TRACE("Finally, eliminating entry states."); - std::unique_ptr> naivePriorities = createNaivePriorityQueue(entryStates); + std::shared_ptr> naivePriorities = createNaivePriorityQueue(entryStates); performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly); STORM_LOG_TRACE("Eliminated/added entry states."); } else { diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 3a77c43fb..65205a41d 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -88,11 +88,11 @@ namespace storm { static std::vector computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget); - static std::unique_ptr> createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); + static std::shared_ptr> createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); - static std::unique_ptr> createNaivePriorityQueue(storm::storage::BitVector const& states); + static std::shared_ptr> createNaivePriorityQueue(storm::storage::BitVector const& states); - static void performPrioritizedStateElimination(std::unique_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); + static void performPrioritizedStateElimination(std::shared_ptr>& priorityQueue, storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, std::vector& values, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly); static void performOrdinaryStateElimination(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::storage::BitVector const& subsystem, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, std::vector& values, boost::optional>& additionalStateValues, boost::optional> const& distanceBasedPriorities); diff --git a/src/solver/stateelimination/LongRunAverageEliminator.cpp b/src/solver/stateelimination/LongRunAverageEliminator.cpp index 250030c54..ec59dd1b1 100644 --- a/src/solver/stateelimination/LongRunAverageEliminator.cpp +++ b/src/solver/stateelimination/LongRunAverageEliminator.cpp @@ -5,7 +5,7 @@ namespace storm { namespace stateelimination { template - LongRunAverageEliminator::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue& priorityQueue, std::vector& stateValues, std::vector& averageTimeInStates) : StateEliminator(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues), averageTimeInStates(averageTimeInStates) { + LongRunAverageEliminator::LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector& stateValues, std::vector& averageTimeInStates) : StateEliminator(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues), averageTimeInStates(averageTimeInStates) { } template @@ -22,7 +22,7 @@ namespace storm { template void LongRunAverageEliminator::updatePriority(storm::storage::sparse::state_type const& state) { - priorityQueue.update(state, StateEliminator::transitionMatrix, StateEliminator::backwardTransitions, stateValues); + priorityQueue->update(state, StateEliminator::transitionMatrix, StateEliminator::backwardTransitions, stateValues); } template diff --git a/src/solver/stateelimination/LongRunAverageEliminator.h b/src/solver/stateelimination/LongRunAverageEliminator.h index 0e5522fef..f9b1e9cce 100644 --- a/src/solver/stateelimination/LongRunAverageEliminator.h +++ b/src/solver/stateelimination/LongRunAverageEliminator.h @@ -11,9 +11,10 @@ namespace storm { class LongRunAverageEliminator : public StateEliminator { typedef typename SparseModelType::ValueType ValueType; + typedef typename std::shared_ptr> PriorityQueuePointer; public: - LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue& priorityQueue, std::vector& stateValues, std::vector& averageTimeInStates); + LongRunAverageEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector& stateValues, std::vector& averageTimeInStates); // Instantiaton of Virtual methods void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override; @@ -24,7 +25,7 @@ namespace storm { private: - storm::modelchecker::StatePriorityQueue& priorityQueue; + PriorityQueuePointer priorityQueue; std::vector& stateValues; std::vector& averageTimeInStates; }; diff --git a/src/solver/stateelimination/PrioritizedEliminator.cpp b/src/solver/stateelimination/PrioritizedEliminator.cpp index de760e66b..567d07df9 100644 --- a/src/solver/stateelimination/PrioritizedEliminator.cpp +++ b/src/solver/stateelimination/PrioritizedEliminator.cpp @@ -5,7 +5,7 @@ namespace storm { namespace stateelimination { template - PrioritizedEliminator::PrioritizedEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue priorityQueue, std::vector& stateValues) : StateEliminator(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) { + PrioritizedEliminator::PrioritizedEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector& stateValues) : StateEliminator(transitionMatrix, backwardTransitions), priorityQueue(priorityQueue), stateValues(stateValues) { } template @@ -20,7 +20,7 @@ namespace storm { template void PrioritizedEliminator::updatePriority(storm::storage::sparse::state_type const& state) { - priorityQueue.update(state, StateEliminator::transitionMatrix, StateEliminator::backwardTransitions, stateValues); + priorityQueue->update(state, StateEliminator::transitionMatrix, StateEliminator::backwardTransitions, stateValues); } template diff --git a/src/solver/stateelimination/PrioritizedEliminator.h b/src/solver/stateelimination/PrioritizedEliminator.h index 7a242ebdf..1180fad09 100644 --- a/src/solver/stateelimination/PrioritizedEliminator.h +++ b/src/solver/stateelimination/PrioritizedEliminator.h @@ -11,9 +11,10 @@ namespace storm { class PrioritizedEliminator : public StateEliminator { typedef typename SparseModelType::ValueType ValueType; + typedef typename std::shared_ptr> PriorityQueuePointer; public: - PrioritizedEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, storm::modelchecker::StatePriorityQueue priorityQueue, std::vector& stateValues); + PrioritizedEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions, PriorityQueuePointer priorityQueue, std::vector& stateValues); // Instantiaton of Virtual methods void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override; @@ -23,7 +24,7 @@ namespace storm { bool isFilterPredecessor() const override; private: - storm::modelchecker::StatePriorityQueue& priorityQueue; + PriorityQueuePointer priorityQueue; std::vector& stateValues; }; diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index 5ab573057..163a25aa4 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -21,9 +21,7 @@ namespace storm { class FlexibleSparseMatrix { public: // TODO: make this class a bit more consistent with the big sparse matrix and improve it: - // * add output iterator and improve the way the matrix is printed - // * add stuff like clearRow, multiplyRowWithScalar - // * implement row grouping + // * add stuff like iterator, clearRow, multiplyRowWithScalar typedef uint_fast64_t index_type; typedef ValueType value_type; From a64a7cdbf8c4ea06fb3d70bb633f45c83c5cd21d Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 11:50:21 +0100 Subject: [PATCH 087/246] Python script compatible with version 3.4 Former-commit-id: 2e78da799d9d2c0a2f6cb6df216becebf8b12ca7 --- benchmark_dft.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index d2c43bf80..8e9a5462b 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -3,7 +3,6 @@ import os.path import subprocess import re import time -import math import argparse STORM_PATH= "/Users/mvolk/develop/dft-storm/build/src/storm-dft" @@ -92,6 +91,11 @@ def run_tool(args, quiet=False): result = output return result +def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): + if a == b: + return True + return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) + if __name__ == "__main__": parser = argparse.ArgumentParser(description='Benchmarking DFTs via Storm') parser.add_argument('--debuglevel', type=int, default=0, help='the debug level (0=silent, 1=print benchmarks, 2=print output from storm') @@ -115,7 +119,7 @@ if __name__ == "__main__": if not parametric: # Float result = float(result) - if not math.isclose(result, float(expected_result), rel_tol=1e-05): + if not isclose(result, float(expected_result), rel_tol=1e-05): print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result)) else: correct += 1 From 7bf5fcb308326f9aacc4aabd860f92f50e857bae Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 11:51:15 +0100 Subject: [PATCH 088/246] Fixed compile issue under Debian Former-commit-id: 13fe157a96964a825d0eeda81342673763f485a8 --- src/solver/stateelimination/StateEliminator.cpp | 1 - src/solver/stateelimination/StateEliminator.h | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/solver/stateelimination/StateEliminator.cpp b/src/solver/stateelimination/StateEliminator.cpp index 3e3d8c53a..09f576e5a 100644 --- a/src/solver/stateelimination/StateEliminator.cpp +++ b/src/solver/stateelimination/StateEliminator.cpp @@ -1,7 +1,6 @@ #include "src/solver/stateelimination/StateEliminator.h" #include "src/storage/BitVector.h" -#include "src/adapters/CarlAdapter.h" #include "src/utility/constants.h" #include "src/utility/macros.h" #include "src/exceptions/InvalidStateException.h" diff --git a/src/solver/stateelimination/StateEliminator.h b/src/solver/stateelimination/StateEliminator.h index 2a58912e8..a0bf04a98 100644 --- a/src/solver/stateelimination/StateEliminator.h +++ b/src/solver/stateelimination/StateEliminator.h @@ -4,6 +4,9 @@ #include "src/storage/FlexibleSparseMatrix.h" #include "src/storage/SparseMatrix.h" #include "src/storage/sparse/StateType.h" +#include "src/models/sparse/Dtmc.h" +#include "src/models/sparse/StandardRewardModel.h" +#include "src/adapters/CarlAdapter.h" #include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" namespace storm { @@ -39,4 +42,4 @@ namespace storm { } // namespace storage } // namespace storm -#endif // STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ \ No newline at end of file +#endif // STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ From 017fa192815a56d2641cd1c15cd08068f0607a42 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 11:55:42 +0100 Subject: [PATCH 089/246] Fixed compile issue Former-commit-id: a58c76d17584b72fcb4c04313f3168ffef854975 --- src/solver/stateelimination/StateEliminator.cpp | 3 +-- src/solver/stateelimination/StateEliminator.h | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/solver/stateelimination/StateEliminator.cpp b/src/solver/stateelimination/StateEliminator.cpp index 3e3d8c53a..01dc8a5af 100644 --- a/src/solver/stateelimination/StateEliminator.cpp +++ b/src/solver/stateelimination/StateEliminator.cpp @@ -1,7 +1,6 @@ #include "src/solver/stateelimination/StateEliminator.h" #include "src/storage/BitVector.h" -#include "src/adapters/CarlAdapter.h" #include "src/utility/constants.h" #include "src/utility/macros.h" #include "src/exceptions/InvalidStateException.h" @@ -256,4 +255,4 @@ namespace storm { } // namespace stateelimination } // namespace storage -} // namespace storm \ No newline at end of file +} // namespace storm diff --git a/src/solver/stateelimination/StateEliminator.h b/src/solver/stateelimination/StateEliminator.h index 2a58912e8..a0bf04a98 100644 --- a/src/solver/stateelimination/StateEliminator.h +++ b/src/solver/stateelimination/StateEliminator.h @@ -4,6 +4,9 @@ #include "src/storage/FlexibleSparseMatrix.h" #include "src/storage/SparseMatrix.h" #include "src/storage/sparse/StateType.h" +#include "src/models/sparse/Dtmc.h" +#include "src/models/sparse/StandardRewardModel.h" +#include "src/adapters/CarlAdapter.h" #include "src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h" namespace storm { @@ -39,4 +42,4 @@ namespace storm { } // namespace storage } // namespace storm -#endif // STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ \ No newline at end of file +#endif // STORM_SOLVER_STATEELIMINATION_STATEELIMINATOR_H_ From 63b0513f38c74bd06b0254d70df9d32e9636d8ef Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 14:58:26 +0100 Subject: [PATCH 090/246] Set probability for pdeps Former-commit-id: 2ac06e76c007d05cef74fc3028e967910abacb06 --- src/builder/ExplicitDFTModelBuilder.cpp | 8 +++++--- src/storage/dft/DFTState.cpp | 3 +-- src/storage/dft/DFTState.h | 11 +++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index cd2704dc6..723d75920 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -187,7 +187,9 @@ namespace storm { // Set transitions if (hasDependencies) { // Failure is due to dependency -> add non-deterministic choice - transitionMatrixBuilder.addNextValue(state->getId() + rowOffset++, newState->getId(), storm::utility::one()); + std::shared_ptr const> dependency = mDft.getDependency(state->getDependencyId(smallest-1)); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset++, newState->getId(), dependency->probability()); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with probability " << dependency->probability()); } else { // Set failure rate according to usage bool isUsed = true; @@ -203,11 +205,11 @@ namespace storm { if (resultFind != outgoingTransitions.end()) { // Add to existing transition resultFind->second += rate; - STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with " << rate << " to " << resultFind->second); + STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with rate " << rate << " to new rate " << resultFind->second); } else { // Insert new transition outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with " << rate); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with rate " << rate); } exitRate += rate; } diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 672ca14a7..8714f0130 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -99,8 +99,7 @@ namespace storm { STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); if (nrFailableDependencies() > 0) { // Consider failure due to dependency - assert(index < nrFailableDependencies()); - std::shared_ptr const> dependency = mDft.getDependency(mFailableDependencies[index]); + std::shared_ptr const> dependency = mDft.getDependency(getDependencyId(index)); std::pair const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true); mFailableDependencies.erase(mFailableDependencies.begin() + index); setFailed(res.first->id()); diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 17a9c2d3b..520587a42 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -6,6 +6,7 @@ #include #include +#include namespace storm { namespace storage { @@ -114,6 +115,16 @@ namespace storm { size_t nrFailableDependencies() const { return mFailableDependencies.size(); } + + /** + * Gets the id of the dependency at index in the list of failable dependencies. + * @param index Index in list of failable dependencies. + * @return Id of the dependency + */ + size_t getDependencyId(size_t index) const { + assert(index < nrFailableDependencies()); + return mFailableDependencies[index]; + } /** * Sets all failable BEs due to dependencies from newly failed element From 3d4c5b3df289d0431000fd9acadaa98aba06a91f Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 17:06:16 +0100 Subject: [PATCH 091/246] Fixed output for flexible matrix Former-commit-id: e2c9913b6eddb4d5add820623115a0fa21a2cb54 --- src/storage/FlexibleSparseMatrix.cpp | 77 ++++++++++++++++++---------- src/storage/FlexibleSparseMatrix.h | 15 ++++++ 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp index 99ed68337..03fcf3d57 100644 --- a/src/storage/FlexibleSparseMatrix.cpp +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -63,6 +63,11 @@ namespace storm { return getRow(rowGroupIndices[rowGroup] + offset); } + template + std::vector::index_type> const& FlexibleSparseMatrix::getRowGroupIndices() const { + return rowGroupIndices; + } + template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowCount() const { return this->data.size(); @@ -164,49 +169,64 @@ namespace storm { } return false; } + + template + std::ostream& FlexibleSparseMatrix::printRow(std::ostream& out, index_type const& rowIndex) const { + index_type columnIndex = 0; + row_type row = this->getRow(rowIndex); + for (index_type column = 0; column < this->getColumnCount(); ++column) { + if (columnIndex < row.size() && row[columnIndex].getColumn() == column) { + // Insert entry + out << row[columnIndex].getValue() << "\t"; + ++columnIndex; + } else { + // Insert zero + out << "0\t"; + } + } + return out; + } + template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix) { + typedef typename FlexibleSparseMatrix::index_type FlexibleIndex; + // Print column numbers in header. out << "\t\t"; - for (typename FlexibleSparseMatrix::index_type i = 0; i < matrix.getColumnCount(); ++i) { + for (FlexibleIndex i = 0; i < matrix.getColumnCount(); ++i) { out << i << "\t"; } out << std::endl; - typename FlexibleSparseMatrix::index_type endIndex = matrix.hasNontrivialRowGrouping() ? matrix.getRowGroupCount() : matrix.getRowCount(); - // Iterate over all rows. - for (typename SparseMatrix::index_type i = 0; i < endIndex; ++i) { - if (matrix.hasNontrivialRowGrouping()) { - out << "\t---- group " << i << "/" << (matrix.getRowGroupCount() - 1) << " ---- " << std::endl; + if (matrix.hasNontrivialRowGrouping()) { + // Iterate over all row groups + FlexibleIndex rowGroupCount = matrix.getRowGroupCount(); + for (FlexibleIndex rowGroup = 0; rowGroup < rowGroupCount; ++rowGroup) { + out << "\t---- group " << rowGroup << "/" << (rowGroupCount - 1) << " ---- " << std::endl; + FlexibleIndex endRow = rowGroup+1 < rowGroupCount ? matrix.rowGroupIndices[rowGroup + 1] : matrix.getRowCount(); + // Iterate over all rows. + for (FlexibleIndex row = matrix.rowGroupIndices[rowGroup]; row < endRow; ++row) { + // Print the actual row. + out << rowGroup << "\t(\t"; + matrix.printRow(out, row); + out << "\t)\t" << rowGroup << std::endl; + } } - typename FlexibleSparseMatrix::index_type startRow = matrix.hasNontrivialRowGrouping() ? matrix.rowGroupIndices[i] : i; - typename FlexibleSparseMatrix::index_type endRow = matrix.hasNontrivialRowGrouping() ? matrix.rowGroupIndices[i + 1] : i+1; - for (typename FlexibleSparseMatrix::index_type rowIndex = startRow; rowIndex < endRow; ++rowIndex) { + + } else { + // Iterate over all rows + for (FlexibleIndex row = 0; row < matrix.getRowCount(); ++row) { // Print the actual row. - out << i << "\t(\t"; - typename FlexibleSparseMatrix::row_type row = matrix.getRow(rowIndex); - typename FlexibleSparseMatrix::index_type columnIndex = 0; - for (auto const& entry : row) { - //Insert zero between entries. - while (columnIndex < entry.getColumn()) { - out << "0\t"; - ++columnIndex; - } - ++columnIndex; - out << entry.getValue() << "\t"; - } - //Insert remaining zeros. - while (columnIndex++ <= matrix.getColumnCount()) { - out << "0\t"; - } - out << "\t)\t" << i << std::endl; + out << row << "\t(\t"; + matrix.printRow(out, row); + out << "\t)\t" << row << std::endl; } } // Print column numbers in footer. out << "\t\t"; - for (typename FlexibleSparseMatrix::index_type i = 0; i < matrix.getColumnCount(); ++i) { + for (FlexibleIndex i = 0; i < matrix.getColumnCount(); ++i) { out << i << "\t"; } out << std::endl; @@ -215,8 +235,11 @@ namespace storm { // Explicitly instantiate the matrix. template class FlexibleSparseMatrix; + template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix); + #ifdef STORM_HAVE_CARL template class FlexibleSparseMatrix; + template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix); #endif } // namespace storage diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index 163a25aa4..d7e74f062 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -85,6 +85,13 @@ namespace storm { * @return An object representing the given row. */ row_type const& getRow(index_type rowGroup, index_type entryInGroup) const; + + /*! + * Returns the grouping of rows of this matrix. + * + * @return The grouping of rows of this matrix. + */ + std::vector const& getRowGroupIndices() const; /*! * Returns the number of rows of the matrix. @@ -163,6 +170,14 @@ namespace storm { */ bool rowHasDiagonalElement(storm::storage::sparse::state_type state); + /*! + * Print row. + * @param out Output stream. + * @param rowIndex Index of row to print. + * @return Output with printed row. + */ + std::ostream& printRow(std::ostream& out, index_type const& rowIndex) const; + template friend std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix); From a6a8e5fff6f7ff08f24d4d1cc0582db8802da923 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 17:14:03 +0100 Subject: [PATCH 092/246] Structure for MA to CTMC Former-commit-id: 6dee4cec3cf0469658f9542db5a77115b4868f26 --- src/builder/ExplicitDFTModelBuilder.cpp | 16 ++++++------ .../SparseMarkovAutomatonCslModelChecker.cpp | 2 +- src/models/sparse/MarkovAutomaton.cpp | 25 +++++++++++++++++++ src/models/sparse/MarkovAutomaton.h | 5 ++++ src/utility/storm.h | 14 ++++++++--- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 723d75920..aa4d46f15 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -73,20 +73,20 @@ namespace storm { } std::shared_ptr> model; - if (deterministic) { - // Turn the probabilities into rates by multiplying each row with the exit rate of the state. - // TODO Matthias: avoid transforming back and forth - storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); - for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { + // Turn the probabilities into rates by multiplying each row with the exit rate of the state. + // TODO Matthias: avoid transforming back and forth + storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); + for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { + if (modelComponents.markovianStates.get(row)) { for (auto& entry : rateMatrix.getRow(row)) { entry.setValue(entry.getValue() * modelComponents.exitRates[row]); } } - + } + if (deterministic) { model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling)); } else { - model = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); - + model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); } model->printModelInformationToStream(std::cout); return model; diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index b33b01436..12db539c8 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -30,7 +30,7 @@ namespace storm { template bool SparseMarkovAutomatonCslModelChecker::canHandle(CheckTask const& checkTask) const { storm::logic::Formula const& formula = checkTask.getFormula(); - return formula.isCslStateFormula() || formula.isCslPathFormula() || (formula.isRewardPathFormula() && formula.isReachabilityRewardFormula()); + return formula.isCslStateFormula() || formula.isCslPathFormula() || (formula.isRewardPathFormula() && formula.isReachabilityRewardFormula()) || formula.isExpectedTimeOperatorFormula(); } template diff --git a/src/models/sparse/MarkovAutomaton.cpp b/src/models/sparse/MarkovAutomaton.cpp index 56a6400d1..c95957248 100644 --- a/src/models/sparse/MarkovAutomaton.cpp +++ b/src/models/sparse/MarkovAutomaton.cpp @@ -3,6 +3,8 @@ #include "src/exceptions/InvalidArgumentException.h" #include "src/utility/constants.h" #include "src/adapters/CarlAdapter.h" +#include "src/storage/FlexibleSparseMatrix.h" +#include "src/models/sparse/Dtmc.h" namespace storm { namespace models { @@ -217,6 +219,29 @@ namespace storm { } } + template + bool MarkovAutomaton::hasOnlyTrivialNondeterminism() const { + // Check every state + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + // Get number of choices in current state + uint_fast64_t numberChoices = this->getTransitionMatrix().getRowGroupIndices()[state + 1] - this->getTransitionMatrix().getRowGroupIndices()[state]; + if (isMarkovianState(state)) { + assert(numberChoices == 1); + } + if (numberChoices > 1) { + assert(isProbabilisticState(state)); + return false; + } + } + return true; + } + + template + std::shared_ptr> MarkovAutomaton::convertToCTMC() { + assert(false) + } + + template class MarkovAutomaton; // template class MarkovAutomaton; diff --git a/src/models/sparse/MarkovAutomaton.h b/src/models/sparse/MarkovAutomaton.h index 731b845f3..ed807ab84 100644 --- a/src/models/sparse/MarkovAutomaton.h +++ b/src/models/sparse/MarkovAutomaton.h @@ -2,6 +2,7 @@ #define STORM_MODELS_SPARSE_MARKOVAUTOMATON_H_ #include "src/models/sparse/NondeterministicModel.h" +#include "src/models/sparse/Ctmc.h" #include "src/utility/OsDetection.h" namespace storm { @@ -121,6 +122,10 @@ namespace storm { */ void close(); + bool hasOnlyTrivialNondeterminism() const; + + std::shared_ptr> convertToCTMC(); + virtual void writeDotToStream(std::ostream& outStream, bool includeLabeling = true, storm::storage::BitVector const* subsystem = nullptr, std::vector const* firstValue = nullptr, std::vector const* secondValue = nullptr, std::vector const* stateColoring = nullptr, std::vector const* colors = nullptr, std::vector* scheduler = nullptr, bool finalizeOutput = true) const; std::size_t getSizeInBytes() const; diff --git a/src/utility/storm.h b/src/utility/storm.h index f297d9e41..f737b318e 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -277,6 +277,8 @@ namespace storm { storm::modelchecker::SparseDtmcEliminationModelChecker> modelchecker2(*dtmc); if (modelchecker2.canHandle(task)) { result = modelchecker2.check(task); + } else { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The property " << *formula << " is not supported on DTMCs."); } } } else if (model->getType() == storm::models::ModelType::Mdp) { @@ -300,9 +302,15 @@ namespace storm { result = modelchecker.check(task); } else if (model->getType() == storm::models::ModelType::MarkovAutomaton) { std::shared_ptr> ma = model->template as>(); - - storm::modelchecker::SparseMarkovAutomatonCslModelChecker> modelchecker(*ma); - result = modelchecker.check(task); + if (ma->hasOnlyTrivialNondeterminism()) { + // Markov automaton can be converted into CTMC + std::shared_ptr> ctmc = ma->convertToCTMC(); + storm::modelchecker::SparseCtmcCslModelChecker> modelchecker(*ctmc); + result = modelchecker.check(task); + } else { + storm::modelchecker::SparseMarkovAutomatonCslModelChecker> modelchecker(*ma); + result = modelchecker.check(task); + } } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The model type " << model->getType() << " is not supported."); } From 0a78ba13f5540e948c0f4aaecaef9134f34623eb Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 18:45:49 +0100 Subject: [PATCH 093/246] MA to CTMC for trivial nondeterminism Former-commit-id: 8a342f032eb1b846265b2841b58793d90bd75abc --- benchmark_dft.py | 1 + examples/dft/fdep3.dft | 5 ++ src/models/sparse/MarkovAutomaton.cpp | 54 +++++++++++++++++++- src/solver/stateelimination/MAEliminator.cpp | 45 ++++++++++++++++ src/solver/stateelimination/MAEliminator.h | 32 ++++++++++++ src/storage/FlexibleSparseMatrix.cpp | 9 ++++ src/storage/FlexibleSparseMatrix.h | 8 +++ 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 examples/dft/fdep3.dft create mode 100644 src/solver/stateelimination/MAEliminator.cpp create mode 100644 src/solver/stateelimination/MAEliminator.h diff --git a/benchmark_dft.py b/benchmark_dft.py index 8e9a5462b..edfc88bda 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -20,6 +20,7 @@ benchmarks = [ ("deathegg", False, [46.667, 1]), ("fdep", False, [0.666667, 1]), ("fdep2", False, [2, 1]), + ("fdep3", False, [2.5, 1]), #("ftpp_complex", False, [0, 1]), # Compute #("ftpp_large", False, [0, 1]), # Compute #("ftpp_standard", False, [0, 1]), # Compute diff --git a/examples/dft/fdep3.dft b/examples/dft/fdep3.dft new file mode 100644 index 000000000..3815c9973 --- /dev/null +++ b/examples/dft/fdep3.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C" "F"; +"F" fdep "B" "C"; +"B" lambda=0.4 dorm=0; +"C" lambda=0.8 dorm=0; diff --git a/src/models/sparse/MarkovAutomaton.cpp b/src/models/sparse/MarkovAutomaton.cpp index c95957248..c757af1a0 100644 --- a/src/models/sparse/MarkovAutomaton.cpp +++ b/src/models/sparse/MarkovAutomaton.cpp @@ -5,6 +5,8 @@ #include "src/adapters/CarlAdapter.h" #include "src/storage/FlexibleSparseMatrix.h" #include "src/models/sparse/Dtmc.h" +#include "src/solver/stateelimination/MAEliminator.h" +#include "src/utility/vector.h" namespace storm { namespace models { @@ -238,7 +240,57 @@ namespace storm { template std::shared_ptr> MarkovAutomaton::convertToCTMC() { - assert(false) + STORM_LOG_TRACE("MA matrix:" << std::endl << this->getTransitionMatrix()); + STORM_LOG_TRACE("Markovian states: " << getMarkovianStates()); + + // Eliminate all probabilistic states by state elimination + // Initialize + storm::storage::FlexibleSparseMatrix flexibleMatrix(this->getTransitionMatrix()); + storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(this->getTransitionMatrix().transpose()); + storm::solver::stateelimination::MAEliminator> stateEliminator(flexibleMatrix, flexibleBackwardTransitions); + + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + assert(!this->isHybridState(state)); + if (this->isProbabilisticState(state)) { + // Eliminate this probabilistic state + stateEliminator.eliminateState(state, true); + STORM_LOG_TRACE("Flexible matrix after eliminating state " << state << ":" << std::endl << flexibleMatrix); + } + } + + // Create the rate matrix for the CTMC + storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, false); + // Remember state to keep + storm::storage::BitVector keepStates(this->getNumberOfStates(), true); + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + if (storm::utility::isZero(flexibleMatrix.getRowSum(state))) { + // State is eliminated and can be discarded + keepStates.set(state, false); + } else { + assert(this->isMarkovianState(state)); + // Copy transitions + for (uint_fast64_t row = flexibleMatrix.getRowGroupIndices()[state]; row < flexibleMatrix.getRowGroupIndices()[state + 1]; ++row) { + for (auto const& entry : flexibleMatrix.getRow(row)) { + // Convert probabilities into rates + transitionMatrixBuilder.addNextValue(state, entry.getColumn(), entry.getValue() * exitRates[state]); + } + } + } + } + + storm::storage::SparseMatrix rateMatrix = transitionMatrixBuilder.build(); + rateMatrix = rateMatrix.getSubmatrix(false, keepStates, keepStates, false); + STORM_LOG_TRACE("New CTMC matrix:" << std::endl << rateMatrix); + // Construct CTMC + storm::models::sparse::StateLabeling stateLabeling = this->getStateLabeling().getSubLabeling(keepStates); + boost::optional> optionalChoiceLabeling = this->getOptionalChoiceLabeling(); + if (optionalChoiceLabeling) { + optionalChoiceLabeling = storm::utility::vector::filterVector(optionalChoiceLabeling.get(), keepStates); + } + //TODO update reward models according to kept states + std::unordered_map rewardModels = this->getRewardModels(); + + return std::make_shared>(std::move(rateMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)); } diff --git a/src/solver/stateelimination/MAEliminator.cpp b/src/solver/stateelimination/MAEliminator.cpp new file mode 100644 index 000000000..7a26e995c --- /dev/null +++ b/src/solver/stateelimination/MAEliminator.cpp @@ -0,0 +1,45 @@ +#include "src/solver/stateelimination/MAEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + MAEliminator::MAEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions) : StateEliminator(transitionMatrix, backwardTransitions){ + } + + template + void MAEliminator::updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) { + // Do nothing + } + + template + void MAEliminator::updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) { + // Do nothing + } + + template + void MAEliminator::updatePriority(storm::storage::sparse::state_type const& state) { + // Do nothing + } + + template + bool MAEliminator::filterPredecessor(storm::storage::sparse::state_type const& state) { + assert(false); + } + + template + bool MAEliminator::isFilterPredecessor() const { + return false; + } + + + template class MAEliminator>; + +#ifdef STORM_HAVE_CARL + template class MAEliminator>; +#endif + + } // namespace stateelimination + } // namespace storage +} // namespace storm diff --git a/src/solver/stateelimination/MAEliminator.h b/src/solver/stateelimination/MAEliminator.h new file mode 100644 index 000000000..d4db284c3 --- /dev/null +++ b/src/solver/stateelimination/MAEliminator.h @@ -0,0 +1,32 @@ +#ifndef STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_ +#define STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_ + +#include "src/solver/stateelimination/StateEliminator.h" + +namespace storm { + namespace solver { + namespace stateelimination { + + template + class MAEliminator : public StateEliminator { + + typedef typename SparseModelType::ValueType ValueType; + + public: + MAEliminator(storm::storage::FlexibleSparseMatrix& transitionMatrix, storm::storage::FlexibleSparseMatrix& backwardTransitions); + + // Instantiaton of Virtual methods + void updateValue(storm::storage::sparse::state_type const& state, ValueType const& loopProbability) override; + void updatePredecessor(storm::storage::sparse::state_type const& predecessor, ValueType const& probability, storm::storage::sparse::state_type const& state) override; + void updatePriority(storm::storage::sparse::state_type const& state) override; + bool filterPredecessor(storm::storage::sparse::state_type const& state) override; + bool isFilterPredecessor() const override; + + private: + }; + + } // namespace stateelimination + } // namespace storage +} // namespace storm + +#endif // STORM_SOLVER_STATEELIMINATION_MAELIMINATOR_H_ diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp index 03fcf3d57..60422dc08 100644 --- a/src/storage/FlexibleSparseMatrix.cpp +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -96,6 +96,15 @@ namespace storm { return rowGroupIndices[group + 1] - rowGroupIndices[group]; } } + + template + ValueType FlexibleSparseMatrix::getRowSum(index_type row) const { + ValueType sum = storm::utility::zero(); + for (auto const& element : getRow(row)) { + sum += element.getValue(); + } + return sum; + } template void FlexibleSparseMatrix::updateDimensions() { diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index d7e74f062..28100e0a2 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -128,6 +128,14 @@ namespace storm { * @return The number of rows that belong to the given row group. */ index_type getRowGroupSize(index_type group) const; + + /*! + * Computes the sum of the entries in a given row. + * + * @param row The row that is to be summed. + * @return The sum of the selected row. + */ + value_type getRowSum(index_type row) const; /*! * Recomputes the number of columns and the number of non-zero entries. From 28bc49ed664988e5a4c6008f3c648c2e3f360ca5 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 15 Feb 2016 19:06:53 +0100 Subject: [PATCH 094/246] Relative paths in benchmark script Former-commit-id: e360ade8cefc568c9106e99724b2448c6f5ca3d8 --- benchmark_dft.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index edfc88bda..dfcecd15f 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -1,13 +1,14 @@ import os import os.path +import sys import subprocess import re import time import argparse -STORM_PATH= "/Users/mvolk/develop/dft-storm/build/src/storm-dft" -EXAMPLE_DIR= "/Users/mvolk/develop/dft-storm/examples/dft/" - +DIR=os.getcwd() +STORM_PATH=os.path.join(DIR, "build/src/storm-dft") +EXAMPLE_DIR=os.path.join(DIR, "examples/dft/") benchmarks = [ ("and", False, [3, 1]), From 67626ff9bb4f30f7f13fd9d6a5a3517a5814e8d3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 16 Feb 2016 11:18:47 +0100 Subject: [PATCH 095/246] Xcode support for new directory Former-commit-id: 7d3776d555dd6406de30e9d5e13a1bab71ff45d9 --- src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be3b825a0..b8fbd6953 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,7 +31,8 @@ file(GLOB STORM_PARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/*.h ${PROJECT_SOUR file(GLOB_RECURSE STORM_PARSER_PRISMPARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.h ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.cpp) file(GLOB STORM_SETTINGS_FILES ${PROJECT_SOURCE_DIR}/src/settings/*.h ${PROJECT_SOURCE_DIR}/src/settings/*.cpp) file(GLOB STORM_SETTINGS_MODULES_FILES ${PROJECT_SOURCE_DIR}/src/settings/modules/*.h ${PROJECT_SOURCE_DIR}/src/settings/modules/*.cpp) -file(GLOB_RECURSE STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp) +file(GLOB STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp) +file(GLOB STORM_SOLVER_STATEELIMINATION_FILES ${PROJECT_SOURCE_DIR}/src/solver/stateelimination/*.h ${PROJECT_SOURCE_DIR}/src/solver/stateelimination/*.cpp) file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp) file(GLOB STORM_STORAGE_BISIMULATION_FILES ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.h ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.cpp) file(GLOB STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp) @@ -79,6 +80,7 @@ source_group(parser\\prismparser FILES ${STORM_PARSER_PRISMPARSER_FILES}) source_group(settings FILES ${STORM_SETTINGS_FILES}) source_group(settings\\modules FILES ${STORM_SETTINGS_MODULES_FILES}) source_group(solver FILES ${STORM_SOLVER_FILES}) +source_group(solver\\stateelimination FILES ${STORM_SOLVER_STATEELIMINATION_FILES}) source_group(storage FILES ${STORM_STORAGE_FILES}) source_group(storage\\bisimulation FILES ${STORM_STORAGE_BISIMULATION_FILES}) source_group(storage\\dd FILES ${STORM_STORAGE_DD_FILES}) From 6b31b23c624e5c10e54a5421d0bc145c92aed49e Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 16 Feb 2016 11:21:37 +0100 Subject: [PATCH 096/246] Removed unused time keeping variables Former-commit-id: 67449791d505d85b39295f700ae502adab7d55d4 --- .../reachability/SparseDtmcEliminationModelChecker.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index c969a639f..5d0bd164c 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -720,15 +720,12 @@ namespace storm { eliminationOrderNeedsReversedDistances(order)); } - std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now(); storm::storage::FlexibleSparseMatrix flexibleMatrix(submatrix); storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(submatrixTransposed, true); - std::chrono::high_resolution_clock::time_point conversionEnd = std::chrono::high_resolution_clock::now(); std::shared_ptr> statePriorities = createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate); STORM_LOG_INFO("Computing conditional probilities." << std::endl); - std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); uint_fast64_t numberOfStatesToEliminate = statePriorities->size(); STORM_LOG_INFO("Eliminating " << numberOfStatesToEliminate << " states using the state elimination technique." << std::endl); performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(), true); @@ -950,10 +947,7 @@ namespace storm { // Then, we convert the reduced matrix to a more flexible format to be able to perform state elimination more easily. storm::storage::FlexibleSparseMatrix flexibleMatrix(transitionMatrix); storm::storage::FlexibleSparseMatrix flexibleBackwardTransitions(backwardTransitions); - auto conversionEnd = std::chrono::high_resolution_clock::now(); - - std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now(); - + storm::settings::modules::SparseDtmcEliminationModelCheckerSettings::EliminationOrder order = storm::settings::sparseDtmcEliminationModelCheckerSettings().getEliminationOrder(); boost::optional> distanceBasedPriorities; if (eliminationOrderNeedsDistances(order)) { From a9c80ef9dc6a1300a5963a0af51a5a0ac0a42052 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 16 Feb 2016 12:06:19 +0100 Subject: [PATCH 097/246] Better error handling Former-commit-id: 36bd1108226df7010e6749e4f989d4bdc8510336 --- src/parser/DFTGalileoParser.cpp | 23 ++++++++--------------- src/parser/DFTGalileoParser.h | 2 +- src/storage/dft/DFTBuilder.h | 9 +++++---- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index c8639ae30..d11f5ae3b 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -15,14 +15,11 @@ namespace storm { template storm::storage::DFT DFTGalileoParser::parseDFT(const std::string& filename) { - if(readFile(filename)) { - storm::storage::DFT dft = builder.build(); - STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); - STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); - return dft; - } else { - throw storm::exceptions::FileIoException(); - } + readFile(filename); + storm::storage::DFT dft = builder.build(); + STORM_LOG_DEBUG("Elements:" << std::endl << dft.getElementsString()); + STORM_LOG_DEBUG("Spare Modules:" << std::endl << dft.getSpareModulesString()); + return dft; } template @@ -39,7 +36,7 @@ namespace storm { } template - bool DFTGalileoParser::readFile(const std::string& filename) { + void DFTGalileoParser::readFile(const std::string& filename) { // constants std::string toplevelToken = "toplevel"; std::string toplevelId; @@ -52,12 +49,11 @@ namespace storm { } catch (std::ifstream::failure e) { STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Exception during file opening on " << filename << "."); - return false; + return; } file.exceptions( std::ifstream::goodbit ); std::string line; - bool generalSuccess = true; while(std::getline(file, line)) { bool success = true; STORM_LOG_TRACE("Parsing: " << line); @@ -119,16 +115,13 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Type name: " << tokens[1] << " not recognized."); success = false; } - } - if (generalSuccess) { - generalSuccess = success; + STORM_LOG_THROW(success, storm::exceptions::FileIoException, "Error while adding element '" << name << "' of line '" << line << "'."); } } if(!builder.setTopLevel(toplevelId)) { STORM_LOG_THROW(false, storm::exceptions::FileIoException, "Top level id unknown."); } file.close(); - return generalSuccess; } template diff --git a/src/parser/DFTGalileoParser.h b/src/parser/DFTGalileoParser.h index 557803465..fc64ee80e 100644 --- a/src/parser/DFTGalileoParser.h +++ b/src/parser/DFTGalileoParser.h @@ -31,7 +31,7 @@ namespace storm { storm::storage::DFT parseDFT(std::string const& filename); private: - bool readFile(std::string const& filename); + void readFile(std::string const& filename); std::string stripQuotsFromName(std::string const& name); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index ef01369c9..37c3c4eaa 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -6,6 +6,7 @@ #include #include #include +#include "src/utility/macros.h" namespace storm { namespace storage { @@ -70,7 +71,7 @@ namespace storm { //0 <= probability <= 1 if (!storm::utility::isOne(probability) && children.size() > 2) { //TODO Matthias: introduce additional element for probability and then add pdeps with probability 1 to children - std::cerr << "Probability != 1 for more than one child currently not supported." << std::endl; + STORM_LOG_ERROR("Probability != 1 for more than one child currently not supported."); return false; } @@ -78,7 +79,7 @@ namespace storm { std::string nameDep = name + "_" + std::to_string(i); if(mElements.count(nameDep) != 0) { // Element with that name already exists. - std::cerr << "Element with name: " << nameDep << " already exists." << std::endl; + STORM_LOG_ERROR("Element with name: " << nameDep << " already exists."); return false; } assert(storm::utility::isOne(probability) || children.size() == 2); @@ -92,7 +93,7 @@ namespace storm { bool addVotElement(std::string const& name, unsigned threshold, std::vector const& children) { assert(children.size() > 0); if(mElements.count(name) != 0) { - std::cerr << "Element with name: " << name << " already exists." << std::endl; + STORM_LOG_ERROR("Element with name: " << name << " already exists."); return false; } // It is an and-gate @@ -105,7 +106,7 @@ namespace storm { } if(threshold > children.size()) { - std::cerr << "Voting gates with threshold higher than the number of children is not supported." << std::endl; + STORM_LOG_ERROR("Voting gates with threshold higher than the number of children is not supported."); return false; } DFTElementPointer element = std::make_shared>(mNextId++, name, threshold); From c5214c6abafe657dc159b8ea0da28b296dac1790 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 16 Feb 2016 12:06:56 +0100 Subject: [PATCH 098/246] Removed unused include Former-commit-id: 90b0a9722e514a557a8d26a43b33f938a0e73794 --- src/storage/BitVector.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index 00a94e86c..dff4b2f5f 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -9,7 +9,6 @@ #include "src/utility/OsDetection.h" #include "src/utility/Hash.h" #include "src/utility/macros.h" -#include "resources/3rdparty/glpk-4.53/src/zlib/zconf.h" namespace storm { namespace storage { From c78d9ff80222c373589b4b7af5ce4d77b1a61465 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 17 Feb 2016 11:21:46 +0100 Subject: [PATCH 099/246] Fixed problems with pdeps Former-commit-id: c46c88b1779b51b6d052fe9cb462d37dc8973e31 --- benchmark_dft.py | 3 +- examples/dft/pdep3.dft | 5 +++ src/builder/ExplicitDFTModelBuilder.cpp | 42 ++++++++++++++++++--- src/storage/dft/DFT.cpp | 32 ++++++++++------ src/storage/dft/DFTBuilder.cpp | 1 + src/storage/dft/DFTElementState.h | 50 ++++++++++++++++++++++++- src/storage/dft/DFTElements.cpp | 2 +- src/storage/dft/DFTElements.h | 32 +++++++++++++++- src/storage/dft/DFTState.cpp | 42 ++++++++++++++++++++- src/storage/dft/DFTState.h | 23 +++++++++++- 10 files changed, 207 insertions(+), 25 deletions(-) create mode 100644 examples/dft/pdep3.dft diff --git a/benchmark_dft.py b/benchmark_dft.py index dfcecd15f..77880d951 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -31,8 +31,9 @@ benchmarks = [ ("or", False, [1, 1]), ("pand", False, ["inf", 0.666667]), ("pand_param", True, ["-1", "(x)/(y+x)"]), - ("pdep", False, [0, 1]), #Compute + ("pdep", False, [2.66667, 1]), ("pdep2", False, [0, 1]), #Compute + ("pdep3", False, [2.79167, 1]), ("spare", False, [3.53846, 1]), ("spare2", False, [1.86957, 1]), ("spare3", False, [1.27273, 1]), diff --git a/examples/dft/pdep3.dft b/examples/dft/pdep3.dft new file mode 100644 index 000000000..a9a73f472 --- /dev/null +++ b/examples/dft/pdep3.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C" "F"; +"F" pdep=0.3 "B" "C"; +"B" lambda=0.4 dorm=0; +"C" lambda=0.8 dorm=0; diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index aa4d46f15..160535443 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -77,17 +77,20 @@ namespace storm { // TODO Matthias: avoid transforming back and forth storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { + assert(row < modelComponents.markovianStates.size()); if (modelComponents.markovianStates.get(row)) { for (auto& entry : rateMatrix.getRow(row)) { entry.setValue(entry.getValue() * modelComponents.exitRates[row]); } } } + if (deterministic) { model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling)); } else { model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); } + model->printModelInformationToStream(std::cout); return model; } @@ -143,9 +146,6 @@ namespace storm { assert(nextBEPair.second == hasDependencies); STORM_LOG_TRACE("with the failure of: " << nextBE->name() << " [" << nextBE->id() << "]"); - // Update failable dependencies - newState->updateFailableDependencies(nextBE->id()); - // Propagate failures storm::storage::DFTStateSpaceGenerationQueues queues; @@ -169,6 +169,9 @@ namespace storm { DFTElementPointer next = queues.nextDontCarePropagation(); next->checkDontCareAnymore(*newState, queues); } + + // Update failable dependencies + newState->updateFailableDependencies(nextBE->id()); if (mStates.contains(newState->status())) { // State already exists @@ -180,7 +183,7 @@ namespace storm { mStates.findOrAdd(newState->status(), newState); STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); - // Add state to search + // Add state to search queue stateQueue.push(newState); } @@ -188,8 +191,37 @@ namespace storm { if (hasDependencies) { // Failure is due to dependency -> add non-deterministic choice std::shared_ptr const> dependency = mDft.getDependency(state->getDependencyId(smallest-1)); - transitionMatrixBuilder.addNextValue(state->getId() + rowOffset++, newState->getId(), dependency->probability()); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, newState->getId(), dependency->probability()); STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with probability " << dependency->probability()); + + if (!storm::utility::isOne(dependency->probability())) { + // Add transition to state where dependency was unsuccessful + DFTStatePointer unsuccessfulState = std::make_shared>(*state); + unsuccessfulState->letDependencyBeUnsuccessful(smallest-1); + + if (mStates.contains(unsuccessfulState->status())) { + // Unsuccessful state already exists + unsuccessfulState = mStates.findOrAdd(unsuccessfulState->status(), unsuccessfulState); + STORM_LOG_TRACE("State " << mDft.getStateString(unsuccessfulState) << " already exists"); + } else { + // New unsuccessful state + unsuccessfulState->setId(newIndex++); + mStates.findOrAdd(unsuccessfulState->status(), unsuccessfulState); + STORM_LOG_TRACE("New state " << mDft.getStateString(unsuccessfulState)); + + // Add unsuccessful state to search queue + stateQueue.push(unsuccessfulState); + } + + ValueType remainingProbability = storm::utility::one() - dependency->probability(); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, unsuccessfulState->getId(), remainingProbability); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << unsuccessfulState->getId() << " with probability " << remainingProbability); + } else { + // Self-loop with probability one cannot be eliminated later one. + assert(state->getId() != newState->getId()); + } + ++rowOffset; + } else { // Set failure rate according to usage bool isUsed = true; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index b3f0dce7a..83e287b3b 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -118,13 +118,17 @@ namespace storm { for (auto const& elem : mElements) { stream << "[" << elem->id() << "]"; stream << elem->toString(); - stream << "\t** " << state->getElementState(elem->id()); - if(elem->isSpareGate()) { - if(state->isActiveSpare(elem->id())) { - stream << " actively"; + if (elem->isDependency()) { + stream << "\t** " << storm::storage::toChar(state->getDependencyState(elem->id())); + } else { + stream << "\t** " << storm::storage::toChar(state->getElementState(elem->id())); + if(elem->isSpareGate()) { + if(state->isActiveSpare(elem->id())) { + stream << " actively"; + } + stream << " using " << state->uses(elem->id()); } - stream << " using " << state->uses(elem->id()); - } + } stream << std::endl; } return stream.str(); @@ -135,13 +139,17 @@ namespace storm { std::stringstream stream; stream << "(" << state->getId() << ") "; for (auto const& elem : mElements) { - stream << state->getElementStateInt(elem->id()); - if(elem->isSpareGate()) { - stream << "["; - if(state->isActiveSpare(elem->id())) { - stream << "actively "; + if (elem->isDependency()) { + stream << storm::storage::toChar(state->getDependencyState(elem->id())) << "[dep]"; + } else { + stream << storm::storage::toChar(state->getElementState(elem->id())); + if(elem->isSpareGate()) { + stream << "["; + if(state->isActiveSpare(elem->id())) { + stream << "actively "; + } + stream << "using " << state->uses(elem->id()) << "]"; } - stream << "using " << state->uses(elem->id()) << "]"; } } return stream.str(); diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 00e416d54..13ed7d7b0 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -40,6 +40,7 @@ namespace storm { DFTGatePointer triggerEvent = std::static_pointer_cast>(mElements[dependency->nameTrigger()]); std::shared_ptr> dependentEvent = std::static_pointer_cast>(mElements[dependency->nameDependent()]); dependency->initialize(triggerEvent, dependentEvent); + triggerEvent->addDependency(dependency); } // Sort elements topologically diff --git a/src/storage/dft/DFTElementState.h b/src/storage/dft/DFTElementState.h index 1926745bf..d191cc2d9 100644 --- a/src/storage/dft/DFTElementState.h +++ b/src/storage/dft/DFTElementState.h @@ -2,9 +2,11 @@ #ifndef DFTELEMENTSTATE_H #define DFTELEMENTSTATE_H +#include + namespace storm { namespace storage { - enum class DFTElementState {Operational = 0, Failed = 2, Failsafe = 1, DontCare = 3}; + enum class DFTElementState {Operational = 0, Failed = 2, Failsafe = 1, DontCare = 3}; inline std::ostream& operator<<(std::ostream& os, DFTElementState st) { switch(st) { @@ -17,7 +19,53 @@ namespace storm { case DFTElementState::DontCare: return os << "Don't Care"; } + assert(false); + } + + inline char toChar(DFTElementState st) { + switch(st) { + case DFTElementState::Operational: + return 'O'; + case DFTElementState::Failed: + return 'F'; + case DFTElementState::Failsafe: + return 'S'; + case DFTElementState::DontCare: + return '-'; + } + assert(false); + } + + enum class DFTDependencyState {Passive = 0, Unsuccessful = 1, Successful = 2, DontCare = 3}; + + inline std::ostream& operator<<(std::ostream& os, DFTDependencyState st) { + switch(st) { + case DFTDependencyState::Passive: + return os << "Passive"; + case DFTDependencyState::Successful: + return os << "Successful"; + case DFTDependencyState::Unsuccessful: + return os << "Unsuccessful"; + case DFTDependencyState::DontCare: + return os << "Don't Care"; + } + assert(false); } + + inline char toChar(DFTDependencyState st) { + switch(st) { + case DFTDependencyState::Passive: + return 'P'; + case DFTDependencyState::Successful: + return 'S'; + case DFTDependencyState::Unsuccessful: + return 'U'; + case DFTDependencyState::DontCare: + return '-'; + } + assert(false); + } + } } diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index d5b089c84..5597f1c5e 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -7,7 +7,7 @@ namespace storm { template bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(!state.dontCare(mId)) + if(!state.dontCare(mId) && !hasDependencies()) { for(DFTGatePointer const& parent : mParents) { if(state.isOperational(parent->id())) { diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 9778d9146..e49b91901 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -23,12 +23,17 @@ namespace storm { template class DFTGate; + + template + class DFTDependency; template class DFTElement { using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; + using DFTDependencyPointer = std::shared_ptr>; + using DFTDependencyVector = std::vector; protected: @@ -36,6 +41,7 @@ namespace storm { std::string mName; size_t mRank = -1; DFTGateVector mParents; + DFTDependencyVector dependencies; public: DFTElement(size_t id, std::string const& name) : @@ -132,6 +138,29 @@ namespace storm { } return res; } + + bool addDependency(DFTDependencyPointer const& e) { + if(std::find(dependencies.begin(), dependencies.end(), e) != dependencies.end()) { + return false; + } + else + { + dependencies.push_back(e); + return true; + } + } + + bool hasDependencies() const { + return !dependencies.empty(); + } + + size_t nrDependencies() const { + return dependencies.size(); + } + + DFTDependencyVector const& getDependencies() const { + return dependencies; + } virtual void extendSpareModule(std::set& elementsInModule) const; @@ -433,8 +462,7 @@ namespace storm { using DFTGatePointer = std::shared_ptr>; using DFTBEPointer = std::shared_ptr>; - using DFTBEVector = std::vector; - + protected: std::string mNameTrigger; std::string mNameDependent; diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 8714f0130..53d0f8761 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -19,6 +19,11 @@ namespace storm { DFTElementState DFTState::getElementState(size_t id) const { return static_cast(getElementStateInt(id)); } + + template + DFTDependencyState DFTState::getDependencyState(size_t id) const { + return static_cast(getElementStateInt(id)); + } template int DFTState::getElementStateInt(size_t id) const { @@ -54,6 +59,20 @@ namespace storm { bool DFTState::dontCare(size_t id) const { return getElementState(id) == DFTElementState::DontCare; } + + template + bool DFTState::dependencyTriggered(size_t id) const { + return getElementStateInt(id) > 0; + } + + template + bool DFTState::dependencySuccessful(size_t id) const { + return mStatus[mDft.failureIndex(id)]; + } + template + bool DFTState::dependencyUnsuccessful(size_t id) const { + return mStatus[mDft.failureIndex(id)+1]; + } template void DFTState::setFailed(size_t id) { @@ -69,6 +88,16 @@ namespace storm { void DFTState::setDontCare(size_t id) { mStatus.setFromInt(mDft.failureIndex(id), 2, static_cast(DFTElementState::DontCare) ); } + + template + void DFTState::setDependencySuccessful(size_t id) { + mStatus.set(mDft.failureIndex(id)); + } + + template + void DFTState::setDependencyUnsuccessful(size_t id) { + mStatus.set(mDft.failureIndex(id)+1); + } template void DFTState::beNoLongerFailable(size_t id) { @@ -84,7 +113,8 @@ namespace storm { for (size_t i = 0; i < mDft.getDependencies().size(); ++i) { std::shared_ptr const> dependency = mDft.getDependency(mDft.getDependencies()[i]); if (dependency->triggerEvent()->id() == id) { - if (!hasFailed(dependency->dependentEvent()->id())) { + if (getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) { + assert(!isFailsafe(dependency->dependentEvent()->id())); mFailableDependencies.push_back(dependency->id()); STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); } @@ -99,10 +129,12 @@ namespace storm { STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString()); if (nrFailableDependencies() > 0) { // Consider failure due to dependency + assert(index < nrFailableDependencies()); std::shared_ptr const> dependency = mDft.getDependency(getDependencyId(index)); std::pair const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true); mFailableDependencies.erase(mFailableDependencies.begin() + index); setFailed(res.first->id()); + setDependencySuccessful(dependency->id()); return res; } else { // Consider "normal" failure @@ -113,6 +145,14 @@ namespace storm { return res; } } + + template + void DFTState::letDependencyBeUnsuccessful(size_t index) { + assert(nrFailableDependencies() > 0 && index < nrFailableDependencies()); + std::shared_ptr const> dependency = mDft.getDependency(getDependencyId(index)); + mFailableDependencies.erase(mFailableDependencies.begin() + index); + setDependencyUnsuccessful(dependency->id()); + } template void DFTState::activate(size_t repr) { diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 520587a42..450953bd7 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -22,6 +22,7 @@ namespace storm { class DFTState { friend struct std::hash; private: + // Status is bitvector where each element has two bits with the meaning according to DFTElementState storm::storage::BitVector mStatus; size_t mId; std::vector mInactiveSpares; @@ -35,6 +36,8 @@ namespace storm { DFTState(DFT const& dft, size_t id); DFTElementState getElementState(size_t id) const; + + DFTDependencyState getDependencyState(size_t id) const; int getElementStateInt(size_t id) const; @@ -50,12 +53,22 @@ namespace storm { bool dontCare(size_t id) const; + bool dependencyTriggered(size_t id) const; + + bool dependencySuccessful(size_t id) const; + + bool dependencyUnsuccessful(size_t id) const; + void setFailed(size_t id); void setFailsafe(size_t id); void setDontCare(size_t id); + void setDependencySuccessful(size_t id); + + void setDependencyUnsuccessful(size_t id); + void beNoLongerFailable(size_t id); void activate(size_t repr); @@ -135,10 +148,16 @@ namespace storm { /** * Sets the next BE as failed - * @param smallestIndex Index in currentlyFailableBE of BE to fail + * @param index Index in currentlyFailableBE of BE to fail * @return Pair of BE which fails and flag indicating if the failure was due to functional dependencies */ - std::pair const>, bool> letNextBEFail(size_t smallestIndex = 0); + std::pair const>, bool> letNextBEFail(size_t index = 0); + + /** + * Sets the dependency as unsuccesful meaning no BE will fail. + * @param index Index of dependency to fail. + */ + void letDependencyBeUnsuccessful(size_t index = 0); std::string getCurrentlyFailableString() const { std::stringstream stream; From 7788d45ab513c2b26f8e9bee3bcf6c00b3f0fe91 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 17 Feb 2016 11:22:15 +0100 Subject: [PATCH 100/246] No distinction between successful dependency and no dependency at all Former-commit-id: b51149328313e653ac2896ebbb3e294785f2807f --- src/storage/dft/DFTState.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 53d0f8761..9916bbe0e 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -91,7 +91,9 @@ namespace storm { template void DFTState::setDependencySuccessful(size_t id) { - mStatus.set(mDft.failureIndex(id)); + // No distinction between successful dependency and no dependency at all + // -> we do not set bit + //mStatus.set(mDft.failureIndex(id)); } template From 5655766d36dd9e3d285bda206590e24f8c2364a3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 17 Feb 2016 11:44:08 +0100 Subject: [PATCH 101/246] Small changes Former-commit-id: cc2a75289e633e71a3c590309939d70bdfe416c0 --- benchmark_dft.py | 12 ++++++------ src/storage/dft/DFTBuilder.cpp | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/benchmark_dft.py b/benchmark_dft.py index 77880d951..6f25e08ed 100644 --- a/benchmark_dft.py +++ b/benchmark_dft.py @@ -13,13 +13,13 @@ EXAMPLE_DIR=os.path.join(DIR, "examples/dft/") benchmarks = [ ("and", False, [3, 1]), ("and_param", True, ["(4*x^2+2*x+1)/((x) * (2*x+1))", "1"]), - ("cardiac", False, [11378, 1]), + ("cardiac", False, [8597.360004, 1]), ("cas", False, [0.859736, 1]), ("cm2", False, [0.256272, 1]), - #("cm4", False, [0, 1]), + #("cm4", False, [0.338225, 1]), # big ("cps", False, ["inf", 0.333333]), - ("deathegg", False, [46.667, 1]), - ("fdep", False, [0.666667, 1]), + #("deathegg", False, [24.642857, 1]), # contains fdep to gate + #("fdep", False, [0.666667, 1]), # contains fdep to two elements ("fdep2", False, [2, 1]), ("fdep3", False, [2.5, 1]), #("ftpp_complex", False, [0, 1]), # Compute @@ -32,13 +32,13 @@ benchmarks = [ ("pand", False, ["inf", 0.666667]), ("pand_param", True, ["-1", "(x)/(y+x)"]), ("pdep", False, [2.66667, 1]), - ("pdep2", False, [0, 1]), #Compute + #("pdep2", False, [0, 1]), #Compute # contains pdep to two elements ("pdep3", False, [2.79167, 1]), ("spare", False, [3.53846, 1]), ("spare2", False, [1.86957, 1]), ("spare3", False, [1.27273, 1]), ("spare4", False, [4.8459, 1]), - ("spare5", False, [2.66667, 1]), # We discard the result 2.16667 from DFTCalc + ("spare5", False, [2.66667, 1]), ("spare6", False, [1.4, 1]), ("spare7", False, [3.67333, 1]), ("symmetry", False, [4.16667, 1]), diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 13ed7d7b0..f35a09f0f 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -38,6 +38,7 @@ namespace storm { // Initialize dependencies for (auto& dependency : mDependencies) { DFTGatePointer triggerEvent = std::static_pointer_cast>(mElements[dependency->nameTrigger()]); + assert(mElements[dependency->nameDependent()]->isBasicElement()); std::shared_ptr> dependentEvent = std::static_pointer_cast>(mElements[dependency->nameDependent()]); dependency->initialize(triggerEvent, dependentEvent); triggerEvent->addDependency(dependency); From b51d997d5b545acb0d3a6fff9b1ffc83250907c2 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 17 Feb 2016 14:31:35 +0100 Subject: [PATCH 102/246] Detect error with more than one spare in a module Former-commit-id: a0812aa201fce62906f0d1ac054678476f101377 --- src/storage/dft/DFT.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 83e287b3b..a23a70f71 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -1,6 +1,7 @@ #include #include "DFT.h" +#include "src/exceptions/NotSupportedException.h" namespace storm { namespace storage { @@ -28,7 +29,12 @@ namespace storm { std::set module = {spareReprs->id()}; spareReprs->extendSpareModule(module); std::vector sparesAndBes; + bool secondSpare = false; for(auto const& modelem : module) { + if (mElements[modelem]->isSpareGate()) { + STORM_LOG_THROW(!secondSpare, storm::exceptions::NotSupportedException, "Module for '" << spareReprs->name() << "' contains more than one spare."); + secondSpare = true; + } if(mElements[modelem]->isSpareGate() || mElements[modelem]->isBasicElement()) { sparesAndBes.push_back(modelem); mRepresentants.insert(std::make_pair(modelem, spareReprs->id())); From 0a9f68ed7478428876a0d5d3c51ddb952945535f Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 17 Feb 2016 19:49:01 +0100 Subject: [PATCH 103/246] update dft towards cnt.abst Former-commit-id: bce7a7a566ac7f6a9f62d66e8e16429d6a255fac --- src/storage/dft/DFT.cpp | 40 ++++++ src/storage/dft/DFT.h | 10 ++ src/storage/dft/DFTIsomorphism.h | 205 +++++++++++++++++++++++++++---- src/utility/iota_n.h | 13 ++ 4 files changed, 242 insertions(+), 26 deletions(-) create mode 100644 src/utility/iota_n.h diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index a23a70f71..0dedd9fb3 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -3,6 +3,9 @@ #include "DFT.h" #include "src/exceptions/NotSupportedException.h" +#include "DFTIsomorphism.h" +#include "utility/iota_n.h" + namespace storm { namespace storage { @@ -168,6 +171,43 @@ namespace storm { return ISD; } + template + DFTColouring DFT::colourDFT() const { + return DFTColouring(*this); + } + + template + std::vector> DFT::findSymmetries(DFTColouring const& colouring) const { + std::vector vec; + vec.reserve(nrElements()); + storm::utility::iota_n(std::back_inserter(vec), 14, 0); + BijectionCandidates completeCategories = colouring.colourSubdft(vec); + std::vector> res; + for(auto const& colourClass : completeCategories.gateCandidates) { + if(colourClass.second.size() > 1) { + for(auto it1 = colourClass.second.cbegin(); it1 != colourClass.second.cend(); ++it1) { + std::vector sortedParent1Ids = getGate(*it1)->parentIds(); + std::sort(sortedParent1Ids.begin(), sortedParent1Ids.end()); + auto it2 = it1; + for(++it2; it2 != colourClass.second.cend(); ++it2) { + std::vector sortedParent2Ids = getGate(*it2)->parentIds(); + std::sort(sortedParent2Ids.begin(), sortedParent2Ids.end()); + if(sortedParent1Ids == sortedParent2Ids) { + std::cout << "Considering ids " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + std::vector isubdft1 = getGate(*it1)->independentSubDft(); + std::vector isubdft2 = getGate(*it2)->independentSubDft(); + if(!isubdft1.empty() && !isubdft2.empty() && isubdft1.size() == isubdft2.size()) { + std::cout << "Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + } + } + } + } + } + } + return res; + } + + // Explicitly instantiate the class. template class DFT; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index ecea467e4..f2036e7d7 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -29,6 +29,11 @@ namespace storm { } }; + + // Forward declarations + template class DFTColouring; + + /** * Represents a Dynamic Fault Tree */ @@ -222,6 +227,11 @@ namespace storm { std::string getStateString(DFTStatePointer const& state) const; std::vector getIndependentSubDftRoots(size_t index) const; + + DFTColouring colourDFT() const; + + std::vector> findSymmetries(DFTColouring const& colouring) const; + private: bool elementIndicesCorrect() const { for(size_t i = 0; i < mElements.size(); ++i) { diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index e9a58d559..6258b05bc 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -1,9 +1,12 @@ #pragma once +#include #include #include +#include #include "DFTElementType.h" #include "DFTElements.h" +#include "DFT.h" namespace storm { namespace storage { @@ -34,14 +37,102 @@ namespace storage { }; + + template + struct BEColourClass { + BEColourClass() = default; + BEColourClass(ValueType a, ValueType p, size_t h) : aRate(a), pRate(p), hash(h) {} + + ValueType aRate; + ValueType pRate; + size_t hash; + }; + + template + bool operator==(BEColourClass const& lhs, BEColourClass const& rhs) { + return lhs.hash == rhs.hash && lhs.aRate == rhs.aRate && lhs.pRate == rhs.pRate; + } + + + + /** * */ template - class BijectionCandidates { - std::unordered_map> groupCandidates; - std::unordered_map, std::vector> beCandidates; + struct BijectionCandidates { + std::unordered_map> gateCandidates; + std::unordered_map, std::vector> beCandidates; + std::unordered_map, std::vector> pdepCandidates; + }; + + template + class DFTColouring { + DFT const& dft; + std::unordered_map gateColour; + std::unordered_map> beColour; + std::unordered_map> depColour; + GateGroupToHash gateColourizer; + + public: + DFTColouring(DFT const& ft) : dft(ft) { + for(size_t id = 0; id < dft.nrElements(); ++id ) { + if(dft.isBasicElement(id)) { + colourize(dft.getBasicElement(id)); + } else if(dft.isGate(id)) { + colourize(dft.getGate(id)); + } else { + assert(dft.isDependency(id)); + colourize(dft.getDependency(id)); + } + } + } + + BijectionCandidates colourSubdft(std::vector const& subDftIndices) const { + BijectionCandidates res; + for (size_t index : subDftIndices) { + if(dft.isBasicElement(index)) { + auto it = res.beCandidates.find(beColour.at(index)); + if(it != res.beCandidates.end()) { + it->second.push_back(index); + } else { + res.beCandidates[beColour.at(index)] = std::vector({index}); + } + } else if(dft.isGate(index)) { + auto it = res.gateCandidates.find(gateColour.at(index)); + if(it != res.gateCandidates.end()) { + it->second.push_back(index); + } else { + res.gateCandidates[gateColour.at(index)] = std::vector({index}); + } + } else { + assert(dft.isDependency(index)); + auto it = res.pdepCandidates.find(depColour.at(index)); + if(it != res.pdepCandidates.end()) { + it->second.push_back(index); + } else { + res.pdepCandidates[depColour.at(index)] = std::vector({index}); + } + } + + } + return res; + } + + + protected: + void colourize(std::shared_ptr> const& be) { + beColour[be->id()] = BEColourClass(be->activeFailureRate(), be->passiveFailureRate(), be->nrParents()); + } + + void colourize(std::shared_ptr> const& gate) { + gateColour[gate->id()] = gateColourizer(gate->type(), gate->nrChildren(), gate->nrParents(), 0, gate->rank()); + } + + void colourize(std::shared_ptr> const& dep) { + depColour[dep->id()] = std::pair(dep->probability(), dep->dependentEvent()->activeFailureRate()); + } }; @@ -107,36 +198,61 @@ namespace storage { } protected: - + /** + * Construct the initial bijection. + */ void constructInitialBijection() { assert(candidatesCompatible); // We first construct the currentPermutations, which helps to determine the current state of the check. - for(auto const& colour : bright.beCandidates) { - if(colour.second.size()>1) { - currentPermutations.beCandidates.insert(colour); + initializePermutationsAndTreatTrivialGroups(bleft.beCandidates, bright.beCandidates, currentPermutations.beCandidates); + initializePermutationsAndTreatTrivialGroups(bleft.gateCandidates, bright.gateCandidates, currentPermutations.gateCandidates); + initializePermutationsAndTreatTrivialGroups(bleft.pdepCandidates, bright.pdepCandidates, currentPermutations.pdepCandidates); + } + + /** + * Construct the next bijection + * @return true if a next bijection exists. + */ + bool findNextBijection() { + bool foundNext = false; + if(!currentPermutations.beCandidates.empty()) { + auto it = currentPermutations.beCandidates.begin(); + while(!foundNext && it == currentPermutations.beCandidates.end()) { + foundNext = std::next_permutation(it->second.begin(), it->second.end()); + ++it; } } - - for(auto const& colour : bright.groupCandidates) { - if(colour.second.size()>1) { - currentPermutations.groupCandidates.insert(colour); + if(!foundNext && !currentPermutations.gateCandidates.empty()) { + auto it = currentPermutations.gateCandidates.begin(); + while(!foundNext && it == currentPermutations.beCandidates.end()) { + foundNext = std::next_permutation(it->second.begin(), it->second.end()); + ++it; } } - // Constructing the initial homomorphism based on the right hand side instead of the current permutations allows us - // to treat trivial and non-trivial classes in one go. - for(auto const& colour : bleft.beCandidates) { - zipVectorsIntoMap(colour.second, bright.beCandidates.find(colour.first)->second, bijection); + if(!foundNext && !currentPermutations.pdepCandidates.empty()) { + auto it = currentPermutations.pdepCandidates.begin(); + while(!foundNext && it == currentPermutations.pdepCandidates.end()) { + foundNext = std::next_permutation(it->second.begin(), it->second.end()); + ++it; + } } - for(auto const& colour : bleft.groupCandidates) { - zipVectorsIntoMap(colour.second, bright.groupCandidates.find(colour.first)->second, bijection); - } + if(foundNext) { + for(auto const& colour : bleft.beCandidates) { + zipVectorsIntoMap(colour.second, currentPermutations.beCandidates.find(colour.first)->second, bijection); + } - } + for(auto const& colour : bleft.gateCandidates) { + zipVectorsIntoMap(colour.second, currentPermutations.gateCandidates.find(colour.first)->second, bijection); + } - bool findNextBijection() { - return false; + for(auto const& colour : bleft.pdepCandidates) { + zipVectorsIntoMap(colour.second, currentPermutations.pdepCandidates.find(colour.first)->second, bijection); + } + } + + return foundNext; } @@ -152,21 +268,21 @@ namespace storage { * Returns true if the colours are compatible. */ bool checkCompatibility() { - if(bleft.groupCandidates.size() != bright.groupCandidates.size()) { + if(bleft.gateCandidates.size() != bright.gateCandidates.size()) { candidatesCompatible = false; } else if(bleft.beCandidates.size() != bright.beCandidates.size()) { candidatesCompatible = false; } else { - for (auto const &gc : bleft.groupCandidates) { - if (bright.groupCandidates.count(gc.first) == 0) { + for (auto const &gc : bleft.gateCandidates) { + if (bright.gateCandidates.count(gc.first) == 0) { candidatesCompatible = false; break; } } if(candidatesCompatible) { - for(auto const& bc : bleft.groupCandidates) { + for(auto const& bc : bleft.gateCandidates) { if(bright.beCandidates.count(bc.first) == 0) { candidatesCompatible = false; break; @@ -176,6 +292,26 @@ namespace storage { } } + /** + * + */ + template + void initializePermutationsAndTreatTrivialGroups(std::unordered_map> const& left, + std::unordered_map> const& right, + std::unordered_map>& permutations) { + for(auto const& colour : right) { + if(colour.second.size()>1) { + auto it = permutations.insert(colour); + std::sort(it->second.begin(), it->second.end()); + zipVectorsIntoMap(colour.second, permutations.find(colour.first)->second, bijection); + } else { + assert(colour.second.size() == 1); + assert(bijection.count(left[colour.first].front()) == 0); + bijection[left[colour.first].front()] = colour.second.front(); + } + } + } + /** * Local helper function for the creation of bijections, should be hidden from api. */ @@ -184,7 +320,6 @@ namespace storage { assert(a.size() == b.size()); auto it = b.cbegin(); for(size_t lIndex : a) { - assert(map.count(lIndex) == 0); map[lIndex] = *it; ++it; } @@ -199,3 +334,21 @@ namespace storage { } // namespace storm::dft } // namespace storm + +namespace std { + template + struct hash> { + size_t operator()(storm::storage::BEColourClass const& bcc) const { + std::hash hasher; + return (hasher(bcc.aRate) ^ hasher(bcc.pRate) << 8) | bcc.hash; + } + }; + + template + struct hash> { + size_t operator()(std::pair const& p) const { + std::hash hasher; + return hasher(p.first) ^ hasher(p.second); + } + }; +} \ No newline at end of file diff --git a/src/utility/iota_n.h b/src/utility/iota_n.h new file mode 100644 index 000000000..a7e4ba829 --- /dev/null +++ b/src/utility/iota_n.h @@ -0,0 +1,13 @@ +#pragma once + +namespace storm { + namespace utility { + template + void iota_n(OutputIterator first, Size n, Assignable value) + { + std::generate_n(first, n, [&value]() { + return value++; + }); + } + } +} From 16a21527944659dbf797b119ebee019b3fc450fb Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 17 Feb 2016 20:44:07 +0100 Subject: [PATCH 104/246] hash_value for cln::cl_ra Former-commit-id: 934795bd78c7f530ff4e47eda1b7df0a5821d273 --- src/adapters/CarlAdapter.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/adapters/CarlAdapter.h b/src/adapters/CarlAdapter.h index 4fd2a98a0..61bd3998b 100644 --- a/src/adapters/CarlAdapter.h +++ b/src/adapters/CarlAdapter.h @@ -41,6 +41,14 @@ namespace carl { std::hash> h; return h(i); } + +} + +namespace cln { + inline size_t hash_value(cl_RA const& n) { + std::hash h; + return h(n); + } } namespace storm { From 266d41716812392911418fec17f6d497dea30361 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 17 Feb 2016 20:44:35 +0100 Subject: [PATCH 105/246] constants.h/cpp extended to treat carl rational numbers Former-commit-id: 12f0dfbc2ce5e76a4afd404dfb697755e6c20210 --- src/utility/constants.cpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/utility/constants.cpp b/src/utility/constants.cpp index 900482a72..be0fcb079 100644 --- a/src/utility/constants.cpp +++ b/src/utility/constants.cpp @@ -76,6 +76,17 @@ namespace storm { // FIXME: this should be treated more properly. return storm::RationalFunction(-1.0); } + + template<> + bool isOne(storm::CarlRationalNumber const& a) { + return carl::isOne(a); + } + + template<> + bool isZero(storm::CarlRationalNumber const& a) { + return carl::isZero(a); + } + #endif template @@ -214,13 +225,21 @@ namespace storm { template storm::RationalFunction infinity(); template RationalFunction pow(RationalFunction const& value, uint_fast64_t exponent); - - template Polynomial one(); - template Polynomial zero(); template RationalFunction simplify(RationalFunction value); template RationalFunction& simplify(RationalFunction& value); template RationalFunction&& simplify(RationalFunction&& value); + + template Polynomial one(); + template Polynomial zero(); + + template bool isOne(CarlRationalNumber const& value); + template bool isZero(CarlRationalNumber const& value); + template bool isConstant(CarlRationalNumber const& value); + + template CarlRationalNumber one(); + template CarlRationalNumber zero(); + template bool isOne(Interval const& value); template bool isZero(Interval const& value); template bool isConstant(Interval const& value); From e24343516c4c49014d272a0841f619a0443533cb Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 17 Feb 2016 20:45:19 +0100 Subject: [PATCH 106/246] constants comparator extended to carlrationalnumber (cln/cl_ra) Former-commit-id: a14c5c4092e2ee17e3f2900cffee79a3c57f2310 --- src/utility/ConstantsComparator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utility/ConstantsComparator.cpp b/src/utility/ConstantsComparator.cpp index 4ad0a2612..e22efbc5e 100644 --- a/src/utility/ConstantsComparator.cpp +++ b/src/utility/ConstantsComparator.cpp @@ -114,6 +114,7 @@ namespace storm { template class ConstantsComparator; template class ConstantsComparator; template class ConstantsComparator; + template class ConstantsComparator; #endif } } \ No newline at end of file From aa72d8a158883d2362173f99e036308a151ec3fb Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 17 Feb 2016 20:46:19 +0100 Subject: [PATCH 107/246] added missing instantiation of sparse matrix with carl ratnumber Former-commit-id: c080e9b4a513d376b4bc1a5559b5ef93eee78179 --- src/storage/SparseMatrix.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/storage/SparseMatrix.cpp b/src/storage/SparseMatrix.cpp index 65f74d874..d41e2ef2c 100644 --- a/src/storage/SparseMatrix.cpp +++ b/src/storage/SparseMatrix.cpp @@ -1257,6 +1257,15 @@ namespace storm { template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; #ifdef STORM_HAVE_CARL + // Rat Function + template class MatrixEntry::index_type, CarlRationalNumber>; + template std::ostream& operator<<(std::ostream& out, MatrixEntry const& entry); + template class SparseMatrixBuilder; + template class SparseMatrix; + template std::ostream& operator<<(std::ostream& out, SparseMatrix const& matrix); + template std::vector SparseMatrix::getPointwiseProductRowSumVector(storm::storage::SparseMatrix const& otherMatrix) const; + template bool SparseMatrix::isSubmatrixOf(SparseMatrix const& matrix) const; + // Rat Function template class MatrixEntry::index_type, RationalFunction>; template std::ostream& operator<<(std::ostream& out, MatrixEntry const& entry); From 3209c52a7cc7ca21d1b066b24920b276f5d6802f Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 17 Feb 2016 20:48:00 +0100 Subject: [PATCH 108/246] elim linear equation solver used the wrong rational number Former-commit-id: ca468397cec8d3039a23eee100cf6106d3467cc9 --- src/solver/EliminationLinearEquationSolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/EliminationLinearEquationSolver.cpp b/src/solver/EliminationLinearEquationSolver.cpp index 67a281b70..98c791c0a 100644 --- a/src/solver/EliminationLinearEquationSolver.cpp +++ b/src/solver/EliminationLinearEquationSolver.cpp @@ -54,7 +54,7 @@ namespace storm { template class EliminationLinearEquationSolver; // TODO: make this work with the proper implementation of solveEquationSystem. - template class EliminationLinearEquationSolver; + template class EliminationLinearEquationSolver; template class EliminationLinearEquationSolver; } From 391556cac166c9e461fcc1edd02bd0037459737e Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 00:16:21 +0100 Subject: [PATCH 109/246] work towards sym checks for dfts Former-commit-id: 8c1b0e86fbfa637709ddf96cd30664d1e83e4228 --- src/storage/dft/DFT.cpp | 4 +++ src/storage/dft/DFTIsomorphism.h | 61 ++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 0dedd9fb3..5735af2a7 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -198,6 +198,10 @@ namespace storm { std::vector isubdft2 = getGate(*it2)->independentSubDft(); if(!isubdft1.empty() && !isubdft2.empty() && isubdft1.size() == isubdft2.size()) { std::cout << "Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + auto LHS = colouring.colourSubdft(isubdft1); + auto RHS = colouring.colourSubdft(isubdft2); + auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); + IsoCheck.findIsomorphism(); } } } diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 6258b05bc..6c4a44ad6 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -55,7 +55,6 @@ namespace storage { - /** * */ @@ -154,9 +153,10 @@ namespace storage { /// Current permutations of right hand side groups which lead to the homomorphism. /// Contains only colours with more than one member. BijectionCandidates currentPermutations; + DFT const& dft; public: - DFTIsomorphismCheck(BijectionCandidates const& left, BijectionCandidates const& right) : bleft(left), bright(right) + DFTIsomorphismCheck(BijectionCandidates const& left, BijectionCandidates const& right, DFT const& dft) : bleft(left), bright(right), dft(dft) { checkCompatibility(); } @@ -217,14 +217,14 @@ namespace storage { bool foundNext = false; if(!currentPermutations.beCandidates.empty()) { auto it = currentPermutations.beCandidates.begin(); - while(!foundNext && it == currentPermutations.beCandidates.end()) { + while(!foundNext && it != currentPermutations.beCandidates.end()) { foundNext = std::next_permutation(it->second.begin(), it->second.end()); ++it; } } if(!foundNext && !currentPermutations.gateCandidates.empty()) { auto it = currentPermutations.gateCandidates.begin(); - while(!foundNext && it == currentPermutations.beCandidates.end()) { + while(!foundNext && it != currentPermutations.gateCandidates.end()) { foundNext = std::next_permutation(it->second.begin(), it->second.end()); ++it; } @@ -232,7 +232,7 @@ namespace storage { if(!foundNext && !currentPermutations.pdepCandidates.empty()) { auto it = currentPermutations.pdepCandidates.begin(); - while(!foundNext && it == currentPermutations.pdepCandidates.end()) { + while(!foundNext && it != currentPermutations.pdepCandidates.end()) { foundNext = std::next_permutation(it->second.begin(), it->second.end()); ++it; } @@ -260,34 +260,48 @@ namespace storage { * */ bool check() { + // We can skip BEs, as they are identified by they're homomorphic if they are in the same class + for(auto const& index : bijection) { + // As they are in the same group, the types are fine already. We just have to check the children. + } + return false; } private: /** * Returns true if the colours are compatible. */ - bool checkCompatibility() { + void checkCompatibility() { if(bleft.gateCandidates.size() != bright.gateCandidates.size()) { candidatesCompatible = false; + return; } - else if(bleft.beCandidates.size() != bright.beCandidates.size()) { + if(bleft.beCandidates.size() != bright.beCandidates.size()) { candidatesCompatible = false; + return; } - else { - for (auto const &gc : bleft.gateCandidates) { - if (bright.gateCandidates.count(gc.first) == 0) { - candidatesCompatible = false; - break; - } + if(bleft.beCandidates.size() != bright.beCandidates.size()) { + candidatesCompatible = false; + return; + } + + for (auto const &gc : bleft.gateCandidates) { + if (bright.gateCandidates.count(gc.first) == 0) { + candidatesCompatible = false; } - if(candidatesCompatible) { - for(auto const& bc : bleft.gateCandidates) { - if(bright.beCandidates.count(bc.first) == 0) { - candidatesCompatible = false; - break; - } - } + } + for(auto const& bc : bleft.beCandidates) { + if(bright.beCandidates.count(bc.first) == 0) { + candidatesCompatible = false; + return; + } + } + + for(auto const& dc : bleft.pdepCandidates) { + if(bright.pdepCandidates.count(dc.first) == 0) { + candidatesCompatible = false; + return; } } } @@ -302,12 +316,13 @@ namespace storage { for(auto const& colour : right) { if(colour.second.size()>1) { auto it = permutations.insert(colour); - std::sort(it->second.begin(), it->second.end()); + assert(it.second); + std::sort(it.first->second.begin(), it.first->second.end()); zipVectorsIntoMap(colour.second, permutations.find(colour.first)->second, bijection); } else { assert(colour.second.size() == 1); - assert(bijection.count(left[colour.first].front()) == 0); - bijection[left[colour.first].front()] = colour.second.front(); + assert(bijection.count(left.at(colour.first).front()) == 0); + bijection[left.at(colour.first).front()] = colour.second.front(); } } } From 8d0046a9a7a2c2477e9bb0426df801b9f2794e1e Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 15:44:31 +0100 Subject: [PATCH 110/246] Dftelements: equalType Former-commit-id: 77b9b382462ed78812fe866db851db130a3be68e --- src/storage/dft/DFTElements.h | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index e49b91901..b7fca51c0 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -122,7 +122,7 @@ namespace storm { bool hasParents() const { return !mParents.empty(); } - + size_t nrParents() const { return mParents.size(); } @@ -194,7 +194,9 @@ namespace storm { */ virtual void extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const; - + virtual bool isTypeEqualTo(DFTElement const& other) const { + return type() == other.type(); + } protected: @@ -368,7 +370,7 @@ namespace storm { } return false; } - + }; @@ -413,6 +415,13 @@ namespace storm { bool isColdBasicElement() const override{ return storm::utility::isZero(mPassiveFailureRate); } + + bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTBE const& otherBE = static_cast const&>(other); + return (mActiveFailureRate == otherBE.mActiveFailureRate) && (mPassiveFailureRate == otherBE.mPassiveFailureRate); + } + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override; }; @@ -454,6 +463,12 @@ namespace storm { return 0; } + bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTConst const& otherCNST = static_cast const&>(other); + return (mFailed == otherCNST.mFailed); + } + }; @@ -518,6 +533,13 @@ namespace storm { virtual bool isDependency() const override { return true; } + + virtual bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTDependency const& otherDEP= static_cast const&>(other); + return (mProbability == otherDEP.mProbability); + } + virtual std::vector independentUnit() const override { std::set unit = {this->mId}; @@ -819,7 +841,12 @@ namespace storm { std::string typestring() const override{ return "VOT (" + std::to_string(mThreshold) + ")"; } - + + virtual bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTVot const& otherVOT = static_cast const&>(other); + return (mThreshold == otherVOT.mThreshold); + } }; template @@ -887,7 +914,12 @@ namespace storm { } } }; - + + template + bool equalType(DFTElement const& e1, DFTElement const& e2) { + return e1.isTypeEqualTo(e2); + } + } } From cd3af54bb5192288b66fd7f40b8b1f8fadc0be20 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 15:44:54 +0100 Subject: [PATCH 111/246] Dftelementstype: is static gate Former-commit-id: a7b82e8ea97b61e48b27b88d1d58bea2d19d9416 --- src/storage/dft/DFTElementType.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/storage/dft/DFTElementType.h b/src/storage/dft/DFTElementType.h index 98d58df5c..a0d801816 100644 --- a/src/storage/dft/DFTElementType.h +++ b/src/storage/dft/DFTElementType.h @@ -6,6 +6,24 @@ namespace storm { enum class DFTElementType : int {AND = 0, COUNTING = 1, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, PDEP = 10, SEQAND = 11}; + inline bool isStaticGateType(DFTElementType const& tp) { + if(!isGateType(tp)) return false; + switch(tp) { + case DFTElementType::AND: + case DFTElementType::OR: + case DFTElementType::VOT: + return true; + case DFTElementType::POR: + case DFTElementType::SPARE: + case DFTElementType::PAND: + case DFTElementType::SEQAND: + return false; + default: + assert(false); + } + } + + inline bool isGateType(DFTElementType const& tp) { switch(tp) { case DFTElementType::AND: From c0dfaef066c965b51bc4907c08f70f85f853b0de Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 15:45:18 +0100 Subject: [PATCH 112/246] DFTElement: hasOnlyStaticParents Former-commit-id: 449222f331d3f59e65d6291dd109e4258d8f319e --- src/storage/dft/DFTElements.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index b7fca51c0..747dfb611 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -119,6 +119,16 @@ namespace storm { } } + bool hasOnlyStaticParents() const { + for(auto const& parent : parents) { + if(!isStaticGateType(parents->type()) { + return false; + } + } + return true; + } + + bool hasParents() const { return !mParents.empty(); } From d00b32b5480ac055fee52e5e8f36fa1e30a38215 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 16:04:32 +0100 Subject: [PATCH 113/246] fix of static parents and fixed warning in element types Former-commit-id: 816efd9c557cf59e78bd19c4a23d80c428adbfc4 --- src/storage/dft/DFTElementType.h | 36 ++++++++++++++++++-------------- src/storage/dft/DFTElements.h | 4 ++-- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/storage/dft/DFTElementType.h b/src/storage/dft/DFTElementType.h index a0d801816..a32745cdf 100644 --- a/src/storage/dft/DFTElementType.h +++ b/src/storage/dft/DFTElementType.h @@ -6,45 +6,49 @@ namespace storm { enum class DFTElementType : int {AND = 0, COUNTING = 1, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, PDEP = 10, SEQAND = 11}; - inline bool isStaticGateType(DFTElementType const& tp) { - if(!isGateType(tp)) return false; + + inline bool isGateType(DFTElementType const& tp) { switch(tp) { case DFTElementType::AND: + case DFTElementType::COUNTING: case DFTElementType::OR: case DFTElementType::VOT: - return true; - case DFTElementType::POR: - case DFTElementType::SPARE: case DFTElementType::PAND: + case DFTElementType::SPARE: + case DFTElementType::POR: case DFTElementType::SEQAND: + return true; + case DFTElementType::BE: + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + case DFTElementType::PDEP: return false; default: assert(false); + return false; } } + - - inline bool isGateType(DFTElementType const& tp) { + inline bool isStaticGateType(DFTElementType const& tp) { + if(!isGateType(tp)) return false; switch(tp) { case DFTElementType::AND: - case DFTElementType::COUNTING: case DFTElementType::OR: case DFTElementType::VOT: - case DFTElementType::PAND: - case DFTElementType::SPARE: + return true; case DFTElementType::POR: + case DFTElementType::SPARE: + case DFTElementType::PAND: case DFTElementType::SEQAND: - return true; - case DFTElementType::BE: - case DFTElementType::CONSTF: - case DFTElementType::CONSTS: - case DFTElementType::PDEP: return false; default: assert(false); + return false; } } - + + } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 747dfb611..6ab165a04 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -120,8 +120,8 @@ namespace storm { } bool hasOnlyStaticParents() const { - for(auto const& parent : parents) { - if(!isStaticGateType(parents->type()) { + for(auto const& parent : mParents) { + if(!isStaticGateType(parent->type())) { return false; } } From 2e4afbc69b5871b29d67174474d5fe6e6c0697d5 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 18 Feb 2016 16:12:37 +0100 Subject: [PATCH 114/246] Ingoing and outgoing dependencies Former-commit-id: 191acc897b9e482bea4c12c21c90f36c0165de77 --- src/storage/dft/DFTBuilder.cpp | 3 +- src/storage/dft/DFTElements.cpp | 2 +- src/storage/dft/DFTElements.h | 53 +++++++++++++++++++++++++-------- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index f35a09f0f..f0d1db5ac 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -41,7 +41,8 @@ namespace storm { assert(mElements[dependency->nameDependent()]->isBasicElement()); std::shared_ptr> dependentEvent = std::static_pointer_cast>(mElements[dependency->nameDependent()]); dependency->initialize(triggerEvent, dependentEvent); - triggerEvent->addDependency(dependency); + triggerEvent->addOutgoingDependency(dependency); + dependentEvent->addIngoingDependency(dependency); } // Sort elements topologically diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 5597f1c5e..c7fc1d960 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -7,7 +7,7 @@ namespace storm { template bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(!state.dontCare(mId) && !hasDependencies()) + if(!state.dontCare(mId) && !hasOutgoingDependencies()) { for(DFTGatePointer const& parent : mParents) { if(state.isOperational(parent->id())) { diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index e49b91901..d7060654f 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -35,13 +35,12 @@ namespace storm { using DFTDependencyPointer = std::shared_ptr>; using DFTDependencyVector = std::vector; - protected: size_t mId; std::string mName; size_t mRank = -1; DFTGateVector mParents; - DFTDependencyVector dependencies; + DFTDependencyVector mOutgoingDependencies; public: DFTElement(size_t id, std::string const& name) : @@ -139,29 +138,30 @@ namespace storm { return res; } - bool addDependency(DFTDependencyPointer const& e) { - if(std::find(dependencies.begin(), dependencies.end(), e) != dependencies.end()) { + bool addOutgoingDependency(DFTDependencyPointer const& e) { + assert(e->triggerEvent()->id() == this->id()); + if(std::find(mOutgoingDependencies.begin(), mOutgoingDependencies.end(), e) != mOutgoingDependencies.end()) { return false; } else { - dependencies.push_back(e); + mOutgoingDependencies.push_back(e); return true; } } - bool hasDependencies() const { - return !dependencies.empty(); + bool hasOutgoingDependencies() const { + return !mOutgoingDependencies.empty(); } - size_t nrDependencies() const { - return dependencies.size(); + size_t nrOutgoingDependencies() const { + return mOutgoingDependencies.size(); } - DFTDependencyVector const& getDependencies() const { - return dependencies; + DFTDependencyVector const& getOutgoingDependencies() const { + return mOutgoingDependencies; } - + virtual void extendSpareModule(std::set& elementsInModule) const; virtual size_t nrChildren() const = 0; @@ -375,9 +375,14 @@ namespace storm { template class DFTBE : public DFTElement { + + using DFTDependencyPointer = std::shared_ptr>; + using DFTDependencyVector = std::vector; + protected: ValueType mActiveFailureRate; ValueType mPassiveFailureRate; + DFTDependencyVector mIngoingDependencies; public: DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : @@ -399,6 +404,30 @@ namespace storm { ValueType const& passiveFailureRate() const { return mPassiveFailureRate; } + + bool addIngoingDependency(DFTDependencyPointer const& e) { + assert(e->dependentEvent()->id() == this->id()); + if(std::find(mIngoingDependencies.begin(), mIngoingDependencies.end(), e) != mIngoingDependencies.end()) { + return false; + } + else + { + mIngoingDependencies.push_back(e); + return true; + } + } + + bool hasIngoingDependencies() const { + return !mIngoingDependencies.empty(); + } + + size_t nrIngoingDependencies() const { + return mIngoingDependencies.size(); + } + + DFTDependencyVector const& getIngoingDependencies() const { + return mIngoingDependencies; + } std::string toString() const override { std::stringstream stream; From 5da88d5d52ec6d3d54c6e194560effa6d690c2d5 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 18 Feb 2016 16:32:45 +0100 Subject: [PATCH 115/246] Small refactoring Former-commit-id: 220d7408e7310d476f4af26bef94ce549fe71cbf --- src/CMakeLists.txt | 2 +- src/builder/ExplicitDFTModelBuilder.h | 2 +- src/storage/dft/DFT.cpp | 22 ++++++++++------------ src/storage/dft/DFT.h | 15 ++++++++++++--- src/storage/dft/DFTState.cpp | 3 +-- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 48428d7cc..3aa121a0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -37,13 +37,13 @@ file(GLOB STORM_SOLVER_STATEELIMINATION_FILES ${PROJECT_SOURCE_DIR}/src/solver/s file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp) file(GLOB STORM_STORAGE_BISIMULATION_FILES ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.h ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.cpp) file(GLOB STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp) +file(GLOB STORM_STORAGE_DFT_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/*.h ${PROJECT_SOURCE_DIR}/src/storage/dft/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_CUDD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/cudd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/cudd/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_SYLVAN_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/sylvan/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/sylvan/*.cpp) file(GLOB_RECURSE STORM_STORAGE_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.h ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.cpp) file(GLOB_RECURSE STORM_STORAGE_PRISM_FILES ${PROJECT_SOURCE_DIR}/src/storage/prism/*.h ${PROJECT_SOURCE_DIR}/src/storage/prism/*.cpp) file(GLOB_RECURSE STORM_STORAGE_SPARSE_FILES ${PROJECT_SOURCE_DIR}/src/storage/sparse/*.h ${PROJECT_SOURCE_DIR}/src/storage/sparse/*.cpp) file(GLOB_RECURSE STORM_UTILITY_FILES ${PROJECT_SOURCE_DIR}/src/utility/*.h ${PROJECT_SOURCE_DIR}/src/utility/*.cpp) -file(GLOB_RECURSE STORM_STORAGE_DFT_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/*.h ${PROJECT_SOURCE_DIR}/src/storage/sparse/*.cpp) # Additional include files like the storm-config.h diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 67dec3dc4..0b80608cf 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -49,7 +49,7 @@ namespace storm { size_t newIndex = 0; public: - ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft), mStates(((mDft.stateSize() / 64) + 1) * 64, std::pow(2, mDft.nrBasicElements())) { + ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, std::pow(2, mDft.nrBasicElements())) { // stateSize is bound for size of bitvector // 2^nrBE is upper bound for state space } diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 5735af2a7..9506b29a5 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -10,13 +10,12 @@ namespace storm { namespace storage { template - DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0) + DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mTopLevelIndex(tle->id()), mNrOfBEs(0), mNrOfSpares(0) { assert(elementIndicesCorrect()); - - size_t stateIndex = 0; mUsageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; - + size_t stateIndex = 0; + for (auto& elem : mElements) { mIdToFailureIndex.push_back(stateIndex); stateIndex += 2; @@ -25,6 +24,7 @@ namespace storm { } else if (elem->isSpareGate()) { ++mNrOfSpares; + bool firstChild = true; for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { if(mActivationIndex.count(spareReprs->id()) == 0) { mActivationIndex[spareReprs->id()] = stateIndex++; @@ -32,11 +32,9 @@ namespace storm { std::set module = {spareReprs->id()}; spareReprs->extendSpareModule(module); std::vector sparesAndBes; - bool secondSpare = false; - for(auto const& modelem : module) { - if (mElements[modelem]->isSpareGate()) { - STORM_LOG_THROW(!secondSpare, storm::exceptions::NotSupportedException, "Module for '" << spareReprs->name() << "' contains more than one spare."); - secondSpare = true; + for(size_t modelem : module) { + if (spareReprs->id() != modelem && (isRepresentative(modelem) || (!firstChild && mTopLevelIndex == modelem))) { + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Module for '" << spareReprs->name() << "' contains more than one representative."); } if(mElements[modelem]->isSpareGate() || mElements[modelem]->isBasicElement()) { sparesAndBes.push_back(modelem); @@ -44,7 +42,7 @@ namespace storm { } } mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); - + firstChild = false; } std::static_pointer_cast>(elem)->setUseIndex(stateIndex); mUsageIndex.insert(std::make_pair(elem->id(), stateIndex)); @@ -71,8 +69,8 @@ namespace storm { } mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); - mStateSize = stateIndex; - mTopLevelIndex = tle->id(); + mStateVectorSize = stateIndex; + } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index f2036e7d7..ca860d074 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -53,7 +53,7 @@ namespace storm { size_t mNrOfSpares; size_t mTopLevelIndex; size_t mUsageInfoBits; - size_t mStateSize; + size_t mStateVectorSize; std::map mActivationIndex; std::map> mSpareModules; std::vector mDependencies; @@ -65,8 +65,8 @@ namespace storm { public: DFT(DFTElementVector const& elements, DFTElementPointer const& tle); - size_t stateSize() const { - return mStateSize; + size_t stateVectorSize() const { + return mStateVectorSize; } size_t nrElements() const { @@ -198,6 +198,15 @@ namespace storm { } return elements; } + + bool isRepresentative(size_t id) const { + for (auto const& parent : getElement(id)->parents()) { + if (parent->isSpareGate()) { + return true; + } + } + return false; + } bool hasRepresentant(size_t id) const { return mRepresentants.find(id) != mRepresentants.end(); diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 9916bbe0e..7e8429fdd 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -6,13 +6,12 @@ namespace storm { namespace storage { template - DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateSize()), mId(id), mDft(dft) { + DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateVectorSize()), mId(id), mDft(dft) { mInactiveSpares = dft.getSpareIndices(); dft.initializeUses(*this); dft.initializeActivation(*this); std::vector alwaysActiveBEs = dft.nonColdBEs(); mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); - } template From cc92085a15de67a6c7a3bc942183429214088f71 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 16:40:44 +0100 Subject: [PATCH 116/246] bijection check for homomorphism Former-commit-id: bf7f2f40662f11c6fbb1772bdc216eb17253ad12 --- src/storage/dft/DFT.cpp | 17 +++++++++++-- src/storage/dft/DFTIsomorphism.h | 43 ++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 5735af2a7..e231c7c8d 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -180,20 +180,29 @@ namespace storm { std::vector> DFT::findSymmetries(DFTColouring const& colouring) const { std::vector vec; vec.reserve(nrElements()); - storm::utility::iota_n(std::back_inserter(vec), 14, 0); + storm::utility::iota_n(std::back_inserter(vec), nrElements(), 0); BijectionCandidates completeCategories = colouring.colourSubdft(vec); std::vector> res; + for(auto const& colourClass : completeCategories.gateCandidates) { if(colourClass.second.size() > 1) { + std::vector handledWithinClass; for(auto it1 = colourClass.second.cbegin(); it1 != colourClass.second.cend(); ++it1) { + if(!getGate(*it1)->hasOnlyStaticParents()) { + continue; + } std::vector sortedParent1Ids = getGate(*it1)->parentIds(); std::sort(sortedParent1Ids.begin(), sortedParent1Ids.end()); auto it2 = it1; for(++it2; it2 != colourClass.second.cend(); ++it2) { + if(!getGate(*it2)->hasOnlyStaticParents()) { + continue; + } std::vector sortedParent2Ids = getGate(*it2)->parentIds(); std::sort(sortedParent2Ids.begin(), sortedParent2Ids.end()); if(sortedParent1Ids == sortedParent2Ids) { std::cout << "Considering ids " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + bool isSymmetry = false; std::vector isubdft1 = getGate(*it1)->independentSubDft(); std::vector isubdft2 = getGate(*it2)->independentSubDft(); if(!isubdft1.empty() && !isubdft2.empty() && isubdft1.size() == isubdft2.size()) { @@ -201,7 +210,11 @@ namespace storm { auto LHS = colouring.colourSubdft(isubdft1); auto RHS = colouring.colourSubdft(isubdft2); auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); - IsoCheck.findIsomorphism(); + isSymmetry = IsoCheck.findIsomorphism(); + } + if(isSymmetry) { + std::cout << "subdfts are symmetric" << std::endl; + } } } diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 6c4a44ad6..182a2b01c 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -261,11 +261,42 @@ namespace storage { */ bool check() { // We can skip BEs, as they are identified by they're homomorphic if they are in the same class - for(auto const& index : bijection) { - // As they are in the same group, the types are fine already. We just have to check the children. - + for(auto const& indexpair : bijection) { + // Check type first. Colouring takes care of a lot, but not necesarily everything (e.g. voting thresholds) + equalType(*dft.getElement(indexpair.first), *dft.getElement(indexpair.second)); + if(dft.isGate(indexpair.first)) { + assert(dft.isGate(indexpair.second)); + auto const& lGate = dft.getGate(indexpair.first); + std::set childrenLeftMapped; + for(auto const& child : lGate->children() ) { + childrenLeftMapped.insert(bijection.at(child->id())); + } + auto const& rGate = dft.getGate(indexpair.second); + std::set childrenRight; + for(auto const& child : rGate->children() ) { + childrenRight.insert(child->id()); + } + if(childrenLeftMapped != childrenRight) { + return false; + } + } else if(dft.isDependency(indexpair.first)) { + assert(dft.isDependency(indexpair.second)); + auto const& lDep = dft.getDependency(indexpair.first); + auto const& rDep = dft.getDependency(indexpair.second); + if(bijection.at(lDep->triggerEvent()->id()) != rDep->triggerEvent()->id()) { + return false; + } + if(bijection.at(lDep->dependentEvent()->id()) != rDep->dependentEvent()->id()) { + return false; + } + } + else { + assert(dft.isBasicElement(indexpair.first)); + assert(dft.isBasicElement(indexpair.second)); + // No operations required. + } } - return false; + return true; } private: @@ -341,9 +372,7 @@ namespace storage { } - //std::vector> computeNextCandidate(){ - - //} + }; From 7bf6dbbaab21ac16a4d2333e45ab0ba25252a450 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 16:45:45 +0100 Subject: [PATCH 117/246] outgoingDependencies in c++ style :) Former-commit-id: 51af1f47ba499719d5c22cb29b97a6da138a7533 --- src/storage/dft/DFTElements.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 36075d005..d69b73f3b 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -168,7 +168,7 @@ namespace storm { return mOutgoingDependencies.size(); } - DFTDependencyVector const& getOutgoingDependencies() const { + DFTDependencyVector const& outgoingDependencies() const { return mOutgoingDependencies; } From ca77078a9c866cc0aee16908333ec37c138557de Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 18:03:57 +0100 Subject: [PATCH 118/246] Deterministic Building for DFTs Former-commit-id: bb669a034e24494ae3c88a6a353931651c0c945a --- src/storage/dft/DFTBuilder.cpp | 4 ++-- src/storage/dft/DFTBuilder.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index f0d1db5ac..1979aea3b 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -123,7 +123,7 @@ namespace storm { } template - void DFTBuilder::topoVisit(DFTElementPointer const& n, std::map& visited, DFTElementVector& L) { + void DFTBuilder::topoVisit(DFTElementPointer const& n, std::map>& visited, DFTElementVector& L) { if(visited[n] == topoSortColour::GREY) { throw storm::exceptions::WrongFormatException("DFT is cyclic"); } else if(visited[n] == topoSortColour::WHITE) { @@ -141,7 +141,7 @@ namespace storm { // TODO Matthias: use typedefs template std::vector>> DFTBuilder::topoSort() { - std::map visited; + std::map> visited; for(auto const& e : mElements) { visited.insert(std::make_pair(e.second, topoSortColour::WHITE)); } diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 37c3c4eaa..17a16cb49 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -141,7 +141,7 @@ namespace storm { enum class topoSortColour {WHITE, BLACK, GREY}; - void topoVisit(DFTElementPointer const& n, std::map& visited, DFTElementVector& L); + void topoVisit(DFTElementPointer const& n, std::map>& visited, DFTElementVector& L); DFTElementVector topoSort(); From 7663c29c5d5a00fdde84ac892f7e3bca87958368 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 18:13:10 +0100 Subject: [PATCH 119/246] Fix in SubDFT computation. Former-commit-id: aec3f5d0de949aa07c35222dfe1f8e320713bf81 --- src/storage/dft/DFTElements.cpp | 26 ++++++++++++----- src/storage/dft/DFTElements.h | 51 +++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index c7fc1d960..d59ec8f41 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -46,14 +46,20 @@ namespace storm { template std::vector DFTElement::independentSubDft() const { + std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; std::vector res; res.push_back(this->id()); - // Extend for pdeps. return res; } template - void DFTElement::extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const { + void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const { + if(elemsInSubtree.count(this->id()) > 0) return; + std::cout << "ID " << this->id() << "PREL elems "; + for(auto const& i : elemsInSubtree) { + std::cout << i << " "; + } + std::cout << "in subtree." << std::endl; if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { // This is a parent of the suspected root, thus it is not a subdft. elemsInSubtree.clear(); @@ -61,13 +67,19 @@ namespace storm { } elemsInSubtree.insert(mId); for(auto const& parent : mParents) { - if(elemsInSubtree.count(parent->id()) != 0) { - parent->extendUnit(elemsInSubtree); - if(elemsInSubtree.empty()) { - return; - } + + parent->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + return; } } + for(auto const& dep : mOutgoingDependencies) { + dep->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + return; + } + + } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index d69b73f3b..81b8ce303 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -202,7 +202,7 @@ namespace storm { * Helper to the independent subtree computation * @see independentSubDft */ - virtual void extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const; + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const; virtual bool isTypeEqualTo(DFTElement const& other) const { return type() == other.type(); @@ -291,6 +291,11 @@ namespace storm { std::vector pids = this->parentIds(); for(auto const& child : mChildren) { child->extendSubDft(unit, pids); + std::cout << "int sub "; + for(auto const& i : unit) { + std::cout << i << " "; + } + std::cout << std::endl; if(unit.empty()) { // Parent in the subdft, ie it is *not* a subdft break; @@ -299,9 +304,10 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + if(elemsInSubtree.count(this->id()) > 0) return; DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); - if(!elemsInSubtree.empty()) { + if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } @@ -309,7 +315,7 @@ namespace storm { child->extendSubDft(elemsInSubtree, parentsOfSubRoot); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft - break; + return; } } } @@ -437,7 +443,7 @@ namespace storm { return mIngoingDependencies.size(); } - DFTDependencyVector const& getIngoingDependencies() const { + DFTDependencyVector const& ingoingDependencies() const { return mIngoingDependencies; } @@ -455,6 +461,22 @@ namespace storm { return storm::utility::isZero(mPassiveFailureRate); } + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + if(elemsInSubtree.count(this->id())) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + for(auto const& incDep : mIngoingDependencies) { + incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + } + } + bool isTypeEqualTo(DFTElement const& other) const override { if(!DFTElement::isTypeEqualTo(other)) return false; DFTBE const& otherBE = static_cast const&>(other); @@ -502,6 +524,8 @@ namespace storm { return 0; } + + bool isTypeEqualTo(DFTElement const& other) const override { if(!DFTElement::isTypeEqualTo(other)) return false; DFTConst const& otherCNST = static_cast const&>(other); @@ -589,6 +613,23 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + if(elemsInSubtree.count(this->id())) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot); + + + } + virtual std::string toString() const override { std::stringstream stream; bool fdep = storm::utility::isOne(mProbability); From 30df7c0bda435a825d92b6a952009386c46a05f8 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 18:44:26 +0100 Subject: [PATCH 120/246] Convenience info about bijectioncandidates Former-commit-id: c2af2c957ae465303b18e07dbc43b7a19a0c46ae --- src/storage/dft/DFTIsomorphism.h | 86 ++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 182a2b01c..6ce267e87 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -63,6 +63,87 @@ namespace storage { std::unordered_map> gateCandidates; std::unordered_map, std::vector> beCandidates; std::unordered_map, std::vector> pdepCandidates; + + size_t nrGroups() const { + return gateCandidates.size() + beCandidates.size() + pdepCandidates.size(); + } + + size_t size() const { + return nrGates() + nrBEs() + nrDeps(); + } + + size_t nrGates() const { + size_t res = 0; + for(auto const& x : gateCandidates) { + res += x.second.size(); + } + return res; + } + + size_t nrBEs() const { + size_t res = 0; + for(auto const& x : beCandidates) { + res += x.second.size(); + } + return res; + } + + size_t nrDeps() const { + size_t res = 0; + for(auto const& x : pdepCandidates) { + res += x.second.size(); + } + return res; + } + + bool hasGate(size_t index) { + for(auto const& x : gateCandidates) { + for( auto const& ind : x.second) { + if(index == ind) return true; + } + } + return false; + } + + bool hasBE(size_t index) { + for(auto const& x : beCandidates) { + for(auto const& ind : x.second) { + if(index == ind) return true; + } + } + return false; + } + + bool hasDep(size_t index) { + for(auto const& x : pdepCandidates) { + for(auto const& ind : x.second) { + if(index == ind) return true; + } + } + return false; + } + + bool has(size_t index) { + return hasGate(index) || hasBE(index) || hasDep(index); + } + + + + size_t trivialGateGroups() const { + size_t res = 0; + for(auto const& x : gateCandidates) { + if(x.second.size() == 1) ++res; + } + return res; + } + + size_t trivialBEGroups() const { + size_t res = 0; + for(auto const& x : beCandidates) { + if(x.second.size() == 1) ++res; + } + return res; + } }; template @@ -207,6 +288,9 @@ namespace storage { initializePermutationsAndTreatTrivialGroups(bleft.beCandidates, bright.beCandidates, currentPermutations.beCandidates); initializePermutationsAndTreatTrivialGroups(bleft.gateCandidates, bright.gateCandidates, currentPermutations.gateCandidates); initializePermutationsAndTreatTrivialGroups(bleft.pdepCandidates, bright.pdepCandidates, currentPermutations.pdepCandidates); + std::cout << bijection.size() << " vs. " << bleft.size() << " vs. " << bright.size() << std::endl; + assert(bijection.size() == bleft.size()); + } /** @@ -214,6 +298,7 @@ namespace storage { * @return true if a next bijection exists. */ bool findNextBijection() { + assert(candidatesCompatible); bool foundNext = false; if(!currentPermutations.beCandidates.empty()) { auto it = currentPermutations.beCandidates.begin(); @@ -260,6 +345,7 @@ namespace storage { * */ bool check() { + assert(bijection.size() == bleft.size()); // We can skip BEs, as they are identified by they're homomorphic if they are in the same class for(auto const& indexpair : bijection) { // Check type first. Colouring takes care of a lot, but not necesarily everything (e.g. voting thresholds) From aaec1fd3bd9b5ff0db8b474ad606100ce0b0837b Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 18:56:36 +0100 Subject: [PATCH 121/246] isomorphism runs through first tests :) Former-commit-id: c83157ba7ad6da368062e7f13e626d0733a14949 --- src/storage/dft/DFTIsomorphism.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 6ce267e87..5aec35714 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -96,7 +96,7 @@ namespace storage { return res; } - bool hasGate(size_t index) { + bool hasGate(size_t index) const { for(auto const& x : gateCandidates) { for( auto const& ind : x.second) { if(index == ind) return true; @@ -105,7 +105,7 @@ namespace storage { return false; } - bool hasBE(size_t index) { + bool hasBE(size_t index) const { for(auto const& x : beCandidates) { for(auto const& ind : x.second) { if(index == ind) return true; @@ -114,7 +114,7 @@ namespace storage { return false; } - bool hasDep(size_t index) { + bool hasDep(size_t index) const { for(auto const& x : pdepCandidates) { for(auto const& ind : x.second) { if(index == ind) return true; @@ -123,7 +123,7 @@ namespace storage { return false; } - bool has(size_t index) { + bool has(size_t index) const { return hasGate(index) || hasBE(index) || hasDep(index); } @@ -355,11 +355,13 @@ namespace storage { auto const& lGate = dft.getGate(indexpair.first); std::set childrenLeftMapped; for(auto const& child : lGate->children() ) { + assert(bleft.has(child->id())); childrenLeftMapped.insert(bijection.at(child->id())); } auto const& rGate = dft.getGate(indexpair.second); std::set childrenRight; for(auto const& child : rGate->children() ) { + assert(bright.has(child->id())); childrenRight.insert(child->id()); } if(childrenLeftMapped != childrenRight) { @@ -435,7 +437,7 @@ namespace storage { auto it = permutations.insert(colour); assert(it.second); std::sort(it.first->second.begin(), it.first->second.end()); - zipVectorsIntoMap(colour.second, permutations.find(colour.first)->second, bijection); + zipVectorsIntoMap(left.at(colour.first), it.first->second, bijection); } else { assert(colour.second.size() == 1); assert(bijection.count(left.at(colour.first).front()) == 0); From 2dbcd260e4127672119fb96474a36014e35fef88 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 19:00:37 +0100 Subject: [PATCH 122/246] symred is now an option Former-commit-id: 572599165612efed2c499668622425b05902927a --- src/storm-dyftee.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index a8122f2bd..f0da80f0f 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -4,6 +4,7 @@ #include "builder/ExplicitDFTModelBuilder.h" #include "modelchecker/results/CheckResult.h" #include "utility/storm.h" +#include "storage/dft/DFTIsomorphism.h" /*! * Load DFT from filename, build corresponding Model and check against given property. @@ -12,13 +13,19 @@ * @param property PCTC formula capturing the property to check. */ template -void analyzeDFT(std::string filename, std::string property) { +void analyzeDFT(std::string filename, std::string property, bool symred = false) { // Parsing DFT std::cout << "Parsing DFT file..." << std::endl; storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(filename); std::cout << "Built data structure" << std::endl; - + + if(symred) { + std::cout << dft.getElementsString() << std::endl; + auto colouring = dft.colourDFT(); + dft.findSymmetries(colouring); + } + // Building Markov Automaton std::cout << "Building Model..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); @@ -52,6 +59,7 @@ int main(int argc, char** argv) { // Parse cli arguments bool parametric = false; + bool symred = false; log4cplus::LogLevel level = log4cplus::WARN_LOG_LEVEL; std::string filename = argv[1]; std::string pctlFormula = ""; @@ -74,6 +82,8 @@ int main(int argc, char** argv) { ++i; assert(i < argc); pctlFormula = argv[i]; + } else if (option == "--symred") { + symred = true; } else { std::cout << "Option '" << option << "' not recognized." << std::endl; return 1; @@ -88,8 +98,8 @@ int main(int argc, char** argv) { std::cout << "Running " << (parametric ? "parametric " : "") << "DFT analysis on file " << filename << " with property " << pctlFormula << std::endl; if (parametric) { - analyzeDFT(filename, pctlFormula); + analyzeDFT(filename, pctlFormula, symred); } else { - analyzeDFT(filename, pctlFormula); + analyzeDFT(filename, pctlFormula, symred); } } From 11f01cdf5273136f0718a170b83ea4202c657431 Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 21:09:12 +0100 Subject: [PATCH 123/246] towards using symred for counting abstr Former-commit-id: 51bad8ba1e6b711cc45c82f69240c79dcf8b03cb --- src/storage/dft/DFT.cpp | 36 +++++++++++++++++++++++++------- src/storage/dft/DFTElements.cpp | 5 ----- src/storage/dft/DFTElements.h | 5 ----- src/storage/dft/DFTIsomorphism.h | 4 ++-- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index e231c7c8d..1ce4618cf 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -186,8 +186,12 @@ namespace storm { for(auto const& colourClass : completeCategories.gateCandidates) { if(colourClass.second.size() > 1) { - std::vector handledWithinClass; + std::set foundEqClassFor; for(auto it1 = colourClass.second.cbegin(); it1 != colourClass.second.cend(); ++it1) { + std::vector> symClass; + if(foundEqClassFor.count(*it1) > 0) { + continue; + } if(!getGate(*it1)->hasOnlyStaticParents()) { continue; } @@ -200,20 +204,38 @@ namespace storm { } std::vector sortedParent2Ids = getGate(*it2)->parentIds(); std::sort(sortedParent2Ids.begin(), sortedParent2Ids.end()); + if(sortedParent1Ids == sortedParent2Ids) { std::cout << "Considering ids " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; bool isSymmetry = false; std::vector isubdft1 = getGate(*it1)->independentSubDft(); std::vector isubdft2 = getGate(*it2)->independentSubDft(); - if(!isubdft1.empty() && !isubdft2.empty() && isubdft1.size() == isubdft2.size()) { - std::cout << "Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; - auto LHS = colouring.colourSubdft(isubdft1); - auto RHS = colouring.colourSubdft(isubdft2); - auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); - isSymmetry = IsoCheck.findIsomorphism(); + if(isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) { + continue; } + std::cout << "Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + auto LHS = colouring.colourSubdft(isubdft1); + auto RHS = colouring.colourSubdft(isubdft2); + auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); + isSymmetry = IsoCheck.findIsomorphism(); if(isSymmetry) { std::cout << "subdfts are symmetric" << std::endl; + foundEqClassFor.insert(*it2); + if(symClass.empty()) { + for(auto const& i : isubdft1) { + symClass.push_back(std::vector({i})); + } + } + auto symClassIt = symClass.begin(); + for(auto const& i : isubdft1) { + symClassIt->emplace_back(IsoCheck.getIsomorphism().at(i)); + for(auto const& v : *symClassIt) { + std::cout << v << " "; + } + std::cout << std::endl; + ++symClassIt; + + } } } diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index d59ec8f41..26f5f9cbe 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -55,11 +55,6 @@ namespace storm { template void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const { if(elemsInSubtree.count(this->id()) > 0) return; - std::cout << "ID " << this->id() << "PREL elems "; - for(auto const& i : elemsInSubtree) { - std::cout << i << " "; - } - std::cout << "in subtree." << std::endl; if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { // This is a parent of the suspected root, thus it is not a subdft. elemsInSubtree.clear(); diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 81b8ce303..c352bd38e 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -291,11 +291,6 @@ namespace storm { std::vector pids = this->parentIds(); for(auto const& child : mChildren) { child->extendSubDft(unit, pids); - std::cout << "int sub "; - for(auto const& i : unit) { - std::cout << i << " "; - } - std::cout << std::endl; if(unit.empty()) { // Parent in the subdft, ie it is *not* a subdft break; diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 5aec35714..0d5590d3d 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -256,8 +256,8 @@ namespace storage { * Can only be called after the findIsomorphism procedure returned that an isomorphism has found. * @see findIsomorphism */ - std::vector> getIsomorphism() const { - + std::map const& getIsomorphism() const { + return bijection; } /** From 130fa1328ab30f297c79122273c100273472767f Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 21:39:43 +0100 Subject: [PATCH 124/246] function returns independent symmetries Former-commit-id: 674f0bcff263b0d52d928a37cfdac50d69066d47 --- src/storage/dft/DFT.cpp | 15 ++++++++------- src/storage/dft/DFT.h | 4 ++-- src/storage/dft/SymmetricUnits.h | 33 ++++++++++++++++++++++++++------ src/storm-dyftee.cpp | 3 ++- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 1ce4618cf..0a90f1513 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -1,5 +1,6 @@ #include +#include #include "DFT.h" #include "src/exceptions/NotSupportedException.h" @@ -177,12 +178,12 @@ namespace storm { } template - std::vector> DFT::findSymmetries(DFTColouring const& colouring) const { + DFTIndependentSymmetries DFT::findSymmetries(DFTColouring const& colouring) const { std::vector vec; vec.reserve(nrElements()); storm::utility::iota_n(std::back_inserter(vec), nrElements(), 0); BijectionCandidates completeCategories = colouring.colourSubdft(vec); - std::vector> res; + std::map>> res; for(auto const& colourClass : completeCategories.gateCandidates) { if(colourClass.second.size() > 1) { @@ -229,10 +230,6 @@ namespace storm { auto symClassIt = symClass.begin(); for(auto const& i : isubdft1) { symClassIt->emplace_back(IsoCheck.getIsomorphism().at(i)); - for(auto const& v : *symClassIt) { - std::cout << v << " "; - } - std::cout << std::endl; ++symClassIt; } @@ -240,10 +237,14 @@ namespace storm { } } } + if(!symClass.empty()) { + res.emplace(*it1, symClass); + } } + } } - return res; + return DFTIndependentSymmetries(res); } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index f2036e7d7..57bfee16d 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -11,7 +11,7 @@ #include "DFTElements.h" #include "../BitVector.h" - +#include "SymmetricUnits.h" #include "../../utility/math.h" #include "src/utility/macros.h" @@ -230,7 +230,7 @@ namespace storm { DFTColouring colourDFT() const; - std::vector> findSymmetries(DFTColouring const& colouring) const; + DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; private: bool elementIndicesCorrect() const { diff --git a/src/storage/dft/SymmetricUnits.h b/src/storage/dft/SymmetricUnits.h index 3959593a1..6521ee8d2 100644 --- a/src/storage/dft/SymmetricUnits.h +++ b/src/storage/dft/SymmetricUnits.h @@ -1,7 +1,28 @@ -#ifndef SYMMETRICUNITS_H -#define SYMMETRICUNITS_H - - - -#endif /* SYMMETRICUNITS_H */ +#pragma once +namespace storm { + namespace storage { + struct DFTIndependentSymmetries { + std::map>> groups; + + DFTIndependentSymmetries(std::map>> groups) : groups(groups) { + + } + }; + + inline std::ostream& operator<<(std::ostream& os, DFTIndependentSymmetries const& s) { + for(auto const& cl : s.groups) { + std::cout << "SYM GROUP FOR " << cl.first << std::endl; + for(auto const& eqClass : cl.second) { + for(auto const& i : eqClass) { + std::cout << i << " "; + } + std::cout << std::endl; + } + } + + + return os; + } + } +} \ No newline at end of file diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index f0da80f0f..49b573f33 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -23,7 +23,8 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) if(symred) { std::cout << dft.getElementsString() << std::endl; auto colouring = dft.colourDFT(); - dft.findSymmetries(colouring); + auto res = dft.findSymmetries(colouring); + std::cout << res; } // Building Markov Automaton From 2ab4417ed4ff6ad07fcfcc242c0075acd64e657f Mon Sep 17 00:00:00 2001 From: sjunges Date: Thu, 18 Feb 2016 21:52:05 +0100 Subject: [PATCH 125/246] symmetry also check deps for roots now Former-commit-id: a1141250c2dee120e442dc72e42417c19053b055 --- src/storage/dft/DFT.cpp | 18 +++++++++++++++--- src/storage/dft/DFT.h | 2 ++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 0a90f1513..d56166f60 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -196,8 +196,8 @@ namespace storm { if(!getGate(*it1)->hasOnlyStaticParents()) { continue; } - std::vector sortedParent1Ids = getGate(*it1)->parentIds(); - std::sort(sortedParent1Ids.begin(), sortedParent1Ids.end()); + + std::pair, std::vector> influencedElem1Ids = getSortedParentAndOutDepIds(*it1); auto it2 = it1; for(++it2; it2 != colourClass.second.cend(); ++it2) { if(!getGate(*it2)->hasOnlyStaticParents()) { @@ -206,7 +206,7 @@ namespace storm { std::vector sortedParent2Ids = getGate(*it2)->parentIds(); std::sort(sortedParent2Ids.begin(), sortedParent2Ids.end()); - if(sortedParent1Ids == sortedParent2Ids) { + if(influencedElem1Ids == getSortedParentAndOutDepIds(*it2)) { std::cout << "Considering ids " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; bool isSymmetry = false; std::vector isubdft1 = getGate(*it1)->independentSubDft(); @@ -247,6 +247,18 @@ namespace storm { return DFTIndependentSymmetries(res); } + template + std::pair, std::vector> DFT::getSortedParentAndOutDepIds(size_t index) const { + std::pair, std::vector> res; + res.first = getElement(index)->parentIds(); + std::sort(res.first.begin(), res.first.end()); + for(auto const& dep : getElement(index)->outgoingDependencies()) { + res.second.push_back(dep->id()); + } + std::sort(res.second.begin(), res.second.end()); + return res; + } + // Explicitly instantiate the class. template class DFT; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 57bfee16d..1583cc8d5 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -233,6 +233,8 @@ namespace storm { DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; private: + std::pair, std::vector> getSortedParentAndOutDepIds(size_t index) const; + bool elementIndicesCorrect() const { for(size_t i = 0; i < mElements.size(); ++i) { if(mElements[i]->id() != i) return false; From 0d3687cf5e89d629431d2cb6ed3d530e1d86ef88 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 18 Feb 2016 23:23:00 +0100 Subject: [PATCH 126/246] Refactored and sorted bitvector Former-commit-id: 28ca00af502f334cbb6a10c03277d3f39b592072 --- src/builder/ExplicitDFTModelBuilder.cpp | 43 ++++++++- src/builder/ExplicitDFTModelBuilder.h | 8 +- src/storage/dft/DFT.cpp | 100 ++++++++++++++++++--- src/storage/dft/DFT.h | 115 ++++++++++++++---------- src/storage/dft/DFTElements.h | 23 +---- src/storage/dft/DFTState.cpp | 72 ++++++++++----- src/storage/dft/DFTState.h | 16 ++-- 7 files changed, 261 insertions(+), 116 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 160535443..91a16f2d2 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -13,11 +13,52 @@ namespace storm { ExplicitDFTModelBuilder::ModelComponents::ModelComponents() : transitionMatrix(), stateLabeling(), markovianStates(), exitRates(), choiceLabeling() { // Intentionally left empty. } + + template + ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, std::pow(2, mDft.nrBasicElements())) { + // stateSize is bound for size of bitvector + // 2^nrBE is upper bound for state space + + // Find symmetries + // TODO activate + // Currently using hack to test + std::vector> symmetries; + std::vector vecB; + std::vector vecC; + std::vector vecD; + if (false) { + for (size_t i = 0; i < mDft.nrElements(); ++i) { + std::string name = mDft.getElement(i)->name(); + size_t id = mDft.getElement(i)->id(); + if (boost::starts_with(name, "B")) { + vecB.push_back(id); + } else if (boost::starts_with(name, "C")) { + vecC.push_back(id); + } else if (boost::starts_with(name, "D")) { + vecD.push_back(id); + } + } + symmetries.push_back(vecB); + symmetries.push_back(vecC); + symmetries.push_back(vecD); + std::cout << "Found the following symmetries:" << std::endl; + for (auto const& symmetry : symmetries) { + for (auto const& elem : symmetry) { + std::cout << elem << " -> "; + } + std::cout << std::endl; + } + } else { + vecB.push_back(mDft.getTopLevelIndex()); + } + mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(vecB, symmetries)); + } + template std::shared_ptr> ExplicitDFTModelBuilder::buildModel() { // Initialize - DFTStatePointer state = std::make_shared>(mDft, newIndex++); + DFTStatePointer state = std::make_shared>(mDft, *mStateGenerationInfo, newIndex++); mStates.findOrAdd(state->status(), state); std::queue stateQueue; diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 0b80608cf..eacf2568c 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -44,15 +44,13 @@ namespace storm { boost::optional>> choiceLabeling; }; - storm::storage::DFT const &mDft; + storm::storage::DFT const& mDft; + std::shared_ptr mStateGenerationInfo; storm::storage::BitVectorHashMap mStates; size_t newIndex = 0; public: - ExplicitDFTModelBuilder(storm::storage::DFT const &dft) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, std::pow(2, mDft.nrBasicElements())) { - // stateSize is bound for size of bitvector - // 2^nrBE is upper bound for state space - } + ExplicitDFTModelBuilder(storm::storage::DFT const& dft); std::shared_ptr> buildModel(); diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 9506b29a5..62f7fe704 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -10,15 +10,18 @@ namespace storm { namespace storage { template - DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mTopLevelIndex(tle->id()), mNrOfBEs(0), mNrOfSpares(0) - { + DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mTopLevelIndex(tle->id()) { assert(elementIndicesCorrect()); - mUsageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; - size_t stateIndex = 0; + size_t stateVectorIndex = 0; + std::set tmpRepresentatives; + size_t usageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; + size_t nrRepresentatives = 0; for (auto& elem : mElements) { - mIdToFailureIndex.push_back(stateIndex); - stateIndex += 2; + stateVectorIndex += 2; + if (isRepresentative(elem->id())) { + ++nrRepresentatives; + } if(elem->isBasicElement()) { ++mNrOfBEs; } @@ -26,9 +29,7 @@ namespace storm { ++mNrOfSpares; bool firstChild = true; for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { - if(mActivationIndex.count(spareReprs->id()) == 0) { - mActivationIndex[spareReprs->id()] = stateIndex++; - } + tmpRepresentatives.insert(spareReprs->id()); std::set module = {spareReprs->id()}; spareReprs->extendSpareModule(module); std::vector sparesAndBes; @@ -44,14 +45,13 @@ namespace storm { mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); firstChild = false; } - std::static_pointer_cast>(elem)->setUseIndex(stateIndex); - mUsageIndex.insert(std::make_pair(elem->id(), stateIndex)); - stateIndex += mUsageInfoBits; + stateVectorIndex += usageInfoBits; } else if (elem->isDependency()) { mDependencies.push_back(elem->id()); } } + stateVectorIndex += tmpRepresentatives.size(); // For the top module, we assume, contrary to [Jun15], that we have all spare gates and basic elements which are not in another module. std::set topModuleSet; @@ -68,12 +68,84 @@ namespace storm { } } mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); - - mStateVectorSize = stateIndex; + + std::cout << tmpRepresentatives.size() << ", " << nrRepresentatives << std::endl; + std::cout << stateVectorIndex << ", " << (nrElements() * 2 + mNrOfSpares * usageInfoBits + tmpRepresentatives.size()) << std::endl; + assert(tmpRepresentatives.size() == nrRepresentatives); + assert(stateVectorIndex == nrElements() * 2 + mNrOfSpares * usageInfoBits + tmpRepresentatives.size()); + mStateVectorSize = stateVectorIndex; } + template + DFTStateGenerationInfo DFT::buildStateGenerationInfo(std::vector const& subTreeRoots, std::vector> const& symmetries) const { + // Use symmetry + // Collect all elements in the first subtree + // TODO make recursive to use for nested subtrees + + DFTStateGenerationInfo generationInfo(nrElements()); + + // Perform DFS and insert all elements of subtree sequentially + size_t stateIndex = 0; + std::queue visitQueue; + std::set visited; + visitQueue.push(subTreeRoots[0]); + bool consideredDependencies = false; + while (true) { + while (!visitQueue.empty()) { + size_t id = visitQueue.front(); + visitQueue.pop(); + if (visited.count(id) == 1) { + // Already visited + continue; + } + visited.insert(id); + DFTElementPointer element = mElements[id]; + + // Insert children + if (element->isGate()) { + for (auto const& child : std::static_pointer_cast>(element)->children()) { + visitQueue.push(child->id()); + } + } + + // Reserve bits for element + generationInfo.addStateIndex(id, stateIndex); + stateIndex += 2; + + if (isRepresentative(id)) { + generationInfo.addSpareActivationIndex(id, stateIndex); + ++stateIndex; + } + + if (element->isSpareGate()) { + generationInfo.addSpareUsageIndex(id, stateIndex); + stateIndex += generationInfo.usageInfoBits(); + } + + } + + if (consideredDependencies) { + break; + } + + // Consider dependencies + for (size_t idDependency : getDependencies()) { + std::shared_ptr const> dependency = getDependency(idDependency); + visitQueue.push(dependency->id()); + visitQueue.push(dependency->triggerEvent()->id()); + visitQueue.push(dependency->dependentEvent()->id()); + } + consideredDependencies = true; + } + assert(stateIndex = mStateVectorSize); + + STORM_LOG_TRACE(generationInfo); + + return generationInfo; } + + template std::string DFT::getElementsString() const { std::stringstream stream; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index ca860d074..015f26c7d 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -33,6 +33,69 @@ namespace storm { // Forward declarations template class DFTColouring; + + class DFTStateGenerationInfo { + private: + const size_t mUsageInfoBits; + std::map mSpareUsageIndex; // id spare -> index first bit in state + std::map mSpareActivationIndex; // id spare representative -> index in state + std::vector mIdToStateIndex; // id -> index first bit in state + + public: + + DFTStateGenerationInfo(size_t nrElements) : mUsageInfoBits(storm::utility::math::uint64_log2(nrElements-1)+1), mIdToStateIndex(nrElements) { + } + + size_t usageInfoBits() const { + return mUsageInfoBits; + } + + void addStateIndex(size_t id, size_t index) { + assert(id < mIdToStateIndex.size()); + mIdToStateIndex[id] = index; + } + + void addSpareActivationIndex(size_t id, size_t index) { + mSpareActivationIndex[id] = index; + } + + void addSpareUsageIndex(size_t id, size_t index) { + mSpareUsageIndex[id] = index; + } + + size_t getStateIndex(size_t id) const { + assert(id < mIdToStateIndex.size()); + return mIdToStateIndex[id]; + } + + size_t getSpareUsageIndex(size_t id) const { + assert(mSpareUsageIndex.count(id) > 0); + return mSpareUsageIndex.at(id); + } + + size_t getSpareActivationIndex(size_t id) const { + assert(mSpareActivationIndex.count(id) > 0); + return mSpareActivationIndex.at(id); + } + + friend std::ostream& operator<<(std::ostream& os, DFTStateGenerationInfo const& info) { + os << "Id to state index:" << std::endl; + for (size_t id = 0; id < info.mIdToStateIndex.size(); ++id) { + os << id << " -> " << info.getStateIndex(id) << std::endl; + } + os << "Spare usage index with usage InfoBits of size " << info.mUsageInfoBits << ":" << std::endl; + for (auto pair : info.mSpareUsageIndex) { + os << pair.first << " -> " << pair.second << std::endl; + } + os << "Spare activation index:" << std::endl; + for (auto pair : info.mSpareActivationIndex) { + os << pair.first << " -> " << pair.second << std::endl; + } + return os; + } + + }; + /** * Represents a Dynamic Fault Tree @@ -52,18 +115,17 @@ namespace storm { size_t mNrOfBEs; size_t mNrOfSpares; size_t mTopLevelIndex; - size_t mUsageInfoBits; size_t mStateVectorSize; - std::map mActivationIndex; std::map> mSpareModules; std::vector mDependencies; std::vector mTopModule; - std::vector mIdToFailureIndex; - std::map mUsageIndex; - std::map mRepresentants; + std::map mRepresentants; // id element -> id representative + std::vector> mSymmetries; public: DFT(DFTElementVector const& elements, DFTElementPointer const& tle); + + DFTStateGenerationInfo buildStateGenerationInfo(std::vector const& subTreeRoots, std::vector> const& symmetries) const; size_t stateVectorSize() const { return mStateVectorSize; @@ -77,34 +139,8 @@ namespace storm { return mNrOfBEs; } - size_t usageInfoBits() const { - return mUsageInfoBits; - } - - size_t usageIndex(size_t id) const { - assert(mUsageIndex.find(id) != mUsageIndex.end()); - return mUsageIndex.find(id)->second; - } - - size_t failureIndex(size_t id) const { - return mIdToFailureIndex[id]; - } - - void initializeUses(DFTState& state) const { - for(auto const& elem : mElements) { - if(elem->isSpareGate()) { - std::static_pointer_cast>(elem)->initializeUses(state); - } - } - } - - void initializeActivation(DFTState& state) const { - state.activate(mTopLevelIndex); - for(auto const& elem : mTopModule) { - if(mElements[elem]->isSpareGate()) { - propagateActivation(state, state.uses(elem)); - } - } + size_t getTopLevelIndex() const { + return mTopLevelIndex; } std::vector getSpareIndices() const { @@ -130,15 +166,6 @@ namespace storm { return mDependencies; } - void propagateActivation(DFTState& state, size_t representativeId) const { - state.activate(representativeId); - for(size_t id : module(representativeId)) { - if(mElements[id]->isSpareGate()) { - propagateActivation(state, state.uses(id)); - } - } - } - std::vector nonColdBEs() const { std::vector result; for(DFTElementPointer elem : mElements) { @@ -170,10 +197,6 @@ namespace storm { return getElement(index)->isDependency(); } -// std::shared_ptr const> getGate(size_t index) const { -// return -// } - std::shared_ptr const> getBasicElement(size_t index) const { assert(isBasicElement(index)); return std::static_pointer_cast const>(mElements[index]); diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 36075d005..db407fb85 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -898,10 +898,6 @@ namespace storm { template class DFTSpare : public DFTGate { - private: - size_t mUseIndex; - size_t mActiveIndex; - public: DFTSpare(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) @@ -919,24 +915,11 @@ namespace storm { return true; } - void setUseIndex(size_t useIndex) { - mUseIndex = useIndex; - } - - void setActiveIndex(size_t activeIndex) { - mActiveIndex = activeIndex; - } - - void initializeUses(storm::storage::DFTState& state) { - assert(this->mChildren.size() > 0); - state.setUsesAtPosition(mUseIndex, this->mChildren[0]->id()); - } - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { - size_t uses = state.extractUses(mUseIndex); + size_t uses = state.uses(this->mId); if(!state.isOperational(uses)) { - bool claimingSuccessful = state.claimNew(this->mId, mUseIndex, uses, this->mChildren); + bool claimingSuccessful = state.claimNew(this->mId, uses, this->mChildren); if(!claimingSuccessful) { this->fail(state, queues); } @@ -946,7 +929,7 @@ namespace storm { void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { - if(state.isFailsafe(state.extractUses((mUseIndex)))) { + if(state.isFailsafe(state.uses(this->mId))) { this->failsafe(state, queues); this->childrenDontCare(state, queues); } diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 7e8429fdd..c3f7c9f32 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -6,10 +6,25 @@ namespace storm { namespace storage { template - DFTState::DFTState(DFT const& dft, size_t id) : mStatus(dft.stateVectorSize()), mId(id), mDft(dft) { + DFTState::DFTState(DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) : mStatus(dft.stateVectorSize()), mId(id), mDft(dft), mStateGenerationInfo(stateGenerationInfo) { mInactiveSpares = dft.getSpareIndices(); - dft.initializeUses(*this); - dft.initializeActivation(*this); + + // Initialize uses + for(size_t id : mDft.getSpareIndices()) { + std::shared_ptr const> elem = mDft.getGate(id); + assert(elem->isSpareGate()); + assert(elem->nrChildren() > 0); + this->setUses(id, elem->children()[0]->id()); + } + + // Initialize activation + this->activate(mDft.getTopLevelIndex()); + for(auto const& id : mDft.module(mDft.getTopLevelIndex())) { + if(mDft.getElement(id)->isSpareGate()) { + propagateActivation(uses(id)); + } + } + std::vector alwaysActiveBEs = dft.nonColdBEs(); mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); } @@ -26,7 +41,7 @@ namespace storm { template int DFTState::getElementStateInt(size_t id) const { - return mStatus.getAsInt(mDft.failureIndex(id), 2); + return mStatus.getAsInt(mStateGenerationInfo.getStateIndex(id), 2); } template @@ -46,12 +61,12 @@ namespace storm { template bool DFTState::hasFailed(size_t id) const { - return mStatus[mDft.failureIndex(id)]; + return mStatus[mStateGenerationInfo.getStateIndex(id)]; } template bool DFTState::isFailsafe(size_t id) const { - return mStatus[mDft.failureIndex(id)+1]; + return mStatus[mStateGenerationInfo.getStateIndex(id)+1]; } template @@ -66,38 +81,38 @@ namespace storm { template bool DFTState::dependencySuccessful(size_t id) const { - return mStatus[mDft.failureIndex(id)]; + return mStatus[mStateGenerationInfo.getStateIndex(id)]; } template bool DFTState::dependencyUnsuccessful(size_t id) const { - return mStatus[mDft.failureIndex(id)+1]; + return mStatus[mStateGenerationInfo.getStateIndex(id)+1]; } template void DFTState::setFailed(size_t id) { - mStatus.set(mDft.failureIndex(id)); + mStatus.set(mStateGenerationInfo.getStateIndex(id)); } template void DFTState::setFailsafe(size_t id) { - mStatus.set(mDft.failureIndex(id)+1); + mStatus.set(mStateGenerationInfo.getStateIndex(id)+1); } template void DFTState::setDontCare(size_t id) { - mStatus.setFromInt(mDft.failureIndex(id), 2, static_cast(DFTElementState::DontCare) ); + mStatus.setFromInt(mStateGenerationInfo.getStateIndex(id), 2, static_cast(DFTElementState::DontCare) ); } template void DFTState::setDependencySuccessful(size_t id) { // No distinction between successful dependency and no dependency at all - // -> we do not set bit - //mStatus.set(mDft.failureIndex(id)); + // => we do not set bit + //mStatus.set(mStateGenerationInfo.mIdToStateIndex(id)); } template void DFTState::setDependencyUnsuccessful(size_t id) { - mStatus.set(mDft.failureIndex(id)+1); + mStatus.set(mStateGenerationInfo.getStateIndex(id)+1); } template @@ -157,8 +172,7 @@ namespace storm { template void DFTState::activate(size_t repr) { - std::vector const& module = mDft.module(repr); - for(size_t elem : module) { + for(size_t elem : mDft.module(repr)) { if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { mIsCurrentlyFailableBE.push_back(elem); } @@ -174,16 +188,26 @@ namespace storm { assert(mDft.getElement(id)->isSpareGate()); return (std::find(mInactiveSpares.begin(), mInactiveSpares.end(), id) == mInactiveSpares.end()); } + + template + void DFTState::propagateActivation(size_t representativeId) { + activate(representativeId); + for(size_t id : mDft.module(representativeId)) { + if(mDft.getElement(id)->isSpareGate()) { + propagateActivation(uses(id)); + } + } + } template uint_fast64_t DFTState::uses(size_t id) const { - return extractUses(mDft.usageIndex(id)); + return extractUses(mStateGenerationInfo.getSpareUsageIndex(id)); } template uint_fast64_t DFTState::extractUses(size_t from) const { - assert(mDft.usageInfoBits() < 64); - return mStatus.getAsInt(from, mDft.usageInfoBits()); + assert(mStateGenerationInfo.usageInfoBits() < 64); + return mStatus.getAsInt(from, mStateGenerationInfo.usageInfoBits()); } template @@ -192,13 +216,13 @@ namespace storm { } template - void DFTState::setUsesAtPosition(size_t usageIndex, size_t child) { - mStatus.setFromInt(usageIndex, mDft.usageInfoBits(), child); + void DFTState::setUses(size_t spareId, size_t child) { + mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), child); mUsedRepresentants.push_back(child); } template - bool DFTState::claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector>> const& children) { + bool DFTState::claimNew(size_t spareId, size_t currentlyUses, std::vector>> const& children) { auto it = children.begin(); while ((*it)->id() != currentlyUses) { assert(it != children.end()); @@ -208,9 +232,9 @@ namespace storm { while(it != children.end()) { size_t childId = (*it)->id(); if(!hasFailed(childId) && !isUsed(childId)) { - setUsesAtPosition(usageIndex, childId); + setUses(spareId, childId); if(isActiveSpare(spareId)) { - mDft.propagateActivation(*this, childId); + propagateActivation(childId); } return true; } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 450953bd7..fcbcdc62d 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -17,6 +17,7 @@ namespace storm { class DFTBE; template class DFTElement; + class DFTStateGenerationInfo; template class DFTState { @@ -31,9 +32,10 @@ namespace storm { std::vector mUsedRepresentants; bool mValid = true; const DFT& mDft; + const DFTStateGenerationInfo& mStateGenerationInfo; public: - DFTState(DFT const& dft, size_t id); + DFTState(DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id); DFTElementState getElementState(size_t id) const; @@ -75,6 +77,8 @@ namespace storm { bool isActiveSpare(size_t id) const; + void propagateActivation(size_t representativeId); + void markAsInvalid() { mValid = false; } @@ -109,13 +113,13 @@ namespace storm { bool isUsed(size_t child) const; /** - * Sets to to the usageIndex which child is now used. - * @param usageIndex - * @param child + * Sets for the spare which child is now used. + * @param spareId Id of the spare + * @param child Id of the child which is now used */ - void setUsesAtPosition(size_t usageIndex, size_t child); + void setUses(size_t spareId, size_t child); - bool claimNew(size_t spareId, size_t usageIndex, size_t currentlyUses, std::vector>> const& children); + bool claimNew(size_t spareId, size_t currentlyUses, std::vector>> const& children); bool hasOutgoingEdges() const { return !mIsCurrentlyFailableBE.empty(); From a89a728f6d41e7cea80e77301e53da901adffe8d Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 18 Feb 2016 23:28:35 +0100 Subject: [PATCH 127/246] Moved benchmark script to SVN Former-commit-id: 92c39188e787522038ae542a6782c7d54762b657 --- benchmark_dft.py | 136 ----------------------------------------------- 1 file changed, 136 deletions(-) delete mode 100644 benchmark_dft.py diff --git a/benchmark_dft.py b/benchmark_dft.py deleted file mode 100644 index 6f25e08ed..000000000 --- a/benchmark_dft.py +++ /dev/null @@ -1,136 +0,0 @@ -import os -import os.path -import sys -import subprocess -import re -import time -import argparse - -DIR=os.getcwd() -STORM_PATH=os.path.join(DIR, "build/src/storm-dft") -EXAMPLE_DIR=os.path.join(DIR, "examples/dft/") - -benchmarks = [ - ("and", False, [3, 1]), - ("and_param", True, ["(4*x^2+2*x+1)/((x) * (2*x+1))", "1"]), - ("cardiac", False, [8597.360004, 1]), - ("cas", False, [0.859736, 1]), - ("cm2", False, [0.256272, 1]), - #("cm4", False, [0.338225, 1]), # big - ("cps", False, ["inf", 0.333333]), - #("deathegg", False, [24.642857, 1]), # contains fdep to gate - #("fdep", False, [0.666667, 1]), # contains fdep to two elements - ("fdep2", False, [2, 1]), - ("fdep3", False, [2.5, 1]), - #("ftpp_complex", False, [0, 1]), # Compute - #("ftpp_large", False, [0, 1]), # Compute - #("ftpp_standard", False, [0, 1]), # Compute - ("mdcs", False, [2.85414, 1]), - ("mdcs2", False, [2.85414, 1]), - ("mp", False, [1.66667, 1]), - ("or", False, [1, 1]), - ("pand", False, ["inf", 0.666667]), - ("pand_param", True, ["-1", "(x)/(y+x)"]), - ("pdep", False, [2.66667, 1]), - #("pdep2", False, [0, 1]), #Compute # contains pdep to two elements - ("pdep3", False, [2.79167, 1]), - ("spare", False, [3.53846, 1]), - ("spare2", False, [1.86957, 1]), - ("spare3", False, [1.27273, 1]), - ("spare4", False, [4.8459, 1]), - ("spare5", False, [2.66667, 1]), - ("spare6", False, [1.4, 1]), - ("spare7", False, [3.67333, 1]), - ("symmetry", False, [4.16667, 1]), - ("symmetry2", False, [3.06111, 1]), - ("tripple_and1", False, [4.16667, 1]), - ("tripple_and2", False, [3.66667, 1]), - ("tripple_and2_c", False, [3.6667, 1]), - ("tripple_and_c", False, [4.16667, 1]), - ("tripple_or", False, [0.5, 1]), - ("tripple_or2", False, [0.666667, 1]), - ("tripple_or2_c", False, [0.66667, 1]), - ("tripple_or_c", False, [0.5, 1]), - ("tripple_pand", False, ["inf", 0.0416667]), - ("tripple_pand2", False, ["inf", 0.166667]), - ("tripple_pand2_c", False, ["inf", 0.166667]), - ("tripple_pand_c", False, ["inf", 0.0416667]), - ("voting", False, [1.66667, 1]), - ("voting2", False, [0.588235, 1]) -] - -def run_storm_dft(filename, prop, parametric, quiet): - # Run storm-dft on filename and return result - dft_file = os.path.join(EXAMPLE_DIR, filename + ".dft") - args = [STORM_PATH, - dft_file, - prop] - if parametric: - args.append('--parametric') - - output = run_tool(args, quiet) - # Get result - match = re.search(r'Result: \[(.*)\]', output) - if not match: - return None - - result = match.group(1) - return result - -def run_tool(args, quiet=False): - """ - Executes a process, - :returns: the `stdout` - """ - pipe = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - result = ""; - for line in iter(pipe.stdout.readline, ""): - if not line and pipe.poll() is not None: - break - output = line.decode(encoding='UTF-8').rstrip() - if output != "": - if not quiet: - print("\t * " + output) - result = output - return result - -def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): - if a == b: - return True - return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Benchmarking DFTs via Storm') - parser.add_argument('--debuglevel', type=int, default=0, help='the debug level (0=silent, 1=print benchmarks, 2=print output from storm') - args = parser.parse_args() - count = 0 - correct = 0 - properties = ['--expectedtime', '--probability'] - start = time.time() - for index, prop in enumerate(properties): - for (benchmark, parametric, result_original) in benchmarks: - expected_result = result_original[index] - # Run benchmark and check result - count += 1; - if args.debuglevel > 0: - print("Running '{}' with property '{}'".format(benchmark, prop)) - result = run_storm_dft(benchmark, prop, parametric, args.debuglevel<2) - if result is None: - print("Error occurred on example '{}' with property '{}'".format(benchmark, prop)) - continue - - if not parametric: - # Float - result = float(result) - if not isclose(result, float(expected_result), rel_tol=1e-05): - print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result)) - else: - correct += 1 - else: - # Parametric - if result != expected_result: - print("Wrong result on example '{}' with property '{}': result: {}, Expected: {}".format(benchmark, prop, result, expected_result)) - else: - correct += 1 - end = time.time() - print("Correct results for {} of {} DFT checks in {}s".format(correct, count, end-start)) From 689acfa28b80fcf9933d99ccc05931ace6b51412 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 09:29:22 +0100 Subject: [PATCH 128/246] Removed debug assertions Former-commit-id: a25b569e58427e70dd1054a9c4583850c998897e --- src/storage/dft/DFT.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 36733eb51..c53f711e4 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -13,13 +13,9 @@ namespace storm { template DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mTopLevelIndex(tle->id()) { assert(elementIndicesCorrect()); - size_t stateVectorIndex = 0; - std::set tmpRepresentatives; - size_t usageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; size_t nrRepresentatives = 0; for (auto& elem : mElements) { - stateVectorIndex += 2; if (isRepresentative(elem->id())) { ++nrRepresentatives; } @@ -30,7 +26,6 @@ namespace storm { ++mNrOfSpares; bool firstChild = true; for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { - tmpRepresentatives.insert(spareReprs->id()); std::set module = {spareReprs->id()}; spareReprs->extendSpareModule(module); std::vector sparesAndBes; @@ -46,14 +41,12 @@ namespace storm { mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); firstChild = false; } - stateVectorIndex += usageInfoBits; } else if (elem->isDependency()) { mDependencies.push_back(elem->id()); } } - stateVectorIndex += tmpRepresentatives.size(); - + // For the top module, we assume, contrary to [Jun15], that we have all spare gates and basic elements which are not in another module. std::set topModuleSet; // Initialize with all ids. @@ -70,11 +63,8 @@ namespace storm { } mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); - std::cout << tmpRepresentatives.size() << ", " << nrRepresentatives << std::endl; - std::cout << stateVectorIndex << ", " << (nrElements() * 2 + mNrOfSpares * usageInfoBits + tmpRepresentatives.size()) << std::endl; - assert(tmpRepresentatives.size() == nrRepresentatives); - assert(stateVectorIndex == nrElements() * 2 + mNrOfSpares * usageInfoBits + tmpRepresentatives.size()); - mStateVectorSize = stateVectorIndex; + size_t usageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; + mStateVectorSize = nrElements() * 2 + mNrOfSpares * usageInfoBits + nrRepresentatives; } template From b8ff542b7b9ada840b2b9f55ee656cb5b218fcaf Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 09:47:03 +0100 Subject: [PATCH 129/246] One conversion less for MA Former-commit-id: d0b47adf9ba64252bb0c3418d7a4df84f5f9abf2 --- src/builder/ExplicitDFTModelBuilder.cpp | 24 ++++++++++++------------ src/models/sparse/MarkovAutomaton.cpp | 13 +++++++++++++ src/models/sparse/MarkovAutomaton.h | 19 +++++++++++++++++++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 91a16f2d2..a7284cb9c 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -114,22 +114,22 @@ namespace storm { } std::shared_ptr> model; - // Turn the probabilities into rates by multiplying each row with the exit rate of the state. - // TODO Matthias: avoid transforming back and forth - storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); - for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { - assert(row < modelComponents.markovianStates.size()); - if (modelComponents.markovianStates.get(row)) { - for (auto& entry : rateMatrix.getRow(row)) { - entry.setValue(entry.getValue() * modelComponents.exitRates[row]); - } - } - } if (deterministic) { + // Turn the probabilities into rates by multiplying each row with the exit rate of the state. + // TODO Matthias: avoid transforming back and forth + storm::storage::SparseMatrix rateMatrix(modelComponents.transitionMatrix); + for (uint_fast64_t row = 0; row < rateMatrix.getRowCount(); ++row) { + assert(row < modelComponents.markovianStates.size()); + if (modelComponents.markovianStates.get(row)) { + for (auto& entry : rateMatrix.getRow(row)) { + entry.setValue(entry.getValue() * modelComponents.exitRates[row]); + } + } + } model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling)); } else { - model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates)); + model = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates), true); } model->printModelInformationToStream(std::cout); diff --git a/src/models/sparse/MarkovAutomaton.cpp b/src/models/sparse/MarkovAutomaton.cpp index c757af1a0..8276f519d 100644 --- a/src/models/sparse/MarkovAutomaton.cpp +++ b/src/models/sparse/MarkovAutomaton.cpp @@ -34,6 +34,19 @@ namespace storm { this->turnRatesToProbabilities(); } + template + MarkovAutomaton::MarkovAutomaton(storm::storage::SparseMatrix&& transitionMatrix, + storm::models::sparse::StateLabeling&& stateLabeling, + storm::storage::BitVector const& markovianStates, + std::vector const& exitRates, + bool probabilities, + std::unordered_map&& rewardModels, + boost::optional>&& optionalChoiceLabeling) + : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), markovianStates(markovianStates), exitRates(std::move(exitRates)), closed(false) { + assert(probabilities); + assert(this->getTransitionMatrix().isProbabilistic()); + } + template bool MarkovAutomaton::isClosed() const { return closed; diff --git a/src/models/sparse/MarkovAutomaton.h b/src/models/sparse/MarkovAutomaton.h index ed807ab84..e335f5050 100644 --- a/src/models/sparse/MarkovAutomaton.h +++ b/src/models/sparse/MarkovAutomaton.h @@ -49,6 +49,25 @@ namespace storm { std::unordered_map&& rewardModels = std::unordered_map(), boost::optional>&& optionalChoiceLabeling = boost::optional>()); + /*! + * Constructs a model by moving the given data. + * + * @param transitionMatrix The matrix representing the transitions in the model in terms of rates. + * @param stateLabeling The labeling of the states. + * @param markovianStates A bit vector indicating the Markovian states of the automaton. + * @param exitRates A vector storing the exit rates of the states. + * @param rewardModels A mapping of reward model names to reward models. + * @param optionalChoiceLabeling A vector that represents the labels associated with the choices of each state. + * @param probabilities Flag if transitions matrix contains probabilities or rates + */ + MarkovAutomaton(storm::storage::SparseMatrix&& transitionMatrix, + storm::models::sparse::StateLabeling&& stateLabeling, + storm::storage::BitVector const& markovianStates, + std::vector const& exitRates, + bool probabilities, + std::unordered_map&& rewardModels = std::unordered_map(), + boost::optional>&& optionalChoiceLabeling = boost::optional>()); + MarkovAutomaton(MarkovAutomaton const& other) = default; MarkovAutomaton& operator=(MarkovAutomaton const& other) = default; From 99c87182e4f2da4f1b341bc3628cc9a2ef70904f Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 11:10:06 +0100 Subject: [PATCH 130/246] Fixed missing include for gcc Former-commit-id: 3cf040d87ccef51985901d4f1104dc04ac944655 --- src/solver/AbstractEquationSolver.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/AbstractEquationSolver.h b/src/solver/AbstractEquationSolver.h index 904e459bd..491570637 100644 --- a/src/solver/AbstractEquationSolver.h +++ b/src/solver/AbstractEquationSolver.h @@ -2,6 +2,7 @@ #define STORM_SOLVER_ABSTRACTEQUATIONSOLVER_H_ #include "src/solver/TerminationCondition.h" +#include namespace storm { namespace solver { @@ -50,4 +51,4 @@ namespace storm { } } -#endif /* STORM_SOLVER_ABSTRACTEQUATIONSOLVER_H_ */ \ No newline at end of file +#endif /* STORM_SOLVER_ABSTRACTEQUATIONSOLVER_H_ */ From 3f70a69d6e453f77094cb4ec0e00cdf6b8174a23 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 11:15:17 +0100 Subject: [PATCH 131/246] Added argument for timebound Former-commit-id: 22a83eae6eaf0630e87a483dbaf180a445687a7a --- src/storm-dyftee.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 49b573f33..fa4047dd6 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -6,6 +6,8 @@ #include "utility/storm.h" #include "storage/dft/DFTIsomorphism.h" +#include + /*! * Load DFT from filename, build corresponding Model and check against given property. * @@ -74,6 +76,20 @@ int main(int argc, char** argv) { } else if (option == "--probability") { assert(pctlFormula.empty()); pctlFormula = "P=? [F \"failed\"]"; + } else if (option == "--timebound") { + assert(pctlFormula.empty()); + ++i; + assert(i < argc); + double timeBound; + try { + timeBound = boost::lexical_cast(argv[i]); + } catch (boost::bad_lexical_cast e) { + std::cerr << "The time bound '" << argv[i] << "' is not valid." << std::endl; + return 2; + } + std::stringstream stream; + stream << "P=? [F<=" << timeBound << " \"failed\"]"; + pctlFormula = stream.str(); } else if (option == "--trace") { level = log4cplus::TRACE_LOG_LEVEL; } else if (option == "--debug") { From e12ac3624902fe969fd3b18bfc06bee02f665e7a Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 11:41:34 +0100 Subject: [PATCH 132/246] Fixed problem with usageInfoBits for only one element Former-commit-id: ac52fff2d7808a2e952252aee3c5f0da88086643 --- src/storage/dft/DFT.cpp | 2 +- src/storage/dft/DFT.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c53f711e4..654fb269e 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -63,7 +63,7 @@ namespace storm { } mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); - size_t usageInfoBits = storm::utility::math::uint64_log2(mElements.size()-1)+1; + size_t usageInfoBits = mElements.size() > 1 ? storm::utility::math::uint64_log2(mElements.size()-1) + 1 : 1; mStateVectorSize = nrElements() * 2 + mNrOfSpares * usageInfoBits + nrRepresentatives; } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 07403fd33..0cedfbfa7 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -43,7 +43,7 @@ namespace storm { public: - DFTStateGenerationInfo(size_t nrElements) : mUsageInfoBits(storm::utility::math::uint64_log2(nrElements-1)+1), mIdToStateIndex(nrElements) { + DFTStateGenerationInfo(size_t nrElements) : mUsageInfoBits(nrElements > 1 ? storm::utility::math::uint64_log2(nrElements-1) + 1 : 1), mIdToStateIndex(nrElements) { } size_t usageInfoBits() const { From 20242e10e50e599da04e689e477628f1f10ce291 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 13:08:37 +0100 Subject: [PATCH 133/246] Small fix Former-commit-id: d702592ab208db0e618a599af680b27e1e71f556 --- src/storm-dyftee.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index fa4047dd6..7b7cea029 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -25,8 +25,8 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) if(symred) { std::cout << dft.getElementsString() << std::endl; auto colouring = dft.colourDFT(); - auto res = dft.findSymmetries(colouring); - std::cout << res; + storm::storage::DFTIndependentSymmetries symmetries = dft.findSymmetries(colouring); + std::cout << symmetries; } // Building Markov Automaton From c25889bc3ee94876c329eafb26fcdcb0e61179ed Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 19 Feb 2016 13:57:38 +0100 Subject: [PATCH 134/246] minor Former-commit-id: 1a746c86f203a21c3b613850c556af7a28f56cf6 --- src/storage/dft/DFT.cpp | 10 ++++++++++ src/storage/dft/DFT.h | 1 + src/storage/dft/DFTElements.h | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index d56166f60..a52cf8984 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -172,11 +172,21 @@ namespace storm { return ISD; } + template + std::vector DFT::immediateFailureCauses(size_t index) const { + if(isGate(index)) { + + } else { + return {index}; + } + } + template DFTColouring DFT::colourDFT() const { return DFTColouring(*this); } + template DFTIndependentSymmetries DFT::findSymmetries(DFTColouring const& colouring) const { std::vector vec; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 1583cc8d5..61f286619 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -232,6 +232,7 @@ namespace storm { DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; + std::vector immediateFailureCauses(size_t index) const; private: std::pair, std::vector> getSortedParentAndOutDepIds(size_t index) const; diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index c352bd38e..1a3c5b512 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -173,6 +173,8 @@ namespace storm { } virtual void extendSpareModule(std::set& elementsInModule) const; + + // virtual void extendImmediateFailureCausePathEvents(std::set& ) const; virtual size_t nrChildren() const = 0; From 102602dea251e76a5247c367401717030718752e Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 19 Feb 2016 15:29:27 +0100 Subject: [PATCH 135/246] some refactoring Former-commit-id: 90be99f04d7736718e19986a2d02d9815813e889 --- src/builder/ExplicitDFTModelBuilder.cpp | 29 ++++++++++++++++++------- src/builder/ExplicitDFTModelBuilder.h | 10 ++++++++- src/storm-dyftee.cpp | 3 ++- src/utility/storm.h | 21 ++++++++++-------- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index a7284cb9c..08b6f4026 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -56,7 +56,7 @@ namespace storm { template - std::shared_ptr> ExplicitDFTModelBuilder::buildModel() { + std::shared_ptr> ExplicitDFTModelBuilder::buildModel(LabelOptions const& labelOpts) { // Initialize DFTStatePointer state = std::make_shared>(mDft, *mStateGenerationInfo, newIndex++); mStates.findOrAdd(state->status(), state); @@ -89,25 +89,32 @@ namespace storm { modelComponents.stateLabeling.addLabel("init"); modelComponents.stateLabeling.addLabelToState("init", 0); // Label all states corresponding to their status (failed, failsafe, failed BE) - modelComponents.stateLabeling.addLabel("failed"); - modelComponents.stateLabeling.addLabel("failsafe"); + if(labelOpts.buildFailLabel) { + modelComponents.stateLabeling.addLabel("failed"); + } + if(labelOpts.buildFailSafeLabel) { + modelComponents.stateLabeling.addLabel("failsafe"); + } + // Collect labels for all BE std::vector>> basicElements = mDft.getBasicElements(); for (std::shared_ptr> elem : basicElements) { - modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); + if(labelOpts.beLabels.count(elem->name()) > 0) { + modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); + } } for (auto const& stateVectorPair : mStates) { DFTStatePointer state = stateVectorPair.second; - if (mDft.hasFailed(state)) { + if (labelOpts.buildFailLabel && mDft.hasFailed(state)) { modelComponents.stateLabeling.addLabelToState("failed", state->getId()); } - if (mDft.isFailsafe(state)) { + if (labelOpts.buildFailSafeLabel && mDft.isFailsafe(state)) { modelComponents.stateLabeling.addLabelToState("failsafe", state->getId()); }; // Set fail status for each BE for (std::shared_ptr> elem : basicElements) { - if (state->hasFailed(elem->id())) { + if (labelOpts.beLabels.count(elem->name()) > 0 && state->hasFailed(elem->id()) ) { modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", state->getId()); } } @@ -129,7 +136,13 @@ namespace storm { } model = std::make_shared>(std::move(rateMatrix), std::move(modelComponents.stateLabeling)); } else { - model = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates), true); + std::shared_ptr> ma = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates), true); + if (ma->hasOnlyTrivialNondeterminism()) { + // Markov automaton can be converted into CTMC + model = ma->convertToCTMC(); + } else { + model = ma; + } } model->printModelInformationToStream(std::cout); diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index eacf2568c..40e0c2a8c 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -44,15 +44,23 @@ namespace storm { boost::optional>> choiceLabeling; }; + + storm::storage::DFT const& mDft; std::shared_ptr mStateGenerationInfo; storm::storage::BitVectorHashMap mStates; size_t newIndex = 0; public: + struct LabelOptions { + bool buildFailLabel = true; + bool buildFailSafeLabel = false; + std::set beLabels = {}; + }; + ExplicitDFTModelBuilder(storm::storage::DFT const& dft); - std::shared_ptr> buildModel(); + std::shared_ptr> buildModel(LabelOptions const& labelOpts); private: bool exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 7b7cea029..805ef7570 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -32,7 +32,8 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) // Building Markov Automaton std::cout << "Building Model..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft); - std::shared_ptr> model = builder.buildModel(); + typename storm::builder::ExplicitDFTModelBuilder::LabelOptions labeloptions; // TODO initialize this with the formula + std::shared_ptr> model = builder.buildModel(labeloptions); std::cout << "Built Model" << std::endl; // Model checking diff --git a/src/utility/storm.h b/src/utility/storm.h index f737b318e..5d02405fa 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -196,6 +196,15 @@ namespace storm { template std::shared_ptr preprocessModel(std::shared_ptr model, std::vector> const& formulas) { + if(model->getType() == storm::models::ModelType::MarkovAutomaton && model->isSparseModel()) { + std::shared_ptr> ma = model->template as>(); + if (ma->hasOnlyTrivialNondeterminism()) { + // Markov automaton can be converted into CTMC + model = ma->convertToCTMC(); + + } + } + if (model->isSparseModel() && storm::settings::generalSettings().isBisimulationSet()) { storm::storage::BisimulationType bisimType = storm::storage::BisimulationType::Strong; if (storm::settings::bisimulationSettings().isWeakBisimulationSet()) { @@ -205,6 +214,7 @@ namespace storm { STORM_LOG_THROW(model->isSparseModel(), storm::exceptions::InvalidSettingsException, "Bisimulation minimization is currently only available for sparse models."); return performBisimulationMinimization(model->template as>(), formulas, bisimType); } + return model; } @@ -302,15 +312,8 @@ namespace storm { result = modelchecker.check(task); } else if (model->getType() == storm::models::ModelType::MarkovAutomaton) { std::shared_ptr> ma = model->template as>(); - if (ma->hasOnlyTrivialNondeterminism()) { - // Markov automaton can be converted into CTMC - std::shared_ptr> ctmc = ma->convertToCTMC(); - storm::modelchecker::SparseCtmcCslModelChecker> modelchecker(*ctmc); - result = modelchecker.check(task); - } else { - storm::modelchecker::SparseMarkovAutomatonCslModelChecker> modelchecker(*ma); - result = modelchecker.check(task); - } + storm::modelchecker::SparseMarkovAutomatonCslModelChecker> modelchecker(*ma); + result = modelchecker.check(task); } else { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The model type " << model->getType() << " is not supported."); } From d160bb1b134784612d0d6a1508102c803a3bcff4 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 15:47:16 +0100 Subject: [PATCH 136/246] Use only state ids instead of complete data structure Former-commit-id: 0852cce6d7ba5e7c6b35630ffdb2631cecf64534 --- src/builder/ExplicitDFTModelBuilder.cpp | 65 +++++++++++++------------ src/builder/ExplicitDFTModelBuilder.h | 4 +- src/storage/BitVectorHashMap.cpp | 8 +-- src/storage/dft/DFT.cpp | 1 + src/storage/dft/DFT.h | 8 +++ src/storage/dft/DFTState.cpp | 10 ++++ src/storage/dft/DFTState.h | 8 ++- 7 files changed, 62 insertions(+), 42 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index a7284cb9c..2d466dec8 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -15,14 +15,13 @@ namespace storm { } template - ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, std::pow(2, mDft.nrBasicElements())) { - // stateSize is bound for size of bitvector - // 2^nrBE is upper bound for state space + ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, INITIAL_BUCKETSIZE) { + // stateVectorSize is bound for size of bitvector // Find symmetries // TODO activate // Currently using hack to test - std::vector> symmetries; + std::vector> symmetriesTmp; std::vector vecB; std::vector vecC; std::vector vecD; @@ -38,11 +37,11 @@ namespace storm { vecD.push_back(id); } } - symmetries.push_back(vecB); - symmetries.push_back(vecC); - symmetries.push_back(vecD); + symmetriesTmp.push_back(vecB); + symmetriesTmp.push_back(vecC); + symmetriesTmp.push_back(vecD); std::cout << "Found the following symmetries:" << std::endl; - for (auto const& symmetry : symmetries) { + for (auto const& symmetry : symmetriesTmp) { for (auto const& elem : symmetry) { std::cout << elem << " -> "; } @@ -51,7 +50,7 @@ namespace storm { } else { vecB.push_back(mDft.getTopLevelIndex()); } - mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(vecB, symmetries)); + mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(vecB, symmetriesTmp)); } @@ -59,7 +58,7 @@ namespace storm { std::shared_ptr> ExplicitDFTModelBuilder::buildModel() { // Initialize DFTStatePointer state = std::make_shared>(mDft, *mStateGenerationInfo, newIndex++); - mStates.findOrAdd(state->status(), state); + mStates.findOrAdd(state->status(), state->getId()); std::queue stateQueue; stateQueue.push(state); @@ -97,18 +96,19 @@ namespace storm { modelComponents.stateLabeling.addLabel(elem->name() + "_fail"); } - for (auto const& stateVectorPair : mStates) { - DFTStatePointer state = stateVectorPair.second; - if (mDft.hasFailed(state)) { - modelComponents.stateLabeling.addLabelToState("failed", state->getId()); + for (auto const& stateIdPair : mStates) { + storm::storage::BitVector state = stateIdPair.first; + size_t stateId = stateIdPair.second; + if (mDft.hasFailed(state, *mStateGenerationInfo)) { + modelComponents.stateLabeling.addLabelToState("failed", stateId); } - if (mDft.isFailsafe(state)) { - modelComponents.stateLabeling.addLabelToState("failsafe", state->getId()); + if (mDft.isFailsafe(state, *mStateGenerationInfo)) { + modelComponents.stateLabeling.addLabelToState("failsafe", stateId); }; // Set fail status for each BE for (std::shared_ptr> elem : basicElements) { - if (state->hasFailed(elem->id())) { - modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", state->getId()); + if (storm::storage::DFTState::hasFailed(state, mStateGenerationInfo->getStateIndex(elem->id()))) { + modelComponents.stateLabeling.addLabelToState(elem->name() + "_fail", stateId); } } } @@ -213,15 +213,16 @@ namespace storm { // Update failable dependencies newState->updateFailableDependencies(nextBE->id()); - + + size_t newStateId; if (mStates.contains(newState->status())) { // State already exists - newState = mStates.findOrAdd(newState->status(), newState); + newStateId = mStates.getValue(newState->status()); STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " already exists"); } else { // New state newState->setId(newIndex++); - mStates.findOrAdd(newState->status(), newState); + newStateId = mStates.findOrAdd(newState->status(), newState->getId()); STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); // Add state to search queue @@ -232,22 +233,22 @@ namespace storm { if (hasDependencies) { // Failure is due to dependency -> add non-deterministic choice std::shared_ptr const> dependency = mDft.getDependency(state->getDependencyId(smallest-1)); - transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, newState->getId(), dependency->probability()); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with probability " << dependency->probability()); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, newStateId, dependency->probability()); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newStateId << " with probability " << dependency->probability()); if (!storm::utility::isOne(dependency->probability())) { // Add transition to state where dependency was unsuccessful DFTStatePointer unsuccessfulState = std::make_shared>(*state); unsuccessfulState->letDependencyBeUnsuccessful(smallest-1); - + size_t unsuccessfulStateId; if (mStates.contains(unsuccessfulState->status())) { // Unsuccessful state already exists - unsuccessfulState = mStates.findOrAdd(unsuccessfulState->status(), unsuccessfulState); + unsuccessfulStateId = mStates.getValue(unsuccessfulState->status()); STORM_LOG_TRACE("State " << mDft.getStateString(unsuccessfulState) << " already exists"); } else { // New unsuccessful state unsuccessfulState->setId(newIndex++); - mStates.findOrAdd(unsuccessfulState->status(), unsuccessfulState); + unsuccessfulStateId = mStates.findOrAdd(unsuccessfulState->status(), unsuccessfulState->getId()); STORM_LOG_TRACE("New state " << mDft.getStateString(unsuccessfulState)); // Add unsuccessful state to search queue @@ -255,11 +256,11 @@ namespace storm { } ValueType remainingProbability = storm::utility::one() - dependency->probability(); - transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, unsuccessfulState->getId(), remainingProbability); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << unsuccessfulState->getId() << " with probability " << remainingProbability); + transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, unsuccessfulStateId, remainingProbability); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << unsuccessfulStateId << " with probability " << remainingProbability); } else { // Self-loop with probability one cannot be eliminated later one. - assert(state->getId() != newState->getId()); + assert(state->getId() != newStateId); } ++rowOffset; @@ -274,15 +275,15 @@ namespace storm { } STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); - auto resultFind = outgoingTransitions.find(newState->getId()); + auto resultFind = outgoingTransitions.find(newStateId); if (resultFind != outgoingTransitions.end()) { // Add to existing transition resultFind->second += rate; STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with rate " << rate << " to new rate " << resultFind->second); } else { // Insert new transition - outgoingTransitions.insert(std::make_pair(newState->getId(), rate)); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newState->getId() << " with rate " << rate); + outgoingTransitions.insert(std::make_pair(newStateId, rate)); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newStateId << " with rate " << rate); } exitRate += rate; } diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index eacf2568c..322790aa4 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -43,10 +43,12 @@ namespace storm { // A vector that stores a labeling for each choice. boost::optional>> choiceLabeling; }; + + const size_t INITIAL_BUCKETSIZE = 20000; storm::storage::DFT const& mDft; std::shared_ptr mStateGenerationInfo; - storm::storage::BitVectorHashMap mStates; + storm::storage::BitVectorHashMap mStates; size_t newIndex = 0; public: diff --git a/src/storage/BitVectorHashMap.cpp b/src/storage/BitVectorHashMap.cpp index be0e32325..4d6238350 100644 --- a/src/storage/BitVectorHashMap.cpp +++ b/src/storage/BitVectorHashMap.cpp @@ -4,9 +4,6 @@ #include "src/utility/macros.h" -#include "src/storage/dft/DFTState.h" -#include "src/adapters/CarlAdapter.h" - namespace storm { namespace storage { template @@ -243,9 +240,6 @@ namespace storm { template class BitVectorHashMap; template class BitVectorHashMap; - template class BitVectorHashMap>>; -#ifdef STORM_HAVE_CARL - template class BitVectorHashMap>>; -#endif + template class BitVectorHashMap; } } diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 654fb269e..522173d81 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -204,6 +204,7 @@ namespace storm { return stream.str(); } + // TODO rewrite to only use bitvector and id template std::string DFT::getStateString(DFTStatePointer const& state) const{ std::stringstream stream; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 0cedfbfa7..2ee1a2edf 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -244,10 +244,18 @@ namespace storm { return state->hasFailed(mTopLevelIndex); } + bool hasFailed(storm::storage::BitVector const& state, DFTStateGenerationInfo const& stateGenerationInfo) const { + return storm::storage::DFTState::hasFailed(state, stateGenerationInfo.getStateIndex(mTopLevelIndex)); + } + bool isFailsafe(DFTStatePointer const& state) const { return state->isFailsafe(mTopLevelIndex); } + bool isFailsafe(storm::storage::BitVector const& state, DFTStateGenerationInfo const& stateGenerationInfo) const { + return storm::storage::DFTState::isFailsafe(state, stateGenerationInfo.getStateIndex(mTopLevelIndex)); + } + std::string getElementsString() const; std::string getInfoString() const; diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index c3f7c9f32..0bad03f78 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -63,11 +63,21 @@ namespace storm { bool DFTState::hasFailed(size_t id) const { return mStatus[mStateGenerationInfo.getStateIndex(id)]; } + + template + bool DFTState::hasFailed(storm::storage::BitVector const& state, size_t indexId) { + return state[indexId]; + } template bool DFTState::isFailsafe(size_t id) const { return mStatus[mStateGenerationInfo.getStateIndex(id)+1]; } + + template + bool DFTState::isFailsafe(storm::storage::BitVector const& state, size_t indexId) { + return state[indexId+1]; + } template bool DFTState::dontCare(size_t id) const { diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index fcbcdc62d..821aa2fcb 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -51,10 +51,14 @@ namespace storm { bool hasFailed(size_t id) const; - bool isFailsafe(size_t id) const ; + static bool hasFailed(storm::storage::BitVector const& state, size_t indexId); + bool isFailsafe(size_t id) const; + + static bool isFailsafe(storm::storage::BitVector const& state, size_t indexId); + bool dontCare(size_t id) const; - + bool dependencyTriggered(size_t id) const; bool dependencySuccessful(size_t id) const; From 2754450f91d26079332baed8d89d1d98cc0b3e90 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 15:47:57 +0100 Subject: [PATCH 137/246] Refactored DFS search into own method Former-commit-id: 3efbcf062f6928f318d91347f3d2eb1eb9946049 --- src/storage/dft/DFT.cpp | 74 ++++++++++++++++++++++------------------- src/storage/dft/DFT.h | 2 ++ 2 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 522173d81..c75d96a6c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -82,43 +82,12 @@ namespace storm { visitQueue.push(subTreeRoots[0]); bool consideredDependencies = false; while (true) { - while (!visitQueue.empty()) { - size_t id = visitQueue.front(); - visitQueue.pop(); - if (visited.count(id) == 1) { - // Already visited - continue; - } - visited.insert(id); - DFTElementPointer element = mElements[id]; - - // Insert children - if (element->isGate()) { - for (auto const& child : std::static_pointer_cast>(element)->children()) { - visitQueue.push(child->id()); - } - } - - // Reserve bits for element - generationInfo.addStateIndex(id, stateIndex); - stateIndex += 2; - - if (isRepresentative(id)) { - generationInfo.addSpareActivationIndex(id, stateIndex); - ++stateIndex; - } - - if (element->isSpareGate()) { - generationInfo.addSpareUsageIndex(id, stateIndex); - stateIndex += generationInfo.usageInfoBits(); - } - - } - if (consideredDependencies) { break; } + stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); + // Consider dependencies for (size_t idDependency : getDependencies()) { std::shared_ptr const> dependency = getDependency(idDependency); @@ -134,8 +103,43 @@ namespace storm { return generationInfo; } - - + + template + size_t DFT::performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, std::set& visited, size_t stateIndex) const { + while (!visitQueue.empty()) { + size_t id = visitQueue.front(); + visitQueue.pop(); + if (visited.count(id) == 1) { + // Already visited + continue; + } + visited.insert(id); + DFTElementPointer element = mElements[id]; + + // Insert children + if (element->isGate()) { + for (auto const& child : std::static_pointer_cast>(element)->children()) { + visitQueue.push(child->id()); + } + } + + // Reserve bits for element + generationInfo.addStateIndex(id, stateIndex); + stateIndex += 2; + + if (isRepresentative(id)) { + generationInfo.addSpareActivationIndex(id, stateIndex); + ++stateIndex; + } + + if (element->isSpareGate()) { + generationInfo.addSpareUsageIndex(id, stateIndex); + stateIndex += generationInfo.usageInfoBits(); + } + + } + return stateIndex; + } template std::string DFT::getElementsString() const { diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 2ee1a2edf..3beacf8d9 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -127,6 +127,8 @@ namespace storm { DFTStateGenerationInfo buildStateGenerationInfo(std::vector const& subTreeRoots, std::vector> const& symmetries) const; + size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, std::set& visited, size_t stateIndex) const; + size_t stateVectorSize() const { return mStateVectorSize; } From b93f5c2f624ebb87316d191b7104badcd65dc23f Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 19 Feb 2016 16:19:36 +0100 Subject: [PATCH 138/246] refactored a bit, plus bisimulation is now done Former-commit-id: 42877cdb29c91063c626f4efd711fc8f2d1460d0 --- src/builder/ExplicitDFTModelBuilder.cpp | 1 - src/storm-dyftee.cpp | 23 ++++++++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index c6d59d6cb..cbb9b69d0 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -145,7 +145,6 @@ namespace storm { } } - model->printModelInformationToStream(std::cout); return model; } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 805ef7570..2160ed210 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -16,12 +16,19 @@ */ template void analyzeDFT(std::string filename, std::string property, bool symred = false) { + storm::settings::SettingsManager& manager = storm::settings::mutableManager(); + manager.setFromString(""); + // Parsing DFT std::cout << "Parsing DFT file..." << std::endl; storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(filename); std::cout << "Built data structure" << std::endl; - + std::cout << "Parse formula..." << std::endl; + std::vector> parsedFormulas = storm::parseFormulasForExplicit(property); + std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); + assert(formulas.size() == 1); + std::cout << "parsed formula." << std::endl; if(symred) { std::cout << dft.getElementsString() << std::endl; auto colouring = dft.colourDFT(); @@ -36,10 +43,20 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::shared_ptr> model = builder.buildModel(labeloptions); std::cout << "Built Model" << std::endl; + + model->printModelInformationToStream(std::cout); + + std::cout << "Bisimulation..." << std::endl; + + if (model->isOfType(storm::models::ModelType::Ctmc)) { + model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); + } + + + model->printModelInformationToStream(std::cout); + // Model checking std::cout << "Model checking..." << std::endl; - std::vector> formulas = storm::parseFormulasForExplicit(property); - assert(formulas.size() == 1); std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); assert(result); std::cout << "Result: "; From 0156b1276485e7acf60a74c25cc89a070b2ab6a3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 19 Feb 2016 17:36:35 +0100 Subject: [PATCH 139/246] Fixed compile problem under gcc Former-commit-id: f5d40795e99f9d40698b8787f2409f6735a1c2f8 --- src/builder/ExplicitDFTModelBuilder.h | 4 ++-- src/storage/BitVectorHashMap.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 522f2375c..a64efaddd 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -50,7 +50,7 @@ namespace storm { storm::storage::DFT const& mDft; std::shared_ptr mStateGenerationInfo; - storm::storage::BitVectorHashMap mStates; + storm::storage::BitVectorHashMap mStates; size_t newIndex = 0; public: @@ -71,4 +71,4 @@ namespace storm { } } -#endif /* EXPLICITDFTMODELBUILDER_H */ \ No newline at end of file +#endif /* EXPLICITDFTMODELBUILDER_H */ diff --git a/src/storage/BitVectorHashMap.cpp b/src/storage/BitVectorHashMap.cpp index 4d6238350..9237dfde3 100644 --- a/src/storage/BitVectorHashMap.cpp +++ b/src/storage/BitVectorHashMap.cpp @@ -240,6 +240,5 @@ namespace storm { template class BitVectorHashMap; template class BitVectorHashMap; - template class BitVectorHashMap; } } From 8755e75a60f12bc9e9cf91fd9ccbfe2367bc623c Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 19 Feb 2016 18:13:05 +0100 Subject: [PATCH 140/246] towards a new element (and actually added a folder) Former-commit-id: 0bca77dfa7b9800ef60225ca2fcc3e01d5e1e157 --- src/CMakeLists.txt | 2 + src/storage/dft/DFTElementType.h | 7 ++- src/storage/dft/DFTElements.h | 54 ----------------------- src/storage/dft/elements/DFTRestriction.h | 13 ++++++ 4 files changed, 18 insertions(+), 58 deletions(-) create mode 100644 src/storage/dft/elements/DFTRestriction.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3aa121a0a..60fbadab9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -38,6 +38,7 @@ file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SO file(GLOB STORM_STORAGE_BISIMULATION_FILES ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.h ${PROJECT_SOURCE_DIR}/src/storage/bisimulation/*.cpp) file(GLOB STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp) file(GLOB STORM_STORAGE_DFT_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/*.h ${PROJECT_SOURCE_DIR}/src/storage/dft/*.cpp) +file(GLOB STORM_STORAGE_DFT_ELEMENTS_FILES ${PROJECT_SOURCE_DIR}/src/storage/dft/elements/*.h ${PROJECT_SOURCE_DIR}/src/storage/dft/elements/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_CUDD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/cudd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/cudd/*.cpp) file(GLOB_RECURSE STORM_STORAGE_DD_SYLVAN_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/sylvan/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/sylvan/*.cpp) file(GLOB_RECURSE STORM_STORAGE_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.h ${PROJECT_SOURCE_DIR}/src/storage/expressions/*.cpp) @@ -94,6 +95,7 @@ source_group(storage\\expressions FILES ${STORM_STORAGE_EXPRESSIONS_FILES}) source_group(storage\\prism FILES ${STORM_STORAGE_PRISM_FILES}) source_group(storage\\sparse FILES ${STORM_STORAGE_SPARSE_FILES}) source_group(storage\\dft FILES ${STORM_STORAGE_DFT_FILES}) +source_group(storage\\dft\\elements FILES ${STORM_STORAGE_DFT_ELEMENTS_FILES}) source_group(utility FILES ${STORM_UTILITY_FILES}) # Add custom additional include or link directories diff --git a/src/storage/dft/DFTElementType.h b/src/storage/dft/DFTElementType.h index a32745cdf..d4bf3bfc2 100644 --- a/src/storage/dft/DFTElementType.h +++ b/src/storage/dft/DFTElementType.h @@ -4,20 +4,20 @@ namespace storm { namespace storage { - enum class DFTElementType : int {AND = 0, COUNTING = 1, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, PDEP = 10, SEQAND = 11}; + enum class DFTElementType : int {AND = 0, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, PDEP = 10, SEQ = 11, MUTEX=12}; inline bool isGateType(DFTElementType const& tp) { switch(tp) { case DFTElementType::AND: - case DFTElementType::COUNTING: case DFTElementType::OR: case DFTElementType::VOT: case DFTElementType::PAND: case DFTElementType::SPARE: case DFTElementType::POR: - case DFTElementType::SEQAND: return true; + case DFTElementType::SEQ: + case DFTElementType::MUTEX: case DFTElementType::BE: case DFTElementType::CONSTF: case DFTElementType::CONSTS: @@ -40,7 +40,6 @@ namespace storm { case DFTElementType::POR: case DFTElementType::SPARE: case DFTElementType::PAND: - case DFTElementType::SEQAND: return false; default: assert(false); diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 11fc31948..c51e180c7 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -726,60 +726,6 @@ namespace storm { - template - class DFTSeqAnd : public DFTGate { - - public: - DFTSeqAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) - {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(!state.hasFailed(this->mId)) { - bool childOperationalBefore = false; - for(auto const& child : this->mChildren) - { - if(!state.hasFailed(child->id())) { - childOperationalBefore = true; - } - else { - if(childOperationalBefore) { - state.markAsInvalid(); - return; - } - } - } - if(!childOperationalBefore) { - fail(state, queues); - } - - } - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ - assert(hasFailsafeChild(state)); - if(state.isOperational(this->mId)) { - failsafe(state, queues); - //return true; - } - //return false; - } - - virtual DFTElementType type() const override { - return DFTElementType::SEQAND; - } - - std::string typestring() const override { - return "SEQAND"; - } - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTSeqAnd const& gate) { - return os << gate.toString(); - } - - template class DFTPand : public DFTGate { diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h new file mode 100644 index 000000000..8bd586deb --- /dev/null +++ b/src/storage/dft/elements/DFTRestriction.h @@ -0,0 +1,13 @@ +#pragma once + +#include "../DFTElements.h" + +namespace storm { + namespace storage { + template + class DFTRestriction : public DFTElement { + + }; + + } +} \ No newline at end of file From 7bcbbe75faf5ea592b3253cad345517b1b3b8bc8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sun, 21 Feb 2016 15:53:14 +0100 Subject: [PATCH 141/246] Set dont care for children if parent gate fails Former-commit-id: c70852b7e85804cea30d6a27090baaa8457e4cb8 --- src/storage/dft/DFTElements.cpp | 26 ++++++++++++++++---------- src/storage/dft/DFTElements.h | 2 ++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 26f5f9cbe..e06b3fe7d 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -7,18 +7,24 @@ namespace storm { template bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(!state.dontCare(mId) && !hasOutgoingDependencies()) - { - for(DFTGatePointer const& parent : mParents) { - if(state.isOperational(parent->id())) { - return false; - } + if (state.dontCare(mId)) { + return false; + } + // Check that no outgoing dependencies can be triggered anymore + for (DFTDependencyPointer dependency : mOutgoingDependencies) { + if (state.isOperational(dependency->dependentEvent()->id()) && state.isOperational(dependency->triggerEvent()->id())) { + return false; } - state.setDontCare(mId); - return true; - } - return false; + // Check that no parent can fail anymore + for(DFTGatePointer const& parent : mParents) { + if(state.isOperational(parent->id())) { + return false; + } + } + + state.setDontCare(mId); + return true; } template diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 11fc31948..d5620717f 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -350,6 +350,7 @@ namespace storm { } } state.setFailed(this->mId); + this->childrenDontCare(state, queues); } void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { @@ -359,6 +360,7 @@ namespace storm { } } state.setFailsafe(this->mId); + this->childrenDontCare(state, queues); } void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { From 74b512a76ef62c727a453a50590c12eded00c234 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sun, 21 Feb 2016 16:05:03 +0100 Subject: [PATCH 142/246] Consider dependencies in DFS for state generation info Former-commit-id: c61210cbd548a265778bc636caedab123107d355 --- src/storage/dft/DFT.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 519036fff..92e780872 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -80,23 +80,17 @@ namespace storm { std::queue visitQueue; std::set visited; visitQueue.push(subTreeRoots[0]); - bool consideredDependencies = false; - while (true) { - if (consideredDependencies) { - break; - } - - stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); - - // Consider dependencies - for (size_t idDependency : getDependencies()) { - std::shared_ptr const> dependency = getDependency(idDependency); - visitQueue.push(dependency->id()); - visitQueue.push(dependency->triggerEvent()->id()); - visitQueue.push(dependency->dependentEvent()->id()); - } - consideredDependencies = true; + stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); + + // Consider dependencies + for (size_t idDependency : getDependencies()) { + std::shared_ptr const> dependency = getDependency(idDependency); + visitQueue.push(dependency->id()); + visitQueue.push(dependency->triggerEvent()->id()); + visitQueue.push(dependency->dependentEvent()->id()); } + stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); + assert(stateIndex = mStateVectorSize); STORM_LOG_TRACE(generationInfo); From 2a2eefa95645e13f2254497c3a58d332dae06076 Mon Sep 17 00:00:00 2001 From: sjunges Date: Sun, 21 Feb 2016 19:25:38 +0100 Subject: [PATCH 143/246] towards restrictions Former-commit-id: e3baec90ea5ea4bf82e91892fd722cc2583a94e0 --- src/storage/dft/DFTBuilder.cpp | 52 +++++- src/storage/dft/DFTBuilder.h | 19 ++- src/storage/dft/DFTElements.h | 20 +++ src/storage/dft/elements/DFTRestriction.h | 195 +++++++++++++++++++++- 4 files changed, 281 insertions(+), 5 deletions(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 1979aea3b..62b022635 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -27,6 +27,7 @@ namespace storm { childElement->addParent(gate); } else { // Child not found -> find first dependent event to assure that child is dependency + // TODO: Not sure whether this is the intended behaviour? auto itFind = mElements.find(child + "_1"); assert(itFind != mElements.end()); assert(itFind->second->isDependency()); @@ -34,6 +35,17 @@ namespace storm { } } } + + for(auto& elem : mRestrictionChildNames) { + for(auto const& childName : elem.second) { + auto itFind = mElements.find(childName); + assert(itFind != mElements.end()); + DFTElementPointer childElement = itFind->second; + assert(!childElement->isDependency() && !childElement->isRestriction()); + elem.first->pushBackChild(childElement); + childElement->addRestriction(elem.first); + } + } // Initialize dependencies for (auto& dependency : mDependencies) { @@ -45,6 +57,17 @@ namespace storm { dependentEvent->addIngoingDependency(dependency); } +// for (auto& restriction : mRestrictions) { +// std::set parentsOfRestrictedElements; +// for (auto& child : restriction->children()) { +// for(DFTGatePointer& parent : child->parents()) { +// parentsOfRestrictedElements.insert(parent); +// } +// } +// +// +// } + // Sort elements topologically // compute rank for (auto& elem : mElements) { @@ -82,6 +105,33 @@ namespace storm { return elem->rank(); } + template + bool DFTBuilder::addRestriction(std::string const& name, std::vector const& children, DFTElementType tp) { + if (children.size() <= 1) { + STORM_LOG_ERROR("Sequence enforcers require at least two children"); + } + if (mElements.count(name) != 0) { + return false; + } + DFTRestrictionPointer restr; + switch (tp) { + case DFTElementType::SEQ: + restr = std::make_shared> + (mNextId++, name); + break; + case DFTElementType::MUTEX: + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); + break; + default: + STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not known."); + break; + } + + mElements[name] = restr; + mRestrictionChildNames[restr] = children; + mRestrictions.push_back(restr); + } + template bool DFTBuilder::addStandardGate(std::string const& name, std::vector const& children, DFTElementType tp) { assert(children.size() > 0); @@ -108,11 +158,11 @@ namespace storm { break; case DFTElementType::BE: case DFTElementType::VOT: + case DFTElementType::PDEP: // Handled separately STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type handled separately."); case DFTElementType::CONSTF: case DFTElementType::CONSTS: - case DFTElementType::PDEP: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); default: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not known."); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 17a16cb49..8ef0d6cf1 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -3,6 +3,7 @@ #define DFTBUILDER_H #include "DFTElements.h" +#include "elements/DFTRestriction.h" #include #include #include @@ -21,13 +22,16 @@ namespace storm { using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; using DFTDependencyPointer = std::shared_ptr>; + using DFTRestrictionPointer = std::shared_ptr>; private: std::size_t mNextId = 0; std::string topLevelIdentifier; std::unordered_map mElements; std::unordered_map> mChildNames; + std::unordered_map> mRestrictionChildNames; std::vector mDependencies; + std::vector mRestrictions; public: DFTBuilder() { @@ -53,9 +57,19 @@ namespace storm { bool addSpareElement(std::string const& name, std::vector const& children) { return addStandardGate(name, children, DFTElementType::SPARE); } + + bool addSequenceEnforcer(std::string const& name, std::vector const& children) { + return addRestriction(name, children, DFTElementType::SEQ); + } + + bool addMutex(std::string const& name, std::vector const& children) { + return addRestriction(name, children, DFTElementType::MUTEX); + } bool addDepElement(std::string const& name, std::vector const& children, ValueType probability) { - assert(children.size() > 1); + if(children.size() <= 1) { + STORM_LOG_ERROR("Dependencies require at least two children"); + } if(mElements.count(name) != 0) { // Element with that name already exists. return false; @@ -138,7 +152,8 @@ namespace storm { unsigned computeRank(DFTElementPointer const& elem); bool addStandardGate(std::string const& name, std::vector const& children, DFTElementType tp); - + bool addRestriction(std::string const& name, std::vector const& children, DFTElementType tp); + enum class topoSortColour {WHITE, BLACK, GREY}; void topoVisit(DFTElementPointer const& n, std::map>& visited, DFTElementVector& L); diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index c51e180c7..66e8b3e8a 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -26,6 +26,8 @@ namespace storm { template class DFTDependency; + template + class DFTRestriction; template class DFTElement { @@ -34,6 +36,9 @@ namespace storm { using DFTGateVector = std::vector; using DFTDependencyPointer = std::shared_ptr>; using DFTDependencyVector = std::vector; + using DFTRestrictionPointer = std::shared_ptr>; + using DFTRestrictionVector = std::vector; + protected: size_t mId; @@ -41,6 +46,8 @@ namespace storm { size_t mRank = -1; DFTGateVector mParents; DFTDependencyVector mOutgoingDependencies; + DFTRestrictionVector mRestrictions; + public: DFTElement(size_t id, std::string const& name) : @@ -95,6 +102,10 @@ namespace storm { virtual bool isDependency() const { return false; } + + virtual bool isRestriction() const { + return false; + } virtual void setId(size_t newId) { mId = newId; @@ -118,6 +129,15 @@ namespace storm { } } + bool addRestriction(DFTRestrictionPointer const& e) { + if (std::find(mRestrictions.begin(), mRestrictions.end(), e) != mRestrictions.end()) { + return false; + } else { + mRestrictions.push_back(e); + return true; + } + } + bool hasOnlyStaticParents() const { for(auto const& parent : mParents) { if(!isStaticGateType(parent->type())) { diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index 8bd586deb..464c49db2 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -6,8 +6,199 @@ namespace storm { namespace storage { template class DFTRestriction : public DFTElement { - + using DFTElementPointer = std::shared_ptr>; + using DFTElementVector = std::vector; + protected: + DFTElementVector mChildren; + + public: + DFTRestriction(size_t id, std::string const& name, DFTElementVector const& children) : + DFTElement(id, name), mChildren(children) + {} + + virtual ~DFTRestriction() {} + + void pushBackChild(DFTElementPointer elem) { + return mChildren.push_back(elem); + } + + size_t nrChildren() const override { + return mChildren.size(); + } + + DFTElementVector const& children() const { + return mChildren; + } + + virtual bool isRestriction() const override { + return true; + } + + + virtual std::string typestring() const = 0; + + virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void extendSpareModule(std::set& elementsInSpareModule) const override { + DFTElement::extendSpareModule(elementsInSpareModule); + for(auto const& child : mChildren) { + if(elementsInSpareModule.count(child->id()) == 0) { + elementsInSpareModule.insert(child->id()); + child->extendSpareModule(elementsInSpareModule); + } + } + } + + virtual std::vector independentUnit() const override { + std::set unit = {this->mId}; + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + return std::vector(unit.begin(), unit.end()); + } + + virtual void extendUnit(std::set& unit) const override { + DFTElement::extendUnit(unit); + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + } + + virtual std::vector independentSubDft() const override { + auto prelRes = DFTElement::independentSubDft(); + if(prelRes.empty()) { + // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. + return prelRes; + } + std::set unit(prelRes.begin(), prelRes.end()); + std::vector pids = this->parentIds(); + for(auto const& child : mChildren) { + child->extendSubDft(unit, pids); + if(unit.empty()) { + // Parent in the subdft, ie it is *not* a subdft + break; + } + } + return std::vector(unit.begin(), unit.end()); + } + + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + if(elemsInSubtree.count(this->id()) > 0) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + for(auto const& child : mChildren) { + child->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + } + } + + + virtual std::string toString() const override { + std::stringstream stream; + stream << "{" << this->name() << "} " << typestring() << "( "; + typename DFTElementVector::const_iterator it = mChildren.begin(); + stream << (*it)->name(); + ++it; + while(it != mChildren.end()) { + stream << ", " << (*it)->name(); + ++it; + } + stream << ")"; + return stream.str(); + } + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(DFTElement::checkDontCareAnymore(state, queues)) { + childrenDontCare(state, queues); + return true; + } + return false; + } + + + protected: + + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + //state.restrictionViolated(this->mId); + } + + void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + + } + + void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + queues.propagateDontCare(mChildren); + } + + bool hasFailsafeChild(DFTState& state) const { + for(auto const& child : mChildren) { + if(state.isFailsafe(child->id())) + { + return true; + } + } + return false; + } + + bool hasFailedChild(DFTState& state) const { + for(auto const& child : mChildren) { + if(state.hasFailed(child->id())) { + return true; + } + } + return false; + } + + + + }; - + + template + class DFTSeq : public DFTRestriction { + + + public: + DFTSeq(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTRestriction(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(queues.failurePropagationDone()); + bool childOperationalBefore = false; + for(auto const& child : this->mChildren) + { + if(!state.hasFailed(child->id())) { + childOperationalBefore = true; + } else if(childOperationalBefore && state.hasFailed(child->id())){ + this->fail(state, queues); + return; + } + } + + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(this->hasFailsafeChild(state)); + + } + + virtual DFTElementType type() const override { + return DFTElementType::SEQ; + } + + std::string typestring() const override { + return "SEQ"; + } + }; + } } \ No newline at end of file From 371ba87f1c08223f0708e8ceee015d1b5d843466 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sun, 21 Feb 2016 19:35:20 +0100 Subject: [PATCH 144/246] Fixed activation of spares Former-commit-id: f62ccdc79a984cad432d00d8c06a855e52debdb1 --- examples/dft/spare8.dft | 7 +++++ src/builder/ExplicitDFTModelBuilder.cpp | 15 +++++----- src/storage/dft/DFT.cpp | 14 +++++---- src/storage/dft/DFTElements.h | 32 ++++++++++++++++---- src/storage/dft/DFTState.cpp | 40 ++++++++++--------------- src/storage/dft/DFTState.h | 9 +++--- 6 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 examples/dft/spare8.dft diff --git a/examples/dft/spare8.dft b/examples/dft/spare8.dft new file mode 100644 index 000000000..c67eaf022 --- /dev/null +++ b/examples/dft/spare8.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" wsp "I" "B"; +"B" wsp "J" "K"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; + diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index cbb9b69d0..4900845a5 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -256,7 +256,7 @@ namespace storm { if (mStates.contains(unsuccessfulState->status())) { // Unsuccessful state already exists unsuccessfulStateId = mStates.getValue(unsuccessfulState->status()); - STORM_LOG_TRACE("State " << mDft.getStateString(unsuccessfulState) << " already exists"); + STORM_LOG_TRACE("State " << mDft.getStateString(unsuccessfulState) << " with id " << unsuccessfulStateId << " already exists"); } else { // New unsuccessful state unsuccessfulState->setId(newIndex++); @@ -277,16 +277,15 @@ namespace storm { ++rowOffset; } else { - // Set failure rate according to usage - bool isUsed = true; + // Set failure rate according to activation + bool isActive = true; if (mDft.hasRepresentant(nextBE->id())) { - DFTElementCPointer representant = mDft.getRepresentant(nextBE->id()); - // Used must be checked for the state we are coming from as this state is responsible for the + // Active must be checked for the state we are coming from as this state is responsible for the // rate and not the new state we are going to - isUsed = state->isUsed(representant->id()); + isActive = state->isActive(mDft.getRepresentant(nextBE->id())->id()); } - STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isUsed ? "used" : "not used")); - ValueType rate = isUsed ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); + STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isActive ? "active" : "not active")); + ValueType rate = isActive ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); auto resultFind = outgoingTransitions.find(newStateId); if (resultFind != outgoingTransitions.end()) { // Add to existing transition diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 92e780872..3fbcd5ee1 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -191,10 +191,11 @@ namespace storm { } else { stream << "\t** " << storm::storage::toChar(state->getElementState(elem->id())); if(elem->isSpareGate()) { - if(state->isActiveSpare(elem->id())) { - stream << " actively"; + size_t useId = state->uses(elem->id()); + if(state->isActive(useId)) { + stream << " actively "; } - stream << " using " << state->uses(elem->id()); + stream << " using " << useId; } } stream << std::endl; @@ -214,10 +215,11 @@ namespace storm { stream << storm::storage::toChar(state->getElementState(elem->id())); if(elem->isSpareGate()) { stream << "["; - if(state->isActiveSpare(elem->id())) { - stream << "actively "; + size_t useId = state->uses(elem->id()); + if(state->isActive(useId)) { + stream << " actively "; } - stream << "using " << state->uses(elem->id()) << "]"; + stream << "using " << useId << "]"; } } } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index eaee1d54a..22c819f84 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -259,11 +259,13 @@ namespace storm { virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; virtual void extendSpareModule(std::set& elementsInSpareModule) const override { - DFTElement::extendSpareModule(elementsInSpareModule); - for(auto const& child : mChildren) { - if(elementsInSpareModule.count(child->id()) == 0) { - elementsInSpareModule.insert(child->id()); - child->extendSpareModule(elementsInSpareModule); + if (!this->isSpareGate()) { + DFTElement::extendSpareModule(elementsInSpareModule); + for( auto const& child : mChildren) { + if(elementsInSpareModule.count(child->id()) == 0) { + elementsInSpareModule.insert(child->id()); + child->extendSpareModule(elementsInSpareModule); + } } } } @@ -350,6 +352,9 @@ namespace storm { } } state.setFailed(this->mId); + if (this->isSpareGate()) { + this->finalizeSpare(state); + } this->childrenDontCare(state, queues); } @@ -360,6 +365,9 @@ namespace storm { } } state.setFailsafe(this->mId); + if (this->isSpareGate()) { + this->finalizeSpare(state); + } this->childrenDontCare(state, queues); } @@ -367,6 +375,20 @@ namespace storm { queues.propagateDontCare(mChildren); } + /** + * Finish failed/failsafe spare gate by activating the children and setting the useIndex to zero. + * This prevents multiple fail states with different usages or activations. + * @param state The current state. + */ + void finalizeSpare(DFTState& state) const { + state.setUses(this->mId, 0); + for (auto child : this->children()) { + if (!state.isActive(child->id())) { + state.activate(child->id()); + } + } + } + bool hasFailsafeChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.isFailsafe(child->id())) diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 0bad03f78..7f34e03ef 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -7,7 +7,6 @@ namespace storm { template DFTState::DFTState(DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) : mStatus(dft.stateVectorSize()), mId(id), mDft(dft), mStateGenerationInfo(stateGenerationInfo) { - mInactiveSpares = dft.getSpareIndices(); // Initialize uses for(size_t id : mDft.getSpareIndices()) { @@ -18,12 +17,7 @@ namespace storm { } // Initialize activation - this->activate(mDft.getTopLevelIndex()); - for(auto const& id : mDft.module(mDft.getTopLevelIndex())) { - if(mDft.getElement(id)->isSpareGate()) { - propagateActivation(uses(id)); - } - } + propagateActivation(mDft.getTopLevelIndex()); std::vector alwaysActiveBEs = dft.nonColdBEs(); mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); @@ -182,29 +176,25 @@ namespace storm { template void DFTState::activate(size_t repr) { - for(size_t elem : mDft.module(repr)) { - if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { - mIsCurrentlyFailableBE.push_back(elem); - } - else if(mDft.getElement(elem)->isSpareGate()) { - assert(std::find(mInactiveSpares.begin(), mInactiveSpares.end(), elem) != mInactiveSpares.end()); - mInactiveSpares.erase(std::find(mInactiveSpares.begin(), mInactiveSpares.end(), elem)); - } - } + size_t activationIndex = mStateGenerationInfo.getSpareActivationIndex(repr); + assert(!mStatus[activationIndex]); + mStatus.set(activationIndex); + propagateActivation(repr); } template - bool DFTState::isActiveSpare(size_t id) const { - assert(mDft.getElement(id)->isSpareGate()); - return (std::find(mInactiveSpares.begin(), mInactiveSpares.end(), id) == mInactiveSpares.end()); + bool DFTState::isActive(size_t id) const { + assert(mDft.isRepresentative(id)); + return mStatus[mStateGenerationInfo.getSpareActivationIndex(id)]; } template void DFTState::propagateActivation(size_t representativeId) { - activate(representativeId); - for(size_t id : mDft.module(representativeId)) { - if(mDft.getElement(id)->isSpareGate()) { - propagateActivation(uses(id)); + for(size_t elem : mDft.module(representativeId)) { + if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { + mIsCurrentlyFailableBE.push_back(elem); + } else if (mDft.getElement(elem)->isSpareGate() && !isActive(uses(elem))) { + activate(uses(elem)); } } } @@ -243,8 +233,8 @@ namespace storm { size_t childId = (*it)->id(); if(!hasFailed(childId) && !isUsed(childId)) { setUses(spareId, childId); - if(isActiveSpare(spareId)) { - propagateActivation(childId); + if(isActive(currentlyUses)) { + activate(childId); } return true; } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 821aa2fcb..7a26e10ab 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -26,7 +26,6 @@ namespace storm { // Status is bitvector where each element has two bits with the meaning according to DFTElementState storm::storage::BitVector mStatus; size_t mId; - std::vector mInactiveSpares; std::vector mIsCurrentlyFailableBE; std::vector mFailableDependencies; std::vector mUsedRepresentants; @@ -79,9 +78,7 @@ namespace storm { void activate(size_t repr); - bool isActiveSpare(size_t id) const; - - void propagateActivation(size_t representativeId); + bool isActive(size_t id) const; void markAsInvalid() { mValid = false; @@ -200,6 +197,10 @@ namespace storm { friend bool operator==(DFTState const& a, DFTState const& b) { return a.mStatus == b.mStatus; } + + private: + void propagateActivation(size_t representativeId); + }; } From a6f389fce2ed993a29a1adf3c6ab165a71e85e1e Mon Sep 17 00:00:00 2001 From: sjunges Date: Sun, 21 Feb 2016 20:59:08 +0100 Subject: [PATCH 145/246] SEQ in the parser Former-commit-id: 8163e7149ccd512ddbb109ca907c040836711079 --- src/parser/DFTGalileoParser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index d11f5ae3b..65ad82437 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -102,6 +102,8 @@ namespace storm { success = builder.addPandElement(name, childNames); } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); + } else if (tokens[1] == "seq") { + success = builder.addSequenceEnforcer(name, childNames); } else if (tokens[1] == "fdep") { success = builder.addDepElement(name, childNames, storm::utility::one()); } else if (boost::starts_with(tokens[1], "pdep=")) { From 9dd2a71f2f78808892bc26b7b8d69c3c4c8b05fb Mon Sep 17 00:00:00 2001 From: sjunges Date: Sun, 21 Feb 2016 20:59:45 +0100 Subject: [PATCH 146/246] towards state space construction for SEQs Former-commit-id: 890ce8bd85d0e7660653f2370e8ec764b8233caf --- src/storage/dft/DFT.h | 1 + src/storage/dft/DFTElements.cpp | 2 +- src/storage/dft/DFTElements.h | 16 +++++++++++++++ .../dft/DFTStateSpaceGenerationQueues.h | 20 +++++++++++++++++++ src/storage/dft/elements/DFTRestriction.h | 4 ++-- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index a0059d81b..1f3e8cceb 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -10,6 +10,7 @@ #include #include "DFTElements.h" +#include "elements/DFTRestriction.h" #include "../BitVector.h" #include "SymmetricUnits.h" #include "../../utility/math.h" diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index e06b3fe7d..9d21e5dd4 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -52,7 +52,7 @@ namespace storm { template std::vector DFTElement::independentSubDft() const { - std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; + //std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; std::vector res; res.push_back(this->id()); return res; diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index db1f0f6cf..bb4be80a7 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -159,6 +159,18 @@ namespace storm { DFTGateVector const& parents() const { return mParents; } + + bool hasRestrictions() const { + return !mRestrictions.empty(); + } + + size_t nrRestrictions() const { + return mRestrictions.size(); + } + + DFTRestrictionVector const& restrictions() const { + return mRestrictions; + } std::vector parentIds() const { std::vector res; @@ -371,7 +383,11 @@ namespace storm { queues.propagateFailure(parent); } } + for(std::shared_ptr> restr : this->mRestrictions) { + queues.checkRestrictionLater(restr); + } state.setFailed(this->mId); + // TODO can this be moved towards DFTSpare? if (this->isSpareGate()) { this->finalizeSpare(state); } diff --git a/src/storage/dft/DFTStateSpaceGenerationQueues.h b/src/storage/dft/DFTStateSpaceGenerationQueues.h index b881a220b..6ded7cb38 100644 --- a/src/storage/dft/DFTStateSpaceGenerationQueues.h +++ b/src/storage/dft/DFTStateSpaceGenerationQueues.h @@ -15,6 +15,8 @@ namespace storm { class DFTGate; template class DFTElement; + template + class DFTRestriction; template @@ -24,11 +26,14 @@ namespace storm { using DFTElementVector = std::vector; using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; + using DFTRestrictionPointer = std::shared_ptr>; + using DFTRestrictionVector = std::vector; std::priority_queue> failurePropagation; DFTGateVector failsafePropagation; DFTElementVector dontcarePropagation; DFTElementVector activatePropagation; + DFTRestrictionVector restrictionChecks; public: void propagateFailure(DFTGatePointer const& elem) { @@ -45,6 +50,21 @@ namespace storm { return next; } + bool restrictionChecksDone() const { + return restrictionChecks.empty(); + } + + DFTRestrictionPointer nextRestrictionCheck() { + assert(!restrictionChecksDone()); + DFTRestrictionPointer next = restrictionChecks.back(); + restrictionChecks.pop_back(); + return next; + } + + void checkRestrictionLater(DFTRestrictionPointer const& restr) { + restrictionChecks.push_back(restr); + } + bool failsafePropagationDone() const { return failsafePropagation.empty(); } diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index 464c49db2..0d8651e50 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -127,7 +127,7 @@ namespace storm { protected: void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - //state.restrictionViolated(this->mId); + state.markAsInvalid(); } void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { @@ -187,7 +187,7 @@ namespace storm { } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(this->hasFailsafeChild(state)); + } From dde9af6c44959254518f5d684a4a73c35184f049 Mon Sep 17 00:00:00 2001 From: sjunges Date: Mon, 22 Feb 2016 00:05:05 +0100 Subject: [PATCH 147/246] mergeFailedStates and some updates for SEQs Former-commit-id: 128a7e0da53e11d8853a07d799c15720724dca34 --- src/builder/ExplicitDFTModelBuilder.cpp | 87 +++++++++++++++-------- src/builder/ExplicitDFTModelBuilder.h | 5 ++ src/storage/dft/DFTBuilder.cpp | 1 + src/storage/dft/DFTElements.cpp | 4 ++ src/storage/dft/elements/DFTRestriction.h | 12 ++-- src/storm-dyftee.cpp | 2 +- 6 files changed, 74 insertions(+), 37 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 4900845a5..1840ba40a 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -57,36 +57,47 @@ namespace storm { template std::shared_ptr> ExplicitDFTModelBuilder::buildModel(LabelOptions const& labelOpts) { // Initialize - DFTStatePointer state = std::make_shared>(mDft, *mStateGenerationInfo, newIndex++); - mStates.findOrAdd(state->status(), state->getId()); - - std::queue stateQueue; - stateQueue.push(state); - bool deterministicModel = false; ModelComponents modelComponents; std::vector tmpMarkovianStates; storm::storage::SparseMatrixBuilder transitionMatrixBuilder(0, 0, 0, false, !deterministicModel, 0); + + if(mergeFailedStates) { + newIndex++; + + transitionMatrixBuilder.newRowGroup(failedIndex); + transitionMatrixBuilder.addNextValue(failedIndex, failedIndex, storm::utility::one()); + STORM_LOG_TRACE("Added self loop for " << failedIndex); + modelComponents.exitRates.push_back(storm::utility::one()); + tmpMarkovianStates.push_back(failedIndex); + } + + DFTStatePointer state = std::make_shared>(mDft, *mStateGenerationInfo, newIndex++); + mStates.findOrAdd(state->status(), state->getId()); + initialStateIndex = state->getId(); + std::queue stateQueue; + stateQueue.push(state); + // Begin model generation bool deterministic = exploreStates(stateQueue, transitionMatrixBuilder, tmpMarkovianStates, modelComponents.exitRates); - STORM_LOG_DEBUG("Generated " << mStates.size() << " states"); + STORM_LOG_DEBUG("Generated " << mStates.size() + (mergeFailedStates ? 1 : 0) << " states"); STORM_LOG_DEBUG("Model is " << (deterministic ? "deterministic" : "non-deterministic")); + size_t stateSize = mStates.size() + (mergeFailedStates ? 1 : 0); // Build Markov Automaton - modelComponents.markovianStates = storm::storage::BitVector(mStates.size(), tmpMarkovianStates); + modelComponents.markovianStates = storm::storage::BitVector(stateSize, tmpMarkovianStates); // Build transition matrix - modelComponents.transitionMatrix = transitionMatrixBuilder.build(); + modelComponents.transitionMatrix = transitionMatrixBuilder.build(stateSize, stateSize); STORM_LOG_DEBUG("Transition matrix: " << std::endl << modelComponents.transitionMatrix); STORM_LOG_DEBUG("Exit rates: " << modelComponents.exitRates); STORM_LOG_DEBUG("Markovian states: " << modelComponents.markovianStates); - assert(!deterministic || modelComponents.transitionMatrix.getRowCount() == modelComponents.transitionMatrix.getColumnCount()); - + // Build state labeling - modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size()); + modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size() + (mergeFailedStates ? 1 : 0)); // Initial state is always first state without any failure modelComponents.stateLabeling.addLabel("init"); - modelComponents.stateLabeling.addLabelToState("init", 0); + modelComponents.stateLabeling.addLabelToState("init", initialStateIndex); // Label all states corresponding to their status (failed, failsafe, failed BE) if(labelOpts.buildFailLabel) { modelComponents.stateLabeling.addLabel("failed"); @@ -103,10 +114,13 @@ namespace storm { } } + if(mergeFailedStates) { + modelComponents.stateLabeling.addLabelToState("failed", failedIndex); + } for (auto const& stateIdPair : mStates) { storm::storage::BitVector state = stateIdPair.first; size_t stateId = stateIdPair.second; - if (labelOpts.buildFailLabel && mDft.hasFailed(state, *mStateGenerationInfo)) { + if (!mergeFailedStates && labelOpts.buildFailLabel && mDft.hasFailed(state, *mStateGenerationInfo)) { modelComponents.stateLabeling.addLabelToState("failed", stateId); } if (labelOpts.buildFailSafeLabel && mDft.isFailsafe(state, *mStateGenerationInfo)) { @@ -151,13 +165,12 @@ namespace storm { template bool ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates) { - assert(exitRates.empty()); - assert(markovianStates.empty()); // TODO Matthias: set Markovian states directly as bitvector? std::map outgoingTransitions; size_t rowOffset = 0; // Captures number of non-deterministic choices bool deterministic = true; - + + while (!stateQueue.empty()) { // Initialization outgoingTransitions.clear(); @@ -189,6 +202,7 @@ namespace storm { // Let BE fail while (smallest < failableCount) { + assert(!mDft.hasFailed(state)); STORM_LOG_TRACE("exploring from: " << mDft.getStateString(state)); // Construct new state as copy from original one @@ -207,11 +221,23 @@ namespace storm { queues.propagateFailure(parent); } } + for (DFTRestrictionPointer restr : nextBE->restrictions()) { + queues.checkRestrictionLater(restr); + } while (!queues.failurePropagationDone()) { DFTGatePointer next = queues.nextFailurePropagation(); next->checkFails(*newState, queues); } + + while(!queues.restrictionChecksDone()) { + DFTRestrictionPointer next = queues.nextRestrictionCheck(); + next->checkFails(*newState, queues); + } + + if(newState->isInvalid()) { + continue; + } while (!queues.failsafePropagationDone()) { DFTGatePointer next = queues.nextFailsafePropagation(); @@ -226,19 +252,24 @@ namespace storm { // Update failable dependencies newState->updateFailableDependencies(nextBE->id()); + bool dftFailed = newState->hasFailed(mDft.getTopLevelIndex()); size_t newStateId; - if (mStates.contains(newState->status())) { - // State already exists - newStateId = mStates.getValue(newState->status()); - STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " already exists"); + if(dftFailed && mergeFailedStates) { + newStateId = failedIndex; } else { - // New state - newState->setId(newIndex++); - newStateId = mStates.findOrAdd(newState->status(), newState->getId()); - STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); - - // Add state to search queue - stateQueue.push(newState); + if (mStates.contains(newState->status())) { + // State already exists + newStateId = mStates.getValue(newState->status()); + STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " already exists"); + } else { + // New state + newState->setId(newIndex++); + newStateId = mStates.findOrAdd(newState->status(), newState->getId()); + STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); + + // Add state to search queue + stateQueue.push(newState); + } } // Set transitions diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 522f2375c..42ca2755d 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -23,6 +23,8 @@ namespace storm { using DFTElementCPointer = std::shared_ptr const>; using DFTGatePointer = std::shared_ptr>; using DFTStatePointer = std::shared_ptr>; + using DFTRestrictionPointer = std::shared_ptr>; + // A structure holding the individual components of a model. struct ModelComponents { @@ -52,6 +54,9 @@ namespace storm { std::shared_ptr mStateGenerationInfo; storm::storage::BitVectorHashMap mStates; size_t newIndex = 0; + bool mergeFailedStates = true; + size_t failedIndex = 0; + size_t initialStateIndex = 0; public: struct LabelOptions { diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 62b022635..213fce0df 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -130,6 +130,7 @@ namespace storm { mElements[name] = restr; mRestrictionChildNames[restr] = children; mRestrictions.push_back(restr); + return true; } template diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 9d21e5dd4..7bb8c2cf5 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -10,6 +10,7 @@ namespace storm { if (state.dontCare(mId)) { return false; } + // Check that no outgoing dependencies can be triggered anymore for (DFTDependencyPointer dependency : mOutgoingDependencies) { if (state.isOperational(dependency->dependentEvent()->id()) && state.isOperational(dependency->triggerEvent()->id())) { @@ -22,6 +23,9 @@ namespace storm { return false; } } + + + state.setDontCare(mId); return true; diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index 0d8651e50..46b6e23cc 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -116,10 +116,6 @@ namespace storm { } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(DFTElement::checkDontCareAnymore(state, queues)) { - childrenDontCare(state, queues); - return true; - } return false; } @@ -134,10 +130,6 @@ namespace storm { } - void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - queues.propagateDontCare(mChildren); - } - bool hasFailsafeChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.isFailsafe(child->id())) @@ -189,6 +181,10 @@ namespace storm { void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + } + + bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) { + } virtual DFTElementType type() const override { diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 2160ed210..aa2e0879f 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -48,7 +48,7 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::cout << "Bisimulation..." << std::endl; - if (model->isOfType(storm::models::ModelType::Ctmc)) { + if (model->getNumberOfStates() > 500 && model->isOfType(storm::models::ModelType::Ctmc)) { model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); } From f89cc46576e1fb07cb3981fd37f042e609aabea8 Mon Sep 17 00:00:00 2001 From: sjunges Date: Mon, 22 Feb 2016 00:05:27 +0100 Subject: [PATCH 148/246] two more small examples Former-commit-id: 9d420a62b21d0e41270a5419071061c0687464cb --- examples/dft/seq1.dft | 5 +++++ examples/dft/spare_cold.dft | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 examples/dft/seq1.dft create mode 100644 examples/dft/spare_cold.dft diff --git a/examples/dft/seq1.dft b/examples/dft/seq1.dft new file mode 100644 index 000000000..8f5459fd2 --- /dev/null +++ b/examples/dft/seq1.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" and "B" "C"; +"X" seq "B" "C"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/spare_cold.dft b/examples/dft/spare_cold.dft new file mode 100644 index 000000000..d01174bd5 --- /dev/null +++ b/examples/dft/spare_cold.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" wsp "I" "M"; +"I" lambda=0.5 dorm=0.0; +"M" lambda=0.5 dorm=0.0; + From fa4a1aa68f24517cfd38d06daec991ebcb2a6903 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 22 Feb 2016 15:44:37 +0100 Subject: [PATCH 149/246] Fixed bug with filtering reward vector Former-commit-id: ad709ad0dd3da3c062480f1cd23e910e46064dab --- .../SparseDtmcEliminationModelChecker.cpp | 23 +++++++++++++++---- .../SparseDtmcEliminationModelChecker.h | 2 ++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index 2ea8fa459..5425044b2 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -584,11 +584,13 @@ namespace storm { // Do some sanity checks to establish some required properties. RewardModelType const& rewardModel = this->getModel().getRewardModel(checkTask.isRewardModelSet() ? checkTask.getRewardModel() : ""); - // TODO use maybeStates instead of all states - std::vector stateRewardValues = rewardModel.getTotalRewardVector(trueStates.getNumberOfSetBits(), this->getModel().getTransitionMatrix(), trueStates); STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException, "Input model does not have a reward model."); - std::vector result = computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates, stateRewardValues, checkTask.isOnlyInitialStatesRelevantSet()); + std::vector result = computeReachabilityRewards(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates, + [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates); + }, + checkTask.isOnlyInitialStatesRelevantSet()); // Construct check result. std::unique_ptr checkResult(new ExplicitQuantitativeCheckResult(result)); @@ -597,6 +599,17 @@ namespace storm { template std::vector SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::vector& stateRewardValues, bool computeForInitialStatesOnly) { + return computeReachabilityRewards(probabilityMatrix, backwardTransitions, initialStates, targetStates, + [&] (uint_fast64_t numberOfRows, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::BitVector const& maybeStates) { + std::vector result(numberOfRows); + storm::utility::vector::selectVectorValues(result, maybeStates, stateRewardValues); + return result; + }, + computeForInitialStatesOnly); + } + + template + std::vector SparseDtmcEliminationModelChecker::computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly) { uint_fast64_t numberOfStates = probabilityMatrix.getRowCount(); @@ -639,9 +652,9 @@ namespace storm { storm::storage::SparseMatrix submatrixTransposed = submatrix.transpose(); // Project the state reward vector to all maybe-states. - storm::storage::BitVector phiStates(numberOfStates, true); + std::vector stateRewardValues = totalStateRewardVectorGetter(submatrix.getRowCount(), probabilityMatrix, maybeStates); - std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, phiStates, targetStates, probabilityMatrix.getConstrainedRowSumVector(maybeStates, targetStates)); + std::vector subresult = computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly, trueStates, targetStates, probabilityMatrix.getConstrainedRowSumVector(maybeStates, targetStates)); storm::utility::vector::setVectorValues(result, maybeStates, subresult); } diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h index 76e939d66..33b61a2c4 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.h @@ -91,6 +91,8 @@ namespace storm { static std::vector computeLongRunValues(storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& maybeStates, bool computeResultsForInitialStatesOnly, std::vector& stateValues); + static std::vector computeReachabilityRewards(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, std::function(uint_fast64_t, storm::storage::SparseMatrix const&, storm::storage::BitVector const&)> const& totalStateRewardVectorGetter, bool computeForInitialStatesOnly); + static std::vector computeReachabilityValues(storm::storage::SparseMatrix const& transitionMatrix, std::vector& values, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& initialStates, bool computeResultsForInitialStatesOnly, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, std::vector const& oneStepProbabilitiesToTarget); static std::shared_ptr> createStatePriorityQueue(boost::optional> const& stateDistances, storm::storage::FlexibleSparseMatrix const& transitionMatrix, storm::storage::FlexibleSparseMatrix const& backwardTransitions, std::vector& oneStepProbabilities, storm::storage::BitVector const& states); From a44d38e0bfe47637a083ac292be31446c33376bf Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 22 Feb 2016 15:48:50 +0100 Subject: [PATCH 150/246] Symmetries are given to StateGenerationInfo Former-commit-id: b91cce3a81815032bcb95b80ea9b37aa8c076aa3 --- src/builder/ExplicitDFTModelBuilder.cpp | 36 ++----------------------- src/builder/ExplicitDFTModelBuilder.h | 6 ++--- src/storage/dft/DFT.cpp | 10 +++++-- src/storage/dft/DFT.h | 2 +- src/storm-dyftee.cpp | 11 ++++---- 5 files changed, 20 insertions(+), 45 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 1840ba40a..a1973d519 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -15,42 +15,10 @@ namespace storm { } template - ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, INITIAL_BUCKETSIZE) { + ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, INITIAL_BUCKETSIZE) { // stateVectorSize is bound for size of bitvector - // Find symmetries - // TODO activate - // Currently using hack to test - std::vector> symmetriesTmp; - std::vector vecB; - std::vector vecC; - std::vector vecD; - if (false) { - for (size_t i = 0; i < mDft.nrElements(); ++i) { - std::string name = mDft.getElement(i)->name(); - size_t id = mDft.getElement(i)->id(); - if (boost::starts_with(name, "B")) { - vecB.push_back(id); - } else if (boost::starts_with(name, "C")) { - vecC.push_back(id); - } else if (boost::starts_with(name, "D")) { - vecD.push_back(id); - } - } - symmetriesTmp.push_back(vecB); - symmetriesTmp.push_back(vecC); - symmetriesTmp.push_back(vecD); - std::cout << "Found the following symmetries:" << std::endl; - for (auto const& symmetry : symmetriesTmp) { - for (auto const& elem : symmetry) { - std::cout << elem << " -> "; - } - std::cout << std::endl; - } - } else { - vecB.push_back(mDft.getTopLevelIndex()); - } - mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(vecB, symmetriesTmp)); + mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(symmetries)); } diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 42ca2755d..6d17375b2 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -1,13 +1,13 @@ #ifndef EXPLICITDFTMODELBUILDER_H #define EXPLICITDFTMODELBUILDER_H -#include "../storage/dft/DFT.h" - #include #include #include #include #include +#include +#include #include #include #include @@ -65,7 +65,7 @@ namespace storm { std::set beLabels = {}; }; - ExplicitDFTModelBuilder(storm::storage::DFT const& dft); + ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries); std::shared_ptr> buildModel(LabelOptions const& labelOpts); diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 3fbcd5ee1..c88fbee1c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -68,7 +68,7 @@ namespace storm { } template - DFTStateGenerationInfo DFT::buildStateGenerationInfo(std::vector const& subTreeRoots, std::vector> const& symmetries) const { + DFTStateGenerationInfo DFT::buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const { // Use symmetry // Collect all elements in the first subtree // TODO make recursive to use for nested subtrees @@ -79,7 +79,13 @@ namespace storm { size_t stateIndex = 0; std::queue visitQueue; std::set visited; - visitQueue.push(subTreeRoots[0]); + size_t firstRoot; + if (symmetries.groups.empty()) { + firstRoot = mTopLevelIndex; + } else { + firstRoot = symmetries.groups.begin()->first; + } + visitQueue.push(firstRoot); stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); // Consider dependencies diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 1f3e8cceb..d8d6aa9bc 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -126,7 +126,7 @@ namespace storm { public: DFT(DFTElementVector const& elements, DFTElementPointer const& tle); - DFTStateGenerationInfo buildStateGenerationInfo(std::vector const& subTreeRoots, std::vector> const& symmetries) const; + DFTStateGenerationInfo buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const; size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, std::set& visited, size_t stateIndex) const; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index aa2e0879f..ba50d90f3 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -28,17 +28,19 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::vector> parsedFormulas = storm::parseFormulasForExplicit(property); std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); - std::cout << "parsed formula." << std::endl; + std::cout << "Parsed formula." << std::endl; + std::map>> emptySymmetry; + storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) { std::cout << dft.getElementsString() << std::endl; auto colouring = dft.colourDFT(); - storm::storage::DFTIndependentSymmetries symmetries = dft.findSymmetries(colouring); - std::cout << symmetries; + symmetries = dft.findSymmetries(colouring); + std::cout << "Symmetries: " << symmetries << std::endl; } // Building Markov Automaton std::cout << "Building Model..." << std::endl; - storm::builder::ExplicitDFTModelBuilder builder(dft); + storm::builder::ExplicitDFTModelBuilder builder(dft, symmetries); typename storm::builder::ExplicitDFTModelBuilder::LabelOptions labeloptions; // TODO initialize this with the formula std::shared_ptr> model = builder.buildModel(labeloptions); std::cout << "Built Model" << std::endl; @@ -52,7 +54,6 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); } - model->printModelInformationToStream(std::cout); // Model checking From 6685b358f07df97ae43890d90493e14fb76f7f7e Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 22 Feb 2016 18:31:52 +0100 Subject: [PATCH 151/246] Symmetry mirrored in state vector Former-commit-id: 7e5a578c44d7c47637f5575621a648edeb13282f --- examples/dft/symmetry3.dft | 12 +++++++ examples/dft/symmetry4.dft | 12 +++++++ src/storage/dft/DFT.cpp | 73 ++++++++++++++++++++++++++++++-------- src/storage/dft/DFT.h | 2 +- 4 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 examples/dft/symmetry3.dft create mode 100644 examples/dft/symmetry4.dft diff --git a/examples/dft/symmetry3.dft b/examples/dft/symmetry3.dft new file mode 100644 index 000000000..edda963f9 --- /dev/null +++ b/examples/dft/symmetry3.dft @@ -0,0 +1,12 @@ +toplevel "A"; +"A" and "B" "B'" "B''"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"B''" and "C''" "D''"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; +"C''" lambda=0.5 dorm=0; +"D''" lambda=0.5 dorm=0; + diff --git a/examples/dft/symmetry4.dft b/examples/dft/symmetry4.dft new file mode 100644 index 000000000..f401fc241 --- /dev/null +++ b/examples/dft/symmetry4.dft @@ -0,0 +1,12 @@ +toplevel "A"; +"A" and "B" "B'" "C" "C'"; +"B" and "D" "E"; +"B'" and "D'" "E'"; +"C" or "F"; +"C'" or "F'"; +"D" lambda=0.5 dorm=0; +"E" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; +"E'" lambda=0.5 dorm=0; +"F" lambda=0.5 dorm=0; +"F'" lambda=0.5 dorm=0; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c88fbee1c..03812c937 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -72,22 +72,60 @@ namespace storm { // Use symmetry // Collect all elements in the first subtree // TODO make recursive to use for nested subtrees - + DFTStateGenerationInfo generationInfo(nrElements()); // Perform DFS and insert all elements of subtree sequentially size_t stateIndex = 0; std::queue visitQueue; - std::set visited; - size_t firstRoot; + storm::storage::BitVector visited(nrElements(), false); + if (symmetries.groups.empty()) { - firstRoot = mTopLevelIndex; + // Perform DFS for whole tree + visitQueue.push(mTopLevelIndex); + stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); } else { - firstRoot = symmetries.groups.begin()->first; + // Perform DFS for first subtree of each symmetry + for (auto const& symmetryGroup : symmetries.groups) { + visitQueue.push(symmetryGroup.first); + size_t stateIndexBefore = stateIndex; + stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); + size_t offset = stateIndex - stateIndexBefore; + + // Mirror symmetries + assert(!symmetryGroup.second.empty()); + for (std::vector symmetricElements : symmetryGroup.second) { + assert(symmetricElements.size() > 1); + size_t originalElement = symmetricElements[0]; + size_t index = generationInfo.getStateIndex(originalElement); + size_t activationIndex = isRepresentative(originalElement) ? generationInfo.getSpareActivationIndex(originalElement) : 0; + size_t usageIndex = mElements[originalElement]->isSpareGate() ? generationInfo.getSpareUsageIndex(originalElement) : 0; + + // Mirror symmetry for each element + for (size_t i = 1; i < symmetricElements.size(); ++i) { + size_t symmetricElement = symmetricElements[i]; + visited.set(symmetricElement); + + generationInfo.addStateIndex(symmetricElement, index + offset * i); + stateIndex += 2; + + assert((activationIndex > 0) == isRepresentative(symmetricElement)); + if (activationIndex > 0) { + generationInfo.addSpareActivationIndex(symmetricElement, activationIndex + offset * i); + ++stateIndex; + } + + assert((usageIndex > 0) == mElements[symmetricElement]->isSpareGate()); + if (usageIndex > 0) { + generationInfo.addSpareUsageIndex(symmetricElement, usageIndex + offset * i); + stateIndex += generationInfo.usageInfoBits(); + } + } + } + } } - visitQueue.push(firstRoot); - stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); - + + // TODO symmetries in dependencies? // Consider dependencies for (size_t idDependency : getDependencies()) { std::shared_ptr const> dependency = getDependency(idDependency); @@ -96,24 +134,31 @@ namespace storm { visitQueue.push(dependency->dependentEvent()->id()); } stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); - - assert(stateIndex = mStateVectorSize); + + // Visit all remaining states + for (size_t i = 0; i < visited.size(); ++i) { + if (!visited[i]) { + visitQueue.push(i); + stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); + } + } STORM_LOG_TRACE(generationInfo); - + assert(stateIndex == mStateVectorSize); + assert(visited.full()); return generationInfo; } template - size_t DFT::performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, std::set& visited, size_t stateIndex) const { + size_t DFT::performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, storm::storage::BitVector& visited, size_t stateIndex) const { while (!visitQueue.empty()) { size_t id = visitQueue.front(); visitQueue.pop(); - if (visited.count(id) == 1) { + if (visited[id]) { // Already visited continue; } - visited.insert(id); + visited.set(id); DFTElementPointer element = mElements[id]; // Insert children diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index d8d6aa9bc..d3da06776 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -128,7 +128,7 @@ namespace storm { DFTStateGenerationInfo buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const; - size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, std::set& visited, size_t stateIndex) const; + size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, storm::storage::BitVector& visited, size_t stateIndex) const; size_t stateVectorSize() const { return mStateVectorSize; From 1e4dbb1e582820109a98bc2cb54878f3b59342d6 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 23 Feb 2016 13:52:06 +0100 Subject: [PATCH 152/246] More preparations for counting abstraction Former-commit-id: b283b28fdd41a254f82d5c8ece22286a77b4eeac --- src/storage/dft/DFT.cpp | 72 ++++++++++++++++++++++++++--------------- src/storage/dft/DFT.h | 29 +++++++++++++++++ 2 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 03812c937..b61425953 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -85,22 +85,28 @@ namespace storm { visitQueue.push(mTopLevelIndex); stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); } else { - // Perform DFS for first subtree of each symmetry for (auto const& symmetryGroup : symmetries.groups) { + assert(!symmetryGroup.second.empty()); + + // Perform DFS for first subtree of each symmetry visitQueue.push(symmetryGroup.first); - size_t stateIndexBefore = stateIndex; + size_t groupIndex = stateIndex; stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); - size_t offset = stateIndex - stateIndexBefore; - + size_t offset = stateIndex - groupIndex; + // Mirror symmetries - assert(!symmetryGroup.second.empty()); + size_t noSymmetricElements = symmetryGroup.second.front().size(); + assert(noSymmetricElements > 1); + for (std::vector symmetricElements : symmetryGroup.second) { - assert(symmetricElements.size() > 1); + assert(symmetricElements.size() == noSymmetricElements); + + // Initialize for original element size_t originalElement = symmetricElements[0]; size_t index = generationInfo.getStateIndex(originalElement); size_t activationIndex = isRepresentative(originalElement) ? generationInfo.getSpareActivationIndex(originalElement) : 0; size_t usageIndex = mElements[originalElement]->isSpareGate() ? generationInfo.getSpareUsageIndex(originalElement) : 0; - + // Mirror symmetry for each element for (size_t i = 1; i < symmetricElements.size(); ++i) { size_t symmetricElement = symmetricElements[i]; @@ -122,6 +128,13 @@ namespace storm { } } } + + // Store starting indices of symmetry groups + std::vector symmetryIndices; + for (size_t i = 0; i < noSymmetricElements; ++i) { + symmetryIndices.push_back(groupIndex + i * offset); + } + generationInfo.addSymmetry(offset, symmetryIndices); } } @@ -146,9 +159,32 @@ namespace storm { STORM_LOG_TRACE(generationInfo); assert(stateIndex == mStateVectorSize); assert(visited.full()); + return generationInfo; } + template + size_t DFT::generateStateInfo(DFTStateGenerationInfo& generationInfo, size_t id, storm::storage::BitVector& visited, size_t stateIndex) const { + assert(!visited[id]); + visited.set(id); + + // Reserve bits for element + generationInfo.addStateIndex(id, stateIndex); + stateIndex += 2; + + if (isRepresentative(id)) { + generationInfo.addSpareActivationIndex(id, stateIndex); + ++stateIndex; + } + + if (mElements[id]->isSpareGate()) { + generationInfo.addSpareUsageIndex(id, stateIndex); + stateIndex += generationInfo.usageInfoBits(); + } + + return stateIndex; + } + template size_t DFT::performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, storm::storage::BitVector& visited, size_t stateIndex) const { while (!visitQueue.empty()) { @@ -158,30 +194,14 @@ namespace storm { // Already visited continue; } - visited.set(id); - DFTElementPointer element = mElements[id]; + stateIndex = generateStateInfo(generationInfo, id, visited, stateIndex); // Insert children - if (element->isGate()) { - for (auto const& child : std::static_pointer_cast>(element)->children()) { + if (mElements[id]->isGate()) { + for (auto const& child : std::static_pointer_cast>(mElements[id])->children()) { visitQueue.push(child->id()); } } - - // Reserve bits for element - generationInfo.addStateIndex(id, stateIndex); - stateIndex += 2; - - if (isRepresentative(id)) { - generationInfo.addSpareActivationIndex(id, stateIndex); - ++stateIndex; - } - - if (element->isSpareGate()) { - generationInfo.addSpareUsageIndex(id, stateIndex); - stateIndex += generationInfo.usageInfoBits(); - } - } return stateIndex; } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index d3da06776..22d001aaf 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -41,6 +41,7 @@ namespace storm { std::map mSpareUsageIndex; // id spare -> index first bit in state std::map mSpareActivationIndex; // id spare representative -> index in state std::vector mIdToStateIndex; // id -> index first bit in state + std::vector>> mSymmetries; // pair (lenght of symmetry group, vector indicating the starting points of the symmetry groups) public: @@ -79,6 +80,24 @@ namespace storm { return mSpareActivationIndex.at(id); } + size_t addSymmetry(size_t lenght, std::vector& startingIndices) { + mSymmetries.push_back(std::make_pair(lenght, startingIndices)); + } + + size_t getSymmetrySize() { + return mSymmetries.size(); + } + + size_t getSymmetryLength(size_t pos) { + assert(pos < mSymmetries.size()); + return mSymmetries[pos].first; + } + + std::vector const& getSymmetryIndices(size_t pos) { + assert(pos < mSymmetries.size()); + return mSymmetries[pos].second; + } + friend std::ostream& operator<<(std::ostream& os, DFTStateGenerationInfo const& info) { os << "Id to state index:" << std::endl; for (size_t id = 0; id < info.mIdToStateIndex.size(); ++id) { @@ -92,6 +111,14 @@ namespace storm { for (auto pair : info.mSpareActivationIndex) { os << pair.first << " -> " << pair.second << std::endl; } + os << "Symmetries:" << std::endl; + for (auto pair : info.mSymmetries) { + os << "Length: " << pair.first << ", starting indices: "; + for (size_t index : pair.second) { + os << index << ", "; + } + os << std::endl; + } return os; } @@ -127,6 +154,8 @@ namespace storm { DFT(DFTElementVector const& elements, DFTElementPointer const& tle); DFTStateGenerationInfo buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const; + + size_t generateStateInfo(DFTStateGenerationInfo& generationInfo, size_t id, storm::storage::BitVector& visited, size_t stateIndex) const; size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, storm::storage::BitVector& visited, size_t stateIndex) const; From 2e8460548b9110a439a519b4e0facbdeb520a5d6 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 23 Feb 2016 13:52:48 +0100 Subject: [PATCH 153/246] Failed spares set use index to own id Former-commit-id: e4da5bd5d8d0400fed1531b2891422a918dc090c --- src/storage/dft/DFT.cpp | 10 +++++----- src/storage/dft/DFTElements.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index b61425953..eef83928d 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -263,10 +263,10 @@ namespace storm { stream << "\t** " << storm::storage::toChar(state->getElementState(elem->id())); if(elem->isSpareGate()) { size_t useId = state->uses(elem->id()); - if(state->isActive(useId)) { - stream << " actively "; + if(useId == elem->id() || state->isActive(useId)) { + stream << "actively "; } - stream << " using " << useId; + stream << "using " << useId; } } stream << std::endl; @@ -287,8 +287,8 @@ namespace storm { if(elem->isSpareGate()) { stream << "["; size_t useId = state->uses(elem->id()); - if(state->isActive(useId)) { - stream << " actively "; + if(useId == elem->id() || state->isActive(useId)) { + stream << "actively "; } stream << "using " << useId << "]"; } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index bb4be80a7..3236a5551 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -412,12 +412,12 @@ namespace storm { } /** - * Finish failed/failsafe spare gate by activating the children and setting the useIndex to zero. + * Finish failed/failsafe spare gate by activating the children and setting the useIndex to the spare id. * This prevents multiple fail states with different usages or activations. * @param state The current state. */ void finalizeSpare(DFTState& state) const { - state.setUses(this->mId, 0); + state.setUses(this->mId, this->mId); for (auto child : this->children()) { if (!state.isActive(child->id())) { state.activate(child->id()); From d1482723869c7571b6a53878d8b6a7dc5519d3f0 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 23 Feb 2016 14:24:44 +0100 Subject: [PATCH 154/246] Forgot const Former-commit-id: 5a748fadf912a65cc3cf332d43bf6ae8a16d3960 --- src/storage/dft/DFT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 22d001aaf..453db1443 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -84,16 +84,16 @@ namespace storm { mSymmetries.push_back(std::make_pair(lenght, startingIndices)); } - size_t getSymmetrySize() { + size_t getSymmetrySize() const { return mSymmetries.size(); } - size_t getSymmetryLength(size_t pos) { + size_t getSymmetryLength(size_t pos) const { assert(pos < mSymmetries.size()); return mSymmetries[pos].first; } - std::vector const& getSymmetryIndices(size_t pos) { + std::vector const& getSymmetryIndices(size_t pos) const { assert(pos < mSymmetries.size()); return mSymmetries[pos].second; } From cce39fbd5dc7eeaff21090f850e83b0522c91573 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 23 Feb 2016 18:57:41 +0100 Subject: [PATCH 155/246] Helper function for symmetry ordering on bitvector Former-commit-id: e98b004de6f93c4287e4a869483c0dce892f29c5 --- src/storage/dft/DFTState.cpp | 31 +++++++++++++++++++++++++++++++ src/storage/dft/DFTState.h | 6 ++++++ 2 files changed, 37 insertions(+) diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 7f34e03ef..591f6f9da 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -242,6 +242,37 @@ namespace storm { } return false; } + + template + bool DFTState::orderBySymmetry() { + bool changed = false; + for (size_t pos = 0; pos < mStateGenerationInfo.getSymmetrySize(); ++pos) { + // Check each symmetry + size_t length = mStateGenerationInfo.getSymmetryLength(pos); + std::vector symmetryIndices = mStateGenerationInfo.getSymmetryIndices(pos); + // Sort symmetry group in decreasing order by bubble sort + // TODO use better algorithm? + size_t tmp, elem1, elem2; + size_t n = symmetryIndices.size(); + do { + tmp = 0; + for (size_t i = 1; i < n; ++i) { + elem1 = mStatus.getAsInt(symmetryIndices[i-1], length); + elem2 = mStatus.getAsInt(symmetryIndices[i], length); + if (elem1 > elem2) { + // Swap elements + mStatus.setFromInt(symmetryIndices[i-1], length, elem2); + mStatus.setFromInt(symmetryIndices[i], length, elem1); + tmp = i; + changed = true; + } + } + n = tmp; + } while (n > 0); + } + return changed; + } + // Explicitly instantiate the class. template class DFTState; diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 7a26e10ab..eccf7f01d 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -164,6 +164,12 @@ namespace storm { */ void letDependencyBeUnsuccessful(size_t index = 0); + /** + * Order the state in decreasing order using the symmetries. + * @return True, if elements were swapped, false if nothing changed. + */ + bool orderBySymmetry(); + std::string getCurrentlyFailableString() const { std::stringstream stream; if (nrFailableDependencies() > 0) { From d340ea74253b17dae0c5cb790aa01aa4db05b0f8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 13:09:21 +0100 Subject: [PATCH 156/246] Helper function for replacing columns in SpareMatrix Former-commit-id: aa37022b7c3831988fe70e331860960685954f05 --- src/storage/SparseMatrix.cpp | 67 ++++++++++++++++++++++++++++++++++++ src/storage/SparseMatrix.h | 16 +++++++++ 2 files changed, 83 insertions(+) diff --git a/src/storage/SparseMatrix.cpp b/src/storage/SparseMatrix.cpp index d41e2ef2c..fa95f3930 100644 --- a/src/storage/SparseMatrix.cpp +++ b/src/storage/SparseMatrix.cpp @@ -220,6 +220,73 @@ namespace storm { return lastColumn; } + // Debug method for printing the current matrix + template + void print(std::vector::index_type> const& rowGroupIndices, std::vector::index_type, typename SparseMatrix::value_type>> const& columnsAndValues, std::vector::index_type> const& rowIndications) { + typename SparseMatrix::index_type endGroups; + typename SparseMatrix::index_type endRows; + // Iterate over all row groups. + for (typename SparseMatrix::index_type group = 0; group < rowGroupIndices.size(); ++group) { + std::cout << "\t---- group " << group << "/" << (rowGroupIndices.size() - 1) << " ---- " << std::endl; + endGroups = group < rowGroupIndices.size()-1 ? rowGroupIndices[group+1] : rowIndications.size(); + // Iterate over all rows in a row group + for (typename SparseMatrix::index_type i = rowGroupIndices[group]; i < endGroups; ++i) { + endRows = i < rowIndications.size()-1 ? rowIndications[i+1] : columnsAndValues.size(); + // Print the actual row. + std::cout << "Row " << i << " (" << rowIndications[i] << " - " << endRows << ")" << ": "; + for (typename SparseMatrix::index_type pos = rowIndications[i]; pos < endRows; ++pos) { + std::cout << "(" << columnsAndValues[pos].getColumn() << ": " << columnsAndValues[pos].getValue() << ") "; + } + std::cout << std::endl; + } + } + } + + template + bool SparseMatrixBuilder::replaceColumns(std::vector const& replacements, index_type offset) { + bool changed = false; + index_type maxColumn = 0; + for (auto& elem : columnsAndValues) { + if (elem.getColumn() >= offset) { + elem.setColumn(replacements[elem.getColumn() - offset]); + changed = true; + } + maxColumn = std::max(maxColumn, elem.getColumn()); + } + assert(changed || highestColumn == maxColumn); + highestColumn = maxColumn; + assert(changed || lastColumn == columnsAndValues[columnsAndValues.size() - 1].getColumn()); + lastColumn = columnsAndValues[columnsAndValues.size() - 1].getColumn(); + + if (changed) { + fixColumns(); + } + return changed; + } + + template + void SparseMatrixBuilder::fixColumns() { + // Sort columns per row + typename SparseMatrix::index_type endGroups; + typename SparseMatrix::index_type endRows; + for (index_type group = 0; group < rowGroupIndices.size(); ++group) { + endGroups = group < rowGroupIndices.size()-1 ? rowGroupIndices[group+1] : rowIndications.size(); + for (index_type i = rowGroupIndices[group]; i < endGroups; ++i) { + endRows = i < rowIndications.size()-1 ? rowIndications[i+1] : columnsAndValues.size(); + // Sort the row + std::sort(columnsAndValues.begin() + rowIndications[i], columnsAndValues.begin() + endRows, + [](MatrixEntry const& a, MatrixEntry const& b) { + return a.getColumn() < b.getColumn(); + }); + // Assert no equal elements + assert(std::is_sorted(columnsAndValues.begin() + rowIndications[i], columnsAndValues.begin() + endRows, + [](MatrixEntry const& a, MatrixEntry const& b) { + return a.getColumn() <= b.getColumn(); + })); + } + } + } + template SparseMatrix::rows::rows(iterator begin, index_type entryCount) : beginIterator(begin), entryCount(entryCount) { // Intentionally left empty. diff --git a/src/storage/SparseMatrix.h b/src/storage/SparseMatrix.h index f9d9916c4..4892dbe32 100644 --- a/src/storage/SparseMatrix.h +++ b/src/storage/SparseMatrix.h @@ -217,6 +217,17 @@ namespace storm { */ index_type getLastColumn() const; + /*! + * Replaces all columns with id > offset according to replacements. + * Every state with id offset+i is replaced by the id in replacements[i]. + * Afterwards the columns are sorted. + * + * @param replacements Mapping indicating the replacements from offset+i -> value of i. + * @param offset Offset to add to each id in vector index. + * @return True if replacement took place, False if nothing changed. + */ + bool replaceColumns(std::vector const& replacements, index_type offset); + private: // A flag indicating whether a row count was set upon construction. bool initialRowCountSet; @@ -277,6 +288,11 @@ namespace storm { // Stores the currently active row group. This is used for correctly constructing the row grouping of the // matrix. index_type currentRowGroup; + + /*! + * Fixes the matrix by sorting the columns to gain increasing order again. + */ + void fixColumns(); }; /*! From 8a77228e32dcf4930d31629e15a28f07145f41d5 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 13:28:13 +0100 Subject: [PATCH 157/246] Set value in BitVectorHashMap Former-commit-id: 2083df9c4abfa5484a694b59bc5e63be41361146 --- src/storage/BitVectorHashMap.cpp | 24 ++++++++++++++++++++++++ src/storage/BitVectorHashMap.h | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/storage/BitVectorHashMap.cpp b/src/storage/BitVectorHashMap.cpp index 4d6238350..08875af3b 100644 --- a/src/storage/BitVectorHashMap.cpp +++ b/src/storage/BitVectorHashMap.cpp @@ -140,6 +140,11 @@ namespace storm { return findOrAddAndGetBucket(key, value).first; } + template + void BitVectorHashMap::setOrAdd(storm::storage::BitVector const& key, ValueType const& value) { + setOrAddAndGetBucket(key, value); + } + template std::pair BitVectorHashMap::findOrAddAndGetBucket(storm::storage::BitVector const& key, ValueType const& value) { // If the load of the map is too high, we increase the size. @@ -161,6 +166,25 @@ namespace storm { } } + template + std::size_t BitVectorHashMap::setOrAddAndGetBucket(storm::storage::BitVector const& key, ValueType const& value) { + // If the load of the map is too high, we increase the size. + if (numberOfElements >= loadFactor * *currentSizeIterator) { + this->increaseSize(); + } + + std::tuple flagBucketTuple = this->findBucketToInsert(key); + STORM_LOG_ASSERT(!std::get<2>(flagBucketTuple), "Failed to find bucket for insertion."); + if (!std::get<0>(flagBucketTuple)) { + // Insert the new bits into the bucket. + buckets.set(std::get<1>(flagBucketTuple) * bucketSize, key); + occupied.set(std::get<1>(flagBucketTuple)); + ++numberOfElements; + } + values[std::get<1>(flagBucketTuple)] = value; + return std::get<1>(flagBucketTuple); + } + template ValueType BitVectorHashMap::getValue(storm::storage::BitVector const& key) const { std::pair flagBucketPair = this->findBucket(key); diff --git a/src/storage/BitVectorHashMap.h b/src/storage/BitVectorHashMap.h index d50dac59e..18ca52186 100644 --- a/src/storage/BitVectorHashMap.h +++ b/src/storage/BitVectorHashMap.h @@ -66,6 +66,15 @@ namespace storm { * @return The found value if the key is already contained in the map and the provided new value otherwise. */ ValueType findOrAdd(storm::storage::BitVector const& key, ValueType const& value); + + /*! + * Sets the given key value pain in the map. If the key is found in the map, the corresponding value is + * overwritten with the given value. Otherwise, the key is inserted with the given value. + * + * @param key The key to search or insert. + * @param value The value to set. + */ + void setOrAdd(storm::storage::BitVector const& key, ValueType const& value); /*! * Searches for the given key in the map. If it is found, the mapped-to value is returned. Otherwise, the @@ -79,6 +88,16 @@ namespace storm { */ std::pair findOrAddAndGetBucket(storm::storage::BitVector const& key, ValueType const& value); + /*! + * Sets the given key value pain in the map. If the key is found in the map, the corresponding value is + * overwritten with the given value. Otherwise, the key is inserted with the given value. + * + * @param key The key to search or insert. + * @param value The value to set. + * @return The index of the bucket into which the key was inserted. + */ + std::size_t setOrAddAndGetBucket(storm::storage::BitVector const& key, ValueType const& value); + /*! * Retrieves the key stored in the given bucket (if any) and the value it is mapped to. * From ea2fe4a19a8da9af321f455eeb8694e0d6d8b000 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 13:39:28 +0100 Subject: [PATCH 158/246] First working version of symmetry reduction Former-commit-id: e3641940d42b15b0c6177201960ffd052e165351 --- src/builder/ExplicitDFTModelBuilder.cpp | 90 +++++++++++++++++++++---- src/builder/ExplicitDFTModelBuilder.h | 6 +- 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index a1973d519..f14408190 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -134,7 +134,7 @@ namespace storm { bool ExplicitDFTModelBuilder::exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates) { // TODO Matthias: set Markovian states directly as bitvector? - std::map outgoingTransitions; + std::map outgoingTransitions; size_t rowOffset = 0; // Captures number of non-deterministic choices bool deterministic = true; @@ -221,23 +221,51 @@ namespace storm { newState->updateFailableDependencies(nextBE->id()); bool dftFailed = newState->hasFailed(mDft.getTopLevelIndex()); - size_t newStateId; + uint_fast64_t newStateId; if(dftFailed && mergeFailedStates) { newStateId = failedIndex; } else { - if (mStates.contains(newState->status())) { + // Order state by symmetry + STORM_LOG_TRACE("Check for symmetry: " << mDft.getStateString(newState)); + bool changed = newState->orderBySymmetry(); + STORM_LOG_TRACE("State " << (changed ? "changed to " : "did not change") << (changed ? mDft.getStateString(newState) : "")); + + // Check if state already exists + if (mStates.contains(newState->status())) { // State already exists newStateId = mStates.getValue(newState->status()); - STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " already exists"); + STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " with id " << newStateId << " already exists"); + + // Check if possible pseudo state can be created now + if (!changed && newStateId >= OFFSET_PSEUDO_STATE) { + newStateId = newStateId - OFFSET_PSEUDO_STATE; + assert(newStateId < mPseudoStatesMapping.size()); + if (mPseudoStatesMapping[newStateId] == 0) { + // Create pseudo state now + newState->setId(newIndex++); + mPseudoStatesMapping[newStateId] = newState->getId(); + newStateId = newState->getId(); + mStates.setOrAdd(newState->status(), newStateId); + stateQueue.push(newState); + STORM_LOG_TRACE("Now create state " << mDft.getStateString(newState) << " with id " << newStateId); + } + } } else { // New state - newState->setId(newIndex++); - newStateId = mStates.findOrAdd(newState->status(), newState->getId()); - STORM_LOG_TRACE("New state " << mDft.getStateString(newState)); - - // Add state to search queue - stateQueue.push(newState); - } + if (changed) { + // Remember to create state later on + newState->setId(mPseudoStatesMapping.size() + OFFSET_PSEUDO_STATE); + mPseudoStatesMapping.push_back(0); + newStateId = mStates.findOrAdd(newState->status(), newState->getId()); + STORM_LOG_TRACE("New state for later creation: " << mDft.getStateString(newState)); + } else { + // Create new state + newState->setId(newIndex++); + newStateId = mStates.findOrAdd(newState->status(), newState->getId()); + STORM_LOG_TRACE("New state: " << mDft.getStateString(newState)); + stateQueue.push(newState); + } + } } // Set transitions @@ -248,10 +276,11 @@ namespace storm { STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newStateId << " with probability " << dependency->probability()); if (!storm::utility::isOne(dependency->probability())) { + // TODO Matthias: use symmetry as well // Add transition to state where dependency was unsuccessful DFTStatePointer unsuccessfulState = std::make_shared>(*state); unsuccessfulState->letDependencyBeUnsuccessful(smallest-1); - size_t unsuccessfulStateId; + uint_fast64_t unsuccessfulStateId; if (mStates.contains(unsuccessfulState->status())) { // Unsuccessful state already exists unsuccessfulStateId = mStates.getValue(unsuccessfulState->status()); @@ -303,6 +332,38 @@ namespace storm { if (hasDependencies) { rowOffset--; // One increment to many } else { + // Try to merge pseudo states with their instantiation + // TODO Matthias: improve? + auto it = outgoingTransitions.begin(); + while (it != outgoingTransitions.end()) { + if (it->first >= OFFSET_PSEUDO_STATE) { + uint_fast64_t newId = it->first - OFFSET_PSEUDO_STATE; + assert(newId < mPseudoStatesMapping.size()); + if (mPseudoStatesMapping[newId] > 0) { + // State exists already + newId = mPseudoStatesMapping[newId]; + auto itFind = outgoingTransitions.find(newId); + if (itFind != outgoingTransitions.end()) { + // Add probability from pseudo state to instantiation + itFind->second += it->second; + STORM_LOG_TRACE("Merged pseudo state " << newId << " adding rate " << it->second << " to total rate of " << itFind->second); + } else { + // Only change id + outgoingTransitions.emplace(newId, it->second); + STORM_LOG_TRACE("Instantiated pseudo state " << newId << " with rate " << it->second); + } + // Remove pseudo state + auto itErase = it; + ++it; + outgoingTransitions.erase(itErase); + } else { + ++it; + } + } else { + ++it; + } + } + // Add all probability transitions for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ++it) { @@ -316,6 +377,11 @@ namespace storm { assert(exitRates.size()-1 == state->getId()); } // end while queue + assert(std::find(mPseudoStatesMapping.begin(), mPseudoStatesMapping.end(), 0) == mPseudoStatesMapping.end()); + + // Replace pseudo states in matrix + transitionMatrixBuilder.replaceColumns(mPseudoStatesMapping, OFFSET_PSEUDO_STATE); + assert(!deterministic || rowOffset == 0); return deterministic; } diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 6d17375b2..b9008f91e 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -47,12 +47,12 @@ namespace storm { }; const size_t INITIAL_BUCKETSIZE = 20000; - - + const uint_fast64_t OFFSET_PSEUDO_STATE = UINT_FAST64_MAX / 2; storm::storage::DFT const& mDft; std::shared_ptr mStateGenerationInfo; - storm::storage::BitVectorHashMap mStates; + storm::storage::BitVectorHashMap mStates; + std::vector mPseudoStatesMapping; size_t newIndex = 0; bool mergeFailedStates = true; size_t failedIndex = 0; From 1e9fedb7ba4f18b383b86fb3700591dd57840848 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 13:55:24 +0100 Subject: [PATCH 159/246] Order symmetries in decreasing order Former-commit-id: 7ba21b0b9e20ae04998040350c66a7963276dba0 --- examples/dft/symmetry5.dft | 21 +++++++++++++++++++++ src/storage/dft/DFTState.cpp | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 examples/dft/symmetry5.dft diff --git a/examples/dft/symmetry5.dft b/examples/dft/symmetry5.dft new file mode 100644 index 000000000..18f700bb2 --- /dev/null +++ b/examples/dft/symmetry5.dft @@ -0,0 +1,21 @@ +toplevel "A"; +"A" and "BA" "BB" "BC" "BD" "BE" "BF"; +"BA" and "CA" "DA"; +"BB" and "CB" "DB"; +"BC" and "CC" "DC"; +"BD" and "CD" "DD"; +"BE" and "CE" "DE"; +"BF" and "CF" "DF"; +"CA" lambda=0.5 dorm=0; +"DA" lambda=0.5 dorm=0; +"CB" lambda=0.5 dorm=0; +"DB" lambda=0.5 dorm=0; +"CC" lambda=0.5 dorm=0; +"DC" lambda=0.5 dorm=0; +"CD" lambda=0.5 dorm=0; +"DD" lambda=0.5 dorm=0; +"CE" lambda=0.5 dorm=0; +"DE" lambda=0.5 dorm=0; +"CF" lambda=0.5 dorm=0; +"DF" lambda=0.5 dorm=0; + diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 591f6f9da..be5c33060 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -259,7 +259,7 @@ namespace storm { for (size_t i = 1; i < n; ++i) { elem1 = mStatus.getAsInt(symmetryIndices[i-1], length); elem2 = mStatus.getAsInt(symmetryIndices[i], length); - if (elem1 > elem2) { + if (elem1 < elem2) { // Swap elements mStatus.setFromInt(symmetryIndices[i-1], length, elem2); mStatus.setFromInt(symmetryIndices[i], length, elem1); From 490f232d7ab36fb17ea1d08ecd6f7781668688fb Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 14:28:24 +0100 Subject: [PATCH 160/246] Example for possible pdep symmetry Former-commit-id: 1ea07bd19666aa9ce5060e98d8ec397a8ca3ea3e --- examples/dft/pdep_symmetry.dft | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 examples/dft/pdep_symmetry.dft diff --git a/examples/dft/pdep_symmetry.dft b/examples/dft/pdep_symmetry.dft new file mode 100644 index 000000000..43224d790 --- /dev/null +++ b/examples/dft/pdep_symmetry.dft @@ -0,0 +1,11 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D" "PDEP"; +"B'" and "C'" "D'" "PDEP'"; +"PDEP" pdep=0.6 "B" "C"; +"PDEP'" pdep=0.6 "B'" "C'"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; +"D'" lambda=0.5 dorm=0; + From 91970cea72d118db128c79dc89669c89ea2c3216 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 24 Feb 2016 15:28:58 +0100 Subject: [PATCH 161/246] intermediate commit Former-commit-id: 2de6f9106211db3f5f04ac76cf101c9142a33a65 --- src/storage/dft/DFT.h | 2 +- src/storage/dft/DFTElements.cpp | 11 +++++++--- src/storage/dft/DFTElements.h | 37 ++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 1f3e8cceb..f0e08b31a 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -41,7 +41,7 @@ namespace storm { std::map mSpareUsageIndex; // id spare -> index first bit in state std::map mSpareActivationIndex; // id spare representative -> index in state std::vector mIdToStateIndex; // id -> index first bit in state - + std::map mRestrictedItems; public: DFTStateGenerationInfo(size_t nrElements) : mUsageInfoBits(nrElements > 1 ? storm::utility::math::uint64_log2(nrElements-1) + 1 : 1), mIdToStateIndex(nrElements) { diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 7bb8c2cf5..81c78ccc6 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -24,9 +24,6 @@ namespace storm { } } - - - state.setDontCare(mId); return true; } @@ -85,6 +82,14 @@ namespace storm { } } + + for(auto const& restr : mRestrictions) { + restr->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(elemsInSubtree.empty()) { + return; + } + } + } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index bb4be80a7..00688f36e 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -200,6 +200,40 @@ namespace storm { return mOutgoingDependencies.size(); } + std::set> restrictedItems() const { + std::set> result; + for(auto const& restr : mRestrictions) { + bool foundThis = false; + for(auto const& child : restr->children()) { + if(!foundThis) { + if(child->id() == mId) { + foundThis = true; + } + } else if(result.count(child) == 0) { + result.insert(child); + } + } + } + } + + std::set> restrictedItemsTC() const { + std::set> result; + for(auto const& restr : mRestrictions) { + bool foundThis = false; + for(auto const& child : restr->children()) { + if(!foundThis) { + if(child->id() == mId) { + foundThis = true; + } + } else if(result.count(child) == 0) { + result.insert(child); + std::set> tmpRes = child->restrictedItemsTC(); + result.insert(tmpRes.begin(), tmpRes.end()); + } + } + } + } + DFTDependencyVector const& outgoingDependencies() const { return mOutgoingDependencies; } @@ -784,9 +818,6 @@ namespace storm { return os << gate.toString(); } - - - template class DFTPand : public DFTGate { From 6b166952e88bf60c23f13913dbe918c4145d76df Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 24 Feb 2016 16:33:20 +0100 Subject: [PATCH 162/246] output operators for element type Former-commit-id: 8298f03f5e0c260394d1eeb542289e100d053ba9 --- src/storage/dft/DFTElementType.h | 36 +++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/DFTElementType.h b/src/storage/dft/DFTElementType.h index d4bf3bfc2..8b8035d45 100644 --- a/src/storage/dft/DFTElementType.h +++ b/src/storage/dft/DFTElementType.h @@ -6,7 +6,6 @@ namespace storm { enum class DFTElementType : int {AND = 0, OR = 2, VOT = 3, BE = 4, CONSTF = 5, CONSTS = 6, PAND = 7, SPARE = 8, POR = 9, PDEP = 10, SEQ = 11, MUTEX=12}; - inline bool isGateType(DFTElementType const& tp) { switch(tp) { case DFTElementType::AND: @@ -29,7 +28,6 @@ namespace storm { } } - inline bool isStaticGateType(DFTElementType const& tp) { if(!isGateType(tp)) return false; switch(tp) { @@ -46,7 +44,39 @@ namespace storm { return false; } } - + + inline std::string toString(DFTElementType const& tp) { + switch(tp) { + case DFTElementType::BE: + return "BE"; + case DFTElementType::OR: + return "OR"; + case DFTElementType::AND: + return "AND"; + case DFTElementType::VOT: + return "VOT"; + case DFTElementType::POR: + return "POR"; + case DFTElementType::PAND: + return "PAND"; + case DFTElementType::SPARE: + return "SPARE"; + case DFTElementType::SEQ: + return "SEQ"; + case DFTElementType::MUTEX: + return "MUTEX"; + case DFTElementType::PDEP: + return "PDEP"; + default: + assert(false); + } + } + + inline std::ostream& operator<<(std::ostream& os, DFTElementType const& tp) { + return os << toString(tp) << std::endl; + } + + } } From 084bc26a5f93315a77506cb6f4a1dd6e0e9e5239 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 24 Feb 2016 16:34:44 +0100 Subject: [PATCH 163/246] fixed some things with respect to SEQs Former-commit-id: 8460c4b5a59f86f4e195248704f1a08384744c63 --- src/storage/dft/DFT.cpp | 1 + src/storage/dft/DFTBuilder.cpp | 3 +-- src/storage/dft/DFTElements.cpp | 1 + src/storage/dft/DFTIsomorphism.h | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index eef83928d..3d2b09088 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -333,6 +333,7 @@ namespace storm { for(auto it1 = colourClass.second.cbegin(); it1 != colourClass.second.cend(); ++it1) { std::vector> symClass; if(foundEqClassFor.count(*it1) > 0) { + // This item is already in a class. continue; } if(!getGate(*it1)->hasOnlyStaticParents()) { diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 213fce0df..5e5c3da84 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -116,8 +116,7 @@ namespace storm { DFTRestrictionPointer restr; switch (tp) { case DFTElementType::SEQ: - restr = std::make_shared> - (mNextId++, name); + restr = std::make_shared>(mNextId++, name); break; case DFTElementType::MUTEX: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 81c78ccc6..f11f0b99f 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -1,6 +1,7 @@ #include #include #include "DFTElements.h" +#include "elements/DFTRestriction.h" namespace storm { namespace storage { diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 0d5590d3d..498170368 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -207,6 +207,7 @@ namespace storage { } void colourize(std::shared_ptr> const& gate) { + std::cout << "Colour " << gate->id() << ": " << gate->type() << " " << gate->nrChildren() << " " << gate->rank() << "." << std::endl; gateColour[gate->id()] = gateColourizer(gate->type(), gate->nrChildren(), gate->nrParents(), 0, gate->rank()); } From 5b6dcd0eed4fb795c810ab41f947ccb2fb57af92 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 18:14:18 +0100 Subject: [PATCH 164/246] UsageIndex is number of used child now Former-commit-id: 629aeae3182982c94900a8b890f4a1b81ac8021c --- examples/dft/spare_symmetry.dft | 9 +++++++++ src/storage/dft/DFT.cpp | 29 +++++++++++++++++++++++++---- src/storage/dft/DFT.h | 12 +++++++++++- src/storage/dft/DFTElements.h | 4 ++-- src/storage/dft/DFTState.cpp | 15 +++++++++++++-- src/storage/dft/DFTState.h | 11 +++++++++-- 6 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 examples/dft/spare_symmetry.dft diff --git a/examples/dft/spare_symmetry.dft b/examples/dft/spare_symmetry.dft new file mode 100644 index 000000000..04b5c253b --- /dev/null +++ b/examples/dft/spare_symmetry.dft @@ -0,0 +1,9 @@ +toplevel "A"; +"A" and "B" "C"; +"B" wsp "I" "J"; +"C" wsp "K" "L"; +"I" lambda=0.5 dorm=0.3; +"J" lambda=0.5 dorm=0.3; +"K" lambda=0.5 dorm=0.3; +"L" lambda=0.5 dorm=0.3; + diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index eef83928d..2924789fd 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -11,7 +11,7 @@ namespace storm { namespace storage { template - DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mTopLevelIndex(tle->id()) { + DFT::DFT(DFTElementVector const& elements, DFTElementPointer const& tle) : mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mTopLevelIndex(tle->id()), mMaxSpareChildCount(0) { assert(elementIndicesCorrect()); size_t nrRepresentatives = 0; @@ -25,6 +25,7 @@ namespace storm { else if (elem->isSpareGate()) { ++mNrOfSpares; bool firstChild = true; + mMaxSpareChildCount = std::max(mMaxSpareChildCount, std::static_pointer_cast>(elem)->children().size()); for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { std::set module = {spareReprs->id()}; spareReprs->extendSpareModule(module); @@ -63,7 +64,9 @@ namespace storm { } mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); - size_t usageInfoBits = mElements.size() > 1 ? storm::utility::math::uint64_log2(mElements.size()-1) + 1 : 1; + //Reserve space for failed spares + ++mMaxSpareChildCount; + size_t usageInfoBits = storm::utility::math::uint64_log2(mMaxSpareChildCount) + 1; mStateVectorSize = nrElements() * 2 + mNrOfSpares * usageInfoBits + nrRepresentatives; } @@ -73,7 +76,7 @@ namespace storm { // Collect all elements in the first subtree // TODO make recursive to use for nested subtrees - DFTStateGenerationInfo generationInfo(nrElements()); + DFTStateGenerationInfo generationInfo(nrElements(), mMaxSpareChildCount); // Perform DFS and insert all elements of subtree sequentially size_t stateIndex = 0; @@ -296,7 +299,25 @@ namespace storm { } return stream.str(); } - + + template + size_t DFT::getChild(size_t spareId, size_t nrUsedChild) const { + assert(mElements[spareId]->isSpareGate()); + return getGate(spareId)->children()[nrUsedChild]->id(); + } + + template + size_t DFT::getNrChild(size_t spareId, size_t childId) const { + assert(mElements[spareId]->isSpareGate()); + DFTElementVector children = getGate(spareId)->children(); + for (size_t nrChild = 0; nrChild < children.size(); ++nrChild) { + if (children[nrChild]->id() == childId) { + return nrChild; + } + } + assert(false); + } + template std::vector DFT::getIndependentSubDftRoots(size_t index) const { auto elem = getElement(index); diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 453db1443..48bb60f68 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -45,7 +45,8 @@ namespace storm { public: - DFTStateGenerationInfo(size_t nrElements) : mUsageInfoBits(nrElements > 1 ? storm::utility::math::uint64_log2(nrElements-1) + 1 : 1), mIdToStateIndex(nrElements) { + DFTStateGenerationInfo(size_t nrElements, size_t maxSpareChildCount) : mUsageInfoBits(storm::utility::math::uint64_log2(maxSpareChildCount) + 1), mIdToStateIndex(nrElements) { + assert(maxSpareChildCount < pow(2, mUsageInfoBits)); } size_t usageInfoBits() const { @@ -144,6 +145,7 @@ namespace storm { size_t mNrOfSpares; size_t mTopLevelIndex; size_t mStateVectorSize; + size_t mMaxSpareChildCount; std::map> mSpareModules; std::vector mDependencies; std::vector mTopModule; @@ -175,6 +177,10 @@ namespace storm { return mTopLevelIndex; } + size_t getMaxSpareChildCount() const { + return mMaxSpareChildCount; + } + std::vector getSpareIndices() const { std::vector indices; for(auto const& elem : mElements) { @@ -288,6 +294,10 @@ namespace storm { return storm::storage::DFTState::isFailsafe(state, stateGenerationInfo.getStateIndex(mTopLevelIndex)); } + size_t getChild(size_t spareId, size_t nrUsedChild) const; + + size_t getNrChild(size_t spareId, size_t childId) const; + std::string getElementsString() const; std::string getInfoString() const; diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 3236a5551..48318d0ae 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -412,12 +412,12 @@ namespace storm { } /** - * Finish failed/failsafe spare gate by activating the children and setting the useIndex to the spare id. + * Finish failed/failsafe spare gate by activating the children and setting the useIndex to the maximum value. * This prevents multiple fail states with different usages or activations. * @param state The current state. */ void finalizeSpare(DFTState& state) const { - state.setUses(this->mId, this->mId); + state.finalizeUses(this->mId); for (auto child : this->children()) { if (!state.isActive(child->id())) { state.activate(child->id()); diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index be5c33060..8af84255c 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -201,7 +201,12 @@ namespace storm { template uint_fast64_t DFTState::uses(size_t id) const { - return extractUses(mStateGenerationInfo.getSpareUsageIndex(id)); + size_t nrUsedChild = extractUses(mStateGenerationInfo.getSpareUsageIndex(id)); + if (nrUsedChild == mDft.getMaxSpareChildCount()) { + return id; + } else { + return mDft.getChild(id, nrUsedChild); + } } template @@ -217,9 +222,15 @@ namespace storm { template void DFTState::setUses(size_t spareId, size_t child) { - mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), child); + mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), mDft.getNrChild(spareId, child)); mUsedRepresentants.push_back(child); } + + template + void DFTState::finalizeUses(size_t spareId) { + assert(hasFailed(spareId)); + mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), mDft.getMaxSpareChildCount()); + } template bool DFTState::claimNew(size_t spareId, size_t currentlyUses, std::vector>> const& children) { diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index eccf7f01d..ea874cf1b 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -93,9 +93,10 @@ namespace storm { } /** - * This method gets the usage information for a spare + * This method returns the id of the used child for a spare. If no element is used, it returns the given id. * @param id Id of the spare - * @return The child that currently is used. + * @return The id of the currently used child or if non is used (because of spare failure) the id of + * the spare. */ uint_fast64_t uses(size_t id) const; @@ -120,6 +121,12 @@ namespace storm { */ void setUses(size_t spareId, size_t child); + /** + * Sets the use for the spare to a default value to gain consistent states after failures. + * @param spareId Id of the spare + */ + void finalizeUses(size_t spareId); + bool claimNew(size_t spareId, size_t currentlyUses, std::vector>> const& children); bool hasOutgoingEdges() const { From d32d90de5b7f5a75062ecd1146077b99d4c0489c Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 24 Feb 2016 18:18:19 +0100 Subject: [PATCH 165/246] Fixed some compile warnings Former-commit-id: 91055b14cff62f8a06b7cbfad79f504a83f44563 --- src/storage/dft/DFT.h | 4 ++-- src/storage/dft/elements/DFTRestriction.h | 2 +- src/storm-dyftee.cpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 48bb60f68..7d10b2ee1 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -81,8 +81,8 @@ namespace storm { return mSpareActivationIndex.at(id); } - size_t addSymmetry(size_t lenght, std::vector& startingIndices) { - mSymmetries.push_back(std::make_pair(lenght, startingIndices)); + void addSymmetry(size_t length, std::vector& startingIndices) { + mSymmetries.push_back(std::make_pair(length, startingIndices)); } size_t getSymmetrySize() const { diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index 46b6e23cc..d0482e4a7 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -183,7 +183,7 @@ namespace storm { } - bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) { + bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index ba50d90f3..07bff5732 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -32,7 +32,6 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) { - std::cout << dft.getElementsString() << std::endl; auto colouring = dft.colourDFT(); symmetries = dft.findSymmetries(colouring); std::cout << "Symmetries: " << symmetries << std::endl; From 9c30394b33ce72e4a7b467743910061ae8c49d09 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 25 Feb 2016 14:59:27 +0100 Subject: [PATCH 166/246] Finalize sparse for failed, failsafe, dontcare Former-commit-id: 722285c8d5e4c4d350ae56150bb287f1c8c5d298 --- src/storage/dft/DFTElements.cpp | 13 +++++++--- src/storage/dft/DFTElements.h | 42 ++++++++++++++++----------------- src/storage/dft/DFTState.cpp | 8 ++++--- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index 7bb8c2cf5..3f1d30017 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -17,17 +17,24 @@ namespace storm { return false; } } + + bool hasParentSpare = false; + // Check that no parent can fail anymore for(DFTGatePointer const& parent : mParents) { if(state.isOperational(parent->id())) { return false; } + if (parent->isSpareGate()) { + hasParentSpare = true; + } } - - - state.setDontCare(mId); + if (hasParentSpare && !state.isActive(mId)) { + // Activate child for consistency in failed spares + state.activate(mId); + } return true; } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 48318d0ae..0b970355f 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -387,10 +387,6 @@ namespace storm { queues.checkRestrictionLater(restr); } state.setFailed(this->mId); - // TODO can this be moved towards DFTSpare? - if (this->isSpareGate()) { - this->finalizeSpare(state); - } this->childrenDontCare(state, queues); } @@ -401,30 +397,13 @@ namespace storm { } } state.setFailsafe(this->mId); - if (this->isSpareGate()) { - this->finalizeSpare(state); - } this->childrenDontCare(state, queues); } - + void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { queues.propagateDontCare(mChildren); } - /** - * Finish failed/failsafe spare gate by activating the children and setting the useIndex to the maximum value. - * This prevents multiple fail states with different usages or activations. - * @param state The current state. - */ - void finalizeSpare(DFTState& state) const { - state.finalizeUses(this->mId); - for (auto child : this->children()) { - if (!state.isActive(child->id())) { - state.activate(child->id()); - } - } - } - bool hasFailsafeChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.isFailsafe(child->id())) @@ -959,6 +938,24 @@ namespace storm { return true; } + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + DFTGate::fail(state, queues); + state.finalizeUses(this->mId); + } + + void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + DFTGate::failsafe(state, queues); + state.finalizeUses(this->mId); + } + + bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if (DFTGate::checkDontCareAnymore(state, queues)) { + state.finalizeUses(this->mId); + return true; + } + return false; + } + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(state.isOperational(this->mId)) { size_t uses = state.uses(this->mId); @@ -979,6 +976,7 @@ namespace storm { } } } + }; template diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 8af84255c..7d3b25c8a 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -179,7 +179,6 @@ namespace storm { size_t activationIndex = mStateGenerationInfo.getSpareActivationIndex(repr); assert(!mStatus[activationIndex]); mStatus.set(activationIndex); - propagateActivation(repr); } template @@ -190,11 +189,14 @@ namespace storm { template void DFTState::propagateActivation(size_t representativeId) { + if (representativeId != mDft.getTopLevelIndex()) { + activate(representativeId); + } for(size_t elem : mDft.module(representativeId)) { if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { mIsCurrentlyFailableBE.push_back(elem); } else if (mDft.getElement(elem)->isSpareGate() && !isActive(uses(elem))) { - activate(uses(elem)); + propagateActivation(uses(elem)); } } } @@ -245,7 +247,7 @@ namespace storm { if(!hasFailed(childId) && !isUsed(childId)) { setUses(spareId, childId); if(isActive(currentlyUses)) { - activate(childId); + propagateActivation(childId); } return true; } From f6374c60f8bb562661b625440d3a73f4c380cf0f Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 26 Feb 2016 11:25:50 +0100 Subject: [PATCH 167/246] Bitte ein Bit Former-commit-id: ff11916b9a2d5a37074404e6025d8ebfe769ac03 --- src/storage/BitVector.cpp | 124 +++++++++++++++++++++++++++++++++++ src/storage/BitVector.h | 36 ++++++++++ src/storage/dft/DFTState.cpp | 9 +-- 3 files changed, 162 insertions(+), 7 deletions(-) diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index dff4b2f5f..02e40aa59 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -10,6 +10,12 @@ #include "src/utility/Hash.h" #include "src/utility/macros.h" +#include + +#ifndef NDEBUG +//#define ASSERT_BITVECTOR +#endif + namespace storm { namespace storage { @@ -413,6 +419,7 @@ namespace storm { } uint_fast64_t BitVector::getAsInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits) const { + assert(numberOfBits <= 64); uint64_t bucket = bitIndex >> 6; uint64_t bitIndexInBucket = bitIndex & mod64mask; @@ -662,6 +669,103 @@ namespace storm { } return endIndex; } + + BitVector BitVector::getAsBitVector(uint_fast64_t start, uint_fast64_t length) { + BitVector result(length); + + uint_fast64_t index = 0; + for ( ; index + 63 <= length; index += 63) { + result.setFromInt(index, 63, getAsInt(start + index, 63)); + } + // Insert remaining bits + result.setFromInt(index, length-index, getAsInt(start+index, length-index)); + +#ifdef ASSERT_BITVECTOR + // Check correctness of getter + for (uint_fast64_t i = 0; i < length; ++i) { + STORM_LOG_ASSERT(result.get(i) == get(start + i), "Getting of bits not correct for index " << i); + } +#endif + return result; + } + + void BitVector::setFromBitVector(uint_fast64_t start, BitVector const& other) { + uint_fast64_t index = 0; + for ( ; index + 63 <= other.bitCount; index += 63) { + setFromInt(start+index, 63, other.getAsInt(index, 63)); + } + // Insert remaining bits + setFromInt(start+index, other.bitCount-index, other.getAsInt(index, other.bitCount-index)); + +#ifdef ASSERT_BITVECTOR + // Check correctness of setter + for (uint_fast64_t i = 0; i < other.bitCount; ++i) { + STORM_LOG_ASSERT(other.get(i) == get(start + i), "Setting of bits not correct for index " << i); + } +#endif + } + + bool BitVector::compareAndSwap(uint_fast64_t start1, uint_fast64_t start2, uint_fast64_t length) { + if (length < 64) { + uint_fast64_t elem1 = getAsInt(start1, length); + uint_fast64_t elem2 = getAsInt(start2, length); + if (elem1 < elem2) { + // Swap elements + setFromInt(start1, length, elem2); + setFromInt(start2, length, elem1); + return true; + } + return false; + } else { + //TODO improve performance + BitVector elem1 = getAsBitVector(start1, length); + BitVector elem2 = getAsBitVector(start2, length); + + if (!(elem1 < elem2)) { + // Elements already sorted +#ifdef ASSERT_BITVECTOR + // Check that sorted + for (uint_fast64_t i = 0; i < length; ++i) { + if (get(start1 + i) > get(start2 + i)) { + break; + } + STORM_LOG_ASSERT(get(start1 + i) >= get(start2 + i), "Bit vector not sorted for indices " << start1+i << " and " << start2+i); + } +#endif + return false; + } + +#ifdef ASSERT_BITVECTOR + BitVector check(*this); +#endif + + // Swap elements + setFromBitVector(start1, elem2); + setFromBitVector(start2, elem1); + +#ifdef ASSERT_BITVECTOR + // Check correctness of swapping + bool tmp; + for (uint_fast64_t i = 0; i < length; ++i) { + tmp = check.get(i + start1); + check.set(i + start1, check.get(i + start2)); + check.set(i + start2, tmp); + } + STORM_LOG_ASSERT(*this == check, "Swapping not correct"); + + // Check that sorted + for (uint_fast64_t i = 0; i < length; ++i) { + if (get(start1 + i) > get(start2 + i)) { + break; + } + STORM_LOG_ASSERT(get(start1 + i) >= get(start2 + i), "Bit vector not sorted for indices " << start1+i << " and " << start2+i); + } +#endif + + return true; + } + } + void BitVector::truncateLastBucket() { if ((bitCount & mod64mask) != 0) { @@ -682,6 +786,26 @@ namespace storm { return out; } + + void BitVector::printBits(std::ostream& out) { + out << "bit vector(" << getNumberOfSetBits() << "/" << bitCount << ") "; + uint_fast64_t index = 0; + for ( ; index * 64 <= bitCount; ++index) { + std::bitset<64> tmp(bucketVector[index]); + out << tmp << "|"; + } + + --index; + // Print last bits + if (index * 64 < bitCount) { + assert(index == bucketVector.size() - 1); + std::bitset<64> tmp(bucketVector[index]); + for (size_t i = 0; i + index * 64 < bitCount; ++i) { + out << tmp[i]; + } + } + out << std::endl; + } std::size_t NonZeroBitVectorHash::operator()(storm::storage::BitVector const& bv) const { STORM_LOG_ASSERT(bv.size() > 0, "Cannot hash bit vector of zero size."); diff --git a/src/storage/BitVector.h b/src/storage/BitVector.h index 695bdcb82..e3f81ebc9 100644 --- a/src/storage/BitVector.h +++ b/src/storage/BitVector.h @@ -461,6 +461,17 @@ namespace storm { */ uint_fast64_t getNextSetIndex(uint_fast64_t startingIndex) const; + /* + * Compare two intervals [start1, start1+length] and [start2, start2+length] and swap them if the second + * one is larger than the first one. After the method the intervals are sorted in decreasing order. + * + * @param start1 Starting index of first interval. + * @param start2 Starting index of second interval. + * @param length Length of both intervals. + * @return True, if the intervals were swapped, false if nothing changed. + */ + bool compareAndSwap(uint_fast64_t start1, uint_fast64_t start2, uint_fast64_t length); + friend std::ostream& operator<<(std::ostream& out, BitVector const& bitVector); friend struct std::hash; friend struct NonZeroBitVectorHash; @@ -490,6 +501,31 @@ namespace storm { */ void truncateLastBucket(); + /*! Retrieves the content of the current bit vector at the given index for the given number of bits as a new + * bit vector. + * + * @param start The index of the first bit to get. + * @param length The number of bits to get. + * @return A new bit vector holding the selected bits. + */ + BitVector getAsBitVector(uint_fast64_t start, uint_fast64_t length); + + /*! + * Sets the exact bit pattern of the given bit vector starting at the given bit index. Note: the given bit + * vector must be shorter than the current one minus the given index. + * + * @param start The index of the first bit that is supposed to be set. + * @param other The bit vector whose pattern to set. + */ + void setFromBitVector(uint_fast64_t start, BitVector const& other); + + /*! + * Print bit vector and display all bits. + * + * @param out Stream to print to. + */ + void printBits(std::ostream& out); + /*! * Retrieves the number of buckets of the underlying storage. * diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 7d3b25c8a..547fdd169 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -265,17 +265,12 @@ namespace storm { std::vector symmetryIndices = mStateGenerationInfo.getSymmetryIndices(pos); // Sort symmetry group in decreasing order by bubble sort // TODO use better algorithm? - size_t tmp, elem1, elem2; + size_t tmp; size_t n = symmetryIndices.size(); do { tmp = 0; for (size_t i = 1; i < n; ++i) { - elem1 = mStatus.getAsInt(symmetryIndices[i-1], length); - elem2 = mStatus.getAsInt(symmetryIndices[i], length); - if (elem1 < elem2) { - // Swap elements - mStatus.setFromInt(symmetryIndices[i-1], length, elem2); - mStatus.setFromInt(symmetryIndices[i], length, elem1); + if (mStatus.compareAndSwap(symmetryIndices[i-1], symmetryIndices[i], length)) { tmp = i; changed = true; } From 73c88a4faf02b85dc9e68208b9281618e1be2bd0 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 13:37:27 +0100 Subject: [PATCH 168/246] update on restrictions Former-commit-id: 5b14895f07bd6c5be922bcda2b0db0ff320b02ce --- src/storage/dft/DFT.cpp | 6 ++--- src/storage/dft/DFTBuilder.cpp | 11 +------- src/storage/dft/DFTElements.cpp | 14 +++++----- src/storage/dft/DFTElements.h | 32 +++++++++++------------ src/storage/dft/elements/DFTRestriction.h | 14 +++++----- 5 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c46b9d84c..2aa557d8c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -321,7 +321,7 @@ namespace storm { template std::vector DFT::getIndependentSubDftRoots(size_t index) const { auto elem = getElement(index); - auto ISD = elem->independentSubDft(); + auto ISD = elem->independentSubDft(false); return ISD; } @@ -373,8 +373,8 @@ namespace storm { if(influencedElem1Ids == getSortedParentAndOutDepIds(*it2)) { std::cout << "Considering ids " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; bool isSymmetry = false; - std::vector isubdft1 = getGate(*it1)->independentSubDft(); - std::vector isubdft2 = getGate(*it2)->independentSubDft(); + std::vector isubdft1 = getGate(*it1)->independentSubDft(false); + std::vector isubdft2 = getGate(*it2)->independentSubDft(false); if(isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) { continue; } diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 5e5c3da84..e3889bf4d 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -57,16 +57,7 @@ namespace storm { dependentEvent->addIngoingDependency(dependency); } -// for (auto& restriction : mRestrictions) { -// std::set parentsOfRestrictedElements; -// for (auto& child : restriction->children()) { -// for(DFTGatePointer& parent : child->parents()) { -// parentsOfRestrictedElements.insert(parent); -// } -// } -// -// -// } + // Sort elements topologically // compute rank diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp index ecb6c049c..4cf49e0b0 100644 --- a/src/storage/dft/DFTElements.cpp +++ b/src/storage/dft/DFTElements.cpp @@ -63,7 +63,7 @@ namespace storm { } template - std::vector DFTElement::independentSubDft() const { + std::vector DFTElement::independentSubDft(bool blockParents) const { //std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; std::vector res; res.push_back(this->id()); @@ -71,7 +71,7 @@ namespace storm { } template - void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const { + void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const { if(elemsInSubtree.count(this->id()) > 0) return; if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { // This is a parent of the suspected root, thus it is not a subdft. @@ -80,14 +80,16 @@ namespace storm { } elemsInSubtree.insert(mId); for(auto const& parent : mParents) { - - parent->extendSubDft(elemsInSubtree, parentsOfSubRoot); + if(blockParents && std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), parent->id()) != parentsOfSubRoot.end()) { + continue; + } + parent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { return; } } for(auto const& dep : mOutgoingDependencies) { - dep->extendSubDft(elemsInSubtree, parentsOfSubRoot); + dep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { return; } @@ -95,7 +97,7 @@ namespace storm { } for(auto const& restr : mRestrictions) { - restr->extendSubDft(elemsInSubtree, parentsOfSubRoot); + restr->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { return; } diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index 43db2c46e..dc07505bd 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -262,15 +262,15 @@ namespace storm { /** * Computes independent subtrees starting with this element (this), that is, all elements (x) which are connected to either * - one of the children of the element, - * - a propabilisistic dependency + * - a probabilistic dependency * such that there exists a path from x to a child of this does not go through this. */ - virtual std::vector independentSubDft() const; + virtual std::vector independentSubDft(bool blockParents) const; /** * Helper to the independent subtree computation * @see independentSubDft */ - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const; + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const; virtual bool isTypeEqualTo(DFTElement const& other) const { return type() == other.type(); @@ -351,8 +351,8 @@ namespace storm { } } - virtual std::vector independentSubDft() const override { - auto prelRes = DFTElement::independentSubDft(); + virtual std::vector independentSubDft(bool blockParents) const override { + auto prelRes = DFTElement::independentSubDft(blockParents); if(prelRes.empty()) { // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. return prelRes; @@ -360,7 +360,7 @@ namespace storm { std::set unit(prelRes.begin(), prelRes.end()); std::vector pids = this->parentIds(); for(auto const& child : mChildren) { - child->extendSubDft(unit, pids); + child->extendSubDft(unit, pids, blockParents); if(unit.empty()) { // Parent in the subdft, ie it is *not* a subdft break; @@ -369,15 +369,15 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { if(elemsInSubtree.count(this->id()) > 0) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for(auto const& child : mChildren) { - child->extendSubDft(elemsInSubtree, parentsOfSubRoot); + child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; @@ -531,15 +531,15 @@ namespace storm { return storm::utility::isZero(mPassiveFailureRate); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { if(elemsInSubtree.count(this->id())) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for(auto const& incDep : mIngoingDependencies) { - incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot); + incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; @@ -683,19 +683,19 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { if(elemsInSubtree.count(this->id())) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } - mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot); + mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } - mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot); + mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); } diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index d0482e4a7..70163a6e6 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -66,8 +66,8 @@ namespace storm { } } - virtual std::vector independentSubDft() const override { - auto prelRes = DFTElement::independentSubDft(); + virtual std::vector independentSubDft(bool blockParents) const override { + auto prelRes = DFTElement::independentSubDft(blockParents); if(prelRes.empty()) { // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. return prelRes; @@ -75,7 +75,7 @@ namespace storm { std::set unit(prelRes.begin(), prelRes.end()); std::vector pids = this->parentIds(); for(auto const& child : mChildren) { - child->extendSubDft(unit, pids); + child->extendSubDft(unit, pids, blockParents); if(unit.empty()) { // Parent in the subdft, ie it is *not* a subdft break; @@ -84,15 +84,15 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { if(elemsInSubtree.count(this->id()) > 0) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for(auto const& child : mChildren) { - child->extendSubDft(elemsInSubtree, parentsOfSubRoot); + child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; @@ -183,7 +183,7 @@ namespace storm { } - bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { } From 11b29cfd87c6f311ff1f6844d2720c9950802e2e Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 14:33:23 +0100 Subject: [PATCH 169/246] splitted elements into single headers Former-commit-id: 6d0774478dc789f2b1f7a392e7aed726bdfecdf8 --- src/storage/dft/DFT.h | 91 +- src/storage/dft/DFTElements.h | 1036 +-------------------- src/storage/dft/DFTStateGenerationInfo.h | 96 ++ src/storage/dft/elements/DFTAnd.h | 50 + src/storage/dft/elements/DFTBE.h | 104 +++ src/storage/dft/elements/DFTConst.h | 47 + src/storage/dft/elements/DFTDependency.h | 118 +++ src/storage/dft/elements/DFTElement.h | 297 ++++++ src/storage/dft/elements/DFTGate.h | 180 ++++ src/storage/dft/elements/DFTOr.h | 45 + src/storage/dft/elements/DFTPand.h | 56 ++ src/storage/dft/elements/DFTPor.h | 36 + src/storage/dft/elements/DFTRestriction.h | 3 +- src/storage/dft/elements/DFTSpare.h | 70 ++ src/storage/dft/elements/DFTVot.h | 75 ++ 15 files changed, 1188 insertions(+), 1116 deletions(-) create mode 100644 src/storage/dft/DFTStateGenerationInfo.h create mode 100644 src/storage/dft/elements/DFTAnd.h create mode 100644 src/storage/dft/elements/DFTBE.h create mode 100644 src/storage/dft/elements/DFTConst.h create mode 100644 src/storage/dft/elements/DFTDependency.h create mode 100644 src/storage/dft/elements/DFTElement.h create mode 100644 src/storage/dft/elements/DFTGate.h create mode 100644 src/storage/dft/elements/DFTOr.h create mode 100644 src/storage/dft/elements/DFTPand.h create mode 100644 src/storage/dft/elements/DFTPor.h create mode 100644 src/storage/dft/elements/DFTSpare.h create mode 100644 src/storage/dft/elements/DFTVot.h diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 408a7a535..9762def61 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -15,6 +15,7 @@ #include "SymmetricUnits.h" #include "../../utility/math.h" #include "src/utility/macros.h" +#include "DFTStateGenerationInfo.h" namespace storm { namespace storage { @@ -35,96 +36,6 @@ namespace storm { template class DFTColouring; - class DFTStateGenerationInfo { - private: - const size_t mUsageInfoBits; - std::map mSpareUsageIndex; // id spare -> index first bit in state - std::map mSpareActivationIndex; // id spare representative -> index in state - std::vector mIdToStateIndex; // id -> index first bit in state - std::map mRestrictedItems; - std::vector>> mSymmetries; // pair (lenght of symmetry group, vector indicating the starting points of the symmetry groups) - - public: - - DFTStateGenerationInfo(size_t nrElements, size_t maxSpareChildCount) : mUsageInfoBits(storm::utility::math::uint64_log2(maxSpareChildCount) + 1), mIdToStateIndex(nrElements) { - assert(maxSpareChildCount < pow(2, mUsageInfoBits)); - } - - size_t usageInfoBits() const { - return mUsageInfoBits; - } - - void addStateIndex(size_t id, size_t index) { - assert(id < mIdToStateIndex.size()); - mIdToStateIndex[id] = index; - } - - void addSpareActivationIndex(size_t id, size_t index) { - mSpareActivationIndex[id] = index; - } - - void addSpareUsageIndex(size_t id, size_t index) { - mSpareUsageIndex[id] = index; - } - - size_t getStateIndex(size_t id) const { - assert(id < mIdToStateIndex.size()); - return mIdToStateIndex[id]; - } - - size_t getSpareUsageIndex(size_t id) const { - assert(mSpareUsageIndex.count(id) > 0); - return mSpareUsageIndex.at(id); - } - - size_t getSpareActivationIndex(size_t id) const { - assert(mSpareActivationIndex.count(id) > 0); - return mSpareActivationIndex.at(id); - } - - void addSymmetry(size_t length, std::vector& startingIndices) { - mSymmetries.push_back(std::make_pair(length, startingIndices)); - } - - size_t getSymmetrySize() const { - return mSymmetries.size(); - } - - size_t getSymmetryLength(size_t pos) const { - assert(pos < mSymmetries.size()); - return mSymmetries[pos].first; - } - - std::vector const& getSymmetryIndices(size_t pos) const { - assert(pos < mSymmetries.size()); - return mSymmetries[pos].second; - } - - friend std::ostream& operator<<(std::ostream& os, DFTStateGenerationInfo const& info) { - os << "Id to state index:" << std::endl; - for (size_t id = 0; id < info.mIdToStateIndex.size(); ++id) { - os << id << " -> " << info.getStateIndex(id) << std::endl; - } - os << "Spare usage index with usage InfoBits of size " << info.mUsageInfoBits << ":" << std::endl; - for (auto pair : info.mSpareUsageIndex) { - os << pair.first << " -> " << pair.second << std::endl; - } - os << "Spare activation index:" << std::endl; - for (auto pair : info.mSpareActivationIndex) { - os << pair.first << " -> " << pair.second << std::endl; - } - os << "Symmetries:" << std::endl; - for (auto pair : info.mSymmetries) { - os << "Length: " << pair.first << ", starting indices: "; - for (size_t index : pair.second) { - os << index << ", "; - } - os << std::endl; - } - return os; - } - - }; /** diff --git a/src/storage/dft/DFTElements.h b/src/storage/dft/DFTElements.h index dc07505bd..49bc5cc53 100644 --- a/src/storage/dft/DFTElements.h +++ b/src/storage/dft/DFTElements.h @@ -1,1024 +1,12 @@ -#ifndef DFTELEMENTS_H -#define DFTELEMENTS_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "DFTElementType.h" -#include "DFTState.h" -#include "DFTStateSpaceGenerationQueues.h" -#include "src/utility/constants.h" -#include "src/adapters/CarlAdapter.h" - -using std::size_t; - -namespace storm { - namespace storage { - - template - class DFTGate; - - template - class DFTDependency; - template - class DFTRestriction; - - template - class DFTElement { - - using DFTGatePointer = std::shared_ptr>; - using DFTGateVector = std::vector; - using DFTDependencyPointer = std::shared_ptr>; - using DFTDependencyVector = std::vector; - using DFTRestrictionPointer = std::shared_ptr>; - using DFTRestrictionVector = std::vector; - - - protected: - size_t mId; - std::string mName; - size_t mRank = -1; - DFTGateVector mParents; - DFTDependencyVector mOutgoingDependencies; - DFTRestrictionVector mRestrictions; - - - public: - DFTElement(size_t id, std::string const& name) : - mId(id), mName(name) - {} - - virtual ~DFTElement() {} - - /** - * Returns the id - */ - virtual size_t id() const { - return mId; - } - - virtual DFTElementType type() const = 0; - - virtual void setRank(size_t rank) { - mRank = rank; - } - - virtual size_t rank() const { - return mRank; - } - - virtual bool isConstant() const { - return false; - } - - virtual bool isGate() const { - return false; - } - - /** - * Returns true if the element is a BE - */ - virtual bool isBasicElement() const { - return false; - } - - virtual bool isColdBasicElement() const { - return false; - } - - /** - * Returns true if the element is a spare gate - */ - virtual bool isSpareGate() const { - return false; - } - - virtual bool isDependency() const { - return false; - } - - virtual bool isRestriction() const { - return false; - } - - virtual void setId(size_t newId) { - mId = newId; - } - - /** - * Returns the name - */ - virtual std::string const& name() const { - return mName; - } - - bool addParent(DFTGatePointer const& e) { - if(std::find(mParents.begin(), mParents.end(), e) != mParents.end()) { - return false; - } - else - { - mParents.push_back(e); - return true; - } - } - - bool addRestriction(DFTRestrictionPointer const& e) { - if (std::find(mRestrictions.begin(), mRestrictions.end(), e) != mRestrictions.end()) { - return false; - } else { - mRestrictions.push_back(e); - return true; - } - } - - bool hasOnlyStaticParents() const { - for(auto const& parent : mParents) { - if(!isStaticGateType(parent->type())) { - return false; - } - } - return true; - } - - - bool hasParents() const { - return !mParents.empty(); - } - - size_t nrParents() const { - return mParents.size(); - } - - DFTGateVector const& parents() const { - return mParents; - } - - bool hasRestrictions() const { - return !mRestrictions.empty(); - } - - size_t nrRestrictions() const { - return mRestrictions.size(); - } - - DFTRestrictionVector const& restrictions() const { - return mRestrictions; - } - - std::vector parentIds() const { - std::vector res; - for(auto parent : parents()) { - res.push_back(parent->id()); - } - return res; - } - - bool addOutgoingDependency(DFTDependencyPointer const& e) { - assert(e->triggerEvent()->id() == this->id()); - if(std::find(mOutgoingDependencies.begin(), mOutgoingDependencies.end(), e) != mOutgoingDependencies.end()) { - return false; - } - else - { - mOutgoingDependencies.push_back(e); - return true; - } - } - - bool hasOutgoingDependencies() const { - return !mOutgoingDependencies.empty(); - } - - size_t nrOutgoingDependencies() const { - return mOutgoingDependencies.size(); - } - - std::set> restrictedItems() const { - std::set> result; - for(auto const& restr : mRestrictions) { - bool foundThis = false; - for(auto const& child : restr->children()) { - if(!foundThis) { - if(child->id() == mId) { - foundThis = true; - } - } else if(result.count(child) == 0) { - result.insert(child); - } - } - } - } - - std::set> restrictedItemsTC() const { - std::set> result; - for(auto const& restr : mRestrictions) { - bool foundThis = false; - for(auto const& child : restr->children()) { - if(!foundThis) { - if(child->id() == mId) { - foundThis = true; - } - } else if(result.count(child) == 0) { - result.insert(child); - std::set> tmpRes = child->restrictedItemsTC(); - result.insert(tmpRes.begin(), tmpRes.end()); - } - } - } - } - - DFTDependencyVector const& outgoingDependencies() const { - return mOutgoingDependencies; - } - - virtual void extendSpareModule(std::set& elementsInModule) const; - - // virtual void extendImmediateFailureCausePathEvents(std::set& ) const; - - virtual size_t nrChildren() const = 0; - - virtual std::string toString() const = 0; - - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; - - /** - * Computes the independent unit of this element, that is, all elements which are direct or indirect successors of an element. - */ - virtual std::vector independentUnit() const; - - /** - * Helper to independent unit computation - * @see independentUnit - */ - virtual void extendUnit(std::set& unit) const; - - /** - * Computes independent subtrees starting with this element (this), that is, all elements (x) which are connected to either - * - one of the children of the element, - * - a probabilistic dependency - * such that there exists a path from x to a child of this does not go through this. - */ - virtual std::vector independentSubDft(bool blockParents) const; - /** - * Helper to the independent subtree computation - * @see independentSubDft - */ - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const; - - virtual bool isTypeEqualTo(DFTElement const& other) const { - return type() == other.type(); - } - - - protected: - // virtual bool checkIsomorphicSubDftHelper(DFTElement const& otherElem, std::vector>& mapping, std::vector const& order ) const = 0; - - }; - - - - - template - class DFTGate : public DFTElement { - - using DFTElementPointer = std::shared_ptr>; - using DFTElementVector = std::vector; - - protected: - DFTElementVector mChildren; - - public: - DFTGate(size_t id, std::string const& name, DFTElementVector const& children) : - DFTElement(id, name), mChildren(children) - {} - - virtual ~DFTGate() {} - - void pushBackChild(DFTElementPointer elem) { - return mChildren.push_back(elem); - } - - size_t nrChildren() const override { - return mChildren.size(); - } - - DFTElementVector const& children() const { - return mChildren; - } - - virtual bool isGate() const override { - return true; - } - - - virtual std::string typestring() const = 0; - - virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; - - virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; - - virtual void extendSpareModule(std::set& elementsInSpareModule) const override { - if (!this->isSpareGate()) { - DFTElement::extendSpareModule(elementsInSpareModule); - for( auto const& child : mChildren) { - if(elementsInSpareModule.count(child->id()) == 0) { - elementsInSpareModule.insert(child->id()); - child->extendSpareModule(elementsInSpareModule); - } - } - } - } - - virtual std::vector independentUnit() const override { - std::set unit = {this->mId}; - for(auto const& child : mChildren) { - child->extendUnit(unit); - } - return std::vector(unit.begin(), unit.end()); - } - - virtual void extendUnit(std::set& unit) const override { - DFTElement::extendUnit(unit); - for(auto const& child : mChildren) { - child->extendUnit(unit); - } - } - - virtual std::vector independentSubDft(bool blockParents) const override { - auto prelRes = DFTElement::independentSubDft(blockParents); - if(prelRes.empty()) { - // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. - return prelRes; - } - std::set unit(prelRes.begin(), prelRes.end()); - std::vector pids = this->parentIds(); - for(auto const& child : mChildren) { - child->extendSubDft(unit, pids, blockParents); - if(unit.empty()) { - // Parent in the subdft, ie it is *not* a subdft - break; - } - } - return std::vector(unit.begin(), unit.end()); - } - - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { - if(elemsInSubtree.count(this->id()) > 0) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - // Parent in the subdft, ie it is *not* a subdft - return; - } - for(auto const& child : mChildren) { - child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - // Parent in the subdft, ie it is *not* a subdft - return; - } - } - } - - - virtual std::string toString() const override { - std::stringstream stream; - stream << "{" << this->name() << "} " << typestring() << "( "; - typename DFTElementVector::const_iterator it = mChildren.begin(); - stream << (*it)->name(); - ++it; - while(it != mChildren.end()) { - stream << ", " << (*it)->name(); - ++it; - } - stream << ")"; - return stream.str(); - } - - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(DFTElement::checkDontCareAnymore(state, queues)) { - childrenDontCare(state, queues); - return true; - } - return false; - } - - - protected: - - void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - for(std::shared_ptr parent : this->mParents) { - if(state.isOperational(parent->id())) { - queues.propagateFailure(parent); - } - } - for(std::shared_ptr> restr : this->mRestrictions) { - queues.checkRestrictionLater(restr); - } - state.setFailed(this->mId); - this->childrenDontCare(state, queues); - } - - void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - for(std::shared_ptr parent : this->mParents) { - if(state.isOperational(parent->id())) { - queues.propagateFailsafe(parent); - } - } - state.setFailsafe(this->mId); - this->childrenDontCare(state, queues); - } - - void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - queues.propagateDontCare(mChildren); - } - - bool hasFailsafeChild(DFTState& state) const { - for(auto const& child : mChildren) { - if(state.isFailsafe(child->id())) - { - return true; - } - } - return false; - } - - bool hasFailedChild(DFTState& state) const { - for(auto const& child : mChildren) { - if(state.hasFailed(child->id())) { - return true; - } - } - return false; - } - - }; - - - - template - class DFTBE : public DFTElement { - - using DFTDependencyPointer = std::shared_ptr>; - using DFTDependencyVector = std::vector; - - protected: - ValueType mActiveFailureRate; - ValueType mPassiveFailureRate; - DFTDependencyVector mIngoingDependencies; - - public: - DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : - DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) - {} - - DFTElementType type() const override { - return DFTElementType::BE; - } - - virtual size_t nrChildren() const override { - return 0; - } - - ValueType const& activeFailureRate() const { - return mActiveFailureRate; - } - - ValueType const& passiveFailureRate() const { - return mPassiveFailureRate; - } - - bool addIngoingDependency(DFTDependencyPointer const& e) { - assert(e->dependentEvent()->id() == this->id()); - if(std::find(mIngoingDependencies.begin(), mIngoingDependencies.end(), e) != mIngoingDependencies.end()) { - return false; - } - else - { - mIngoingDependencies.push_back(e); - return true; - } - } - - bool hasIngoingDependencies() const { - return !mIngoingDependencies.empty(); - } - - size_t nrIngoingDependencies() const { - return mIngoingDependencies.size(); - } - - DFTDependencyVector const& ingoingDependencies() const { - return mIngoingDependencies; - } - - std::string toString() const override { - std::stringstream stream; - stream << *this; - return stream.str(); - } - - bool isBasicElement() const override{ - return true; - } - - bool isColdBasicElement() const override{ - return storm::utility::isZero(mPassiveFailureRate); - } - - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { - if(elemsInSubtree.count(this->id())) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - // Parent in the subdft, ie it is *not* a subdft - return; - } - for(auto const& incDep : mIngoingDependencies) { - incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - // Parent in the subdft, ie it is *not* a subdft - return; - } - } - } - - bool isTypeEqualTo(DFTElement const& other) const override { - if(!DFTElement::isTypeEqualTo(other)) return false; - DFTBE const& otherBE = static_cast const&>(other); - return (mActiveFailureRate == otherBE.mActiveFailureRate) && (mPassiveFailureRate == otherBE.mPassiveFailureRate); - } - - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override; - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTBE const& be) { - return os << "{" << be.name() << "} BE(" << be.activeFailureRate() << ", " << be.passiveFailureRate() << ")"; - } - - - - template - class DFTConst : public DFTElement { - - bool mFailed; - - public: - DFTConst(size_t id, std::string const& name, bool failed) : - DFTElement(id, name), mFailed(failed) - {} - - DFTElementType type() const override { - if(mFailed) { - return DFTElementType::CONSTF; - } else { - return DFTElementType::CONSTS; - } - } - - - bool failed() const { - return mFailed; - } - - virtual bool isConstant() const { - return true; - } - - virtual size_t nrChildren() const override { - return 0; - } - - - - bool isTypeEqualTo(DFTElement const& other) const override { - if(!DFTElement::isTypeEqualTo(other)) return false; - DFTConst const& otherCNST = static_cast const&>(other); - return (mFailed == otherCNST.mFailed); - } - - }; - - - template - class DFTDependency : public DFTElement { - - using DFTGatePointer = std::shared_ptr>; - using DFTBEPointer = std::shared_ptr>; - - protected: - std::string mNameTrigger; - std::string mNameDependent; - ValueType mProbability; - DFTGatePointer mTriggerEvent; - DFTBEPointer mDependentEvent; - - public: - DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent, ValueType probability) : - DFTElement(id, name), mNameTrigger(trigger), mNameDependent(dependent), mProbability(probability) - { - } - - virtual ~DFTDependency() {} - - void initialize(DFTGatePointer triggerEvent, DFTBEPointer dependentEvent) { - assert(triggerEvent->name() == mNameTrigger); - assert(dependentEvent->name() == mNameDependent); - mTriggerEvent = triggerEvent; - mDependentEvent = dependentEvent; - } - - std::string nameTrigger() const { - return mNameTrigger; - } - - std::string nameDependent() const { - return mNameDependent; - } - - ValueType const& probability() const { - return mProbability; - } - - DFTGatePointer const& triggerEvent() const { - assert(mTriggerEvent); - return mTriggerEvent; - } - - DFTBEPointer const& dependentEvent() const { - assert(mDependentEvent); - return mDependentEvent; - } - - DFTElementType type() const override { - return DFTElementType::PDEP; - } - - virtual size_t nrChildren() const override { - return 1; - } - - virtual bool isDependency() const override { - return true; - } - - virtual bool isTypeEqualTo(DFTElement const& other) const override { - if(!DFTElement::isTypeEqualTo(other)) return false; - DFTDependency const& otherDEP= static_cast const&>(other); - return (mProbability == otherDEP.mProbability); - } - - - virtual std::vector independentUnit() const override { - std::set unit = {this->mId}; - mDependentEvent->extendUnit(unit); - if(unit.count(mTriggerEvent->id()) != 0) { - return {}; - } - return std::vector(unit.begin(), unit.end()); - } - - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { - if(elemsInSubtree.count(this->id())) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - // Parent in the subdft, ie it is *not* a subdft - return; - } - mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - // Parent in the subdft, ie it is *not* a subdft - return; - } - mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - - - } - - virtual std::string toString() const override { - std::stringstream stream; - bool fdep = storm::utility::isOne(mProbability); - stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; - if (!fdep) { - stream << " with probability " << mProbability; - } - return stream.str(); - } - - protected: - - }; - - - template - class DFTAnd : public DFTGate { - - public: - DFTAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) - {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(state.isOperational(this->mId)) { - for(auto const& child : this->mChildren) - { - if(!state.hasFailed(child->id())) { - return; - } - } - this->fail(state, queues); - } - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(this->hasFailsafeChild(state)); - if(state.isOperational(this->mId)) { - this->failsafe(state, queues); - this->childrenDontCare(state, queues); - } - } - - virtual DFTElementType type() const override { - return DFTElementType::AND; - } - - std::string typestring() const override { - return "AND"; - } - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { - return os << gate.toString(); - } - - - - template - class DFTOr : public DFTGate { - - public: - DFTOr(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) - {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(this->hasFailedChild(state)); - if(state.isOperational(this->mId)) { - this->fail(state, queues); - } - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - for(auto const& child : this->mChildren) { - if(!state.isFailsafe(child->id())) { - return; - } - } - this->failsafe(state, queues); - } - - virtual DFTElementType type() const override { - return DFTElementType::OR; - } - - std::string typestring() const override { - return "OR"; - } - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { - return os << gate.toString(); - } - - template - class DFTPand : public DFTGate { - - public: - DFTPand(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) - {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(state.isOperational(this->mId)) { - bool childOperationalBefore = false; - for(auto const& child : this->mChildren) - { - if(!state.hasFailed(child->id())) { - childOperationalBefore = true; - } else if(childOperationalBefore && state.hasFailed(child->id())){ - this->failsafe(state, queues); - this->childrenDontCare(state, queues); - return; - } - } - if(!childOperationalBefore) { - this->fail(state, queues); - } - } - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(this->hasFailsafeChild(state)); - if(state.isOperational(this->mId)) { - this->failsafe(state, queues); - this->childrenDontCare(state, queues); - } - } - - virtual DFTElementType type() const override { - return DFTElementType::PAND; - } - - std::string typestring() const override { - return "PAND"; - } - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { - return os << gate.toString(); - } - - - - template - class DFTPor : public DFTGate { - public: - DFTPor(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) - {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(false); - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(false); - } - - virtual DFTElementType type() const override { - return DFTElementType::POR; - } - - std::string typestring() const override { - return "POR"; - } - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { - return os << gate.toString(); - } - - - - template - class DFTVot : public DFTGate { - - private: - unsigned mThreshold; - - public: - DFTVot(size_t id, std::string const& name, unsigned threshold, std::vector>> const& children = {}) : - DFTGate(id, name, children), mThreshold(threshold) - {} - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(state.isOperational(this->mId)) { - unsigned nrFailedChildren = 0; - for(auto const& child : this->mChildren) - { - if(state.hasFailed(child->id())) { - ++nrFailedChildren; - if(nrFailedChildren >= mThreshold) - { - this->fail(state, queues); - return; - } - } - } - - } - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(this->hasFailsafeChild(state)); - if(state.isOperational(this->mId)) { - unsigned nrFailsafeChildren = 0; - for(auto const& child : this->mChildren) - { - if(state.isFailsafe(child->id())) { - ++nrFailsafeChildren; - if(nrFailsafeChildren > this->nrChildren() - mThreshold) - { - this->failsafe(state, queues); - this->childrenDontCare(state, queues); - return; - } - } - } - } - } - - virtual DFTElementType type() const override { - return DFTElementType::VOT; - } - - std::string typestring() const override{ - return "VOT (" + std::to_string(mThreshold) + ")"; - } - - virtual bool isTypeEqualTo(DFTElement const& other) const override { - if(!DFTElement::isTypeEqualTo(other)) return false; - DFTVot const& otherVOT = static_cast const&>(other); - return (mThreshold == otherVOT.mThreshold); - } - }; - - template - inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { - return os << gate.toString(); - } - - - - template - class DFTSpare : public DFTGate { - - public: - DFTSpare(size_t id, std::string const& name, std::vector>> const& children = {}) : - DFTGate(id, name, children) - {} - - std::string typestring() const override { - return "SPARE"; - } - - virtual DFTElementType type() const override { - return DFTElementType::SPARE; - } - - bool isSpareGate() const override { - return true; - } - - void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - DFTGate::fail(state, queues); - state.finalizeUses(this->mId); - } - - void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - DFTGate::failsafe(state, queues); - state.finalizeUses(this->mId); - } - - bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if (DFTGate::checkDontCareAnymore(state, queues)) { - state.finalizeUses(this->mId); - return true; - } - return false; - } - - void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(state.isOperational(this->mId)) { - size_t uses = state.uses(this->mId); - if(!state.isOperational(uses)) { - bool claimingSuccessful = state.claimNew(this->mId, uses, this->mChildren); - if(!claimingSuccessful) { - this->fail(state, queues); - } - } - } - } - - void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - if(state.isOperational(this->mId)) { - if(state.isFailsafe(state.uses(this->mId))) { - this->failsafe(state, queues); - this->childrenDontCare(state, queues); - } - } - } - - }; - - template - bool equalType(DFTElement const& e1, DFTElement const& e2) { - return e1.isTypeEqualTo(e2); - } - - } -} - - - -#endif /* DFTELEMENTS_H */ - +#pragma once + +#include "elements/DFTAnd.h" +#include "elements/DFTBE.h" +#include "elements/DFTConst.h" +#include "elements/DFTDependency.h" +#include "elements/DFTOr.h" +#include "elements/DFTPand.h" +#include "elements/DFTPor.h" +#include "elements/DFTRestriction.h" +#include "elements/DFTSpare.h" +#include "elements/DFTVot.h" \ No newline at end of file diff --git a/src/storage/dft/DFTStateGenerationInfo.h b/src/storage/dft/DFTStateGenerationInfo.h new file mode 100644 index 000000000..f82d4e8af --- /dev/null +++ b/src/storage/dft/DFTStateGenerationInfo.h @@ -0,0 +1,96 @@ +#pragma once + +namespace storm { + namespace storage { + class DFTStateGenerationInfo { + private: + const size_t mUsageInfoBits; + std::map mSpareUsageIndex; // id spare -> index first bit in state + std::map mSpareActivationIndex; // id spare representative -> index in state + std::vector mIdToStateIndex; // id -> index first bit in state + std::map mRestrictedItems; + std::vector>> mSymmetries; // pair (lenght of symmetry group, vector indicating the starting points of the symmetry groups) + + public: + + DFTStateGenerationInfo(size_t nrElements, size_t maxSpareChildCount) : mUsageInfoBits(storm::utility::math::uint64_log2(maxSpareChildCount) + 1), mIdToStateIndex(nrElements) { + assert(maxSpareChildCount < pow(2, mUsageInfoBits)); + } + + size_t usageInfoBits() const { + return mUsageInfoBits; + } + + void addStateIndex(size_t id, size_t index) { + assert(id < mIdToStateIndex.size()); + mIdToStateIndex[id] = index; + } + + void addSpareActivationIndex(size_t id, size_t index) { + mSpareActivationIndex[id] = index; + } + + void addSpareUsageIndex(size_t id, size_t index) { + mSpareUsageIndex[id] = index; + } + + size_t getStateIndex(size_t id) const { + assert(id < mIdToStateIndex.size()); + return mIdToStateIndex[id]; + } + + size_t getSpareUsageIndex(size_t id) const { + assert(mSpareUsageIndex.count(id) > 0); + return mSpareUsageIndex.at(id); + } + + size_t getSpareActivationIndex(size_t id) const { + assert(mSpareActivationIndex.count(id) > 0); + return mSpareActivationIndex.at(id); + } + + void addSymmetry(size_t length, std::vector& startingIndices) { + mSymmetries.push_back(std::make_pair(length, startingIndices)); + } + + size_t getSymmetrySize() const { + return mSymmetries.size(); + } + + size_t getSymmetryLength(size_t pos) const { + assert(pos < mSymmetries.size()); + return mSymmetries[pos].first; + } + + std::vector const& getSymmetryIndices(size_t pos) const { + assert(pos < mSymmetries.size()); + return mSymmetries[pos].second; + } + + friend std::ostream& operator<<(std::ostream& os, DFTStateGenerationInfo const& info) { + os << "Id to state index:" << std::endl; + for (size_t id = 0; id < info.mIdToStateIndex.size(); ++id) { + os << id << " -> " << info.getStateIndex(id) << std::endl; + } + os << "Spare usage index with usage InfoBits of size " << info.mUsageInfoBits << ":" << std::endl; + for (auto pair : info.mSpareUsageIndex) { + os << pair.first << " -> " << pair.second << std::endl; + } + os << "Spare activation index:" << std::endl; + for (auto pair : info.mSpareActivationIndex) { + os << pair.first << " -> " << pair.second << std::endl; + } + os << "Symmetries:" << std::endl; + for (auto pair : info.mSymmetries) { + os << "Length: " << pair.first << ", starting indices: "; + for (size_t index : pair.second) { + os << index << ", "; + } + os << std::endl; + } + return os; + } + + }; + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTAnd.h b/src/storage/dft/elements/DFTAnd.h new file mode 100644 index 000000000..5a5763166 --- /dev/null +++ b/src/storage/dft/elements/DFTAnd.h @@ -0,0 +1,50 @@ +#pragma once +#include "DFTGate.h" + +namespace storm { + namespace storage { + template + class DFTAnd : public DFTGate { + + public: + DFTAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(state.isOperational(this->mId)) { + for(auto const& child : this->mChildren) + { + if(!state.hasFailed(child->id())) { + return; + } + } + this->fail(state, queues); + } + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(this->hasFailsafeChild(state)); + if(state.isOperational(this->mId)) { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + } + } + + virtual DFTElementType type() const override { + return DFTElementType::AND; + } + + std::string typestring() const override { + return "AND"; + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { + return os << gate.toString(); + } + + + } +} diff --git a/src/storage/dft/elements/DFTBE.h b/src/storage/dft/elements/DFTBE.h new file mode 100644 index 000000000..5e09e965e --- /dev/null +++ b/src/storage/dft/elements/DFTBE.h @@ -0,0 +1,104 @@ +#pragma once +namespace storm { + namespace storage { + template + class DFTBE : public DFTElement { + + using DFTDependencyPointer = std::shared_ptr>; + using DFTDependencyVector = std::vector; + + protected: + ValueType mActiveFailureRate; + ValueType mPassiveFailureRate; + DFTDependencyVector mIngoingDependencies; + + public: + DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : + DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) + {} + + DFTElementType type() const override { + return DFTElementType::BE; + } + + virtual size_t nrChildren() const override { + return 0; + } + + ValueType const& activeFailureRate() const { + return mActiveFailureRate; + } + + ValueType const& passiveFailureRate() const { + return mPassiveFailureRate; + } + + bool addIngoingDependency(DFTDependencyPointer const& e) { + assert(e->dependentEvent()->id() == this->id()); + if(std::find(mIngoingDependencies.begin(), mIngoingDependencies.end(), e) != mIngoingDependencies.end()) { + return false; + } + else + { + mIngoingDependencies.push_back(e); + return true; + } + } + + bool hasIngoingDependencies() const { + return !mIngoingDependencies.empty(); + } + + size_t nrIngoingDependencies() const { + return mIngoingDependencies.size(); + } + + DFTDependencyVector const& ingoingDependencies() const { + return mIngoingDependencies; + } + + std::string toString() const override { + std::stringstream stream; + stream << *this; + return stream.str(); + } + + bool isBasicElement() const override{ + return true; + } + + bool isColdBasicElement() const override{ + return storm::utility::isZero(mPassiveFailureRate); + } + + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { + if(elemsInSubtree.count(this->id())) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + for(auto const& incDep : mIngoingDependencies) { + incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + } + } + + bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTBE const& otherBE = static_cast const&>(other); + return (mActiveFailureRate == otherBE.mActiveFailureRate) && (mPassiveFailureRate == otherBE.mPassiveFailureRate); + } + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override; + }; + + template + inline std::ostream& operator<<(std::ostream& os, DFTBE const& be) { + return os << "{" << be.name() << "} BE(" << be.activeFailureRate() << ", " << be.passiveFailureRate() << ")"; + } + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTConst.h b/src/storage/dft/elements/DFTConst.h new file mode 100644 index 000000000..e827e173c --- /dev/null +++ b/src/storage/dft/elements/DFTConst.h @@ -0,0 +1,47 @@ +#pragma once + + +#include "DFTElement.h" +namespace storm { + namespace storage { + template + class DFTConst : public DFTElement { + + bool mFailed; + + public: + DFTConst(size_t id, std::string const& name, bool failed) : + DFTElement(id, name), mFailed(failed) + {} + + DFTElementType type() const override { + if(mFailed) { + return DFTElementType::CONSTF; + } else { + return DFTElementType::CONSTS; + } + } + + + bool failed() const { + return mFailed; + } + + virtual bool isConstant() const { + return true; + } + + virtual size_t nrChildren() const override { + return 0; + } + + + bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTConst const& otherCNST = static_cast const&>(other); + return (mFailed == otherCNST.mFailed); + } + + }; + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTDependency.h b/src/storage/dft/elements/DFTDependency.h new file mode 100644 index 000000000..c7f3f6bfd --- /dev/null +++ b/src/storage/dft/elements/DFTDependency.h @@ -0,0 +1,118 @@ +#pragma once + + +#include "DFTElement.h" +namespace storm { + namespace storage { + + template + class DFTDependency : public DFTElement { + + using DFTGatePointer = std::shared_ptr>; + using DFTBEPointer = std::shared_ptr>; + + protected: + std::string mNameTrigger; + std::string mNameDependent; + ValueType mProbability; + DFTGatePointer mTriggerEvent; + DFTBEPointer mDependentEvent; + + public: + DFTDependency(size_t id, std::string const& name, std::string const& trigger, std::string const& dependent, ValueType probability) : + DFTElement(id, name), mNameTrigger(trigger), mNameDependent(dependent), mProbability(probability) + { + } + + virtual ~DFTDependency() {} + + void initialize(DFTGatePointer triggerEvent, DFTBEPointer dependentEvent) { + assert(triggerEvent->name() == mNameTrigger); + assert(dependentEvent->name() == mNameDependent); + mTriggerEvent = triggerEvent; + mDependentEvent = dependentEvent; + } + + std::string nameTrigger() const { + return mNameTrigger; + } + + std::string nameDependent() const { + return mNameDependent; + } + + ValueType const& probability() const { + return mProbability; + } + + DFTGatePointer const& triggerEvent() const { + assert(mTriggerEvent); + return mTriggerEvent; + } + + DFTBEPointer const& dependentEvent() const { + assert(mDependentEvent); + return mDependentEvent; + } + + DFTElementType type() const override { + return DFTElementType::PDEP; + } + + virtual size_t nrChildren() const override { + return 1; + } + + virtual bool isDependency() const override { + return true; + } + + virtual bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTDependency const& otherDEP= static_cast const&>(other); + return (mProbability == otherDEP.mProbability); + } + + + virtual std::vector independentUnit() const override { + std::set unit = {this->mId}; + mDependentEvent->extendUnit(unit); + if(unit.count(mTriggerEvent->id()) != 0) { + return {}; + } + return std::vector(unit.begin(), unit.end()); + } + + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { + if(elemsInSubtree.count(this->id())) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + + + } + + virtual std::string toString() const override { + std::stringstream stream; + bool fdep = storm::utility::isOne(mProbability); + stream << "{" << this->name() << "} " << (fdep ? "FDEP" : "PDEP") << "(" << mTriggerEvent->name() << " => " << mDependentEvent->name() << ")"; + if (!fdep) { + stream << " with probability " << mProbability; + } + return stream.str(); + } + + protected: + + }; + + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTElement.h b/src/storage/dft/elements/DFTElement.h new file mode 100644 index 000000000..d6840132a --- /dev/null +++ b/src/storage/dft/elements/DFTElement.h @@ -0,0 +1,297 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + + + +#include "../DFTElementType.h" +#include "../DFTState.h" +#include "../DFTStateSpaceGenerationQueues.h" +#include "src/utility/constants.h" +#include "src/adapters/CarlAdapter.h" + + + + +namespace storm { + namespace storage { + + using std::size_t; + template + class DFTGate; + + template + class DFTDependency; + template + class DFTRestriction; + + + template + class DFTElement { + + using DFTGatePointer = std::shared_ptr>; + using DFTGateVector = std::vector; + using DFTDependencyPointer = std::shared_ptr>; + using DFTDependencyVector = std::vector; + using DFTRestrictionPointer = std::shared_ptr>; + using DFTRestrictionVector = std::vector; + + + protected: + std::size_t mId; + std::string mName; + std::size_t mRank = -1; + DFTGateVector mParents; + DFTDependencyVector mOutgoingDependencies; + DFTRestrictionVector mRestrictions; + + + public: + DFTElement(size_t id, std::string const& name) : + mId(id), mName(name) + {} + + virtual ~DFTElement() {} + + /** + * Returns the id + */ + virtual size_t id() const { + return mId; + } + + virtual DFTElementType type() const = 0; + + virtual void setRank(size_t rank) { + mRank = rank; + } + + virtual size_t rank() const { + return mRank; + } + + virtual bool isConstant() const { + return false; + } + + virtual bool isGate() const { + return false; + } + + /** + * Returns true if the element is a BE + */ + virtual bool isBasicElement() const { + return false; + } + + virtual bool isColdBasicElement() const { + return false; + } + + /** + * Returns true if the element is a spare gate + */ + virtual bool isSpareGate() const { + return false; + } + + virtual bool isDependency() const { + return false; + } + + virtual bool isRestriction() const { + return false; + } + + virtual void setId(size_t newId) { + mId = newId; + } + + /** + * Returns the name + */ + virtual std::string const& name() const { + return mName; + } + + bool addParent(DFTGatePointer const& e) { + if(std::find(mParents.begin(), mParents.end(), e) != mParents.end()) { + return false; + } + else + { + mParents.push_back(e); + return true; + } + } + + bool addRestriction(DFTRestrictionPointer const& e) { + if (std::find(mRestrictions.begin(), mRestrictions.end(), e) != mRestrictions.end()) { + return false; + } else { + mRestrictions.push_back(e); + return true; + } + } + + bool hasOnlyStaticParents() const { + for(auto const& parent : mParents) { + if(!isStaticGateType(parent->type())) { + return false; + } + } + return true; + } + + + bool hasParents() const { + return !mParents.empty(); + } + + size_t nrParents() const { + return mParents.size(); + } + + DFTGateVector const& parents() const { + return mParents; + } + + bool hasRestrictions() const { + return !mRestrictions.empty(); + } + + size_t nrRestrictions() const { + return mRestrictions.size(); + } + + DFTRestrictionVector const& restrictions() const { + return mRestrictions; + } + + std::vector parentIds() const { + std::vector res; + for(auto parent : parents()) { + res.push_back(parent->id()); + } + return res; + } + + bool addOutgoingDependency(DFTDependencyPointer const& e) { + assert(e->triggerEvent()->id() == this->id()); + if(std::find(mOutgoingDependencies.begin(), mOutgoingDependencies.end(), e) != mOutgoingDependencies.end()) { + return false; + } + else + { + mOutgoingDependencies.push_back(e); + return true; + } + } + + bool hasOutgoingDependencies() const { + return !mOutgoingDependencies.empty(); + } + + size_t nrOutgoingDependencies() const { + return mOutgoingDependencies.size(); + } + + std::set> restrictedItems() const { + std::set> result; + for(auto const& restr : mRestrictions) { + bool foundThis = false; + for(auto const& child : restr->children()) { + if(!foundThis) { + if(child->id() == mId) { + foundThis = true; + } + } else if(result.count(child) == 0) { + result.insert(child); + } + } + } + } + + std::set> restrictedItemsTC() const { + std::set> result; + for(auto const& restr : mRestrictions) { + bool foundThis = false; + for(auto const& child : restr->children()) { + if(!foundThis) { + if(child->id() == mId) { + foundThis = true; + } + } else if(result.count(child) == 0) { + result.insert(child); + std::set> tmpRes = child->restrictedItemsTC(); + result.insert(tmpRes.begin(), tmpRes.end()); + } + } + } + } + + DFTDependencyVector const& outgoingDependencies() const { + return mOutgoingDependencies; + } + + virtual void extendSpareModule(std::set& elementsInModule) const; + + // virtual void extendImmediateFailureCausePathEvents(std::set& ) const; + + virtual std::size_t nrChildren() const = 0; + + virtual std::string toString() const = 0; + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; + + /** + * Computes the independent unit of this element, that is, all elements which are direct or indirect successors of an element. + */ + virtual std::vector independentUnit() const; + + /** + * Helper to independent unit computation + * @see independentUnit + */ + virtual void extendUnit(std::set& unit) const; + + /** + * Computes independent subtrees starting with this element (this), that is, all elements (x) which are connected to either + * - one of the children of the element, + * - a probabilistic dependency + * such that there exists a path from x to a child of this does not go through this. + */ + virtual std::vector independentSubDft(bool blockParents) const; + /** + * Helper to the independent subtree computation + * @see independentSubDft + */ + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const; + + virtual bool isTypeEqualTo(DFTElement const& other) const { + return type() == other.type(); + } + + + protected: + // virtual bool checkIsomorphicSubDftHelper(DFTElement const& otherElem, std::vector>& mapping, std::vector const& order ) const = 0; + + }; + + + + + template + bool equalType(DFTElement const& e1, DFTElement const& e2) { + return e1.isTypeEqualTo(e2); + } + } +} diff --git a/src/storage/dft/elements/DFTGate.h b/src/storage/dft/elements/DFTGate.h new file mode 100644 index 000000000..52f9bcd43 --- /dev/null +++ b/src/storage/dft/elements/DFTGate.h @@ -0,0 +1,180 @@ +#pragma once + +#include "DFTElement.h" +namespace storm { + namespace storage { + template + class DFTGate : public DFTElement { + + using DFTElementPointer = std::shared_ptr>; + using DFTElementVector = std::vector; + + protected: + DFTElementVector mChildren; + + public: + DFTGate(size_t id, std::string const& name, DFTElementVector const& children) : + DFTElement(id, name), mChildren(children) + {} + + virtual ~DFTGate() {} + + void pushBackChild(DFTElementPointer elem) { + return mChildren.push_back(elem); + } + + size_t nrChildren() const override { + return mChildren.size(); + } + + DFTElementVector const& children() const { + return mChildren; + } + + virtual bool isGate() const override { + return true; + } + + + virtual std::string typestring() const = 0; + + virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; + + virtual void extendSpareModule(std::set& elementsInSpareModule) const override { + if (!this->isSpareGate()) { + DFTElement::extendSpareModule(elementsInSpareModule); + for( auto const& child : mChildren) { + if(elementsInSpareModule.count(child->id()) == 0) { + elementsInSpareModule.insert(child->id()); + child->extendSpareModule(elementsInSpareModule); + } + } + } + } + + virtual std::vector independentUnit() const override { + std::set unit = {this->mId}; + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + return std::vector(unit.begin(), unit.end()); + } + + virtual void extendUnit(std::set& unit) const override { + DFTElement::extendUnit(unit); + for(auto const& child : mChildren) { + child->extendUnit(unit); + } + } + + virtual std::vector independentSubDft(bool blockParents) const override { + auto prelRes = DFTElement::independentSubDft(blockParents); + if(prelRes.empty()) { + // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. + return prelRes; + } + std::set unit(prelRes.begin(), prelRes.end()); + std::vector pids = this->parentIds(); + for(auto const& child : mChildren) { + child->extendSubDft(unit, pids, blockParents); + if(unit.empty()) { + // Parent in the subdft, ie it is *not* a subdft + break; + } + } + return std::vector(unit.begin(), unit.end()); + } + + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { + if(elemsInSubtree.count(this->id()) > 0) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + for(auto const& child : mChildren) { + child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + } + } + + + virtual std::string toString() const override { + std::stringstream stream; + stream << "{" << this->name() << "} " << typestring() << "( "; + typename DFTElementVector::const_iterator it = mChildren.begin(); + stream << (*it)->name(); + ++it; + while(it != mChildren.end()) { + stream << ", " << (*it)->name(); + ++it; + } + stream << ")"; + return stream.str(); + } + + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(DFTElement::checkDontCareAnymore(state, queues)) { + childrenDontCare(state, queues); + return true; + } + return false; + } + + + protected: + + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + for(std::shared_ptr parent : this->mParents) { + if(state.isOperational(parent->id())) { + queues.propagateFailure(parent); + } + } + for(std::shared_ptr> restr : this->mRestrictions) { + queues.checkRestrictionLater(restr); + } + state.setFailed(this->mId); + this->childrenDontCare(state, queues); + } + + void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + for(std::shared_ptr parent : this->mParents) { + if(state.isOperational(parent->id())) { + queues.propagateFailsafe(parent); + } + } + state.setFailsafe(this->mId); + this->childrenDontCare(state, queues); + } + + void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + queues.propagateDontCare(mChildren); + } + + bool hasFailsafeChild(DFTState& state) const { + for(auto const& child : mChildren) { + if(state.isFailsafe(child->id())) + { + return true; + } + } + return false; + } + + bool hasFailedChild(DFTState& state) const { + for(auto const& child : mChildren) { + if(state.hasFailed(child->id())) { + return true; + } + } + return false; + } + + }; + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTOr.h b/src/storage/dft/elements/DFTOr.h new file mode 100644 index 000000000..93e481d35 --- /dev/null +++ b/src/storage/dft/elements/DFTOr.h @@ -0,0 +1,45 @@ +#pragma once + +#include "DFTGate.h" +namespace storm { + namespace storage { + template + class DFTOr : public DFTGate { + + public: + DFTOr(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(this->hasFailedChild(state)); + if(state.isOperational(this->mId)) { + this->fail(state, queues); + } + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + for(auto const& child : this->mChildren) { + if(!state.isFailsafe(child->id())) { + return; + } + } + this->failsafe(state, queues); + } + + virtual DFTElementType type() const override { + return DFTElementType::OR; + } + + std::string typestring() const override { + return "OR"; + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { + return os << gate.toString(); + } + } +} + \ No newline at end of file diff --git a/src/storage/dft/elements/DFTPand.h b/src/storage/dft/elements/DFTPand.h new file mode 100644 index 000000000..86472d76f --- /dev/null +++ b/src/storage/dft/elements/DFTPand.h @@ -0,0 +1,56 @@ +#pragma once + +#include "DFTGate.h" +namespace storm { + namespace storage { + template + class DFTPand : public DFTGate { + + public: + DFTPand(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(state.isOperational(this->mId)) { + bool childOperationalBefore = false; + for(auto const& child : this->mChildren) + { + if(!state.hasFailed(child->id())) { + childOperationalBefore = true; + } else if(childOperationalBefore && state.hasFailed(child->id())){ + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + return; + } + } + if(!childOperationalBefore) { + this->fail(state, queues); + } + } + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(this->hasFailsafeChild(state)); + if(state.isOperational(this->mId)) { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + } + } + + virtual DFTElementType type() const override { + return DFTElementType::PAND; + } + + std::string typestring() const override { + return "PAND"; + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { + return os << gate.toString(); + } + + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTPor.h b/src/storage/dft/elements/DFTPor.h new file mode 100644 index 000000000..1aaa943b0 --- /dev/null +++ b/src/storage/dft/elements/DFTPor.h @@ -0,0 +1,36 @@ +#pragma once + +#include "DFTGate.h" +namespace storm { + namespace storage { + template + class DFTPor : public DFTGate { + public: + DFTPor(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(false); + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(false); + } + + virtual DFTElementType type() const override { + return DFTElementType::POR; + } + + std::string typestring() const override { + return "POR"; + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { + return os << gate.toString(); + } + + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index 70163a6e6..f0fef5845 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -1,7 +1,6 @@ #pragma once -#include "../DFTElements.h" - +#include "DFTElement.h" namespace storm { namespace storage { template diff --git a/src/storage/dft/elements/DFTSpare.h b/src/storage/dft/elements/DFTSpare.h new file mode 100644 index 000000000..dd3689311 --- /dev/null +++ b/src/storage/dft/elements/DFTSpare.h @@ -0,0 +1,70 @@ +#pragma once + + +#include "DFTGate.h" +namespace storm { + namespace storage { + + + template + class DFTSpare : public DFTGate { + + public: + DFTSpare(size_t id, std::string const& name, std::vector>> const& children = {}) : + DFTGate(id, name, children) + {} + + std::string typestring() const override { + return "SPARE"; + } + + virtual DFTElementType type() const override { + return DFTElementType::SPARE; + } + + bool isSpareGate() const override { + return true; + } + + void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + DFTGate::fail(state, queues); + state.finalizeUses(this->mId); + } + + void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + DFTGate::failsafe(state, queues); + state.finalizeUses(this->mId); + } + + bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if (DFTGate::checkDontCareAnymore(state, queues)) { + state.finalizeUses(this->mId); + return true; + } + return false; + } + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(state.isOperational(this->mId)) { + size_t uses = state.uses(this->mId); + if(!state.isOperational(uses)) { + bool claimingSuccessful = state.claimNew(this->mId, uses, this->mChildren); + if(!claimingSuccessful) { + this->fail(state, queues); + } + } + } + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(state.isOperational(this->mId)) { + if(state.isFailsafe(state.uses(this->mId))) { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + } + } + } + + }; + } +} \ No newline at end of file diff --git a/src/storage/dft/elements/DFTVot.h b/src/storage/dft/elements/DFTVot.h new file mode 100644 index 000000000..3a3e818d2 --- /dev/null +++ b/src/storage/dft/elements/DFTVot.h @@ -0,0 +1,75 @@ +#pragma once +namespace storm { + namespace storage { + + + template + class DFTVot : public DFTGate { + + private: + unsigned mThreshold; + + public: + DFTVot(size_t id, std::string const& name, unsigned threshold, std::vector>> const& children = {}) : + DFTGate(id, name, children), mThreshold(threshold) + {} + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(state.isOperational(this->mId)) { + unsigned nrFailedChildren = 0; + for(auto const& child : this->mChildren) + { + if(state.hasFailed(child->id())) { + ++nrFailedChildren; + if(nrFailedChildren >= mThreshold) + { + this->fail(state, queues); + return; + } + } + } + + } + } + + void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + assert(this->hasFailsafeChild(state)); + if(state.isOperational(this->mId)) { + unsigned nrFailsafeChildren = 0; + for(auto const& child : this->mChildren) + { + if(state.isFailsafe(child->id())) { + ++nrFailsafeChildren; + if(nrFailsafeChildren > this->nrChildren() - mThreshold) + { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + return; + } + } + } + } + } + + virtual DFTElementType type() const override { + return DFTElementType::VOT; + } + + std::string typestring() const override{ + return "VOT (" + std::to_string(mThreshold) + ")"; + } + + virtual bool isTypeEqualTo(DFTElement const& other) const override { + if(!DFTElement::isTypeEqualTo(other)) return false; + DFTVot const& otherVOT = static_cast const&>(other); + return (mThreshold == otherVOT.mThreshold); + } + }; + + template + inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { + return os << gate.toString(); + } + + } +} \ No newline at end of file From 2a4157947691e91caa1ebb0cc6fceecda013e376 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 14:50:46 +0100 Subject: [PATCH 170/246] refactored source file for elements Former-commit-id: 0315e8a8cb685ef5969664e951593fa372db0918 --- src/storage/dft/DFTElements.cpp | 127 -------------------------- src/storage/dft/elements/DFTBE.h | 8 +- src/storage/dft/elements/DFTElement.h | 5 +- src/storage/dft/elements/DFTVot.h | 1 + 4 files changed, 11 insertions(+), 130 deletions(-) delete mode 100644 src/storage/dft/DFTElements.cpp diff --git a/src/storage/dft/DFTElements.cpp b/src/storage/dft/DFTElements.cpp deleted file mode 100644 index 4cf49e0b0..000000000 --- a/src/storage/dft/DFTElements.cpp +++ /dev/null @@ -1,127 +0,0 @@ -#include -#include -#include "DFTElements.h" -#include "elements/DFTRestriction.h" - -namespace storm { - namespace storage { - - template - bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if (state.dontCare(mId)) { - return false; - } - - // Check that no outgoing dependencies can be triggered anymore - for (DFTDependencyPointer dependency : mOutgoingDependencies) { - if (state.isOperational(dependency->dependentEvent()->id()) && state.isOperational(dependency->triggerEvent()->id())) { - return false; - } - } - - bool hasParentSpare = false; - - // Check that no parent can fail anymore - for(DFTGatePointer const& parent : mParents) { - if(state.isOperational(parent->id())) { - return false; - } - if (parent->isSpareGate()) { - hasParentSpare = true; - } - } - - state.setDontCare(mId); - if (hasParentSpare && !state.isActive(mId)) { - // Activate child for consistency in failed spares - state.activate(mId); - } - return true; - } - - template - void DFTElement::extendSpareModule(std::set& elementsInModule) const { - for(auto const& parent : mParents) { - if(elementsInModule.count(parent->id()) == 0 && !parent->isSpareGate()) { - elementsInModule.insert(parent->id()); - parent->extendSpareModule(elementsInModule); - } - } - } - - template - std::vector DFTElement::independentUnit() const { - std::vector res; - res.push_back(this->id()); - // Extend for pdeps. - return res; - } - - template - void DFTElement::extendUnit(std::set& unit) const { - unit.insert(mId); - } - - template - std::vector DFTElement::independentSubDft(bool blockParents) const { - //std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; - std::vector res; - res.push_back(this->id()); - return res; - } - - template - void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const { - if(elemsInSubtree.count(this->id()) > 0) return; - if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { - // This is a parent of the suspected root, thus it is not a subdft. - elemsInSubtree.clear(); - return; - } - elemsInSubtree.insert(mId); - for(auto const& parent : mParents) { - if(blockParents && std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), parent->id()) != parentsOfSubRoot.end()) { - continue; - } - parent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - return; - } - } - for(auto const& dep : mOutgoingDependencies) { - dep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - return; - } - - } - - for(auto const& restr : mRestrictions) { - restr->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - if(elemsInSubtree.empty()) { - return; - } - } - - } - - - template - bool DFTBE::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { - if(DFTElement::checkDontCareAnymore(state, queues)) { - state.beNoLongerFailable(this->mId); - return true; - } - return false; - } - - - // Explicitly instantiate the class. - template class DFTBE; - -#ifdef STORM_HAVE_CARL - template class DFTBE; -#endif - - } -} diff --git a/src/storage/dft/elements/DFTBE.h b/src/storage/dft/elements/DFTBE.h index 5e09e965e..a9c5b030d 100644 --- a/src/storage/dft/elements/DFTBE.h +++ b/src/storage/dft/elements/DFTBE.h @@ -93,7 +93,13 @@ namespace storm { return (mActiveFailureRate == otherBE.mActiveFailureRate) && (mPassiveFailureRate == otherBE.mPassiveFailureRate); } - virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override; + virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { + if(DFTElement::checkDontCareAnymore(state, queues)) { + state.beNoLongerFailable(this->mId); + return true; + } + return false; + } }; template diff --git a/src/storage/dft/elements/DFTElement.h b/src/storage/dft/elements/DFTElement.h index d6840132a..11223f3fa 100644 --- a/src/storage/dft/elements/DFTElement.h +++ b/src/storage/dft/elements/DFTElement.h @@ -8,6 +8,7 @@ #include #include #include +#include @@ -204,7 +205,7 @@ namespace storm { return mOutgoingDependencies.size(); } - std::set> restrictedItems() const { + /*std::set> restrictedItems() const { std::set> result; for(auto const& restr : mRestrictions) { bool foundThis = false; @@ -236,7 +237,7 @@ namespace storm { } } } - } + }*/ DFTDependencyVector const& outgoingDependencies() const { return mOutgoingDependencies; diff --git a/src/storage/dft/elements/DFTVot.h b/src/storage/dft/elements/DFTVot.h index 3a3e818d2..0233d979d 100644 --- a/src/storage/dft/elements/DFTVot.h +++ b/src/storage/dft/elements/DFTVot.h @@ -1,4 +1,5 @@ #pragma once +#include "DFTGate.h" namespace storm { namespace storage { From 6e777e88d1ad0eba0c56c255cdbc9e4f0b17685c Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 14:51:03 +0100 Subject: [PATCH 171/246] fixed warning for restriction Former-commit-id: ac2addb5318e7a8862e64d36551d1442725889b1 --- src/storage/dft/elements/DFTRestriction.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index f0fef5845..78036528e 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -183,7 +183,8 @@ namespace storm { } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - + // Actually, it doesnt matter what we return here.. + return false; } virtual DFTElementType type() const override { From a204ac3a66409700fada898b22b722328d37fdda Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 16:31:00 +0100 Subject: [PATCH 172/246] added a comment Former-commit-id: 19a026c3f913d0bac6ce24ec886b2518e57d8d4f --- src/storage/dft/DFTBuilder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index e3889bf4d..08d85d879 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -110,6 +110,7 @@ namespace storm { restr = std::make_shared>(mNextId++, name); break; case DFTElementType::MUTEX: + // TODO notice that mutex state generation support is lacking anyway, as DONT CARE propagation would be broken for this. STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Gate type not supported."); break; default: From ed651409114127ed2db67307857e442a15999561 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 16:49:18 +0100 Subject: [PATCH 173/246] add missing file Former-commit-id: af1ea74d659e3fa9a99c46a7d621c346b5f97cfa --- src/storage/dft/elements/DFTElement.cpp | 120 ++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/storage/dft/elements/DFTElement.cpp diff --git a/src/storage/dft/elements/DFTElement.cpp b/src/storage/dft/elements/DFTElement.cpp new file mode 100644 index 000000000..b71e0672b --- /dev/null +++ b/src/storage/dft/elements/DFTElement.cpp @@ -0,0 +1,120 @@ +#include +#include +#include +#include "DFTElement.h" +#include "../DFTElements.h" + +namespace storm { + namespace storage { + + template + bool DFTElement::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { + if (state.dontCare(mId)) { + return false; + } + + // Check that no outgoing dependencies can be triggered anymore + for (DFTDependencyPointer dependency : mOutgoingDependencies) { + if (state.isOperational(dependency->dependentEvent()->id()) && state.isOperational(dependency->triggerEvent()->id())) { + return false; + } + } + + bool hasParentSpare = false; + + // Check that no parent can fail anymore + for(DFTGatePointer const& parent : mParents) { + if(state.isOperational(parent->id())) { + return false; + } + if (parent->isSpareGate()) { + hasParentSpare = true; + } + } + + state.setDontCare(mId); + if (hasParentSpare && !state.isActive(mId)) { + // Activate child for consistency in failed spares + state.activate(mId); + } + return true; + } + + template + void DFTElement::extendSpareModule(std::set& elementsInModule) const { + for(auto const& parent : mParents) { + if(elementsInModule.count(parent->id()) == 0 && !parent->isSpareGate()) { + elementsInModule.insert(parent->id()); + parent->extendSpareModule(elementsInModule); + } + } + } + + template + std::vector DFTElement::independentUnit() const { + std::vector res; + res.push_back(this->id()); + // Extend for pdeps. + return res; + } + + template + void DFTElement::extendUnit(std::set& unit) const { + unit.insert(mId); + } + + template + std::vector DFTElement::independentSubDft(bool blockParents) const { + //std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; + std::vector res; + res.push_back(this->id()); + return res; + } + + template + void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const { + if(elemsInSubtree.count(this->id()) > 0) return; + if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { + // This is a parent of the suspected root, thus it is not a subdft. + elemsInSubtree.clear(); + return; + } + elemsInSubtree.insert(mId); + for(auto const& parent : mParents) { + if(blockParents && std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), parent->id()) != parentsOfSubRoot.end()) { + continue; + } + parent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + return; + } + } + for(auto const& dep : mOutgoingDependencies) { + dep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + return; + } + + } + + for(auto const& restr : mRestrictions) { + restr->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + if(elemsInSubtree.empty()) { + return; + } + } + + } + + + + // Explicitly instantiate the class. + template class DFTElement; + +#ifdef STORM_HAVE_CARL + template class DFTElement; +#endif + + + } +} From c6098e6a6a8a749c7d78baf88223096c2454908b Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 16:49:44 +0100 Subject: [PATCH 174/246] post and pre SEQ elements for state space generation Former-commit-id: 03e44081890d546b9d3033f7e1f85864c7d1ac06 --- src/storage/dft/DFT.cpp | 10 ++++ src/storage/dft/DFTStateGenerationInfo.h | 16 +++++- src/storage/dft/elements/DFTElement.h | 66 ++++++++++++++--------- src/storage/dft/elements/DFTRestriction.h | 10 ++++ 4 files changed, 75 insertions(+), 27 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 2aa557d8c..9a12fe2f6 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -77,12 +77,22 @@ namespace storm { // TODO make recursive to use for nested subtrees DFTStateGenerationInfo generationInfo(nrElements(), mMaxSpareChildCount); + + // Generate Pre and Post info for restrictions + for(auto const& elem : mElements) { + if(!elem->isDependency() && !elem->isRestriction()) { + generationInfo.setRestrictionPreElements(elem->id(), elem->seqRestrictionPres()); + generationInfo.setRestrictionPostElements(elem->id(), elem->seqRestrictionPosts()); + } + } + // Perform DFS and insert all elements of subtree sequentially size_t stateIndex = 0; std::queue visitQueue; storm::storage::BitVector visited(nrElements(), false); + // TODO make subfunction for this? if (symmetries.groups.empty()) { // Perform DFS for whole tree visitQueue.push(mTopLevelIndex); diff --git a/src/storage/dft/DFTStateGenerationInfo.h b/src/storage/dft/DFTStateGenerationInfo.h index f82d4e8af..a89add9bf 100644 --- a/src/storage/dft/DFTStateGenerationInfo.h +++ b/src/storage/dft/DFTStateGenerationInfo.h @@ -8,12 +8,16 @@ namespace storm { std::map mSpareUsageIndex; // id spare -> index first bit in state std::map mSpareActivationIndex; // id spare representative -> index in state std::vector mIdToStateIndex; // id -> index first bit in state - std::map mRestrictedItems; + std::map> mSeqRestrictionPreElements; // id -> list of restriction pre elements; + std::map> mSeqRestrictionPostElements; // id -> list of restriction post elements; std::vector>> mSymmetries; // pair (lenght of symmetry group, vector indicating the starting points of the symmetry groups) public: - DFTStateGenerationInfo(size_t nrElements, size_t maxSpareChildCount) : mUsageInfoBits(storm::utility::math::uint64_log2(maxSpareChildCount) + 1), mIdToStateIndex(nrElements) { + DFTStateGenerationInfo(size_t nrElements, size_t maxSpareChildCount) : + mUsageInfoBits(storm::utility::math::uint64_log2(maxSpareChildCount) + 1), + mIdToStateIndex(nrElements) + { assert(maxSpareChildCount < pow(2, mUsageInfoBits)); } @@ -26,6 +30,14 @@ namespace storm { mIdToStateIndex[id] = index; } + void setRestrictionPreElements(size_t id, std::vector const& elems) { + mSeqRestrictionPreElements[id] = elems; + } + + void setRestrictionPostElements(size_t id, std::vector const& elems) { + mSeqRestrictionPostElements[id] = elems; + } + void addSpareActivationIndex(size_t id, size_t index) { mSpareActivationIndex[id] = index; } diff --git a/src/storage/dft/elements/DFTElement.h b/src/storage/dft/elements/DFTElement.h index 11223f3fa..2d57567e9 100644 --- a/src/storage/dft/elements/DFTElement.h +++ b/src/storage/dft/elements/DFTElement.h @@ -205,39 +205,55 @@ namespace storm { return mOutgoingDependencies.size(); } - /*std::set> restrictedItems() const { - std::set> result; - for(auto const& restr : mRestrictions) { - bool foundThis = false; - for(auto const& child : restr->children()) { - if(!foundThis) { - if(child->id() == mId) { - foundThis = true; - } - } else if(result.count(child) == 0) { - result.insert(child); + /** + * Obtains ids of elements which are the direct successor in the list of children of a restriction + * @return A vector of ids + */ + std::vector seqRestrictionPosts() const { + std::vector res; + for (auto const& restr : mRestrictions) { + if(!restr->isSeqEnforcer()) { + continue; + } + auto it = restr->children().cbegin(); + for(; it != restr->children().cend(); ++it) { + if((*it)->id() == mId) { + break; } } + assert(it != restr->children().cend()); + ++it; + if(it != restr->children().cend()) { + res.push_back((*it)->id()); + } } + return res; } - std::set> restrictedItemsTC() const { - std::set> result; - for(auto const& restr : mRestrictions) { - bool foundThis = false; - for(auto const& child : restr->children()) { - if(!foundThis) { - if(child->id() == mId) { - foundThis = true; - } - } else if(result.count(child) == 0) { - result.insert(child); - std::set> tmpRes = child->restrictedItemsTC(); - result.insert(tmpRes.begin(), tmpRes.end()); + /** + * Obtains ids of elements which are the direct predecessor in the list of children of a restriction + * @return A vector of ids + */ + std::vector seqRestrictionPres() const { + std::vector res; + for (auto const& restr : mRestrictions) { + if(!restr->isSeqEnforcer()) { + continue; + } + auto it = restr->children().cbegin(); + for(++it; it != restr->children().cend(); ++it) { + if((*it)->id() == mId) { + break; } } + assert(it != restr->children().cend()); + if(it != restr->children().cbegin()) { + --it; + res.push_back((*it)->id()); + } } - }*/ + return res; + } DFTDependencyVector const& outgoingDependencies() const { return mOutgoingDependencies; diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index 78036528e..dc2e6116e 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -32,6 +32,10 @@ namespace storm { virtual bool isRestriction() const override { return true; } + + virtual bool isSeqEnforcer() const { + return false; + } virtual std::string typestring() const = 0; @@ -162,6 +166,12 @@ namespace storm { DFTRestriction(id, name, children) {} + virtual bool isSeqEnforcer() const override { + return true; + } + + + void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { assert(queues.failurePropagationDone()); bool childOperationalBefore = false; From a6c087f4610a818183146b6f624d3e95dd93de15 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 17:50:51 +0100 Subject: [PATCH 175/246] Dont Care Propagation and SEQ are now sound (but more DCs can be propagated with some care) Former-commit-id: 96288dd8d951caf24325caef0d7eff00cd3e23db --- src/storage/dft/DFT.h | 4 ++++ src/storage/dft/DFTState.cpp | 13 +++++++++++++ src/storage/dft/DFTState.h | 7 +++++++ src/storage/dft/DFTStateGenerationInfo.h | 6 ++++++ src/storage/dft/elements/DFTElement.cpp | 5 ++++- src/storage/dft/elements/DFTElement.h | 2 +- 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 9762def61..22041da85 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -146,6 +146,10 @@ namespace storm { bool isDependency(size_t index) const { return getElement(index)->isDependency(); } + + bool isRestriction(size_t index) const { + return getElement(index)->isRestriction(); + } std::shared_ptr const> getBasicElement(size_t index) const { assert(isBasicElement(index)); diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 547fdd169..419403d55 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -233,6 +233,19 @@ namespace storm { assert(hasFailed(spareId)); mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), mDft.getMaxSpareChildCount()); } + + template + bool DFTState::hasOperationalPostSeqElements(size_t id) const { + assert(!mDft.isDependency(id)); + assert(!mDft.isRestriction(id)); + auto const& postIds = mStateGenerationInfo.seqRestrictionPostElements(id); + for(size_t id : postIds) { + if(isOperational(id)) { + return true; + } + } + return false; + } template bool DFTState::claimNew(size_t spareId, size_t currentlyUses, std::vector>> const& children) { diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index ea874cf1b..826e510d5 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -177,6 +177,13 @@ namespace storm { */ bool orderBySymmetry(); + /** + * Checks whether operational post seq elements are present + * @param id + * @return + */ + bool hasOperationalPostSeqElements(size_t id) const; + std::string getCurrentlyFailableString() const { std::stringstream stream; if (nrFailableDependencies() > 0) { diff --git a/src/storage/dft/DFTStateGenerationInfo.h b/src/storage/dft/DFTStateGenerationInfo.h index a89add9bf..4b3ef92c9 100644 --- a/src/storage/dft/DFTStateGenerationInfo.h +++ b/src/storage/dft/DFTStateGenerationInfo.h @@ -38,6 +38,12 @@ namespace storm { mSeqRestrictionPostElements[id] = elems; } + std::vector const& seqRestrictionPostElements(size_t index) const { + assert(mSeqRestrictionPostElements.count(index) > 0); + return mSeqRestrictionPostElements.at(index); + } + + void addSpareActivationIndex(size_t id, size_t index) { mSpareActivationIndex[id] = index; } diff --git a/src/storage/dft/elements/DFTElement.cpp b/src/storage/dft/elements/DFTElement.cpp index b71e0672b..0ee8a3cd2 100644 --- a/src/storage/dft/elements/DFTElement.cpp +++ b/src/storage/dft/elements/DFTElement.cpp @@ -32,6 +32,10 @@ namespace storm { } } + if(!mRestrictions.empty() && state.hasOperationalPostSeqElements(mId)) { + return false; + } + state.setDontCare(mId); if (hasParentSpare && !state.isActive(mId)) { // Activate child for consistency in failed spares @@ -65,7 +69,6 @@ namespace storm { template std::vector DFTElement::independentSubDft(bool blockParents) const { - //std::cout << "INDEPENDENT SUBTREE CALL " << this->id() << std::endl; std::vector res; res.push_back(this->id()); return res; diff --git a/src/storage/dft/elements/DFTElement.h b/src/storage/dft/elements/DFTElement.h index 2d57567e9..2b3b05c98 100644 --- a/src/storage/dft/elements/DFTElement.h +++ b/src/storage/dft/elements/DFTElement.h @@ -241,7 +241,7 @@ namespace storm { continue; } auto it = restr->children().cbegin(); - for(++it; it != restr->children().cend(); ++it) { + for(; it != restr->children().cend(); ++it) { if((*it)->id() == mId) { break; } From f562a84316eaf408df7ed633437cdf8cfce21711 Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 18:54:20 +0100 Subject: [PATCH 176/246] getRestriction added to DFT interface Former-commit-id: ba114e4478f80c73353310368a0d2c13838a39a7 --- src/storage/dft/DFT.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 22041da85..32e807197 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -165,6 +165,11 @@ namespace storm { assert(isDependency(index)); return std::static_pointer_cast const>(mElements[index]); } + + std::shared_ptr const> getRestriction(size_t index) const { + assert(isRestriction(index)); + return std::static_pointer_cast const>(mElements[index]); + } std::vector>> getBasicElements() const { std::vector>> elements; From 63d2faf1edeee6398fa751dfd78cfcc7820129da Mon Sep 17 00:00:00 2001 From: sjunges Date: Fri, 26 Feb 2016 18:54:48 +0100 Subject: [PATCH 177/246] DFTIsomorphism now runs in the presence of SEQs Former-commit-id: 2666490663774164c43df8eb05a4a3f3a6d35b49 --- src/storage/dft/DFTIsomorphism.h | 111 ++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 11 deletions(-) diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 498170368..e487e92bf 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -14,7 +14,7 @@ namespace storage { struct GateGroupToHash { static constexpr uint_fast64_t fivebitmask = (1 << 6) - 1; - static constexpr uint_fast64_t eightbitmaks = (1 << 8) - 1; + static constexpr uint_fast64_t eightbitmask = (1 << 8) - 1; /** * Hash function, which ensures that the colours are sorted according to their rank. @@ -25,7 +25,7 @@ namespace storage { //Assumes 5 bits for the rank, groupHash |= (static_cast(rank) & fivebitmask) << (62 - 5); // 8 bits for the nrChildren, - groupHash |= (static_cast(nrChildren) & eightbitmaks) << (62 - 5 - 8); + groupHash |= (static_cast(nrChildren) & eightbitmask) << (62 - 5 - 8); // 5 bits for nrParents, groupHash |= (static_cast(nrParents) & fivebitmask) << (62 - 5 - 8 - 5); // 5 bits for nrPDEPs, @@ -36,6 +36,20 @@ namespace storage { } }; + + struct RestrictionGroupToHash { + static constexpr uint_fast64_t fivebitmask = (1 << 6) - 1; + + static constexpr uint_fast64_t eightbitmask = (1 << 8) - 1; + + uint_fast64_t operator()(DFTElementType type, size_t nrChildren, size_t rank) const { + uint_fast64_t groupHash = static_cast(0); + groupHash |= (static_cast(rank) & fivebitmask) << (62 - 5); + groupHash |= (static_cast(nrChildren) & eightbitmask) << (62 - 5 - 8); + groupHash |= (static_cast(type) & fivebitmask) << (62 - 5 - 8 - 5); + return groupHash; + } + }; template @@ -53,8 +67,6 @@ namespace storage { return lhs.hash == rhs.hash && lhs.aRate == rhs.aRate && lhs.pRate == rhs.pRate; } - - /** * */ @@ -63,13 +75,14 @@ namespace storage { std::unordered_map> gateCandidates; std::unordered_map, std::vector> beCandidates; std::unordered_map, std::vector> pdepCandidates; + std::unordered_map> restrictionCandidates; size_t nrGroups() const { - return gateCandidates.size() + beCandidates.size() + pdepCandidates.size(); + return gateCandidates.size() + beCandidates.size() + pdepCandidates.size() + restrictionCandidates.size(); } size_t size() const { - return nrGates() + nrBEs() + nrDeps(); + return nrGates() + nrBEs() + nrDeps() + nrRestrictions(); } size_t nrGates() const { @@ -96,6 +109,14 @@ namespace storage { return res; } + size_t nrRestrictions() const { + size_t res = 0; + for(auto const& x : restrictionCandidates) { + res += x.second.size(); + } + return res; + } + bool hasGate(size_t index) const { for(auto const& x : gateCandidates) { for( auto const& ind : x.second) { @@ -123,8 +144,18 @@ namespace storage { return false; } + bool hasRestriction(size_t index) const { + for(auto const& x : restrictionCandidates) { + for(auto const& ind : x.second) { + if(index == ind) return true; + } + } + return false; + } + + bool has(size_t index) const { - return hasGate(index) || hasBE(index) || hasDep(index); + return hasGate(index) || hasBE(index) || hasDep(index) || hasRestriction(index); } @@ -152,7 +183,9 @@ namespace storage { std::unordered_map gateColour; std::unordered_map> beColour; std::unordered_map> depColour; + std::unordered_map restrictionColour; GateGroupToHash gateColourizer; + RestrictionGroupToHash restrColourizer; public: DFTColouring(DFT const& ft) : dft(ft) { @@ -161,9 +194,11 @@ namespace storage { colourize(dft.getBasicElement(id)); } else if(dft.isGate(id)) { colourize(dft.getGate(id)); - } else { - assert(dft.isDependency(id)); + } else if(dft.isDependency(id)) { colourize(dft.getDependency(id)); + } else { + assert(dft.isRestriction(id)); + colourize(dft.getRestriction(id)); } } } @@ -186,14 +221,21 @@ namespace storage { } else { res.gateCandidates[gateColour.at(index)] = std::vector({index}); } - } else { - assert(dft.isDependency(index)); + } else if(dft.isDependency(index)) { auto it = res.pdepCandidates.find(depColour.at(index)); if(it != res.pdepCandidates.end()) { it->second.push_back(index); } else { res.pdepCandidates[depColour.at(index)] = std::vector({index}); } + } else { + assert(dft.isRestriction(index)); + auto it = res.restrictionCandidates.find(restrictionColour.at(index)); + if(it != res.restrictionCandidates.end()) { + it->second.push_back(index); + } else { + res.restrictionCandidates[restrictionColour.at(index)] = std::vector({index}); + } } } @@ -214,6 +256,10 @@ namespace storage { void colourize(std::shared_ptr> const& dep) { depColour[dep->id()] = std::pair(dep->probability(), dep->dependentEvent()->activeFailureRate()); } + + void colourize(std::shared_ptr> const& restr) { + restrictionColour[restr->id()] = restrColourizer(restr->type(), restr->nrChildren(), restr->rank()); + } }; @@ -289,6 +335,7 @@ namespace storage { initializePermutationsAndTreatTrivialGroups(bleft.beCandidates, bright.beCandidates, currentPermutations.beCandidates); initializePermutationsAndTreatTrivialGroups(bleft.gateCandidates, bright.gateCandidates, currentPermutations.gateCandidates); initializePermutationsAndTreatTrivialGroups(bleft.pdepCandidates, bright.pdepCandidates, currentPermutations.pdepCandidates); + initializePermutationsAndTreatTrivialGroups(bleft.restrictionCandidates, bright.restrictionCandidates, currentPermutations.restrictionCandidates); std::cout << bijection.size() << " vs. " << bleft.size() << " vs. " << bright.size() << std::endl; assert(bijection.size() == bleft.size()); @@ -323,6 +370,15 @@ namespace storage { ++it; } } + + if(!foundNext && !currentPermutations.restrictionCandidates.empty()) { + auto it = currentPermutations.restrictionCandidates.begin(); + while(!foundNext && it != currentPermutations.restrictionCandidates.end()) { + foundNext = std::next_permutation(it->second.begin(), it->second.end()); + ++it; + } + } + if(foundNext) { for(auto const& colour : bleft.beCandidates) { @@ -336,6 +392,10 @@ namespace storage { for(auto const& colour : bleft.pdepCandidates) { zipVectorsIntoMap(colour.second, currentPermutations.pdepCandidates.find(colour.first)->second, bijection); } + + for(auto const& colour : bleft.restrictionCandidates) { + zipVectorsIntoMap(colour.second, currentPermutations.restrictionCandidates.find(colour.first)->second, bijection); + } } return foundNext; @@ -378,6 +438,23 @@ namespace storage { if(bijection.at(lDep->dependentEvent()->id()) != rDep->dependentEvent()->id()) { return false; } + } else if(dft.isRestriction(indexpair.first)) { + assert(dft.isRestriction(indexpair.second)); + auto const& lRestr = dft.getRestriction(indexpair.first); + std::set childrenLeftMapped; + for(auto const& child : lRestr->children() ) { + assert(bleft.has(child->id())); + childrenLeftMapped.insert(bijection.at(child->id())); + } + auto const& rRestr = dft.getRestriction(indexpair.second); + std::set childrenRight; + for(auto const& child : rRestr->children() ) { + assert(bright.has(child->id())); + childrenRight.insert(child->id()); + } + if(childrenLeftMapped != childrenRight) { + return false; + } } else { assert(dft.isBasicElement(indexpair.first)); @@ -405,10 +482,15 @@ namespace storage { candidatesCompatible = false; return; } + if(bleft.restrictionCandidates.size() != bright.restrictionCandidates.size()) { + candidatesCompatible = false; + return; + } for (auto const &gc : bleft.gateCandidates) { if (bright.gateCandidates.count(gc.first) == 0) { candidatesCompatible = false; + return; } } for(auto const& bc : bleft.beCandidates) { @@ -424,6 +506,13 @@ namespace storage { return; } } + + for(auto const& dc : bleft.restrictionCandidates) { + if(bright.restrictionCandidates.count(dc.first) == 0) { + candidatesCompatible = false; + return; + } + } } /** From b74cd564e440e25bf17d85a2022a026a597f713f Mon Sep 17 00:00:00 2001 From: sjunges Date: Mon, 29 Feb 2016 10:38:08 +0100 Subject: [PATCH 178/246] some further changes Former-commit-id: ad72bbef3677218e2e875b9b3c7de6450862ba2b --- src/storage/dft/DFTIsomorphism.h | 42 +++++++++++++++++++++--------- src/storage/dft/elements/DFTGate.h | 4 +++ 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index e487e92bf..542fa954a 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -414,20 +414,38 @@ namespace storage { if(dft.isGate(indexpair.first)) { assert(dft.isGate(indexpair.second)); auto const& lGate = dft.getGate(indexpair.first); - std::set childrenLeftMapped; - for(auto const& child : lGate->children() ) { - assert(bleft.has(child->id())); - childrenLeftMapped.insert(bijection.at(child->id())); - } auto const& rGate = dft.getGate(indexpair.second); - std::set childrenRight; - for(auto const& child : rGate->children() ) { - assert(bright.has(child->id())); - childrenRight.insert(child->id()); - } - if(childrenLeftMapped != childrenRight) { - return false; + if(lGate->isDynamicGate()) { + std::vector childrenLeftMapped; + for(auto const& child : lGate->children() ) { + assert(bleft.has(child->id())); + childrenLeftMapped.push_back(bijection.at(child->id())); + } + std::vector childrenRight; + for(auto const& child : rGate->children() ) { + assert(bright.has(child->id())); + childrenRight.push_back(child->id()); + } + if(childrenLeftMapped != childrenRight) { + return false; + } + } else { + std::set childrenLeftMapped; + for(auto const& child : lGate->children() ) { + assert(bleft.has(child->id())); + childrenLeftMapped.insert(bijection.at(child->id())); + } + std::set childrenRight; + for(auto const& child : rGate->children() ) { + assert(bright.has(child->id())); + childrenRight.insert(child->id()); + } + if(childrenLeftMapped != childrenRight) { + return false; + } } + + } else if(dft.isDependency(indexpair.first)) { assert(dft.isDependency(indexpair.second)); auto const& lDep = dft.getDependency(indexpair.first); diff --git a/src/storage/dft/elements/DFTGate.h b/src/storage/dft/elements/DFTGate.h index 52f9bcd43..d82906895 100644 --- a/src/storage/dft/elements/DFTGate.h +++ b/src/storage/dft/elements/DFTGate.h @@ -35,6 +35,10 @@ namespace storm { return true; } + bool isDynamicGate() const { + return !isStaticGateType(this->type()); + } + virtual std::string typestring() const = 0; From 9d97750ca53f65cc4b5e5e0f8e38491415043c13 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 29 Feb 2016 10:59:16 +0100 Subject: [PATCH 179/246] Improved compareAndSwap on BitVector Former-commit-id: db953c187a962edf3eadd2ea4e2017b8e00eeb46 --- src/storage/BitVector.cpp | 128 +++++++++++++++++++++++++++++++++----- src/storage/BitVector.h | 4 +- 2 files changed, 113 insertions(+), 19 deletions(-) diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index 02e40aa59..884ea546c 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -670,16 +670,60 @@ namespace storm { return endIndex; } - BitVector BitVector::getAsBitVector(uint_fast64_t start, uint_fast64_t length) { - BitVector result(length); + storm::storage::BitVector BitVector::getAsBitVector(uint_fast64_t start, uint_fast64_t length) const { + assert(start + length <= bitCount); + storm::storage::BitVector result(length, false); - uint_fast64_t index = 0; - for ( ; index + 63 <= length; index += 63) { - result.setFromInt(index, 63, getAsInt(start + index, 63)); + uint_fast64_t offset = start % 64; + uint_fast64_t bucketIndex = start / 64; + uint_fast64_t insertBucket = 0; + uint_fast64_t getValue; + uint_fast64_t writeValue = 0; + uint_fast64_t noBits = 0; + if (offset == 0) { + // Copy complete buckets + for ( ; noBits + 64 <= length; ++bucketIndex, ++insertBucket, noBits += 64) { + result.bucketVector[insertBucket] = bucketVector[bucketIndex]; + } + } else { + //Get first bits up until next bucket + getValue = bucketVector[bucketIndex]; + writeValue = (getValue << offset); + noBits += (64-offset); + ++bucketIndex; + + //Get complete buckets + for ( ; noBits + 64 <= length; ++bucketIndex, ++insertBucket, noBits += 64) { + getValue = bucketVector[bucketIndex]; + // Get bits till write bucket is full + writeValue |= (getValue >> (64-offset)); + result.bucketVector[insertBucket] = writeValue; + // Get bits up until next bucket + writeValue = (getValue << offset); + } } - // Insert remaining bits - result.setFromInt(index, length-index, getAsInt(start+index, length-index)); + // Write last bits + uint_fast64_t remainingBits = length - noBits; + assert(bucketIndex < bucketCount()); + // Get remaining bits + getValue = (bucketVector[bucketIndex] >> (64-remainingBits)) << (64-remainingBits); + assert(remainingBits < 64); + if (remainingBits <= offset || offset == 0) { + // Write completely + assert(insertBucket == result.bucketCount()-1); + writeValue = getValue; + result.bucketVector[insertBucket] = writeValue; + } else { + // Remaining bits do not fit in value -> need new value + assert(insertBucket == result.bucketCount() - 2); + writeValue |= (getValue >> (64-offset)); + result.bucketVector[insertBucket] = writeValue; + // Write last bits + writeValue = (getValue << (remainingBits-offset)); + result.bucketVector[++insertBucket] = writeValue; + } + #ifdef ASSERT_BITVECTOR // Check correctness of getter for (uint_fast64_t i = 0; i < length; ++i) { @@ -690,13 +734,62 @@ namespace storm { } void BitVector::setFromBitVector(uint_fast64_t start, BitVector const& other) { - uint_fast64_t index = 0; - for ( ; index + 63 <= other.bitCount; index += 63) { - setFromInt(start+index, 63, other.getAsInt(index, 63)); + assert(start + other.bitCount <= bitCount); + + uint_fast64_t offset = start % 64; + uint_fast64_t bucketIndex = start / 64; + uint_fast64_t getBucket = 0; + uint_fast64_t getValue; + uint_fast64_t writeValue = 0; + uint_fast64_t noBits = 0; + if (offset == 0) { + // Copy complete buckets + for ( ; noBits + 64 <= other.bitCount; ++bucketIndex, ++getBucket, noBits += 64) { + bucketVector[bucketIndex] = other.bucketVector[getBucket]; + } + } else { + //Get first bits up until next bucket + getValue = other.bucketVector[getBucket]; + writeValue = (bucketVector[bucketIndex] >> (64-offset)) << (64-offset); + writeValue |= (getValue >> offset); + bucketVector[bucketIndex] = writeValue; + noBits += (64-offset); + ++bucketIndex; + + //Get complete buckets + for ( ; noBits + 64 <= other.bitCount; ++bucketIndex, noBits += 64) { + // Get all remaining bits from other bucket + writeValue = getValue << (64-offset); + // Get bits from next bucket + getValue = other.bucketVector[++getBucket]; + writeValue |= getValue >> offset; + bucketVector[bucketIndex] = writeValue; + } } - // Insert remaining bits - setFromInt(start+index, other.bitCount-index, other.getAsInt(index, other.bitCount-index)); + // Write last bits + uint_fast64_t remainingBits = other.bitCount - noBits; + assert(bucketIndex < bucketCount()); + assert(getBucket < other.bucketCount()); + // Get remaining bits + getValue = other.bucketVector[getBucket] << (64-offset); + assert(remainingBits < 64); + if (remainingBits <= offset || offset == 0) { + // Write completely + assert(getBucket == other.bucketCount()-1); + getValue = (getValue >> (64-offset-remainingBits)) << (64-offset-remainingBits); + writeValue = (bucketVector[bucketIndex] << (offset+remainingBits)) >> (offset+remainingBits); + writeValue |= getValue; + bucketVector[bucketIndex] = writeValue; + } else { + // Remaining bits do not come from one bucket -> consider two buckets + assert(getBucket == other.bucketCount() - 2); + getValue |= other.bucketVector[++getBucket] >> offset; + writeValue = (bucketVector[bucketIndex] << (offset+remainingBits)) >> (offset+remainingBits); + writeValue |= getValue; + bucketVector[bucketIndex] = writeValue; + } + #ifdef ASSERT_BITVECTOR // Check correctness of setter for (uint_fast64_t i = 0; i < other.bitCount; ++i) { @@ -707,6 +800,7 @@ namespace storm { bool BitVector::compareAndSwap(uint_fast64_t start1, uint_fast64_t start2, uint_fast64_t length) { if (length < 64) { + // Just use one number uint_fast64_t elem1 = getAsInt(start1, length); uint_fast64_t elem2 = getAsInt(start2, length); if (elem1 < elem2) { @@ -717,7 +811,7 @@ namespace storm { } return false; } else { - //TODO improve performance + // Use bit vectors BitVector elem1 = getAsBitVector(start1, length); BitVector elem2 = getAsBitVector(start2, length); @@ -787,21 +881,21 @@ namespace storm { return out; } - void BitVector::printBits(std::ostream& out) { + void BitVector::printBits(std::ostream& out) const { out << "bit vector(" << getNumberOfSetBits() << "/" << bitCount << ") "; uint_fast64_t index = 0; - for ( ; index * 64 <= bitCount; ++index) { + for ( ; index * 64 + 64 <= bitCount; ++index) { std::bitset<64> tmp(bucketVector[index]); out << tmp << "|"; } - --index; // Print last bits if (index * 64 < bitCount) { assert(index == bucketVector.size() - 1); std::bitset<64> tmp(bucketVector[index]); for (size_t i = 0; i + index * 64 < bitCount; ++i) { - out << tmp[i]; + // Bits are counted from rightmost in bitset + out << tmp[63-i]; } } out << std::endl; diff --git a/src/storage/BitVector.h b/src/storage/BitVector.h index e3f81ebc9..2338faac6 100644 --- a/src/storage/BitVector.h +++ b/src/storage/BitVector.h @@ -508,7 +508,7 @@ namespace storm { * @param length The number of bits to get. * @return A new bit vector holding the selected bits. */ - BitVector getAsBitVector(uint_fast64_t start, uint_fast64_t length); + BitVector getAsBitVector(uint_fast64_t start, uint_fast64_t length) const; /*! * Sets the exact bit pattern of the given bit vector starting at the given bit index. Note: the given bit @@ -524,7 +524,7 @@ namespace storm { * * @param out Stream to print to. */ - void printBits(std::ostream& out); + void printBits(std::ostream& out) const; /*! * Retrieves the number of buckets of the underlying storage. From f935f502dd44309ee38670f7af17afc15917af83 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 29 Feb 2016 15:49:33 +0100 Subject: [PATCH 180/246] Activate pCTMCs for storm Former-commit-id: 5cacb49d18817483dd2f7f2c9d3a546debf0dd15 --- src/cli/entrypoints.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/entrypoints.h b/src/cli/entrypoints.h index bbb9d6404..8071d99c1 100644 --- a/src/cli/entrypoints.h +++ b/src/cli/entrypoints.h @@ -29,7 +29,7 @@ namespace storm { inline void verifySparseModel(std::shared_ptr> model, std::vector> const& formulas, bool onlyInitialStatesRelevant) { for (auto const& formula : formulas) { - STORM_LOG_THROW(model->getType() == storm::models::ModelType::Dtmc, storm::exceptions::InvalidSettingsException, "Currently parametric verification is only available for DTMCs."); + STORM_LOG_THROW(model->getType() == storm::models::ModelType::Dtmc || model->getType() == storm::models::ModelType::Ctmc, storm::exceptions::InvalidSettingsException, "Currently parametric verification is only available for DTMCs and CTMCs."); std::cout << std::endl << "Model checking property: " << *formula << " ..."; std::unique_ptr result(storm::verifySparseModel(model, formula, onlyInitialStatesRelevant)); if (result) { From 9b8dd018cfcde5a6cd53f5affb3fefb1ced0aaff Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 29 Feb 2016 19:08:32 +0100 Subject: [PATCH 181/246] Fixed problem with gate as trigger events for dependencies Former-commit-id: 87cd1115bbe7dd4cb672d99b9d1671478626de5a --- src/builder/ExplicitDFTModelBuilder.cpp | 4 +++- src/storage/dft/DFT.cpp | 32 ++++++++++++++++++------- src/storage/dft/DFTState.cpp | 19 ++++++++------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index f14408190..1c9c64684 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -196,12 +196,14 @@ namespace storm { while (!queues.failurePropagationDone()) { DFTGatePointer next = queues.nextFailurePropagation(); next->checkFails(*newState, queues); + newState->updateFailableDependencies(next->id()); } while(!queues.restrictionChecksDone()) { DFTRestrictionPointer next = queues.nextRestrictionCheck(); next->checkFails(*newState, queues); - } + newState->updateFailableDependencies(next->id()); + } if(newState->isInvalid()) { continue; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 9a12fe2f6..bf68a095c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -56,14 +56,24 @@ namespace storm { topModuleSet.insert(elem->id()); } } - + // Erase spare modules for(auto const& module : mSpareModules) { for(auto const& index : module.second) { topModuleSet.erase(index); } } + // Extend top module and insert those elements which are part of the top module and a spare module + mElements[mTopLevelIndex]->extendSpareModule(topModuleSet); mTopModule = std::vector(topModuleSet.begin(), topModuleSet.end()); - + // Clear all spare modules where at least one element is also in the top module + if (!mTopModule.empty()) { + for (auto& module : mSpareModules) { + if (std::find(module.second.begin(), module.second.end(), mTopModule.front()) != module.second.end()) { + module.second.clear(); + } + } + } + //Reserve space for failed spares ++mMaxSpareChildCount; size_t usageInfoBits = storm::utility::math::uint64_log2(mMaxSpareChildCount) + 1; @@ -240,6 +250,10 @@ namespace storm { std::stringstream stream; stream << "[" << mElements[mTopLevelIndex]->id() << "] {"; std::vector::const_iterator it = mTopModule.begin(); + if (it == mTopModule.end()) { + stream << "}" << std::endl; + return stream.str(); + } assert(it != mTopModule.end()); stream << mElements[(*it)]->name(); ++it; @@ -251,13 +265,15 @@ namespace storm { for(auto const& spareModule : mSpareModules) { stream << "[" << mElements[spareModule.first]->name() << "] = {"; - std::vector::const_iterator it = spareModule.second.begin(); - assert(it != spareModule.second.end()); - stream << mElements[(*it)]->name(); - ++it; - while(it != spareModule.second.end()) { - stream << ", " << mElements[(*it)]->name(); + if (!spareModule.second.empty()) { + std::vector::const_iterator it = spareModule.second.begin(); + assert(it != spareModule.second.end()); + stream << mElements[(*it)]->name(); ++it; + while(it != spareModule.second.end()) { + stream << ", " << mElements[(*it)]->name(); + ++it; + } } stream << "}" << std::endl; } diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 419403d55..1d34362f9 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -129,15 +129,16 @@ namespace storm { template bool DFTState::updateFailableDependencies(size_t id) { - assert(hasFailed(id)); - for (size_t i = 0; i < mDft.getDependencies().size(); ++i) { - std::shared_ptr const> dependency = mDft.getDependency(mDft.getDependencies()[i]); - if (dependency->triggerEvent()->id() == id) { - if (getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) { - assert(!isFailsafe(dependency->dependentEvent()->id())); - mFailableDependencies.push_back(dependency->id()); - STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); - } + if (!hasFailed(id)) { + return false; + } + + for (auto dependency : mDft.getElement(id)->outgoingDependencies()) { + assert(dependency->triggerEvent()->id() == id); + if (getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) { + assert(!isFailsafe(dependency->dependentEvent()->id())); + mFailableDependencies.push_back(dependency->id()); + STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); } } return nrFailableDependencies() > 0; From 7f4fa270088b1adc8ea11346d7ce5af810cf5865 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 10:21:21 +0100 Subject: [PATCH 182/246] Initialize closed for MA Former-commit-id: 292352f2580315b8e5c48d0736bfb9314c96b146 --- src/models/sparse/MarkovAutomaton.cpp | 19 ++++++++++++++++--- src/models/sparse/MarkovAutomaton.h | 7 +++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/models/sparse/MarkovAutomaton.cpp b/src/models/sparse/MarkovAutomaton.cpp index 8276f519d..aa5ffc5e2 100644 --- a/src/models/sparse/MarkovAutomaton.cpp +++ b/src/models/sparse/MarkovAutomaton.cpp @@ -19,8 +19,9 @@ namespace storm { std::vector const& exitRates, std::unordered_map const& rewardModels, boost::optional> const& optionalChoiceLabeling) - : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, transitionMatrix, stateLabeling, rewardModels, optionalChoiceLabeling), markovianStates(markovianStates), exitRates(exitRates), closed(false) { + : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, transitionMatrix, stateLabeling, rewardModels, optionalChoiceLabeling), markovianStates(markovianStates), exitRates(exitRates) { this->turnRatesToProbabilities(); + closed = !hasHybridState(); } template @@ -30,8 +31,9 @@ namespace storm { std::vector const& exitRates, std::unordered_map&& rewardModels, boost::optional>&& optionalChoiceLabeling) - : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), markovianStates(markovianStates), exitRates(std::move(exitRates)), closed(false) { + : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), markovianStates(markovianStates), exitRates(std::move(exitRates)) { this->turnRatesToProbabilities(); + closed = !hasHybridState(); } template @@ -42,9 +44,10 @@ namespace storm { bool probabilities, std::unordered_map&& rewardModels, boost::optional>&& optionalChoiceLabeling) - : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), markovianStates(markovianStates), exitRates(std::move(exitRates)), closed(false) { + : NondeterministicModel(storm::models::ModelType::MarkovAutomaton, std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels), std::move(optionalChoiceLabeling)), markovianStates(markovianStates), exitRates(std::move(exitRates)) { assert(probabilities); assert(this->getTransitionMatrix().isProbabilistic()); + closed = !hasHybridState(); } template @@ -67,6 +70,16 @@ namespace storm { return !this->markovianStates.get(state); } + template + bool MarkovAutomaton::hasHybridState() const { + for (uint_fast64_t state = 0; state < this->getNumberOfStates(); ++state) { + if (this->isHybridState(state)) { + return true; + } + } + return false; + } + template std::vector const& MarkovAutomaton::getExitRates() const { return this->exitRates; diff --git a/src/models/sparse/MarkovAutomaton.h b/src/models/sparse/MarkovAutomaton.h index e335f5050..d97ff1517 100644 --- a/src/models/sparse/MarkovAutomaton.h +++ b/src/models/sparse/MarkovAutomaton.h @@ -157,6 +157,13 @@ namespace storm { */ void turnRatesToProbabilities(); + /*! + * Check if at least one hybrid state exists. + * + * @return True, if at least one hybrid state exists, false if none exists. + */ + bool hasHybridState() const; + // A bit vector representing the set of Markovian states. storm::storage::BitVector markovianStates; From f8b9ece2fd9b788ba163934c1203cf753448e01e Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 10:21:55 +0100 Subject: [PATCH 183/246] Added mini test for BitVector Former-commit-id: 8ec7395c0d80a1cb31eeef8b2cf9e74a50639238 --- test/functional/storage/BitVectorTest.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/functional/storage/BitVectorTest.cpp b/test/functional/storage/BitVectorTest.cpp index db92724fe..3e4d53235 100644 --- a/test/functional/storage/BitVectorTest.cpp +++ b/test/functional/storage/BitVectorTest.cpp @@ -510,4 +510,17 @@ TEST(BitVectorTest, Iterator) { for (auto bit : vector) { ASSERT_TRUE(bit % 2 == 0); } +} + +TEST(BitVectorTest, CompareAndSwap) { + storm::storage::BitVector vector(140); + vector.setFromInt(0, 64, 2377830234574424100); + vector.setFromInt(64, 64, 1152921504607379586); + vector.setFromInt(128, 12, 2080); + + bool result = vector.compareAndSwap(0, 68, 68); + ASSERT_FALSE(result); + + result = vector.compareAndSwap(68, 0, 68); + ASSERT_TRUE(result); } \ No newline at end of file From e4c270288904fdb531969501823b1a177bedb5b8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 12:18:01 +0100 Subject: [PATCH 184/246] Fixed problem in MaximalEndComponents Former-commit-id: 950b9cfdfa677f47567e2c90fdadd3a65867dac4 --- .../helper/SparseMarkovAutomatonCslHelper.cpp | 46 +++++++------ src/storage/Decomposition.cpp | 5 ++ src/storage/Decomposition.h | 7 ++ .../MaximalEndComponentDecomposition.cpp | 68 ++++++++++--------- 4 files changed, 72 insertions(+), 54 deletions(-) diff --git a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp index d926917a5..95007a9e6 100644 --- a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp @@ -407,33 +407,35 @@ namespace storm { infinityStates = storm::storage::BitVector(numberOfStates); } } - // Now we identify the states for which values need to be computed. storm::storage::BitVector maybeStates = ~(goalStates | infinityStates); - - // Then, we can eliminate the rows and columns for all states whose values are already known to be 0. - std::vector x(maybeStates.getNumberOfSetBits()); - storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates); - - // Now prepare the expected reward values for all states so they can be used as the right-hand side of the equation system. - std::vector rewardValues(stateRewards); - for (auto state : markovianStates) { - rewardValues[state] = rewardValues[state] / exitRateVector[state]; - } - - // Finally, prepare the actual right-hand side. - std::vector b(submatrix.getRowCount()); - storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, transitionMatrix.getRowGroupIndices(), rewardValues); - - // Solve the corresponding system of equations. - std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(submatrix); - solver->solveEquationSystem(dir, x, b); - + // Create resulting vector. std::vector result(numberOfStates); - // Set values of resulting vector according to previous result and return the result. - storm::utility::vector::setVectorValues(result, maybeStates, x); + if (!maybeStates.empty()) { + // Then, we can eliminate the rows and columns for all states whose values are already known. + std::vector x(maybeStates.getNumberOfSetBits()); + storm::storage::SparseMatrix submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates); + + // Now prepare the expected reward values for all states so they can be used as the right-hand side of the equation system. + std::vector rewardValues(stateRewards); + for (auto state : markovianStates) { + rewardValues[state] = rewardValues[state] / exitRateVector[state]; + } + + // Finally, prepare the actual right-hand side. + std::vector b(submatrix.getRowCount()); + storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, transitionMatrix.getRowGroupIndices(), rewardValues); + + // Solve the corresponding system of equations. + std::unique_ptr> solver = minMaxLinearEquationSolverFactory.create(submatrix); + solver->solveEquationSystem(dir, x, b); + + // Set values of resulting vector according to previous result and return the result. + storm::utility::vector::setVectorValues(result, maybeStates, x); + } + storm::utility::vector::setVectorValues(result, goalStates, storm::utility::zero()); storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity()); diff --git a/src/storage/Decomposition.cpp b/src/storage/Decomposition.cpp index 4e2ebcb02..54d7ef12e 100644 --- a/src/storage/Decomposition.cpp +++ b/src/storage/Decomposition.cpp @@ -41,6 +41,11 @@ namespace storm { return blocks.size(); } + template + bool Decomposition::empty() const { + return blocks.empty(); + } + template typename Decomposition::iterator Decomposition::begin() { return blocks.begin(); diff --git a/src/storage/Decomposition.h b/src/storage/Decomposition.h index ce522c171..76f8a28a8 100644 --- a/src/storage/Decomposition.h +++ b/src/storage/Decomposition.h @@ -63,6 +63,13 @@ namespace storm { */ std::size_t size() const; + /*! + * Checks if the decomposition is empty. + * + * @return True, if the decomposition is empty. + */ + bool empty() const; + /*! * Retrieves an iterator that points to the first block of this decomposition. * diff --git a/src/storage/MaximalEndComponentDecomposition.cpp b/src/storage/MaximalEndComponentDecomposition.cpp index 31c421224..a944ecd23 100644 --- a/src/storage/MaximalEndComponentDecomposition.cpp +++ b/src/storage/MaximalEndComponentDecomposition.cpp @@ -86,48 +86,52 @@ namespace storm { mecChanged |= sccs.size() > 1 || (sccs.size() > 0 && sccs[0].size() < mec.size()); // Check for each of the SCCs whether there is at least one action for each state that does not leave the SCC. - for (auto& scc : sccs) { - statesToCheck.set(scc.begin(), scc.end()); - - while (!statesToCheck.empty()) { - storm::storage::BitVector statesToRemove(numberOfStates); + if (sccs.empty()) { + mecChanged = true; + } else { + for (auto& scc : sccs) { + statesToCheck.set(scc.begin(), scc.end()); - for (auto state : statesToCheck) { - bool keepStateInMEC = false; + while (!statesToCheck.empty()) { + storm::storage::BitVector statesToRemove(numberOfStates); - for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { - bool choiceContainedInMEC = true; - for (auto const& entry : transitionMatrix.getRow(choice)) { - if (!scc.containsState(entry.getColumn())) { - choiceContainedInMEC = false; + for (auto state : statesToCheck) { + bool keepStateInMEC = false; + + for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { + bool choiceContainedInMEC = true; + for (auto const& entry : transitionMatrix.getRow(choice)) { + if (!scc.containsState(entry.getColumn())) { + choiceContainedInMEC = false; + break; + } + } + + // If there is at least one choice whose successor states are fully contained in the MEC, we can leave the state in the MEC. + if (choiceContainedInMEC) { + keepStateInMEC = true; break; } } - // If there is at least one choice whose successor states are fully contained in the MEC, we can leave the state in the MEC. - if (choiceContainedInMEC) { - keepStateInMEC = true; - break; + if (!keepStateInMEC) { + statesToRemove.set(state, true); } } - if (!keepStateInMEC) { - statesToRemove.set(state, true); + // Now erase the states that have no option to stay inside the MEC with all successors. + mecChanged |= !statesToRemove.empty(); + for (uint_fast64_t state : statesToRemove) { + scc.erase(state); } - } - - // Now erase the states that have no option to stay inside the MEC with all successors. - mecChanged |= !statesToRemove.empty(); - for (uint_fast64_t state : statesToRemove) { - scc.erase(state); - } - - // Now check which states should be reconsidered, because successors of them were removed. - statesToCheck.clear(); - for (auto state : statesToRemove) { - for (auto const& entry : backwardTransitions.getRow(state)) { - if (scc.containsState(entry.getColumn())) { - statesToCheck.set(entry.getColumn()); + + // Now check which states should be reconsidered, because successors of them were removed. + statesToCheck.clear(); + for (auto state : statesToRemove) { + for (auto const& entry : backwardTransitions.getRow(state)) { + if (scc.containsState(entry.getColumn())) { + statesToCheck.set(entry.getColumn()); + } } } } From 37a86d81906bcc18c690c6036412249ee99d8e3f Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 13:22:14 +0100 Subject: [PATCH 185/246] Compile fixes for gcc Former-commit-id: cb1b187ef84f512ff5583d7c3d276cac9157ed05 --- src/settings/Option.cpp | 3 ++- src/storage/BitVectorHashMap.cpp | 1 + src/storage/dd/Bdd.cpp | 4 +++- src/utility/macros.h | 3 ++- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/settings/Option.cpp b/src/settings/Option.cpp index b5cba7759..cba074b58 100644 --- a/src/settings/Option.cpp +++ b/src/settings/Option.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "ArgumentBase.h" #include "Argument.h" @@ -211,4 +212,4 @@ namespace storm { return out; } } -} \ No newline at end of file +} diff --git a/src/storage/BitVectorHashMap.cpp b/src/storage/BitVectorHashMap.cpp index 07eefee1d..760ffe039 100644 --- a/src/storage/BitVectorHashMap.cpp +++ b/src/storage/BitVectorHashMap.cpp @@ -1,6 +1,7 @@ #include "src/storage/BitVectorHashMap.h" #include +#include #include "src/utility/macros.h" diff --git a/src/storage/dd/Bdd.cpp b/src/storage/dd/Bdd.cpp index 8f176048e..f8bf6b368 100644 --- a/src/storage/dd/Bdd.cpp +++ b/src/storage/dd/Bdd.cpp @@ -1,3 +1,5 @@ +#include + #include "src/storage/dd/Bdd.h" #include "src/storage/dd/Add.h" #include "src/storage/dd/Odd.h" @@ -360,4 +362,4 @@ namespace storm { template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; } -} \ No newline at end of file +} diff --git a/src/utility/macros.h b/src/utility/macros.h index 4f70b1691..16dd4d70e 100644 --- a/src/utility/macros.h +++ b/src/utility/macros.h @@ -2,6 +2,7 @@ #define STORM_UTILITY_MACROS_H_ #include +#include #include "storm-config.h" #ifndef STORM_LOGGING_FRAMEWORK @@ -272,4 +273,4 @@ LOG4CPLUS_INFO(logger, "Enabled trace mode, log output gets printed to console." STORM_PRINT(message); \ } -#endif /* STORM_UTILITY_MACROS_H_ */ \ No newline at end of file +#endif /* STORM_UTILITY_MACROS_H_ */ From 4c2b1d7c22019a0ff8c9a16cfbf45e7e48336fb3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 13:22:43 +0100 Subject: [PATCH 186/246] Model info for benchmarking scripts Former-commit-id: 7a686f5f79f5951edee96fb434a84312476b1a2a --- src/storm-dyftee.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index e167633bd..c1bafd78a 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -46,7 +46,8 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) model->printModelInformationToStream(std::cout); - + std::cout << "No. states (Explored): " << model->getNumberOfStates() << std::endl; + std::cout << "No. transitions (Explored): " << model->getNumberOfTransitions() << std::endl; std::cout << "Bisimulation..." << std::endl; if (model->getNumberOfStates() > 500 && model->isOfType(storm::models::ModelType::Ctmc)) { @@ -54,6 +55,8 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) } model->printModelInformationToStream(std::cout); + std::cout << "No. states (Bisimulation): " << model->getNumberOfStates() << std::endl; + std::cout << "No. transitions (Bisimulation): " << model->getNumberOfTransitions() << std::endl; // Model checking std::cout << "Model checking..." << std::endl; From c05e6711111a200c4fec993ad80b07f79cf4b3f4 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 13:28:38 +0100 Subject: [PATCH 187/246] Handling of min and max for non-determinism Former-commit-id: 1a3a38c5115e19e93ed24f4d433e7705520988a6 --- src/storm-dyftee.cpp | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index e167633bd..3d93d4107 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -47,14 +47,12 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) model->printModelInformationToStream(std::cout); - std::cout << "Bisimulation..." << std::endl; - if (model->getNumberOfStates() > 500 && model->isOfType(storm::models::ModelType::Ctmc)) { - model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); + std::cout << "Bisimulation..." << std::endl; + model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); + model->printModelInformationToStream(std::cout); } - model->printModelInformationToStream(std::cout); - // Model checking std::cout << "Model checking..." << std::endl; std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); @@ -81,20 +79,25 @@ int main(int argc, char** argv) { // Parse cli arguments bool parametric = false; bool symred = false; + bool minimal = true; std::string filename = argv[1]; + std::string operatorType = ""; + std::string targetFormula = ""; std::string pctlFormula = ""; for (int i = 2; i < argc; ++i) { std::string option = argv[i]; if (option == "--parametric") { parametric = true; } else if (option == "--expectedtime") { - assert(pctlFormula.empty()); - pctlFormula = "ET=?[F \"failed\"]"; + assert(targetFormula.empty()); + operatorType = "ET"; + targetFormula = "F \"failed\""; } else if (option == "--probability") { - assert(pctlFormula.empty()); - pctlFormula = "P=? [F \"failed\"]"; + assert(targetFormula.empty()); + operatorType = "P";; + targetFormula = "F \"failed\""; } else if (option == "--timebound") { - assert(pctlFormula.empty()); + assert(targetFormula.empty()); ++i; assert(i < argc); double timeBound; @@ -105,8 +108,9 @@ int main(int argc, char** argv) { return 2; } std::stringstream stream; - stream << "P=? [F<=" << timeBound << " \"failed\"]"; - pctlFormula = stream.str(); + stream << "F<=" << timeBound << " \"failed\""; + operatorType = "P"; + targetFormula = stream.str(); } else if (option == "--trace") { STORM_GLOBAL_LOGLEVEL_TRACE(); } else if (option == "--debug") { @@ -118,11 +122,22 @@ int main(int argc, char** argv) { pctlFormula = argv[i]; } else if (option == "--symred") { symred = true; + } else if (option == "--min") { + minimal = true; + } else if (option == "--max") { + minimal = false; } else { std::cout << "Option '" << option << "' not recognized." << std::endl; return 1; } } + + // Construct pctlFormula + if (!targetFormula.empty()) { + assert(pctlFormula.empty()); + pctlFormula = operatorType + (minimal ? "min" : "max") + "=?[" + targetFormula + "]"; + } + assert(!pctlFormula.empty()); storm::utility::setUp(); From 7b7b999548844103bde63c37b493ec8de2bf3950 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 16:44:34 +0100 Subject: [PATCH 188/246] Bisimulation for small models as well Former-commit-id: 51bcbc23d820363c447dbdaaaa51426844d520a3 --- src/storm-dyftee.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index c30e6e5ba..13b43f5ff 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -49,7 +49,7 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::cout << "No. states (Explored): " << model->getNumberOfStates() << std::endl; std::cout << "No. transitions (Explored): " << model->getNumberOfTransitions() << std::endl; - if (model->getNumberOfStates() > 500 && model->isOfType(storm::models::ModelType::Ctmc)) { + if (model->isOfType(storm::models::ModelType::Ctmc)) { std::cout << "Bisimulation..." << std::endl; model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); model->printModelInformationToStream(std::cout); From b75b5f1928d8e39d83509a665367a1cd5b77039f Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 1 Mar 2016 17:31:52 +0100 Subject: [PATCH 189/246] No bisimulation for parametric case Former-commit-id: 7b30c7e5af3af1fd8a6d21edddf7fb4a07da36df --- src/storm-dyftee.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 13b43f5ff..97f583e28 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -15,7 +15,7 @@ * @param property PCTC formula capturing the property to check. */ template -void analyzeDFT(std::string filename, std::string property, bool symred = false) { +void analyzeDFT(std::string filename, std::string property, bool symred = false, bool bisimulation = true) { storm::settings::SettingsManager& manager = storm::settings::mutableManager(); manager.setFromString(""); @@ -49,7 +49,7 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::cout << "No. states (Explored): " << model->getNumberOfStates() << std::endl; std::cout << "No. transitions (Explored): " << model->getNumberOfTransitions() << std::endl; - if (model->isOfType(storm::models::ModelType::Ctmc)) { + if (bisimulation && model->isOfType(storm::models::ModelType::Ctmc)) { std::cout << "Bisimulation..." << std::endl; model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); model->printModelInformationToStream(std::cout); @@ -149,8 +149,8 @@ int main(int argc, char** argv) { std::cout << "Running " << (parametric ? "parametric " : "") << "DFT analysis on file " << filename << " with property " << pctlFormula << std::endl; if (parametric) { - analyzeDFT(filename, pctlFormula, symred); + analyzeDFT(filename, pctlFormula, symred, false); } else { - analyzeDFT(filename, pctlFormula, symred); + analyzeDFT(filename, pctlFormula, symred, true); } } From b8c7f063c1cdbe54b2364bb16877bdb334e15f22 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 2 Mar 2016 00:36:15 +0100 Subject: [PATCH 190/246] Maybe fix try to fix bisimulation instead of deactivating Former-commit-id: 772956d2ed7162d5dc4d5130d783ef18f38d24c6 --- src/storm-dyftee.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 97f583e28..13b43f5ff 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -15,7 +15,7 @@ * @param property PCTC formula capturing the property to check. */ template -void analyzeDFT(std::string filename, std::string property, bool symred = false, bool bisimulation = true) { +void analyzeDFT(std::string filename, std::string property, bool symred = false) { storm::settings::SettingsManager& manager = storm::settings::mutableManager(); manager.setFromString(""); @@ -49,7 +49,7 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false, std::cout << "No. states (Explored): " << model->getNumberOfStates() << std::endl; std::cout << "No. transitions (Explored): " << model->getNumberOfTransitions() << std::endl; - if (bisimulation && model->isOfType(storm::models::ModelType::Ctmc)) { + if (model->isOfType(storm::models::ModelType::Ctmc)) { std::cout << "Bisimulation..." << std::endl; model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); model->printModelInformationToStream(std::cout); @@ -149,8 +149,8 @@ int main(int argc, char** argv) { std::cout << "Running " << (parametric ? "parametric " : "") << "DFT analysis on file " << filename << " with property " << pctlFormula << std::endl; if (parametric) { - analyzeDFT(filename, pctlFormula, symred, false); + analyzeDFT(filename, pctlFormula, symred); } else { - analyzeDFT(filename, pctlFormula, symred, true); + analyzeDFT(filename, pctlFormula, symred); } } From 174058bb5e39dbbdfc70185930ee9795d7e86356 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 2 Mar 2016 11:53:41 +0100 Subject: [PATCH 191/246] Do not destroy the universe by dividing by 0 Former-commit-id: bd784f7adeca0f114e80da3870857bd14c24a8b6 --- src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index 3ffe7bbe8..18a56f5ab 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -663,8 +663,8 @@ namespace storm { // Initialize rewards. std::vector totalRewardVector; for (size_t i = 0; i < exitRateVector.size(); ++i) { - if (targetStates[i]) { - // Set reward for target states to 0. + if (targetStates[i] || storm::utility::isZero(exitRateVector[i])) { + // Set reward for target states or states without outgoing transitions to 0. totalRewardVector.push_back(storm::utility::zero()); } else { // Reward is (1 / exitRate). @@ -685,8 +685,8 @@ namespace storm { // Initialize rewards. std::vector totalRewardVector; for (size_t i = 0; i < exitRateVector.size(); ++i) { - if (targetStates[i]) { - // Set reward for target states to 0. + if (targetStates[i] || storm::utility::isZero(exitRateVector[i])) { + // Set reward for target states or states without outgoing transitions to 0. totalRewardVector.push_back(storm::utility::zero()); } else { // Reward is (1 / exitRate). From 1e79e5b2a43cc94415edbf5dbb2d006e310282a1 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 2 Mar 2016 15:24:29 +0100 Subject: [PATCH 192/246] Only print debug matrix for small state sizes Former-commit-id: c2e793d9b9f9fa4a3bedd8af52fe009706021b72 --- src/builder/ExplicitDFTModelBuilder.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 1c9c64684..3c5a39702 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -57,9 +57,13 @@ namespace storm { modelComponents.markovianStates = storm::storage::BitVector(stateSize, tmpMarkovianStates); // Build transition matrix modelComponents.transitionMatrix = transitionMatrixBuilder.build(stateSize, stateSize); - STORM_LOG_DEBUG("Transition matrix: " << std::endl << modelComponents.transitionMatrix); - STORM_LOG_DEBUG("Exit rates: " << modelComponents.exitRates); - STORM_LOG_DEBUG("Markovian states: " << modelComponents.markovianStates); + if (stateSize <= 15) { + STORM_LOG_TRACE("Transition matrix: " << std::endl << modelComponents.transitionMatrix); + } else { + STORM_LOG_TRACE("Transition matrix: too big to print"); + } + STORM_LOG_TRACE("Exit rates: " << modelComponents.exitRates); + STORM_LOG_TRACE("Markovian states: " << modelComponents.markovianStates); // Build state labeling modelComponents.stateLabeling = storm::models::sparse::StateLabeling(mStates.size() + (mergeFailedStates ? 1 : 0)); From e322c568207240e1327963c7c42d03b0d232ee17 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 2 Mar 2016 15:30:00 +0100 Subject: [PATCH 193/246] findModularisationRewrite Former-commit-id: ba948b7720f6742a8ebe2f101f17c422b30b24ab --- src/storage/dft/DFT.cpp | 35 +++++++++++++++++++++++++++++++++++ src/storage/dft/DFT.h | 2 ++ src/storm-dyftee.cpp | 8 ++++++++ 3 files changed, 45 insertions(+) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index bf68a095c..890e2de25 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -436,6 +436,41 @@ namespace storm { } return DFTIndependentSymmetries(res); } + + template + std::vector DFT::findModularisationRewrite() const { + for(auto const& e : mElements) { + if(e->isGate() && (e->type() == DFTElementType::AND || e->type() == DFTElementType::OR) ) { + // suitable parent gate! - Lets check the independent submodules of the children + auto const& children = std::static_pointer_cast>(e)->children(); + for(auto const& child : children) { + //std::cout << "check idea for: " << child->id() << std::endl;; + auto ISD = std::static_pointer_cast>(child)->independentSubDft(true); + // In the ISD, check for other children: + //std::cout << "** subdft = "; + for(auto const& isdelemid : ISD) { + std::cout << isdelemid << " "; + } + std::cout << std::endl; + + std::vector rewrite = {e->id(), child->id()}; + for(size_t isdElemId : ISD) { + if(isdElemId == child->id()) continue; + if(std::find_if(children.begin(), children.end(), [&isdElemId](std::shared_ptr> const& e) { return e->id() == isdElemId; } ) != children.end()) { + //std::cout << "** found child in subdft: " << isdElemId << std::endl; + rewrite.push_back(isdElemId); + } + } + if(rewrite.size() > 2) { + return rewrite; + } + + } + } + } + return {}; + } + template std::pair, std::vector> DFT::getSortedParentAndOutDepIds(size_t index) const { diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 32e807197..75092e479 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -236,6 +236,8 @@ namespace storm { DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; std::vector immediateFailureCauses(size_t index) const; + + std::vector findModularisationRewrite() const; private: std::pair, std::vector> getSortedParentAndOutDepIds(size_t index) const; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 13b43f5ff..c5997ddd3 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -29,6 +29,14 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); std::cout << "Parsed formula." << std::endl; + auto modIdea = dft.findModularisationRewrite(); + std::cout << "Modularisation idea: " << std::endl; + + for( auto const& i : modIdea ) { + std::cout << i << ", "; + } + std::cout << std::endl; + std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) { From a6f8ba37168df42233eb5f33245514cd8d214165 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 2 Mar 2016 15:30:22 +0100 Subject: [PATCH 194/246] seq examples Former-commit-id: 42c0f279b9c8dee9e8c03f342e42a58cf738ff5b --- examples/dft/seq1.dft | 2 +- examples/dft/seq2.dft | 6 ++++++ examples/dft/seq3.dft | 6 ++++++ examples/dft/seq3.txt | 6 ++++++ examples/dft/seq4.dft | 6 ++++++ examples/dft/seq5.dft | 7 +++++++ examples/dft/seq6.dft | 8 ++++++++ 7 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 examples/dft/seq2.dft create mode 100644 examples/dft/seq3.dft create mode 100644 examples/dft/seq3.txt create mode 100644 examples/dft/seq4.dft create mode 100644 examples/dft/seq5.dft create mode 100644 examples/dft/seq6.dft diff --git a/examples/dft/seq1.dft b/examples/dft/seq1.dft index 8f5459fd2..6fd99bc3b 100644 --- a/examples/dft/seq1.dft +++ b/examples/dft/seq1.dft @@ -1,5 +1,5 @@ toplevel "A"; "A" and "B" "C"; -"X" seq "B" "C"; +"X" seq "B" "C" "B" lambda=0.5 dorm=0.3; "C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq2.dft b/examples/dft/seq2.dft new file mode 100644 index 000000000..408d4c26d --- /dev/null +++ b/examples/dft/seq2.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "B" "C" "D"; +"X" seq "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq3.dft b/examples/dft/seq3.dft new file mode 100644 index 000000000..b22b9e8b6 --- /dev/null +++ b/examples/dft/seq3.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "C" "D"; +"X" seq "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq3.txt b/examples/dft/seq3.txt new file mode 100644 index 000000000..b22b9e8b6 --- /dev/null +++ b/examples/dft/seq3.txt @@ -0,0 +1,6 @@ +toplevel "A"; +"A" and "C" "D"; +"X" seq "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq4.dft b/examples/dft/seq4.dft new file mode 100644 index 000000000..260a88266 --- /dev/null +++ b/examples/dft/seq4.dft @@ -0,0 +1,6 @@ +toplevel "A"; +"A" or "C" "D"; +"X" seq "B" "C" "D"; +"B" lambda=0.5 dorm=0.3; +"C" lambda=0.5 dorm=0.3; +"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq5.dft b/examples/dft/seq5.dft new file mode 100644 index 000000000..60bf149af --- /dev/null +++ b/examples/dft/seq5.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" and "T1" "B3"; +"T1" or "B1" "B2"; +"X" seq "B1" "B2" "B3"; +"B1" lambda=0.5 dorm=0.3; +"B2" lambda=0.5 dorm=0.3; +"B3" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq6.dft b/examples/dft/seq6.dft new file mode 100644 index 000000000..8453cb411 --- /dev/null +++ b/examples/dft/seq6.dft @@ -0,0 +1,8 @@ +toplevel "A"; +"A" and "T1" "T2"; +"T1" pand "B1" "B2"; +"T2" pand "B3" "B4; +"B1" lambda=0.7 dorm=0.3; +"B2" lambda=0.5 dorm=0.3; +"B3" lambda=0.5 dorm=0.3; +"B4" lambda=0.7 dorm=0.3; From 52573c90ca6886dfeef45e84be3ef695d9bef3e9 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 2 Mar 2016 16:10:47 +0100 Subject: [PATCH 195/246] Copy DFT Former-commit-id: 97eb17a5d9c34d8212f8431de52405442248f537 --- src/storage/dft/DFT.cpp | 90 ++++++++++++++++++++++++++++++- src/storage/dft/DFT.h | 9 ++++ src/storage/dft/DFTBuilder.cpp | 85 ++++++++++++++++++++++++++++- src/storage/dft/DFTBuilder.h | 25 +++++++-- src/storage/dft/elements/DFTVot.h | 4 ++ src/storm-dyftee.cpp | 3 ++ 6 files changed, 210 insertions(+), 6 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index bf68a095c..a4a15947c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -2,6 +2,7 @@ #include #include "DFT.h" +#include "DFTBuilder.h" #include "src/exceptions/NotSupportedException.h" #include "DFTIsomorphism.h" @@ -228,7 +229,87 @@ namespace storm { } return stateIndex; } - + + template + DFT DFT::optimize() const { + std::vector> rewriteIds = findModulesRewrite(); + if (rewriteIds.empty()) { + // No rewrite needed + return *this; + } + + DFTBuilder builder; + + // Accumulate elements which must be rewritten + std::set rewriteSet; + for (std::vector rewrites : rewriteIds) { + rewriteSet.insert(rewrites.front()); + } + // Copy all other elements which do not change + for (auto elem : mElements) { + if (rewriteSet.count(elem->id()) == 0) { + builder.copyElement(elem); + } + } + + // Add rewritten elements + for (std::vector rewrites : rewriteIds) { + assert(rewrites.size() > 1); + assert(mElements[rewrites[1]]->hasParents()); + assert(mElements[rewrites[1]]->parents().front()->isGate()); + DFTGatePointer originalParent = std::static_pointer_cast>(mElements[rewrites[1]]->parents().front()); + std::string newParentName = builder.getUniqueName(originalParent->name()); + + // Accumulate children names + std::vector childrenNames; + for (size_t i = 1; i < rewrites.size(); ++i) { + assert(mElements[rewrites[i]]->parents().front()->id() == originalParent->id()); // Children have the same father + childrenNames.push_back(mElements[rewrites[i]]->name()); + } + + // Add element inbetween parent and children + switch (originalParent->type()) { + case DFTElementType::AND: + builder.addAndElement(newParentName, childrenNames); + break; + case DFTElementType::OR: + builder.addOrElement(newParentName, childrenNames); + break; + case DFTElementType::BE: + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + case DFTElementType::VOT: + case DFTElementType::PAND: + case DFTElementType::SPARE: + case DFTElementType::POR: + case DFTElementType::PDEP: + case DFTElementType::SEQ: + case DFTElementType::MUTEX: + // Other elements are not supported + assert(false); + break; + default: + assert(false); + } + + // Add parent with the new child newParent and all its remaining children + childrenNames.clear(); + childrenNames.push_back(newParentName); + for (auto const& child : originalParent->children()) { + if (std::find(rewrites.begin()+1, rewrites.end(), child->id()) == rewrites.end()) { + // Child was not rewritten and must be kept + childrenNames.push_back(child->name()); + } + } + builder.copyGate(originalParent, childrenNames); + } + + builder.setTopLevel(mElements[mTopLevelIndex]->name()); + // TODO use reference? + DFT newDft = builder.build(); + return newDft.optimize(); + } + template std::string DFT::getElementsString() const { std::stringstream stream; @@ -449,6 +530,13 @@ namespace storm { return res; } + template + std::vector> DFT::findModulesRewrite() const { + std::vector> modulesRewrite; + // TODO write + return modulesRewrite; + } + // Explicitly instantiate the class. template class DFT; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 32e807197..557914d7e 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -34,6 +34,8 @@ namespace storm { // Forward declarations template class DFTColouring; + + template class DFTBuilder; @@ -72,6 +74,10 @@ namespace storm { size_t generateStateInfo(DFTStateGenerationInfo& generationInfo, size_t id, storm::storage::BitVector& visited, size_t stateIndex) const; size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, storm::storage::BitVector& visited, size_t stateIndex) const; + + DFT optimize() const; + + void copyElements(std::vector elements, DFTBuilder builder) const; size_t stateVectorSize() const { return mStateVectorSize; @@ -236,6 +242,9 @@ namespace storm { DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; std::vector immediateFailureCauses(size_t index) const; + + std::vector> findModulesRewrite() const; + private: std::pair, std::vector> getSortedParentAndOutDepIds(size_t index) const; diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 08d85d879..f3d83e4c0 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -70,7 +70,8 @@ namespace storm { for(DFTElementPointer e : elems) { e->setId(id++); } - return DFT(elems, mElements[topLevelIdentifier]); + assert(!mTopLevelIdentifier.empty()); + return DFT(elems, mElements[mTopLevelIdentifier]); } template @@ -180,7 +181,6 @@ namespace storm { } } - // TODO Matthias: use typedefs template std::vector>> DFTBuilder::topoSort() { std::map> visited; @@ -195,6 +195,87 @@ namespace storm { //std::reverse(L.begin(), L.end()); return L; } + + template + std::string DFTBuilder::getUniqueName(std::string name) { + return name + "_" + std::to_string(++mUniqueOffset); + } + + template + void DFTBuilder::copyElement(DFTElementPointer element) { + std::vector children; + switch (element->type()) { + case DFTElementType::AND: + case DFTElementType::OR: + case DFTElementType::PAND: + case DFTElementType::POR: + case DFTElementType::SPARE: + case DFTElementType::VOT: + { + for (DFTElementPointer const& elem : std::static_pointer_cast>(element)->children()) { + children.push_back(elem->name()); + } + copyGate(std::static_pointer_cast>(element), children); + break; + } + case DFTElementType::BE: + { + std::shared_ptr> be = std::static_pointer_cast>(element); + ValueType dormancyFactor = storm::utility::zero(); + if (!storm::utility::isZero(be->passiveFailureRate())) { + dormancyFactor = be->activeFailureRate() / be->passiveFailureRate(); + } + addBasicElement(be->name(), be->activeFailureRate(), dormancyFactor); + break; + } + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + // TODO + assert(false); + break; + case DFTElementType::PDEP: + { + DFTDependencyPointer dependency = std::static_pointer_cast>(element); + children.push_back(dependency->triggerEvent()->name()); + children.push_back(dependency->dependentEvent()->name()); + addDepElement(element->name(), children, dependency->probability()); + break; + } + case DFTElementType::SEQ: + case DFTElementType::MUTEX: + { + for (DFTElementPointer const& elem : std::static_pointer_cast>(element)->children()) { + children.push_back(elem->name()); + } + addRestriction(element->name(), children, element->type()); + break; + } + default: + assert(false); + break; + } + } + + template + void DFTBuilder::copyGate(DFTGatePointer gate, std::vector const& children) { + switch (gate->type()) { + case DFTElementType::AND: + case DFTElementType::OR: + case DFTElementType::PAND: + case DFTElementType::POR: + case DFTElementType::SPARE: + addStandardGate(gate->name(), children, gate->type()); + break; + case DFTElementType::VOT: + addVotElement(gate->name(), std::static_pointer_cast>(gate)->threshold(), children); + break; + default: + assert(false); + break; + } + } + + // Explicitly instantiate the class. template class DFTBuilder; diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 8ef0d6cf1..6c6fcc143 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -26,7 +26,8 @@ namespace storm { private: std::size_t mNextId = 0; - std::string topLevelIdentifier; + std::size_t mUniqueOffset = 0; + std::string mTopLevelIdentifier; std::unordered_map mElements; std::unordered_map> mChildNames; std::unordered_map> mRestrictionChildNames; @@ -140,18 +141,36 @@ namespace storm { } bool setTopLevel(std::string const& tle) { - topLevelIdentifier = tle; + mTopLevelIdentifier = tle; return mElements.count(tle) > 0; } + std::string getUniqueName(std::string name); + DFT build(); + + /** + * Copy element and insert it again in the builder. + * + * @param element Element to copy. + */ + void copyElement(DFTElementPointer element); + + /** + * Copy gate with given children and insert it again in the builder. The current children of the element + * are discarded. + * + * @param gate Gate to copy. + * @param children New children of copied element. + */ + void copyGate(DFTGatePointer gate, std::vector const& children); - private: unsigned computeRank(DFTElementPointer const& elem); bool addStandardGate(std::string const& name, std::vector const& children, DFTElementType tp); + bool addRestriction(std::string const& name, std::vector const& children, DFTElementType tp); enum class topoSortColour {WHITE, BLACK, GREY}; diff --git a/src/storage/dft/elements/DFTVot.h b/src/storage/dft/elements/DFTVot.h index 0233d979d..776055848 100644 --- a/src/storage/dft/elements/DFTVot.h +++ b/src/storage/dft/elements/DFTVot.h @@ -51,6 +51,10 @@ namespace storm { } } } + + unsigned threshold() const { + return mThreshold; + } virtual DFTElementType type() const override { return DFTElementType::VOT; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 13b43f5ff..6240bf374 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -29,6 +29,9 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); std::cout << "Parsed formula." << std::endl; + + dft = dft.optimize(); + std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) { From f12e02f8ff0c2543a4207cef4ec4f91ef2fee086 Mon Sep 17 00:00:00 2001 From: sjunges Date: Wed, 2 Mar 2016 17:14:50 +0100 Subject: [PATCH 196/246] dont modularise modules Former-commit-id: 90f95b2065c1c0d25eea32c3b27b95f3611a7fd4 --- src/storage/dft/DFT.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 890e2de25..4d6e88d0f 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -461,7 +461,7 @@ namespace storm { rewrite.push_back(isdElemId); } } - if(rewrite.size() > 2) { + if(rewrite.size() > 2 && rewrite.size() < e->children().size() - 1) { return rewrite; } From 28a49659dbbf5cb81cdc3c9d8acd0b3e6ba25261 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 2 Mar 2016 17:36:56 +0100 Subject: [PATCH 197/246] Small fixes Former-commit-id: ee8ef605c370ba7219335e0cc48c5c82861bf471 --- src/storage/dft/DFT.cpp | 2 +- src/storage/dft/DFTBuilder.cpp | 3 +++ src/storage/dft/DFTBuilder.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 2a0bfa244..242995834 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -551,7 +551,7 @@ namespace storm { rewrite.push_back(isdElemId); } } - if(rewrite.size() > 2 && rewrite.size() < e->children().size() - 1) { + if(rewrite.size() > 2 && rewrite.size() < children.size() - 1) { return rewrite; } diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index f3d83e4c0..ea273e234 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -12,6 +12,9 @@ namespace storm { namespace storage { + + template + std::size_t DFTBuilder::mUniqueOffset = 0; template DFT DFTBuilder::build() { diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 6c6fcc143..d630c24fb 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -26,7 +26,7 @@ namespace storm { private: std::size_t mNextId = 0; - std::size_t mUniqueOffset = 0; + static std::size_t mUniqueOffset; std::string mTopLevelIdentifier; std::unordered_map mElements; std::unordered_map> mChildNames; From 3f41aa55f802c14b454497975d5a35817c4a0052 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 3 Mar 2016 14:57:51 +0100 Subject: [PATCH 198/246] Cleaned up debug output Former-commit-id: daabe84596916b55b1cc0716a2ba736c726336eb --- .../SparseDtmcEliminationModelChecker.cpp | 2 + src/storage/dft/DFT.cpp | 23 ++++------- src/storage/dft/DFTIsomorphism.h | 4 +- src/storage/dft/SymmetricUnits.h | 8 ++-- src/storm-dyftee.cpp | 40 ++++++++++++------- src/utility/vector.h | 20 ++++++++++ 6 files changed, 60 insertions(+), 37 deletions(-) diff --git a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp index ecf795182..db972f49a 100644 --- a/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp +++ b/src/modelchecker/reachability/SparseDtmcEliminationModelChecker.cpp @@ -1233,6 +1233,8 @@ namespace storm { template class StatePriorityQueue; template class SparseDtmcEliminationModelChecker>; + template uint_fast64_t estimateComplexity(double const& value); + #ifdef STORM_HAVE_CARL template class StatePriorityQueue; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 242995834..c40fadceb 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -7,6 +7,7 @@ #include "DFTIsomorphism.h" #include "utility/iota_n.h" +#include "utility/vector.h" namespace storm { namespace storage { @@ -233,12 +234,8 @@ namespace storm { template DFT DFT::optimize() const { std::vector modIdea = findModularisationRewrite(); - std::cout << "Modularisation idea: " << std::endl; - - for( auto const& i : modIdea ) { - std::cout << i << ", "; - } - + STORM_LOG_DEBUG("Modularisation idea: " << storm::utility::vector::toString(modIdea)); + if (modIdea.empty()) { // No rewrite needed return *this; @@ -316,6 +313,7 @@ namespace storm { builder.setTopLevel(mElements[mTopLevelIndex]->name()); // TODO use reference? DFT newDft = builder.build(); + STORM_LOG_TRACE(newDft.getElementsString()); return newDft.optimize(); } @@ -487,20 +485,20 @@ namespace storm { std::sort(sortedParent2Ids.begin(), sortedParent2Ids.end()); if(influencedElem1Ids == getSortedParentAndOutDepIds(*it2)) { - std::cout << "Considering ids " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + STORM_LOG_TRACE("Considering ids " << *it1 << ", " << *it2 << " for isomorphism."); bool isSymmetry = false; std::vector isubdft1 = getGate(*it1)->independentSubDft(false); std::vector isubdft2 = getGate(*it2)->independentSubDft(false); if(isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) { continue; } - std::cout << "Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism." << std::endl; + STORM_LOG_TRACE("Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism."); auto LHS = colouring.colourSubdft(isubdft1); auto RHS = colouring.colourSubdft(isubdft2); auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); isSymmetry = IsoCheck.findIsomorphism(); if(isSymmetry) { - std::cout << "subdfts are symmetric" << std::endl; + STORM_LOG_TRACE("Subdfts are symmetric"); foundEqClassFor.insert(*it2); if(symClass.empty()) { for(auto const& i : isubdft1) { @@ -534,20 +532,13 @@ namespace storm { // suitable parent gate! - Lets check the independent submodules of the children auto const& children = std::static_pointer_cast>(e)->children(); for(auto const& child : children) { - //std::cout << "check idea for: " << child->id() << std::endl;; auto ISD = std::static_pointer_cast>(child)->independentSubDft(true); // In the ISD, check for other children: - //std::cout << "** subdft = "; - for(auto const& isdelemid : ISD) { - std::cout << isdelemid << " "; - } - std::cout << std::endl; std::vector rewrite = {e->id(), child->id()}; for(size_t isdElemId : ISD) { if(isdElemId == child->id()) continue; if(std::find_if(children.begin(), children.end(), [&isdElemId](std::shared_ptr> const& e) { return e->id() == isdElemId; } ) != children.end()) { - //std::cout << "** found child in subdft: " << isdElemId << std::endl; rewrite.push_back(isdElemId); } } diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index 542fa954a..b1f845b9f 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -249,7 +249,7 @@ namespace storage { } void colourize(std::shared_ptr> const& gate) { - std::cout << "Colour " << gate->id() << ": " << gate->type() << " " << gate->nrChildren() << " " << gate->rank() << "." << std::endl; + STORM_LOG_TRACE("Colour " << gate->id() << ": " << gate->type() << " " << gate->nrChildren() << " " << gate->rank() << "."); gateColour[gate->id()] = gateColourizer(gate->type(), gate->nrChildren(), gate->nrParents(), 0, gate->rank()); } @@ -336,7 +336,7 @@ namespace storage { initializePermutationsAndTreatTrivialGroups(bleft.gateCandidates, bright.gateCandidates, currentPermutations.gateCandidates); initializePermutationsAndTreatTrivialGroups(bleft.pdepCandidates, bright.pdepCandidates, currentPermutations.pdepCandidates); initializePermutationsAndTreatTrivialGroups(bleft.restrictionCandidates, bright.restrictionCandidates, currentPermutations.restrictionCandidates); - std::cout << bijection.size() << " vs. " << bleft.size() << " vs. " << bright.size() << std::endl; + STORM_LOG_TRACE(bijection.size() << " vs. " << bleft.size() << " vs. " << bright.size()); assert(bijection.size() == bleft.size()); } diff --git a/src/storage/dft/SymmetricUnits.h b/src/storage/dft/SymmetricUnits.h index 6521ee8d2..58a70e492 100644 --- a/src/storage/dft/SymmetricUnits.h +++ b/src/storage/dft/SymmetricUnits.h @@ -12,16 +12,14 @@ namespace storm { inline std::ostream& operator<<(std::ostream& os, DFTIndependentSymmetries const& s) { for(auto const& cl : s.groups) { - std::cout << "SYM GROUP FOR " << cl.first << std::endl; + os << "Symmetry group for " << cl.first << std::endl; for(auto const& eqClass : cl.second) { for(auto const& i : eqClass) { - std::cout << i << " "; + os << i << " "; } - std::cout << std::endl; + os << std::endl; } } - - return os; } } diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 6240bf374..49f97b76b 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -20,53 +20,65 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) manager.setFromString(""); // Parsing DFT - std::cout << "Parsing DFT file..." << std::endl; + std::chrono::high_resolution_clock::time_point parsingStart = std::chrono::high_resolution_clock::now(); storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(filename); - std::cout << "Built data structure" << std::endl; - std::cout << "Parse formula..." << std::endl; std::vector> parsedFormulas = storm::parseFormulasForExplicit(property); std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); - std::cout << "Parsed formula." << std::endl; + // Optimize DFT dft = dft.optimize(); - std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) { auto colouring = dft.colourDFT(); symmetries = dft.findSymmetries(colouring); - std::cout << "Symmetries: " << symmetries << std::endl; + std::cout << "Found " << symmetries.groups.size() << " symmetries." << std::endl; + STORM_LOG_TRACE("Symmetries: " << std::endl << symmetries); } - + std::chrono::high_resolution_clock::time_point parsingEnd = std::chrono::high_resolution_clock::now(); + // Building Markov Automaton std::cout << "Building Model..." << std::endl; storm::builder::ExplicitDFTModelBuilder builder(dft, symmetries); typename storm::builder::ExplicitDFTModelBuilder::LabelOptions labeloptions; // TODO initialize this with the formula std::shared_ptr> model = builder.buildModel(labeloptions); - std::cout << "Built Model" << std::endl; - - - model->printModelInformationToStream(std::cout); + //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(); + // Bisimulation if (model->isOfType(storm::models::ModelType::Ctmc)) { std::cout << "Bisimulation..." << std::endl; model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, storm::storage::BisimulationType::Weak)->template as>(); - model->printModelInformationToStream(std::cout); + //model->printModelInformationToStream(std::cout); } - std::cout << "No. states (Bisimulation): " << model->getNumberOfStates() << std::endl; std::cout << "No. transitions (Bisimulation): " << model->getNumberOfTransitions() << std::endl; + std::chrono::high_resolution_clock::time_point bisimulationEnd = std::chrono::high_resolution_clock::now(); // Model checking std::cout << "Model checking..." << std::endl; std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); assert(result); - std::cout << "Result: "; result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); + + // Times + std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now(); + std::chrono::duration parsingTime = parsingEnd - parsingStart; + std::chrono::duration explorationTime = explorationEnd - parsingEnd; + std::chrono::duration bisimulationTime = bisimulationEnd - explorationEnd; + std::chrono::duration modelCheckingTime = modelCheckingEnd - bisimulationEnd; + std::chrono::duration totalTime = modelCheckingEnd - parsingStart; + std::cout << "Times:" << std::endl; + std::cout << "Parsing:\t" << parsingTime.count() << std::endl; + std::cout << "Exploration:\t" << explorationTime.count() << std::endl; + std::cout << "Bisimulaton:\t" << bisimulationTime.count() << std::endl; + std::cout << "Modelchecking:\t" << modelCheckingTime.count() << std::endl; + std::cout << "Total:\t\t" << totalTime.count() << std::endl; + std::cout << "Result: "; std::cout << *result << std::endl; } diff --git a/src/utility/vector.h b/src/utility/vector.h index aa526cf54..b5480de9b 100644 --- a/src/utility/vector.h +++ b/src/utility/vector.h @@ -705,6 +705,26 @@ namespace storm { assert(result.size() == filter.getNumberOfSetBits()); return result; } + + /*! + * Output vector as string. + * + * @param vector Vector to output. + * @return String containing the representation of the vector. + */ + template + std::string toString(std::vector vector) { + std::stringstream stream; + stream << "vector (" << vector.size() << ") [ "; + for (uint_fast64_t i = 0; i < vector.size() - 1; ++i) { + stream << vector[i] << ", "; + } + if (!vector.empty()) { + stream << vector.back(); + } + stream << " ]"; + return stream.str(); + } } // namespace vector } // namespace utility } // namespace storm From 796d7652df67dfcd38ca533371f36c65c00c0268 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 3 Mar 2016 18:49:00 +0100 Subject: [PATCH 199/246] Fixed problem with bounds in MA model checker Former-commit-id: c40c4e479513338c7739d15d99aa75343761cfa7 --- .../csl/SparseMarkovAutomatonCslModelChecker.cpp | 12 ++++++++++-- .../csl/helper/SparseMarkovAutomatonCslHelper.cpp | 6 +----- .../csl/helper/SparseMarkovAutomatonCslHelper.h | 2 +- src/utility/vector.h | 6 +++--- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp index da8d72c47..05e2cf823 100644 --- a/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseMarkovAutomatonCslModelChecker.cpp @@ -45,8 +45,16 @@ namespace storm { STORM_LOG_THROW(this->getModel().isClosed(), storm::exceptions::InvalidPropertyException, "Unable to compute time-bounded reachability probabilities in non-closed Markov automaton."); std::unique_ptr rightResultPointer = this->check(pathFormula.getRightSubformula()); ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult(); - - std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), rightResult.getTruthValuesVector(), pathFormula.getIntervalBounds(), *minMaxLinearEquationSolverFactory); + double lowerBound = 0; + double upperBound = 0; + if (!pathFormula.hasDiscreteTimeBound()) { + std::pair const& intervalBounds = pathFormula.getIntervalBounds(); + lowerBound = intervalBounds.first; + upperBound = intervalBounds.second; + } else { + upperBound = pathFormula.getDiscreteTimeBound(); + } + std::vector result = storm::modelchecker::helper::SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(checkTask.getOptimizationDirection(), this->getModel().getTransitionMatrix(), this->getModel().getExitRates(), this->getModel().getMarkovianStates(), rightResult.getTruthValuesVector(), lowerBound, upperBound, *minMaxLinearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(result))); } diff --git a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp index 95007a9e6..00a4e57c0 100644 --- a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp @@ -119,13 +119,9 @@ namespace storm { template - std::vector SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::pair const& boundsPair, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + std::vector SparseMarkovAutomatonCslHelper::computeBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, double lowerBound, double upperBound, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { uint_fast64_t numberOfStates = transitionMatrix.getRowGroupCount(); - // 'Unpack' the bounds to make them more easily accessible. - double lowerBound = boundsPair.first; - double upperBound = boundsPair.second; - // (1) Compute the accuracy we need to achieve the required error bound. ValueType maxExitRate = 0; for (auto value : exitRateVector) { diff --git a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.h b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.h index 5b24fe569..764eb542c 100644 --- a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.h +++ b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.h @@ -14,7 +14,7 @@ namespace storm { template class SparseMarkovAutomatonCslHelper { public: - static std::vector computeBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, std::pair const& boundsPair, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeBoundedUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, std::vector const& exitRateVector, storm::storage::BitVector const& markovianStates, storm::storage::BitVector const& psiStates, double lowerBound, double upperBound, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); static std::vector computeUntilProbabilities(OptimizationDirection dir, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); diff --git a/src/utility/vector.h b/src/utility/vector.h index b5480de9b..d9ad13e64 100644 --- a/src/utility/vector.h +++ b/src/utility/vector.h @@ -716,10 +716,10 @@ namespace storm { std::string toString(std::vector vector) { std::stringstream stream; stream << "vector (" << vector.size() << ") [ "; - for (uint_fast64_t i = 0; i < vector.size() - 1; ++i) { - stream << vector[i] << ", "; - } if (!vector.empty()) { + for (uint_fast64_t i = 0; i < vector.size() - 1; ++i) { + stream << vector[i] << ", "; + } stream << vector.back(); } stream << " ]"; From ccec8b8f7a270bd2437e46a33d200f2473940372 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 7 Mar 2016 13:45:53 +0100 Subject: [PATCH 200/246] Renaming Former-commit-id: f10a647dc53c2f598816e50a22a5fee736c35d8d --- src/storm-dyftee.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 49f97b76b..1f170072b 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -19,15 +19,15 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) storm::settings::SettingsManager& manager = storm::settings::mutableManager(); manager.setFromString(""); - // Parsing DFT - std::chrono::high_resolution_clock::time_point parsingStart = std::chrono::high_resolution_clock::now(); + // Building DFT + std::chrono::high_resolution_clock::time_point buildingStart = std::chrono::high_resolution_clock::now(); storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(filename); std::vector> parsedFormulas = storm::parseFormulasForExplicit(property); std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); - // Optimize DFT + // Optimizing DFT dft = dft.optimize(); std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); @@ -37,7 +37,7 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::cout << "Found " << symmetries.groups.size() << " symmetries." << std::endl; STORM_LOG_TRACE("Symmetries: " << std::endl << symmetries); } - std::chrono::high_resolution_clock::time_point parsingEnd = std::chrono::high_resolution_clock::now(); + std::chrono::high_resolution_clock::time_point buildingEnd = std::chrono::high_resolution_clock::now(); // Building Markov Automaton std::cout << "Building Model..." << std::endl; @@ -67,15 +67,15 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) // Times std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now(); - std::chrono::duration parsingTime = parsingEnd - parsingStart; - std::chrono::duration explorationTime = explorationEnd - parsingEnd; + std::chrono::duration buildingTime = buildingEnd - buildingStart; + std::chrono::duration explorationTime = explorationEnd - buildingEnd; std::chrono::duration bisimulationTime = bisimulationEnd - explorationEnd; std::chrono::duration modelCheckingTime = modelCheckingEnd - bisimulationEnd; - std::chrono::duration totalTime = modelCheckingEnd - parsingStart; + std::chrono::duration totalTime = modelCheckingEnd - buildingStart; std::cout << "Times:" << std::endl; - std::cout << "Parsing:\t" << parsingTime.count() << std::endl; + std::cout << "Building:\t" << buildingTime.count() << std::endl; std::cout << "Exploration:\t" << explorationTime.count() << std::endl; - std::cout << "Bisimulaton:\t" << bisimulationTime.count() << std::endl; + std::cout << "Bisimulation:\t" << bisimulationTime.count() << std::endl; std::cout << "Modelchecking:\t" << modelCheckingTime.count() << std::endl; std::cout << "Total:\t\t" << totalTime.count() << std::endl; std::cout << "Result: "; From 83b6496fd22b178278e1cc727b66fbe8d658bd9f Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 7 Mar 2016 17:25:20 +0100 Subject: [PATCH 201/246] Fixed bugs in BitVector Former-commit-id: 8f1d5cbfac29ea2467d42c544d6ee883ae833981 --- src/storage/BitVector.cpp | 51 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index 572efea20..6bfd4ea5e 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -710,25 +710,26 @@ namespace storm { // Get remaining bits getValue = (bucketVector[bucketIndex] >> (64-remainingBits)) << (64-remainingBits); assert(remainingBits < 64); - if (remainingBits <= offset || offset == 0) { - // Write completely - assert(insertBucket == result.bucketCount()-1); - writeValue = getValue; - result.bucketVector[insertBucket] = writeValue; - } else { - // Remaining bits do not fit in value -> need new value - assert(insertBucket == result.bucketCount() - 2); - writeValue |= (getValue >> (64-offset)); - result.bucketVector[insertBucket] = writeValue; - // Write last bits - writeValue = (getValue << (remainingBits-offset)); + // Write bucket + assert(insertBucket <= result.bucketCount()-1); + writeValue |= getValue >> (64-offset); + result.bucketVector[insertBucket] = writeValue; + if (remainingBits >= offset) { + // Write last bits in new value + writeValue = (getValue << offset); result.bucketVector[++insertBucket] = writeValue; } #ifdef ASSERT_BITVECTOR // Check correctness of getter for (uint_fast64_t i = 0; i < length; ++i) { - STORM_LOG_ASSERT(result.get(i) == get(start + i), "Getting of bits not correct for index " << i); + if (result.get(i) != get(start + i)) { + std::cout << "Getting of bits not correct for index " << i << std::endl; + std::cout << "Getting from " << start << " with length " << length << std::endl; + printBits(std::cout); + result.printBits(std::cout); + assert(false); + } } #endif return result; @@ -775,26 +776,36 @@ namespace storm { // Get remaining bits getValue = other.bucketVector[getBucket] << (64-offset); assert(remainingBits < 64); - if (remainingBits <= offset || offset == 0) { + if (remainingBits <= offset) { // Write completely assert(getBucket == other.bucketCount()-1); - getValue = (getValue >> (64-offset-remainingBits)) << (64-offset-remainingBits); - writeValue = (bucketVector[bucketIndex] << (offset+remainingBits)) >> (offset+remainingBits); + writeValue = (bucketVector[bucketIndex] << (offset+remainingBits)) >> remainingBits; writeValue |= getValue; bucketVector[bucketIndex] = writeValue; } else { // Remaining bits do not come from one bucket -> consider two buckets assert(getBucket == other.bucketCount() - 2); - getValue |= other.bucketVector[++getBucket] >> offset; - writeValue = (bucketVector[bucketIndex] << (offset+remainingBits)) >> (offset+remainingBits); - writeValue |= getValue; + writeValue = getValue; + getValue = other.bucketVector[++getBucket]; + writeValue |= getValue >> offset; + bucketVector[bucketIndex] = writeValue; + remainingBits = remainingBits + offset - 64; + // Write last bucket + writeValue = (bucketVector[++bucketIndex] << remainingBits) >> remainingBits; + writeValue |= getValue << (64-offset); bucketVector[bucketIndex] = writeValue; } #ifdef ASSERT_BITVECTOR // Check correctness of setter for (uint_fast64_t i = 0; i < other.bitCount; ++i) { - STORM_LOG_ASSERT(other.get(i) == get(start + i), "Setting of bits not correct for index " << i); + if (other.get(i) != get(start + i)) { + std::cout << "Setting of bits not correct for index " << i << std::endl; + std::cout << "Setting from " << start << " with length " << other.bitCount << std::endl; + printBits(std::cout); + other.printBits(std::cout); + assert(false); + } } #endif } From 811d04c2a705ea9289ed048caa68ce092da4c516 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 8 Mar 2016 13:29:31 +0100 Subject: [PATCH 202/246] Fixed bug in BitVector Former-commit-id: ae967348791271d2fdac5b88dd58d9212e1918a7 --- src/storage/BitVector.cpp | 82 ++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index 6bfd4ea5e..9ad566258 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -673,6 +673,9 @@ namespace storm { storm::storage::BitVector BitVector::getAsBitVector(uint_fast64_t start, uint_fast64_t length) const { assert(start + length <= bitCount); +#ifdef ASSERT_BITVECTOR + BitVector original(*this); +#endif storm::storage::BitVector result(length, false); uint_fast64_t offset = start % 64; @@ -711,13 +714,18 @@ namespace storm { getValue = (bucketVector[bucketIndex] >> (64-remainingBits)) << (64-remainingBits); assert(remainingBits < 64); // Write bucket - assert(insertBucket <= result.bucketCount()-1); - writeValue |= getValue >> (64-offset); - result.bucketVector[insertBucket] = writeValue; - if (remainingBits >= offset) { - // Write last bits in new value - writeValue = (getValue << offset); - result.bucketVector[++insertBucket] = writeValue; + assert(insertBucket < result.bucketCount()); + if (offset == 0) { + result.bucketVector[insertBucket]= getValue; + } else { + writeValue |= getValue >> (64-offset); + result.bucketVector[insertBucket] = writeValue; + if (remainingBits > offset) { + // Write last bits in new value + writeValue = (getValue << offset); + assert(insertBucket+1 < result.bucketCount()); + result.bucketVector[++insertBucket] = writeValue; + } } #ifdef ASSERT_BITVECTOR @@ -731,11 +739,26 @@ namespace storm { assert(false); } } + for (uint_fast64_t i = 0; i < bitCount; ++i) { + if (i < start || i >= start+length) { + if (original.get(i) != get(i)) { + std::cout << "Getting did change bitvector at index " << i << std::endl; + std::cout << "Getting from " << start << " with length " << length << std::endl; + printBits(std::cout); + original.printBits(std::cout); + assert(false); + } + } + } + #endif return result; } void BitVector::setFromBitVector(uint_fast64_t start, BitVector const& other) { +#ifdef ASSERT_BITVECTOR + BitVector original(*this); +#endif assert(start + other.bitCount <= bitCount); uint_fast64_t offset = start % 64; @@ -771,30 +794,24 @@ namespace storm { // Write last bits uint_fast64_t remainingBits = other.bitCount - noBits; + assert(remainingBits < 64); assert(bucketIndex < bucketCount()); assert(getBucket < other.bucketCount()); - // Get remaining bits - getValue = other.bucketVector[getBucket] << (64-offset); - assert(remainingBits < 64); - if (remainingBits <= offset) { - // Write completely - assert(getBucket == other.bucketCount()-1); - writeValue = (bucketVector[bucketIndex] << (offset+remainingBits)) >> remainingBits; - writeValue |= getValue; - bucketVector[bucketIndex] = writeValue; - } else { - // Remaining bits do not come from one bucket -> consider two buckets + // Get remaining bits of bucket + getValue = other.bucketVector[getBucket]; + if (offset > 0) { + getValue = getValue << (64-offset); + } + // Get unchanged part of bucket + writeValue = (bucketVector[bucketIndex] << remainingBits) >> remainingBits; + if (remainingBits > offset && offset > 0) { + // Remaining bits do not come from one bucket -> consider next bucket assert(getBucket == other.bucketCount() - 2); - writeValue = getValue; - getValue = other.bucketVector[++getBucket]; - writeValue |= getValue >> offset; - bucketVector[bucketIndex] = writeValue; - remainingBits = remainingBits + offset - 64; - // Write last bucket - writeValue = (bucketVector[++bucketIndex] << remainingBits) >> remainingBits; - writeValue |= getValue << (64-offset); - bucketVector[bucketIndex] = writeValue; + getValue |= other.bucketVector[++getBucket] >> offset; } + // Write completely + writeValue |= getValue; + bucketVector[bucketIndex] = writeValue; #ifdef ASSERT_BITVECTOR // Check correctness of setter @@ -807,6 +824,17 @@ namespace storm { assert(false); } } + for (uint_fast64_t i = 0; i < bitCount; ++i) { + if (i < start || i >= start+other.bitCount) { + if (original.get(i) != get(i)) { + std::cout << "Setting did change bitvector at index " << i << std::endl; + std::cout << "Setting from " << start << " with length " << other.bitCount << std::endl; + printBits(std::cout); + original.printBits(std::cout); + assert(false); + } + } + } #endif } From 4284c633f4bbef188ef3d19713f0ba72c62a757e Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 10 Mar 2016 16:56:28 +0100 Subject: [PATCH 203/246] StateGenerationInfo does not use DFS for symmetries Former-commit-id: 7111f5764a28aa38e3b7a751a8006a1e11fd0c8b --- src/storage/dft/DFT.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index c40fadceb..650712ebd 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -113,10 +113,11 @@ namespace storm { for (auto const& symmetryGroup : symmetries.groups) { assert(!symmetryGroup.second.empty()); - // Perform DFS for first subtree of each symmetry - visitQueue.push(symmetryGroup.first); + // Insert all elements of first subtree of each symmetry size_t groupIndex = stateIndex; - stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); + for (std::vector const& symmetryElement : symmetryGroup.second) { + stateIndex = generateStateInfo(generationInfo, symmetryElement[0], visited, stateIndex); + } size_t offset = stateIndex - groupIndex; // Mirror symmetries From a2a3a734a605e74b00eab861261aa15e7e0756a1 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 11 Mar 2016 00:04:19 +0100 Subject: [PATCH 204/246] First version of symmetry for shared spares. Still some problems in contrast to Dortmund which had absolutely no problems with Tottenham. Former-commit-id: c03062d4bd4b01f949cfa5c0660d5c4906a0f9d5 --- examples/dft/symmetry_shared.dft | 7 ++ src/storage/dft/DFT.cpp | 116 ++++++++++++++++++---- src/storage/dft/DFT.h | 2 + src/storage/dft/DFTIsomorphism.h | 113 +++++++++++++++------ src/storage/dft/elements/DFTBE.h | 6 +- src/storage/dft/elements/DFTDependency.h | 11 +- src/storage/dft/elements/DFTElement.cpp | 10 +- src/storage/dft/elements/DFTElement.h | 4 +- src/storage/dft/elements/DFTGate.h | 10 +- src/storage/dft/elements/DFTRestriction.h | 10 +- src/storage/dft/elements/DFTSpare.h | 39 ++++++++ 11 files changed, 251 insertions(+), 77 deletions(-) create mode 100644 examples/dft/symmetry_shared.dft diff --git a/examples/dft/symmetry_shared.dft b/examples/dft/symmetry_shared.dft new file mode 100644 index 000000000..73ebed519 --- /dev/null +++ b/examples/dft/symmetry_shared.dft @@ -0,0 +1,7 @@ +toplevel "A"; +"A" and "B" "B'"; +"B" wsp "C" "D"; +"B'" wsp "C'" "D"; +"C" lambda=0.5 dorm=0; +"D" lambda=0.5 dorm=0; +"C'" lambda=0.5 dorm=0; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 650712ebd..e9b4c659e 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -454,6 +454,98 @@ namespace storm { return DFTColouring(*this); } + template + std::map DFT::findBijection(size_t index1, size_t index2, DFTColouring const& colouring, bool sparesAsLeaves) const { + STORM_LOG_TRACE("Considering ids " << index1 << ", " << index2 << " for isomorphism."); + bool sharedSpareMode = false; + std::map bijection; + + if (isBasicElement(index1)) { + if (!isBasicElement(index2)) { + return {}; + } + if (colouring.hasSameColour(index1, index2)) { + bijection[index1] = index2; + return bijection; + } else { + return {}; + } + } + + assert(isGate(index1)); + assert(isGate(index2)); + std::vector isubdft1 = getGate(index1)->independentSubDft(false); + std::vector isubdft2 = getGate(index2)->independentSubDft(false); + if(isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) { + if (isubdft1.empty() && isubdft2.empty() && sparesAsLeaves) { + // Check again for shared spares + sharedSpareMode = true; + isubdft1 = getGate(index1)->independentSubDft(false, true); + isubdft2 = getGate(index2)->independentSubDft(false, true); + if(isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) { + return {}; + } + } else { + return {}; + } + } + STORM_LOG_TRACE("Checking subdfts from " << index1 << ", " << index2 << " for isomorphism."); + auto LHS = colouring.colourSubdft(isubdft1); + auto RHS = colouring.colourSubdft(isubdft2); + auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); + + while (IsoCheck.findNextIsomorphism()) { + bijection = IsoCheck.getIsomorphism(); + if (sharedSpareMode) { + bool bijectionSpareCompatible = true; + for (size_t elementId : isubdft1) { + if (getElement(elementId)->isSpareGate()) { + std::shared_ptr> spareLeft = std::static_pointer_cast>(mElements[elementId]); + std::shared_ptr> spareRight = std::static_pointer_cast>(mElements[bijection.at(elementId)]); + + if (spareLeft->nrChildren() != spareRight->nrChildren()) { + bijectionSpareCompatible = false; + break; + } + // Check bijection for spare children + for (size_t i = 0; i < spareLeft->nrChildren(); ++i) { + size_t childLeftId = spareLeft->children().at(i)->id(); + size_t childRightId = spareRight->children().at(i)->id(); + + assert(bijection.count(childLeftId) == 0); + if (childLeftId == childRightId) { + // Ignore shared child + continue; + } + + // TODO generalize for more than one parent + if (spareLeft->children().at(i)->nrParents() != 1 || spareRight->children().at(i)->nrParents() != 1) { + bijectionSpareCompatible = false; + break; + } + + std::map tmpBijection = findBijection(childLeftId, childRightId, colouring, false); + if (!tmpBijection.empty()) { + bijection.insert(tmpBijection.begin(), tmpBijection.end()); + } else { + bijectionSpareCompatible = false; + break; + } + } + if (!bijectionSpareCompatible) { + break; + } + } + } + if (bijectionSpareCompatible) { + return bijection; + } + } else { + return bijection; + } + } // end while + return {}; + } template DFTIndependentSymmetries DFT::findSymmetries(DFTColouring const& colouring) const { @@ -486,33 +578,21 @@ namespace storm { std::sort(sortedParent2Ids.begin(), sortedParent2Ids.end()); if(influencedElem1Ids == getSortedParentAndOutDepIds(*it2)) { - STORM_LOG_TRACE("Considering ids " << *it1 << ", " << *it2 << " for isomorphism."); - bool isSymmetry = false; - std::vector isubdft1 = getGate(*it1)->independentSubDft(false); - std::vector isubdft2 = getGate(*it2)->independentSubDft(false); - if(isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) { - continue; - } - STORM_LOG_TRACE("Checking subdfts from " << *it1 << ", " << *it2 << " for isomorphism."); - auto LHS = colouring.colourSubdft(isubdft1); - auto RHS = colouring.colourSubdft(isubdft2); - auto IsoCheck = DFTIsomorphismCheck(LHS, RHS, *this); - isSymmetry = IsoCheck.findIsomorphism(); - if(isSymmetry) { + std::map bijection = findBijection(*it1, *it2, colouring, true); + if (!bijection.empty()) { STORM_LOG_TRACE("Subdfts are symmetric"); foundEqClassFor.insert(*it2); if(symClass.empty()) { - for(auto const& i : isubdft1) { - symClass.push_back(std::vector({i})); + for(auto const& i : bijection) { + symClass.push_back(std::vector({i.first})); } } auto symClassIt = symClass.begin(); - for(auto const& i : isubdft1) { - symClassIt->emplace_back(IsoCheck.getIsomorphism().at(i)); + for(auto const& i : bijection) { + symClassIt->emplace_back(i.second); ++symClassIt; } - } } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 64805ade4..f28d244f0 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -238,6 +238,8 @@ namespace storm { std::vector getIndependentSubDftRoots(size_t index) const; DFTColouring colourDFT() const; + + std::map findBijection(size_t index1, size_t index2, DFTColouring const& colouring, bool sparesAsLeaves) const; DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; diff --git a/src/storage/dft/DFTIsomorphism.h b/src/storage/dft/DFTIsomorphism.h index b1f845b9f..d94640d9c 100644 --- a/src/storage/dft/DFTIsomorphism.h +++ b/src/storage/dft/DFTIsomorphism.h @@ -202,6 +202,10 @@ namespace storage { } } } + + bool hasSameColour(size_t index1, size_t index2) const { + return beColour.at(index1) == beColour.at(index2); + } BijectionCandidates colourSubdft(std::vector const& subDftIndices) const { @@ -308,13 +312,21 @@ namespace storage { } /** - * Check whether an isomorphism exists. + * Check whether another isomorphism exists. * - * @return true iff an isomorphism exists. + * @return true iff another isomorphism exists. */ - bool findIsomorphism() { - if(!candidatesCompatible) return false; - constructInitialBijection(); + bool findNextIsomorphism() { + if(!candidatesCompatible){ + return false; + } + if (bijection.empty()) { + constructInitialBijection(); + } else { + if (!findNextBijection()) { + return false; + } + } while(!check()) { // continue our search if(!findNextBijection()) { @@ -382,19 +394,31 @@ namespace storage { if(foundNext) { for(auto const& colour : bleft.beCandidates) { - zipVectorsIntoMap(colour.second, currentPermutations.beCandidates.find(colour.first)->second, bijection); + if (colour.second.size() > 1) { + assert(currentPermutations.beCandidates.find(colour.first) != currentPermutations.beCandidates.end()); + zipVectorsIntoMap(colour.second, currentPermutations.beCandidates.find(colour.first)->second, bijection); + } } for(auto const& colour : bleft.gateCandidates) { - zipVectorsIntoMap(colour.second, currentPermutations.gateCandidates.find(colour.first)->second, bijection); + if (colour.second.size() > 1) { + assert(currentPermutations.gateCandidates.find(colour.first) != currentPermutations.gateCandidates.end()); + zipVectorsIntoMap(colour.second, currentPermutations.gateCandidates.find(colour.first)->second, bijection); + } } for(auto const& colour : bleft.pdepCandidates) { - zipVectorsIntoMap(colour.second, currentPermutations.pdepCandidates.find(colour.first)->second, bijection); + if (colour.second.size() > 1) { + assert(currentPermutations.pdepCandidates.find(colour.first) != currentPermutations.pdepCandidates.end()); + zipVectorsIntoMap(colour.second, currentPermutations.pdepCandidates.find(colour.first)->second, bijection); + } } for(auto const& colour : bleft.restrictionCandidates) { - zipVectorsIntoMap(colour.second, currentPermutations.restrictionCandidates.find(colour.first)->second, bijection); + if (colour.second.size() > 1) { + assert(currentPermutations.restrictionCandidates.find(colour.first) != currentPermutations.restrictionCandidates.end()); + zipVectorsIntoMap(colour.second, currentPermutations.restrictionCandidates.find(colour.first)->second, bijection); + } } } @@ -405,7 +429,7 @@ namespace storage { /** * */ - bool check() { + bool check() const { assert(bijection.size() == bleft.size()); // We can skip BEs, as they are identified by they're homomorphic if they are in the same class for(auto const& indexpair : bijection) { @@ -418,13 +442,23 @@ namespace storage { if(lGate->isDynamicGate()) { std::vector childrenLeftMapped; for(auto const& child : lGate->children() ) { - assert(bleft.has(child->id())); - childrenLeftMapped.push_back(bijection.at(child->id())); + if (bleft.has(child->id())) { + childrenLeftMapped.push_back(bijection.at(child->id())); + } else { + // Indicate shared child which is not part of the symmetry + // For dynamic gates the order is important + childrenLeftMapped.push_back(-1); + } } std::vector childrenRight; for(auto const& child : rGate->children() ) { - assert(bright.has(child->id())); - childrenRight.push_back(child->id()); + if (bright.has(child->id())) { + childrenRight.push_back(child->id()); + } else { + // Indicate shared child which is not part of the symmetry + // For dynamic gates the order is important + childrenRight.push_back(-1); + } } if(childrenLeftMapped != childrenRight) { return false; @@ -432,13 +466,15 @@ namespace storage { } else { std::set childrenLeftMapped; for(auto const& child : lGate->children() ) { - assert(bleft.has(child->id())); - childrenLeftMapped.insert(bijection.at(child->id())); + if (bleft.has(child->id())) { + childrenLeftMapped.insert(bijection.at(child->id())); + } } std::set childrenRight; for(auto const& child : rGate->children() ) { - assert(bright.has(child->id())); - childrenRight.insert(child->id()); + if (bright.has(child->id())) { + childrenRight.insert(child->id()); + } } if(childrenLeftMapped != childrenRight) { return false; @@ -459,16 +495,26 @@ namespace storage { } else if(dft.isRestriction(indexpair.first)) { assert(dft.isRestriction(indexpair.second)); auto const& lRestr = dft.getRestriction(indexpair.first); - std::set childrenLeftMapped; + std::vector childrenLeftMapped; for(auto const& child : lRestr->children() ) { - assert(bleft.has(child->id())); - childrenLeftMapped.insert(bijection.at(child->id())); + if (bleft.has(child->id())) { + childrenLeftMapped.push_back(bijection.at(child->id())); + } else { + // Indicate shared child which is not part of the symmetry + // For dynamic gates the order is important + childrenLeftMapped.push_back(-1); + } } auto const& rRestr = dft.getRestriction(indexpair.second); - std::set childrenRight; + std::vector childrenRight; for(auto const& child : rRestr->children() ) { - assert(bright.has(child->id())); - childrenRight.insert(child->id()); + if (bright.has(child->id())) { + childrenRight.push_back(child->id()); + } else { + // Indicate shared child which is not part of the symmetry + // For dynamic gates the order is important + childrenRight.push_back(-1); + } } if(childrenLeftMapped != childrenRight) { return false; @@ -487,50 +533,51 @@ namespace storage { /** * Returns true if the colours are compatible. */ - void checkCompatibility() { + bool checkCompatibility() { if(bleft.gateCandidates.size() != bright.gateCandidates.size()) { candidatesCompatible = false; - return; + return false; } if(bleft.beCandidates.size() != bright.beCandidates.size()) { candidatesCompatible = false; - return; + return false; } if(bleft.beCandidates.size() != bright.beCandidates.size()) { candidatesCompatible = false; - return; + return false; } if(bleft.restrictionCandidates.size() != bright.restrictionCandidates.size()) { candidatesCompatible = false; - return; + return false; } for (auto const &gc : bleft.gateCandidates) { if (bright.gateCandidates.count(gc.first) == 0) { candidatesCompatible = false; - return; + return false; } } for(auto const& bc : bleft.beCandidates) { if(bright.beCandidates.count(bc.first) == 0) { candidatesCompatible = false; - return; + return false; } } for(auto const& dc : bleft.pdepCandidates) { if(bright.pdepCandidates.count(dc.first) == 0) { candidatesCompatible = false; - return; + return false; } } for(auto const& dc : bleft.restrictionCandidates) { if(bright.restrictionCandidates.count(dc.first) == 0) { candidatesCompatible = false; - return; + return false; } } + return true; } /** diff --git a/src/storage/dft/elements/DFTBE.h b/src/storage/dft/elements/DFTBE.h index a9c5b030d..58e580262 100644 --- a/src/storage/dft/elements/DFTBE.h +++ b/src/storage/dft/elements/DFTBE.h @@ -71,15 +71,15 @@ namespace storm { return storm::utility::isZero(mPassiveFailureRate); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { if(elemsInSubtree.count(this->id())) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for(auto const& incDep : mIngoingDependencies) { - incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + incDep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; diff --git a/src/storage/dft/elements/DFTDependency.h b/src/storage/dft/elements/DFTDependency.h index c7f3f6bfd..44a5ab9df 100644 --- a/src/storage/dft/elements/DFTDependency.h +++ b/src/storage/dft/elements/DFTDependency.h @@ -83,20 +83,19 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { - if(elemsInSubtree.count(this->id())) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { + if(elemsInSubtree.count(this->id())) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } - mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + mDependentEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } - mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); - + mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); } diff --git a/src/storage/dft/elements/DFTElement.cpp b/src/storage/dft/elements/DFTElement.cpp index 0ee8a3cd2..803199508 100644 --- a/src/storage/dft/elements/DFTElement.cpp +++ b/src/storage/dft/elements/DFTElement.cpp @@ -68,14 +68,14 @@ namespace storm { } template - std::vector DFTElement::independentSubDft(bool blockParents) const { + std::vector DFTElement::independentSubDft(bool blockParents, bool sparesAsLeaves) const { std::vector res; res.push_back(this->id()); return res; } template - void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const { + void DFTElement::extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const { if(elemsInSubtree.count(this->id()) > 0) return; if(std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), mId) != parentsOfSubRoot.end()) { // This is a parent of the suspected root, thus it is not a subdft. @@ -87,13 +87,13 @@ namespace storm { if(blockParents && std::find(parentsOfSubRoot.begin(), parentsOfSubRoot.end(), parent->id()) != parentsOfSubRoot.end()) { continue; } - parent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + parent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { return; } } for(auto const& dep : mOutgoingDependencies) { - dep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + dep->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { return; } @@ -101,7 +101,7 @@ namespace storm { } for(auto const& restr : mRestrictions) { - restr->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + restr->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { return; } diff --git a/src/storage/dft/elements/DFTElement.h b/src/storage/dft/elements/DFTElement.h index 2b3b05c98..8a8a35d28 100644 --- a/src/storage/dft/elements/DFTElement.h +++ b/src/storage/dft/elements/DFTElement.h @@ -286,12 +286,12 @@ namespace storm { * - a probabilistic dependency * such that there exists a path from x to a child of this does not go through this. */ - virtual std::vector independentSubDft(bool blockParents) const; + virtual std::vector independentSubDft(bool blockParents, bool sparesAsLeaves = false) const; /** * Helper to the independent subtree computation * @see independentSubDft */ - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const; + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const; virtual bool isTypeEqualTo(DFTElement const& other) const { return type() == other.type(); diff --git a/src/storage/dft/elements/DFTGate.h b/src/storage/dft/elements/DFTGate.h index d82906895..67fa0f70a 100644 --- a/src/storage/dft/elements/DFTGate.h +++ b/src/storage/dft/elements/DFTGate.h @@ -73,7 +73,7 @@ namespace storm { } } - virtual std::vector independentSubDft(bool blockParents) const override { + virtual std::vector independentSubDft(bool blockParents, bool sparesAsLeaves = false) const override { auto prelRes = DFTElement::independentSubDft(blockParents); if(prelRes.empty()) { // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. @@ -82,7 +82,7 @@ namespace storm { std::set unit(prelRes.begin(), prelRes.end()); std::vector pids = this->parentIds(); for(auto const& child : mChildren) { - child->extendSubDft(unit, pids, blockParents); + child->extendSubDft(unit, pids, blockParents, sparesAsLeaves); if(unit.empty()) { // Parent in the subdft, ie it is *not* a subdft break; @@ -91,15 +91,15 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { if(elemsInSubtree.count(this->id()) > 0) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for(auto const& child : mChildren) { - child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; diff --git a/src/storage/dft/elements/DFTRestriction.h b/src/storage/dft/elements/DFTRestriction.h index dc2e6116e..25441b5b1 100644 --- a/src/storage/dft/elements/DFTRestriction.h +++ b/src/storage/dft/elements/DFTRestriction.h @@ -69,7 +69,7 @@ namespace storm { } } - virtual std::vector independentSubDft(bool blockParents) const override { + virtual std::vector independentSubDft(bool blockParents, bool sparesAsLeaves) const override { auto prelRes = DFTElement::independentSubDft(blockParents); if(prelRes.empty()) { // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. @@ -78,7 +78,7 @@ namespace storm { std::set unit(prelRes.begin(), prelRes.end()); std::vector pids = this->parentIds(); for(auto const& child : mChildren) { - child->extendSubDft(unit, pids, blockParents); + child->extendSubDft(unit, pids, blockParents, sparesAsLeaves); if(unit.empty()) { // Parent in the subdft, ie it is *not* a subdft break; @@ -87,15 +87,15 @@ namespace storm { return std::vector(unit.begin(), unit.end()); } - virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents) const override { + virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { if(elemsInSubtree.count(this->id()) > 0) return; - DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for(auto const& child : mChildren) { - child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents); + child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; diff --git a/src/storage/dft/elements/DFTSpare.h b/src/storage/dft/elements/DFTSpare.h index dd3689311..81017ff19 100644 --- a/src/storage/dft/elements/DFTSpare.h +++ b/src/storage/dft/elements/DFTSpare.h @@ -64,6 +64,45 @@ namespace storm { } } } + + std::vector independentSubDft(bool blockParents, bool sparesAsLeaves = false) const override { + auto prelRes = DFTElement::independentSubDft(blockParents); + if(prelRes.empty()) { + // No elements (especially not this->id) in the prelimanry result, so we know already that it is not a subdft. + return prelRes; + } + std::set unit(prelRes.begin(), prelRes.end()); + std::vector pids = this->parentIds(); + if (!sparesAsLeaves) { + for(auto const& child : this->mChildren) { + child->extendSubDft(unit, pids, blockParents, sparesAsLeaves); + if(unit.empty()) { + // Parent in the subdft, ie it is *not* a subdft + break; + } + } + } + return std::vector(unit.begin(), unit.end()); + } + + void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { + if(elemsInSubtree.count(this->id()) > 0) return; + DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + if (!sparesAsLeaves) { + for(auto const& child : this->mChildren) { + child->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); + if(elemsInSubtree.empty()) { + // Parent in the subdft, ie it is *not* a subdft + return; + } + } + } + } + }; } From 7e8b790451b01f0fd0c1dc27272eda8695bee65b Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 11 Mar 2016 11:49:53 +0100 Subject: [PATCH 205/246] Preparation for pseudo state generation from bit vector Former-commit-id: a273f13a676bb7b1a9f5ae2b1ced896c40808e81 --- src/builder/ExplicitDFTModelBuilder.cpp | 39 ++++++++++++++++++++----- src/builder/ExplicitDFTModelBuilder.h | 2 +- src/storage/dft/DFTState.cpp | 7 +++++ src/storage/dft/DFTState.h | 5 ++++ 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 3c5a39702..d57dec2e7 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -246,10 +246,11 @@ namespace storm { if (!changed && newStateId >= OFFSET_PSEUDO_STATE) { newStateId = newStateId - OFFSET_PSEUDO_STATE; assert(newStateId < mPseudoStatesMapping.size()); - if (mPseudoStatesMapping[newStateId] == 0) { + if (mPseudoStatesMapping[newStateId].first == 0) { // Create pseudo state now + assert(mPseudoStatesMapping[newStateId].second == newState->status()); newState->setId(newIndex++); - mPseudoStatesMapping[newStateId] = newState->getId(); + mPseudoStatesMapping[newStateId].first = newState->getId(); newStateId = newState->getId(); mStates.setOrAdd(newState->status(), newStateId); stateQueue.push(newState); @@ -261,7 +262,7 @@ namespace storm { if (changed) { // Remember to create state later on newState->setId(mPseudoStatesMapping.size() + OFFSET_PSEUDO_STATE); - mPseudoStatesMapping.push_back(0); + mPseudoStatesMapping.push_back(std::make_pair(0, newState->status())); newStateId = mStates.findOrAdd(newState->status(), newState->getId()); STORM_LOG_TRACE("New state for later creation: " << mDft.getStateString(newState)); } else { @@ -345,9 +346,9 @@ namespace storm { if (it->first >= OFFSET_PSEUDO_STATE) { uint_fast64_t newId = it->first - OFFSET_PSEUDO_STATE; assert(newId < mPseudoStatesMapping.size()); - if (mPseudoStatesMapping[newId] > 0) { + if (mPseudoStatesMapping[newId].first > 0) { // State exists already - newId = mPseudoStatesMapping[newId]; + newId = mPseudoStatesMapping[newId].first; auto itFind = outgoingTransitions.find(newId); if (itFind != outgoingTransitions.end()) { // Add probability from pseudo state to instantiation @@ -382,11 +383,35 @@ namespace storm { exitRates.push_back(exitRate); assert(exitRates.size()-1 == state->getId()); + if (stateQueue.empty()) { + // Before ending the exploration check for pseudo states which are no be initialized yet + for (auto & pseudoStatePair : mPseudoStatesMapping) { + if (pseudoStatePair.first == 0) { + // Create state from pseudo state and explore + assert(mStates.contains(pseudoStatePair.second)); + assert(mStates.getValue(pseudoStatePair.second) >= OFFSET_PSEUDO_STATE); + STORM_LOG_TRACE("Create pseudo state from bit vector " << pseudoStatePair.second); + DFTStatePointer pseudoState = std::make_shared>(pseudoStatePair.second, mDft, *mStateGenerationInfo, newIndex++); + assert(pseudoStatePair.second == pseudoState->status()); + pseudoStatePair.first = pseudoState->getId(); + mStates.setOrAdd(pseudoState->status(), pseudoState->getId()); + stateQueue.push(pseudoState); + STORM_LOG_TRACE("Explore pseudo state " << mDft.getStateString(pseudoState) << " with id " << pseudoState->getId()); + break; + } + } + } + } // end while queue - assert(std::find(mPseudoStatesMapping.begin(), mPseudoStatesMapping.end(), 0) == mPseudoStatesMapping.end()); + + std::vector pseudoStatesVector; + for (auto const& pseudoStatePair : mPseudoStatesMapping) { + pseudoStatesVector.push_back(pseudoStatePair.first); + } + assert(std::find(pseudoStatesVector.begin(), pseudoStatesVector.end(), 0) == pseudoStatesVector.end()); // Replace pseudo states in matrix - transitionMatrixBuilder.replaceColumns(mPseudoStatesMapping, OFFSET_PSEUDO_STATE); + transitionMatrixBuilder.replaceColumns(pseudoStatesVector, OFFSET_PSEUDO_STATE); assert(!deterministic || rowOffset == 0); return deterministic; diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 13b3eaf0d..7fc343be2 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -52,7 +52,7 @@ namespace storm { storm::storage::DFT const& mDft; std::shared_ptr mStateGenerationInfo; storm::storage::BitVectorHashMap mStates; - std::vector mPseudoStatesMapping; + std::vector> mPseudoStatesMapping; // vector of (id to concrete state, bitvector) size_t newIndex = 0; bool mergeFailedStates = true; size_t failedIndex = 0; diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 1d34362f9..b7061b9b2 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -22,6 +22,13 @@ namespace storm { std::vector alwaysActiveBEs = dft.nonColdBEs(); mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); } + + template + DFTState::DFTState(storm::storage::BitVector const& status, DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) : mStatus(status), mId(id), mDft(dft), mStateGenerationInfo(stateGenerationInfo) { + // TODO implement + assert(false); + } + template DFTElementState DFTState::getElementState(size_t id) const { diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 826e510d5..faf183411 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -36,6 +36,11 @@ namespace storm { public: DFTState(DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id); + /** + * Construct state from underlying bitvector. + */ + DFTState(storm::storage::BitVector const& status, DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id); + DFTElementState getElementState(size_t id) const; DFTDependencyState getDependencyState(size_t id) const; From 652aeb75624cddc7e0b37f5edd2b13ef789dae27 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 11 Mar 2016 14:01:59 +0100 Subject: [PATCH 206/246] Fixed compile error with CarlRationalNumber instead of RationalNumber Former-commit-id: 0fbb4ad1c102926aaa92b1b0ce049a2953b1fef9 --- src/utility/constants.cpp | 14 ++++---- src/utility/parametric.h | 2 +- .../utility/ModelInstantiatorTest.cpp | 34 +++++++++---------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/utility/constants.cpp b/src/utility/constants.cpp index 6b3bb296b..06c934864 100644 --- a/src/utility/constants.cpp +++ b/src/utility/constants.cpp @@ -133,13 +133,13 @@ namespace storm { } template<> - double convertNumber(RationalNumber const& number){ + double convertNumber(CarlRationalNumber const& number){ return carl::toDouble(number); } template<> - RationalNumber convertNumber(double const& number){ - return carl::rationalize(number); + CarlRationalNumber convertNumber(double const& number){ + return carl::rationalize(number); } #endif @@ -241,7 +241,7 @@ namespace storm { template RationalFunction& simplify(RationalFunction& value); template RationalFunction&& simplify(RationalFunction&& value); - /*template Polynomial one(); + template Polynomial one(); template Polynomial zero(); template bool isOne(CarlRationalNumber const& value); @@ -249,10 +249,10 @@ namespace storm { template bool isConstant(CarlRationalNumber const& value); template CarlRationalNumber one(); - template CarlRationalNumber zero();*/ + template CarlRationalNumber zero(); - template double convertNumber(RationalNumber const& number); - template RationalNumber convertNumber(double const& number); + template double convertNumber(CarlRationalNumber const& number); + template CarlRationalNumber convertNumber(double const& number); template bool isOne(Interval const& value); template bool isZero(Interval const& value); diff --git a/src/utility/parametric.h b/src/utility/parametric.h index 2ebf1e18c..ec2c9aa84 100644 --- a/src/utility/parametric.h +++ b/src/utility/parametric.h @@ -30,7 +30,7 @@ namespace storm { template<> struct VariableType { typedef storm::Variable type; }; template<> - struct CoefficientType { typedef storm::RationalNumber type; }; + struct CoefficientType { typedef storm::CarlRationalNumber type; }; #endif /*! diff --git a/test/functional/utility/ModelInstantiatorTest.cpp b/test/functional/utility/ModelInstantiatorTest.cpp index af8f5b8d2..0bf692a60 100644 --- a/test/functional/utility/ModelInstantiatorTest.cpp +++ b/test/functional/utility/ModelInstantiatorTest.cpp @@ -39,13 +39,13 @@ TEST(ModelInstantiatorTest, Brp_Prob) { EXPECT_FALSE(dtmc->hasRewardModel()); { - std::map valuation; + std::map valuation; storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL"); ASSERT_NE(pL, carl::Variable::NO_VARIABLE); storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK"); ASSERT_NE(pK, carl::Variable::NO_VARIABLE); - valuation.insert(std::make_pair(pL,carl::rationalize(0.8))); - valuation.insert(std::make_pair(pK,carl::rationalize(0.9))); + valuation.insert(std::make_pair(pL,carl::rationalize(0.8))); + valuation.insert(std::make_pair(pK,carl::rationalize(0.9))); storm::models::sparse::Dtmc const& instantiated(modelInstantiator.instantiate(valuation)); @@ -72,13 +72,13 @@ TEST(ModelInstantiatorTest, Brp_Prob) { } { - std::map valuation; + std::map valuation; storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL"); ASSERT_NE(pL, carl::Variable::NO_VARIABLE); storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK"); ASSERT_NE(pK, carl::Variable::NO_VARIABLE); - valuation.insert(std::make_pair(pL,carl::rationalize(1))); - valuation.insert(std::make_pair(pK,carl::rationalize(1))); + valuation.insert(std::make_pair(pL,carl::rationalize(1))); + valuation.insert(std::make_pair(pK,carl::rationalize(1))); storm::models::sparse::Dtmc const& instantiated(modelInstantiator.instantiate(valuation)); @@ -105,13 +105,13 @@ TEST(ModelInstantiatorTest, Brp_Prob) { } { - std::map valuation; + std::map valuation; storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL"); ASSERT_NE(pL, carl::Variable::NO_VARIABLE); storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK"); ASSERT_NE(pK, carl::Variable::NO_VARIABLE); - valuation.insert(std::make_pair(pL,carl::rationalize(1))); - valuation.insert(std::make_pair(pK,carl::rationalize(0.9))); + valuation.insert(std::make_pair(pL,carl::rationalize(1))); + valuation.insert(std::make_pair(pK,carl::rationalize(0.9))); storm::models::sparse::Dtmc const& instantiated(modelInstantiator.instantiate(valuation)); @@ -159,7 +159,7 @@ TEST(ModelInstantiatorTest, Brp_Rew) { storm::utility::ModelInstantiator, storm::models::sparse::Dtmc> modelInstantiator(*dtmc); { - std::map valuation; + std::map valuation; storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL"); ASSERT_NE(pL, carl::Variable::NO_VARIABLE); storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK"); @@ -168,10 +168,10 @@ TEST(ModelInstantiatorTest, Brp_Rew) { ASSERT_NE(pK, carl::Variable::NO_VARIABLE); storm::Variable const& TOAck = carl::VariablePool::getInstance().findVariableWithName("TOAck"); ASSERT_NE(pK, carl::Variable::NO_VARIABLE); - valuation.insert(std::make_pair(pL,carl::rationalize(0.9))); - valuation.insert(std::make_pair(pK,carl::rationalize(0.3))); - valuation.insert(std::make_pair(TOMsg,carl::rationalize(0.3))); - valuation.insert(std::make_pair(TOAck,carl::rationalize(0.5))); + valuation.insert(std::make_pair(pL,carl::rationalize(0.9))); + valuation.insert(std::make_pair(pK,carl::rationalize(0.3))); + valuation.insert(std::make_pair(TOMsg,carl::rationalize(0.3))); + valuation.insert(std::make_pair(TOAck,carl::rationalize(0.5))); storm::models::sparse::Dtmc const& instantiated(modelInstantiator.instantiate(valuation)); @@ -231,13 +231,13 @@ TEST(ModelInstantiatorTest, consensus) { storm::utility::ModelInstantiator, storm::models::sparse::Mdp> modelInstantiator(*mdp); - std::map valuation; + std::map valuation; storm::Variable const& p1 = carl::VariablePool::getInstance().findVariableWithName("p1"); ASSERT_NE(p1, carl::Variable::NO_VARIABLE); storm::Variable const& p2 = carl::VariablePool::getInstance().findVariableWithName("p2"); ASSERT_NE(p2, carl::Variable::NO_VARIABLE); - valuation.insert(std::make_pair(p1,carl::rationalize(0.51))); - valuation.insert(std::make_pair(p2,carl::rationalize(0.49))); + valuation.insert(std::make_pair(p1,carl::rationalize(0.51))); + valuation.insert(std::make_pair(p2,carl::rationalize(0.49))); storm::models::sparse::Mdp const& instantiated(modelInstantiator.instantiate(valuation)); ASSERT_EQ(mdp->getTransitionMatrix().getRowGroupIndices(), instantiated.getTransitionMatrix().getRowGroupIndices()); From 306eb8a9ccbbd14d357b0a352d0bdec96b41a0a3 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 11 Mar 2016 15:13:24 +0100 Subject: [PATCH 207/246] Construct state from bit vector Former-commit-id: 705af6d503fafdc8520e5769511f8802144bded8 --- examples/dft/mcs.dft | 22 ++++++++++++++++++++++ src/storage/dft/DFTState.cpp | 28 +++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 examples/dft/mcs.dft diff --git a/examples/dft/mcs.dft b/examples/dft/mcs.dft new file mode 100644 index 000000000..733a7a599 --- /dev/null +++ b/examples/dft/mcs.dft @@ -0,0 +1,22 @@ +toplevel "n12"; +"n12" or "n1" "n103" "n7"; +"n103" wsp "n106" "n14"; +"n7" and "n18" "n26"; +"n26" or "n28" "n19" "n23"; +"n19" wsp "n16" "n13"; +"n23" wsp "n0" "n17"; +"n18" or "n15" "n9" "n3"; +"n3" wsp "n2" "n17"; +"n9" wsp "n8" "n27"; +"n16" lambda=8.0 dorm=0.0; +"n0" lambda=0.003 dorm=0.0; +"n13" lambda=8.0 dorm=0.5; +"n2" lambda=0.003 dorm=0.0; +"n17" lambda=0.003 dorm=0.5; +"n15" lambda=0.05 dorm=0.0; +"n106" lambda=1.2 dorm=0.0; +"n14" lambda=0.6 dorm=0.0; +"n1" lambda=2.0E-4 dorm=0.0; +"n27" lambda=8.0 dorm=0.5; +"n8" lambda=8.0 dorm=0.0; +"n28" lambda=0.05 dorm=0.0; diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index b7061b9b2..c17bad0b6 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -25,10 +25,32 @@ namespace storm { template DFTState::DFTState(storm::storage::BitVector const& status, DFT const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) : mStatus(status), mId(id), mDft(dft), mStateGenerationInfo(stateGenerationInfo) { - // TODO implement - assert(false); + + for(size_t index = 0; index < mDft.nrElements(); ++index) { + // Initialize currently failable BE + if (mDft.isBasicElement(index) && isOperational(index)) { + if (!mDft.getBasicElement(index)->isColdBasicElement() || !mDft.hasRepresentant(index) || isActive(mDft.getRepresentant(index)->id())) { + mIsCurrentlyFailableBE.push_back(index); + STORM_LOG_TRACE("Currently failable: " << mDft.getBasicElement(index)->toString()); + } + } else if (mDft.getElement(index)->isSpareGate()) { + // Initialize used representants + uint_fast64_t useId = uses(index); + mUsedRepresentants.push_back(useId); + STORM_LOG_TRACE("Spare " << index << " uses " << useId); + } + } + + // Initialize failable dependencies + for (size_t dependencyId : mDft.getDependencies()) { + std::shared_ptr const> dependency = mDft.getDependency(dependencyId); + assert(dependencyId == dependency->id()); + if (hasFailed(dependency->triggerEvent()->id()) && getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) { + mFailableDependencies.push_back(dependencyId); + STORM_LOG_TRACE("New dependency failure: " << dependency->toString()); + } + } } - template DFTElementState DFTState::getElementState(size_t id) const { From a21715cbc38d249c9b060e7a06d95212b425f6d7 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 12 Mar 2016 00:15:47 +0100 Subject: [PATCH 208/246] Nested symmetries seem to work for at least binary symmetries Former-commit-id: dfa2052d1802239b4f8ae800a1a2b6cf14f97772 --- src/storage/dft/DFT.cpp | 27 ++++-- src/storage/dft/DFTStateGenerationInfo.h | 28 +++++- src/storage/dft/SymmetricUnits.h | 110 ++++++++++++++++++++++- 3 files changed, 155 insertions(+), 10 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index e9b4c659e..dd771f230 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -110,22 +110,35 @@ namespace storm { visitQueue.push(mTopLevelIndex); stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); } else { - for (auto const& symmetryGroup : symmetries.groups) { - assert(!symmetryGroup.second.empty()); + for (size_t symmetryIndex : symmetries.sortedSymmetries) { + assert(!visited[symmetryIndex]); + auto const& symmetryGroup = symmetries.groups.at(symmetryIndex); + assert(!symmetryGroup.empty()); // Insert all elements of first subtree of each symmetry size_t groupIndex = stateIndex; - for (std::vector const& symmetryElement : symmetryGroup.second) { - stateIndex = generateStateInfo(generationInfo, symmetryElement[0], visited, stateIndex); + for (std::vector const& symmetryElement : symmetryGroup) { + if (visited[symmetryElement[0]]) { + groupIndex = std::min(groupIndex, generationInfo.getStateIndex(symmetryElement[0])); + } else { + stateIndex = generateStateInfo(generationInfo, symmetryElement[0], visited, stateIndex); + } } size_t offset = stateIndex - groupIndex; // Mirror symmetries - size_t noSymmetricElements = symmetryGroup.second.front().size(); + size_t noSymmetricElements = symmetryGroup.front().size(); assert(noSymmetricElements > 1); - for (std::vector symmetricElements : symmetryGroup.second) { + for (std::vector symmetricElements : symmetryGroup) { assert(symmetricElements.size() == noSymmetricElements); + if (visited[symmetricElements[1]]) { + // Elements already mirrored + for (size_t index : symmetricElements) { + assert(visited[index]); + } + continue; + } // Initialize for original element size_t originalElement = symmetricElements[0]; @@ -181,6 +194,8 @@ namespace storm { stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); } } + + generationInfo.generateSymmetries(symmetries); STORM_LOG_TRACE(generationInfo); assert(stateIndex == mStateVectorSize); diff --git a/src/storage/dft/DFTStateGenerationInfo.h b/src/storage/dft/DFTStateGenerationInfo.h index 4b3ef92c9..d4bbdee8b 100644 --- a/src/storage/dft/DFTStateGenerationInfo.h +++ b/src/storage/dft/DFTStateGenerationInfo.h @@ -10,7 +10,7 @@ namespace storm { std::vector mIdToStateIndex; // id -> index first bit in state std::map> mSeqRestrictionPreElements; // id -> list of restriction pre elements; std::map> mSeqRestrictionPostElements; // id -> list of restriction post elements; - std::vector>> mSymmetries; // pair (lenght of symmetry group, vector indicating the starting points of the symmetry groups) + std::vector>> mSymmetries; // pair (length of symmetry group, vector indicating the starting points of the symmetry groups) public: @@ -70,6 +70,32 @@ namespace storm { void addSymmetry(size_t length, std::vector& startingIndices) { mSymmetries.push_back(std::make_pair(length, startingIndices)); } + + /** + * Generate more symmetries by combining two symmetries + */ + void generateSymmetries(storm::storage::DFTIndependentSymmetries const& symmetries) { + for (size_t i = 0; i < mSymmetries.size(); ++i) { + size_t childStart = mSymmetries[i].second[0]; + size_t childLength = mSymmetries[i].first; + for (size_t j = i+1; j < mSymmetries.size(); ++j) { + size_t parentStart = mSymmetries[j].second[0]; + size_t parentLength = mSymmetries[j].first; + // Check if child lies in parent + if (parentStart <= childStart && childStart + childLength < parentStart + parentLength) { + // Get symmetric start by applying the bijection + std::vector newStarts; + for (size_t symmetryStarts : mSymmetries[i].second) { + newStarts.push_back(symmetryStarts + parentLength); + } + // Insert after child + mSymmetries.insert(mSymmetries.begin() + i + 1, std::make_pair(childLength, newStarts)); + ++i; + break; + } + } + } + } size_t getSymmetrySize() const { return mSymmetries.size(); diff --git a/src/storage/dft/SymmetricUnits.h b/src/storage/dft/SymmetricUnits.h index 58a70e492..33c8efeae 100644 --- a/src/storage/dft/SymmetricUnits.h +++ b/src/storage/dft/SymmetricUnits.h @@ -1,19 +1,123 @@ #pragma once +#include "src/utility/macros.h" + namespace storm { namespace storage { struct DFTIndependentSymmetries { std::map>> groups; + std::vector sortedSymmetries; + + bool existsInFirstSymmetry(size_t index, size_t value) { + for (std::vector symmetry : groups[index]) { + if (symmetry.front() == value) { + return true; + } + } + return false; + } + + bool existsInSymmetry(size_t index, size_t value) { + for (std::vector symmetry : groups[index]) { + for (size_t index : symmetry) { + if (index == value) { + return true; + } + } + } + return false; + } + + /** + * Apply symmetry and get bijection. Result is symmetry(value)[index] + * + * @param symmetry The symmetry. + * @param value The value to apply the bijection to. + * @param index The index of the symmetry group to apply. + * @return Symmetric value, -1 if the bijection could not be applied. + */ + int applySymmetry(std::vector> const& symmetry, size_t value, size_t index) const { + for (std::vector element : symmetry) { + if (element[0] == value) { + return element[index]; + } + } + return -1; + } + + std::vector> createSymmetry(std::vector> parentSymmetry, std::vector> childSymmetry, size_t index) { + std::vector> result; + for (std::vector childSymmetry : childSymmetry) { + std::vector symmetry; + for (size_t child : childSymmetry) { + int bijectionValue = applySymmetry(parentSymmetry, child, index); + if (bijectionValue >= 0) { + symmetry.push_back(bijectionValue); + } else { + return result; + } + } + result.push_back(symmetry); + } + return result; + } + + void sortHierarchical(size_t parent, std::vector& candidates) { + std::vector children; + for (int i = candidates.size() - 1; i >= 0; --i) { + size_t currentRoot = candidates[i]; + if (existsInSymmetry(parent, currentRoot)) { + // Is child + STORM_LOG_TRACE(currentRoot << " is child of " << parent); + children.insert(children.begin(), currentRoot); + candidates.erase(candidates.begin()+i); + } + } + for (size_t i = 0; i < children.size(); ++i) { + std::vector> possibleSymmetry = createSymmetry(groups.at(parent), groups.at(children[i]), 1); + for (size_t j = i + 1; j < children.size(); ++j) { + if (possibleSymmetry == groups.at(children[j])) { + STORM_LOG_TRACE("Child " << children[j] << " ignored as created by symmetries " << parent << " and " << children[j]); + groups.erase(children[j]); + children.erase(children.begin() + j); + } + } + } + while (!children.empty()) { + // Insert largest element + size_t largestChild = children.back(); + children.pop_back(); + sortHierarchical(largestChild, children); + sortedSymmetries.push_back(largestChild); + } + } + DFTIndependentSymmetries(std::map>> groups) : groups(groups) { + std::vector sortedGroups; + for (auto const& cl : groups) { + sortedGroups.push_back(cl.first); + } + // Sort by length of symmetry + std::sort(sortedGroups.begin(), sortedGroups.end(), [&](const size_t left, const size_t right) { + return groups.at(left).size() < groups.at(right).size(); + }); + // Sort hierarchical + while (!sortedGroups.empty()) { + // Insert largest element + size_t currentRoot = sortedGroups.back(); + sortedGroups.pop_back(); + sortHierarchical(currentRoot, sortedGroups); + sortedSymmetries.push_back(currentRoot); + } } }; inline std::ostream& operator<<(std::ostream& os, DFTIndependentSymmetries const& s) { - for(auto const& cl : s.groups) { - os << "Symmetry group for " << cl.first << std::endl; - for(auto const& eqClass : cl.second) { + for(size_t index : s.sortedSymmetries) { + os << "Symmetry group for " << index << std::endl; + for(auto const& eqClass : s.groups.at(index)) { for(auto const& i : eqClass) { os << i << " "; } From 150f177bcd7e5d11f80d672db8a25f62bfd7a57e Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 12 Mar 2016 15:13:36 +0100 Subject: [PATCH 209/246] Symred on mcs seems to work now Former-commit-id: d6a830f8a1757fe4c924ad98e1b256b3c4a66fb3 --- src/storage/dft/DFTStateGenerationInfo.h | 20 ++++++++++++++------ src/storage/dft/SymmetricUnits.h | 24 ++++++++++++++++-------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/storage/dft/DFTStateGenerationInfo.h b/src/storage/dft/DFTStateGenerationInfo.h index d4bbdee8b..e700d8700 100644 --- a/src/storage/dft/DFTStateGenerationInfo.h +++ b/src/storage/dft/DFTStateGenerationInfo.h @@ -75,22 +75,30 @@ namespace storm { * Generate more symmetries by combining two symmetries */ void generateSymmetries(storm::storage::DFTIndependentSymmetries const& symmetries) { + // Iterate over possible children for (size_t i = 0; i < mSymmetries.size(); ++i) { size_t childStart = mSymmetries[i].second[0]; size_t childLength = mSymmetries[i].first; + // Iterate over possible parents for (size_t j = i+1; j < mSymmetries.size(); ++j) { size_t parentStart = mSymmetries[j].second[0]; size_t parentLength = mSymmetries[j].first; // Check if child lies in parent if (parentStart <= childStart && childStart + childLength < parentStart + parentLength) { - // Get symmetric start by applying the bijection - std::vector newStarts; - for (size_t symmetryStarts : mSymmetries[i].second) { - newStarts.push_back(symmetryStarts + parentLength); + std::vector> newSymmetries; + for (size_t index = 1; index < mSymmetries[j].second.size(); ++index) { + // Get symmetric start by applying the bijection + std::vector newStarts; + for (size_t symmetryStarts : mSymmetries[i].second) { + newStarts.push_back(symmetryStarts + mSymmetries[j].second[index]); + } + newSymmetries.push_back(newStarts); } // Insert after child - mSymmetries.insert(mSymmetries.begin() + i + 1, std::make_pair(childLength, newStarts)); - ++i; + for (size_t index = 0; index < newSymmetries.size(); ++index) { + mSymmetries.insert(mSymmetries.begin() + i + 1 + index, std::make_pair(childLength, newSymmetries[index])); + } + i += mSymmetries[j].second.size(); break; } } diff --git a/src/storage/dft/SymmetricUnits.h b/src/storage/dft/SymmetricUnits.h index 33c8efeae..82d747115 100644 --- a/src/storage/dft/SymmetricUnits.h +++ b/src/storage/dft/SymmetricUnits.h @@ -64,6 +64,7 @@ namespace storm { } void sortHierarchical(size_t parent, std::vector& candidates) { + // Find subsymmetries of current symmetry std::vector children; for (int i = candidates.size() - 1; i >= 0; --i) { size_t currentRoot = candidates[i]; @@ -74,16 +75,23 @@ namespace storm { candidates.erase(candidates.begin()+i); } } + + // Find child symmetries which are created by parent and other child symmetries for (size_t i = 0; i < children.size(); ++i) { - std::vector> possibleSymmetry = createSymmetry(groups.at(parent), groups.at(children[i]), 1); - for (size_t j = i + 1; j < children.size(); ++j) { - if (possibleSymmetry == groups.at(children[j])) { - STORM_LOG_TRACE("Child " << children[j] << " ignored as created by symmetries " << parent << " and " << children[j]); - groups.erase(children[j]); - children.erase(children.begin() + j); + // Iterate over all possible symmetry groups + for (size_t index = 1; index < groups.at(parent).front().size(); ++index) { + std::vector> possibleSymmetry = createSymmetry(groups.at(parent), groups.at(children[i]), index); + for (size_t j = i + 1; j < children.size(); ++j) { + if (possibleSymmetry == groups.at(children[j])) { + STORM_LOG_TRACE("Child " << children[j] << " ignored as created by symmetries " << parent << " and " << children[i]); + groups.erase(children[j]); + children.erase(children.begin() + j); + } } } } + + // Apply sorting recursively while (!children.empty()) { // Insert largest element size_t largestChild = children.back(); @@ -98,9 +106,9 @@ namespace storm { for (auto const& cl : groups) { sortedGroups.push_back(cl.first); } - // Sort by length of symmetry + // Sort by length of symmetry or (if equal) by lower first element std::sort(sortedGroups.begin(), sortedGroups.end(), [&](const size_t left, const size_t right) { - return groups.at(left).size() < groups.at(right).size(); + return groups.at(left).size() < groups.at(right).size() || (groups.at(left).size() == groups.at(right).size() && groups.at(left).front().front() < groups.at(left).front().front()); }); // Sort hierarchical From 5a066b9ae0a36dfea6252165fbdec9fb0cb83894 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 12 Mar 2016 15:32:48 +0100 Subject: [PATCH 210/246] Used duplicate variable name Former-commit-id: 3f47dfb3d1f9927ab9bd60897c56ad0b000610b4 --- src/storage/dft/SymmetricUnits.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/storage/dft/SymmetricUnits.h b/src/storage/dft/SymmetricUnits.h index 82d747115..643305045 100644 --- a/src/storage/dft/SymmetricUnits.h +++ b/src/storage/dft/SymmetricUnits.h @@ -48,9 +48,9 @@ namespace storm { std::vector> createSymmetry(std::vector> parentSymmetry, std::vector> childSymmetry, size_t index) { std::vector> result; - for (std::vector childSymmetry : childSymmetry) { + for (std::vector childSym : childSymmetry) { std::vector symmetry; - for (size_t child : childSymmetry) { + for (size_t child : childSym) { int bijectionValue = applySymmetry(parentSymmetry, child, index); if (bijectionValue >= 0) { symmetry.push_back(bijectionValue); @@ -135,4 +135,4 @@ namespace storm { return os; } } -} \ No newline at end of file +} From 6ca6ab27e89c1e4d4d25c9ce80c4d34312889a37 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 12 Mar 2016 18:02:30 +0100 Subject: [PATCH 211/246] Activate failed representatives Former-commit-id: dcda573443bcec1efb4e1ab98c8171d9b7b3d720 --- src/storage/dft/DFTState.cpp | 13 ++++++++++++- src/storage/dft/elements/DFTElement.cpp | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index c17bad0b6..558192678 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -123,16 +123,28 @@ namespace storm { template void DFTState::setFailed(size_t id) { + if (mDft.isRepresentative(id)) { + // Activate failed element + activate(id); + } mStatus.set(mStateGenerationInfo.getStateIndex(id)); } template void DFTState::setFailsafe(size_t id) { + if (mDft.isRepresentative(id)) { + // Activate failed element + activate(id); + } mStatus.set(mStateGenerationInfo.getStateIndex(id)+1); } template void DFTState::setDontCare(size_t id) { + if (mDft.isRepresentative(id)) { + // Activate failed element + activate(id); + } mStatus.setFromInt(mStateGenerationInfo.getStateIndex(id), 2, static_cast(DFTElementState::DontCare) ); } @@ -207,7 +219,6 @@ namespace storm { template void DFTState::activate(size_t repr) { size_t activationIndex = mStateGenerationInfo.getSpareActivationIndex(repr); - assert(!mStatus[activationIndex]); mStatus.set(activationIndex); } diff --git a/src/storage/dft/elements/DFTElement.cpp b/src/storage/dft/elements/DFTElement.cpp index 803199508..1f0ab892d 100644 --- a/src/storage/dft/elements/DFTElement.cpp +++ b/src/storage/dft/elements/DFTElement.cpp @@ -37,7 +37,7 @@ namespace storm { } state.setDontCare(mId); - if (hasParentSpare && !state.isActive(mId)) { + if (hasParentSpare) { // Activate child for consistency in failed spares state.activate(mId); } From db3c40e6d738f026b791ee47ad89924569dd8e40 Mon Sep 17 00:00:00 2001 From: Mavo Date: Sat, 12 Mar 2016 18:46:01 +0100 Subject: [PATCH 212/246] Fixed bugs Former-commit-id: d602972afc29bbdeb6c6eb338a393c60d3135ce7 --- src/storage/dft/DFTState.cpp | 10 +--------- src/storage/dft/DFTStateGenerationInfo.h | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 558192678..24291b446 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -123,26 +123,18 @@ namespace storm { template void DFTState::setFailed(size_t id) { - if (mDft.isRepresentative(id)) { - // Activate failed element - activate(id); - } mStatus.set(mStateGenerationInfo.getStateIndex(id)); } template void DFTState::setFailsafe(size_t id) { - if (mDft.isRepresentative(id)) { - // Activate failed element - activate(id); - } mStatus.set(mStateGenerationInfo.getStateIndex(id)+1); } template void DFTState::setDontCare(size_t id) { if (mDft.isRepresentative(id)) { - // Activate failed element + // Activate dont care element activate(id); } mStatus.setFromInt(mStateGenerationInfo.getStateIndex(id), 2, static_cast(DFTElementState::DontCare) ); diff --git a/src/storage/dft/DFTStateGenerationInfo.h b/src/storage/dft/DFTStateGenerationInfo.h index e700d8700..513a6a7a0 100644 --- a/src/storage/dft/DFTStateGenerationInfo.h +++ b/src/storage/dft/DFTStateGenerationInfo.h @@ -98,7 +98,7 @@ namespace storm { for (size_t index = 0; index < newSymmetries.size(); ++index) { mSymmetries.insert(mSymmetries.begin() + i + 1 + index, std::make_pair(childLength, newSymmetries[index])); } - i += mSymmetries[j].second.size(); + i += newSymmetries.size(); break; } } From 9ae9700d5c9f4dbb5e1073b27f9bc1f712c60a04 Mon Sep 17 00:00:00 2001 From: sjunges Date: Sat, 12 Mar 2016 20:43:37 +0100 Subject: [PATCH 213/246] modularisation on and and or Former-commit-id: 50950ba49767282d35ac4b7dba78dc9c98af5f2b --- src/modelchecker/DFTAnalyser.h | 158 +++++++++++++++++++++++++++++++++ src/storage/dft/DFT.cpp | 40 +++++++++ src/storage/dft/DFT.h | 7 ++ src/storm-dyftee.cpp | 76 +++------------- 4 files changed, 218 insertions(+), 63 deletions(-) create mode 100644 src/modelchecker/DFTAnalyser.h diff --git a/src/modelchecker/DFTAnalyser.h b/src/modelchecker/DFTAnalyser.h new file mode 100644 index 000000000..93bc7c7b1 --- /dev/null +++ b/src/modelchecker/DFTAnalyser.h @@ -0,0 +1,158 @@ +#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 + +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) { + + // 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); + 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) { + std::cout << "check helper called" << std::endl; + bool invResults = false; + std::vector> dfts = {dft}; + std::vector res; + + if(allowModularisation) { + std::cout << dft.topLevelType() << std::endl; + if(dft.topLevelType() == storm::storage::DFTElementType::AND) { + std::cout << "top modularisation called AND" << std::endl; + dfts = dft.topModularisation(); + if(dfts.size() > 1) { + for(auto const ft : dfts) { + res.push_back(checkHelper(ft, formula, symred, allowModularisation)); + } + } + } + if(dft.topLevelType() == storm::storage::DFTElementType::OR) { + std::cout << "top modularisation called OR" << std::endl; + dfts = dft.topModularisation(); + if(dfts.size() > 1) { + for(auto const ft : dfts) { + res.push_back(checkHelper(ft, formula, symred, allowModularisation)); + } + } + invResults = true; + } + } + if(res.empty()) { + // Model based modularisation. + auto const& models = buildMarkovModels(dfts, formula, symred); + + + 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); + } + } + + ValueType result = storm::utility::one(); + for(auto const& r : res) { + if(invResults) { + result *= storm::utility::one() - r; + } else { + result *= r; + } + } + if(invResults) { + return storm::utility::one() - result; + } + return result; + } + + + std::vector>> buildMarkovModels(std::vector> const& dfts, std::shared_ptr const& formula, bool symred) { + 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); + 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; + } + +}; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index dd771f230..482e8203c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -247,6 +247,46 @@ namespace storm { return stateIndex; } + template + std::vector> DFT::topModularisation() const { + assert(isGate(mTopLevelIndex)); + auto const& children = getGate(mTopLevelIndex)->children(); + std::map> subdfts; + for(auto const& child : children) { + std::vector isubdft; + if(child->nrParents() > 1 || child->hasOutgoingDependencies()) { + return {*this}; + } + if (isGate(child->id())) { + isubdft = getGate(child->id())->independentSubDft(false); + } else { + assert(isBasicElement(child->id())); + if(!getBasicElement(child->id())->hasIngoingDependencies()) { + isubdft = {child->id()}; + } + + } + if(isubdft.empty()) { + return {*this}; + } else { + subdfts[child->id()] = isubdft; + } + } + + std::vector> res; + for(auto const& subdft : subdfts) { + DFTBuilder builder; + + for(size_t id : subdft.second) { + builder.copyElement(mElements[id]); + } + builder.setTopLevel(mElements[subdft.first]->name()); + res.push_back(builder.build()); + } + return res; + + } + template DFT DFT::optimize() const { std::vector modIdea = findModularisationRewrite(); diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index f28d244f0..0f4832fb5 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -95,6 +96,10 @@ namespace storm { return mTopLevelIndex; } + DFTElementType topLevelType() const { + return mElements[getTopLevelIndex()]->type(); + } + size_t getMaxSpareChildCount() const { return mMaxSpareChildCount; } @@ -187,6 +192,8 @@ namespace storm { return elements; } + std::vector> topModularisation() const; + bool isRepresentative(size_t id) const { for (auto const& parent : getElement(id)->parents()) { if (parent->isSpareGate()) { diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 1f170072b..f280bbebf 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -1,11 +1,7 @@ #include "logic/Formula.h" -#include "parser/DFTGalileoParser.h" #include "utility/initialize.h" -#include "builder/ExplicitDFTModelBuilder.h" -#include "modelchecker/results/CheckResult.h" #include "utility/storm.h" -#include "storage/dft/DFTIsomorphism.h" - +#include "modelchecker/DFTAnalyser.h" #include /*! @@ -15,71 +11,20 @@ * @param property PCTC formula capturing the property to check. */ template -void analyzeDFT(std::string filename, std::string property, bool symred = false) { +void analyzeDFT(std::string filename, std::string property, bool symred = false, bool allowModularisation = false) { storm::settings::SettingsManager& manager = storm::settings::mutableManager(); manager.setFromString(""); - // Building DFT - std::chrono::high_resolution_clock::time_point buildingStart = std::chrono::high_resolution_clock::now(); storm::parser::DFTGalileoParser parser; storm::storage::DFT dft = parser.parseDFT(filename); std::vector> parsedFormulas = storm::parseFormulasForExplicit(property); std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); - // Optimizing DFT - dft = dft.optimize(); - 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(); - - // Building Markov Automaton - std::cout << "Building Model..." << std::endl; - storm::builder::ExplicitDFTModelBuilder builder(dft, symmetries); - 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(); - - // Bisimulation - if (model->isOfType(storm::models::ModelType::Ctmc)) { - std::cout << "Bisimulation..." << std::endl; - model = storm::performDeterministicSparseBisimulationMinimization>(model->template as>(), formulas, 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; - std::chrono::high_resolution_clock::time_point bisimulationEnd = std::chrono::high_resolution_clock::now(); - - // Model checking - std::cout << "Model checking..." << std::endl; - std::unique_ptr result(storm::verifySparseModel(model, formulas[0])); - assert(result); - result->filter(storm::modelchecker::ExplicitQualitativeCheckResult(model->getInitialStates())); - - // Times - std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now(); - std::chrono::duration buildingTime = buildingEnd - buildingStart; - std::chrono::duration explorationTime = explorationEnd - buildingEnd; - std::chrono::duration bisimulationTime = bisimulationEnd - explorationEnd; - std::chrono::duration modelCheckingTime = modelCheckingEnd - bisimulationEnd; - std::chrono::duration totalTime = modelCheckingEnd - buildingStart; - std::cout << "Times:" << std::endl; - std::cout << "Building:\t" << buildingTime.count() << std::endl; - std::cout << "Exploration:\t" << explorationTime.count() << std::endl; - std::cout << "Bisimulation:\t" << bisimulationTime.count() << std::endl; - std::cout << "Modelchecking:\t" << modelCheckingTime.count() << std::endl; - std::cout << "Total:\t\t" << totalTime.count() << std::endl; - std::cout << "Result: "; - std::cout << *result << std::endl; + DFTAnalyser analyser; + analyser.check(dft, formulas[0], symred, allowModularisation); + analyser.printTimings(); + analyser.printResult(); } /*! @@ -100,6 +45,8 @@ int main(int argc, char** argv) { bool parametric = false; bool symred = false; bool minimal = true; + bool allowModular = true; + bool enableModularisation = false; std::string filename = argv[1]; std::string operatorType = ""; std::string targetFormula = ""; @@ -112,6 +59,7 @@ int main(int argc, char** argv) { assert(targetFormula.empty()); operatorType = "ET"; targetFormula = "F \"failed\""; + allowModular = false; } else if (option == "--probability") { assert(targetFormula.empty()); operatorType = "P";; @@ -142,6 +90,8 @@ int main(int argc, char** argv) { pctlFormula = argv[i]; } else if (option == "--symred") { symred = true; + } else if (option == "--modularisation") { + enableModularisation = true; } else if (option == "--min") { minimal = true; } else if (option == "--max") { @@ -164,8 +114,8 @@ int main(int argc, char** argv) { std::cout << "Running " << (parametric ? "parametric " : "") << "DFT analysis on file " << filename << " with property " << pctlFormula << std::endl; if (parametric) { - analyzeDFT(filename, pctlFormula, symred); + analyzeDFT(filename, pctlFormula, symred, allowModular && enableModularisation ); } else { - analyzeDFT(filename, pctlFormula, symred); + analyzeDFT(filename, pctlFormula, symred, allowModular && enableModularisation); } } From e5fd60449830058b3fc95f2097bc03ac29548c7b Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 14 Mar 2016 16:42:53 +0100 Subject: [PATCH 214/246] Flag for disabling DC propagation Former-commit-id: 1fa850ef266cc00bb51068934823a1ca95ff79da --- src/builder/ExplicitDFTModelBuilder.cpp | 4 ++-- src/builder/ExplicitDFTModelBuilder.h | 3 ++- src/modelchecker/DFTAnalyser.h | 12 ++++++------ src/storm-dyftee.cpp | 11 +++++++---- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index d57dec2e7..f5296a487 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -15,7 +15,7 @@ namespace storm { } template - ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, INITIAL_BUCKETSIZE) { + ExplicitDFTModelBuilder::ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries, bool enableDC) : mDft(dft), mStates(((mDft.stateVectorSize() / 64) + 1) * 64, INITIAL_BUCKETSIZE), enableDC(enableDC) { // stateVectorSize is bound for size of bitvector mStateGenerationInfo = std::make_shared(mDft.buildStateGenerationInfo(symmetries)); @@ -218,7 +218,7 @@ namespace storm { next->checkFailsafe(*newState, queues); } - while (!queues.dontCarePropagationDone()) { + while (enableDC && !queues.dontCarePropagationDone()) { DFTElementPointer next = queues.nextDontCarePropagation(); next->checkDontCareAnymore(*newState, queues); } diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 7fc343be2..4f1dff514 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -55,6 +55,7 @@ namespace storm { std::vector> mPseudoStatesMapping; // vector of (id to concrete state, bitvector) size_t newIndex = 0; bool mergeFailedStates = true; + bool enableDC = true; size_t failedIndex = 0; size_t initialStateIndex = 0; @@ -65,7 +66,7 @@ namespace storm { std::set beLabels = {}; }; - ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries); + ExplicitDFTModelBuilder(storm::storage::DFT const& dft, storm::storage::DFTIndependentSymmetries const& symmetries, bool enableDC); std::shared_ptr> buildModel(LabelOptions const& labelOpts); diff --git a/src/modelchecker/DFTAnalyser.h b/src/modelchecker/DFTAnalyser.h index 93bc7c7b1..0bf9d491e 100644 --- a/src/modelchecker/DFTAnalyser.h +++ b/src/modelchecker/DFTAnalyser.h @@ -20,7 +20,7 @@ class DFTAnalyser { 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) { + 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(); @@ -29,7 +29,7 @@ public: // Optimizing DFT dft = dft.optimize(); std::vector> dfts; - checkResult = checkHelper(dft, formula, symred, allowModularisation); + checkResult = checkHelper(dft, formula, symred, allowModularisation, enableDC); totalTime = std::chrono::high_resolution_clock::now() - totalStart; @@ -37,7 +37,7 @@ public: } private: - ValueType checkHelper(storm::storage::DFT const& dft , std::shared_ptr const& formula, bool symred = true, bool allowModularisation = true) { + 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}; @@ -67,7 +67,7 @@ private: } if(res.empty()) { // Model based modularisation. - auto const& models = buildMarkovModels(dfts, formula, symred); + auto const& models = buildMarkovModels(dfts, formula, symred, enableDC); for (auto const& model : models) { @@ -98,7 +98,7 @@ private: } - std::vector>> buildMarkovModels(std::vector> const& dfts, std::shared_ptr const& formula, bool symred) { + 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(); @@ -116,7 +116,7 @@ private: // Building Markov Automaton std::cout << "Building Model..." << std::endl; - storm::builder::ExplicitDFTModelBuilder builder(dft, symmetries); + 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); diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index f280bbebf..ea0da3a14 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -11,7 +11,7 @@ * @param property PCTC formula capturing the property to check. */ template -void analyzeDFT(std::string filename, std::string property, bool symred = false, bool allowModularisation = false) { +void analyzeDFT(std::string filename, std::string property, bool symred = false, bool allowModularisation = false, bool enableDC = true) { storm::settings::SettingsManager& manager = storm::settings::mutableManager(); manager.setFromString(""); @@ -22,7 +22,7 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false, assert(formulas.size() == 1); DFTAnalyser analyser; - analyser.check(dft, formulas[0], symred, allowModularisation); + analyser.check(dft, formulas[0], symred, allowModularisation, enableDC); analyser.printTimings(); analyser.printResult(); } @@ -47,6 +47,7 @@ int main(int argc, char** argv) { bool minimal = true; bool allowModular = true; bool enableModularisation = false; + bool disableDC = false; std::string filename = argv[1]; std::string operatorType = ""; std::string targetFormula = ""; @@ -92,6 +93,8 @@ int main(int argc, char** argv) { symred = true; } else if (option == "--modularisation") { enableModularisation = true; + } else if (option == "--disabledc") { + disableDC = true; } else if (option == "--min") { minimal = true; } else if (option == "--max") { @@ -114,8 +117,8 @@ int main(int argc, char** argv) { std::cout << "Running " << (parametric ? "parametric " : "") << "DFT analysis on file " << filename << " with property " << pctlFormula << std::endl; if (parametric) { - analyzeDFT(filename, pctlFormula, symred, allowModular && enableModularisation ); + analyzeDFT(filename, pctlFormula, symred, allowModular && enableModularisation, !disableDC ); } else { - analyzeDFT(filename, pctlFormula, symred, allowModular && enableModularisation); + analyzeDFT(filename, pctlFormula, symred, allowModular && enableModularisation, !disableDC); } } From e390e1c39d01c5ad6fc98d6a54dd0a87e1b0f680 Mon Sep 17 00:00:00 2001 From: sjunges Date: Mon, 14 Mar 2016 20:47:14 +0100 Subject: [PATCH 215/246] several updates for better modularisation and support for VOT-modularisation Former-commit-id: 97d5d03a868debcea7ae474b6ae070bfa9247ea4 --- src/modelchecker/DFTAnalyser.h | 74 +++++++++++++++++++++++++--------- src/storage/dft/DFT.cpp | 4 +- src/storage/dft/DFT.h | 4 ++ src/utility/bitoperations.h | 17 ++++++++ 4 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 src/utility/bitoperations.h diff --git a/src/modelchecker/DFTAnalyser.h b/src/modelchecker/DFTAnalyser.h index 93bc7c7b1..de128af64 100644 --- a/src/modelchecker/DFTAnalyser.h +++ b/src/modelchecker/DFTAnalyser.h @@ -6,6 +6,7 @@ #include "modelchecker/results/CheckResult.h" #include "utility/storm.h" #include "storage/dft/DFTIsomorphism.h" +#include "utility/bitoperations.h" #include @@ -42,28 +43,42 @@ private: 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) { - std::cout << dft.topLevelType() << std::endl; if(dft.topLevelType() == storm::storage::DFTElementType::AND) { - std::cout << "top modularisation called AND" << std::endl; + STORM_LOG_TRACE("top modularisation called AND"); dfts = dft.topModularisation(); - if(dfts.size() > 1) { - for(auto const ft : dfts) { - res.push_back(checkHelper(ft, formula, symred, allowModularisation)); - } - } + STORM_LOG_TRACE("Modularsation into " << dfts.size() << " submodules."); + nrK = dfts.size(); + nrM = dfts.size(); } if(dft.topLevelType() == storm::storage::DFTElementType::OR) { - std::cout << "top modularisation called OR" << std::endl; + STORM_LOG_TRACE("top modularisation called OR"); dfts = dft.topModularisation(); - if(dfts.size() > 1) { - for(auto const ft : dfts) { - res.push_back(checkHelper(ft, formula, symred, allowModularisation)); - } - } + 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. @@ -82,14 +97,33 @@ private: res.push_back(result->asExplicitQuantitativeCheckResult().getValueMap().begin()->second); } } + if(nrM <= 1) { + // No modularisation done. + assert(res.size()==1); + return res[0]; + } - ValueType result = storm::utility::one(); - for(auto const& r : res) { - if(invResults) { - result *= storm::utility::one() - r; - } else { - result *= r; - } + 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; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 482e8203c..4111a2113 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -261,8 +261,8 @@ namespace storm { isubdft = getGate(child->id())->independentSubDft(false); } else { assert(isBasicElement(child->id())); - if(!getBasicElement(child->id())->hasIngoingDependencies()) { - isubdft = {child->id()}; + if(getBasicElement(child->id())->hasIngoingDependencies()) { + return {*this}; } } diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 0f4832fb5..d82c45dfa 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -167,6 +167,10 @@ namespace storm { return std::static_pointer_cast const>(mElements[index]); } + std::shared_ptr const> getTopLevelGate() const { + return getGate(mTopLevelIndex); + } + std::shared_ptr const> getGate(size_t index) const { assert(isGate(index)); return std::static_pointer_cast const>(mElements[index]); diff --git a/src/utility/bitoperations.h b/src/utility/bitoperations.h new file mode 100644 index 000000000..55456dd61 --- /dev/null +++ b/src/utility/bitoperations.h @@ -0,0 +1,17 @@ +#pragma once + +inline size_t smallestIntWithNBitsSet(size_t n) { + assert(sizeof(size_t) == 8); + assert(n < 64); // TODO fix this for 32 bit architectures! + if(n==0) return static_cast(0); + return (1 << n) - 1; +} + +inline size_t nextBitPermutation(size_t v) { + if(v==0) return static_cast(0); + // From https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation + unsigned int t = (v | (v - 1)) + 1; + return t | ((((t & -t) / (v & -v)) >> 1) - 1); +} + + \ No newline at end of file From 2c15c897510daa9a517d7a8839a0b3f6326d1256 Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 14 Mar 2016 23:15:07 +0100 Subject: [PATCH 216/246] No DC propagation for failed toplevel Former-commit-id: a2cf30e0718699411e8972f2c2b8bbb3de6b9455 --- src/builder/ExplicitDFTModelBuilder.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index f5296a487..09fde00ef 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -212,21 +212,23 @@ namespace storm { if(newState->isInvalid()) { continue; } - - while (!queues.failsafePropagationDone()) { + bool dftFailed = newState->hasFailed(mDft.getTopLevelIndex()); + + while (!dftFailed && !queues.failsafePropagationDone()) { DFTGatePointer next = queues.nextFailsafePropagation(); next->checkFailsafe(*newState, queues); } - while (enableDC && !queues.dontCarePropagationDone()) { + while (!dftFailed && enableDC && !queues.dontCarePropagationDone()) { DFTElementPointer next = queues.nextDontCarePropagation(); next->checkDontCareAnymore(*newState, queues); } // Update failable dependencies - newState->updateFailableDependencies(nextBE->id()); + if (!dftFailed) { + newState->updateFailableDependencies(nextBE->id()); + } - bool dftFailed = newState->hasFailed(mDft.getTopLevelIndex()); uint_fast64_t newStateId; if(dftFailed && mergeFailedStates) { newStateId = failedIndex; From 25e2a9c070110b5346b1f086a5d2e726e5f67c7f Mon Sep 17 00:00:00 2001 From: Mavo Date: Mon, 14 Mar 2016 23:52:26 +0100 Subject: [PATCH 217/246] Removed assertion Former-commit-id: a6a64068084841907a4ba7c3cb77a63e76b8ebd3 --- src/storage/dft/DFT.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 4111a2113..653a5dc78 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -26,23 +26,18 @@ namespace storm { } else if (elem->isSpareGate()) { ++mNrOfSpares; - bool firstChild = true; mMaxSpareChildCount = std::max(mMaxSpareChildCount, std::static_pointer_cast>(elem)->children().size()); for(auto const& spareReprs : std::static_pointer_cast>(elem)->children()) { std::set module = {spareReprs->id()}; spareReprs->extendSpareModule(module); std::vector sparesAndBes; for(size_t modelem : module) { - if (spareReprs->id() != modelem && (isRepresentative(modelem) || (!firstChild && mTopLevelIndex == modelem))) { - STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Module for '" << spareReprs->name() << "' contains more than one representative."); - } if(mElements[modelem]->isSpareGate() || mElements[modelem]->isBasicElement()) { sparesAndBes.push_back(modelem); mRepresentants.insert(std::make_pair(modelem, spareReprs->id())); } } mSpareModules.insert(std::make_pair(spareReprs->id(), sparesAndBes)); - firstChild = false; } } else if (elem->isDependency()) { From d68829602253e6fb01f5ce6fcd7bbfd6bf68f195 Mon Sep 17 00:00:00 2001 From: sjunges Date: Tue, 15 Mar 2016 00:21:10 +0100 Subject: [PATCH 218/246] even more modularisation oppurtunaties are now taken Former-commit-id: de8fd4c848df80c14380437fe6847eacab504d19 --- src/modelchecker/DFTAnalyser.h | 5 ++--- src/storage/dft/DFT.cpp | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/modelchecker/DFTAnalyser.h b/src/modelchecker/DFTAnalyser.h index 0058f41f0..519b8090a 100644 --- a/src/modelchecker/DFTAnalyser.h +++ b/src/modelchecker/DFTAnalyser.h @@ -21,15 +21,14 @@ class DFTAnalyser { 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) { + void check(storm::storage::DFT const& origDft , 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; + storm::storage::DFT dft = origDft.optimize(); checkResult = checkHelper(dft, formula, symred, allowModularisation, enableDC); totalTime = std::chrono::high_resolution_clock::now() - totalStart; diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 4111a2113..b679b8a81 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -255,6 +255,7 @@ namespace storm { for(auto const& child : children) { std::vector isubdft; if(child->nrParents() > 1 || child->hasOutgoingDependencies()) { + STORM_LOG_TRACE("child " << child->name() << "does not allow modularisation."); return {*this}; } if (isGate(child->id())) { @@ -262,7 +263,10 @@ namespace storm { } else { assert(isBasicElement(child->id())); if(getBasicElement(child->id())->hasIngoingDependencies()) { + STORM_LOG_TRACE("child " << child->name() << "does not allow modularisation."); return {*this}; + } else { + isubdft = {child->id()}; } } From 4db05a7c208a14d137d68c4c238b806bcfa64ae4 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 15 Mar 2016 15:50:46 +0100 Subject: [PATCH 219/246] Fixed bug with wrong dormancyFactor when copying elements Former-commit-id: 3c2ddcc08a23ecc1184c76eaa31539c0f03cacd1 --- src/storage/dft/DFTBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index ea273e234..8241ea70a 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -226,7 +226,7 @@ namespace storm { std::shared_ptr> be = std::static_pointer_cast>(element); ValueType dormancyFactor = storm::utility::zero(); if (!storm::utility::isZero(be->passiveFailureRate())) { - dormancyFactor = be->activeFailureRate() / be->passiveFailureRate(); + dormancyFactor = be->passiveFailureRate() / be->activeFailureRate(); } addBasicElement(be->name(), be->activeFailureRate(), dormancyFactor); break; From ebbc4ce7b4b9f2887ecb578ee1d443da3564a8f2 Mon Sep 17 00:00:00 2001 From: Mavo Date: Tue, 15 Mar 2016 18:09:24 +0100 Subject: [PATCH 220/246] Fixed compile issues introduced in merge Former-commit-id: 059b7c84b3b2c7fd9088657621fcbc75c2bf06d1 --- .../csl/SparseCtmcCslModelChecker.cpp | 6 +- .../csl/SparseCtmcCslModelChecker.h | 2 +- .../csl/helper/SparseCtmcCslHelper.cpp | 6 +- .../csl/helper/SparseCtmcCslHelper.h | 6 +- src/parser/FormulaParser.cpp | 6 +- src/storage/BitVector.cpp | 81 ++++++++++--------- src/storage/FlexibleSparseMatrix.cpp | 10 +-- src/storage/FlexibleSparseMatrix.h | 12 +-- src/storage/SparseMatrix.cpp | 64 +++++---------- src/storm-dyftee.cpp | 2 +- src/utility/storm.h | 8 +- 11 files changed, 93 insertions(+), 110 deletions(-) diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp index e3cea0fb6..8356620c1 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.cpp @@ -34,7 +34,7 @@ namespace storm { template bool SparseCtmcCslModelChecker::canHandle(CheckTask const& checkTask) const { storm::logic::Formula const& formula = checkTask.getFormula(); - return formula.isInFragment(storm::logic::csrl().setGloballyFormulasAllowed(false).setLongRunAverageRewardFormulasAllowed(false).setLongRunAverageProbabilitiesAllowed(true).setExpectedTimeAllowed(true)); + return formula.isInFragment(storm::logic::csrl().setGloballyFormulasAllowed(false).setLongRunAverageRewardFormulasAllowed(false).setLongRunAverageProbabilitiesAllowed(true).setTimeAllowed(true)); } template @@ -114,12 +114,12 @@ namespace storm { } template - std::unique_ptr SparseCtmcCslModelChecker::computeExpectedTimes(CheckTask const& checkTask) { + std::unique_ptr SparseCtmcCslModelChecker::computeReachabilityTimes(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) { storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula(); std::unique_ptr subResultPointer = this->check(eventuallyFormula.getSubformula()); ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), this->getModel().getInitialStates(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), this->getModel().getInitialStates(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet(), *linearEquationSolverFactory); return std::unique_ptr(new ExplicitQuantitativeCheckResult(std::move(numericResult))); } diff --git a/src/modelchecker/csl/SparseCtmcCslModelChecker.h b/src/modelchecker/csl/SparseCtmcCslModelChecker.h index 4d838d4d8..802841dee 100644 --- a/src/modelchecker/csl/SparseCtmcCslModelChecker.h +++ b/src/modelchecker/csl/SparseCtmcCslModelChecker.h @@ -28,7 +28,7 @@ namespace storm { virtual std::unique_ptr computeInstantaneousRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; virtual std::unique_ptr computeReachabilityRewards(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; virtual std::unique_ptr computeLongRunAverageProbabilities(CheckTask const& checkTask) override; - virtual std::unique_ptr computeExpectedTimes(CheckTask const& checkTask) override; + virtual std::unique_ptr computeReachabilityTimes(storm::logic::RewardMeasureType rewardMeasureType, CheckTask const& checkTask) override; private: // An object that is used for solving linear equations and performing matrix-vector multiplication. diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp index ff04148aa..d0f8a1b69 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp @@ -656,7 +656,7 @@ namespace storm { } template - std::vector SparseCtmcCslHelper::computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { + std::vector SparseCtmcCslHelper::computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory) { // Compute expected time on CTMC by reduction to DTMC with rewards. storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); @@ -677,7 +677,7 @@ namespace storm { template - std::vector SparseCtmcCslHelper::computeExpectedTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative) { + std::vector SparseCtmcCslHelper::computeReachabilityTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative) { // Use "normal" function again, if RationalFunction finally is supported. // Compute expected time on CTMC by reduction to DTMC with rewards. storm::storage::SparseMatrix probabilityMatrix = computeProbabilityMatrix(rateMatrix, exitRateVector); @@ -704,7 +704,7 @@ namespace storm { #ifdef STORM_HAVE_CARL template std::vector SparseCtmcCslHelper::computeUntilProbabilitiesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool qualitative); - template std::vector SparseCtmcCslHelper::computeExpectedTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); + template std::vector SparseCtmcCslHelper::computeReachabilityTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); #endif } } diff --git a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h index 14a98f752..2b4dd6043 100644 --- a/src/modelchecker/csl/helper/SparseCtmcCslHelper.h +++ b/src/modelchecker/csl/helper/SparseCtmcCslHelper.h @@ -29,8 +29,8 @@ namespace storm { static std::vector computeLongRunAverageProbabilities(storm::storage::SparseMatrix const& probabilityMatrix, storm::storage::BitVector const& psiStates, std::vector const* exitRateVector, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& linearEquationSolverFactory); - static std::vector computeExpectedTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); - static std::vector computeExpectedTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); + static std::vector computeReachabilityTimes(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory const& minMaxLinearEquationSolverFactory); + static std::vector computeReachabilityTimesElimination(storm::storage::SparseMatrix const& rateMatrix, storm::storage::SparseMatrix const& backwardTransitions, std::vector const& exitRateVector, storm::storage::BitVector const& initialStates, storm::storage::BitVector const& targetStates, bool qualitative); /*! * Computes the matrix representing the transitions of the uniformized CTMC. @@ -82,4 +82,4 @@ namespace storm { } } -#endif /* STORM_MODELCHECKER_SPARSE_CTMC_CSL_MODELCHECKER_HELPER_H_ */ \ No newline at end of file +#endif /* STORM_MODELCHECKER_SPARSE_CTMC_CSL_MODELCHECKER_HELPER_H_ */ diff --git a/src/parser/FormulaParser.cpp b/src/parser/FormulaParser.cpp index 97614507a..22803d9c1 100644 --- a/src/parser/FormulaParser.cpp +++ b/src/parser/FormulaParser.cpp @@ -280,7 +280,7 @@ namespace storm { booleanLiteralFormula = (qi::lit("true")[qi::_a = true] | qi::lit("false")[qi::_a = false])[qi::_val = phoenix::bind(&FormulaParserGrammar::createBooleanLiteralFormula, phoenix::ref(*this), qi::_a)]; booleanLiteralFormula.name("boolean literal formula"); - operatorFormula = probabilityOperator | rewardOperator | longRunAverageOperator | expectedTimeOperator; + operatorFormula = probabilityOperator | rewardOperator | longRunAverageOperator | timeOperator; operatorFormula.name("operator formulas"); atomicStateFormula = booleanLiteralFormula | labelFormula | expressionFormula | (qi::lit("(") > stateFormula > qi::lit(")")) | operatorFormula; @@ -355,7 +355,7 @@ namespace storm { debug(probabilityOperator); debug(rewardOperator); debug(longRunAverageOperator); - debug(expectedTimeOperator); + debug(timeOperator); debug(pathFormulaWithoutUntil); debug(pathFormula); // debug(conditionalFormula); @@ -379,7 +379,7 @@ namespace storm { qi::on_error(probabilityOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(rewardOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(longRunAverageOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); - qi::on_error(expectedTimeOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); + qi::on_error(timeOperator, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(operatorInformation, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormulaWithoutUntil, handler(qi::_1, qi::_2, qi::_3, qi::_4)); qi::on_error(pathFormula, handler(qi::_1, qi::_2, qi::_3, qi::_4)); diff --git a/src/storage/BitVector.cpp b/src/storage/BitVector.cpp index f5aea6370..28f6bdcff 100644 --- a/src/storage/BitVector.cpp +++ b/src/storage/BitVector.cpp @@ -468,10 +468,10 @@ namespace storm { if (bitIndexInBucket < 62) { // bitIndexInBucket + 2 < 64 // If the value stops before the end of the bucket, we need to erase some lower bits. mask &= ~((1ull << (62 - (bitIndexInBucket))) - 1ull); - return (bucketVector[bucket] & mask) >> (62 - bitIndexInBucket); + return (buckets[bucket] & mask) >> (62 - bitIndexInBucket); } else { // In this case, it suffices to take the current mask. - return bucketVector[bucket] & mask; + return buckets[bucket] & mask; } } @@ -669,29 +669,29 @@ namespace storm { storm::storage::BitVector result(length, false); uint_fast64_t offset = start % 64; - uint_fast64_t bucketIndex = start / 64; - uint_fast64_t insertBucket = 0; + uint64_t* getBucket = buckets + (start / 64); + uint64_t* insertBucket = result.buckets; uint_fast64_t getValue; uint_fast64_t writeValue = 0; uint_fast64_t noBits = 0; if (offset == 0) { // Copy complete buckets - for ( ; noBits + 64 <= length; ++bucketIndex, ++insertBucket, noBits += 64) { - result.bucketVector[insertBucket] = bucketVector[bucketIndex]; + for ( ; noBits + 64 <= length; ++getBucket, ++insertBucket, noBits += 64) { + *insertBucket = *getBucket; } } else { //Get first bits up until next bucket - getValue = bucketVector[bucketIndex]; + getValue = *getBucket; writeValue = (getValue << offset); noBits += (64-offset); - ++bucketIndex; + ++getBucket; //Get complete buckets - for ( ; noBits + 64 <= length; ++bucketIndex, ++insertBucket, noBits += 64) { - getValue = bucketVector[bucketIndex]; + for ( ; noBits + 64 <= length; ++getBucket, ++insertBucket, noBits += 64) { + getValue = *getBucket; // Get bits till write bucket is full writeValue |= (getValue >> (64-offset)); - result.bucketVector[insertBucket] = writeValue; + *insertBucket = writeValue; // Get bits up until next bucket writeValue = (getValue << offset); } @@ -699,22 +699,23 @@ namespace storm { // Write last bits uint_fast64_t remainingBits = length - noBits; - assert(bucketIndex < bucketCount()); + assert(getBucket != buckets + bucketCount()); // Get remaining bits - getValue = (bucketVector[bucketIndex] >> (64-remainingBits)) << (64-remainingBits); + getValue = (*getBucket >> (64-remainingBits)) << (64-remainingBits); assert(remainingBits < 64); // Write bucket - assert(insertBucket < result.bucketCount()); + assert(insertBucket != result.buckets + result.bucketCount()); if (offset == 0) { - result.bucketVector[insertBucket]= getValue; + *insertBucket = getValue; } else { writeValue |= getValue >> (64-offset); - result.bucketVector[insertBucket] = writeValue; + *insertBucket = writeValue; if (remainingBits > offset) { // Write last bits in new value writeValue = (getValue << offset); - assert(insertBucket+1 < result.bucketCount()); - result.bucketVector[++insertBucket] = writeValue; + ++insertBucket; + assert(insertBucket != result.buckets + result.bucketCount()); + *insertBucket = writeValue; } } @@ -752,56 +753,58 @@ namespace storm { assert(start + other.bitCount <= bitCount); uint_fast64_t offset = start % 64; - uint_fast64_t bucketIndex = start / 64; - uint_fast64_t getBucket = 0; + uint64_t* insertBucket = buckets + (start / 64); + uint64_t* getBucket = other.buckets; uint_fast64_t getValue; uint_fast64_t writeValue = 0; uint_fast64_t noBits = 0; if (offset == 0) { // Copy complete buckets - for ( ; noBits + 64 <= other.bitCount; ++bucketIndex, ++getBucket, noBits += 64) { - bucketVector[bucketIndex] = other.bucketVector[getBucket]; + for ( ; noBits + 64 <= other.bitCount; ++insertBucket, ++getBucket, noBits += 64) { + *insertBucket = *getBucket; } } else { //Get first bits up until next bucket - getValue = other.bucketVector[getBucket]; - writeValue = (bucketVector[bucketIndex] >> (64-offset)) << (64-offset); + getValue = *getBucket; + writeValue = (*insertBucket >> (64-offset)) << (64-offset); writeValue |= (getValue >> offset); - bucketVector[bucketIndex] = writeValue; + *insertBucket = writeValue; noBits += (64-offset); - ++bucketIndex; + ++insertBucket; //Get complete buckets - for ( ; noBits + 64 <= other.bitCount; ++bucketIndex, noBits += 64) { + for ( ; noBits + 64 <= other.bitCount; ++insertBucket, noBits += 64) { // Get all remaining bits from other bucket writeValue = getValue << (64-offset); // Get bits from next bucket - getValue = other.bucketVector[++getBucket]; + ++getBucket; + getValue = *getBucket; writeValue |= getValue >> offset; - bucketVector[bucketIndex] = writeValue; + *insertBucket = writeValue; } } // Write last bits uint_fast64_t remainingBits = other.bitCount - noBits; assert(remainingBits < 64); - assert(bucketIndex < bucketCount()); - assert(getBucket < other.bucketCount()); + assert(insertBucket != buckets + bucketCount()); + assert(getBucket != other.buckets + other.bucketCount()); // Get remaining bits of bucket - getValue = other.bucketVector[getBucket]; + getValue = *getBucket; if (offset > 0) { getValue = getValue << (64-offset); } // Get unchanged part of bucket - writeValue = (bucketVector[bucketIndex] << remainingBits) >> remainingBits; + writeValue = (*insertBucket << remainingBits) >> remainingBits; if (remainingBits > offset && offset > 0) { // Remaining bits do not come from one bucket -> consider next bucket - assert(getBucket == other.bucketCount() - 2); - getValue |= other.bucketVector[++getBucket] >> offset; + ++getBucket; + assert(getBucket != other.buckets + other.bucketCount()); + getValue |= *getBucket >> offset; } // Write completely writeValue |= getValue; - bucketVector[bucketIndex] = writeValue; + *insertBucket = writeValue; #ifdef ASSERT_BITVECTOR // Check correctness of setter @@ -919,14 +922,14 @@ namespace storm { out << "bit vector(" << getNumberOfSetBits() << "/" << bitCount << ") "; uint_fast64_t index = 0; for ( ; index * 64 + 64 <= bitCount; ++index) { - std::bitset<64> tmp(bucketVector[index]); + std::bitset<64> tmp(buckets[index]); out << tmp << "|"; } // Print last bits if (index * 64 < bitCount) { - assert(index == bucketVector.size() - 1); - std::bitset<64> tmp(bucketVector[index]); + assert(index == bucketCount() - 1); + std::bitset<64> tmp(buckets[index]); for (size_t i = 0; i + index * 64 < bitCount; ++i) { // Bits are counted from rightmost in bitset out << tmp[63-i]; diff --git a/src/storage/FlexibleSparseMatrix.cpp b/src/storage/FlexibleSparseMatrix.cpp index 60422dc08..2e3a4e876 100644 --- a/src/storage/FlexibleSparseMatrix.cpp +++ b/src/storage/FlexibleSparseMatrix.cpp @@ -13,8 +13,8 @@ namespace storm { } template - FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()), nontrivialRowGrouping(matrix.hasNontrivialRowGrouping()) { - if (nontrivialRowGrouping) { + FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()), trivialRowGrouping(matrix.hasTrivialRowGrouping()) { + if (!trivialRowGrouping) { rowGroupIndices = matrix.getRowGroupIndices(); } for (index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { @@ -130,8 +130,8 @@ namespace storm { } template - bool FlexibleSparseMatrix::hasNontrivialRowGrouping() const { - return nontrivialRowGrouping; + bool FlexibleSparseMatrix::hasTrivialRowGrouping() const { + return trivialRowGrouping; } template @@ -208,7 +208,7 @@ namespace storm { } out << std::endl; - if (matrix.hasNontrivialRowGrouping()) { + if (!matrix.hasTrivialRowGrouping()) { // Iterate over all row groups FlexibleIndex rowGroupCount = matrix.getRowGroupCount(); for (FlexibleIndex rowGroup = 0; rowGroup < rowGroupCount; ++rowGroup) { diff --git a/src/storage/FlexibleSparseMatrix.h b/src/storage/FlexibleSparseMatrix.h index 28100e0a2..d5e6c2124 100644 --- a/src/storage/FlexibleSparseMatrix.h +++ b/src/storage/FlexibleSparseMatrix.h @@ -149,11 +149,11 @@ namespace storm { bool empty() const; /*! - * Retrieves whether the matrix has a (possibly) non-trivial row grouping. + * Retrieves whether the matrix has a (possibly) trivial row grouping. * - * @return True iff the matrix has a (possibly) non-trivial row grouping. + * @return True iff the matrix has a (possibly) trivial row grouping. */ - bool hasNontrivialRowGrouping() const; + bool hasTrivialRowGrouping() const; /*! * Creates a submatrix of the current matrix in place by dropping all rows and columns whose bits are not @@ -198,9 +198,9 @@ namespace storm { // The number of entries in the matrix. index_type nonzeroEntryCount; - // A flag that indicates whether the matrix has a non-trivial row-grouping, i.e. (possibly) more than one - // row per row group. - bool nontrivialRowGrouping; + // A flag indicating whether the matrix has a trivial row grouping. Note that this may be true and yet + // there may be row group indices, because they were requested from the outside. + bool trivialRowGrouping; // A vector indicating the row groups of the matrix. std::vector rowGroupIndices; diff --git a/src/storage/SparseMatrix.cpp b/src/storage/SparseMatrix.cpp index 69f12b696..d4028b55d 100644 --- a/src/storage/SparseMatrix.cpp +++ b/src/storage/SparseMatrix.cpp @@ -264,9 +264,26 @@ namespace storm { // Sort columns per row typename SparseMatrix::index_type endGroups; typename SparseMatrix::index_type endRows; - for (index_type group = 0; group < rowGroupIndices.size(); ++group) { - endGroups = group < rowGroupIndices.size()-1 ? rowGroupIndices[group+1] : rowIndications.size(); - for (index_type i = rowGroupIndices[group]; i < endGroups; ++i) { + + if (hasCustomRowGrouping) { + for (index_type group = 0; group < rowGroupIndices.get().size(); ++group) { + endGroups = group < rowGroupIndices.get().size()-1 ? rowGroupIndices.get()[group+1] : rowIndications.size(); + for (index_type i = rowGroupIndices.get()[group]; i < endGroups; ++i) { + endRows = i < rowIndications.size()-1 ? rowIndications[i+1] : columnsAndValues.size(); + // Sort the row + std::sort(columnsAndValues.begin() + rowIndications[i], columnsAndValues.begin() + endRows, + [](MatrixEntry const& a, MatrixEntry const& b) { + return a.getColumn() < b.getColumn(); + }); + // Assert no equal elements + assert(std::is_sorted(columnsAndValues.begin() + rowIndications[i], columnsAndValues.begin() + endRows, + [](MatrixEntry const& a, MatrixEntry const& b) { + return a.getColumn() <= b.getColumn(); + })); + } + } + } else { + for (index_type i = 0; i < rowIndications.size(); ++i) { endRows = i < rowIndications.size()-1 ? rowIndications[i+1] : columnsAndValues.size(); // Sort the row std::sort(columnsAndValues.begin() + rowIndications[i], columnsAndValues.begin() + endRows, @@ -279,47 +296,10 @@ namespace storm { return a.getColumn() <= b.getColumn(); })); } + } } - - template - bool SparseMatrixBuilder::replaceColumns(std::vector const& replacements, index_type offset) { - bool matrixChanged = false; - - // Walk through all rows. - for (index_type row = 0; row < rowIndications.size(); ++row) { - bool rowChanged = false; - index_type rowEnd = row < rowIndications.size()-1 ? rowIndications[row+1] : columnsAndValues.size(); - - for (auto it = columnsAndValues.begin() + rowIndications[row], ite = columnsAndValues.begin() + rowEnd; it != ite; ++it) { - if (it->getColumn() >= offset && it->getColumn() != replacements[it->getColumn() - offset]) { - it->setColumn(replacements[it->getColumn() - offset]); - rowChanged = true; - } - // Update highest column in a way that only works if the highest appearing index does not become - // lower during performing the replacement. - highestColumn = std::max(highestColumn, it->getColumn()); - } - - if (rowChanged) { - matrixChanged = true; - - // Sort the row. - std::sort(columnsAndValues.begin() + rowIndications[row], columnsAndValues.begin() + rowEnd, - [](MatrixEntry const& a, MatrixEntry const& b) { - return a.getColumn() < b.getColumn(); - }); - // Assert no equal elements - STORM_LOG_ASSERT(std::is_sorted(columnsAndValues.begin() + rowIndications[row], columnsAndValues.begin() + rowEnd, - [](MatrixEntry const& a, MatrixEntry const& b) { - return a.getColumn() <= b.getColumn(); - }), "Must not have different elements with the same column in a row."); - } - } - - return matrixChanged; - } - + template SparseMatrix::rows::rows(iterator begin, index_type entryCount) : beginIterator(begin), entryCount(entryCount) { // Intentionally left empty. diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index ea0da3a14..4f6c1f7e0 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -58,7 +58,7 @@ int main(int argc, char** argv) { parametric = true; } else if (option == "--expectedtime") { assert(targetFormula.empty()); - operatorType = "ET"; + operatorType = "T"; targetFormula = "F \"failed\""; allowModular = false; } else if (option == "--probability") { diff --git a/src/utility/storm.h b/src/utility/storm.h index 96087e30a..ea58705b8 100644 --- a/src/utility/storm.h +++ b/src/utility/storm.h @@ -356,10 +356,10 @@ namespace storm { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The parametric engine currently does not support MDPs."); } else if (model->getType() == storm::models::ModelType::Ctmc) { // Hack to avoid instantiating the CTMC Model Checker which currently does not work for rational functions - if (formula->isExpectedTimeOperatorFormula()) { + if (formula->isTimeOperatorFormula()) { // Compute expected time for pCTMCs - STORM_LOG_THROW(formula->asExpectedTimeOperatorFormula().getSubformula().isReachbilityExpectedTimeFormula(), storm::exceptions::NotSupportedException, "The parametric engine only supports Eventually formulas for this property"); - storm::logic::EventuallyFormula eventuallyFormula = formula->asExpectedTimeOperatorFormula().getSubformula().asEventuallyFormula(); + STORM_LOG_THROW(formula->asTimeOperatorFormula().getSubformula().isReachabilityTimeFormula(), storm::exceptions::NotSupportedException, "The parametric engine only supports reachability formulas for this property"); + storm::logic::EventuallyFormula eventuallyFormula = formula->asTimeOperatorFormula().getSubformula().asReachabilityTimeFormula(); STORM_LOG_THROW(eventuallyFormula.getSubformula().isInFragment(storm::logic::propositional()), storm::exceptions::NotSupportedException, "The parametric engine does not support nested formulas on CTMCs"); // Compute goal states @@ -368,7 +368,7 @@ namespace storm { std::unique_ptr subResultPointer = propositionalModelchecker.check(eventuallyFormula.getSubformula()); storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector(); - std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeExpectedTimesElimination(ctmc->getTransitionMatrix(), ctmc->getBackwardTransitions(), ctmc->getExitRateVector(), ctmc->getInitialStates(), targetStates, false); + std::vector numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimesElimination(ctmc->getTransitionMatrix(), ctmc->getBackwardTransitions(), ctmc->getExitRateVector(), ctmc->getInitialStates(), targetStates, false); result = std::unique_ptr(new storm::modelchecker::ExplicitQuantitativeCheckResult(std::move(numericResult))); } else if (formula->isProbabilityOperatorFormula()) { From bdad8aedd70da4d5eeaca136047c29799397771f Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 16 Mar 2016 16:59:30 +0100 Subject: [PATCH 221/246] Set dependencies to dont care after dependent event has failed Former-commit-id: 506f5c3107492d91fda2f90152a19c966cf453ef --- examples/dft/pdep_symmetry.dft | 4 ++-- src/builder/ExplicitDFTModelBuilder.cpp | 1 + src/storage/dft/DFTState.cpp | 26 +++++++++++++++++++++---- src/storage/dft/DFTState.h | 8 ++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/examples/dft/pdep_symmetry.dft b/examples/dft/pdep_symmetry.dft index 43224d790..5c9254aa5 100644 --- a/examples/dft/pdep_symmetry.dft +++ b/examples/dft/pdep_symmetry.dft @@ -2,8 +2,8 @@ toplevel "A"; "A" and "B" "B'"; "B" and "C" "D" "PDEP"; "B'" and "C'" "D'" "PDEP'"; -"PDEP" pdep=0.6 "B" "C"; -"PDEP'" pdep=0.6 "B'" "C'"; +"PDEP" pdep=0.6 "C" "D"; +"PDEP'" pdep=0.6 "C'" "D'"; "C" lambda=0.5 dorm=0; "D" lambda=0.5 dorm=0; "C'" lambda=0.5 dorm=0; diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 09fde00ef..103e87af3 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -227,6 +227,7 @@ namespace storm { // Update failable dependencies if (!dftFailed) { newState->updateFailableDependencies(nextBE->id()); + newState->updateDontCareDependencies(nextBE->id()); } uint_fast64_t newStateId; diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 24291b446..1468a36ff 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -142,14 +142,21 @@ namespace storm { template void DFTState::setDependencySuccessful(size_t id) { - // No distinction between successful dependency and no dependency at all - // => we do not set bit - //mStatus.set(mStateGenerationInfo.mIdToStateIndex(id)); + // Only distinguish between passive and dont care dependencies + //mStatus.set(mStateGenerationInfo.getStateIndex(id)); + setDependencyDontCare(id); } template void DFTState::setDependencyUnsuccessful(size_t id) { - mStatus.set(mStateGenerationInfo.getStateIndex(id)+1); + // Only distinguish between passive and dont care dependencies + //mStatus.set(mStateGenerationInfo.getStateIndex(id)+1); + setDependencyDontCare(id); + } + + template + void DFTState::setDependencyDontCare(size_t id) { + mStatus.setFromInt(mStateGenerationInfo.getStateIndex(id), 2, static_cast(DFTDependencyState::DontCare)); } template @@ -176,6 +183,17 @@ namespace storm { } return nrFailableDependencies() > 0; } + + template + void DFTState::updateDontCareDependencies(size_t id) { + assert(mDft.isBasicElement(id)); + assert(hasFailed(id)); + + for (auto dependency : mDft.getBasicElement(id)->ingoingDependencies()) { + assert(dependency->dependentEvent()->id() == id); + setDependencyDontCare(dependency->id()); + } + } template std::pair const>, bool> DFTState::letNextBEFail(size_t index) diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index faf183411..1311d74ae 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -79,6 +79,8 @@ namespace storm { void setDependencyUnsuccessful(size_t id); + void setDependencyDontCare(size_t id); + void beNoLongerFailable(size_t id); void activate(size_t repr); @@ -162,6 +164,12 @@ namespace storm { * @return true if failable dependent events exist */ bool updateFailableDependencies(size_t id); + + /** + * Sets all dependencies dont care whose dependent event is the newly failed BE. + * @param id Id of the newly failed element + */ + void updateDontCareDependencies(size_t id); /** * Sets the next BE as failed From 7c60e4275d98b5e207f956492ec9d5efa48ceb01 Mon Sep 17 00:00:00 2001 From: Mavo Date: Wed, 16 Mar 2016 18:18:53 +0100 Subject: [PATCH 222/246] Some more parametric DFT examples Former-commit-id: a2401c9453242663bb864d8e53a94efeae2a0b4c --- examples/dft/nonmonoton_param.dft | 8 ++++++++ examples/dft/spare_param.dft | 9 +++++++++ examples/dft/symmetry_param.dft | 10 ++++++++++ 3 files changed, 27 insertions(+) create mode 100644 examples/dft/nonmonoton_param.dft create mode 100644 examples/dft/spare_param.dft create mode 100644 examples/dft/symmetry_param.dft diff --git a/examples/dft/nonmonoton_param.dft b/examples/dft/nonmonoton_param.dft new file mode 100644 index 000000000..e83f3b012 --- /dev/null +++ b/examples/dft/nonmonoton_param.dft @@ -0,0 +1,8 @@ +param x; +param y; +toplevel "A"; +"A" or "B" "Z"; +"B" pand "D" "S"; +"Z" lambda=y dorm=0; +"D" lambda=100 dorm=0; +"S" lambda=100*x dorm=0; diff --git a/examples/dft/spare_param.dft b/examples/dft/spare_param.dft new file mode 100644 index 000000000..5378b13d2 --- /dev/null +++ b/examples/dft/spare_param.dft @@ -0,0 +1,9 @@ +param x; +param y; +toplevel "SF"; +"SF" or "FW" "BW"; +"FW" wsp "W1" "WS"; +"BW" wsp "W2" "WS"; +"W1" lambda=x dorm=0; +"W2" lambda=1 dorm=0; +"WS" lambda=y dorm=0; diff --git a/examples/dft/symmetry_param.dft b/examples/dft/symmetry_param.dft new file mode 100644 index 000000000..412968c80 --- /dev/null +++ b/examples/dft/symmetry_param.dft @@ -0,0 +1,10 @@ +param x; +param y; +toplevel "A"; +"A" and "B" "B'"; +"B" and "C" "D"; +"B'" and "C'" "D'"; +"C" lambda=x dorm=0; +"D" lambda=y dorm=0; +"C'" lambda=x dorm=0; +"D'" lambda=y dorm=0; From fe7037e7fd7d151509ae186c0371bf242b21d22f Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Mar 2016 10:47:50 +0100 Subject: [PATCH 223/246] Support for POR (priority or) Former-commit-id: f0e782bcb1024ff36a6afcb3989fb132b8e56a6c --- src/parser/DFTGalileoParser.cpp | 2 ++ src/storage/dft/elements/DFTPor.h | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/parser/DFTGalileoParser.cpp b/src/parser/DFTGalileoParser.cpp index 65ad82437..0a0aa5b32 100644 --- a/src/parser/DFTGalileoParser.cpp +++ b/src/parser/DFTGalileoParser.cpp @@ -100,6 +100,8 @@ namespace storm { success = builder.addVotElement(name, threshold, childNames); } else if (tokens[1] == "pand") { success = builder.addPandElement(name, childNames); + } else if (tokens[1] == "por") { + success = builder.addPorElement(name, childNames); } else if (tokens[1] == "wsp" || tokens[1] == "csp") { success = builder.addSpareElement(name, childNames); } else if (tokens[1] == "seq") { diff --git a/src/storage/dft/elements/DFTPor.h b/src/storage/dft/elements/DFTPor.h index 1aaa943b0..c37331354 100644 --- a/src/storage/dft/elements/DFTPor.h +++ b/src/storage/dft/elements/DFTPor.h @@ -11,11 +11,27 @@ namespace storm { {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(false); + if(state.isOperational(this->mId)) { + if (state.hasFailed(this->mChildren.front()->id())) { + // First child has failed before others + this->fail(state, queues); + } else { + for (size_t i = 1; i < this->nrChildren(); ++i) { + if (state.hasFailed(this->mChildren[i]->id())) { + // Child has failed before first child + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + } + } + } + } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { - assert(false); + if (state.isFailsafe(this->mChildren.front()->id())) { + this->failsafe(state, queues); + this->childrenDontCare(state, queues); + } } virtual DFTElementType type() const override { From 5796da9a5cc81be97f662561fc5425b06de67f51 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Mar 2016 11:28:14 +0100 Subject: [PATCH 224/246] Refactoring Former-commit-id: ab8665d114efa8f314bb15ebe1e0c6507d06a8f8 --- src/builder/ExplicitDFTModelBuilder.cpp | 115 +++++++++++------------- src/builder/ExplicitDFTModelBuilder.h | 2 + 2 files changed, 56 insertions(+), 61 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 103e87af3..7f892a822 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -234,48 +234,7 @@ namespace storm { if(dftFailed && mergeFailedStates) { newStateId = failedIndex; } else { - // Order state by symmetry - STORM_LOG_TRACE("Check for symmetry: " << mDft.getStateString(newState)); - bool changed = newState->orderBySymmetry(); - STORM_LOG_TRACE("State " << (changed ? "changed to " : "did not change") << (changed ? mDft.getStateString(newState) : "")); - - // Check if state already exists - if (mStates.contains(newState->status())) { - // State already exists - newStateId = mStates.getValue(newState->status()); - STORM_LOG_TRACE("State " << mDft.getStateString(newState) << " with id " << newStateId << " already exists"); - - // Check if possible pseudo state can be created now - if (!changed && newStateId >= OFFSET_PSEUDO_STATE) { - newStateId = newStateId - OFFSET_PSEUDO_STATE; - assert(newStateId < mPseudoStatesMapping.size()); - if (mPseudoStatesMapping[newStateId].first == 0) { - // Create pseudo state now - assert(mPseudoStatesMapping[newStateId].second == newState->status()); - newState->setId(newIndex++); - mPseudoStatesMapping[newStateId].first = newState->getId(); - newStateId = newState->getId(); - mStates.setOrAdd(newState->status(), newStateId); - stateQueue.push(newState); - STORM_LOG_TRACE("Now create state " << mDft.getStateString(newState) << " with id " << newStateId); - } - } - } else { - // New state - if (changed) { - // Remember to create state later on - newState->setId(mPseudoStatesMapping.size() + OFFSET_PSEUDO_STATE); - mPseudoStatesMapping.push_back(std::make_pair(0, newState->status())); - newStateId = mStates.findOrAdd(newState->status(), newState->getId()); - STORM_LOG_TRACE("New state for later creation: " << mDft.getStateString(newState)); - } else { - // Create new state - newState->setId(newIndex++); - newStateId = mStates.findOrAdd(newState->status(), newState->getId()); - STORM_LOG_TRACE("New state: " << mDft.getStateString(newState)); - stateQueue.push(newState); - } - } + newStateId = addState(newState, stateQueue); } // Set transitions @@ -286,25 +245,10 @@ namespace storm { STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newStateId << " with probability " << dependency->probability()); if (!storm::utility::isOne(dependency->probability())) { - // TODO Matthias: use symmetry as well // Add transition to state where dependency was unsuccessful DFTStatePointer unsuccessfulState = std::make_shared>(*state); unsuccessfulState->letDependencyBeUnsuccessful(smallest-1); - uint_fast64_t unsuccessfulStateId; - if (mStates.contains(unsuccessfulState->status())) { - // Unsuccessful state already exists - unsuccessfulStateId = mStates.getValue(unsuccessfulState->status()); - STORM_LOG_TRACE("State " << mDft.getStateString(unsuccessfulState) << " with id " << unsuccessfulStateId << " already exists"); - } else { - // New unsuccessful state - unsuccessfulState->setId(newIndex++); - unsuccessfulStateId = mStates.findOrAdd(unsuccessfulState->status(), unsuccessfulState->getId()); - STORM_LOG_TRACE("New state " << mDft.getStateString(unsuccessfulState)); - - // Add unsuccessful state to search queue - stateQueue.push(unsuccessfulState); - } - + uint_fast64_t unsuccessfulStateId = addState(unsuccessfulState, stateQueue); ValueType remainingProbability = storm::utility::one() - dependency->probability(); transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, unsuccessfulStateId, remainingProbability); STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << unsuccessfulStateId << " with probability " << remainingProbability); @@ -322,17 +266,16 @@ namespace storm { // rate and not the new state we are going to isActive = state->isActive(mDft.getRepresentant(nextBE->id())->id()); } - STORM_LOG_TRACE("BE " << nextBE->name() << " is " << (isActive ? "active" : "not active")); ValueType rate = isActive ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); auto resultFind = outgoingTransitions.find(newStateId); if (resultFind != outgoingTransitions.end()) { // Add to existing transition resultFind->second += rate; - STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with rate " << rate << " to new rate " << resultFind->second); + STORM_LOG_TRACE("Updated transition from " << state->getId() << " to " << resultFind->first << " with " << (isActive ? "active" : "passive") << " rate " << rate << " to new rate " << resultFind->second); } else { // Insert new transition outgoingTransitions.insert(std::make_pair(newStateId, rate)); - STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newStateId << " with rate " << rate); + STORM_LOG_TRACE("Added transition from " << state->getId() << " to " << newStateId << " with " << (isActive ? "active" : "passive") << " rate " << rate); } exitRate += rate; } @@ -420,6 +363,56 @@ namespace storm { return deterministic; } + template + uint_fast64_t ExplicitDFTModelBuilder::addState(DFTStatePointer state, std::queue& stateQueue) { + // Order state by symmetry + STORM_LOG_TRACE("Check for symmetry: " << mDft.getStateString(state)); + bool changed = state->orderBySymmetry(); + STORM_LOG_TRACE("State " << (changed ? "changed to " : "did not change") << (changed ? mDft.getStateString(state) : "")); + + uint_fast64_t stateId; + + // Check if state already exists + if (mStates.contains(state->status())) { + // State already exists + stateId = mStates.getValue(state->status()); + STORM_LOG_TRACE("State " << mDft.getStateString(state) << " with id " << stateId << " already exists"); + + // Check if possible pseudo state can be created now + if (!changed && stateId >= OFFSET_PSEUDO_STATE) { + stateId -= OFFSET_PSEUDO_STATE; + assert(stateId < mPseudoStatesMapping.size()); + if (mPseudoStatesMapping[stateId].first == 0) { + // Create pseudo state now + assert(mPseudoStatesMapping[stateId].second == state->status()); + state->setId(newIndex++); + mPseudoStatesMapping[stateId].first = state->getId(); + stateId = state->getId(); + mStates.setOrAdd(state->status(), stateId); + stateQueue.push(state); + STORM_LOG_TRACE("Now create state " << mDft.getStateString(state) << " with id " << stateId); + } + } + } else { + // New state + if (changed) { + // Remember to create state later on + state->setId(mPseudoStatesMapping.size() + OFFSET_PSEUDO_STATE); + mPseudoStatesMapping.push_back(std::make_pair(0, state->status())); + stateId = mStates.findOrAdd(state->status(), state->getId()); + STORM_LOG_TRACE("New state for later creation: " << mDft.getStateString(state)); + } else { + // Create new state + state->setId(newIndex++); + stateId = mStates.findOrAdd(state->status(), state->getId()); + STORM_LOG_TRACE("New state: " << mDft.getStateString(state)); + stateQueue.push(state); + } + } + return stateId; + } + + // Explicitly instantiate the class. template class ExplicitDFTModelBuilder; diff --git a/src/builder/ExplicitDFTModelBuilder.h b/src/builder/ExplicitDFTModelBuilder.h index 4f1dff514..2f197255e 100644 --- a/src/builder/ExplicitDFTModelBuilder.h +++ b/src/builder/ExplicitDFTModelBuilder.h @@ -72,6 +72,8 @@ namespace storm { private: bool exploreStates(std::queue& stateQueue, storm::storage::SparseMatrixBuilder& transitionMatrixBuilder, std::vector& markovianStates, std::vector& exitRates); + + uint_fast64_t addState(DFTStatePointer state, std::queue& stateQueue); }; } From 2c172cd0827e33609cb7209a3e88b6ffac5abec8 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Mar 2016 11:55:40 +0100 Subject: [PATCH 225/246] Refactoring Former-commit-id: e9af97f7afd148d23f1667ce82f12cfba63d4881 --- src/builder/ExplicitDFTModelBuilder.cpp | 9 +++------ src/models/sparse/MarkovAutomaton.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 7f892a822..018e0eb90 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -124,7 +124,7 @@ namespace storm { } else { std::shared_ptr> ma = std::make_shared>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling), std::move(modelComponents.markovianStates), std::move(modelComponents.exitRates), true); if (ma->hasOnlyTrivialNondeterminism()) { - // Markov automaton can be converted into CTMC + // Markov automaton can be converted into CTMC model = ma->convertToCTMC(); } else { model = ma; @@ -287,8 +287,7 @@ namespace storm { } else { // Try to merge pseudo states with their instantiation // TODO Matthias: improve? - auto it = outgoingTransitions.begin(); - while (it != outgoingTransitions.end()) { + for (auto it = outgoingTransitions.begin(); it != outgoingTransitions.end(); ) { if (it->first >= OFFSET_PSEUDO_STATE) { uint_fast64_t newId = it->first - OFFSET_PSEUDO_STATE; assert(newId < mPseudoStatesMapping.size()); @@ -306,9 +305,7 @@ namespace storm { STORM_LOG_TRACE("Instantiated pseudo state " << newId << " with rate " << it->second); } // Remove pseudo state - auto itErase = it; - ++it; - outgoingTransitions.erase(itErase); + it = outgoingTransitions.erase(it); } else { ++it; } diff --git a/src/models/sparse/MarkovAutomaton.h b/src/models/sparse/MarkovAutomaton.h index 45c8855d9..4251640fc 100644 --- a/src/models/sparse/MarkovAutomaton.h +++ b/src/models/sparse/MarkovAutomaton.h @@ -56,9 +56,9 @@ namespace storm { * @param stateLabeling The labeling of the states. * @param markovianStates A bit vector indicating the Markovian states of the automaton. * @param exitRates A vector storing the exit rates of the states. + * @param probabilities Flag if transitions matrix contains probabilities or rates * @param rewardModels A mapping of reward model names to reward models. * @param optionalChoiceLabeling A vector that represents the labels associated with the choices of each state. - * @param probabilities Flag if transitions matrix contains probabilities or rates */ MarkovAutomaton(storm::storage::SparseMatrix&& transitionMatrix, storm::models::sparse::StateLabeling&& stateLabeling, From 869b0f95d1d318a3572383ebc7c7bd3043f16b51 Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Mar 2016 17:03:46 +0100 Subject: [PATCH 226/246] Support for pdeps with more than one child Former-commit-id: f3de8f2abd2ff3cb40d7fdc739166ec929b10ba5 --- examples/dft/be_nonfail.dft | 4 +++ examples/dft/pdep4.dft | 7 +++++ examples/dft/por.dft | 5 ++++ src/builder/ExplicitDFTModelBuilder.cpp | 5 ++-- src/storage/dft/DFT.h | 2 +- src/storage/dft/DFTBuilder.cpp | 2 +- src/storage/dft/DFTBuilder.h | 40 +++++++++++++++---------- src/storage/dft/DFTState.cpp | 6 ++-- src/storage/dft/elements/DFTBE.h | 8 ++++- 9 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 examples/dft/be_nonfail.dft create mode 100644 examples/dft/pdep4.dft create mode 100644 examples/dft/por.dft diff --git a/examples/dft/be_nonfail.dft b/examples/dft/be_nonfail.dft new file mode 100644 index 000000000..d53dca551 --- /dev/null +++ b/examples/dft/be_nonfail.dft @@ -0,0 +1,4 @@ +toplevel "A"; +"A" and "B" "C"; +"B" lambda=0 dorm=0.3; +"C" lambda=0.5 dorm=0.3; diff --git a/examples/dft/pdep4.dft b/examples/dft/pdep4.dft new file mode 100644 index 000000000..eace91847 --- /dev/null +++ b/examples/dft/pdep4.dft @@ -0,0 +1,7 @@ +toplevel "SF"; +"SF" pand "S" "A" "B"; +"PDEP" pdep=0.2 "S" "A" "B"; + +"S" lambda=0.5 dorm=0; +"A" lambda=0.5 dorm=0; +"B" lambda=0.5 dorm=0; diff --git a/examples/dft/por.dft b/examples/dft/por.dft new file mode 100644 index 000000000..020687f62 --- /dev/null +++ b/examples/dft/por.dft @@ -0,0 +1,5 @@ +toplevel "A"; +"A" por "B" "C" "D"; +"B" lambda=0.4 dorm=0.0; +"C" lambda=0.2 dorm=0.0; +"D" lambda=0.2 dorm=0.0; diff --git a/src/builder/ExplicitDFTModelBuilder.cpp b/src/builder/ExplicitDFTModelBuilder.cpp index 018e0eb90..fa8be6e1a 100644 --- a/src/builder/ExplicitDFTModelBuilder.cpp +++ b/src/builder/ExplicitDFTModelBuilder.cpp @@ -160,7 +160,7 @@ namespace storm { transitionMatrixBuilder.newRowGroup(state->getId() + rowOffset); // Add self loop for target states - if (mDft.hasFailed(state) || mDft.isFailsafe(state)) { + if (mDft.hasFailed(state) || mDft.isFailsafe(state) || state->nrFailableBEs() == 0) { transitionMatrixBuilder.addNextValue(state->getId() + rowOffset, state->getId(), storm::utility::one()); STORM_LOG_TRACE("Added self loop for " << state->getId()); exitRates.push_back(storm::utility::one()); @@ -168,8 +168,6 @@ namespace storm { markovianStates.push_back(state->getId()); // No further exploration required continue; - } else { - STORM_LOG_THROW(state->nrFailableBEs() > 0, storm::exceptions::UnexpectedException, "State " << state->getId() << " is no target state but behaves like one"); } // Let BE fail @@ -267,6 +265,7 @@ namespace storm { isActive = state->isActive(mDft.getRepresentant(nextBE->id())->id()); } ValueType rate = isActive ? nextBE->activeFailureRate() : nextBE->passiveFailureRate(); + assert(!storm::utility::isZero(rate)); auto resultFind = outgoingTransitions.find(newStateId); if (resultFind != outgoingTransitions.end()) { // Add to existing transition diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index d82c45dfa..071a7e56a 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -130,7 +130,7 @@ namespace storm { std::vector nonColdBEs() const { std::vector result; for(DFTElementPointer elem : mElements) { - if(elem->isBasicElement() && !elem->isColdBasicElement()) { + if(elem->isBasicElement() && std::static_pointer_cast>(elem)->canFail() && !elem->isColdBasicElement()) { result.push_back(elem->id()); } } diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 8241ea70a..6998529f8 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -225,7 +225,7 @@ namespace storm { { std::shared_ptr> be = std::static_pointer_cast>(element); ValueType dormancyFactor = storm::utility::zero(); - if (!storm::utility::isZero(be->passiveFailureRate())) { + if (be->canFail()) { dormancyFactor = be->passiveFailureRate() / be->activeFailureRate(); } addBasicElement(be->name(), be->activeFailureRate(), dormancyFactor); diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index d630c24fb..168b27755 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -85,24 +85,32 @@ namespace storm { //TODO Matthias: collect constraints for SMT solving //0 <= probability <= 1 if (!storm::utility::isOne(probability) && children.size() > 2) { - //TODO Matthias: introduce additional element for probability and then add pdeps with probability 1 to children - STORM_LOG_ERROR("Probability != 1 for more than one child currently not supported."); - return false; - } - - for (size_t i = 1; i < children.size(); ++i) { - std::string nameDep = name + "_" + std::to_string(i); - if(mElements.count(nameDep) != 0) { - // Element with that name already exists. - STORM_LOG_ERROR("Element with name: " << nameDep << " already exists."); - return false; + // Introduce additional element for first capturing the proabilistic dependency + std::string nameAdditional = name + "_additional"; + addBasicElement(nameAdditional, storm::utility::zero(), storm::utility::zero()); + // First consider probabilistic dependency + addDepElement(name + "_pdep", {children.front(), nameAdditional}, probability); + // Then consider dependencies to the children if probabilistic dependency failed + std::vector newChildren = children; + newChildren[0] = nameAdditional; + addDepElement(name, newChildren, storm::utility::one()); + return true; + } else { + // Add dependencies + for (size_t i = 1; i < children.size(); ++i) { + std::string nameDep = name + "_" + std::to_string(i); + if(mElements.count(nameDep) != 0) { + // Element with that name already exists. + STORM_LOG_ERROR("Element with name: " << nameDep << " already exists."); + return false; + } + assert(storm::utility::isOne(probability) || children.size() == 2); + DFTDependencyPointer element = std::make_shared>(mNextId++, nameDep, trigger, children[i], probability); + mElements[element->name()] = element; + mDependencies.push_back(element); } - assert(storm::utility::isOne(probability) || children.size() == 2); - DFTDependencyPointer element = std::make_shared>(mNextId++, nameDep, trigger, children[i], probability); - mElements[element->name()] = element; - mDependencies.push_back(element); + return true; } - return true; } bool addVotElement(std::string const& name, unsigned threshold, std::vector const& children) { diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 1468a36ff..4d603e501 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -29,7 +29,8 @@ namespace storm { for(size_t index = 0; index < mDft.nrElements(); ++index) { // Initialize currently failable BE if (mDft.isBasicElement(index) && isOperational(index)) { - if (!mDft.getBasicElement(index)->isColdBasicElement() || !mDft.hasRepresentant(index) || isActive(mDft.getRepresentant(index)->id())) { + std::shared_ptr> be = mDft.getBasicElement(index); + if ((!be->isColdBasicElement() && be->canFail()) || !mDft.hasRepresentant(index) || isActive(mDft.getRepresentant(index)->id())) { mIsCurrentlyFailableBE.push_back(index); STORM_LOG_TRACE("Currently failable: " << mDft.getBasicElement(index)->toString()); } @@ -212,6 +213,7 @@ namespace storm { // Consider "normal" failure assert(index < nrFailableBEs()); std::pair const>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false); + assert(res.first->canFail()); mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index); setFailed(res.first->id()); return res; @@ -244,7 +246,7 @@ namespace storm { activate(representativeId); } for(size_t elem : mDft.module(representativeId)) { - if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem)) { + if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem) && mDft.getBasicElement(elem)->canFail()) { mIsCurrentlyFailableBE.push_back(elem); } else if (mDft.getElement(elem)->isSpareGate() && !isActive(uses(elem))) { propagateActivation(uses(elem)); diff --git a/src/storage/dft/elements/DFTBE.h b/src/storage/dft/elements/DFTBE.h index 58e580262..e7f912fd4 100644 --- a/src/storage/dft/elements/DFTBE.h +++ b/src/storage/dft/elements/DFTBE.h @@ -33,6 +33,10 @@ namespace storm { return mPassiveFailureRate; } + bool canFail() const { + return !storm::utility::isZero(mActiveFailureRate); + } + bool addIngoingDependency(DFTDependencyPointer const& e) { assert(e->dependentEvent()->id() == this->id()); if(std::find(mIngoingDependencies.begin(), mIngoingDependencies.end(), e) != mIngoingDependencies.end()) { @@ -72,7 +76,9 @@ namespace storm { } virtual void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { - if(elemsInSubtree.count(this->id())) return; + if(elemsInSubtree.count(this->id())) { + return; + } DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if(elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft From c23eb7312974381c22af6885e967054b2362910e Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Mar 2016 17:31:45 +0100 Subject: [PATCH 227/246] Cleaned examples Former-commit-id: 37a0ad6cc84026e81f60754cd9db7054277ca9b2 --- examples/dft/{seq1.dft => seq.dft} | 0 examples/dft/seq3.txt | 6 ------ examples/dft/seq4.dft | 11 ++++++----- examples/dft/seq5.dft | 10 ++++++---- examples/dft/seq6.dft | 8 -------- 5 files changed, 12 insertions(+), 23 deletions(-) rename examples/dft/{seq1.dft => seq.dft} (100%) delete mode 100644 examples/dft/seq3.txt delete mode 100644 examples/dft/seq6.dft diff --git a/examples/dft/seq1.dft b/examples/dft/seq.dft similarity index 100% rename from examples/dft/seq1.dft rename to examples/dft/seq.dft diff --git a/examples/dft/seq3.txt b/examples/dft/seq3.txt deleted file mode 100644 index b22b9e8b6..000000000 --- a/examples/dft/seq3.txt +++ /dev/null @@ -1,6 +0,0 @@ -toplevel "A"; -"A" and "C" "D"; -"X" seq "B" "C" "D"; -"B" lambda=0.5 dorm=0.3; -"C" lambda=0.5 dorm=0.3; -"D" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq4.dft b/examples/dft/seq4.dft index 260a88266..60bf149af 100644 --- a/examples/dft/seq4.dft +++ b/examples/dft/seq4.dft @@ -1,6 +1,7 @@ toplevel "A"; -"A" or "C" "D"; -"X" seq "B" "C" "D"; -"B" lambda=0.5 dorm=0.3; -"C" lambda=0.5 dorm=0.3; -"D" lambda=0.5 dorm=0.3; +"A" and "T1" "B3"; +"T1" or "B1" "B2"; +"X" seq "B1" "B2" "B3"; +"B1" lambda=0.5 dorm=0.3; +"B2" lambda=0.5 dorm=0.3; +"B3" lambda=0.5 dorm=0.3; diff --git a/examples/dft/seq5.dft b/examples/dft/seq5.dft index 60bf149af..77b13ddeb 100644 --- a/examples/dft/seq5.dft +++ b/examples/dft/seq5.dft @@ -1,7 +1,9 @@ toplevel "A"; -"A" and "T1" "B3"; -"T1" or "B1" "B2"; -"X" seq "B1" "B2" "B3"; -"B1" lambda=0.5 dorm=0.3; +"A" and "T1" "T2"; +"T1" pand "B1" "B2"; +"T2" pand "B3" "B4"; +"X" seq "B4" "B3"; +"B1" lambda=0.7 dorm=0.3; "B2" lambda=0.5 dorm=0.3; "B3" lambda=0.5 dorm=0.3; +"B4" lambda=0.7 dorm=0.3; diff --git a/examples/dft/seq6.dft b/examples/dft/seq6.dft deleted file mode 100644 index 8453cb411..000000000 --- a/examples/dft/seq6.dft +++ /dev/null @@ -1,8 +0,0 @@ -toplevel "A"; -"A" and "T1" "T2"; -"T1" pand "B1" "B2"; -"T2" pand "B3" "B4; -"B1" lambda=0.7 dorm=0.3; -"B2" lambda=0.5 dorm=0.3; -"B3" lambda=0.5 dorm=0.3; -"B4" lambda=0.7 dorm=0.3; From 2e9089eca67d3a66a65389e2ca26dc3a5204e8ed Mon Sep 17 00:00:00 2001 From: Mavo Date: Thu, 17 Mar 2016 18:12:04 +0100 Subject: [PATCH 228/246] Small changes Former-commit-id: aa36b0ae302e0fccb8b7f403153466c8f68afba3 --- src/storage/dft/DFT.cpp | 46 ++++++++++++++++++++------- src/storage/dft/DFT.h | 9 ++++-- src/storage/dft/DFTState.cpp | 12 +++++-- src/storage/dft/DFTState.h | 2 ++ src/storage/dft/elements/DFTBE.h | 4 +-- src/storage/dft/elements/DFTElement.h | 4 --- 6 files changed, 56 insertions(+), 21 deletions(-) diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index 9a1b086fc..ea4417915 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -79,10 +79,6 @@ namespace storm { template DFTStateGenerationInfo DFT::buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const { - // Use symmetry - // Collect all elements in the first subtree - // TODO make recursive to use for nested subtrees - DFTStateGenerationInfo generationInfo(nrElements(), mMaxSpareChildCount); // Generate Pre and Post info for restrictions @@ -92,19 +88,17 @@ namespace storm { generationInfo.setRestrictionPostElements(elem->id(), elem->seqRestrictionPosts()); } } - - // Perform DFS and insert all elements of subtree sequentially size_t stateIndex = 0; std::queue visitQueue; storm::storage::BitVector visited(nrElements(), false); - // TODO make subfunction for this? if (symmetries.groups.empty()) { // Perform DFS for whole tree visitQueue.push(mTopLevelIndex); stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex); } else { + // Generate information according to symmetries for (size_t symmetryIndex : symmetries.sortedSymmetries) { assert(!visited[symmetryIndex]); auto const& symmetryGroup = symmetries.groups.at(symmetryIndex); @@ -430,7 +424,7 @@ namespace storm { stream << "[" << elem->id() << "]"; stream << elem->toString(); if (elem->isDependency()) { - stream << "\t** " << storm::storage::toChar(state->getDependencyState(elem->id())); + stream << "\t** " << storm::storage::toChar(state->getDependencyState(elem->id())) << "[dep]"; } else { stream << "\t** " << storm::storage::toChar(state->getElementState(elem->id())); if(elem->isSpareGate()) { @@ -445,10 +439,9 @@ namespace storm { } return stream.str(); } - - // TODO rewrite to only use bitvector and id + template - std::string DFT::getStateString(DFTStatePointer const& state) const{ + std::string DFT::getStateString(DFTStatePointer const& state) const { std::stringstream stream; stream << "(" << state->getId() << ") "; for (auto const& elem : mElements) { @@ -467,6 +460,37 @@ namespace storm { } } return stream.str(); + } + + template + std::string DFT::getStateString(storm::storage::BitVector const& status, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) const { + std::stringstream stream; + stream << "(" << id << ") "; + for (auto const& elem : mElements) { + size_t elemIndex = stateGenerationInfo.getStateIndex(elem->id()); + int elementState = DFTState::getElementStateInt(status, elemIndex); + if (elem->isDependency()) { + stream << storm::storage::toChar(static_cast(elementState)) << "[dep]"; + } else { + stream << storm::storage::toChar(static_cast(elementState)); + if(elem->isSpareGate()) { + stream << "["; + size_t nrUsedChild = status.getAsInt(stateGenerationInfo.getSpareUsageIndex(elem->id()), stateGenerationInfo.usageInfoBits()); + size_t useId; + if (nrUsedChild == getMaxSpareChildCount()) { + useId = elem->id(); + } else { + useId = getChild(elem->id(), nrUsedChild); + } + bool isActive = status[stateGenerationInfo.getSpareActivationIndex(useId)]; + if(useId == elem->id() || isActive) { + stream << "actively "; + } + stream << "using " << useId << "]"; + } + } + } + return stream.str(); } template diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 071a7e56a..6fdfd08ef 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -130,8 +130,11 @@ namespace storm { std::vector nonColdBEs() const { std::vector result; for(DFTElementPointer elem : mElements) { - if(elem->isBasicElement() && std::static_pointer_cast>(elem)->canFail() && !elem->isColdBasicElement()) { - result.push_back(elem->id()); + if(elem->isBasicElement()) { + std::shared_ptr> be = std::static_pointer_cast>(elem); + if (be->canFail() && !be->isColdBasicElement()) { + result.push_back(be->id()); + } } } return result; @@ -246,6 +249,8 @@ namespace storm { std::string getStateString(DFTStatePointer const& state) const; + std::string getStateString(storm::storage::BitVector const& status, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) const; + std::vector getIndependentSubDftRoots(size_t index) const; DFTColouring colourDFT() const; diff --git a/src/storage/dft/DFTState.cpp b/src/storage/dft/DFTState.cpp index 4d603e501..b1c9a4fc1 100644 --- a/src/storage/dft/DFTState.cpp +++ b/src/storage/dft/DFTState.cpp @@ -67,6 +67,11 @@ namespace storm { int DFTState::getElementStateInt(size_t id) const { return mStatus.getAsInt(mStateGenerationInfo.getStateIndex(id), 2); } + + template + int DFTState::getElementStateInt(storm::storage::BitVector const& state, size_t indexId) { + return state.getAsInt(indexId, 2); + } template size_t DFTState::getId() const { @@ -246,8 +251,11 @@ namespace storm { activate(representativeId); } for(size_t elem : mDft.module(representativeId)) { - if(mDft.getElement(elem)->isColdBasicElement() && isOperational(elem) && mDft.getBasicElement(elem)->canFail()) { - mIsCurrentlyFailableBE.push_back(elem); + if(mDft.isBasicElement(elem) && isOperational(elem)) { + std::shared_ptr> be = mDft.getBasicElement(elem); + if (be->isColdBasicElement() && be->canFail()) { + mIsCurrentlyFailableBE.push_back(elem); + } } else if (mDft.getElement(elem)->isSpareGate() && !isActive(uses(elem))) { propagateActivation(uses(elem)); } diff --git a/src/storage/dft/DFTState.h b/src/storage/dft/DFTState.h index 1311d74ae..5b68d46ae 100644 --- a/src/storage/dft/DFTState.h +++ b/src/storage/dft/DFTState.h @@ -47,6 +47,8 @@ namespace storm { int getElementStateInt(size_t id) const; + static int getElementStateInt(storm::storage::BitVector const& state, size_t indexId); + size_t getId() const; void setId(size_t id); diff --git a/src/storage/dft/elements/DFTBE.h b/src/storage/dft/elements/DFTBE.h index e7f912fd4..d41e37344 100644 --- a/src/storage/dft/elements/DFTBE.h +++ b/src/storage/dft/elements/DFTBE.h @@ -67,11 +67,11 @@ namespace storm { return stream.str(); } - bool isBasicElement() const override{ + bool isBasicElement() const override { return true; } - bool isColdBasicElement() const override{ + bool isColdBasicElement() const { return storm::utility::isZero(mPassiveFailureRate); } diff --git a/src/storage/dft/elements/DFTElement.h b/src/storage/dft/elements/DFTElement.h index 8a8a35d28..366d0fe91 100644 --- a/src/storage/dft/elements/DFTElement.h +++ b/src/storage/dft/elements/DFTElement.h @@ -93,10 +93,6 @@ namespace storm { return false; } - virtual bool isColdBasicElement() const { - return false; - } - /** * Returns true if the element is a spare gate */ From f529a1315f6f2628ae19702b45f490798715c429 Mon Sep 17 00:00:00 2001 From: Mavo Date: Fri, 18 Mar 2016 15:37:48 +0100 Subject: [PATCH 229/246] Settings module do not need settings manager Former-commit-id: b26ccc902dcac8914b12eaee5eb4dc9f91768e64 --- src/settings/SettingsManager.cpp | 26 +++++++++---------- src/settings/modules/BisimulationSettings.cpp | 2 +- src/settings/modules/BisimulationSettings.h | 6 ++--- .../CounterexampleGeneratorSettings.cpp | 2 +- .../modules/CounterexampleGeneratorSettings.h | 6 ++--- src/settings/modules/CuddSettings.cpp | 2 +- src/settings/modules/CuddSettings.h | 6 ++--- src/settings/modules/DebugSettings.cpp | 2 +- src/settings/modules/DebugSettings.h | 6 ++--- src/settings/modules/GeneralSettings.cpp | 2 +- src/settings/modules/GeneralSettings.h | 6 ++--- src/settings/modules/GlpkSettings.cpp | 2 +- src/settings/modules/GlpkSettings.h | 6 ++--- .../modules/GmmxxEquationSolverSettings.cpp | 2 +- .../modules/GmmxxEquationSolverSettings.h | 6 ++--- src/settings/modules/GurobiSettings.cpp | 2 +- src/settings/modules/GurobiSettings.h | 6 ++--- src/settings/modules/ModuleSettings.cpp | 6 +---- src/settings/modules/ModuleSettings.h | 11 +------- .../modules/NativeEquationSolverSettings.cpp | 2 +- .../modules/NativeEquationSolverSettings.h | 6 ++--- src/settings/modules/ParametricSettings.cpp | 2 +- src/settings/modules/ParametricSettings.h | 6 ++--- ...rseDtmcEliminationModelCheckerSettings.cpp | 2 +- ...parseDtmcEliminationModelCheckerSettings.h | 6 ++--- src/settings/modules/SylvanSettings.cpp | 2 +- src/settings/modules/SylvanSettings.h | 6 ++--- ...alValueIterationEquationSolverSettings.cpp | 2 +- ...icalValueIterationEquationSolverSettings.h | 6 ++--- 29 files changed, 54 insertions(+), 93 deletions(-) diff --git a/src/settings/SettingsManager.cpp b/src/settings/SettingsManager.cpp index fffb10366..7ca1efca2 100644 --- a/src/settings/SettingsManager.cpp +++ b/src/settings/SettingsManager.cpp @@ -35,19 +35,19 @@ namespace storm { SettingsManager::SettingsManager() : modules(), longNameToOptions(), shortNameToOptions(), moduleOptions() { // Register all known settings modules. - this->addModule(std::unique_ptr(new modules::GeneralSettings(*this))); - this->addModule(std::unique_ptr(new modules::DebugSettings(*this))); - this->addModule(std::unique_ptr(new modules::CounterexampleGeneratorSettings(*this))); - this->addModule(std::unique_ptr(new modules::CuddSettings(*this))); - this->addModule(std::unique_ptr(new modules::SylvanSettings(*this))); - this->addModule(std::unique_ptr(new modules::GmmxxEquationSolverSettings(*this))); - this->addModule(std::unique_ptr(new modules::NativeEquationSolverSettings(*this))); - this->addModule(std::unique_ptr(new modules::BisimulationSettings(*this))); - this->addModule(std::unique_ptr(new modules::GlpkSettings(*this))); - this->addModule(std::unique_ptr(new modules::GurobiSettings(*this))); - this->addModule(std::unique_ptr(new modules::TopologicalValueIterationEquationSolverSettings(*this))); - this->addModule(std::unique_ptr(new modules::ParametricSettings(*this))); - this->addModule(std::unique_ptr(new modules::SparseDtmcEliminationModelCheckerSettings(*this))); + this->addModule(std::unique_ptr(new modules::GeneralSettings())); + this->addModule(std::unique_ptr(new modules::DebugSettings())); + this->addModule(std::unique_ptr(new modules::CounterexampleGeneratorSettings())); + this->addModule(std::unique_ptr(new modules::CuddSettings())); + this->addModule(std::unique_ptr(new modules::SylvanSettings())); + this->addModule(std::unique_ptr(new modules::GmmxxEquationSolverSettings())); + this->addModule(std::unique_ptr(new modules::NativeEquationSolverSettings())); + this->addModule(std::unique_ptr(new modules::BisimulationSettings())); + this->addModule(std::unique_ptr(new modules::GlpkSettings())); + this->addModule(std::unique_ptr(new modules::GurobiSettings())); + this->addModule(std::unique_ptr(new modules::TopologicalValueIterationEquationSolverSettings())); + this->addModule(std::unique_ptr(new modules::ParametricSettings())); + this->addModule(std::unique_ptr(new modules::SparseDtmcEliminationModelCheckerSettings())); } SettingsManager::~SettingsManager() { diff --git a/src/settings/modules/BisimulationSettings.cpp b/src/settings/modules/BisimulationSettings.cpp index db3bdce9e..1926e93ef 100644 --- a/src/settings/modules/BisimulationSettings.cpp +++ b/src/settings/modules/BisimulationSettings.cpp @@ -13,7 +13,7 @@ namespace storm { const std::string BisimulationSettings::moduleName = "bisimulation"; const std::string BisimulationSettings::typeOptionName = "type"; - BisimulationSettings::BisimulationSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + BisimulationSettings::BisimulationSettings() : ModuleSettings(moduleName) { std::vector types = { "strong", "weak" }; this->addOption(storm::settings::OptionBuilder(moduleName, typeOptionName, true, "Sets the kind of bisimulation quotienting used. Available are: { strong, weak }.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the type to use.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(types)).setDefaultValueString("strong").build()).build()); } diff --git a/src/settings/modules/BisimulationSettings.h b/src/settings/modules/BisimulationSettings.h index 3e2d1efe7..7bace55ce 100644 --- a/src/settings/modules/BisimulationSettings.h +++ b/src/settings/modules/BisimulationSettings.h @@ -16,11 +16,9 @@ namespace storm { enum class BisimulationType { Strong, Weak }; /*! - * Creates a new set of bisimulation settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of bisimulation settings. */ - BisimulationSettings(storm::settings::SettingsManager& settingsManager); + BisimulationSettings(); /*! * Retrieves whether strong bisimulation is to be used. diff --git a/src/settings/modules/CounterexampleGeneratorSettings.cpp b/src/settings/modules/CounterexampleGeneratorSettings.cpp index e4f8d2a32..6ad644822 100644 --- a/src/settings/modules/CounterexampleGeneratorSettings.cpp +++ b/src/settings/modules/CounterexampleGeneratorSettings.cpp @@ -17,7 +17,7 @@ namespace storm { const std::string CounterexampleGeneratorSettings::encodeReachabilityOptionName = "encreach"; const std::string CounterexampleGeneratorSettings::schedulerCutsOptionName = "schedcuts"; - CounterexampleGeneratorSettings::CounterexampleGeneratorSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + CounterexampleGeneratorSettings::CounterexampleGeneratorSettings() : ModuleSettings(moduleName) { std::vector techniques = {"maxsat", "milp"}; this->addOption(storm::settings::OptionBuilder(moduleName, minimalCommandSetOptionName, true, "Computes a counterexample for the given model in terms of a minimal command set. Note that this requires the model to be given in a symbolic format.") .addArgument(storm::settings::ArgumentBuilder::createStringArgument("method", "Sets which technique is used to derive the counterexample. Available are {milp, maxsat}").setDefaultValueString("maxsat").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(techniques)).build()).build()); diff --git a/src/settings/modules/CounterexampleGeneratorSettings.h b/src/settings/modules/CounterexampleGeneratorSettings.h index 049747183..6103f0102 100644 --- a/src/settings/modules/CounterexampleGeneratorSettings.h +++ b/src/settings/modules/CounterexampleGeneratorSettings.h @@ -13,11 +13,9 @@ namespace storm { class CounterexampleGeneratorSettings : public ModuleSettings { public: /*! - * Creates a new set of counterexample settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of counterexample settings. */ - CounterexampleGeneratorSettings(storm::settings::SettingsManager& settingsManager); + CounterexampleGeneratorSettings(); /*! * Retrieves whether the option to generate a minimal command set was set. diff --git a/src/settings/modules/CuddSettings.cpp b/src/settings/modules/CuddSettings.cpp index 1cd54d011..bf15d1cc6 100644 --- a/src/settings/modules/CuddSettings.cpp +++ b/src/settings/modules/CuddSettings.cpp @@ -16,7 +16,7 @@ namespace storm { const std::string CuddSettings::maximalMemoryOptionName = "maxmem"; const std::string CuddSettings::reorderOptionName = "reorder"; - CuddSettings::CuddSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + CuddSettings::CuddSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, precisionOptionName, true, "Sets the precision used by Cudd.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision up to which to constants are considered to be different.").setDefaultValueDouble(1e-15).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, maximalMemoryOptionName, true, "Sets the upper bound of memory available to Cudd in MB.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("value", "The memory available to Cudd (0 means unlimited).").setDefaultValueUnsignedInteger(4096).build()).build()); diff --git a/src/settings/modules/CuddSettings.h b/src/settings/modules/CuddSettings.h index db59ddc77..8aaa8f007 100644 --- a/src/settings/modules/CuddSettings.h +++ b/src/settings/modules/CuddSettings.h @@ -16,11 +16,9 @@ namespace storm { enum class ReorderingTechnique { None, Random, RandomPivot, Sift, SiftConv, SymmetricSift, SymmetricSiftConv, GroupSift, GroupSiftConv, Win2, Win2Conv, Win3, Win3Conv, Win4, Win4Conv, Annealing, Genetic, Exact }; /*! - * Creates a new set of CUDD settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of CUDD settings. */ - CuddSettings(storm::settings::SettingsManager& settingsManager); + CuddSettings(); /*! * Retrieves the precision that CUDD is supposed to use for distinguishing constants. diff --git a/src/settings/modules/DebugSettings.cpp b/src/settings/modules/DebugSettings.cpp index cf2867181..16d035015 100644 --- a/src/settings/modules/DebugSettings.cpp +++ b/src/settings/modules/DebugSettings.cpp @@ -16,7 +16,7 @@ namespace storm { const std::string DebugSettings::logfileOptionName = "logfile"; const std::string DebugSettings::logfileOptionShortName = "l"; - DebugSettings::DebugSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + DebugSettings::DebugSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, debugOptionName, false, "Print debug output.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, traceOptionName, false, "Print even more debug output.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, logfileOptionName, false, "If specified, the log output will also be written to this file.").setShortName(logfileOptionShortName) diff --git a/src/settings/modules/DebugSettings.h b/src/settings/modules/DebugSettings.h index 024246b68..f78a4e3a8 100644 --- a/src/settings/modules/DebugSettings.h +++ b/src/settings/modules/DebugSettings.h @@ -13,11 +13,9 @@ namespace storm { class DebugSettings : public ModuleSettings { public: /*! - * Creates a new set of debug settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of debug settings. */ - DebugSettings(storm::settings::SettingsManager& settingsManager); + DebugSettings(); /*! * Retrieves whether the debug option was set. diff --git a/src/settings/modules/GeneralSettings.cpp b/src/settings/modules/GeneralSettings.cpp index 9979c6824..0b477d667 100644 --- a/src/settings/modules/GeneralSettings.cpp +++ b/src/settings/modules/GeneralSettings.cpp @@ -66,7 +66,7 @@ namespace storm { const std::string GeneralSettings::parametricOptionName = "parametric"; #endif - GeneralSettings::GeneralSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, helpOptionName, false, "Shows all available options, arguments and descriptions.").setShortName(helpOptionShortName) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("hint", "A regular expression to show help for all matching entities or 'all' for the complete help.").setDefaultValueString("all").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, prismCompatibilityOptionName, false, "Enables PRISM compatibility. This may be necessary to process some PRISM models.").setShortName(prismCompatibilityOptionShortName).build()); diff --git a/src/settings/modules/GeneralSettings.h b/src/settings/modules/GeneralSettings.h index ad268db93..cf8a9318e 100644 --- a/src/settings/modules/GeneralSettings.h +++ b/src/settings/modules/GeneralSettings.h @@ -32,11 +32,9 @@ namespace storm { }; /*! - * Creates a new set of general settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of general settings. */ - GeneralSettings(storm::settings::SettingsManager& settingsManager); + GeneralSettings(); /*! * Retrieves whether the help option was set. diff --git a/src/settings/modules/GlpkSettings.cpp b/src/settings/modules/GlpkSettings.cpp index a459ddbb8..8e879fc6d 100644 --- a/src/settings/modules/GlpkSettings.cpp +++ b/src/settings/modules/GlpkSettings.cpp @@ -16,7 +16,7 @@ namespace storm { const std::string GlpkSettings::integerToleranceOption = "inttol"; const std::string GlpkSettings::outputOptionName = "output"; - GlpkSettings::GlpkSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GlpkSettings::GlpkSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, outputOptionName, true, "If set, the glpk output will be printed to the command line.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, integerToleranceOption, true, "Sets glpk's precision for integer variables.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.").setDefaultValueDouble(1e-06).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); } diff --git a/src/settings/modules/GlpkSettings.h b/src/settings/modules/GlpkSettings.h index b58e91746..2f33009fa 100644 --- a/src/settings/modules/GlpkSettings.h +++ b/src/settings/modules/GlpkSettings.h @@ -13,11 +13,9 @@ namespace storm { class GlpkSettings : public ModuleSettings { public: /*! - * Creates a new set of glpk settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of glpk settings. */ - GlpkSettings(storm::settings::SettingsManager& settingsManager); + GlpkSettings(); /*! * Retrieves whether the output option was set. diff --git a/src/settings/modules/GmmxxEquationSolverSettings.cpp b/src/settings/modules/GmmxxEquationSolverSettings.cpp index fb7cbe307..4904239ba 100644 --- a/src/settings/modules/GmmxxEquationSolverSettings.cpp +++ b/src/settings/modules/GmmxxEquationSolverSettings.cpp @@ -22,7 +22,7 @@ namespace storm { const std::string GmmxxEquationSolverSettings::precisionOptionName = "precision"; const std::string GmmxxEquationSolverSettings::absoluteOptionName = "absolute"; - GmmxxEquationSolverSettings::GmmxxEquationSolverSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GmmxxEquationSolverSettings::GmmxxEquationSolverSettings() : ModuleSettings(moduleName) { std::vector methods = {"bicgstab", "qmr", "gmres", "jacobi"}; this->addOption(storm::settings::OptionBuilder(moduleName, techniqueOptionName, true, "The method to be used for solving linear equation systems with the gmm++ engine. Available are {bicgstab, qmr, gmres, jacobi}.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(methods)).setDefaultValueString("gmres").build()).build()); diff --git a/src/settings/modules/GmmxxEquationSolverSettings.h b/src/settings/modules/GmmxxEquationSolverSettings.h index 8cb0761a8..71c7fcee1 100644 --- a/src/settings/modules/GmmxxEquationSolverSettings.h +++ b/src/settings/modules/GmmxxEquationSolverSettings.h @@ -22,11 +22,9 @@ namespace storm { enum class ConvergenceCriterion { Absolute, Relative }; /*! - * Creates a new set of gmm++ settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of gmm++ settings. */ - GmmxxEquationSolverSettings(storm::settings::SettingsManager& settingsManager); + GmmxxEquationSolverSettings(); /*! * Retrieves whether the linear equation system method has been set. diff --git a/src/settings/modules/GurobiSettings.cpp b/src/settings/modules/GurobiSettings.cpp index 837c631de..f94fc988c 100644 --- a/src/settings/modules/GurobiSettings.cpp +++ b/src/settings/modules/GurobiSettings.cpp @@ -16,7 +16,7 @@ namespace storm { const std::string GurobiSettings::threadsOption = "threads"; const std::string GurobiSettings::outputOption = "output"; - GurobiSettings::GurobiSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) { + GurobiSettings::GurobiSettings() : ModuleSettings(moduleName) { this->addOption(storm::settings::OptionBuilder(moduleName, threadsOption, true, "The number of threads that may be used by Gurobi.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The number of threads.").setDefaultValueUnsignedInteger(1).build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, outputOption, true, "If set, the Gurobi output will be printed to the command line.").build()); diff --git a/src/settings/modules/GurobiSettings.h b/src/settings/modules/GurobiSettings.h index ce7fcd78f..ccad8cbc0 100644 --- a/src/settings/modules/GurobiSettings.h +++ b/src/settings/modules/GurobiSettings.h @@ -13,11 +13,9 @@ namespace storm { class GurobiSettings : public ModuleSettings { public: /*! - * Creates a new set of Gurobi settings that is managed by the given manager. - * - * @param settingsManager The responsible manager. + * Creates a new set of Gurobi settings. */ - GurobiSettings(storm::settings::SettingsManager& settingsManager); + GurobiSettings(); /*! * Retrieves whether the integer tolerance has been set. diff --git a/src/settings/modules/ModuleSettings.cpp b/src/settings/modules/ModuleSettings.cpp index f99d50e35..1f7a2b7f3 100644 --- a/src/settings/modules/ModuleSettings.cpp +++ b/src/settings/modules/ModuleSettings.cpp @@ -10,7 +10,7 @@ namespace storm { namespace settings { namespace modules { - ModuleSettings::ModuleSettings(storm::settings::SettingsManager& settingsManager, std::string const& moduleName) : settingsManager(settingsManager), moduleName(moduleName) { + ModuleSettings::ModuleSettings(std::string const& moduleName) : moduleName(moduleName) { // Intentionally left empty. } @@ -19,10 +19,6 @@ namespace storm { } void ModuleSettings::finalize() { } - - storm::settings::SettingsManager const& ModuleSettings::getSettingsManager() const { - return this->settingsManager; - } void ModuleSettings::set(std::string const& name) { return this->getOption(name).setHasOptionBeenSet(); diff --git a/src/settings/modules/ModuleSettings.h b/src/settings/modules/ModuleSettings.h index 027664433..08c92909d 100644 --- a/src/settings/modules/ModuleSettings.h +++ b/src/settings/modules/ModuleSettings.h @@ -27,10 +27,9 @@ namespace storm { /*! * Constructs a new settings object. * - * @param settingsManager The manager responsible for these settings. * @param moduleName The name of the module for which to build the settings. */ - ModuleSettings(storm::settings::SettingsManager& settingsManager, std::string const& moduleName); + ModuleSettings(std::string const& moduleName); /*! * Checks whether the settings are consistent. If they are inconsistent, an exception is thrown. @@ -77,12 +76,6 @@ namespace storm { uint_fast64_t getPrintLengthOfLongestOption() const; protected: - /*! - * Retrieves the manager responsible for the settings. - * - * @return The manager responsible for the settings. - */ - storm::settings::SettingsManager const& getSettingsManager() const; /*! * Retrieves the option with the given long name. If no such option exists, an exception is thrown. @@ -132,8 +125,6 @@ namespace storm { void addOption(std::shared_ptr