| 
						
						
						
					 | 
				
				 | 
				
					@ -1,19 +1,123 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#pragma once | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "src/utility/macros.h" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					    namespace storage { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        struct DFTIndependentSymmetries { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::map<size_t, std::vector<std::vector<size_t>>> groups; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<size_t> sortedSymmetries; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            bool existsInFirstSymmetry(size_t index, size_t value) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (std::vector<size_t> symmetry : groups[index]) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (symmetry.front() == value) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            bool existsInSymmetry(size_t index, size_t value) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (std::vector<size_t> symmetry : groups[index]) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for (size_t index : symmetry) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (index == value) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            return true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            /** | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             * Apply symmetry and get bijection. Result is symmetry(value)[index] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             * | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             * @param symmetry The symmetry. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             * @param value The value to apply the bijection to. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             * @param index The index of the symmetry group to apply. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             * @return Symmetric value, -1 if the bijection could not be applied. | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            int applySymmetry(std::vector<std::vector<size_t>> const& symmetry, size_t value, size_t index) const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (std::vector<size_t> element : symmetry) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (element[0] == value) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        return element[index]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return -1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<std::vector<size_t>> createSymmetry(std::vector<std::vector<size_t>> parentSymmetry, std::vector<std::vector<size_t>> childSymmetry, size_t index) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::vector<std::vector<size_t>> result; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (std::vector<size_t> childSymmetry : childSymmetry) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::vector<size_t> symmetry; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for (size_t child : childSymmetry) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        int bijectionValue = applySymmetry(parentSymmetry, child, index); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (bijectionValue >= 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            symmetry.push_back(bijectionValue); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            return result; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    result.push_back(symmetry); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return result; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            void sortHierarchical(size_t parent, std::vector<size_t>& candidates) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::vector<size_t> children; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (int i = candidates.size() - 1; i >= 0; --i) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    size_t currentRoot = candidates[i]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (existsInSymmetry(parent, currentRoot)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Is child | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        STORM_LOG_TRACE(currentRoot << " is child of " << parent); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        children.insert(children.begin(), currentRoot); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        candidates.erase(candidates.begin()+i); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (size_t i = 0; i < children.size(); ++i) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::vector<std::vector<size_t>> possibleSymmetry = createSymmetry(groups.at(parent), groups.at(children[i]), 1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for (size_t j = i + 1; j < children.size(); ++j) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (possibleSymmetry == groups.at(children[j])) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            STORM_LOG_TRACE("Child " << children[j] << " ignored as created by symmetries " << parent << " and " << children[j]); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            groups.erase(children[j]); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            children.erase(children.begin() + j); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                while (!children.empty()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // Insert largest element | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    size_t largestChild = children.back(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    children.pop_back(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    sortHierarchical(largestChild, children); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    sortedSymmetries.push_back(largestChild); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					             | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            DFTIndependentSymmetries(std::map<size_t, std::vector<std::vector<size_t>>> groups) : groups(groups) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::vector<size_t> sortedGroups; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (auto const& cl : groups) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    sortedGroups.push_back(cl.first); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Sort by length of symmetry | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::sort(sortedGroups.begin(), sortedGroups.end(), [&](const size_t left, const size_t right) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return groups.at(left).size() < groups.at(right).size(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                }); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Sort hierarchical | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                while (!sortedGroups.empty()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // Insert largest element | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    size_t currentRoot = sortedGroups.back(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    sortedGroups.pop_back(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    sortHierarchical(currentRoot, sortedGroups); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    sortedSymmetries.push_back(currentRoot); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        }; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					         | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        inline std::ostream& operator<<(std::ostream& os, DFTIndependentSymmetries const& s)  { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for(auto const& cl : s.groups) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                os << "Symmetry group for " << cl.first << std::endl; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for(auto const& eqClass : cl.second) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            for(size_t index : s.sortedSymmetries) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                os << "Symmetry group for " << index << std::endl; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for(auto const& eqClass : s.groups.at(index)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    for(auto const& i : eqClass) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        os << i << " "; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |