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


Quelle  largebase.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of recog, a package for the GAP computer algebra system
##  which provides a collection of methods for the constructive recognition
##  of groups.
##
##  This files's authors include Maska Law, Alice C. Niemeyer, Ákos Seress.
##
##  Copyright of recog belongs to its developers whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-3.0-or-later
##
##
##  This file provides code for recognising a subfamily of large base primitive
##  permutation groups.  To be in that subfamily, a primitive permutation group
##  G on N points must be permutation isomorphic to a subgroup of the product
##  action wreath product G wr S_r, where G is S_n acting on k-sets, and hence
##  N = Binomial(n,k)^r.
##  For a precise description of which groups are recognised by this file
##  confer to the documentation of the function LargeBasePrimitive.
##  This file is based on the article [LNPS06].
##
#############################################################################


DeclareInfoClass( "InfoJellyfish" );
SetInfoLevel( InfoJellyfish, 1 );


#############################################################################
##
#F  NkrGetParameters( <N> )
##
##  Computes all [n,k,r] such that N = Binomial(n,k)^r. Returns those
##  satisfying k*r > 1 and 2*r*k^2 < n (sufficient condition from
##  [BLS97] (Lemma 2.10) that ensures that there is a unique minimal and a
##  unique maximal suborbit of the form which is needed). Note that
##  this last condition can be changed in the last line of the code.

RECOG.NkrGetParameters := function( N )

    local maxr, list, r, k, n, newN, num;

    list:=[];
    maxr:=Gcd(List(Collected(FactorsInt(N)),x->x[2]));
    for r in DivisorsInt(maxr) do
        newN:=RootInt(N,r);
        k:=0;
        repeat
            k:=k+1;
            num:=RootInt(newN*Factorial(k),k);
            for n in [num..num+k-1] do
                if Binomial(n,k)=newN then
                    Add(list, [n,k,r]);
                fi;
            od;
        until Binomial(2*k,k)>newN;
    od;
    #return list;
    return Filtered(list,x-> x[2]*x[3]>1 and x[1]>2*x[2]^2*x[3]);

end;


#############################################################################
##
#F  NkrSchreierTree( <alpha>, <gens>, <gensinv> )
##

RECOG.NkrSchreierTree := function ( alpha, gens, gensinv )

    local sv, stack, i, j, beta, gamma;

    sv := List( [1 .. LargestMovedPoint(gens)], i -> false );
    sv[alpha] := One(gens[1]);

    stack := [alpha];
    i := 1;

    while i <= Length(stack) do
        beta := stack[i];
        for j in [1 .. Length(gens)] do
            gamma := beta^gens[j];
            if sv[gamma] = false then
                sv[gamma] := gensinv[j];
                Add(stack, gamma);
            fi;
        od;
        i := i + 1;
    od;

    return sv;

end;


#############################################################################
##
#F  NkrTraceSchreierTree( <beta>, <sv> )
##

RECOG.NkrTraceSchreierTree := function( beta, sv )

    local o, h;

    if sv[beta] = false then
        return fail;
    fi;

    o := One(sv[beta]);
    h := One(sv[beta]);
    while sv[beta] <> o do
        h := h * sv[beta];
        beta := beta^sv[beta];
    od;

    return h;

end;


#############################################################################
##
#F  NkrOrbitsOfStabiliser( <alpha>, <sv>, <grp> )
##
##  The following function attempts to construct the stabiliser in <G>
##  of a point <alpha>.

RECOG.NkrOrbitsOfStabiliser := function ( alpha, sv, grp )

    local  NextGeneratorStabiliser, N, gens, i, orbs;

    NextGeneratorStabiliser := function( alpha, sv, grp )
        local g;
        g := PseudoRandom( grp );
        return g * RECOG.NkrTraceSchreierTree( alpha^g, sv );
    end;

    N := LargestMovedPoint( grp );

    gens := [];
    for i in [1 .. Maximum( 4, Int(Log(N,2)/2) )] do
        Add( gens, NextGeneratorStabiliser( alpha, sv, grp ) );
    od;

    orbs := OrbitsPerms( gens, Difference( [1..N], [alpha] ) );

    return orbs;

end;


#############################################################################
##
#F  FirstJellyfish( <alpha>, <svalpha>, <gammaalpha>, <deltaalpha>,
##                  <G>, <n>, <k>, <r> )
##
##  The following function attempts to construct a jellyfish, namely the
##  set of all points whose i-th component contains the letter l, for
##  some fixed i in [1..r] and l in [1..n].
##  A jellyfish has size (n-1 choose k-1)*(n choose k)^(r-1).
##
##  The set of points used to construct the jellyfish are returned for
##  use later as an identifier.

