Browse Source
First version of the monolithic state space generation
First version of the monolithic state space generation
Former-commit-id: fab8f6e356
tempestpy_adaptions
sjunges
10 years ago
21 changed files with 1989 additions and 48 deletions
-
93src/builder/ExplicitDFTModelBuilder.h
-
102src/parser/DFTGalileoParser.cpp
-
29src/parser/DFTGalileoParser.h
-
25src/storage/BitVector.cpp
-
7src/storage/BitVector.h
-
121src/storage/dft/DFT.cpp
-
184src/storage/dft/DFT.h
-
132src/storage/dft/DFTBuilder.cpp
-
116src/storage/dft/DFTBuilder.h
-
26src/storage/dft/DFTElementState.h
-
38src/storage/dft/DFTElements.cpp
-
635src/storage/dft/DFTElements.h
-
125src/storage/dft/DFTState.cpp
-
138src/storage/dft/DFTState.h
-
78src/storage/dft/DFTStateSpaceGenerationQueues.h
-
18src/storage/dft/OrderDFTElementsById.cpp
-
24src/storage/dft/OrderDFTElementsById.h
-
22src/storm-dyftee.cpp
-
48src/utility/cli.h
-
68src/utility/initialize.h
-
8src/utility/math.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<storm::storage::DFTState, size_t> mStateIndices; |
|||
size_t newIndex = 0; |
|||
//std::stack<std::shared_ptr<storm::storage::DFTState>> 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<std::shared_ptr<storm::storage::DFTBE<double>>, 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<storm::storage::DFTGate> parent : nextBE.first->parents()) { |
|||
if(newState.isOperational(parent->id())) { |
|||
queues.propagateFailure(parent); |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
while(!queues.failurePropagationDone()) { |
|||
std::shared_ptr<storm::storage::DFTGate> next = queues.nextFailurePropagation(); |
|||
next->checkFails(newState, queues); |
|||
} |
|||
|
|||
while(!queues.failsafePropagationDone()) { |
|||
std::shared_ptr<storm::storage::DFTGate> next = queues.nextFailsafePropagation(); |
|||
next->checkFailsafe(newState, queues); |
|||
} |
|||
|
|||
while(!queues.dontCarePropagationDone()) { |
|||
std::shared_ptr<storm::storage::DFTElement> 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 */ |
|||
|
@ -0,0 +1,102 @@ |
|||
#include "DFTGalileoParser.h"
|
|||
|
|||
#include <iostream>
|
|||
#include <fstream>
|
|||
#include <boost/algorithm/string.hpp>
|
|||
#include <boost/lexical_cast.hpp>
|
|||
#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<std::string> tokens; |
|||
boost::split(tokens, line, boost::is_any_of(" ")); |
|||
std::string name(stripQuotsFromName(tokens[0])); |
|||
|
|||
std::vector<std::string> 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<unsigned>(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<double>(tokens[1].substr(7)), boost::lexical_cast<double>(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; |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
@ -0,0 +1,29 @@ |
|||
#ifndef DFTGALILEOPARSER_H |
|||
#define DFTGALILEOPARSER_H |
|||
|
|||
#include "../storage/dft/DFT.h" |
|||
#include "../storage/dft/DFTBuilder.h" |
|||
|
|||
#include <map> |
|||
|
|||
|
|||
|
|||
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 */ |
|||
|
@ -0,0 +1,121 @@ |
|||
#include "DFT.h"
|
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
|
|||
DFT::DFT(std::vector<std::shared_ptr<DFTElement>> const& elements, std::shared_ptr<DFTElement> 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<DFTSpare>(elem)->children()) { |
|||
if(mActivationIndex.count(spareReprs->id()) == 0) { |
|||
mActivationIndex[spareReprs->id()] = stateIndex++; |
|||
} |
|||
std::set<size_t> module = {spareReprs->id()}; |
|||
spareReprs->extendSpareModule(module); |
|||
std::vector<size_t> 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<DFTSpare>(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<size_t> 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<size_t>(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<size_t>::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<size_t>::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; |
|||
|
|||
|
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,184 @@ |
|||
|
|||
#ifndef DFT_H |
|||
#define DFT_H |
|||
|
|||
|
|||
#include "DFTElements.h" |
|||
#include "../BitVector.h" |
|||
#include <memory> |
|||
#include <unordered_map> |
|||
#include <list> |
|||
#include <map> |
|||
|
|||
#include "../../utility/math.h" |
|||
#include <boost/iterator/counting_iterator.hpp> |
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
|
|||
|
|||
struct DFTElementSort { |
|||
bool operator()(std::shared_ptr<DFTElement> const& a, std::shared_ptr<DFTElement> const& b) const { |
|||
if (a->rank() == 0 && b->rank() == 0) { |
|||
return a->isConstant(); |
|||
} else { |
|||
return a->rank() < b->rank(); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
class DFT { |
|||
|
|||
|
|||
|
|||
private: |
|||
std::vector<std::shared_ptr<DFTElement>> mElements; |
|||
size_t mNrOfBEs; |
|||
size_t mNrOfSpares; |
|||
size_t mTopLevelIndex; |
|||
size_t mUsageInfoBits; |
|||
size_t mStateSize; |
|||
std::map<size_t, size_t> mActivationIndex; |
|||
std::map<size_t, std::vector<size_t>> mSpareModules; |
|||
std::vector<size_t> mTopModule; |
|||
std::vector<size_t> mIdToFailureIndex; |
|||
std::map<size_t, size_t> mUsageIndex; |
|||
|
|||
|
|||
public: |
|||
DFT(std::vector<std::shared_ptr<DFTElement>> const& elements, std::shared_ptr<DFTElement> 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<DFTSpare>(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<size_t> getSpareIndices() const { |
|||
std::vector<size_t> indices; |
|||
for(auto const& elem : mElements) { |
|||
if(elem->isSpareGate()) { |
|||
indices.push_back(elem->id()); |
|||
} |
|||
} |
|||
return indices; |
|||
} |
|||
|
|||
std::vector<size_t> 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<size_t> nonColdBEs() const { |
|||
std::vector<size_t> result; |
|||
for(std::shared_ptr<DFTElement> elem : mElements) { |
|||
if(elem->isBasicElement() && !elem->isColdBasicElement()) { |
|||
result.push_back(elem->id()); |
|||
} |
|||
} |
|||
return result; |
|||
} |
|||
|
|||
std::shared_ptr<DFTElement> const& getElement(size_t index) const { |
|||
assert(index < nrElements()); |
|||
return mElements[index]; |
|||
} |
|||
|
|||
std::shared_ptr<DFTBE<double>> getBasicElement(size_t index) const { |
|||
assert(mElements[index]->isBasicElement()); |
|||
return std::static_pointer_cast<DFTBE<double>>(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 */ |
|||
|
@ -0,0 +1,132 @@ |
|||
|
|||
|
|||
#include "DFTBuilder.h"
|
|||
|
|||
#include "DFT.h"
|
|||
#include <algorithm>
|
|||
#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<DFTGate> gate = std::static_pointer_cast<DFTGate>(elem.first); |
|||
gate->pushBackChild(mElements[child]); |
|||
mElements[child]->addParent(gate); |
|||
} |
|||
} |
|||
|
|||
// Sort elements topologically
|
|||
|
|||
|
|||
|
|||
// compute rank
|
|||
for (auto& elem : mElements) { |
|||
computeRank(elem.second); |
|||
} |
|||
|
|||
std::vector<std::shared_ptr<DFTElement>> elems = topoSort(); |
|||
size_t id = 0; |
|||
for(std::shared_ptr<DFTElement> 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<DFTElement> const& elem) { |
|||
if(elem->rank() == -1) { |
|||
if(elem->nrChildren() == 0) { |
|||
elem->setRank(0); |
|||
return 0; |
|||
} |
|||
std::shared_ptr<DFTGate> gate = std::static_pointer_cast<DFTGate>(elem); |
|||
unsigned maxrnk = 0; |
|||
unsigned newrnk = 0; |
|||
|
|||
for(std::shared_ptr<DFTElement> 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<std::string> const& children, DFTElementTypes tp) { |
|||
assert(children.size() > 0); |
|||
if(mElements.count(name) != 0) { |
|||
// Element with that name already exists.
|
|||
return false; |
|||
} |
|||
std::shared_ptr<DFTElement> element; |
|||
switch(tp) { |
|||
case DFTElementTypes::AND: |
|||
element = std::make_shared<DFTAnd>(mNextId++, name); |
|||
break; |
|||
case DFTElementTypes::OR: |
|||
element = std::make_shared<DFTOr>(mNextId++, name); |
|||
break; |
|||
case DFTElementTypes::PAND: |
|||
element = std::make_shared<DFTPand>(mNextId++, name); |
|||
break; |
|||
case DFTElementTypes::POR: |
|||
element = std::make_shared<DFTPor>(mNextId++, name); |
|||
break; |
|||
case DFTElementTypes::SPARE: |
|||
element = std::make_shared<DFTSpare>(mNextId++, name); |
|||
break; |
|||
} |
|||
mElements[name] = element; |
|||
mChildNames[element] = children; |
|||
return true; |
|||
} |
|||
|
|||
|
|||
void DFTBuilder::topoVisit(std::shared_ptr<DFTElement> const& n, std::map<std::shared_ptr<DFTElement>, topoSortColour>& visited, std::vector<std::shared_ptr<DFTElement>>& 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<DFTElement> const& c : std::static_pointer_cast<DFTGate>(n)->children()) { |
|||
topoVisit(c, visited, L); |
|||
} |
|||
} |
|||
visited[n] = topoSortColour::BLACK; |
|||
L.push_back(n); |
|||
|
|||
} |
|||
} |
|||
|
|||
std::vector<std::shared_ptr<DFTElement>> DFTBuilder::topoSort() { |
|||
std::map<std::shared_ptr<DFTElement>, topoSortColour> visited; |
|||
for(auto const& e : mElements) { |
|||
visited.insert(std::make_pair(e.second, topoSortColour::WHITE)); |
|||
} |
|||
|
|||
std::vector<std::shared_ptr<DFTElement>> L; |
|||
for(auto const& e : visited) { |
|||
topoVisit(e.first, visited, L); |
|||
} |
|||
//std::reverse(L.begin(), L.end());
|
|||
return L; |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
@ -0,0 +1,116 @@ |
|||
|
|||
#ifndef DFTBUILDER_H |
|||
#define DFTBUILDER_H |
|||
|
|||
#include "DFTElements.h" |
|||
#include <iostream> |
|||
#include <unordered_map> |
|||
#include <map> |
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
class DFT; |
|||
|
|||
class DFTBuilder { |
|||
|
|||
std::size_t mNextId = 0; |
|||
std::string topLevelIdentifier; |
|||
std::unordered_map<std::string, std::shared_ptr<DFTElement>> mElements; |
|||
std::unordered_map<std::shared_ptr<DFTElement>, std::vector<std::string>> mChildNames; |
|||
|
|||
public: |
|||
DFTBuilder() { |
|||
|
|||
} |
|||
|
|||
bool addAndElement(std::string const& name, std::vector<std::string> const& children) { |
|||
return addStandardGate(name, children, DFTElementTypes::AND); |
|||
} |
|||
|
|||
bool addOrElement(std::string const& name, std::vector<std::string> const& children) { |
|||
return addStandardGate(name, children, DFTElementTypes::OR); |
|||
} |
|||
|
|||
bool addPandElement(std::string const& name, std::vector<std::string> const& children) { |
|||
return addStandardGate(name, children, DFTElementTypes::PAND); |
|||
} |
|||
|
|||
bool addPorElement(std::string const& name, std::vector<std::string> const& children) { |
|||
return addStandardGate(name, children, DFTElementTypes::POR); |
|||
} |
|||
|
|||
bool addSpareElement(std::string const& name, std::vector<std::string> const& children) { |
|||
return addStandardGate(name, children, DFTElementTypes::SPARE); |
|||
} |
|||
|
|||
|
|||
|
|||
bool addVotElement(std::string const& name, unsigned threshold, std::vector<std::string> 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<DFTElement> element = std::make_shared<DFTVot>(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<DFTBE<double>>(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<DFTElement> const& elem); |
|||
|
|||
bool addStandardGate(std::string const& name, std::vector<std::string> const& children, DFTElementTypes tp); |
|||
|
|||
enum class topoSortColour {WHITE, BLACK, GREY}; |
|||
|
|||
void topoVisit(std::shared_ptr<DFTElement> const& n, std::map<std::shared_ptr<DFTElement>, topoSortColour>& visited, std::vector<std::shared_ptr<DFTElement>>& L); |
|||
std::vector<std::shared_ptr<DFTElement>> topoSort(); |
|||
|
|||
|
|||
}; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
#endif /* DFTBUILDER_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 */ |
|||
|
@ -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<DFTGate> const& parent : mParents) { |
|||
if(state.isOperational(parent->id())) { |
|||
return false; |
|||
} |
|||
} |
|||
state.setDontCare(mId); |
|||
return true; |
|||
|
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void DFTElement::extendSpareModule(std::set<size_t>& 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<double>::checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { |
|||
if(DFTElement::checkDontCareAnymore(state, queues)) { |
|||
state.beNoLongerFailable(mId); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,635 @@ |
|||
#ifndef DFTELEMENTS_H |
|||
#define DFTELEMENTS_H |
|||
|
|||
#include <set> |
|||
#include <vector> |
|||
#include <memory> |
|||
#include <string> |
|||
#include <cassert> |
|||
#include <cstdlib> |
|||
#include <iostream> |
|||
|
|||
#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<std::shared_ptr<DFTGate>> 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<DFTGate> 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<std::shared_ptr<DFTGate>> const& parents() const { |
|||
return mParents; |
|||
} |
|||
|
|||
virtual void extendSpareModule(std::set<size_t>& 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<std::shared_ptr<DFTElement>> mChildren; |
|||
public: |
|||
DFTGate(size_t id, std::string const& name, std::vector<std::shared_ptr<DFTElement>> const& children) : |
|||
DFTElement(id, name), mChildren(children) |
|||
{} |
|||
|
|||
virtual ~DFTGate() {} |
|||
|
|||
void pushBackChild(std::shared_ptr<DFTElement> elem) { |
|||
return mChildren.push_back(elem); |
|||
} |
|||
|
|||
size_t nrChildren() const { |
|||
return mChildren.size(); |
|||
} |
|||
|
|||
std::vector<std::shared_ptr<DFTElement>> 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<size_t>& 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<std::shared_ptr<DFTElement>>::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<DFTGate> parent : mParents) { |
|||
if(state.isOperational(parent->id())) { |
|||
queues.propagateFailure(parent); |
|||
} |
|||
} |
|||
state.setFailed(mId); |
|||
} |
|||
|
|||
void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { |
|||
for(std::shared_ptr<DFTGate> 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<typename FailureRateType> |
|||
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<double> 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<std::shared_ptr<DFTElement>> 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<std::shared_ptr<DFTElement>> 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<std::shared_ptr<DFTElement>> 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<std::shared_ptr<DFTElement>> 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<std::shared_ptr<DFTElement>> 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<std::shared_ptr<DFTElement>> 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<std::shared_ptr<DFTElement>> 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<size_t> 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 */ |
|||
|
@ -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<size_t> alwaysActiveBEs = dft.nonColdBEs(); |
|||
mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end()); |
|||
|
|||
} |
|||
|
|||
DFTElementState DFTState::getElementState(size_t id) const { |
|||
return static_cast<DFTElementState>(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<uint_fast64_t>(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<std::shared_ptr<DFTBE<double>>, bool> DFTState::letNextBEFail(size_t index) |
|||
{ |
|||
assert(index < mIsCurrentlyFailableBE.size()); |
|||
//std::cout << "currently failable: ";
|
|||
//printCurrentlyFailable(std::cout);
|
|||
std::pair<std::shared_ptr<DFTBE<double>>,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<size_t> 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<size_t> 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; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,138 @@ |
|||
#ifndef DFTSTATE_H |
|||
#define DFTSTATE_H |
|||
|
|||
#include "../BitVector.h" |
|||
#include "DFTElementState.h" |
|||
|
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
|
|||
class DFT; |
|||
template<typename T> |
|||
class DFTBE; |
|||
|
|||
|
|||
|
|||
class DFTState { |
|||
friend struct std::hash<DFTState>; |
|||
private: |
|||
storm::storage::BitVector mStatus; |
|||
std::vector<size_t> mInactiveSpares; |
|||
std::vector<size_t> mIsCurrentlyFailableBE; |
|||
std::vector<size_t> 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<size_t> const& childIds); |
|||
|
|||
bool hasOutgoingEdges() const { |
|||
return !mIsCurrentlyFailableBE.empty(); |
|||
} |
|||
|
|||
size_t nrFailableBEs() const { |
|||
return mIsCurrentlyFailableBE.size(); |
|||
} |
|||
|
|||
std::pair<std::shared_ptr<DFTBE<double>>, 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<storm::storage::DFTState> { |
|||
size_t operator()(storm::storage::DFTState const& s) const { |
|||
return hash<storm::storage::BitVector>()(s.mStatus); |
|||
} |
|||
}; |
|||
} |
|||
|
|||
#endif /* DFTSTATE_H */ |
|||
|
@ -0,0 +1,78 @@ |
|||
#ifndef DFTSTATESPACEGENERATIONQUEUES_H |
|||
#define DFTSTATESPACEGENERATIONQUEUES_H |
|||
|
|||
#include <list> |
|||
#include <queue> |
|||
#include <vector> |
|||
#include <deque> |
|||
|
|||
#include "OrderDFTElementsById.h" |
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
class DFTGate; |
|||
class DFTElement; |
|||
|
|||
|
|||
|
|||
class DFTStateSpaceGenerationQueues { |
|||
std::priority_queue<std::shared_ptr<DFTGate>, std::vector<std::shared_ptr<DFTGate>>, OrderElementsByRank> failurePropagation; |
|||
std::vector<std::shared_ptr<DFTGate>> failsafePropagation; |
|||
std::vector<std::shared_ptr<DFTElement>> dontcarePropagation; |
|||
std::vector<std::shared_ptr<DFTElement>> activatePropagation; |
|||
|
|||
public: |
|||
void propagateFailure(std::shared_ptr<DFTGate> const& elem) { |
|||
failurePropagation.push(elem); |
|||
} |
|||
|
|||
bool failurePropagationDone() const { |
|||
return failurePropagation.empty(); |
|||
} |
|||
|
|||
std::shared_ptr<DFTGate> nextFailurePropagation() { |
|||
std::shared_ptr<DFTGate> next= failurePropagation.top(); |
|||
failurePropagation.pop(); |
|||
return next; |
|||
} |
|||
|
|||
bool failsafePropagationDone() const { |
|||
return failsafePropagation.empty(); |
|||
} |
|||
|
|||
void propagateFailsafe(std::shared_ptr<DFTGate> const& gate) { |
|||
failsafePropagation.push_back(gate); |
|||
} |
|||
|
|||
std::shared_ptr<DFTGate> nextFailsafePropagation() { |
|||
std::shared_ptr<DFTGate> next = failsafePropagation.back(); |
|||
failsafePropagation.pop_back(); |
|||
return next; |
|||
} |
|||
|
|||
bool dontCarePropagationDone() const { |
|||
return dontcarePropagation.empty(); |
|||
} |
|||
|
|||
void propagateDontCare(std::shared_ptr<DFTElement> const& elem) { |
|||
dontcarePropagation.push_back(elem); |
|||
} |
|||
|
|||
void propagateDontCare(std::vector<std::shared_ptr<DFTElement>> const& elems) { |
|||
dontcarePropagation.insert(dontcarePropagation.end(), elems.begin(), elems.end()); |
|||
} |
|||
|
|||
std::shared_ptr<DFTElement> nextDontCarePropagation() { |
|||
std::shared_ptr<DFTElement> next = dontcarePropagation.back(); |
|||
dontcarePropagation.pop_back(); |
|||
return next; |
|||
} |
|||
}; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
#endif /* DFTSTATESPACEGENERATIONQUEUES_H */ |
|||
|
@ -0,0 +1,18 @@ |
|||
#include "OrderDFTElementsById.h"
|
|||
#include "DFTElements.h"
|
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
bool OrderElementsById::operator()(std::shared_ptr<DFTGate> const& a , std::shared_ptr<DFTGate> const& b) const { |
|||
return a->id() < b->id(); |
|||
} |
|||
bool OrderElementsById::operator ()(const std::shared_ptr<DFTElement>& a, const std::shared_ptr<DFTElement>& b) const { |
|||
return a->id() < b->id(); |
|||
} |
|||
|
|||
|
|||
bool OrderElementsByRank::operator ()(const std::shared_ptr<DFTGate>& a, const std::shared_ptr<DFTGate>& b) const { |
|||
return a->rank() < b->rank(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
#ifndef ORDERDFTELEMENTS_H |
|||
#define ORDERDFTELEMENTS_H |
|||
|
|||
#include <memory> |
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
class DFTGate; |
|||
class DFTElement; |
|||
|
|||
struct OrderElementsById { |
|||
bool operator()(std::shared_ptr<DFTGate> const& a , std::shared_ptr<DFTGate> const& b) const; |
|||
bool operator()(std::shared_ptr<DFTElement> const& a, std::shared_ptr<DFTElement> const& b) const; |
|||
}; |
|||
|
|||
struct OrderElementsByRank { |
|||
bool operator()(std::shared_ptr<DFTGate> const& a, std::shared_ptr<DFTGate> const& b) const; |
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* ORDERDFTELEMENTSBYID_H */ |
|||
|
@ -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(); |
|||
} |
|||
|
@ -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<log4cplus::Layout>(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<log4cplus::Layout>(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%S} (%r ms) - %F:%L: %m%n"))); |
|||
logger.addAppender(fileLogAppender); |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
#endif /* INITIALIZE_H */ |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue