Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DftSymmetries.cpp
Go to the documentation of this file.
1#include "DftSymmetries.h"
2
4
5namespace storm::dft {
6namespace storage {
7
8DftSymmetries::DftSymmetries(std::map<size_t, std::vector<std::vector<size_t>>> groups) : groups(groups) {
9 std::vector<size_t> sortedGroups;
10 for (auto const& cl : groups) {
11 sortedGroups.push_back(cl.first);
12 }
13 // Sort by length of symmetry or (if equal) by lower first element
14 std::sort(sortedGroups.begin(), sortedGroups.end(), [&](const size_t left, const size_t right) {
15 return groups.at(left).size() < groups.at(right).size() ||
16 (groups.at(left).size() == groups.at(right).size() && groups.at(left).front().front() < groups.at(right).front().front());
17 });
18
19 // Sort hierarchical
20 while (!sortedGroups.empty()) {
21 // Insert largest element
22 size_t currentRoot = sortedGroups.back();
23 sortedGroups.pop_back();
24 sortHierarchical(currentRoot, sortedGroups);
25 sortedSymmetries.push_back(currentRoot);
26 }
27}
28
30 return groups.size();
31}
32
33std::vector<size_t>::const_iterator DftSymmetries::begin() const {
34 return sortedSymmetries.begin();
35}
36
37std::vector<size_t>::const_iterator DftSymmetries::end() const {
38 return sortedSymmetries.end();
39}
40
41std::vector<std::vector<size_t>> const& DftSymmetries::getSymmetryGroup(size_t index) const {
42 STORM_LOG_ASSERT(groups.count(index) > 0, "Invalid index");
43 return groups.at(index);
44}
45
46bool DftSymmetries::existsInFirstSymmetry(size_t index, size_t value) const {
47 for (std::vector<size_t> symmetry : getSymmetryGroup(index)) {
48 if (symmetry.front() == value) {
49 return true;
50 }
51 }
52 return false;
53}
54
55bool DftSymmetries::existsInSymmetry(size_t index, size_t value) const {
56 for (std::vector<size_t> symmetry : getSymmetryGroup(index)) {
57 for (size_t index : symmetry) {
58 if (index == value) {
59 return true;
60 }
61 }
62 }
63 return false;
64}
65
66int DftSymmetries::applySymmetry(std::vector<std::vector<size_t>> const& symmetry, size_t value, size_t index) const {
67 for (std::vector<size_t> element : symmetry) {
68 if (element[0] == value) {
69 return element[index];
70 }
71 }
72 return -1;
73}
74
75std::vector<std::vector<size_t>> DftSymmetries::createSymmetry(std::vector<std::vector<size_t>> parentSymmetry, std::vector<std::vector<size_t>> childSymmetry,
76 size_t index) {
77 std::vector<std::vector<size_t>> result;
78 for (std::vector<size_t> childSym : childSymmetry) {
79 std::vector<size_t> symmetry;
80 for (size_t child : childSym) {
81 int bijectionValue = applySymmetry(parentSymmetry, child, index);
82 if (bijectionValue >= 0) {
83 symmetry.push_back(bijectionValue);
84 } else {
85 STORM_LOG_ASSERT(result.empty(), "Returning inconsistent result.");
86 return result;
87 }
88 }
89 result.push_back(symmetry);
90 }
91 return result;
92}
93
94void DftSymmetries::sortHierarchical(size_t parent, std::vector<size_t>& candidates) {
95 // Find subsymmetries of current symmetry
96 std::vector<size_t> children;
97 for (int i = candidates.size() - 1; i >= 0; --i) {
98 size_t currentRoot = candidates[i];
99 if (existsInSymmetry(parent, currentRoot)) {
100 // Is child
101 STORM_LOG_TRACE(currentRoot << " is child of " << parent);
102 children.insert(children.begin(), currentRoot);
103 candidates.erase(candidates.begin() + i); // Removing is okay as i is decremented
104 }
105 }
106
107 // Find child symmetries which are created by parent and other child symmetries
108 for (size_t i = 0; i < children.size(); ++i) {
109 // Iterate over all possible symmetry groups
110 for (size_t index = 1; index < groups.at(parent).front().size(); ++index) {
111 std::vector<std::vector<size_t>> possibleSymmetry = createSymmetry(groups.at(parent), groups.at(children[i]), index);
112 if (possibleSymmetry.empty()) {
113 // No symmetry created
114 break;
115 }
116 for (size_t j = 0; j < children.size(); /*manual increment*/) {
117 if (j == i) {
118 // Ignore identity
119 ++j;
120 continue;
121 }
122 if (possibleSymmetry == groups.at(children[j])) {
123 STORM_LOG_TRACE("Child " << children[j] << " ignored as created by symmetries " << parent << " and " << children[i]);
124 groups.erase(children[j]);
125 children.erase(children.begin() + j);
126 // Update iterator
127 if (i > j) {
128 --i;
129 }
130 } else {
131 // Consider next element
132 ++j;
133 }
134 }
135 }
136 }
137
138 // Apply sorting recursively
139 while (!children.empty()) {
140 // Insert largest element
141 size_t largestChild = children.back();
142 children.pop_back();
143 sortHierarchical(largestChild, children);
144 sortedSymmetries.push_back(largestChild);
145 }
146}
147
148std::ostream& operator<<(std::ostream& os, DftSymmetries const& symmetries) {
149 for (size_t index : symmetries.sortedSymmetries) {
150 os << "Symmetry group for " << index << '\n';
151 for (auto const& eqClass : symmetries.groups.at(index)) {
152 for (auto const& i : eqClass) {
153 os << i << " ";
154 }
155 os << '\n';
156 }
157 }
158 return os;
159}
160
161} // namespace storage
162} // namespace storm::dft
std::vector< std::vector< size_t > > const & getSymmetryGroup(size_t index) const
Get symmetry group corresponding to give top level index.
std::vector< size_t >::const_iterator begin() const
Retrieves an constant iterator that points to the beginning of the ordered symmetry groups.
std::vector< size_t >::const_iterator end() const
Retrieves an constant iterator that points past the last ordered symmetry group.
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
std::ostream & operator<<(std::ostream &os, DFTElementState st)