RECOG.FirstJellyfish := function( alpha, svalpha, gammaalpha, deltaalpha,
                            G, n, k, r )

    local beta, g, deltabeta, gams, jellyfish, I, gamma, deltagamma, idjf;

    # we need a point <beta> in <gammaalpha> : best to choose random
    # <beta> in <gammaalpha> since <gammaalpha> is small
    # wlog : assume <alpha> and <beta> differ in component 1 and the
    # letter x satisfies x in <beta>[1] and not x in <alpha>[1]
    beta := Random( gammaalpha );
    g := RECOG.NkrTraceSchreierTree( beta, svalpha );
    if g = fail then
        Info(InfoJellyfish,2,"Schreier tracing failed");
        return fail;
    else g := g^-1;
    fi;

    # use <g> to obtain the longest <G>_<beta>-orbit
    deltabeta := List( deltaalpha, i -> i^g );

    # <gams> will be those points <gamma> such that
    # (a)  <gamma>[i] is disjoint from <alpha>[i] for i >= 1;
    # (b)  <gamma>[1] meet <beta>[1] is x.
    gams := Difference( deltaalpha, deltabeta );

    # the domain <D> of all points
    jellyfish := [1..LargestMovedPoint(G)];

    # for each <gamma> in <gams>, we will remove from <D> those points
    # in deltagamma, leaving the jellyfish on x in component 1

    # we can calculate some small number <I> to determine how many
    # points in <gams> are enough, up to some acceptable probability
    I := 4*k*r;
    # <idjf> will record those <gamma> used to construct the jellyfish
    idjf := [ ];
    while I>0 and Size(jellyfish)>Binomial(n-1,k-1)*Binomial(n,k)^(r-1) do
        I := I - 1;
        gamma := Random( gams );
        g := RECOG.NkrTraceSchreierTree( gamma, svalpha );
        if g = fail then
            Info(InfoJellyfish,2,"Schreier tracing failed - 2");
            return fail;
        else g := g^-1;
        fi;
        deltagamma := List( deltaalpha, i -> i^g );
        Add( idjf, gamma );
        jellyfish := Difference( jellyfish, deltagamma );
    od;

    if I = 0 and Size(jellyfish)>Binomial(n-1,k-1)*Binomial(n,k)^(r-1)
        then Info(InfoJellyfish,2,"gammas ran out for ",[n,k,r]);
        return fail;
    elif Size(jellyfish) < Binomial(n-1,k-1)*Binomial(n,k)^(r-1)
        then Info(InfoJellyfish,2,"too small set remained");
        return fail;
    fi;

    return [ jellyfish, Set(idjf) ];

end;


#############################################################################
##
#F  GetAllJellyfish( <jellyfish>, <idjf>, <G>, <n>, <k>, <r> )
##
##  The following function takes a jellyfish <jellyfish> and constructs
##  n*r jellyfish by building up the <G>-orbit of <jellyfish>, since <G>
##  is transitive on jellyfish. The order in which the jellyfish are
##  constructed (as images of some previous jellyfish) determines the
##  number in [1..n*r] that it represents. This correspondence is recorded
##  in the table <T>, the rows of which represent the points and contain
##  the numbers of the jellyfish containing that point.
##
##  Each jellyfish is identified by a subset of its tentacles : the size
##  of these identifying subsets is determined by the number of points
##  <gamma> in Difference( <deltaalpha>, <deltabeta> ) originally needed
##  to construct the first jellyfish. These identifying subsets are also
##  returned for use in constructing more efficiently the permutation
##  corresponding to a given group element.

RECOG.GetAllJellyfish := function( jellyfish, idjf, G, n, k, r )

    local HaveSeen, T, seen, orb, i, top, cnt, gens, jf, id, im, mm, g;

    # if one jellyfish contains the identifying tentacles of another
    # jellyfish, then the two jellyfish are equal

    HaveSeen := function( jellyfish )
        local s;
        for s in seen do
            if IsSubset(jellyfish,s) then
                return true;
            fi;
        od;
        return false;
    end;

    T := List( [1..LargestMovedPoint(G)], i -> [ ] );

    seen := [ idjf ];

    orb := [ rec(jf:=jellyfish,id:=idjf) ];

    for i in jellyfish do
        Add( T[i], 1 );
    od;

    top := 1;
    cnt := 1;

    gens := GeneratorsOfGroup( G );

    while top > 0 do
        jf := orb[top].jf;
        id := orb[top].id;
        for g in gens do
            im := OnSets( jf, g );
            mm := OnSets( id ,g );
            if not HaveSeen(im) then
                cnt := cnt + 1;
                for i in im do
                    Add( T[i], cnt );
                od;
                Add( seen, mm );
                orb[top] := rec(jf:=im,id:=mm);
                top := top + 1;
            fi;
        od;
        top := top - 1;
    od;

    if Length( seen ) <> n*r then
        return fail;
    fi;

    return [ T, seen ];

