Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  rm2.g   Sprache: unbekannt

 
# take an absolutely irreducible matrix group g over k and
# decide if it is (modulo scalars in k)
# conjugate to a group over f
#
# Robert McDougal, Nick Werner,
# Justin Lynd, Niraj Khare

# *********  REQUIRES alg4 *********
alg8 := function ( g , f , k )
  local gPrime, gPrimeGenerators, moduleGenerators,
 s, temp, t, cosets, cosetReps, length, c,
 smallRing, charPoly, j, i, perm, c_jSizes ,
        done , positionInTree , descendNext ,
        chanceOfSuccess , depthInTree , gPrimeGenerators2 ,
        testThreshold , k2 , b , bInverse ,
        success , skew ;

  # check for absolute irreducibility of g first
  if not (MTX.IsAbsolutelyIrreducible (
      GModuleByMats(GeneratorsOfGroup(g) , k))) then
    Print("This algorithm requires an absolutely irreducible group.\n");
    return fail ;
  fi ;

  # check to make sure that f is contained in k
  if not IsSubset(k, f) then
    Print("\nError. f = ", f,
   " must be contained in of k = ", k, "\n");
    return fail;
  fi;

  # Calculating the derived subgroup in general takes a LONG time
  # Let's not do that if our group is really just conjugate to
  # a matrix group over the smaller field
  # For certain types of testing, you may wish to comment out this
  # section.
  temp := alg4 ( g , f , k ) ;
  if ( temp <> fail and temp <> false ) then
    return temp ;
  fi ;

  # set the threshold for testing (currently arbitrarily)
  testThreshold := 10 ;

  # Step 1:  find a list s of elements of g that together
  #          with g' act absolutely irreducibly.

  gPrime := DerivedSubgroup ( g ) ;
  gPrimeGenerators2 := GeneratorsOfGroup ( gPrime ) ;
  gPrimeGenerators := [ ] ;
  for temp in gPrimeGenerators2 do
    Add ( gPrimeGenerators , temp ) ;
  od ;
  s := [ ] ;
  moduleGenerators := StructuralCopy ( gPrimeGenerators ) ;

  while not (MTX.IsAbsolutelyIrreducible(
          GModuleByMats(moduleGenerators , k ))) do

    # to avoid redundancy in s, we check each time
    # to make sure that temp is not already in s
    temp := PseudoRandom ( g ) ;
    if Length ( s ) >= 1 then
      while temp in Group ( s ) do
        temp := PseudoRandom(g);
      od ;
    fi ;
    Add ( s , temp ) ;
    Add ( moduleGenerators , temp ) ;
  od ;
  t := Length ( s ) ;
  if t = 0 then
    Print("This algorithm requires that the commutator subgroup\n");
    Print("act absolutely irreducibly.\n");
    return(fail);
  fi ;
  # Step 1 ends here


  # Step 2a:  Find the set c_j of cosets of Units(f) in
  #           Units(k) such that x*s[j] has its char poly
  #           in f, where x is a representative of a coset

  # we require the cosets of the group of units of f in the
  # group of units of k
  cosets := RightCosets(Units(k), Units(f));

  # since we will have a list of cosets and a list of coset
  # representatives running in parallel, we work with the
  # indices of the elements of the lists rather than the
  # actual elements. That is, we use
  # 'for i in [1..Length(cosets]' rather than
  # 'for x in cosets'

  length := Length(cosets);
  cosetReps := [];
  for i in [1..length] do
    Add(cosetReps, Representative(cosets[i]));
  od;

  # c will be the list of lists of cosets c_j for which
  # cosetReps[i]*s[j] has its charPoly in f
  c := [];
  smallRing := PolynomialRing(f);
  for j in [1 .. t] do
    c[j] := [];
    for i in [1..length] do
      charPoly := CharacteristicPolynomial ( cosetReps [ i ] * s [ j ] ) ;
      if charPoly in smallRing then
        Add ( c [ j ] , cosetReps [ i ] ) ;
      fi;
    od;

    if Length ( c [ j ] ) = 0 then
      return false ;
    fi ;
  od ;


