Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/sotgrps/gap/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 29.7.2024 mit Größe 71 kB image not shown  

Quelle  IdFunc.gi   Sprache: unbekannt

 
## Functions to identify a group of order n, where n factorises in at most 4 primes, by its SOT-group ID.
## By reversing the process of constructing a deterministically ordered list, we identify a given group of order n with an isomorphism type in the AllSOTGroups(n) list.
## This is achieved using various group invariants, such as the centre of a group, the derived subgroup, the Fitting subgroup, the Frattini subgroup, the structure of the Sylow subgroups, etc,
  ## and application of the results on classification of split extensions. For further details, see [2, Section 3.2].
######################################################
##
## the case of p-groups of order dividing p^4
##
SOTRec.IdPGroup := function(group, n, fac)
local p, k, i, Id, flag, a, b, c, d, F, N, Zen, gens, pcgs, G, m, x, y;
    p := fac[1][1];
    k := fac[1][2];
    Assert(1, IsPrimeInt(p));
##
    flag := [Exponent(group)];

    if k = 1 then
        return [n, 1];
    fi;

    if k = 2 then
        if flag[1] = n then
            return [n, 1];
        else
            return [n, 2];
        fi;
    fi;

    if k = 3 then
        if IsAbelian(group) then
            if flag[1] = n then
                return [n, 1];
            elif flag[1] = p^2 then
                return [n, 2];
            else
                return [n, 3];
            fi;
        elif flag[1] = p and p > 2 then
            return [n, 4];
        elif flag[1] > p and p > 2 then
            return [n, 5];
        elif p = 2 and Size(Omega(group, 2)) = 8 then
            return [8, 4];
        elif p = 2 and Size(Omega(group, 2)) = 2 then
            return [8, 5];
        fi;
    fi;

    if k = 4 and p > 2 then
        F := FrattiniSubgroup(group);
        Zen := Centre(group);

      if IsAbelian(group) then
          Add(flag, Size(F));
          if flag[1] = n then
              return [n, 1];
          elif flag[1] = p^3 then
              return [n, 2];
          elif flag = [p^2, p^2] then
              return [n, 3];
          elif flag = [p^2, p] then
              return [n, 4];
          else
              return [n, 5];
          fi;
      else
          Append(flag, [IsPowerfulPGroup(group), Size(Zen), IsAbelian(DerivedSubgroup(group)), Exponent(group/DerivedSubgroup(group)), Exponent(Zen)]);
          if flag = [p^2, true, p^2, true, p, p^2] then
              return [n, 6];
          elif flag = [p^3, true, p^2, true, p^2, p^2] then
              return [n, 7];
          elif flag = [p^2, true, p^2, true, p, p] then
              return [n, 8];
          elif flag = [p^2, false, p^2, true, p^2, p] then
              return [n, 9];
          elif flag = [p^2, true, p^2, true, p^2, p] then
              return [n, 10];
          elif flag = [p, false, p^2, true, p, p] then
              return [n, 11];
          elif flag = [p, false, p, true, p, p] then
              return [n, 14];
          elif flag = [p^2, false, p, true, p, p] and p > 3 then
              d := Filtered(Pcgs(F), x -> not x in Zen)[1];
              N := Centralizer(group, F);
              if Exponent(N) = p then
                  return [n, 15];
              else
                  gens := Pcgs(group);
                  a := Filtered(gens, x-> not x in N)[1];
                  b := Filtered(Pcgs(N), x->Order(x) = p^2 and x^p in Zen)[1];
                  pcgs := [a, b, b^p, d];
                  G := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
                  x := Inverse(ExponentsOfPcElement(G, pcgs[2]^pcgs[1])[4]) mod p;
                  y := ExponentsOfPcElement(G, pcgs[4]^(pcgs[1]^x))[3];
                  if Legendre(y, p) = 1 then
                      return [n, 12];
                  else
                      return [n, 13];
                  fi;
              fi;
          elif flag = [9, false, 3, true, 3, 3] then
              if IsAbelian(Omega(group, 3)) then
                  return [81, 15];
              else
                  m := Size(Filtered(group, x -> Order(x) < 4));
                  if m = 27 then
                      return [81, 12];
                  elif m = 63 then
                      return [81, 13];
                  elif m = 45 then
                      return [81, 14];
                  fi;
              fi;
          fi;
      fi;
    elif k = 4 and p = 2 then
        if IsAbelian(group) then
            Add(flag, Size(Agemo(group, 2)));
            if flag[1] = 16 then
                return [16, 1];
            elif flag[1] = 8 then
                return [16, 2];
            elif flag = [4, 4] then
                return [16, 3];
            elif flag = [4, 2] then
                return [16, 4];
            else
                return [16, 5];
            fi;
        else
            Zen := Centre(group);
            flag := [Exponent(Zen), Size(Agemo(group, 2)), Size(Zen), Size(Omega(group, 2))];
            if flag{[1, 2]} = [4, 2] then
                return [16, 6];
            elif flag{[1, 2]} = [4, 4] then
                return [16, 11];
            elif flag{[1, 2, 3, 4]} = [2, 2, 4, 16] then
                return [16, 7];
            elif flag{[1, 2, 3, 4]} = [2, 4, 4, 8] then
                return [16, 8];
            elif flag{[1, 2, 3, 4]} = [2, 2, 4, 4] then
                return [16, 9];
            elif flag{[1, 2, 3, 4]} = [2, 4, 4, 4] then
                return [16, 10];
            elif flag{[3, 4]} = [2, 8] then
                return [16, 12];
            elif flag{[3, 4]} = [2, 16] then
                return [16, 13];
            else
                return [16, 14];
            fi;
        fi;
    fi;
end;

######################################################
#
# the case of groups of order pq
#
SOTRec.IdGroupPQ := function(group, n, fac)
local p, q, Id;
    q := fac[1][1];
    p := fac[2][1];
    ####
    Assert(1, p > q);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));

    if not (p - 1) mod q = 0 and IsAbelian(group) then
        return [n, 1];
    elif IsAbelian(group) then
        return [n, 2];
    else
        return [n, 1];
    fi;
end;
######################################################
#
# the case of groups of order p^2q
#
SOTRec.IdGroupP2Q := function(group, n, fac)
local p, q, Id, a, b, c, d, flag, P, Q, Zen,gens, G, exps1, exps2, pcgs, pc, m, det, x, k, pcgsp, pcgsq;
    p := fac[2][1];
    q := fac[1][1];
    ####
    Assert(1, p <> q);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));
    ####
    a := Z(p);
    b := Z(q);
    c := ZmodnZObj(Int(Z(p)),p^2);
    if not c^(p - 1) = ZmodnZObj(1, p^2) then
      d := c;
    else
      d := c + 1;
    fi;
    P := SylowSubgroup(group, p);
    Q := SylowSubgroup(group, q);
    pcgsp := Pcgs(P);
    pcgsq := Pcgs(Q);
    Zen := Centre(group);

    flag := [Exponent(P), Size(Zen)];

    if IsAbelian(group) then
      if flag[1] = p^2 then
        return [n, 1];
      else
        return [n, 2];
      fi;
    elif p > q and q > 2 and (p + 1) mod q = 0 then
      if flag[1] = p then
        return [n, 3];
      fi;
    elif (p - 1) mod q = 0 and q > 2 then
      if flag{[1, 2]} = [p, p] then
        return [n, 3];
      elif flag{[1, 2]} = [p, 1] then
        gens := [pcgsq[1], pcgsp[1], pcgsp[2]];
        G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
        exps1 := ExponentsOfPcElement(G, gens[2]^gens[1]);
        exps2 := ExponentsOfPcElement(G, gens[3]^gens[1]);
        m := [ exps1{[2, 3]}, exps2{[2, 3]} ] * One(GF(p));
        x := Inverse(LogFFE(Eigenvalues(GF(p), m)[1], a^((p - 1)/q))) mod q;
        det := LogFFE((LogFFE(DeterminantMat(m^x), a^((p - 1)/q)) - 1)*One(GF(q)), b) mod (q - 1);
        if det < (q + 1)/2 then
          k := det;
        else
          k := (q - 1) - det;
        fi;
        return [n, 4 + k];
      elif flag[1] = p^2 then
        return [n, 5 + (q - 1)/2];
      fi;
    elif p > q and q = 2 then
      if flag{[1, 2]} = [p, p] then
        return [n, 3];
      elif flag{[1, 2]} = [p, 1] then
        return [n, 4];
      elif flag[1] = p^2 then
        return [n, 5];
      fi;
    elif p = 2 and q = 3 then
      if flag[1] = p^2 then
        return [12, 5];
      elif flag[2] = 2 then
        return [12, 4];
      else
        return [12, 3];
      fi;
    elif (q - 1) mod p = 0 and q > 3 then
      if flag[1] = p then
        return [n, 3];
      elif flag[1] = p^2 then
        if flag[2] = p then
          return [n, 4];
        else
          return [n, 5];
        fi;
      fi;
    fi;