end;


#########################################################################
##
#F OtherGetAllJellyfish( <jellyfish>, <idjf>, <G>, <n>, <k>, <r> )
##
## A variant of GetAllJellyfish.
##

# FIXME: unused?
RECOG.OtherGetAllJellyfish:=function ( jellyfish, idjf, G, n, k, r )

    local  HaveSeen, T, seen, orb, i, g, gens, cnt, pnt, jf, id, img, mm;

    HaveSeen := function( jellyfish )
        local s;
        for s in seen do
            if IsSubset(jellyfish,s) then
                return true;
            fi;
        od;
        return false;
    end;

    T := List( [1..LargestMovedPoint(G)], i -> [ ] );
    seen := [ idjf ];
    orb := [ rec(jf:=jellyfish,id:=idjf) ];

    for i in jellyfish do
        Add( T[i], 1 );
    od;

    gens := GeneratorsOfGroup( G );
    cnt := 1;

    for pnt in orb do
        jf := pnt.jf;
        id := pnt.id;
        for g in gens do
            img := OnSets( jf, g );
            mm := OnSets( id ,g );
            if not HaveSeen(img) then
                cnt := cnt + 1;
                for i in img do
                    Add( T[i], cnt );
                od;
                Add( orb, rec(jf:=img,id:=mm) );
                Add( seen, mm );
            fi;
        od;
    od;

    if Length( seen ) <> n*r then
        return fail;
    fi;

    return [ T, seen ];

end;


#########################################################################
##
#F AllJellyfish( <G> )
##
## This is the main function.
##
## Note re: the shortest orbit and the longest orbit of <G>_<alpha> :
## (i) the shortest orbit consists of those points in Omega for which
## the k-sets in each of r-1 components are identical to the k-sets of
## <alpha> in those r-1 components and for which the k-set in the
## remaining component meets the k-set of <alpha> in that component in
## k-1 letters. It has size (k choose k-1)*(n-k)*r. Notation: gammaalpha.
## (ii) the longest orbit consists of those points in Omega for which
## the k-set in each component is disjoint from the k-set in the same
## component of <alpha>. It has size (n-k choose k)^r. Notation: deltaalpha.

RECOG.AllJellyfish := function( G )

    local N, D, gens, gensinv, i, g, alpha, svalpha, alphaorbs, sizes,
          s, l, params, p, n, k, r, jellyfishone, alljellyfish;

    N := LargestMovedPoint(G);
    params := RECOG.NkrGetParameters( N );
    if IsEmpty(params) then
        return NeverApplicable;
    fi;

    D := [ 1 .. N ];

    gens := ShallowCopy( GeneratorsOfGroup(G) );
    gensinv := List( gens, g -> g^-1 );
    for i in [1 .. LogInt(N,10)] do
        g := PseudoRandom(G);
        Add( gens, g );
        Add( gensinv, g^-1 );
    od;

    alpha := 1;  # alpha:=Random( [1..LargestMovedPoint(G)] );
    svalpha := RECOG.NkrSchreierTree( alpha, gens, gensinv );
    alphaorbs := RECOG.NkrOrbitsOfStabiliser( alpha, svalpha, G );

    sizes := List( alphaorbs, i -> Length(i) );
    s := Minimum( sizes );
    l := Maximum( sizes );
    if Length(Filtered(sizes,i->i=s)) > 1 or
       Length(Filtered(sizes,i->i=l)) > 1 then
        Info(InfoJellyfish,2,"no unique max or min sized G_alpha orbit");
        return TemporaryFailure;
    fi;
    s := alphaorbs[ Position(sizes,s) ]; # shortest <G>_<alpha>-orbit
    l := alphaorbs[ Position(sizes,l) ]; # longest <G>_<alpha>-orbit

    for p in params do
        n := p[1]; k := p[2]; r := p[3];
        if Size(s) = Binomial(k,k-1) * (n-k) * r and
           Size(l) = Binomial(n-k,k)^r then
            jellyfishone := RECOG.FirstJellyfish(alpha,svalpha,s,l,G,n,k,r);
            if jellyfishone <> fail then
                Info(InfoJellyfish,2,"found jellyfish for ",p);
                alljellyfish := RECOG.GetAllJellyfish( jellyfishone[1],
                                 jellyfishone[2], G,n,k,r );
                if alljellyfish <> fail then
                    return alljellyfish;
                fi;
            fi;
        else
            Info(InfoJellyfish,2,
        "couldn't find orbits of correct size for n=",n," k=",k," r=",r);
        fi;
    od;

    Info(InfoJellyfish,3,"getting jellyfish failed");
    return TemporaryFailure;

end;


