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 #include <boost/shared_ptr.hpp> 00033 00034 #include <algorithm> 00035 #include <map> 00036 #include <permlib/abstract_permutation_group.h> 00037 00038 #ifndef ABSTRACT_SYMMETRIC_PRODUCT_H_ 00039 #define ABSTRACT_SYMMETRIC_PRODUCT_H_ 00040 00041 namespace permlib { 00042 00044 class AbstractSymmetricProduct : public AbstractPermutationGroup { 00045 public: 00047 00054 template<typename InputIterator> 00055 AbstractSymmetricProduct(InputIterator begin, InputIterator end) { 00056 for (InputIterator it = begin; it != end; ++it) { 00057 m_indices.push_back(std::set<dom_int>((*it).begin(), (*it).end())); 00058 } 00059 } 00060 00061 virtual AbstractPermutationGroup* setStabilizer(const std::vector<dom_int>& s) const; 00062 virtual OrbitList* orbits() const; 00063 // TODO: must s be sorted? 00064 virtual OrbitList* orbits(const std::vector<dom_int>& s) const; 00065 00066 virtual bool isLexMinSet(const std::vector<dom_int>& setIndices, const std::vector<dom_int>& rankIndices) const; 00067 00068 virtual AbstractGroupType type() const { return AGT_SymmetricProduct; } 00069 protected: 00070 virtual void transversalSizes(std::vector<unsigned long>& sizes) const; 00071 00072 private: 00073 AbstractSymmetricProduct() {} 00074 00075 typedef std::list<std::set<dom_int> > IndexList; 00076 std::list<std::set<dom_int> > m_indices; 00077 mutable std::map<dom_int, dom_int> m_indicesReverse; 00078 00079 int getOrbitRank(dom_int x) const; 00080 }; 00081 00082 inline void AbstractSymmetricProduct::transversalSizes(std::vector<unsigned long>& sizes) const { 00083 sizes.clear(); 00084 sizes.reserve(m_indices.size()); 00085 BOOST_FOREACH(const std::set<dom_int>& ind, m_indices) { 00086 for (unsigned long x = ind.size(); x > 1; --x) 00087 sizes.push_back(x); 00088 } 00089 } 00090 00091 inline AbstractPermutationGroup* AbstractSymmetricProduct::setStabilizer(const std::vector<dom_int>& svec) const { 00092 std::set<dom_int> s(svec.begin(), svec.end()); 00093 00094 AbstractSymmetricProduct* stabilizer = new AbstractSymmetricProduct(); 00095 BOOST_FOREACH(const std::set<dom_int>& ind, m_indices) { 00096 std::set<dom_int> sA, sB; 00097 std::set_difference(ind.begin(), ind.end(), s.begin(), s.end(), std::inserter(sA, sA.begin())); 00098 if (sA.size() > 1) { 00099 stabilizer->m_indices.push_back(sA); 00100 } 00101 std::set_intersection(ind.begin(), ind.end(), s.begin(), s.end(), std::inserter(sB, sB.begin())); 00102 if (sB.size() > 1) { 00103 stabilizer->m_indices.push_back(sB); 00104 } 00105 } 00106 return stabilizer; 00107 } 00108 00109 inline AbstractPermutationGroup::OrbitList* AbstractSymmetricProduct::orbits() const { 00110 OrbitList* retList = new OrbitList(m_indices); 00111 return retList; 00112 } 00113 00114 inline AbstractPermutationGroup::OrbitList* AbstractSymmetricProduct::orbits(const std::vector<dom_int>& s) const { 00115 OrbitList* retList = new OrbitList(); 00116 BOOST_FOREACH(const std::set<dom_int>& ind, m_indices) { 00117 std::set<dom_int>::const_iterator indIt = std::find_first_of(ind.begin(), ind.end(), s.begin(), s.end()); 00118 if (indIt != ind.end()) { 00119 retList->push_back(ind); 00120 } 00121 } 00122 return retList; 00123 } 00124 00125 inline bool AbstractSymmetricProduct::isLexMinSet(const std::vector<dom_int>& setIndices, const std::vector<dom_int>& rankIndices) const { 00126 std::vector<unsigned int> expectedPosition(m_indices.size()); 00127 00128 BOOST_FOREACH(dom_int x, setIndices) { 00129 // if x is not at expectedPosition of its orbit 00130 // return false 00131 const int rank = getOrbitRank(x); 00132 if (rank < 0) 00133 continue; 00134 00135 dom_int position = 0; 00136 BOOST_FOREACH(dom_int el, rankIndices) { 00137 if (el == x) 00138 break; 00139 if (getOrbitRank(el) == rank) 00140 ++position; 00141 } 00142 00143 if (expectedPosition[rank] != position) 00144 return false; 00145 00146 ++expectedPosition[rank]; 00147 } 00148 00149 return true; 00150 } 00151 00152 inline int AbstractSymmetricProduct::getOrbitRank(dom_int x) const { 00153 if (m_indicesReverse.empty()) { 00154 if (m_indices.empty()) 00155 return -1; 00156 00157 dom_int rank = 0; 00158 BOOST_FOREACH(const std::set<dom_int>& orb, m_indices) { 00159 BOOST_FOREACH(dom_int el, orb) { 00160 m_indicesReverse[el] = rank; 00161 } 00162 ++rank; 00163 } 00164 } 00165 00166 std::map<dom_int, dom_int>::const_iterator pos = m_indicesReverse.find(x); 00167 if (pos == m_indicesReverse.end()) 00168 return -1; 00169 00170 return (*pos).second; 00171 } 00172 00173 } // end NS 00174 00175 #endif