end;
######################################################
#
# the case of groups of order pqr
#
SOTRec.IdGroupPQR := function(group, n, fac)
local p, q, r, a, b, k, G, Q, R, P, flag, c1, c2, c3, c4, c5, pcgs, pcp, pc, x, pcgsp, pcgsq, pcgsr;
    r := fac[1][1];
    q := fac[2][1];
    p := fac[3][1];
    ####
    Assert(1, p > q and q > r);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));
    Assert(1, IsPrimeInt(r));

    a := Z(p);
    b := Z(q);

    P := SylowSubgroup(group, p);
    Q := SylowSubgroup(group, q);
    R := SylowSubgroup(group, r);
    pcgsp := Pcgs(P);
    pcgsq := Pcgs(Q);
    pcgsr := Pcgs(R);

    c1 := SOTRec.w((q - 1), r);
    c2 := SOTRec.w((p - 1), r);
    c3 := SOTRec.w((p - 1), q);
    c4 := (r - 1)*SOTRec.w((q - 1), r) * SOTRec.w((p - 1), r);
    c5 := SOTRec.w((p - 1), q*r);

    if IsAbelian(group) then
      return [n, 1];
    else
      flag := [Size(Centre(group))];
      if flag[1] = p then
        return [n, 2]; ##r | (q - 1)
      elif flag[1] = q then
        return [n, 2 + c1]; ##r |(p - 1)
      elif (p - 1) mod q = 0 and flag[1] = r then
        return [n, 2 + c1 + c2];
      elif flag[1] = 1 then
        if pcgsp[1]^pcgsq[1] = pcgsp[1] and (q - 1) mod r = 0 and (p - 1) mod r = 0 then ##r |(p - 1) and r | (q - 1)
          pcgs := [pcgsr[1], pcgsq[1], pcgsp[1]];
          pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
          x := Inverse(LogFFE(ExponentsOfPcElement(pc, pcgs[2]^pcgs[1])[2]*One(GF(q)), b^((q-1)/r))) mod r;
          k := LogFFE(ExponentsOfPcElement(pc, pcgs[3]^(pcgs[1]^x))[3]*One(GF(p)), a^((p-1)/r)) mod r;
          return [n, 3 + c3 + k];
        elif pcgsp[1]^pcgsq[1] <> pcgsp[1] and (p - 1) mod (r*q) = 0 then
          return [n, 2 + c1 + c2 + c3 + c4];
        fi;
      fi;
    fi;
end;
######################################################
######################################################
######################################################
#
# the case of groups of order p^2q^2
#
SOTRec.IdGroupP2Q2 := function(group, n, fac)
local p, q, P, Q, Zen,a, b, c, d, e, f, ind, gens, G, pcgs, pc, g, h, ev,
  gexp1, gexp2, gexp3, gexp4, mat, Id, k, l, x, y, det, mat1, mat2, pcgsp, pcgsq;
    q := fac[1][1];
    p := fac[2][1];
    ####
    Assert(1, p > q);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));

    Q := SylowSubgroup(group, q);
    P := SylowSubgroup(group, p);
    Zen := Centre(group);

    pcgsp := Pcgs(P);
    pcgsq := Pcgs(Q);
    a := Z(p);
    b := Z(q);
    c := ZmodnZObj(Int(Z(p)), p^2);
    if not c^(p - 1) = ZmodnZObj(1, p^2) then
      d := c;
    else
      d := c + 1;
    fi;
    e := ZmodnZObj(Int(Z(q)), q^2);
    if not e^(q - 1) = ZmodnZObj(1, q^2) then
      f := e;
    else
      f := e + 1;
    fi;

    ind := [Exponent(P), Exponent(Q)];

    if IsAbelian(group) then
        if ind[1] = p^2 and ind[2] = q^2 then
          return [n, 1];
        elif ind[2] = q^2 then
          return [n, 2];
        elif ind[1] = p^2 then
          return [n, 3];
        else
          return [n, 4];
        fi;
    else
        gens := [];
        Append(gens, Filtered(pcgsq, x-> not x in Zen));
        Append(gens, Filtered(pcgsq, x-> not x in gens));
        Append(gens, pcgsp);
        G := PcgsByPcSequence(FamilyObj(gens[1]), gens);;
        Add(ind, Size(Zen));
    fi;

    if n = 36 then
        k := Position([ [ 9, 4, 36 ], [ 3, 4, 36 ], [ 9, 2, 36 ], [ 3, 2, 36 ], [ 9, 4, 2 ], [ 9, 2, 2 ], [ 9, 2, 3 ], [ 3, 4, 6 ], [ 3, 4, 2 ], [ 3, 4, 1 ], [ 3, 2, 6 ], [ 3, 2, 2 ], [ 3, 2, 1 ], [ 3, 2, 3 ] ], ind);
        return [36, k];
    fi;
    if ((p - 1) mod q = 0 and q > 2) then
        if ind = [p^2, q^2, q] then
            return [n, 5];
        elif ind = [p^2, q^2, 1] and ((p - 1) mod q^2 = 0 and q > 2) then
            return [n, 5 + SOTRec.w((p - 1), q^2)];
        elif ind = [p^2, q, q] then
            return [n, 6 + SOTRec.w((p - 1), q^2)];
        elif ind = [p, q^2, q*p] then
            return [n, 7 + SOTRec.w((p - 1), q^2)];
        elif ind = [p, q^2, q] then
            g := Filtered(pcgsq, x -> Order(x) = q^2)[1];
            gens := [g, g^q, pcgsp[1], pcgsp[2]];
            G := PcgsByPcSequence(FamilyObj(gens[1]), gens);;
            gexp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
            gexp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
            mat := [gexp1{[3, 4]}, gexp2{[3, 4]}]*One(GF(p));
            x := Inverse(LogFFE(Eigenvalues(GF(p), mat)[1], a^((p - 1)/q))) mod q;
            det := LogFFE((LogFFE(DeterminantMat(mat^x), a^((p - 1)/q)) - 1)*One(GF(q)), b) mod (q - 1);
            if det < (q + 1)/2 then
                k := det;
            else
                k := (q - 1) - det;
            fi;
            return [n, 6 + 2 + k + SOTRec.w((p - 1), q^2)];
        elif ind = [p, q^2, p] and (p - 1) mod (q^2) = 0 and q > 2 then
            return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2)];
        elif ind = [p, q^2, 1] and (p - 1) mod (q^2) = 0 and q > 2 then
            g := Filtered(pcgsq, x -> Order(x)=q^2)[1];
            h := Filtered(pcgsp, x -> not x in Centre(Group([g^q, pcgsp[1], pcgsp[2]])))[1];
            if Size(Centre(Group([g^q, pcgsp[1], pcgsp[2]]))) = p then
                gens := [g, g^q, h, Pcgs(Centre(Group([g^q, pcgsp[1], pcgsp[2]])))[1]];
                G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
                gexp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
                gexp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
                mat := [gexp1{[3, 4]}, gexp2{[3, 4]}]*One(GF(p));
                x := Inverse(LogFFE(Filtered(Eigenvalues(GF(p), mat), x -> Order(x) = q^2)[1], a^((p - 1)/(q^2)))) mod q^2;
                ev := List(Eigenvalues(GF(p), mat^x), x -> LogFFE(x, a^((p - 1)/(q^2))));
                k := Filtered(ev, x -> x <> 1)[1]/q;
                return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2) + (q^2 - q + 2)/2 + k];
            else
                gens := [g, g^q, h, Filtered(pcgsp, x -> x <> h)[1]];
                G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
                gexp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
                gexp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
                mat := [gexp1{[3, 4]}, gexp2{[3, 4]}]*One(GF(p));
                x := Inverse(LogFFE(Eigenvalues(GF(p), mat)[1], a^((p - 1)/(q^2)))) mod q^2;
                ev := List(Eigenvalues(GF(p), mat^x), x -> LogMod(LogFFE(x, a^((p - 1)/(q^2))), Int(f), q^2) mod (q^2 - q));
                if Length(ev) = 1 then
                    k := 0;
                    return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2) + k + 1];
                elif Length(ev) > 1 then
                    k := Filtered(ev, x -> x <> 0)[1];
                    if k > (q^2 - q)/2 then
                        return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2) + (q^2 - q - k) + 1];
                    else
                        return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2) + k + 1];
                    fi;
                fi;
            fi;
        elif ind = [p, q, q * p] and q > 2 then
            return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2)*(q^2 + q + 4)/2 ];
        elif ind = [p, q, q] and q > 2 then
            g := Filtered(pcgsq, x -> not x in Zen)[1];
            h := Pcgs(Zen)[1];
            gens := [g, h, pcgsp[1], pcgsp[2]];
            G := PcgsByPcSequence(FamilyObj(gens[1]), gens);;
            gexp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
            gexp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
            mat := [gexp1{[3, 4]}, gexp2{[3, 4]}]*One(GF(p));
            x := Inverse(LogFFE(Eigenvalues(GF(p), mat)[1], a^((p - 1)/q))) mod q;
            det := LogFFE((LogFFE(DeterminantMat(mat^x), a^((p - 1)/q)) - 1)*One(GF(q)), b) mod (q - 1);
            if det < (q + 1)/2 then
                k := det;
            else
                k := (q - 1) - det;
            fi;
            return [n, 6 + (q + 5)/2 + SOTRec.w((p - 1), q^2)*(q^2 + q + 4)/2 + k + 1];
        elif ind = [p, q, 1] and q > 2 then
            return [n, 10 + q + SOTRec.w((p - 1), q^2)*(q^2 + q + 4)/2];
        fi;
    fi;
    if (p + 1) mod q = 0 and q > 2 then
        if ind = [p, q, q] then
            return [n, 6 + SOTRec.w((p + 1), q^2)];
        elif ind = [p, q^2, q] then
            return [n, 5];
        fi;
    fi;
    if ( p + 1) mod (q^2) = 0 and q > 2 and ind[3] = 1 then
        return [n, 6];
    fi;

    if q = 2 and p > 3 then
        if ind = [p^2, 4, 2] then
            return [n, 5];
        elif p mod 4 = 1 and ind = [p^2, 4, 1] then
            return [n, 5 + SOTRec.w((p - 1), 4)];
        elif ind{[1, 2]} = [p^2, 2] then
            return [n, 6 + SOTRec.w((p - 1), 4)];
        elif ind = [p, 4, 2*p] then
            return [n, 7 + SOTRec.w((p - 1), 4)];
        elif ind = [p, 4, 2] then
            return [n, 8 + SOTRec.w((p - 1), 4)];
        elif p mod 4 = 1 and ind = [p, 4, p] then
            return [n, 8 + 1 + SOTRec.w((p - 1), 4)];
        elif p mod 4 = 1 and ind = [p, 4, 1] then
            gexp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
            gexp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
            gexp3 := ExponentsOfPcElement(G, gens[3]^gens[2]);
            gexp4 := ExponentsOfPcElement(G, gens[4]^gens[2]);
            mat1 := [gexp1{[3, 4]}, gexp2{[3, 4]}]*One(GF(p));
            mat2 := [gexp3{[3, 4]}, gexp4{[3, 4]}]*One(GF(p));
            x := DeterminantMat(mat1);
            y := DeterminantMat(mat2);
            if AsSet([Int(x), Int(y)]) = AsSet([p - 1, 1]) then
                return [n, 8 + 2 + SOTRec.w((p - 1), 4)];
            elif AsSet([Int(x), Int(y)]) = AsSet([1, 1]) then
                return [n, 8 + 3 + SOTRec.w((p - 1), 4)];
            elif (not a^0 in Eigenvalues(GF(p), mat1) and a^0 in Eigenvalues(GF(p), mat2)) or (not a^0 in Eigenvalues(GF(p), mat2) and a^0 in Eigenvalues(GF(p), mat1)) then
                return [n, 8 + 4 + SOTRec.w((p - 1), 4)];
            fi;
        elif p mod 4 = 3 and ind = [p, q^2, 1] then
            return [n, 9];
        elif ind = [p, q, 2 * p] then
            return [n, 9 + SOTRec.w((p + 1), 4)+ 5*SOTRec.w((p - 1), 4)];
        elif ind = [p, q, 2] then
            return [n, 10 + SOTRec.w((p + 1), 4)+ 5*SOTRec.w((p - 1), 4)];
        elif ind = [p, q, 1] then
            return [n, 11 + SOTRec.w((p + 1), 4)+ 5*SOTRec.w((p - 1), 4)];
        fi;
    fi;
end;
######################################################
#
# the case of groups of order p^3q
#
SOTRec.IdGroupP3Q := function(group, n, fac)
local p, q, P, Q, O, Zen, a, b, r1, r2, r3, s1, s2, s3, c, d, e, f, g, h, x, y, k, l, tst,
  Id, gens, pc, pcgs, G, exp1, exp2, exp3, mat, matGL2, matGL3, det, Idfunc, tmp, ev, evm, N1, N2,
  c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, pcgsp, pcgsq;
    p := fac[2][1];
    q := fac[1][1];
    Assert(1, p <> q);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));
    ##
    Idfunc := function(q, l)
      local x, y, a, b, tuple, n, id;
        x := l[1] mod (q - 1);
        y := l[2] mod (q - 1);
        if l in [[(q-1)/3, 2*(q-1)/3], [2*(q-1)/3, (q-1)/3]] then
          return 1/6*(q^2 - 5*q + 6 + 4*SOTRec.w((q - 1), 3));
        else
          tuple := SortedList(Filtered(
          [SortedList([x, y]), SortedList([-x, y-x] mod (q - 1)), SortedList([-y, x-y] mod (q - 1))],
          list -> list[1] < Int((q + 2)/3) and list[2] < q - 1 - list[1]))[1];
          a := tuple[1];
          b := tuple[2];
          return Sum([1..a-1], x -> q - 1 - 3*x) + b + 1 - 2*a;
        fi;
    end;
    ##
    a := Z(p);
    b := Z(q);
    if (q - 1) mod p = 0 then
      r1 := b^((q-1)/p);
    fi;
    if (q - 1) mod (p^2) = 0 then
      r2 := b^((q-1)/(p^2));
    fi;
    if (q - 1) mod (p^3) = 0 then
      r3 := b^((q-1)/(p^3));
    fi;
    P := SylowSubgroup(group, p);
    pcgsp := Pcgs(P);
    Q := SylowSubgroup(group, q);
    pcgsq := Pcgs(Q);
    Zen := Centre(group);

    tst := [IsNormal(group, P), IsNormal(group, Q), IsAbelian(P), Exponent(P), Size(Zen)];
    if p = 2 then
      Add(tst, Size(Omega(P, 2)));
    fi;
  ############ enumeration
    c1 := SOTRec.delta(n, 24) + SOTRec.w((q - 1), p) + SOTRec.w((q - 1), p^2) + SOTRec.w((q - 1), p^3);
    c2 := 2*SOTRec.w((q - 1), p) + SOTRec.w((q - 1), p^2);
    c3 := SOTRec.w((q - 1), p);
    c4 := SOTRec.w((q - 1), p) + SOTRec.delta(p, 2);
    c5 := p*SOTRec.w((q - 1), p)*(1 - SOTRec.delta(p, 2)) + SOTRec.delta(p, 2);
    c6 := SOTRec.w((p - 1), q);
    c7 := (q + 1)*SOTRec.w((p - 1), q);
    c8 := (1 - SOTRec.delta(q, 2))*(
    1/6*(q^2 + 4*q + 9 + 4*SOTRec.w((q - 1), 3))*SOTRec.w((p - 1), q)
    + SOTRec.w((p^2 + p + 1), q)*(1 - SOTRec.delta(q, 3))
    + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2)))
    + 3*SOTRec.delta(q, 2);
    c9 := (1/2*(q + 3)*SOTRec.w((p - 1), q) + SOTRec.w((p + 1), q))*(1 - SOTRec.delta(q, 2))*(1 - SOTRec.delta(p, 2))
    + 2*SOTRec.delta(q, 2);
    c10 := SOTRec.w((p - 1), q);
  ############ abelian groups:
    if IsAbelian(group) then
      if tst[4] = p^3 then
        return [n, 1];
      elif tst[4] = p^2 then
        return [n, 2];
      elif tst[4] = p then
        return [n, 3];
      fi;
    fi;
  ############ case 1: no normal Sylow subgroup -- necessarily n = 24
    if not IsNormal(group, P) and not IsNormal(group, Q) then
      return [24, 15];
    fi;
  ############ interlude: n = 24
    if n = 24 and not IsAbelian(group) then
      if [tst[1], tst[2], tst[4], tst[6]] = [ true, true, 4, 8 ] then
        return [24, 4];
      elif [tst[1], tst[2], tst[4], tst[6]] = [ true, true, 4, 2 ] then
        return [24, 5];
      elif [tst[1], tst[2], tst[4], tst[6]] = [ false, true, 8, 2 ] then
        return [24, 6];
      elif [tst[1], tst[2], tst[4], tst[6]] = [ false, true, 4, 4 ] then
        O := Omega(P, 2);
        if IsNormal(group, O) then
          return [24, 8];
        else
          return [24, 7];
        fi;
      elif [tst[1], tst[2], tst[4], tst[6], tst[5]] = [ false, true, 2, 8, 4 ] then
        return [24, 9];
      elif [tst[1], tst[2], tst[4], tst[6]] = [ false, true, 4, 8 ] then
        d := pcgsq[1];
        repeat c := Random(P); until not c in Centre(P) and d*c = c*d;
        O := Group([c, d, Pcgs(Zen)[1]]);
        if IsCyclic(O) then
          return [24, 11];
        else
          return [24, 10];
        fi;
      elif [tst[1], tst[2], tst[4], tst[6]] = [ false, true, 4, 2 ] then
        return [24, 12];
      elif [tst[1], tst[2], tst[4], tst[6]] = [ true, false, 2, 8 ] then
        return [24, 13];
      elif [tst[1], tst[2], tst[4], tst[6]] = [ true, false, 4, 2 ] then
        return [24, 14];
      fi;
    fi;

  ############ case 2: nonabelian and every Sylow subgroup is normal, namely, P \times Q -- determined by the isomorphism type of P
    if p > 2 and [tst[1], tst[2]] = [true, true] and IsAbelian(group) = false then
      if tst[4] = p then
        return [n, 4];
      elif tst[4] = p^2 then
        return [n, 5];
      fi;
    elif p = 2 and q > 3 and IsNilpotent(group) and IsAbelian(group) = false then
      if tst[6] = 8 then
        return [n, 4];
      elif tst[6] = 2 then
        return [n, 5];
      fi;
    fi;

  ############ case 3: nonabelian and only Sylow q-subgroup is normal, namely, P \ltimes Q
    if n <> 24 and [tst[1], tst[2]] = [false, true] then ##it follows that (q - 1) mod p = 0
      ## class 1: when P = C_{p^3}
      if tst[4] = p^3 and (q - 1) mod p = 0 then
        if tst[5] = p^2 then
          return [n, 6];
        elif (q - 1) mod (p^2) = 0 and tst[5] = p then
          return [n, 7];
        elif (q - 1) mod (p^3) = 0 and tst[5] = 1 then
          return [n, 8];
        fi;
      ## class 2: when P = C_{p^2} \times C_p, there are at most three isom types of semidirect products of P \ltimes Q
      elif tst[3] = true and tst[4] = p^2 then
        if Exponent(Zen) = p^2 then
          return [n, 6 + c1];
        elif Exponent(Zen) = p and tst[5] = p^2 then
          return [n, 7 + c1];
        elif (q - 1) mod (p^2) = 0 and tst[5] = p then
          return [n, 8 + c1];
        fi;
      ## class 3: when P is elementary abelian, there is at most one isom type of P \ltimes Q
      elif tst[3] = true and (q - 1) mod p = 0 then
        return [n, 6 + c1 + c2];
      ## class 4: when P is extraspecial + type
      elif not tst[3] = true and tst[4] = p and p > 2 then
        return [n, 6 + c1 + c2 + c3];
      elif not tst[3] = true and tst[4] = 4 and tst[6] = 8 then
        d := pcgsq[1];
        repeat c := Random(P); until not c in Centre(P) and d*c = c*d;
        O := Group([c, d, Pcgs(Zen)[1]]);
        if IsCyclic(O) then
          return [n, 11 + 2*SOTRec.w((q - 1), p^2) + SOTRec.w((q - 1), p^3)];
        else
          return [n, 10 + 2*SOTRec.w((q - 1), p^2) + SOTRec.w((q - 1), p^3)];
        fi;
      ## class 5: when P is extraspecial - type
      elif not tst[3] = true and tst[4] = p^2 and p > 2 then
        repeat c := Random(P); until Order(c) = p and not c in Centre(P) and not IsCyclic(Group([c, Pcgs(Centre(P))[1]]));
        d := pcgsq[1];
        repeat g := Random(P); until Order(g) = p^2 and g^p in Centre(P);
        h := g^p;
        gens := [c, g, h, d];;
        G := PcgsByPcSequence(FamilyObj(gens[1]), gens);;
        x := Inverse(ExponentsOfPcElement(G, gens[2]^gens[1])[3]) mod p;
        k := LogFFE(ExponentsOfPcElement(G, gens[4]^(gens[1]^x))[4]*One(GF(q)), r1) mod p;
        if k > 0 then
          return [n, 10 + k + 2*SOTRec.w((q - 1), p^2) + SOTRec.w((q - 1), p^3)];
        else
          return [n, 11 + 2*SOTRec.w((q - 1), p^2) + SOTRec.w((q - 1), p^3) + (p - 1)];
        fi;
      ## class 6: when P = Q_8, there is a unique isom type of P \ltimes Q
      elif not tst[3] = true and tst[6] = 2 then
        return [n, 12 + 2*SOTRec.w((q - 1), p^2) + SOTRec.w((q - 1), p^3)];
      fi;
    fi;
  ############ case 4: nonabelian and only the Sylow p-subgroup is normal
    if n <> 24 and [tst[1], tst[2]] = [true, false] then
      if (p - 1) mod q = 0 then
        s1 := a^((p - 1)/q);

        c := ZmodnZObj(Int(Z(p)), p^3);
        if not c^(p - 1) = ZmodnZObj(1, p^2) then
          d := c;
        else
          d := c + 1;
        fi;
        s3 := d^((p^3 - p^2)/q);

        e := ZmodnZObj(Int(Z(p)), p^2);
        if not e^(p - 1) = ZmodnZObj(1, p^2) then
          f := e;
        else
          f := e + 1;
        fi;

        s2 := f^((p^2-p)/q);
      fi;

      ## class 1: when P is cyclic, there is at most isom type of semidirect products of Q \ltimes P #it follows that (p - 1) mod q = 0
      if tst[4] = p^3 then
        return [n, 6];
      ## class 2: when P = C_{p^2} \times C_p, there are at most (q + 1) isomorphism types of Q \ltimes P
    elif tst[3] = true and tst[4] = p^2 and tst[5] = p^2 then ## (C_q \ltimes C_p) \times C_{p^2}
        return [n, 7];
      elif tst[3] = true and tst[4] = p^2 and tst[5] = p then ## (C_q \ltimes C_{p^2}) \times C_p
        return [n, 8];
      elif tst[3] = true and tst[4] = p^2 and tst[5] = 1 and q > 2 then ## C_q \ltimes (C_{p^2} \times C_p)
        repeat g := Random(P); until Order(g) = p and not g in FrattiniSubgroup(P);
        h := Filtered(pcgsp, x -> Order(x) = p^2)[1];
        gens:= [pcgsq[1], h, h^p, g];
        G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
        x := Inverse(LogMod(ExponentsOfPcElement(G, gens[3]^gens[1])[3], Int(s2), p)) mod q;
        k := LogFFE(ExponentsOfPcElement(G, gens[4]^gens[1])[4]^x*One(GF(p)), s1) mod q;
        return [n, 8 + k];
      elif tst[3] = true and tst[4] = p^2 and tst[5] = 1 and q = 2 then ## C_q \ltimes (C_{p^2} \times C_p)
        return [n, 9];
      ## class 3: when P is elementary abelian
    elif tst[3] = true and tst[5] = p^2 then ## (C_q \ltimes C_p) \times C_p^2
        return [n, 9 + (q - 1)];
      elif tst[3] = true and tst[5] = p and (p - 1) mod q = 0 and q > 2 then ## (C_q \ltimes C_p^2) \times C_p when q | (p - 1)
        gens:= [pcgsq[1], Filtered(pcgsp, x->not x in Zen)[1], Filtered(pcgsp, x->not x in Zen)[2], Filtered(pcgsp, x->x in Zen)[1]];
        G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
        exp1 := ExponentsOfPcElement(G, gens[2]^gens[1]);
        exp2 := ExponentsOfPcElement(G, gens[3]^gens[1]);
        matGL2 := [exp1{[2, 3]}, exp2{[2, 3]}]* One(GF(p));
        x := Inverse(LogFFE(Eigenvalues(GF(p), matGL2)[1], s1)) mod q;
        det := LogFFE((LogFFE(DeterminantMat(matGL2^x), s1) - 1)*One(GF(q)), b) mod (q - 1);
        if det < (q + 1)/2 then
          k := det;
        else
          k := (q - 1) - det;
        fi;
        return [n, 10 + k + (q - 1)];
      elif tst[3] = true and tst[5] = p and q = 2 then ## (C_q \ltimes C_p^2) \times C_p when q | (p - 1)
        return [n, 10 + (q - 1)];
      elif tst[3] = true and tst[5] = p and (p + 1) mod q = 0 and q > 2 then
        return [n, 6 + (5 + p)*SOTRec.w((q - 1), p)];
      ## below: (C_q \ltimes C_p^3) when q | (p - 1)
      elif tst[3] = true and tst[5] = 1 and q = 2 then
        return [n, 12];
      elif tst[3] = true and tst[5] = 1 and (p - 1) mod q = 0 and q > 2 then
        gens := [pcgsq[1], pcgsp[1], pcgsp[2], pcgsp[3]];
        G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
        exp1 := ExponentsOfPcElement(G, gens[2]^gens[1]);
        exp2 := ExponentsOfPcElement(G, gens[3]^gens[1]);
        exp3 := ExponentsOfPcElement(G, gens[4]^gens[1]);
        mat := [exp1{[2, 3, 4]}, exp2{[2, 3, 4]}, exp3{[2, 3, 4]}] * One(GF(p));
        ev := Eigenvalues(GF(p), mat);
        if Length(ev) = 1 then
          return [n, 10 + (q + 1)/2 + (q - 1)];
        elif Length(ev) <> 1 then
          if Length(ev) = 2 then
            evm := SOTRec.EigenvaluesWithMultiplicitiesGL3P(mat, p);
            x := Inverse(LogFFE(Filtered(evm, x -> x[2] = 2)[1][1], s1)) mod q;
            k := LogFFE(Filtered(evm, x -> x[2] = 1)[1][1]^x, s1) mod q;
            return [n, 9 + k + (q + 1)/2 + (q - 1)];
          elif Length(ev) = 3 then
            x := Inverse(LogFFE(Eigenvalues(GF(p), mat)[1], s1)) mod q;
            l := List(ev, i -> i^x);
            y := List(Filtered(l, x->x <> s1), x -> LogFFE(x, s1)*One(GF(q)));
            l := List(y, x -> (LogFFE(x, b) mod (q - 1)));
            k := Idfunc(q, l);
            return [n, 9 + k + (q - 1) + (q + 1)/2 + (q - 1)];
          fi;
        fi;
      elif tst[3] = true and tst[4] = p and tst[5] = 1 and (p^2 + p + 1) mod q = 0 and q > 3 then
        return [n, 5 + (5+p)*SOTRec.w((q-1), p) + 2*SOTRec.w((q-1), p^2)
          + SOTRec.w((q-1), p^3) + (15+q^2+10*q+4*SOTRec.w((q-1),3))*SOTRec.w((p-1), q)*(1 - SOTRec.delta(q, 2))/6
          + SOTRec.w((p+1), q) + SOTRec.w((p^2+p+1), q)*(1 - SOTRec.delta(q, 3))];
      ## class 4: when P is extraspecial of type +
      elif (not tst[3] = true and tst[4] = p and (p - 1) mod q = 0) then
        if tst[5] = p then ## q | (p - 1), Z(G) = C_p
          if n mod 2 = 1 then
            return [n, 6 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8];
          else
            return [n, 5 + 7*SOTRec.delta(p, 2) + 2*SOTRec.w((q-1),4) + SOTRec.w((q-1), 8)
            + 8*SOTRec.delta(q, 2) + 3*SOTRec.delta(n,24) + SOTRec.delta(n, 56)];
          fi;
        elif tst[5] = 1 then ## q | (p - 1), Z(G) = 1
          if Size(DerivedSubgroup(group)) = p^2 and q > 2 then
            return [n, 8 + (15+q^2+10*q+4*SOTRec.w((q-1),3))/6 + SOTRec.w((p^2+p+1), q)*(1 - SOTRec.delta(q, 3))];
          elif Size(DerivedSubgroup(group)) = p^2 and q = 2 then
            return [n, 5 + 7*SOTRec.delta(p,2) + 2*SOTRec.w((q-1),4) + SOTRec.w((q-1), 8)
              + 9*SOTRec.delta(q, 2) + 3*SOTRec.delta(n,24) + SOTRec.delta(n, 56)];
          elif Size(DerivedSubgroup(group)) = p^3 and q > 2 then
            gens := [pcgsq[1], Filtered(pcgsp, x -> not x in Centre(P))[1], Filtered(pcgsp, x -> not x in Centre(P))[2], Filtered(pcgsp, x->x in Centre(P))[1]];
            G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
            exp1 := ExponentsOfPcElement(G, gens[2]^gens[1]);
            exp2 := ExponentsOfPcElement(G, gens[3]^gens[1]);
            exp3 := ExponentsOfPcElement(G, gens[4]^gens[1]);
            x := Inverse(LogFFE(exp3[4] * One(GF(p)), s1)) mod q;
            matGL3 := ([exp1{[2, 3, 4]}, exp2{[2, 3, 4]}, exp3{[2, 3, 4]}])^x * One(GF(p));
            y := List(Filtered(Eigenvalues(GF(p), matGL3), x -> x <> s1), x -> LogFFE(x, s1) mod q)[1];
            if y > (q + 1)/2 then
              k := (q + 1) - y - 1;
            else
              k := y - 1;
            fi;
            return [n, 8 + k + (15+q^2+10*q+4*SOTRec.w((q-1),3))/6 + SOTRec.w((p^2+p+1), q)*(1 - SOTRec.delta(q, 3))];
          fi;
        fi;
      elif not tst[3] = true and tst[4] = p and (p + 1) mod q = 0 and q > 2 and p > 2 then
        return [n, 7];
      ## class 5: when P is extraspecial of type -,
      elif not tst[3] = true and tst[4] = p^2 and (p - 1) mod q = 0 then
        if n mod 2 = 1 then
          return [n, 6 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9];
        else
          return [n, 5 + 7*SOTRec.delta(p, 2) + 2*SOTRec.w((q-1),4) + SOTRec.w((q-1), 8)
            + 10*SOTRec.delta(q, 2) + 3*SOTRec.delta(n,24) + SOTRec.delta(n, 56)];
        fi;
      fi;
    fi;
