You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

194 lines
6.7 KiB

#include "test/storm_gtest.h"
#include "storm-config.h"
#include "storm-dft/api/storm-dft.h"
#include "storm-dft/transformations/DftTransformator.h"
#include "storm-dft/generator/DftNextStateGenerator.h"
#include "storm-dft/simulator/DFTTraceSimulator.h"
#include "storm-dft/storage/dft/SymmetricUnits.h"
#include "storm-dft/storage/dft/DFTIsomorphism.h"
#include "storm-parsers/api/storm-parsers.h"
namespace {
// Configurations for DFT traces
struct DftTracesConfig {
bool useDC;
bool useSR;
};
class NoOptimizationsConfig {
public:
typedef double ValueType;
static DftTracesConfig createConfig() {
return DftTracesConfig{false, false};
}
};
class DontCareConfig {
public:
typedef double ValueType;
static DftTracesConfig createConfig() {
return DftTracesConfig{true, false};
}
};
class SymmetryReductionConfig {
public:
typedef double ValueType;
static DftTracesConfig createConfig() {
return DftTracesConfig{false, true};
}
};
class AllOptimizationsConfig {
public:
typedef double ValueType;
static DftTracesConfig createConfig() {
return DftTracesConfig{true, true};
}
};
// General base class for testing of generating DFT traces.
template<typename TestType>
class DftTraceGeneratorTest : public ::testing::Test {
public:
typedef typename TestType::ValueType ValueType;
DftTraceGeneratorTest() : config(TestType::createConfig()) {
}
DftTracesConfig const& getConfig() const {
return config;
}
std::pair<std::shared_ptr<storm::storage::DFT<double>>, storm::storage::DFTStateGenerationInfo> prepareDFT(std::string const& file) {
// Load, build and prepare DFT
storm::transformations::dft::DftTransformator<double> dftTransformator = storm::transformations::dft::DftTransformator<double>();
std::shared_ptr<storm::storage::DFT<double>> dft = dftTransformator.transformBinaryFDEPs(*(storm::api::loadDFTGalileoFile<double>(file)));
EXPECT_TRUE(storm::api::isWellFormed(*dft).first);
// Compute relevant events
std::vector<std::string> relevantNames;
if (!config.useDC) {
relevantNames.push_back("all");
}
storm::utility::RelevantEvents relevantEvents = storm::api::computeRelevantEvents<double>(*dft, {}, relevantNames, false);
dft->setRelevantEvents(relevantEvents);
// Find symmetries
std::map<size_t, std::vector<std::vector<size_t>>> emptySymmetry;
storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry);
if (config.useSR) {
auto colouring = dft->colourDFT();
symmetries = dft->findSymmetries(colouring);
}
EXPECT_EQ(config.useSR && config.useDC, !symmetries.sortedSymmetries.empty());
storm::storage::DFTStateGenerationInfo stateGenerationInfo(dft->buildStateGenerationInfo(symmetries));
return std::make_pair(dft, stateGenerationInfo);
}
private:
DftTracesConfig config;
};
typedef ::testing::Types<
NoOptimizationsConfig,
DontCareConfig,
SymmetryReductionConfig,
AllOptimizationsConfig
> TestingTypes;
TYPED_TEST_SUITE(DftTraceGeneratorTest, TestingTypes,);
TYPED_TEST(DftTraceGeneratorTest, And) {
auto pair = this->prepareDFT(STORM_TEST_RESOURCES_DIR "/dft/and.dft");
auto dft = pair.first;
storm::generator::DftNextStateGenerator<double> generator(*dft, pair.second);
// Start with initial state
auto state = generator.createInitialState();
EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
bool changed = state->orderBySymmetry();
EXPECT_FALSE(changed);
// Let C fail
auto iterFailable = state->getFailableElements().begin();
ASSERT_NE(iterFailable, state->getFailableElements().end());
++iterFailable;
ASSERT_NE(iterFailable, state->getFailableElements().end());
auto nextBEPair = iterFailable.getFailBE(*dft);
auto nextBE = nextBEPair.first;
auto triggerDep = nextBEPair.second;
ASSERT_TRUE(nextBE);
ASSERT_FALSE(triggerDep);
ASSERT_EQ(nextBE->name(), "C");
state = generator.createSuccessorState(state, nextBE, triggerDep);
EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
changed = state->orderBySymmetry();
EXPECT_EQ(this->getConfig().useSR && this->getConfig().useDC, changed);
if (this->getConfig().useSR && this->getConfig().useDC) {
EXPECT_TRUE(state->hasFailed(0));
} else {
EXPECT_TRUE(state->hasFailed(1));
}
// Let B fail
iterFailable = state->getFailableElements().begin();
ASSERT_NE(iterFailable, state->getFailableElements().end());
nextBEPair = iterFailable.getFailBE(*dft);
nextBE = nextBEPair.first;
triggerDep = nextBEPair.second;
ASSERT_TRUE(nextBE);
ASSERT_FALSE(triggerDep);
if (this->getConfig().useSR && this->getConfig().useDC){
// TODO: Apply symmetry to failable elements as well
return;
ASSERT_EQ(nextBE->name(), "C");
} else {
ASSERT_EQ(nextBE->name(), "B");
}
state = generator.createSuccessorState(state, nextBE, triggerDep);
changed = state->orderBySymmetry();
EXPECT_FALSE(changed);
EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
}
TYPED_TEST(DftTraceGeneratorTest, RandomStepsAnd) {
auto pair = this->prepareDFT(STORM_TEST_RESOURCES_DIR "/dft/and.dft");
auto dft = pair.first;
// Init random number generator
boost::mt19937 gen(5u);
storm::dft::simulator::DFTTraceSimulator<double> simulator(*dft, pair.second, gen);
auto state = simulator.getCurrentState();
EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
// First random step
double timebound = simulator.randomStep();
#if BOOST_VERSION > 106400
// Older Boost versions yield different value
EXPECT_FLOAT_EQ(timebound, 0.522079);
#endif
state = simulator.getCurrentState();
EXPECT_FALSE(state->hasFailed(dft->getTopLevelIndex()));
timebound = simulator.randomStep();
#if BOOST_VERSION > 106400
// Older Boost versions yield different value
EXPECT_FLOAT_EQ(timebound, 0.9497214);
#endif
state = simulator.getCurrentState();
EXPECT_TRUE(state->hasFailed(dft->getTopLevelIndex()));
}
}