Browse Source

First version of simulator for failure traces in DFTs

tempestpy_adaptions
Matthias Volk 4 years ago
parent
commit
54e665aff1
No known key found for this signature in database GPG Key ID: 83A57678F739FCD3
  1. 124
      src/storm-dft/simulator/DFTTraceSimulator.cpp
  2. 97
      src/storm-dft/simulator/DFTTraceSimulator.h

124
src/storm-dft/simulator/DFTTraceSimulator.cpp

@ -0,0 +1,124 @@
#include "DFTTraceSimulator.h"
namespace storm {
namespace dft {
namespace simulator {
template<typename ValueType>
DFTTraceSimulator<ValueType>::DFTTraceSimulator(storm::storage::DFT<ValueType> const& dft, storm::storage::DFTStateGenerationInfo const& stateGenerationInfo, boost::mt19937& randomGenerator) : dft(dft), stateGenerationInfo(stateGenerationInfo), generator(dft, stateGenerationInfo), randomGenerator(randomGenerator) {
// Set initial state
state = generator.createInitialState();
}
template<typename ValueType>
void DFTTraceSimulator<ValueType>::setRandomNumberGenerator(boost::mt19937& randomNumberGenerator) {
this->randomGenerator = randomNumberGenerator;
}
template<typename ValueType>
void DFTTraceSimulator<ValueType>::resetToInitial() {
state = generator.createInitialState();;
}
template<typename ValueType>
typename DFTTraceSimulator<ValueType>::DFTStatePointer DFTTraceSimulator<ValueType>::getCurrentState() const {
return state;
}
template<typename ValueType>
double DFTTraceSimulator<ValueType>::randomStep() {
auto iterFailable = state->getFailableElements().begin();
// Check for absorbing state:
// - either no relevant event remains (i.e., all relevant events have failed already), or
// - no BE can fail
if (!state->hasOperationalRelevantEvent() || iterFailable == state->getFailableElements().end()) {
STORM_LOG_TRACE("No sucessor states available for " << state->getId());
return -1;
}
// Get all failable elements
if (iterFailable.isFailureDueToDependency()) {
if (iterFailable.isConflictingDependency()) {
// We take the first dependeny to resolve the non-determinism
STORM_LOG_WARN("Non-determinism present! We take the dependency with the lowest id");
}
STORM_LOG_TRACE("Let dependency " << *iterFailable.getFailBE(dft).second << " fail");
bool res = step(iterFailable);
return res ? 0 : -1;
} else {
// Consider all "normal" BE failures
// Initialize with first BE
storm::dft::storage::FailableElements::const_iterator nextFail = iterFailable;
double rate = state->getBERate(iterFailable.getFailBE(dft).first->id());
storm::utility::ExponentialDistributionGenerator rateGenerator(rate);
double smallestTimebound = rateGenerator.random(randomGenerator);
++iterFailable;
// Consider all other BEs and find the one which fails first
for (; iterFailable != state->getFailableElements().end(); ++iterFailable) {
auto nextBE = iterFailable.getFailBE(dft).first;
rate = state->getBERate(nextBE->id());
rateGenerator = storm::utility::ExponentialDistributionGenerator(rate);
double timebound = rateGenerator.random(randomGenerator);
if (timebound < smallestTimebound) {
// BE fails earlier -> use as nextFail
nextFail = iterFailable;
smallestTimebound = timebound;
}
}
STORM_LOG_TRACE("Let BE " << *nextFail.getFailBE(dft).first << "fail after time " << smallestTimebound);
bool res = step(nextFail);
return res ? smallestTimebound : -1;
}
}
template<typename ValueType>
bool DFTTraceSimulator<ValueType>::step(storm::dft::storage::FailableElements::const_iterator nextFailElement) {
if (nextFailElement == state->getFailableElements().end()) {
return false;
}
auto nextBEPair = nextFailElement.getFailBE(dft);
auto newState = generator.createSuccessorState(state, nextBEPair.first, nextBEPair.second);
// TODO handle PDEP
if(newState->isInvalid() || newState->isTransient()) {
STORM_LOG_TRACE("Step is invalid because new state " << (newState->isInvalid() ? "it is invalid" : "the transient fault is ignored"));
return false;
}
state = newState;
return true;
}
template<typename ValueType>
bool DFTTraceSimulator<ValueType>::simulateCompleteTrace(double timebound) {
resetToInitial();
double time = 0;
while (time <= timebound) {
// Check whether DFT failed within timebound
if (state->hasFailed(dft.getTopLevelIndex())) {
STORM_LOG_TRACE("DFT has failed after " << time);
return true;
}
// Generate next state
double res = randomStep();
STORM_LOG_TRACE("Current state: " << dft.getStateString(state));
if (res < 0) {
// No next state can be reached
STORM_LOG_TRACE("No next state possible in state " << dft.getStateString(state));
return false;
}
time += res;
}
// Time is up
return false;
}
template class DFTTraceSimulator<double>;
}
}
}