end;
######################################################
#
# the case of groups of order p^2qr
#
SOTRec.IdGroupP2QR := function(group, n, fac)
local p, q, r, P, Q, R, Zen,a, b, c, u, v, flag, G, gens, pc, pcgs, g, h,
  c1, c2, c3, c4, c5, c6, c7, k, l, m, tmp, exp, exp1, exp2, expp1q, expp2q, expp1r, expp2r,
  matq, det, matr, detr, matqr, evqr, mat, mat_k, Id, x, y, z, ev, lst, N1, N2,
  pcgsp, pcgsq, pcgsr;

    p := fac[3][1];
    q := fac[1][1];
    r := fac[2][1];
    ####
    Assert(1, r > q);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));
    Assert(1, IsPrimeInt(r));

    a := Z(r);;
    b := Z(p);;
    c := Z(q);;

    u := ZmodnZObj(Int(Z(p)), p^2);;
    if not u^(p-1) = ZmodnZObj(1, p^2) then
      v := u;
    else
      v := u + 1;
    fi;

    P := SylowSubgroup(group, p);
    Q := SylowSubgroup(group, q);
    R := SylowSubgroup(group, r);
    pcgsp := Pcgs(P);
    pcgsq := Pcgs(Q);
    pcgsr := Pcgs(R);
    Zen := Centre(group);

    flag := [Size(FittingSubgroup(group)), Size(Zen), Exponent(P)];

    c1 := SOTRec.w((r - 1), p^2*q);;
    c2 := SOTRec.w((q - 1), p^2) + (p - 1)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p)
    + (p^2 - p)*SOTRec.w((r - 1), p^2)*SOTRec.w((q - 1), p^2)
    + SOTRec.w((r - 1), p^2) + (p - 1)*SOTRec.w((q - 1), p)*SOTRec.w((r - 1), p^2)
    + SOTRec.w((r - 1), p)*SOTRec.w((q - 1), p);;
    c3 := 1/2*(q*r+q+r+7)*SOTRec.w((p - 1), q*r)
    + SOTRec.w((p^2 - 1), q*r)*(1 - SOTRec.w((p - 1), q*r))*(1 - SOTRec.delta(q, 2))
    + 2*SOTRec.w((p + 1), r)*SOTRec.delta(q, 2);;
    c4 := 1/2*(r + 5)*SOTRec.w((p - 1), r) + SOTRec.w((p + 1), r);;
    c5 := 8*SOTRec.delta(q, 2)
    + (1 - SOTRec.delta(q, 2))*(1/2*(q - 1)*(q + 4)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
    + 1/2*(q - 1)*SOTRec.w((p + 1), q)*SOTRec.w((r - 1), q)
    + 1/2*(q + 5)*SOTRec.w((p - 1), q)
    + 2*SOTRec.w((r - 1), q)
    + SOTRec.w((p + 1), q));;
    c6 := SOTRec.w((r - 1), p)*(SOTRec.w((p - 1), q)*(1 + (q - 1)*SOTRec.w((r - 1), q))
    + 2*SOTRec.w((r - 1), q));;
    c7 := 2*(SOTRec.w((q - 1), p) + SOTRec.w((r - 1), p) +
    (p - 1)*SOTRec.w((q - 1), p)*SOTRec.w((r - 1), p)) + SOTRec.delta(n, 60);

    if IsSolvable(group) then
      ############ abelian groups:
      if IsAbelian(group) and flag[3] = p^2 then
        return [n, 1];
      elif IsAbelian(group) and flag[3] = p then
        return [n, 2];
      fi;
      ############ case 1: nonabelian and Fitting subgroup has order r -- unique isomorphism type iff p^2q | (r - 1)
      if flag[1] = r then
        return [n, 3]; ##C_{p^2q} \ltimes C_r
      ############ case 2: nonabelian and Fitting subgroup has order qr -- p^2 | (q - 1)(r - 1) or (p^2 | (q - 1) or (r - 1)) or (p | (q - 1) and p | (r - 1))
      elif flag[1] = q*r then
        if flag[2] = r then ## p^2 | (q - 1) and G \cong (C_{p^2} \ltimes C_q) \times C_r
          return [n, 3 + c1];
        elif flag[2] = q then ## p^2 | (r - 1), and G \cong (C_{p^2} \ltimes C_r) \times C_q
          return [n, 3 + c1 + (p^2 - p)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p^2)
          + (p - 1)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p)
          + SOTRec.w((q - 1), (p^2))];
        elif flag[2] = 1 and flag[3] = p^2 then
          gens := [pcgsp[1], pcgsp[2], pcgsq[1], pcgsr[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          exp := ExponentsOfPcElement(G, gens[3]^gens[1]);

          if IsOne(Comm(gens[2], gens[4])) and not IsOne(Comm(gens[2], gens[3])) then ## p^2 | (q - 1), p | (r - 1), and G \cong C_{p^2} \ltimes (C_q \times C_r)
            x := Inverse(LogFFE(exp[3]*One(GF(q)), c^((q-1)/(p^2)))) mod (p^2);
            pcgs := [gens[1]^x, gens[1]^(x*p), gens[3], gens[4]];
            pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
            exp1 := ExponentsOfPcElement(pc, pcgs[4]^pcgs[1]);
            k := LogFFE(exp1[4]*One(GF(r)), a^((r-1)/p)) mod p;
            return [n, 2 + k + c1 + SOTRec.w((q - 1), (p^2))];
          elif (not IsOne(Comm(gens[2], gens[4]))) and (not IsOne(Comm(gens[2], gens[3]))) then ## p^2 | (q - 1), p^2 | (r - 1), and G \cong C_{p^2} \ltimes (C_q \times C_r)
            x := Inverse(LogFFE(exp[3]*One(GF(q)), c^((q-1)/(p^2)))) mod (p^2);
            pcgs := [gens[1]^x, gens[1]^(x*p), gens[3], gens[4]];
            pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
            exp1 := ExponentsOfPcElement(pc, pcgs[4]^pcgs[1]);
            k := PositionSet(SOTRec.groupofunitsP2(p), LogFFE(exp1[4]*One(GF(r)), a^((r-1)/(p^2))) mod (p^2));
            return [n, 2 + k + c1 + (p - 1)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p)
            + SOTRec.w((q - 1), (p^2))];
          elif (not IsOne(Comm(gens[2], gens[4]))) and IsOne(Comm(gens[2], gens[3])) then ## p | (q - 1), p^2 | (r - 1), and G \cong C_{p^2} \ltimes (C_q \times C_r)
            x := Inverse(LogFFE(exp[3]*One(GF(q)), c^((q-1)/p))) mod p;
            pcgs := [gens[1]^x, gens[1]^(x*p), gens[3], gens[4]];
            pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
            exp1 := ExponentsOfPcElement(pc, pcgs[4]^pcgs[2]);
            k := LogFFE(exp1[4]*One(GF(r)), a^((r-1)/p)) mod p;
            return [n, 2 + k + c1 + SOTRec.w((r - 1), p^2) + (p^2 - p)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p^2)
            + (p - 1)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p)
            + SOTRec.w((q - 1), (p^2))];
          fi;
        elif flag[2] = 1 and Exponent(group) = p * q * r then ## p | (q - 1), p | (r - 1), and G \cong (C_p \ltimes C_q) \times (C_p \ltimes C_r)
          return [n, 3 + c1 + (p - 1)*SOTRec.w((q - 1), p)*SOTRec.w((r - 1), p^2)
          + SOTRec.w((r - 1), p^2) + (p^2 - p)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p^2)
          + (p - 1)*SOTRec.w((q - 1), p^2)*SOTRec.w((r - 1), p)
          + SOTRec.w((q - 1), (p^2))];
        fi;
      ############ case 3: nonabelian and Fitting subgroup has order p^2 -- qr | (p^2 - 1)
    elif flag[1] = p^2 and flag[3] = p^2 and flag[2] = 1 then ## qr | (p - 1) and G \cong C_{qr} \ltimes C_{p^2}
        return [n, 3 + c1 + c2];
      elif flag[1] = p^2 and flag[3] = p and flag[2] = 1 and (p - 1) mod (q*r) = 0 then
        N1 := Group([pcgsq[1], pcgsp[1], pcgsp[2]]);
        N2 := Group([pcgsr[1], pcgsp[1], pcgsp[2]]);
        if Size(Centre(N1)) = p and Size(Centre(N2)) = p then
           return [n, 3 + c1 + c2 + SOTRec.w((p - 1), q*r)];
        elif pcgsr[1]^pcgsq[1] = pcgsr[1] and Size(Centre(N2)) = p and Size(Centre(N1)) = 1 then ##R acts trivially on one of the generators of P
          gens := [pcgsq[1]*pcgsr[1], pcgsq[1], Filtered(pcgsp, x-> x^pcgsq[1] <> x and x^pcgsr[1] <> x)[1], Pcgs(Centre(N2))[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          exp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
          exp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
          mat := [exp1{[3, 4]}, exp2{[3, 4]}]*One(GF(p));
          ev := Eigenvalues(GF(p), mat);
          if Length(ev) = 1 then
            k := 1;
          else
            x := Inverse(LogFFE(Filtered(ev, x->Order(x) = q*r)[1], b^((p - 1)/(q*r)))) mod (q*r);
            matq := mat^x;
            k := LogFFE(Filtered(Eigenvalues(GF(p), matq), x->Order(x) = q)[1], b^((p - 1)/(q*r))) mod q;
          fi;
          return [n, 3 + (k - 1) + c1 + c2 + 3*SOTRec.w((p - 1), q*r)];
        elif pcgsr[1]^pcgsq[1] = pcgsr[1] and Size(Centre(N1)) = p and Size(Centre(N2)) = 1 then ##Q acts trivially on one of the generators of P
          gens := [pcgsq[1]*pcgsr[1], pcgsr[1], Filtered(pcgsp, x-> x^pcgsq[1] <> x and x^pcgsr[1] <> x)[1], Pcgs(Centre(N1))[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          exp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
          exp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
          mat := [exp1{[3, 4]}, exp2{[3, 4]}]*One(GF(p));
          ev := Eigenvalues(GF(p), mat);
          if Length(ev) = 1 then
            k := 1;
          else
            x := Inverse(LogFFE(Filtered(ev, x->Order(x) = q*r)[1], b^((p - 1)/(q*r)))) mod (q*r);
            matr := mat^x;
            k := LogFFE(Filtered(Eigenvalues(GF(p), matr), x->Order(x) = r)[1], b^((p - 1)/(q*r))) mod r;
          fi;
          return [n, 3 + (k - 1) + c1 + c2
                  + 3*SOTRec.w((p - 1), q*r)
                  + (q - 1) * SOTRec.w((p - 1), q*r)];
        elif pcgsr[1]^pcgsq[1] = pcgsr[1] and Size(Centre(N1)) = 1 and Size(Centre(N2)) = 1 then ## Q and R act nontrivially on both the generators of P
          gens := [pcgsq[1]*pcgsr[1], pcgsr[1], pcgsp[1], pcgsp[2]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          exp1 := ExponentsOfPcElement(G, gens[3]^gens[1]);
          exp2 := ExponentsOfPcElement(G, gens[4]^gens[1]);
          mat := [exp1{[3, 4]}, exp2{[3, 4]}] * One(GF(p));
          x := Eigenvalues(GF(p), mat);
          if (p-1) mod (q*r) = 0 and q > 2 then
            tmp := [];
            for k in [0..(q - 1)/2] do
              for l in [0..(r - 1)/2] do
                Add(tmp, AsSet([[k, l], [(-k) mod (q - 1), (-l) mod (r - 1)]])); #AsSet([[(k) mod (q - 1), (-l) mod (r - 1)], [(-k) mod (q - 1), (l) mod (r - 1)]])]));
              od;
            od;
            for k in [1..(q-3)/2] do
              for l in [(r+1)/2..(r-2)] do
                Add(tmp, AsSet([[k, l], [(-k) mod (q - 1), (-l) mod (r - 1)]])); #AsSet([[(k) mod (q - 1), (-l) mod (r - 1)], [(-k) mod (q - 1), (l) mod (r - 1)]])]));
              od;
            od;
          fi;
          if (p-1) mod (q*r) = 0 and q = 2 then
            tmp := [];
            for l in [0..(r-1)/2] do
              Add(tmp, AsSet([[0, l], [0, (-l) mod (r - 1)]]));
            od;
          fi;
          if Length(x) = 1 then
            k := 0;
            l := 0;
          else
            k := LogFFE(LogFFE(x[2], x[1])*One(GF(q)), c) mod (q - 1);
            l := LogFFE(LogFFE(x[2], x[1])*One(GF(r)), a) mod (r - 1);
          fi;
          m := Position(tmp, AsSet([[k, l], [(-k) mod (q - 1), (-l) mod (r - 1)]]));
          return [n, 3 + (m - 1) + c1 + c2
          + 3*SOTRec.w((p - 1), q*r)
          + (r - 1 + q - 1) * SOTRec.w((p - 1), q*r)];
        elif q = 2 and pcgsr[1]^pcgsq[1] <> pcgsr[1] then ##q = 2, r | (p - 1), and G \cong (C_2 \ltimes C_r) \ltimes C_p^2
          return [n, 3 + c1 + c2
          + 3*SOTRec.w((p - 1), q*r)
          + ((r + 1)/2 + r - 1 + q - 1) * SOTRec.w((p - 1), q*r)];
        fi;
      elif flag[1] = p^2 and flag[3] = p and flag[2] = p then  ## qr | (p - 1) and G \cong (C_{qr} \ltimes C_p) \times C_p
        return [n, 3 + c1 + c2
        + 2*SOTRec.w((p - 1), q*r)];
      elif flag[1] = p^2 and flag[3] = p and flag[2] = 1 and (p + 1) mod (q*r) = 0 and q > 2 then ## qr | (p + 1), q > 2, and G \cong C_{qr} \ltimes C_p^2
        return [n, 3 + c1 + c2];
      elif flag[1] = p^2 and flag[3] = p and flag[2] = 1 and (p + 1) mod (q*r) = 0 and q = 2 then
        if IsOne(Comm(pcgsq[1], pcgsr[1])) then ## qr | (p + 1), q = 2, and G \cong C_{qr} \ltimes C_p^2
          return [n, 3 + c1 + c2];
        else ## qr | (p + 1), q = 2, and G \cong (C_2 \ltimes C_r)\ltimes C_p^2
          return [n, 4 + c1 + c2];
        fi;
      elif flag[1] = p^2 and flag[3] = p and flag[2] = 1 and (p + 1) mod r = 0 and (p - 1) mod q = 0 and q > 2 then ## q | (p - 1), r | (p + 1), and G \cong (C_q \times C_r) \ltimes C_p^2
        return [n, 3 + c1 + c2];
      elif flag[1] = p^2 and flag[3] = p and flag[2] = 1 and (p - 1) mod r = 0 and (p + 1) mod q = 0 and q > 2 then ## q | (p + 1), r | (p - 1), and G \cong (C_q \times C_r) \ltimes C_p^2
        return [n, 3 + c1 + c2];

      ############ case 4: nonabelian and Fitting subgroup has order p^2q -- r | (p - 1) or r | (p + 1)
      elif flag[1] = p^2*q then
        if flag[3] = p^2 and flag[2] = q then ## r | (p - 1) and G \cong (C_r \ltimes C_{p^2}) \times C_q
          return [n, 3 + c1 + c2 + c3];
        elif flag[2] = p*q then ## r | (p - 1) and G \cong (C_r \ltimes C_p) \times (C_p \times C_q)
          return [n, 3 + c1 + c2 + c3
          + SOTRec.w((p - 1), r)];
        elif flag[3] = p and flag[2] = q and (p - 1) mod r = 0 then ## r | (p - 1) and G \cong (C_r \ltimes C_p^2) \times C_q
          gens := [pcgsr[1], pcgsp[1], pcgsp[2], pcgsq[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          expp1r := ExponentsOfPcElement(G, gens[2]^gens[1]);
          expp2r := ExponentsOfPcElement(G, gens[3]^gens[1]);
          matr := [expp1r{[2, 3]}, expp2r{[2, 3]}]*One(GF(p));
          x := Inverse(LogFFE(Eigenvalues(GF(p), matr)[1], b^((p-1)/r))) mod r;
          detr := LogFFE((LogFFE(DeterminantMat(matr^x), b^((p-1)/r)) - 1)*One(GF(r)), a) mod (r - 1);
          if detr < (r + 1)/2 then
            k := detr;
          else
            k := (r - 1) - detr;
          fi;
          return [n, 3 + k + c1 + c2 + c3
          + 2*SOTRec.w((p - 1), r)];
        elif flag[3] = p and flag[2] = q and (p + 1) mod r = 0 then ## r | (p - 1) and G \cong (C_r \ltimes C_p^2) \times C_q
          return [n, 3 + c1 + c2 + c3];
        fi;
      ############ case 5: nonabelian and Fitting subgroup has order p^2r -- q | (p - 1)(r - 1) or q | (p + 1)(r - 1)
      elif flag[1] = p^2*r then
        if flag[2] = p^2 and IsCyclic(Zen) then ## q \mid (r - 1) and G \cong (C_q \ltimes C_r) \times C_{p^2}
          return [n, 3 + c1 + c2 + c3 + c4];
        elif flag[3] = p^2 and flag[2] = r then ## q \mid (p - 1) and G \cong (C_q \ltimes C_{p^2}) \times C_r
          return [n, 3 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)];
        elif flag[3] = p^2 and flag[2] = 1 then ## q \mid (p - 1), q | (r - 1) and G \cong C_q \ltimes (C_{p^2} \times C_r)
          gens:= [pcgsq[1], Filtered(pcgsp, x->Order(x) = p^2)[1], Filtered(pcgsp, x->Order(x) = p^2)[1]^p, pcgsr[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          x := Inverse(LogMod(ExponentsOfPcElement(G, gens[3]^gens[1])[3], Int(v^((p^2-p)/q)), p)) mod q;
          pcgs := [gens[1]^x, gens[2], gens[3], gens[4]];
          pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
          k := LogFFE(ExponentsOfPcElement(pc, pcgs[4]^pcgs[1])[4]*One(GF(r)), a^((r - 1)/q)) mod q;
          return [n, 3 + (k - 1) + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)];
        elif flag[2] = p*r then ## q \mid (p - 1) and G \cong (C_q \ltimes C_p) \times (C_p \times C_r)
          return [n, 3 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)];
        elif (p - 1) mod q = 0 and flag[3] = p and flag[2] = r and q > 2 then ## q | (p - 1) and G \cong (C_q \ltimes C_p^2) \times C_r
          gens:= [pcgsq[1], pcgsp[1], pcgsp[2], pcgsr[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          expp1q := ExponentsOfPcElement(G, gens[2]^gens[1]);
          expp2q := ExponentsOfPcElement(G, gens[3]^gens[1]);
          x := Inverse(LogFFE(Eigenvalues(GF(p), [expp1q{[2, 3]}, expp2q{[2, 3]}]* One(GF(p)))[1], b^((p-1)/q))) mod q;
          pcgs := [gens[1]^x, gens[2], gens[3], gens[4]];
          pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
          matq := [expp1q{[2, 3]}, expp2q{[2, 3]}]^x * One(GF(p));
          det := LogFFE((LogFFE(DeterminantMat(matq), b^((p-1)/q)) - 1)*One(GF(q)), c) mod (q - 1);
          if det < (q + 1)/2 then
            k := det;
          else
            k := (q - 1) - det;
          fi;
          return [n, 3 + k + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)];
        elif flag[3] = p and flag[2] = r and q = 2 then ## q | (p - 1) and G \cong (C_q \ltimes C_p^2) \times C_r
          return [n, 3 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)];
        elif (p + 1) mod q = 0 and flag[2] = r and q > 2 then ## q | (p + 1), and G \cong (C_q \ltimes C_p^2) \times C_r
          return [n, 3 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)];
        elif flag[2] = p^2 and IsElementaryAbelian(Zen) then ## q | (r - 1), and G \cong (C_q \ltimes C_r) \times C_p^2
          return [n, 3 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q + 1)/2*SOTRec.w((p - 1), q)*(1 - SOTRec.delta(q, 2))
          + SOTRec.delta(q, 2)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))];
        elif flag[2] = p and q > 2 then ## q | (r - 1), q | (p - 1), and G \cong C_q \ltimes (C_r \times C_p) \times C_p
          gens := [pcgsq[1], pcgsr[1], Filtered(pcgsp, x-> not x in Zen)[1], Filtered(pcgsp, x-> x in Zen)[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          x := Inverse(LogFFE(ExponentsOfPcElement(G, gens[2]^gens[1])[2]*One(GF(r)), a^((r - 1)/q))) mod q;
          pcgs := [gens[1]^x, gens[2], gens[3], gens[4]];
          pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
          k := LogFFE(ExponentsOfPcElement(pc, pcgs[3]^pcgs[1])[3]*One(GF(p)), b^((p - 1)/q)) mod q;
          return [n, 3 + (k - 1) + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q + 1)/2*SOTRec.w((p - 1), q)*(1 - SOTRec.delta(q, 2))
          + SOTRec.delta(q, 2)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))
          + SOTRec.w((r - 1), q)];
        elif flag[2] = p and q = 2 then
          return [n, 4 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q + 1)/2*SOTRec.w((p - 1), q)*(1 - SOTRec.delta(q, 2))
          + SOTRec.delta(q, 2)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))];
        elif flag[3] = p and flag[2] = 1 and q > 2 and (r - 1) mod q = 0 and (p - 1) mod q = 0 then ##(r - 1) mod q = 0 and (p - 1) mod q = 0, G \cong C_q \ltimes (C_r \times C_p^2)
          tmp := [];
          for k in [0..(q - 3)/2] do
            Add(tmp, AsSet([[0, k], [0, (- k) mod (q - 1)]]));
          od;
          for l in [1..(q - 3)/2] do
            for k in [0..(q - 1)/2] do
              Add(tmp, AsSet([[l, k], [(l - k) mod (q - 1), (- k) mod (q - 1)]]));
            od;
          od;
          Add(tmp, AsSet([[(q - 1)/2, (q - 1)/2], [0, (q - 1)/2]]));
          for l in [(q - 1)/2..q - 2] do
            for k in [0..(q - 3)/2] do
              Add(tmp, AsSet([[l, k], [(l - k) mod (q - 1), (- k) mod (q - 1)]]));
            od;
          od;
          gens := [pcgsq[1], pcgsr[1], pcgsp[1], pcgsp[2]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          expp1q := ExponentsOfPcElement(G, gens[3]^gens[1]);
          expp2q := ExponentsOfPcElement(G, gens[4]^gens[1]);
          matq := [expp1q{[3, 4]}, expp2q{[3, 4]}]* One(GF(p));
          ev := List(Eigenvalues(GF(p), matq), x->LogFFE(LogFFE(x, b^((p - 1)/q))*One(GF(q)), c) mod (q - 1));
          if Length(ev) = 1 then
            x := LogFFE(LogFFE(ExponentsOfPcElement(G, gens[2]^gens[1])[2]*One(GF(r)), a^((r - 1)/q))*One(GF(q)), c) mod (q - 1);
            y := ev[1];
            z := ev[1];
          else
            x := LogFFE(LogFFE(ExponentsOfPcElement(G, gens[2]^gens[1])[2]*One(GF(r)), a^((r - 1)/q))*One(GF(q)), c) mod (q - 1);
            y := ev[1];
            z := ev[2];
          fi;
          if AsSet([[(x - y) mod (q - 1), (z - y) mod (q - 1)], [(x - z) mod (q - 1), (y - z) mod (q - 1)]]) in tmp then
            m := Position(tmp, AsSet([[(x - y) mod (q - 1), (z - y) mod (q - 1)], [(x - z) mod (q - 1), (y - z) mod (q - 1)]]));
          elif AsSet([[(x - y) mod (q - 1), (z - y) mod (q - 1)], [(y - x) mod (q - 1), (y - z) mod (q - 1)]]) in tmp then
            m := Position(tmp, AsSet([[(x - y) mod (q - 1), (z - y) mod (q - 1)], [(y - x) mod (q - 1), (y - z) mod (q - 1)]]));
          else
            m := Position(tmp, AsSet([[(x - z) mod (q - 1), (y - z) mod (q - 1)], [(z - x) mod (q - 1), (z - y) mod (q - 1)]]));
          fi;
          return [n, 3 + (m - 1) + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q + 1)/2*SOTRec.w((p - 1), q)*(1 - SOTRec.delta(q, 2))
          + 2*SOTRec.delta(q, 2)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))
          + SOTRec.w((r - 1), q)];
        elif flag[3] = p and flag[2] = 1 and q = 2 then ## G \cong C_2 \ltimes (C_r \times C_p^2)
          return [n, 4 + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q + 1)/2*SOTRec.w((p - 1), q)*(1 - SOTRec.delta(q, 2))
          + 2*SOTRec.delta(q, 2)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))];
        elif flag[3] = p and flag[2] = 1 and (p + 1) mod q = 0 and q > 2 then ## q | (r - 1), q | (p + 1), and G \cong C_q \ltimes (C_r \times C_p^2)
          gens := [pcgsq[1], pcgsr[1], pcgsp[1], pcgsp[2]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          x := Inverse(LogFFE(ExponentsOfPcElement(G, gens[2]^gens[1])[2]*One(GF(r)), a^((r - 1)/q))) mod q;
          expp1q := ExponentsOfPcElement(G, gens[3]^gens[1]);
          expp2q := ExponentsOfPcElement(G, gens[4]^gens[1]);
          mat_k := [expp1q{[3, 4]}, expp2q{[3, 4]}]^x * One(GF(p^2));
          ev := List(Eigenvalues(GF(p^2), mat_k), x -> LogFFE(x, PrimitiveElement(GF(p^2))^((p^2 - 1)/q)) mod q);
          tmp := [];
          for k in [1..(q - 1)] do
            Add(tmp, AsSet([k, k*p mod q]));
          od;
          if Position(tmp, AsSet(ev)) < (q + 1)/2 then
            m := Position(tmp, AsSet(ev));
          else
            m := (q - 1) - Position(tmp, AsSet(ev));
          fi;
          return [n, 3 + (m - 1) + c1 + c2 + c3 + c4
          + SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p - 1), q)
          + (q + 1)/2*SOTRec.w((p - 1), q)*(1 - SOTRec.delta(q, 2))
          + 2*SOTRec.delta(q, 2)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))
          + (q - 1)*SOTRec.w((p - 1), q)*SOTRec.w((r - 1), q)
          + SOTRec.w((p + 1), q)*(1 - SOTRec.delta(q, 2))];
        fi;
      ############ case 6: nonabelian and Fitting subgroup has order pr -- q | (p - 1)(r - 1) and p | (r - 1)
      elif flag[1] = p*r then
        if flag[3] = p and flag[2] = p then ## q | (r - 1), p | (r - 1), and G \cong (C_{p^2} \times C_q) \ltimes C_r
          return [n, 3 + c1 + c2 + c3 + c4 + c5];
        elif flag[3] = p^2 and flag[2] = p then ## q | (r - 1), p | (r - 1), and G \cong ((C_p \times C_q) \ltimes C_r) \times C_p
          return [n, 3 + c1 + c2 + c3 + c4 + c5
          + SOTRec.w((r - 1), p*q)];
        elif flag[2] = 1 then
          gens := [Filtered(pcgsp, x -> not x in FittingSubgroup(group))[1], pcgsq[1], Filtered(pcgsp, x-> x in FittingSubgroup(group))[1], pcgsr[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          if IsOne(Comm(gens[2], gens[4])) then ## q | (p - 1), p | (r - 1), and G \cong (C_p \ltimes C_r) \times (C_q \ltimes C_p)
            return [n, 3 + c1 + c2 + c3 + c4 + c5
            + 2*SOTRec.w((r - 1), p*q)];
          else ## q | (p - 1), p | (r - 1), q | (r - 1), and G \cong (C_p \times C_q) \ltimes (C_r \times C_p)
            x := Inverse(LogFFE(ExponentsOfPcElement(G, gens[4]^gens[2])[4]*One(GF(r)), a^((r - 1)/q))) mod q;
            pcgs := [gens[1], gens[2]^x, gens[3], gens[4]];
            pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
            k := LogFFE(ExponentsOfPcElement(pc, pcgs[3]^pcgs[2])[3]*One(GF(p)), b^((p - 1)/q)) mod q;
            return [n, 3 + (k - 1) + c1 + c2 + c3 + c4 + c5
            + 2*SOTRec.w((r - 1), p*q)
            + SOTRec.w((p - 1), q)*SOTRec.w((r - 1), p)];
          fi;
        fi;
      ############ case 7: nonabelian and Fitting subgroup has order pqr -- p | (r - 1)(q - 1)
      elif flag[1] = p*q*r then
        if flag[3] = p^2 and flag[2] = p*q then ## P \cong C_{p^2}, p | (r - 1) and G \cong (C_{p^2} \ltimes C_r) \times C_q
          return [n, 3 + c1 + c2 + c3 + c4 + c5 + c6];
        elif flag[3] = p^2 and flag[2] = p*r then ## P \cong C_{p^2}, p | (q - 1) and G \cong (C_{p^2} \ltimes C_q) \times C_r
          return [n, 3 + c1 + c2 + c3 + c4 + c5 + c6
          + SOTRec.w((r - 1), p)];
        elif flag[3] = p^2 and flag[2] = p then ## P \cong C_{p^2} and G \cong C_{p^2} \ltimes (C_q \times C_r)
          gens := [pcgsp[1], pcgsp[2], pcgsq[1], pcgsr[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          x := Inverse(LogFFE(ExponentsOfPcElement(G, gens[3]^gens[1])[3]*One(GF(q)), c^((q - 1)/p))) mod p;
          k := LogFFE(ExponentsOfPcElement(G, gens[4]^gens[1])[4]^x*One(GF(r)), a^((r - 1)/p)) mod p;
          return [n, 3 + (k - 1) + c1 + c2 + c3 + c4 + c5 + c6
          + SOTRec.w((r - 1), p)
          + SOTRec.w((q - 1), p)];
        elif flag[3] = p and flag[2] = p*q then ## P \cong C_p^2, p | (r - 1) and G \cong C_p \times (C_p \ltimes C_r) \times C_q
          return [n, 3 + c1 + c2 + c3 + c4 + c5 + c6
          + SOTRec.w((r - 1), p)
          + SOTRec.w((q - 1), p)
          + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((q - 1), p)];
        elif flag[3] = p and flag[2] = p*r then ## P \cong C_p^2, p | (q - 1) and G \cong C_p \times (C_p \ltimes C_q) \times C_r
          return [n, 3 + c1 + c2 + c3 + c4 + c5 + c6
          + SOTRec.w((r - 1), p)
          + SOTRec.w((q - 1), p)
          + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((q - 1), p)
          + SOTRec.w((r - 1), p)];
        elif flag[3] = p and flag[2] = p then ## P \cong C_p^2 and G \cong C_{p^2} \ltimes (C_q \times C_r)
          b := Pcgs(Zen)[1];
          gens := [Filtered(pcgsp, x->not x in Zen)[1], b, pcgsq[1], pcgsr[1]];
          G := PcgsByPcSequence(FamilyObj(gens[1]), gens);
          x := Inverse(LogFFE(ExponentsOfPcElement(G, gens[3]^gens[1])[3]*One(GF(q)), c^((q - 1)/p))) mod p;
          k := LogFFE(ExponentsOfPcElement(G, gens[4]^gens[1])[4]^x*One(GF(r)), a^((r - 1)/p)) mod p;
          return [n, 3 + (k - 1) + c1 + c2 + c3 + c4 + c5 + c6
          + 2*SOTRec.w((r - 1), p)
          + 2*SOTRec.w((q - 1), p)
          + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((q - 1), p)];
        fi;
      fi;
    else
      return [60, 13];
    fi;
end;
##########################################
SOTRec.IdGroupPQRS := function(group, n, fac)
local p, q, r, s, P, Q, R, S, H, u, v, w, k, l, flag, lst, sizefit,
    G, pcgs, pc, fgens, i, a, b, c, d, x, y, Id,
    c1, c2, c3, c4, c5, c6, exprp, exprq, expsp, expsq, expsr, expqp,
    pcgsp, pcgsq, pcgsr, pcgss;

    p := fac[1][1];
    q := fac[2][1];
    r := fac[3][1];
    s := fac[4][1];

    ####
    Assert(1, p < q and q < r and r < s);
    Assert(1, IsPrimeInt(p));
    Assert(1, IsPrimeInt(q));
    Assert(1, IsPrimeInt(r));
    Assert(1, IsPrimeInt(s));

    P := SylowSubgroup(group, p);
    Q := SylowSubgroup(group, q);
    R := SylowSubgroup(group, r);
    S := SylowSubgroup(group, s);
    pcgsp := Pcgs(P);
    pcgsq := Pcgs(Q);
    pcgsr := Pcgs(R);
    pcgss := Pcgs(S);

    u := Z(q);
    v := Z(r);
    w := Z(s);

    c1 := SOTRec.w((s - 1), r) + SOTRec.w((s - 1), q) + SOTRec.w((r - 1), q)
        + SOTRec.w((s - 1), p) + SOTRec.w((r - 1), p) + SOTRec.w((q - 1), p);
    c2 := (q - 1)*SOTRec.w((r - 1), q)*SOTRec.w((s - 1), q) + SOTRec.w((s - 1), (q*r))
        + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((s - 1), p) + SOTRec.w((s - 1), (p*r))
        + (p - 1)*SOTRec.w((q - 1), p)*SOTRec.w((s - 1), p) + SOTRec.w((s - 1), (p*q))
        + (p - 1)*SOTRec.w((q - 1), p)*SOTRec.w((r - 1), p) + SOTRec.w((r - 1), (p*q));
    c3 := (p - 1)^2*SOTRec.w((q - 1), p)*SOTRec.w((r - 1), p)*SOTRec.w((s - 1), p)
        + (p - 1)*(q - 1)*SOTRec.w((s - 1), (p*q))*SOTRec.w((r - 1), (p*q))
        + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((s - 1), (p*q))
        + (q - 1)*SOTRec.w((r - 1), q)*SOTRec.w((s - 1), (p*q))
        + (p - 1)*SOTRec.w((s - 1), p)*SOTRec.w((r - 1), (p*q))
        + (q - 1)*SOTRec.w((s - 1), q)*SOTRec.w((r - 1), (p*q))
        + SOTRec.w((r - 1), p)*SOTRec.w((s - 1), q)
        + SOTRec.w((r - 1), q)*SOTRec.w((s - 1), p)
        + SOTRec.w((s - 1), r)*SOTRec.w((q - 1), p)
        + (p - 1)*SOTRec.w((q - 1), p)*SOTRec.w((s - 1), (p*r))
        + SOTRec.w((s - 1), (p*q*r));

    flag := [Size(Centre(group))];

    if flag[1] = n then
      return [n, 1];
    else
      pcgs := [pcgsp[1], pcgsq[1], pcgsr[1], pcgss[1]];
      pc := PcgsByPcSequence(FamilyObj(pcgs[1]), pcgs);
      exprp := ExponentsOfPcElement(pc, pcgs[3]^pcgs[1]);
      exprq := ExponentsOfPcElement(pc, pcgs[3]^pcgs[2]);
      expsp := ExponentsOfPcElement(pc, pcgs[4]^pcgs[1]);
      expsq := ExponentsOfPcElement(pc, pcgs[4]^pcgs[2]);
      expsr := ExponentsOfPcElement(pc, pcgs[4]^pcgs[3]);
      expqp := ExponentsOfPcElement(pc, pcgs[2]^pcgs[1]);
    fi;

    if flag[1] = p * q then
      return [n, 2];
    elif flag[1] = p * r then
      return [n, 2 + SOTRec.w((s - 1), r)];
    elif flag[1] = p * s then
      return [n, 2 + SOTRec.w((s - 1), r) + SOTRec.w((s - 1), q)];
    elif flag[1] = q * r then
      return [n, 2 + SOTRec.w((s - 1), r) + SOTRec.w((s - 1), q) + SOTRec.w((r - 1), q)];
    elif flag[1] = q * s then
      return [n, 2 + SOTRec.w((s - 1), r) + SOTRec.w((s - 1), q)
      + SOTRec.w((r - 1), q) + SOTRec.w((s - 1), p)];
    elif flag[1] = r * s then
      return [n, 2 + SOTRec.w((s - 1), r) + SOTRec.w((s - 1), q)
      + SOTRec.w((s - 1), p) + SOTRec.w((r - 1), q) + SOTRec.w((r - 1), p)];
    elif flag[1] = p then
      if expsq[4] <> 1 and exprq[3] <> 1 and expsr[4] = 1 then
        x := Inverse(LogFFE(exprq[3]*One(GF(r)), v^((r - 1)/q))) mod q;
        k := LogFFE(expsq[4]^x*One(GF(s)), w^((s - 1)/q)) mod q;
        return [n, 2 + c1 + k - 1];
      elif expsq[4] <> 1 and expsr[4] <> 1 and exprq[3] = 1 then
        return [n, 2 + c1 + (q - 1)*SOTRec.w((r - 1), q)*SOTRec.w((s - 1), q)];
      fi;
    elif flag[1] = q then
      if exprp[3] <> 1 and expsp[4] <> 1 and expsr[4] = 1 then
        x := Inverse(LogFFE(exprp[3]*One(GF(r)), v^((r - 1)/p))) mod p;
        k := LogFFE(expsp[4]^x*One(GF(s)), w^((s - 1)/p)) mod p;
        return [n, 2 + c1 + (q - 1)*SOTRec.w((r - 1), q)*SOTRec.w((s - 1), q)
        + SOTRec.w((s - 1), (q*r)) + k - 1];
      elif expsp[4] <> 1 and expsr[4] <> 1 and exprp[3] = 1 then
        return [n, 2 + c1 + (q - 1)*SOTRec.w((r - 1), q)*SOTRec.w((s - 1), q)
        + SOTRec.w((s - 1), (q*r))
        + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((s - 1), p)];
      fi;
    elif flag[1] = r then
      if expqp[2] <> 1 and expsp[4] <> 1 and expsq[4] = 1 then
        x := Inverse(LogFFE(expqp[2]*One(GF(q)), u^((q - 1)/p))) mod p;
        k := LogFFE(expsp[4]^x*One(GF(s)), w^((s - 1)/p)) mod p;
        return [n, 2 + c1 + (q - 1)*SOTRec.w((r - 1), q)*SOTRec.w((s - 1), q)
        + SOTRec.w((s - 1), (q*r))
        + (p - 1)*SOTRec.w((r - 1), p)*SOTRec.w((s - 1), p)
        + SOTRec.w((s - 1), (p*r)) + k - 1];
      elif expsp[4] <> 1 and expsq[4] <> 1 and expqp[2] = 1 then
--> --------------------

--> maximum size reached

--> --------------------

[ zur Elbe Produktseite wechseln0.77Quellennavigators  Analyse erneut starten  ]