|
|
@ -1,9 +1,12 @@ |
|
|
|
#pragma once |
|
|
|
|
|
|
|
#include <cassert> |
|
|
|
#include <vector> |
|
|
|
#include <unordered_map> |
|
|
|
#include <utility> |
|
|
|
#include "DFTElementType.h" |
|
|
|
#include "DFTElements.h" |
|
|
|
#include "DFT.h" |
|
|
|
|
|
|
|
namespace storm { |
|
|
|
namespace storage { |
|
|
@ -34,14 +37,102 @@ namespace storage { |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
struct BEColourClass { |
|
|
|
BEColourClass() = default; |
|
|
|
BEColourClass(ValueType a, ValueType p, size_t h) : aRate(a), pRate(p), hash(h) {} |
|
|
|
|
|
|
|
ValueType aRate; |
|
|
|
ValueType pRate; |
|
|
|
size_t hash; |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
bool operator==(BEColourClass<ValueType> const& lhs, BEColourClass<ValueType> const& rhs) { |
|
|
|
return lhs.hash == rhs.hash && lhs.aRate == rhs.aRate && lhs.pRate == rhs.pRate; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
*/ |
|
|
|
template<typename ValueType> |
|
|
|
class BijectionCandidates { |
|
|
|
std::unordered_map<size_t, std::vector<size_t>> groupCandidates; |
|
|
|
std::unordered_map<std::pair<ValueType, ValueType>, std::vector<size_t>> beCandidates; |
|
|
|
struct BijectionCandidates { |
|
|
|
std::unordered_map<size_t, std::vector<size_t>> gateCandidates; |
|
|
|
std::unordered_map<BEColourClass<ValueType>, std::vector<size_t>> beCandidates; |
|
|
|
std::unordered_map<std::pair<ValueType, ValueType>, std::vector<size_t>> pdepCandidates; |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
class DFTColouring { |
|
|
|
DFT<ValueType> const& dft; |
|
|
|
std::unordered_map<size_t, size_t> gateColour; |
|
|
|
std::unordered_map<size_t, BEColourClass<ValueType>> beColour; |
|
|
|
std::unordered_map<size_t, std::pair<ValueType, ValueType>> depColour; |
|
|
|
GateGroupToHash gateColourizer; |
|
|
|
|
|
|
|
public: |
|
|
|
DFTColouring(DFT<ValueType> const& ft) : dft(ft) { |
|
|
|
for(size_t id = 0; id < dft.nrElements(); ++id ) { |
|
|
|
if(dft.isBasicElement(id)) { |
|
|
|
colourize(dft.getBasicElement(id)); |
|
|
|
} else if(dft.isGate(id)) { |
|
|
|
colourize(dft.getGate(id)); |
|
|
|
} else { |
|
|
|
assert(dft.isDependency(id)); |
|
|
|
colourize(dft.getDependency(id)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
BijectionCandidates<ValueType> colourSubdft(std::vector<size_t> const& subDftIndices) const { |
|
|
|
BijectionCandidates<ValueType> res; |
|
|
|
for (size_t index : subDftIndices) { |
|
|
|
if(dft.isBasicElement(index)) { |
|
|
|
auto it = res.beCandidates.find(beColour.at(index)); |
|
|
|
if(it != res.beCandidates.end()) { |
|
|
|
it->second.push_back(index); |
|
|
|
} else { |
|
|
|
res.beCandidates[beColour.at(index)] = std::vector<size_t>({index}); |
|
|
|
} |
|
|
|
} else if(dft.isGate(index)) { |
|
|
|
auto it = res.gateCandidates.find(gateColour.at(index)); |
|
|
|
if(it != res.gateCandidates.end()) { |
|
|
|
it->second.push_back(index); |
|
|
|
} else { |
|
|
|
res.gateCandidates[gateColour.at(index)] = std::vector<size_t>({index}); |
|
|
|
} |
|
|
|
} else { |
|
|
|
assert(dft.isDependency(index)); |
|
|
|
auto it = res.pdepCandidates.find(depColour.at(index)); |
|
|
|
if(it != res.pdepCandidates.end()) { |
|
|
|
it->second.push_back(index); |
|
|
|
} else { |
|
|
|
res.pdepCandidates[depColour.at(index)] = std::vector<size_t>({index}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
void colourize(std::shared_ptr<const DFTBE<ValueType>> const& be) { |
|
|
|
beColour[be->id()] = BEColourClass<ValueType>(be->activeFailureRate(), be->passiveFailureRate(), be->nrParents()); |
|
|
|
} |
|
|
|
|
|
|
|
void colourize(std::shared_ptr<const DFTGate<ValueType>> const& gate) { |
|
|
|
gateColour[gate->id()] = gateColourizer(gate->type(), gate->nrChildren(), gate->nrParents(), 0, gate->rank()); |
|
|
|
} |
|
|
|
|
|
|
|
void colourize(std::shared_ptr<const DFTDependency<ValueType>> const& dep) { |
|
|
|
depColour[dep->id()] = std::pair<ValueType, ValueType>(dep->probability(), dep->dependentEvent()->activeFailureRate()); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -107,36 +198,61 @@ namespace storage { |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
|
|
|
|
/** |
|
|
|
* Construct the initial bijection. |
|
|
|
*/ |
|
|
|
void constructInitialBijection() { |
|
|
|
assert(candidatesCompatible); |
|
|
|
// We first construct the currentPermutations, which helps to determine the current state of the check. |
|
|
|
for(auto const& colour : bright.beCandidates) { |
|
|
|
if(colour.second.size()>1) { |
|
|
|
currentPermutations.beCandidates.insert(colour); |
|
|
|
initializePermutationsAndTreatTrivialGroups(bleft.beCandidates, bright.beCandidates, currentPermutations.beCandidates); |
|
|
|
initializePermutationsAndTreatTrivialGroups(bleft.gateCandidates, bright.gateCandidates, currentPermutations.gateCandidates); |
|
|
|
initializePermutationsAndTreatTrivialGroups(bleft.pdepCandidates, bright.pdepCandidates, currentPermutations.pdepCandidates); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Construct the next bijection |
|
|
|
* @return true if a next bijection exists. |
|
|
|
*/ |
|
|
|
bool findNextBijection() { |
|
|
|
bool foundNext = false; |
|
|
|
if(!currentPermutations.beCandidates.empty()) { |
|
|
|
auto it = currentPermutations.beCandidates.begin(); |
|
|
|
while(!foundNext && it == currentPermutations.beCandidates.end()) { |
|
|
|
foundNext = std::next_permutation(it->second.begin(), it->second.end()); |
|
|
|
++it; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for(auto const& colour : bright.groupCandidates) { |
|
|
|
if(colour.second.size()>1) { |
|
|
|
currentPermutations.groupCandidates.insert(colour); |
|
|
|
if(!foundNext && !currentPermutations.gateCandidates.empty()) { |
|
|
|
auto it = currentPermutations.gateCandidates.begin(); |
|
|
|
while(!foundNext && it == currentPermutations.beCandidates.end()) { |
|
|
|
foundNext = std::next_permutation(it->second.begin(), it->second.end()); |
|
|
|
++it; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Constructing the initial homomorphism based on the right hand side instead of the current permutations allows us |
|
|
|
// to treat trivial and non-trivial classes in one go. |
|
|
|
for(auto const& colour : bleft.beCandidates) { |
|
|
|
zipVectorsIntoMap(colour.second, bright.beCandidates.find(colour.first)->second, bijection); |
|
|
|
if(!foundNext && !currentPermutations.pdepCandidates.empty()) { |
|
|
|
auto it = currentPermutations.pdepCandidates.begin(); |
|
|
|
while(!foundNext && it == currentPermutations.pdepCandidates.end()) { |
|
|
|
foundNext = std::next_permutation(it->second.begin(), it->second.end()); |
|
|
|
++it; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for(auto const& colour : bleft.groupCandidates) { |
|
|
|
zipVectorsIntoMap(colour.second, bright.groupCandidates.find(colour.first)->second, bijection); |
|
|
|
} |
|
|
|
if(foundNext) { |
|
|
|
for(auto const& colour : bleft.beCandidates) { |
|
|
|
zipVectorsIntoMap(colour.second, currentPermutations.beCandidates.find(colour.first)->second, bijection); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
for(auto const& colour : bleft.gateCandidates) { |
|
|
|
zipVectorsIntoMap(colour.second, currentPermutations.gateCandidates.find(colour.first)->second, bijection); |
|
|
|
} |
|
|
|
|
|
|
|
bool findNextBijection() { |
|
|
|
return false; |
|
|
|
for(auto const& colour : bleft.pdepCandidates) { |
|
|
|
zipVectorsIntoMap(colour.second, currentPermutations.pdepCandidates.find(colour.first)->second, bijection); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return foundNext; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -152,21 +268,21 @@ namespace storage { |
|
|
|
* Returns true if the colours are compatible. |
|
|
|
*/ |
|
|
|
bool checkCompatibility() { |
|
|
|
if(bleft.groupCandidates.size() != bright.groupCandidates.size()) { |
|
|
|
if(bleft.gateCandidates.size() != bright.gateCandidates.size()) { |
|
|
|
candidatesCompatible = false; |
|
|
|
} |
|
|
|
else if(bleft.beCandidates.size() != bright.beCandidates.size()) { |
|
|
|
candidatesCompatible = false; |
|
|
|
} |
|
|
|
else { |
|
|
|
for (auto const &gc : bleft.groupCandidates) { |
|
|
|
if (bright.groupCandidates.count(gc.first) == 0) { |
|
|
|
for (auto const &gc : bleft.gateCandidates) { |
|
|
|
if (bright.gateCandidates.count(gc.first) == 0) { |
|
|
|
candidatesCompatible = false; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if(candidatesCompatible) { |
|
|
|
for(auto const& bc : bleft.groupCandidates) { |
|
|
|
for(auto const& bc : bleft.gateCandidates) { |
|
|
|
if(bright.beCandidates.count(bc.first) == 0) { |
|
|
|
candidatesCompatible = false; |
|
|
|
break; |
|
|
@ -176,6 +292,26 @@ namespace storage { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* |
|
|
|
*/ |
|
|
|
template<typename ColourType> |
|
|
|
void initializePermutationsAndTreatTrivialGroups(std::unordered_map<ColourType, std::vector<size_t>> const& left, |
|
|
|
std::unordered_map<ColourType, std::vector<size_t>> const& right, |
|
|
|
std::unordered_map<ColourType, std::vector<size_t>>& permutations) { |
|
|
|
for(auto const& colour : right) { |
|
|
|
if(colour.second.size()>1) { |
|
|
|
auto it = permutations.insert(colour); |
|
|
|
std::sort(it->second.begin(), it->second.end()); |
|
|
|
zipVectorsIntoMap(colour.second, permutations.find(colour.first)->second, bijection); |
|
|
|
} else { |
|
|
|
assert(colour.second.size() == 1); |
|
|
|
assert(bijection.count(left[colour.first].front()) == 0); |
|
|
|
bijection[left[colour.first].front()] = colour.second.front(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Local helper function for the creation of bijections, should be hidden from api. |
|
|
|
*/ |
|
|
@ -184,7 +320,6 @@ namespace storage { |
|
|
|
assert(a.size() == b.size()); |
|
|
|
auto it = b.cbegin(); |
|
|
|
for(size_t lIndex : a) { |
|
|
|
assert(map.count(lIndex) == 0); |
|
|
|
map[lIndex] = *it; |
|
|
|
++it; |
|
|
|
} |
|
|
@ -199,3 +334,21 @@ namespace storage { |
|
|
|
|
|
|
|
} // namespace storm::dft |
|
|
|
} // namespace storm |
|
|
|
|
|
|
|
namespace std { |
|
|
|
template<typename ValueType> |
|
|
|
struct hash<storm::storage::BEColourClass<ValueType>> { |
|
|
|
size_t operator()(storm::storage::BEColourClass<ValueType> const& bcc) const { |
|
|
|
std::hash<ValueType> hasher; |
|
|
|
return (hasher(bcc.aRate) ^ hasher(bcc.pRate) << 8) | bcc.hash; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
struct hash<std::pair<ValueType, ValueType>> { |
|
|
|
size_t operator()(std::pair<ValueType, ValueType> const& p) const { |
|
|
|
std::hash<ValueType> hasher; |
|
|
|
return hasher(p.first) ^ hasher(p.second); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |