Matthias Volk
4 years ago
No known key found for this signature in database
GPG Key ID: 83A57678F739FCD3
2 changed files with 221 additions and 0 deletions
@ -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>; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -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; |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue