Browse Source
Implemented modularisation for MTTF via parallel composition of CTMCs
Implemented modularisation for MTTF via parallel composition of CTMCs
Former-commit-id: 552949346b
main
6 changed files with 392 additions and 44 deletions
-
172src/builder/ParallelCompositionBuilder.cpp
-
24src/builder/ParallelCompositionBuilder.h
-
218src/modelchecker/dft/DFTModelChecker.cpp
-
14src/modelchecker/dft/DFTModelChecker.h
-
2src/storage/dft/DFT.cpp
-
6src/storm-dyftee.cpp
@ -0,0 +1,172 @@ |
|||
#include "src/builder/ParallelCompositionBuilder.h"
|
|||
#include "src/models/sparse/StandardRewardModel.h"
|
|||
#include <src/utility/constants.h>
|
|||
|
|||
namespace storm { |
|||
namespace builder { |
|||
|
|||
template<typename ValueType> |
|||
std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> ParallelCompositionBuilder<ValueType>::compose(std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> const& ctmcA, std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> const& ctmcB, bool labelAnd) { |
|||
STORM_LOG_TRACE("Parallel composition"); |
|||
|
|||
storm::storage::SparseMatrix<ValueType> matrixA = ctmcA->getTransitionMatrix(); |
|||
storm::storage::SparseMatrix<ValueType> matrixB = ctmcB->getTransitionMatrix(); |
|||
storm::models::sparse::StateLabeling labelingA = ctmcA->getStateLabeling(); |
|||
storm::models::sparse::StateLabeling labelingB = ctmcB->getStateLabeling(); |
|||
size_t sizeA = ctmcA->getNumberOfStates(); |
|||
size_t sizeB = ctmcB->getNumberOfStates(); |
|||
size_t size = sizeA * sizeB; |
|||
size_t rowIndex = 0; |
|||
|
|||
// Build matrix
|
|||
storm::storage::SparseMatrixBuilder<ValueType> builder(size, size, 0, true, false, 0); |
|||
|
|||
for (size_t stateA = 0; stateA < sizeA; ++stateA) { |
|||
for (size_t stateB = 0; stateB < sizeB; ++stateB) { |
|||
STORM_LOG_ASSERT(rowIndex == stateA * sizeB + stateB, "Row " << rowIndex << " is not correct"); |
|||
|
|||
auto rowA = matrixA.getRow(stateA); |
|||
auto itA = rowA.begin(); |
|||
auto rowB = matrixB.getRow(stateB); |
|||
auto itB = rowB.begin(); |
|||
|
|||
// First consider all target states of A < the current stateA
|
|||
while (itA != rowA.end() && itA->getColumn() < stateA) { |
|||
builder.addNextValue(rowIndex, itA->getColumn() * sizeB + stateB, itA->getValue()); |
|||
++itA; |
|||
} |
|||
|
|||
// Then consider all target states of B
|
|||
while (itB != rowB.end()) { |
|||
builder.addNextValue(rowIndex, stateA * sizeB + itB->getColumn(), itB->getValue()); |
|||
++itB; |
|||
} |
|||
|
|||
// Last consider all remaining target states of A > the current stateA
|
|||
while (itA != rowA.end()) { |
|||
builder.addNextValue(rowIndex, itA->getColumn() * sizeB + stateB, itA->getValue()); |
|||
++itA; |
|||
} |
|||
|
|||
++rowIndex; |
|||
} |
|||
} |
|||
|
|||
storm::storage::SparseMatrix<ValueType> matrixComposed = builder.build(); |
|||
STORM_LOG_ASSERT(matrixComposed.getRowCount() == size, "Row count is not correct"); |
|||
STORM_LOG_ASSERT(matrixComposed.getColumnCount() == size, "Column count is not correct"); |
|||
|
|||
// Build labeling
|
|||
storm::models::sparse::StateLabeling labeling = storm::models::sparse::StateLabeling(sizeA * sizeB); |
|||
|
|||
if (labelAnd) { |
|||
for (std::string const& label : labelingA.getLabels()) { |
|||
if (labelingB.containsLabel(label)) { |
|||
// Only consider labels contained in both CTMCs
|
|||
storm::storage::BitVector labelStates(size, false); |
|||
for (auto entryA : labelingA.getStates(label)) { |
|||
for (auto entryB : labelingB.getStates(label)) { |
|||
labelStates.set(entryA * sizeB + entryB); |
|||
} |
|||
} |
|||
labeling.addLabel(label, labelStates); |
|||
} |
|||
} |
|||
} else { |
|||
// Set labels from A
|
|||
for (std::string const& label : labelingA.getLabels()) { |
|||
if (label == "init") { |
|||
// Initial states must be initial in both CTMCs
|
|||
STORM_LOG_ASSERT(labelingB.containsLabel(label), "B does not have init."); |
|||
storm::storage::BitVector labelStates(size, false); |
|||
for (auto entryA : labelingA.getStates(label)) { |
|||
for (auto entryB : labelingB.getStates(label)) { |
|||
labelStates.set(entryA * sizeB + entryB); |
|||
} |
|||
} |
|||
labeling.addLabel(label, labelStates); |
|||
} else { |
|||
storm::storage::BitVector labelStates(size, false); |
|||
for (auto entry : labelingA.getStates(label)) { |
|||
for (size_t index = entry * sizeB; index < entry * sizeB + sizeB; ++index) { |
|||
labelStates.set(index, true); |
|||
} |
|||
} |
|||
labeling.addLabel(label, labelStates); |
|||
} |
|||
} |
|||
// Set labels from B
|
|||
for (std::string const& label : labelingB.getLabels()) { |
|||
if (label == "init") { |
|||
continue; |
|||
} |
|||
if (labeling.containsLabel(label)) { |
|||
// Label is already there from A
|
|||
for (auto entry : labelingB.getStates(label)) { |
|||
for (size_t index = 0; index < sizeA; ++index) { |
|||
labeling.addLabelToState(label, index * sizeB + entry); |
|||
} |
|||
} |
|||
} else { |
|||
storm::storage::BitVector labelStates(size, false); |
|||
for (auto entry : labelingB.getStates(label)) { |
|||
for (size_t index = 0; index < sizeA; ++index) { |
|||
labelStates.set(index * sizeB + entry, true); |
|||
} |
|||
} |
|||
labeling.addLabel(label, labelStates); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
// Build CTMC
|
|||
std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> composedCtmc = std::make_shared<storm::models::sparse::Ctmc<ValueType>>(matrixComposed, labeling); |
|||
|
|||
// Print for debugging
|
|||
/*std::cout << "Matrix A:" << std::endl;
|
|||
std::cout << matrixA << std::endl; |
|||
std::cout << "Matrix B:" << std::endl; |
|||
std::cout << matrixB << std::endl; |
|||
std::cout << "Composed matrix: " << std::endl << matrixComposed; |
|||
std::cout << "Labeling A" << std::endl; |
|||
labelingA.printLabelingInformationToStream(std::cout); |
|||
for (size_t stateA = 0; stateA < sizeA; ++stateA) { |
|||
std::cout << "State " << stateA << ": "; |
|||
for (auto label : labelingA.getLabelsOfState(stateA)) { |
|||
std::cout << label << ", "; |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
std::cout << "Labeling B" << std::endl; |
|||
labelingB.printLabelingInformationToStream(std::cout); |
|||
for (size_t stateB = 0; stateB < sizeB; ++stateB) { |
|||
std::cout << "State " << stateB << ": "; |
|||
for (auto label : labelingB.getLabelsOfState(stateB)) { |
|||
std::cout << label << ", "; |
|||
} |
|||
std::cout << std::endl; |
|||
} |
|||
std::cout << "Labeling Composed" << std::endl; |
|||
labeling.printLabelingInformationToStream(std::cout); |
|||
for (size_t state = 0; state < size; ++state) { |
|||
std::cout << "State " << state << ": "; |
|||
for (auto label : labeling.getLabelsOfState(state)) { |
|||
std::cout << label << ", "; |
|||
} |
|||
std::cout << std::endl; |
|||
}*/ |
|||
|
|||
return composedCtmc; |
|||
} |
|||
|
|||
|
|||
// Explicitly instantiate the class.
|
|||
template class ParallelCompositionBuilder<double>; |
|||
|
|||
#ifdef STORM_HAVE_CARL
|
|||
template class ParallelCompositionBuilder<storm::RationalFunction>; |
|||
#endif
|
|||
|
|||
} // namespace builder
|
|||
} // namespace storm
|
@ -0,0 +1,24 @@ |
|||
#ifndef PARALLELCOMPOSITIONBUILDER_H |
|||
#define PARALLELCOMPOSITIONBUILDER_H |
|||
|
|||
#include <src/models/sparse/Ctmc.h> |
|||
|
|||
namespace storm { |
|||
namespace builder { |
|||
|
|||
/*! |
|||
* Build a parallel composition of Markov chains. |
|||
*/ |
|||
template<typename ValueType> |
|||
class ParallelCompositionBuilder { |
|||
|
|||
public: |
|||
|
|||
static std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> compose(std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> const& ctmcA, std::shared_ptr<storm::models::sparse::Ctmc<ValueType>> const& ctmcB, bool labelAnd); |
|||
|
|||
}; |
|||
|
|||
} |
|||
} |
|||
|
|||
#endif /* EXPLICITDFTMODELBUPARALLELCOMPOSITIONBUILDER_HILDERAPPROX_H */ |
Reference in new issue
xxxxxxxxxx