PermLib
|
00001 // --------------------------------------------------------------------------- 00002 // 00003 // This file is part of PermLib. 00004 // 00005 // Copyright (c) 2009-2012 Thomas Rehn <thomas@carmen76.de> 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions 00010 // are met: 00011 // 1. Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 3. The name of the author may not be used to endorse or promote products 00017 // derived from this software without specific prior written permission. 00018 // 00019 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00020 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00021 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00022 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00023 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00024 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00028 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 // 00030 // --------------------------------------------------------------------------- 00031 00032 00033 #ifndef TYPERECOGNITIONHEURISTIC_H_ 00034 #define TYPERECOGNITIONHEURISTIC_H_ 00035 00036 #include <list> 00037 #include <vector> 00038 00039 #include <boost/iterator/counting_iterator.hpp> 00040 #include <boost/pending/disjoint_sets.hpp> 00041 00042 namespace permlib { 00043 00045 00049 template <class PERM> 00050 class SymmetricGroupRecognitionHeuristic { 00051 public: 00056 SymmetricGroupRecognitionHeuristic(unsigned int n, bool storeUnusedGenerators = false); 00057 00059 00063 bool addGenerator(const PERM& p); 00065 00068 void symmetricGroupOrbits(std::vector<std::list<dom_int> >& orbits); 00069 00071 const std::list<PERM>& unusedGenerators() { return m_unusedGenerators; } 00072 private: 00073 bool addUnusedGenerator(const PERM& p); 00074 00075 unsigned int m_n; 00076 bool m_storeUnusedGenerators; 00077 std::list<PERM> m_unusedGenerators; 00078 00079 std::vector<dom_int> m_rank; 00080 std::vector<dom_int> m_parent; 00081 boost::disjoint_sets<dom_int*,dom_int*> m_components; 00082 00083 }; 00084 00085 // 00086 // ---- IMPLEMENTATION 00087 // 00088 00089 template <class PERM> 00090 SymmetricGroupRecognitionHeuristic<PERM>::SymmetricGroupRecognitionHeuristic(unsigned int n, bool storeUnusedGenerators) 00091 : m_n(n), m_storeUnusedGenerators(storeUnusedGenerators), m_rank(n), m_parent(n), m_components(&m_rank[0], &m_parent[0]) 00092 { 00093 for (dom_int i = 0; i < n; ++i) 00094 m_components.make_set(i); 00095 } 00096 00097 00098 template <class PERM> 00099 bool SymmetricGroupRecognitionHeuristic<PERM>::addGenerator(const PERM& p) { 00100 BOOST_ASSERT( p.size() == m_n ); 00101 00102 dom_int cycle[2]; 00103 unsigned int cycleIndex = 0; 00104 00105 for (unsigned int i = 0; i < p.size(); ++i) { 00106 if (p.at(i) != i) { 00107 if (cycleIndex >= 2) 00108 return addUnusedGenerator(p); 00109 00110 cycle[cycleIndex++] = i; 00111 } 00112 } 00113 00114 if (cycleIndex == 0) 00115 // discard identity 00116 return true; 00117 00118 BOOST_ASSERT(cycleIndex == 2); 00119 00120 m_components.union_set(cycle[0], cycle[1]); 00121 return true; 00122 } 00123 00124 00125 template <class PERM> 00126 void SymmetricGroupRecognitionHeuristic<PERM>::symmetricGroupOrbits(std::vector<std::list<dom_int> >& orbits) { 00127 m_components.compress_sets(boost::counting_iterator<dom_int>(0), boost::counting_iterator<dom_int>(m_n)); 00128 00129 std::vector<unsigned int> componentSizes(m_n); 00130 for (unsigned int i = 0; i < m_n; ++i) { 00131 ++componentSizes[ m_components.find_set(i) ]; 00132 } 00133 00134 std::vector<int> nonTrivialComponentMap(m_n, -1); 00135 unsigned int nonTrivialIndex = 0; 00136 for (unsigned int i = 0; i < m_n; ++i) { 00137 if (componentSizes[i] > 1) 00138 nonTrivialComponentMap[i] = nonTrivialIndex++; 00139 } 00140 00141 orbits.clear(); 00142 orbits.resize(nonTrivialIndex); 00143 00144 for (unsigned int i = 0; i < m_n; ++i) { 00145 unsigned int componentIndex = m_components.find_set(i); 00146 if (nonTrivialComponentMap[componentIndex] >= 0) 00147 orbits[ nonTrivialComponentMap[componentIndex] ].push_back(i); 00148 } 00149 } 00150 00151 00152 template <class PERM> 00153 bool SymmetricGroupRecognitionHeuristic<PERM>::addUnusedGenerator(const PERM& p) { 00154 m_unusedGenerators.push_back(p); 00155 return false; 00156 } 00157 00158 } // end NS 00159 00160 #endif // -- TYPERECOGNITIONHEURISTIC_H_