####################################
#  Step 2b:  Reorder s (and c) in order of
#            increasing size of c_j
############################################

  SortParallel(c,s, function(v,w) return Length(v) < Length(w) ; end );


  # Step 3:  backtrack search fun
  done := false ;
  depthInTree := 0 ;
  positionInTree := [ ] ;
  descendNext := true ;   # true when next move to descend;
                          # false when next move to advance
  success := false ;
  while not done do

    # move to next position in tree

    if descendNext then
      depthInTree := depthInTree + 1 ;
      positionInTree [ depthInTree ] := 1 ;
    else
      positionInTree [ depthInTree ] := positionInTree [ depthInTree ]+ 1
;
      if positionInTree [ depthInTree ] <= Length ( c [ depthInTree ] )
then
        done := true ;
      fi ;
      # backtrack if we can't advance until we get to a point where we can
      # (and then advance at that point)
      while not done do
        depthInTree := depthInTree - 1 ;
        if depthInTree = 0 then
          done := true ;
        else
          positionInTree [ depthInTree ] := positionInTree [ depthInTree ] + 1 ;
          if positionInTree [ depthInTree ] <= Length ( c [ depthInTree ]
) then
            done := true ;
          fi ;
        fi ;
      od ;
      if depthInTree > 0 then
        done := false ;
      fi ;
    fi ;

    if depthInTree > 0 then
      # is there any chance of this position working?
      # We do this by picking some elements of
      #   F[<g' , s_1*c_1 , ... , s_depthInTree*c_depthInTree>]
      # and checking their characteristic poly
      # To work, the characteristic poly must lie in F[x]...
      # we try testThreshold number of times using elements
      # with testThreshold parts from G' and testThreshold
      # parts from s_i*c_i
      chanceOfSuccess := true ;

      for i in [ 1 .. testThreshold ] do
        if chanceOfSuccess then
          temp := Zero ( f ) ;
          for j in [ 1 .. testThreshold ] do
            k2 := Random ( [ 1 .. depthInTree ] ) ;
            temp := temp + Random ( f ) * PseudoRandom ( gPrime )
                         + Random ( f ) * s [ k2 ] * c [ k2 ] [ positionInTree [ k2 ] ];
          od ;
          if not ( CharacteristicPolynomial ( temp ) in smallRing ) then
            chanceOfSuccess := false ;
          fi ;
        fi ;
      od ;

      # if yes, next time descend;
      # if no, next time advance on same level (or backtrack)
      descendNext := chanceOfSuccess ;  # we use these being independent
                                        # later, so don't try to
                                        # consolidate variables without
                                        # taking that into account

      # are we at depth t?  Be deterministic then (only check of
      # course if there's a chance that this could work)
      if depthInTree = t then
        descendNext := false ;
        if chanceOfSuccess then
          # Can < g' , s_1*c_1 , ... , s_t*c_t > be written over F?
          # sounds like a job for alg4
          temp := ShallowCopy ( gPrimeGenerators ) ;
          for i in [ 1 .. t ] do
            Add ( temp , s [ i ] * c [ i ] [ positionInTree [ i ] ] ) ;
          od ;
          b := alg4 ( Group ( temp ) , f , k ) ;
          if ( b <> fail ) and ( b <> false ) then
            # if we're inside this if loop, then yes it could be.
            # conjugating matrix is b.  So let's check the generators
            # of the original group g to see if when we conjugate them by
            # b, we get a matrix that is a k-scalar multiple of a matrix
            # in f.
            success := true ;
            bInverse := b ^ ( -1 ) ;
            for k2 in GeneratorsOfGroup ( g ) do
              if success then
                temp := bInverse * k2 * b ;
                done := false ;
                # find a nonzero i , j position inside temp
                # must exist since temp <> [ 0 ]
                i := 1 ;
                j := 1 ;
                while not done do
                  if IsZero ( temp [ i ] [ j ] ) then
                    i := i + 1 ;
                    if i > Size ( temp ) then
                      i := 1 ;
                      j := j + 1 ;
                    fi ;
                  else
                    done := true ;
                  fi ;
                od ;
                # all entries of temp must lie in the same coset
                # as temp [ i ] [ j ]... thus if we divide the entries
                # all by this element the result must lie in f
                skew := temp [ i ] [ j ] ;
                 success := ( skew ^ ( -1 ) * temp ) in GL ( Size ( temp ) , f ) ;
              fi ;
            od ;
            # done iff success
            done := success ;
          fi ;
        fi ;
      fi ;

    else
      done := true ;
    fi ;

  od ;

  if success then
    return b ;
  fi ;

  return false ;

  end;

[ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge