PermLib
abstract_symmetric_product.h
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