97
src/storm-dft/simulator/DFTTraceSimulator.h

@ -0,0 +1,97 @@
#include "storm-dft/generator/DftNextStateGenerator.h"
#include "storm-dft/storage/dft/DFT.h"
#include "storm-dft/storage/dft/DFTState.h"
#include "storm-dft/storage/dft/FailableElements.h"
#include "storm/utility/random.h"
namespace storm {
namespace dft {
namespace simulator {
/*!
* Simulator for DFTs.
* A step in the simulation corresponds to the failure of one BE (either on its own or triggered by a dependency)
* and the failure propagation through the DFT.
* The simulator also allows to randomly generate a next failure according to the failure rates.
*/
template<typename ValueType>
class DFTTraceSimulator {
using DFTStatePointer = std::shared_ptr<storm::storage::DFTState<ValueType>>;
public:
/*!
* Constructor.
*
* @param dft DFT.
* @param stateGenerationInfo Info for state generation.
* @param randomGenerator Random number generator.
*/
DFTTraceSimulator(storm::storage::DFT<ValueType> const& dft, storm::storage::DFTStateGenerationInfo const& stateGenerationInfo, boost::mt19937& randomGenerator);
/*!
* Set the random number generator.
*
* @param randomNumberGenerator Random number generator.
*/
void setRandomNumberGenerator(boost::mt19937& randomNumberGenerator);
/*!
* Set the current state back to the intial state in order to start a new simulation.
*/
void resetToInitial();
/*!
* Get the current DFT state.
*
* @return DFTStatePointer DFT state.
*/
DFTStatePointer getCurrentState() const;
/*!
* Perform one simulation step by letting the next element fail.
*
* @param nextFailElement Iterator giving the next element which should fail.
* @return True iff step could be performed successfully.
*/
bool step(storm::dft::storage::FailableElements::const_iterator nextFailElement);
/*!
* Perform a random step by using the random number generator.
*
* @return double The time which progessed between the last step and this step.
* Returns -1 if no next step could be created.
*/
double randomStep();
/*!
* Perform a complete simulation of a failure trace by using the random number generator.
* The simulation starts in the initial state and tries to reach a state where the top-level event of the DFT has failed.
* If this target state can be reached within the given timebound, the simulation was successful.
*
* @param timebound Time bound in which the system failure should occur.
* @return True iff a system failure occurred for the generated trace within the time bound.
*/
bool simulateCompleteTrace(double timebound);
protected:
// The DFT used for the generation of next states.
storm::storage::DFT<ValueType> const& dft;
// General information for the state generation.
storm::storage::DFTStateGenerationInfo const& stateGenerationInfo;
// Generator for creating next state in DFT
storm::generator::DftNextStateGenerator<double> generator;
// Current state
DFTStatePointer state;
// Random number generator
boost::mt19937& randomGenerator;
};
}
}
}
Loading…
Cancel
Save