9template<
typename ValueType>
16 std::map<size_t, std::vector<std::vector<size_t>>> res;
19 for (
auto const& colourClass : completeCategories.
gateCandidates) {
20 findSymmetriesHelper(dft, colourClass.second, colouring, res);
24 for (
auto const& colourClass : completeCategories.
beCandidates) {
25 findSymmetriesHelper(dft, colourClass.second, colouring, res);
31template<
typename ValueType>
34 STORM_LOG_TRACE(
"Considering ids " << index1 <<
", " << index2 <<
" for isomorphism.");
35 bool sharedSpareMode =
false;
36 std::map<size_t, size_t> bijection;
48 bijection[index1] = index2;
57 std::vector<size_t> isubdft1 = dft.
getGate(index1)->independentSubDft(
false);
58 std::vector<size_t> isubdft2 = dft.
getGate(index2)->independentSubDft(
false);
59 if (isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) {
60 if (isubdft1.empty() && isubdft2.empty() && sparesAsLeaves) {
62 sharedSpareMode =
true;
63 isubdft1 = dft.
getGate(index1)->independentSubDft(
false,
true);
64 isubdft2 = dft.
getGate(index2)->independentSubDft(
false,
true);
65 if (isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) {
72 STORM_LOG_TRACE(
"Checking subdfts from " << index1 <<
", " << index2 <<
" for isomorphism.");
77 while (IsoCheck.findNextIsomorphism()) {
78 bijection = IsoCheck.getIsomorphism();
79 if (sharedSpareMode) {
80 bool bijectionSpareCompatible =
true;
81 for (
size_t elementId : isubdft1) {
82 if (dft.
getElement(elementId)->isSpareGate()) {
83 auto spareLeft = std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType>
const>(dft.
getElement(elementId));
85 std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType>
const>(dft.
getElement(bijection.at(elementId)));
87 if (spareLeft->nrChildren() != spareRight->nrChildren()) {
88 bijectionSpareCompatible =
false;
92 for (
size_t i = 0;
i < spareLeft->nrChildren(); ++
i) {
93 size_t childLeftId = spareLeft->children().at(i)->id();
94 size_t childRightId = spareRight->children().at(i)->id();
96 STORM_LOG_ASSERT(bijection.count(childLeftId) == 0,
"Child already part of bijection.");
97 if (childLeftId == childRightId) {
103 if (spareLeft->children().at(i)->nrParents() != 1 || spareRight->children().at(i)->nrParents() != 1) {
104 bijectionSpareCompatible =
false;
108 std::map<size_t, size_t> tmpBijection = findBijection(dft, childLeftId, childRightId, colouring,
false);
109 if (!tmpBijection.empty()) {
110 bijection.insert(tmpBijection.begin(), tmpBijection.end());
112 bijectionSpareCompatible =
false;
116 if (!bijectionSpareCompatible) {
121 if (bijectionSpareCompatible) {
131template<
typename ValueType>
134 std::map<
size_t, std::vector<std::vector<size_t>>>& result) {
135 if (candidates.size() <= 0) {
139 std::set<size_t> foundEqClassFor;
140 for (
auto it1 = candidates.cbegin(); it1 != candidates.cend(); ++it1) {
141 std::vector<std::vector<size_t>> symClass;
142 if (foundEqClassFor.count(*it1) > 0) {
147 if (!elem1->hasOnlyStaticParents()) {
150 if (hasSeqRestriction(elem1)) {
154 std::tuple<std::vector<size_t>, std::vector<size_t>, std::vector<size_t>, std::vector<size_t>> influencedElem1Ids = getInfluencedIds(dft, *it1);
156 for (++it2; it2 != candidates.cend(); ++it2) {
158 if (!elem2->hasOnlyStaticParents()) {
161 if (hasSeqRestriction(elem2)) {
165 if (influencedElem1Ids == getInfluencedIds(dft, *it2)) {
166 std::map<size_t, size_t> bijection = findBijection(dft, *it1, *it2, colouring,
true);
167 if (!bijection.empty()) {
169 foundEqClassFor.insert(*it2);
170 if (symClass.empty()) {
171 for (
auto const& i : bijection) {
172 symClass.push_back(std::vector<size_t>({
i.first}));
175 auto symClassIt = symClass.begin();
176 for (
auto const& i : bijection) {
177 symClassIt->emplace_back(
i.second);
184 if (!symClass.empty()) {
185 result.emplace(*it1, symClass);
190template<
typename ValueType>
192 for (
auto const& restr : elem->restrictions()) {
193 if (restr->isSeqEnforcer()) {
200template<
typename ValueType>
201std::tuple<std::vector<size_t>, std::vector<size_t>, std::vector<size_t>, std::vector<size_t>> SymmetryFinder<ValueType>::getInfluencedIds(
204 std::vector<size_t> parents = dft.
getElement(index)->parentIds();
205 std::sort(parents.begin(), parents.end());
207 std::vector<size_t> ingoingDeps;
209 for (
auto const& dep : dft.getBasicElement(index)->ingoingDependencies()) {
210 ingoingDeps.push_back(dep->id());
212 std::sort(ingoingDeps.begin(), ingoingDeps.end());
215 std::vector<size_t> outgoingDeps;
216 for (
auto const& dep : dft.getElement(index)->outgoingDependencies()) {
217 outgoingDeps.push_back(dep->id());
219 std::sort(outgoingDeps.begin(), outgoingDeps.end());
220 std::vector<size_t> restrictions;
221 for (
auto const& restr : dft.getElement(index)->restrictions()) {
222 restrictions.push_back(restr->id());
224 return std::make_tuple(parents, ingoingDeps, outgoingDeps, restrictions);
227template class SymmetryFinder<double>;
228template class SymmetryFinder<storm::RationalFunction>;
bool hasSameColour(size_t index1, size_t index2) const
BijectionCandidates< ValueType > colourSubdft(std::vector< size_t > const &subDftIndices) const
Represents a Dynamic Fault Tree.
DFTElementCPointer getElement(size_t index) const
Get a pointer to an element in the DFT.
size_t nrElements() const
std::shared_ptr< storm::dft::storage::elements::DFTGate< ValueType > const > getGate(size_t index) const
bool isGate(size_t index) const
bool isBasicElement(size_t index) const
Saves isomorphism between subtrees.
Abstract base class for DFT elements.
static storm::dft::storage::DftSymmetries findSymmetries(storm::dft::storage::DFT< ValueType > const &dft)
Find symmetries in the given DFT.
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
std::vector< T > buildVectorForRange(T min, T max)
Constructs a vector [min, min+1, ...., max-1].
std::unordered_map< size_t, std::vector< size_t > > gateCandidates
std::unordered_map< BEColourClass< ValueType >, std::vector< size_t > > beCandidates