PermLib

giant_test.h

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