########################################################################
##
#F FindImageJellyfish( <g>, <T>, <seen> )
##
## This function returns the permutation of [1..n*r] corresponding to <g>.
##
## A jellyfish is identified by a subset of its tentacles : the size of
## these identifying subsets is determined by the number of points
## <gamma> in Difference( <deltaalpha>, <deltabeta> ) originally needed
## to construct the first jellyfish. The intersection of the images
## under <g> of the points in an identifying subset determines the image
## of the letter of the jellyfish.

RECOG.FindImageJellyfish := function( g, T, seen )

    local nr, h, i, gams, tmp;

    nr := Length( seen );
    h := List( [1..nr], i -> 0 );

    for i in [1..nr] do
        gams := OnSets( seen[i], g );
        if ForAny( gams, t -> not IsBound(T[t])) then
            return fail;
        fi;
        tmp := Intersection( List( gams, t -> T[t] ) );
        if Length(tmp) = 0 then
            return fail;
        fi;
        h[i] := tmp[1];
    od;

    if Size(Set(h)) <> nr then
        return fail;
    else
        return PermList(h);
    fi;

end;

########################################################################
##
#F  FindHomMethodsPerm.LargeBasePrimitive
##

RECOG.JellyHomFunc := function(data,el)
  return RECOG.FindImageJellyfish(el,data.T,data.seen);
end;

#! @BeginChunk LargeBasePrimitive
#! This method tries to determine whether the input group <A>G</A> is a
#! fixed-point-free large-base primitive group that neither is a symmetric nor an alternating
#! group in its natural action.
#! This method is an implementation of <Cite Key="LNPS06"/>.
#!
#! A primitive group <M>H</M> acting on <M>N</M> points is called <E>large</E> if
#! there exist <M>n</M>, <M>k</M>, and <M>r</M> with
#! <M>N = \{n \choose k\}^r</M>, and up to a permutational isomorphism <M>H</M>
#! is a subgroup of the product action wreath product <M>S_n \wr S_r</M>,
#! and an overgroup of <M>(A_n) ^ r</M> where <M>S_n</M> and <M>A_n</M> act on
#! the <M>k</M>-subsets of <M>\{1, ..., n\}</M>.
#! This algorithm recognises fixed-point-free large primitive groups with
#! <M>r \cdot k > 1</M>
#! and <M>2 \cdot r \cdot k^2 \le n</M>.
#!
#! A large primitive group <M>H</M> of the above type which does have fixed
#! points is handled as follows: if the group <M>H</M> does not know yet that
#! it is primitive, then <Ref Func="ThrowAwayFixedPoints"/> returns
#! <K>NotEnoughInformation</K>. After the first call to
#! <C>LargeBasePrimitive</C>, the group <M>H</M> knows that it is primitive,
#! but since it has fixed points <C>LargeBasePrimitive</C> returns
#! <K>NeverApplicable</K>. Since <Ref Func="ThrowAwayFixedPoints"/> previously
#! returned <K>NotEnoughInformation</K>, it will be called again. Then it will
#! use the new information about <M>H</M> being primitive, and is guaranteed to
#! prune away the fixed points and set up a reduction homomorphism.
#! <C>LargeBasePrimitive</C> is then applicable to the image of that
#! homomorphism.
#!
#! If <A>G</A> is imprimitive then the output is
#! <K>NeverApplicable</K>. If <A>G</A> is primitive then
#! the output is either a homomorphism into the
#! natural imprimitive action of <A>G</A> on <M>nr</M> points with
#! <M>r</M> blocks of size <M>n</M>,  or <K>TemporaryFailure</K>, or
#! <K>NeverApplicable</K> if no parameters <M>n</M>, <M>k</M>, and <M>r</M> as
#! above exist.
#! @EndChunk
BindRecogMethod(FindHomMethodsPerm, "LargeBasePrimitive",
"recognises large-base primitive permutation groups",
rec(validatesOrAlwaysValidInput := true),
function(ri, grp)
    local res,T,seen,imgens,hom;
    if not IsPermGroup(grp) then
        return NeverApplicable;
    fi;
    if not IsPrimitive(grp) then
        return NeverApplicable;
    fi;
    RECOG.SetPseudoRandomStamp(grp,"Jellyfish");
    res := RECOG.AllJellyfish(grp);
    RECOG.SetPseudoRandomStamp(grp,"PseudoRandom");
    if res = NeverApplicable or res = TemporaryFailure then
        return res;
    fi;
    ri!.jellyfishinfo := res;
    T := res[1];
    seen := res[2];
    # Build the homomorphism:
    imgens := List(GeneratorsOfGroup(grp),
                   x->RECOG.FindImageJellyfish(x,T,seen));
    hom := GroupHomByFuncWithData(grp,Group(imgens),RECOG.JellyHomFunc,
                                  rec(T := T,seen := seen));
    SetHomom(ri,hom);

    findgensNmeth(ri).method := FindKernelDoNothing;

    return Success;
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