PermLib
|
00001 // --------------------------------------------------------------------------- 00002 // 00003 // This file is part of PermLib. 00004 // 00005 // Copyright (c) 2009-2011 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 GIANT_TEST_H_ 00034 #define GIANT_TEST_H_ 00035 00036 #include <permlib/generator/product_replacement_generator.h> 00037 #include <permlib/transversal/explicit_transversal.h> 00038 #include <permlib/bsgs.h> 00039 #include <permlib/construct/schreier_sims_construction.h> 00040 #include <permlib/prime_helper.h> 00041 00042 #include <boost/foreach.hpp> 00043 #include <cmath> 00044 #include <algorithm> 00045 00046 namespace permlib { 00047 00048 00049 struct GiantTestBase { 00051 enum GiantGroupType { None, Alternating, Symmetric }; 00052 }; 00053 00055 00059 template<typename PERM> 00060 class GiantTest : public GiantTestBase { 00061 public: 00063 00074 template<typename ForwardIterator, typename TRANS> 00075 GiantGroupType determineGiantType(double eps, unsigned int n, ForwardIterator begin, ForwardIterator end, BSGS<PERM, TRANS>& bsgs) const; 00076 00078 00088 template<typename ForwardIterator> 00089 GiantGroupType determineGiantType(double eps, unsigned int n, ForwardIterator begin, ForwardIterator end) const { 00090 typedef ExplicitTransversal<PERM> TRANS; 00091 BSGS<PERM, TRANS> bsgs(n); 00092 return determineGiantType<ForwardIterator, TRANS>(eps, n, begin, end, bsgs); 00093 } 00094 00096 00102 template<typename ForwardIterator> 00103 static bool isSubgroupOfAlternatingGroup(ForwardIterator begin, ForwardIterator end); 00104 00105 private: 00106 template<class T> 00107 static GiantGroupType giantTypeByOrder(const T& order, const T& symOrder); 00108 }; 00109 00110 00111 template<typename PERM> 00112 template<typename ForwardIterator> 00113 bool GiantTest<PERM>::isSubgroupOfAlternatingGroup(ForwardIterator begin, ForwardIterator end) { 00114 typedef std::pair<dom_int, unsigned int> CyclePair; 00115 for (ForwardIterator pit = begin; pit != end; ++pit) { 00116 unsigned int parity = 0; 00117 std::list<CyclePair> genCycles = (*pit)->cycles(); 00118 BOOST_FOREACH(const CyclePair& c, genCycles) { 00119 if (c.second % 2 == 0) 00120 ++parity; 00121 } 00122 if (parity % 2 != 0) 00123 return false; 00124 } 00125 return true; 00126 } 00127 00128 template<typename PERM> 00129 template<typename T> 00130 GiantTestBase::GiantGroupType GiantTest<PERM>::giantTypeByOrder(const T& order, const T& symOrder) { 00131 if (order == symOrder / 2) 00132 return Alternating; 00133 if (order == symOrder) 00134 return Symmetric; 00135 return None; 00136 } 00137 00138 template<typename PERM> 00139 template<typename ForwardIterator, typename TRANS> 00140 GiantTestBase::GiantGroupType GiantTest<PERM>::determineGiantType(double eps, unsigned int n, ForwardIterator begin, ForwardIterator end, BSGS<PERM, TRANS>& bsgs) const { 00141 BOOST_ASSERT(n > 1); 00142 00143 // special cases for n < 8 00144 00145 if (n == 2) { 00146 for (ForwardIterator pit = begin; pit != end; ++pit) { 00147 if ( ! (*pit)->isIdentity() ) 00148 return Symmetric; 00149 } 00150 return None; 00151 } else if (n < 8) { 00152 SchreierSimsConstruction<PERM, TRANS> ssc(n); 00153 bsgs = ssc.construct(begin, end); 00154 const boost::uint64_t order = bsgs.order(); 00155 switch (n) { 00156 case 3: 00157 return giantTypeByOrder(order, static_cast<boost::uint64_t>(6)); 00158 case 4: 00159 return giantTypeByOrder(order, static_cast<boost::uint64_t>(24)); 00160 case 5: 00161 return giantTypeByOrder(order, static_cast<boost::uint64_t>(120)); 00162 case 6: 00163 return giantTypeByOrder(order, static_cast<boost::uint64_t>(720)); 00164 case 7: 00165 return giantTypeByOrder(order, static_cast<boost::uint64_t>(5040)); 00166 default: 00167 // should not happen 00168 BOOST_ASSERT(false); 00169 return None; 00170 } 00171 } 00172 00173 // This constant 0.395 comes from 0.57 * log(2) 00174 const unsigned int randomRuns = static_cast<unsigned int>(-std::log(eps) * std::log(n) / 0.395); 00175 00176 ProductReplacementGenerator<PERM> rng(n, begin, end); 00177 for (unsigned int i = 0; i < randomRuns; ++i) { 00178 PERM randPerm = rng.next(); 00179 typedef std::pair<dom_int, unsigned int> CyclePair; 00180 std::list<CyclePair> cycleList = randPerm.cycles(); 00181 BOOST_FOREACH(const CyclePair& c, cycleList) { 00182 if (c.second > n/2 && c.second < n-2 && PrimeHelper::isPrimeNumber(c.second, true)) { 00183 if (isSubgroupOfAlternatingGroup(begin, end)) 00184 return Alternating; 00185 else 00186 return Symmetric; 00187 } 00188 } 00189 } 00190 00191 return None; 00192 } 00193 00194 00195 } // end NS permlib 00196 00197 #endif