|
#############################################################################
##
## projector.gi CRISP Burkhard Höfling
##
## Copyright © 2000-2003, 2005, 2011 Burkhard Höfling
##
#############################################################################
##
#M CoveringSubgroupOp(<grp>, <class>)
##
InstallMethod(CoveringSubgroupOp, "for Schunck classes: return projector",
true,
[IsGroup, IsSchunckClass], 0,
function(G, C)
return Projector(G, C);
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "if ProjectorFunction is known", true,
[IsGroup, IsSchunckClass and HasProjectorFunction],
SUM_FLAGS, # highly preferable
function(G, C)
return ProjectorFunction(C)(G);
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "compute from LocalDefinitionFunction", true,
[IsGroup and IsFinite and CanEasilyComputePcgs,
IsSaturatedFormation and HasLocalDefinitionFunction],
RankFilter(HasBoundaryFunction), # prefer to method using boundary func
function(G, C)
return ProjectorFromExtendedBoundaryFunction(
G,
rec(
char := Characteristic(C),
class := C,
dfunc := DFUNC_FROM_CHARACTERISTIC,
cfunc := CFUNC_FROM_CHARACTERISTIC,
kfunc := KFUNC_FROM_LOCAL_DEFINITION,
lfunc := function(G, p, data)
return LocalDefinitionFunction(data.class)(G, p);
end),
false); # we want a projector, not a membership test
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "compute from boundary", true,
[IsGroup and IsFinite and CanEasilyComputePcgs,
IsSchunckClass and HasBoundaryFunction],
RankFilter(HasMemberFunction),
function(G, C)
return ProjectorFromExtendedBoundaryFunction(
G,
rec(
cfunc := CFUNC_FROM_CHARACTERISTIC_SCHUNCK,
char := Characteristic(C),
class := C,
bfunc := BFUNC_FROM_TEST_FUNC,
test := function(G, data)
return BoundaryFunction(data.class)(G);
end),
false); # we want a projector, not a membership test
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "use MemberFunction", true,
[IsGroup and IsFinite and CanEasilyComputePcgs,
IsSchunckClass and HasMemberFunction],
0,
function(G, C)
return ProjectorFromExtendedBoundaryFunction(
G,
rec(
dfunc := DFUNC_FROM_MEMBER_FUNCTION,
memberf := MemberFunction(C)),
false); # we want a projector, not a membership test
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "use only membership test", true,
[IsGroup and IsFinite and CanEasilyComputePcgs,
IsSchunckClass],
0,
function(G, C)
return ProjectorFromExtendedBoundaryFunction(
G,
rec(
class := C,
char := Characteristic(C),
cfunc := CFUNC_FROM_CHARACTERISTIC_SCHUNCK,
bfunc := BFUNC_FROM_TEST_FUNC,
test := function(G, data)
return not G in data.class;
end),
false); # we want a projector, not a membership test
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp, "for intersection of group classes", true,
[IsGroup and IsFinite and CanEasilyComputePcgs,
IsSchunckClass and IsClassByIntersectionRep],
0,
function(G, C)
local D, data;
data := rec(locform := [],
schunck := [],
others := [],
char := Characteristic(C),
cfunc := CFUNC_FROM_CHARACTERISTIC_SCHUNCK);
for D in C!.intersected do
if HasIsSchunckClass(D) and IsSchunckClass(D) then
if HasLocalDefinitionFunction(D) then
Add(data.locform, D);
elif HasBoundaryFunction(D) then
Add(data.schunck, D);
else
Add(data.others, D);
fi;
else
Add(data.others, D);
fi;
od;
if not IsEmpty(data.locform) then
data.kfunc := KFUNC_FROM_LOCAL_DEFINITION;
data.lfunc := function(G, p, data)
local gens, new;
gens := [];
# compute generators of residual of intersection
#(this is the join of the generators of the
# residuals of the individual classes
for D in data.locform do
new := LocalDefinitionFunction(D)(G, p);
if new = fail then
return fail; # empty local definition
fi;
if IsGroup(new) then
new := GeneratorsOfGroup(new);
fi;
new := Union(gens, new);
od;
return gens;
end;
fi;
if not IsEmpty(data.others) or not IsEmpty(data.schunck) then
data.bfunc := BFUNC_FROM_TEST_FUNC;
data.test := function(G, dat)
return ForAny(data.schunck, H -> BoundaryFunction(H)(G))
or ForAny(data.others, H -> not G in H);
end;
fi;
return ProjectorFromExtendedBoundaryFunction(
G, data, false); # we want a projector, not a membership test
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethod(ProjectorOp,
"for intersection of group classes which is a local formation", true,
[IsGroup and IsFinite and CanEasilyComputePcgs,
IsSaturatedFormation and IsClassByIntersectionRep],
0,
function(G, C)
local D, data;
data := rec(locform := [],
schunck := [],
others := [],
char := Characteristic(C),
dfunc := DFUNC_FROM_CHARACTERISTIC,
cfunc := CFUNC_FROM_CHARACTERISTIC);
for D in C!.intersected do
if HasIsSchunckClass(D) and IsSchunckClass(D) then
if HasLocalDefinitionFunction(D) then
Add(data.locform, D);
elif HasBoundaryFunction(D) then
Add(data.schunck, D);
else
Add(data.others, D);
fi;
else
Add(data.others, D);
fi;
od;
if not IsEmpty(data.locform) then
data.kfunc := KFUNC_FROM_LOCAL_DEFINITION;
data.lfunc := function(G, p, data)
local gens, new;
gens := [];
# compute generators of residual of intersection
#(this is the join of the generators of the
# residuals of the individual classes
for D in data.locform do
new := LocalDefinitionFunction(D)(G, p);
if new = fail then
return fail; # empty local definition
fi;
if IsGroup(new) then
new := GeneratorsOfGroup(new);
fi;
gens := Union(gens, new);
od;
return gens;
end;
fi;
if not IsEmpty(data.others) or not IsEmpty(data.schunck) then
data.bfunc := BFUNC_FROM_TEST_FUNC;
data.test := function(G, dat)
return ForAny(data.schunck, H -> BoundaryFunction(H)(G))
or ForAny(data.others, H -> not G in H);
end;
fi;
return ProjectorFromExtendedBoundaryFunction(
G, data, false); # we want a projector, not a membership test
end);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethodByNiceMonomorphismForGroupAndClass(ProjectorOp,
IsFinite and IsSolvableGroup, IsSchunckClass);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
InstallMethodByIsomorphismPcGroupForGroupAndClass(ProjectorOp,
IsFinite and IsSolvableGroup, IsSchunckClass);
#############################################################################
##
#M ProjectorOp(<grp>, <class>)
##
CRISP_RedispatchOnCondition(ProjectorOp,
"redispatch if group is finite or soluble",
true,
[IsGroup, IsGroupClass], [IsFinite and IsSolvableGroup],
RankFilter(IsGroup) + RankFilter(IsGroupClass));
###################################################################################
##
#F BFUNC_FROM_TEST_FUNC_FAC(<upcgs>, <cpcgs>, <kpcgs>, <npcgs>, <p>,
## <centind>, <data>)
##
InstallGlobalFunction(BFUNC_FROM_TEST_FUNC_FAC,
function(upcgs, cpcgs, kpcgs, npcgs, p, centind, data)
local H, N, cent, x, nat, F, hom;
H := GroupOfPcgs(upcgs);
hom := NaturalHomomorphismByNormalSubgroupNC(H,
GroupOfPcgs(DenominatorOfModuloPcgs(npcgs)));
# compute centralizer of npcgs in the group generated by cpcgs
# in factor group
N := ImagesSet(hom, GroupOfPcgs(NumeratorOfModuloPcgs(npcgs)));
cent := Centralizer(ImagesSet(hom, GroupOfPcgs(cpcgs)), N);
# now compute primitive image
nat := NaturalHomomorphismByNormalSubgroupNC(ImagesSource(hom), cent);
F := ImagesSource(nat);
SetIsPrimitiveSolubleGroup(F, true);
SetSocle(F, ImagesSet(nat, N));
SetSocleComplement(F,
ImagesSet(nat, ImagesSet(hom, GroupOfPcgs(cpcgs))));
return data.test(F, data);
end);
###################################################################################
##
#F BFUNC_FROM_TEST_FUNC_MOD(<upcgs>, <cpcgs>, <kpcgs>, <npcgs>, <p>,
## <centind>, <data>)
##
InstallGlobalFunction(BFUNC_FROM_TEST_FUNC_MOD,
function(upcgs, cpcgs, kpcgs, npcgs, p, centind, data)
local H, cent, x, nat, F;
H := GroupOfPcgs(upcgs);
cent := GroupOfPcgs(cpcgs);
for x in npcgs do
cent := CentralizerModulo(cent,
GroupOfPcgs(DenominatorOfModuloPcgs(npcgs)),
x);
od;
# compute H/C_<cpcgs>(npcgs), which will be the primitive factor group
# which either lies in the Schunck class or its boundary
nat := NaturalHomomorphismByNormalSubgroupNC(H, cent);
F := ImagesSource(nat);
SetIsPrimitiveSolubleGroup(F, true);
SetSocle(F, ImagesSet(nat, GroupOfPcgs(npcgs)));
SetSocleComplement(F, ImagesSet(nat, GroupOfPcgs(cpcgs)));
return data.test(F, data);
end);
###################################################################################
##
#F KFUNC_FROM_LOCAL_DEFINITION(<upcgs>, <kpcgs>, <npcgs>, <p>, <centind>, <data>)
##
InstallGlobalFunction(KFUNC_FROM_LOCAL_DEFINITION,
function(upcgs, kpcgs, npcgs, p, cent, data)
local ldef;
ldef := data.lfunc(GroupOfPcgs(upcgs), p, data);
if ldef = fail then
return true; # empty local def - in boundary
elif IsGroup(ldef) then
ldef := GeneratorsOfGroup(ldef);
fi;
return not CentralizesLayer(ldef, npcgs);
end);
###################################################################################
##
#F DFUNC_FROM_CHARACTERISTIC(<upcgs>, <npcgs>, <p>, <data>)
##
## this only works if groups in C only have prime divisors in the characteristic
##
InstallGlobalFunction(DFUNC_FROM_CHARACTERISTIC,
function(upcgs, npcgs, p, data)
if p in data.char then
return fail;
else
return true;
fi;
end);
###################################################################################
##
#F DFUNC_FROM_MEMBER_FUNCTION(<upcgs>, <npcgs>, <p>, <data>)
##
## use a membership function to test if the factor group is in the class
##
InstallGlobalFunction(DFUNC_FROM_MEMBER_FUNCTION,
function(upcgs, npcgs, p, data)
return not data.memberf(
GroupOfPcgs(upcgs)/GroupOfPcgs(DenominatorOfModuloPcgs(npcgs)));
end);
###################################################################################
##
#F CFUNC_FROM_CHARACTERISTIC(<upcgs>, <npcgs>, <p>, <centind>, <data>)
##
InstallGlobalFunction(CFUNC_FROM_CHARACTERISTIC,
function(upcgs, npcgs, p, centind, data)
if centind = 1 then # p in Characteristic has been tested by DFUNC...
return false; # the primitive group is cyclic of order p
else
return fail;
fi;
end);
###################################################################################
##
#F CFUNC_FROM_CHARACTERISTIC_SCHUNCK(<upcgs>, <npcgs>, <p>, <centind>, <data>)
##
InstallGlobalFunction(CFUNC_FROM_CHARACTERISTIC_SCHUNCK,
function(upcgs, npcgs, p, centind, data)
if centind = 1 and p in data.char then
return false; # the primitive group is cyclic of order p
else
return fail;
fi;
end);
###################################################################################
##
#M ProjectorFromExtendedBoundaryFunction(<grp>, <rec>, <inonly>)
##
InstallMethod(ProjectorFromExtendedBoundaryFunction, "for pc group",
[IsPcGroup and IsFinite, IsRecord, IsBool], 0,
function(grp, r, inonly)
local pcgs, re;
if not IsBound(r.dfunc) then
r.dfunc := ReturnFail;
fi;
if not IsBound(r.cfunc) then
r.cfunc := ReturnFail;
fi;
if not IsBound(r.kfunc) then
r.kfunc := ReturnFail;
fi;
if not IsBound(r.bfunc) then
r.bfunc := ReturnFail;
fi;
pcgs := PcgsElementaryAbelianSeries(grp);
re := PROJECTOR_FROM_BOUNDARY(
pcgs, r, inonly, true, true);
if inonly then
return re;
else
return GroupOfPcgs(re);
fi;
end);
###################################################################################
##
#M ProjectorFromExtendedBoundaryFunction(<grp>, <rec>, <inonly>)
##
InstallMethod(ProjectorFromExtendedBoundaryFunction, "for soluble groups",
[IsGroup and IsFinite and IsSolvableGroup, IsRecord, IsBool], 0,
function(grp, r, inonly)
local pcgs, re;
if not IsBound(r.dfunc) then
r.dfunc := ReturnFail;
fi;
if not IsBound(r.cfunc) then
r.cfunc := ReturnFail;
fi;
if not IsBound(r.kfunc) then
r.kfunc := ReturnFail;
fi;
if not IsBound(r.bfunc) then
r.bfunc := ReturnFail;
fi;
pcgs := PcgsElementaryAbelianSeries(grp);
re := PROJECTOR_FROM_BOUNDARY(
pcgs, r, inonly, false, false);
if inonly then
return re;
else
return GroupOfPcgs(re);
fi;
end);
###################################################################################
##
#M ProjectorFromExtendedBoundaryFunction(<grp>, <rec>, <inonly>)
##
CRISP_RedispatchOnCondition(ProjectorFromExtendedBoundaryFunction,
"redispatch if group is finite or soluble",
true,
[IsGroup, IsRecord, IsBool],
[IsGroup and IsSolvableGroup],
RankFilter(IsGroup) + RankFilter(IsRecord) + RankFilter(IsBool));
###################################################################################
##
#F PROJECTOR_FROM_BOUNDARY(<gpcgs>, <data>, <inonly>, <hom>, <conv>)
##
InstallGlobalFunction("PROJECTOR_FROM_BOUNDARY",
function(pcgs, data, inonly, hom, conv)
local
ppcgs, # pcgs wrt to which all computations are carried out
grp, # group in which all computations are carried out
opcgs, # image of ppcgs
elabpcgs, # elementary abelian series derived from pcgs
fac, # images mod el. ab. series
inds, # indices of pcgs exhibiting an elementary abelian series
upcgs, # pcgs of a projector
userinds, # indices of an el. ab. series of upcgs,
# as obtained by intersecting with elabpcgs
diff, # difference between composition length of projector
# of upcgs mod elabpcgs[i+1] and upcgs mod elabpcgs[i]
userp, # prime exponents of el ab series of upcgs
i, j, # loop variables
mpcgs, # modulo pcgs representing a factor of the series in elabpcgs
ser, # upcgs-composition series of mpcgs
npcgs, # modulo pcgs representing a composition factor of ser
centind, # all elements of upcgs {[centind..Length(upcgs)]} centralise npcgs
centpcgs, # upcgs {[centind..Length(upcgs)]}
p, # exponent of mpcgs and npcgs
cpcgs, # pcgs of a complement of npcgs in upcgs
kpcgs, # pcgs of a normal complement of npcgs in a suitable normal subgroup
# of upcgs
id, # a suitable identity matrix
bool; # result returned by the boundary function, or false if no complement
if Length(pcgs) = 0 then
if inonly then
return true;
else
return pcgs;
fi;
fi;
if not IsPcgsElementaryAbelianSeries(pcgs) then
Error("pcgs must refine an elementary abelian series");
fi;
inds := IndicesEANormalSteps(pcgs);
if conv or hom then
grp := PcGroupWithPcgs(pcgs);
else
grp := GroupOfPcgs(pcgs);
fi;
if hom then
# compute factor groups modulo subgroups in el. ab. series of pcgs
fac := [];
fac[Length(inds)] := grp;
for j in [Length(inds)-1, Length(inds)-2..2] do
ppcgs := FamilyPcgs(fac[j+1]);
fac[j] := PcGroupWithPcgs(
ppcgs mod InducedPcgsByPcSequenceNC(ppcgs, ppcgs{[inds[j]..Length(ppcgs)]}));
od;
else
if conv then
ppcgs := FamilyPcgs(grp);
else
ppcgs := pcgs;
fi;
elabpcgs := List(inds,
i -> InducedPcgsByPcSequenceNC(pcgs, pcgs{[i, i+1..Length(pcgs)]}));
upcgs := pcgs; # set up the projector
ppcgs := pcgs;
fi;
userinds := [1];
userp := [];
# treat the layers of the elementary abelian series obtained from pcgs
for j in [1,2..Length(inds) - 1] do
Info(InfoProjector, 1, "starting step ",j, " of ",Length(inds) - 1);
if hom then
# translate results from factor group
grp := fac[j+1];
ppcgs := FamilyPcgs(grp);
mpcgs := InducedPcgsByPcSequenceNC(ppcgs, ppcgs{[inds[j]..Length(ppcgs)]});
if j = 1 then
upcgs := ppcgs; # projector is whole group
else
opcgs := FamilyPcgs(fac[j]);
upcgs := InducedPcgsByPcSequenceNC(ppcgs,
Concatenation( List(upcgs, x ->
PcElementByExponentsNC(ppcgs, [1..inds[j]-1], ExponentsOfPcElement(opcgs, x))),
mpcgs));
fi;
else
mpcgs := elabpcgs[j] mod elabpcgs[j+1];
fi;
# we assume that upcgs mod elabpcgs[j] represents a projector
# of pcgs mod elabpcgs[j]
p := RelativeOrderOfPcElement(ppcgs, mpcgs[1]); # exp. of mpcgs
ser := PcgsCompositionSeriesElAbModuloPcgsUnderAction(
upcgs{[1,2..userinds[Length(userinds)]-1]}, mpcgs);
Info(InfoProjector, 2, Length(ser)-1, " composition factors");
diff := 0; # assume that the composition length remains the same
# now find a projector of upcgs mod elabpcgs[j+1] - this
# will be a projector of pcgs mod elabpcgs[j+1] as well
for i in [1..Length(ser) - 1] do
# We want to replace upcgs mod ser[i+1] by one of its
# projectors. There are two possibilities
# between which dfunc, cfunc, kfunc, bfunc try to decide:
# if upcgs mod ser[i+1] is in the Schunck class,
# it is itself a projector. In this case, we have bool=false
# eventually. Otherwise the projectors are the maximal subgroups
# complementing ser[i] mod ser[i+1](bool = true).
# If we want to decide membership
# only, we can return false as soon as we know that
# the projector is a proper subgroup, i.e., as soon as bool
# becomes true.
npcgs := ser[i] mod ser[i+1];
# try if we can decide with only minimal information
# for instance by testing if p is in the characteristic of a
# saturated formation
bool := data.dfunc(upcgs, npcgs, p, data);
Info(InfoProjector, 3, "dfunc returns ", bool);
if inonly and bool = true then
return false; # factor group in boundary
fi;
if bool <> false then
# if dfunc returns false, we know that upcgs mod ser[i+1] is the projector
# Otherwise we look for a complement of npcgs = ser[i] mod ser[i+1]
Info(InfoProjector, 2, "complementing factor of size ",p,"^",Length(npcgs));
centind := Length(userinds);
# find the largest term centpcgs in the el. ab. series
# of upcgs centralising npcgs
while centind > 1 and
(p = userp[centind-1] or
CentralizesLayer(upcgs{[userinds[centind-1]..userinds[centind]-1]}, npcgs)) do
centind := centind - 1;
od;
Info(InfoProjector, 3, "centralizing level: ",userinds[centind]);
centpcgs := InducedPcgsByPcSequenceNC(ppcgs,
upcgs{[userinds[centind]..Length(upcgs)]});
# if we haven't reached a decision yet, try with additional information
# for instance if npcgs is central, we can use the characteristic of the
# Schunck class
if bool = fail then
bool := data.cfunc(upcgs, npcgs, p, userinds[centind], data);
Info(InfoProjector, 3, "cfunc returns ", bool);
if inonly and bool = true then
return false;
fi;
fi;
if bool <> false then
# now find upcgs-invariant complement of npcgs in centpcgs
# note that any complement of npcgs in upcgs intersects
# centpcgs in such a complement, and any upcgs-invariant
# complement arises in that way(see crisp.dvi)
if centind = Length(userinds) and i = 1 and diff = 0 then
# centind = Length(userinds) means that ser[1] = centpcgs, so that
# the complement is trivial
kpcgs := ser[i+1];
Info(InfoProjector, 3, "trivial normal complement");
else
kpcgs := PcgsComplementsOfCentralModuloPcgsUnderActionNC(
List(upcgs{[1,2..userinds[centind]-1]},
x -> InnerAutomorphismNC(grp, x)),
ppcgs, centpcgs mod ser[i], npcgs, ser[i+1], false);
if Length(kpcgs) = 0 then # no complement exists
kpcgs := fail;
bool := false;
Assert(1, p in userp,
"coprime situation but no complement");
Info(InfoProjector, 3, "no normal complement found");
else
Info(InfoProjector, 3, Length(kpcgs)," normal complement(s) found");
kpcgs := kpcgs[1]; # we only want one normal complement
Assert(1, IsSubgroup(GroupOfPcgs(kpcgs), GroupOfPcgs(ser[i+1])),
" complement is not a subgroup");
Assert(1, GroupOfPcgs(SumPcgs(ppcgs, kpcgs, ser[i]))
= GroupOfPcgs(InducedPcgsByPcSequenceNC(ppcgs,
upcgs{[userinds[centind]..Length(upcgs)]})),
"wrong join for normal complement");
Assert(1, GroupOfPcgs(NormalIntersectionPcgs(ppcgs, kpcgs, ser[i]))
= GroupOfPcgs(ser[i+1]),
"wrong intersection for normal complement");
fi;
fi;
if bool = fail then
# we have more information(kpcgs) at hand, so
# try to decide again
bool := data.kfunc(upcgs, kpcgs, npcgs, p,
userinds[centind], data);
Info(InfoProjector, 3, "kfunc returns ", bool);
if inonly and bool = true then
return false; # not in Schunck class
fi;
fi;
fi;
if bool <> false then
# at this point, we either know whether upcgs mod ser[i+1]
# is in the Schunck class(bool = false/true), or we have
# an upcgs-invariant subgroup of centpcgs complementing
# npcgs
# now find a complement of npcgs in upcgs
if centind = 1 then
# npcgs is central, so kpcgs is a complement
cpcgs := kpcgs;
Info(InfoProjector, 3, "central socle");
else
Assert(1, userp[centind-1] <> p, Error("wrong prime ", p));
Info(InfoProjector, 3, "noncentral socle - computing complement");
# compute a complement of npcgs from the normal complement
# obtained before
cpcgs := PcgsComplementOfChiefFactor(ppcgs,
upcgs{[1..userinds[centind]-1]},
userinds[centind-1], centpcgs mod kpcgs, kpcgs);
Assert(1, Length(npcgs) + Length(cpcgs) = Length(upcgs),
Error("cpcgs does not complement"));
fi;
if bool = fail then
# now we have all information at hand - do the final test
Info(InfoProjector, 3, "testing group of size ",
Product(RelativeOrders(upcgs)) /
Product(RelativeOrders(ser[i+1])),
" size of socle: ",
Product(RelativeOrders(npcgs)),
" size of complement: ",
Product(RelativeOrders(cpcgs)) /
Product(RelativeOrders(ser[i+1])));
bool := data.bfunc(upcgs, cpcgs, kpcgs, npcgs, p,
userinds[centind], data);
Info(InfoProjector, 3, "bfunc returns ", bool);
if bool = fail then
Error("bfunc must not return fail");
fi;
if inonly and bool = true then
return false;
fi;
fi;
fi;
fi;
if bool then # cpcgs mod ser[i+1] is a projector
upcgs := cpcgs;
# note that npcgs centralises ser and that cpcgs together with npcgs
# generate the same group as upcgs, so that ser is also a
# cpcgs-composition series of mpcgs
else
diff := diff + Length(npcgs); # adjust composition length
fi;
od;
if diff > 0 then # update the elementary abelian series of upcgs
Add(userp, p);
Add(userinds, userinds[Length(userinds)]+diff);
fi;
od;
if inonly then # group equals projector, so it belongs to the Schunck class
return true;
fi;
if hom or conv then # translate result back to previous pcgs
upcgs := InducedPcgsByPcSequenceNC(pcgs,
List(upcgs, x ->
PcElementByExponentsNC(pcgs, ExponentsOfPcElement(ppcgs, x))));
fi;
return upcgs;
end);
############################################################################
##
#E
##
[ Verzeichnis aufwärts0.46unsichere Verbindung
Übersetzung europäischer Sprachen durch Browser
]
|