10template<
typename ValueType>
17 std::map<size_t, std::vector<std::vector<size_t>>> res;
20 for (
auto const& colourClass : completeCategories.
gateCandidates) {
21 findSymmetriesHelper(dft, colourClass.second, colouring, res);
25 for (
auto const& colourClass : completeCategories.
beCandidates) {
26 findSymmetriesHelper(dft, colourClass.second, colouring, res);
32template<
typename ValueType>
35 STORM_LOG_TRACE(
"Considering ids " << index1 <<
", " << index2 <<
" for isomorphism.");
36 bool sharedSpareMode =
false;
37 std::map<size_t, size_t> bijection;
49 bijection[index1] = index2;
58 std::vector<size_t> isubdft1 = dft.
getGate(index1)->independentSubDft(
false);
59 std::vector<size_t> isubdft2 = dft.
getGate(index2)->independentSubDft(
false);
60 if (isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) {
61 if (isubdft1.empty() && isubdft2.empty() && sparesAsLeaves) {
63 sharedSpareMode =
true;
64 isubdft1 = dft.
getGate(index1)->independentSubDft(
false,
true);
65 isubdft2 = dft.
getGate(index2)->independentSubDft(
false,
true);
66 if (isubdft1.empty() || isubdft2.empty() || isubdft1.size() != isubdft2.size()) {
73 STORM_LOG_TRACE(
"Checking subdfts from " << index1 <<
", " << index2 <<
" for isomorphism.");
78 while (IsoCheck.findNextIsomorphism()) {
79 bijection = IsoCheck.getIsomorphism();
80 if (sharedSpareMode) {
81 bool bijectionSpareCompatible =
true;
82 for (
size_t elementId : isubdft1) {
83 if (dft.
getElement(elementId)->isSpareGate()) {
84 auto spareLeft = std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType>
const>(dft.
getElement(elementId));
86 std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType>
const>(dft.
getElement(bijection.at(elementId)));
88 if (spareLeft->nrChildren() != spareRight->nrChildren()) {
89 bijectionSpareCompatible =
false;
93 for (
size_t i = 0;
i < spareLeft->nrChildren(); ++
i) {
94 size_t childLeftId = spareLeft->children().at(i)->id();
95 size_t childRightId = spareRight->children().at(i)->id();
97 STORM_LOG_ASSERT(bijection.count(childLeftId) == 0,
"Child already part of bijection.");
98 if (childLeftId == childRightId) {
104 if (spareLeft->children().at(i)->nrParents() != 1 || spareRight->children().at(i)->nrParents() != 1) {
105 bijectionSpareCompatible =
false;
109 std::map<size_t, size_t> tmpBijection = findBijection(dft, childLeftId, childRightId, colouring,
false);
110 if (!tmpBijection.empty()) {
111 bijection.insert(tmpBijection.begin(), tmpBijection.end());
113 bijectionSpareCompatible =
false;
117 if (!bijectionSpareCompatible) {
122 if (bijectionSpareCompatible) {
132template<
typename ValueType>
135 std::map<
size_t, std::vector<std::vector<size_t>>>& result) {
136 if (candidates.size() <= 0) {
140 std::set<size_t> foundEqClassFor;
141 for (
auto it1 = candidates.cbegin(); it1 != candidates.cend(); ++it1) {
142 std::vector<std::vector<size_t>> symClass;
143 if (foundEqClassFor.count(*it1) > 0) {
148 if (!elem1->hasOnlyStaticParents()) {
151 if (hasSeqRestriction(elem1)) {
155 std::tuple<std::vector<size_t>, std::vector<size_t>, std::vector<size_t>, std::vector<size_t>> influencedElem1Ids = getInfluencedIds(dft, *it1);
157 for (++it2; it2 != candidates.cend(); ++it2) {
159 if (!elem2->hasOnlyStaticParents()) {
162 if (hasSeqRestriction(elem2)) {
166 if (influencedElem1Ids == getInfluencedIds(dft, *it2)) {
167 std::map<size_t, size_t> bijection = findBijection(dft, *it1, *it2, colouring,
true);
168 if (!bijection.empty()) {
170 foundEqClassFor.insert(*it2);
171 if (symClass.empty()) {
172 for (
auto const& i : bijection) {
173 symClass.push_back(std::vector<size_t>({
i.first}));
176 auto symClassIt = symClass.begin();
177 for (
auto const& i : bijection) {
178 symClassIt->emplace_back(
i.second);
185 if (!symClass.empty()) {
186 result.emplace(*it1, symClass);
191template<
typename ValueType>
193 for (
auto const& restr : elem->restrictions()) {
194 if (restr->isSeqEnforcer()) {
201template<
typename ValueType>
202std::tuple<std::vector<size_t>, std::vector<size_t>, std::vector<size_t>, std::vector<size_t>> SymmetryFinder<ValueType>::getInfluencedIds(
205 std::vector<size_t> parents = dft.
getElement(index)->parentIds();
206 std::sort(parents.begin(), parents.end());
208 std::vector<size_t> ingoingDeps;
210 for (
auto const& dep : dft.getBasicElement(index)->ingoingDependencies()) {
211 ingoingDeps.push_back(dep->id());
213 std::sort(ingoingDeps.begin(), ingoingDeps.end());
216 std::vector<size_t> outgoingDeps;
217 for (
auto const& dep : dft.getElement(index)->outgoingDependencies()) {
218 outgoingDeps.push_back(dep->id());
220 std::sort(outgoingDeps.begin(), outgoingDeps.end());
221 std::vector<size_t> restrictions;
222 for (
auto const& restr : dft.getElement(index)->restrictions()) {
223 restrictions.push_back(restr->id());
225 return std::make_tuple(parents, ingoingDeps, outgoingDeps, restrictions);
228template class SymmetryFinder<double>;
229template 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