diff --git a/lib/grp.gd b/lib/grp.gd
index 401edcd7d6..67c9e8ed31 100644
--- a/lib/grp.gd
+++ b/lib/grp.gd
@@ -2216,6 +2216,11 @@ DeclareAttribute( "LargestElementGroup", IsGroup );
## with getting a reasonably small set of generators, you better use
## .
##
+## Another way to find the minimal generating set is
+## MinimalGeneratingSetUsingChiefSeries
+## which executes in time polynominally bounded by the size of group,
+## but is slower than MinimalGeneratingSet for practical purposes.
+##
## Information about the minimal generating sets of the finite simple
## groups of order less than 10^6 can be found in .
## See also the package AtlasRep.
diff --git a/lib/grp.gi b/lib/grp.gi
index 76c8861eb5..56b1560228 100644
--- a/lib/grp.gi
+++ b/lib/grp.gi
@@ -11,6 +11,106 @@
## This file contains generic methods for groups.
##
+#############################################################################
+##
+#M MinimalGeneratingSetUsingChiefSeries( )
+##
+# This algorithm is described in the paper
+# "The Minimum Generating Set Problem" by Dhara Thakar and Andrea Lucchini.
+# link : https://arxiv.org/abs/2306.07633
+BindGlobal("MinimalGeneratingSetUsingChiefSeries",function(G)
+ local
+ cs, # The chief series of G
+ check, # A function to check if GbyGk is generated by cosets with given representative
+ GbyGk, # The quotient group of G with the k+1 st group in its chief series (1st is G)
+ Gkm1byGk, # Quotient of the kth and k-1 th groups in chief series of G.
+ Gkm1byGk_elem_reps, # The coset representatives of Gkm1byGk
+ Gkm1byGk_gen, # A (small) generating set of Gkm1byGk
+ Gkm1byGk_gen_reps, # The coset representatives (CR) of elements Gkm1byGk_gen
+ mingenset_k_reps, # The CR of minimum generating set (MGS) of GbyGkm1
+ phi_GbyG1, # Homomorphism for quotient group GbyG1
+ GbyG1, # Quotient of G and 2nd group in its chief series
+ phi_GbyGk, # Homomorphism for quotient group GbyG1
+ phi_Gkm1byGk, # Homomorphism for quotient group Gkm1byGk
+ temp,i,j,l,L,x,xl,prev,gmod,g,g0,g1,s,r,stop,k;
+ if IsTrivial(G) then return []; fi;
+ cs := ChiefSeries(G);
+ phi_GbyG1 := NaturalHomomorphismByNormalSubgroupNC(G,cs[2]);
+ GbyG1 := Image(phi_GbyG1);
+ mingenset_k_reps := List(MinimalGeneratingSet(GbyG1), x -> PreImagesRepresentative(phi_GbyG1, x));
+ # GbyG1 is a simple group, so it has a 2 size generating set which can be found easily.
+ # I'll rely on MinimalGeneratingSet to do this.
+ check := gx -> GbyGk = GroupWithGenerators(ImagesSet(phi_GbyGk,gx));
+ for k in [3..Length(cs)] do # Lifting
+ # We wish to compute the CR of MGS of GbyGk, given the CR of MGS of GbyGkm1 .
+ phi_GbyGk := NaturalHomomorphismByNormalSubgroupNC(G,cs[k]);
+ GbyGk := Image(phi_GbyGk);
+ if check(mingenset_k_reps) then continue; fi;
+ phi_Gkm1byGk := NaturalHomomorphismByNormalSubgroupNC(cs[k-1],cs[k]);
+ Gkm1byGk := Image(phi_Gkm1byGk);
+ Gkm1byGk_gen := SmallGeneratingSet(Gkm1byGk);
+ Gkm1byGk_gen_reps := List(Gkm1byGk_gen,x -> PreImagesRepresentative(phi_Gkm1byGk,x));
+ g := ShallowCopy(mingenset_k_reps);
+ stop := false;
+ if IsAbelian(Gkm1byGk) then
+ for i in [1..Length(g)] do
+ if stop then break; fi;
+ for j in [1..Length(Gkm1byGk_gen_reps)] do
+ temp := g[i];
+ g[i] := temp * Gkm1byGk_gen_reps[j];
+ if check(g) then
+ mingenset_k_reps := g;
+ stop := true;
+ break;
+ fi;
+ g[i] := temp;
+ od;
+ od;
+ if not stop then
+ Add(g,Gkm1byGk_gen_reps[1]);
+ Assert(1,check(g),"The algorithm is failing");
+ mingenset_k_reps := g;
+ fi;
+ else
+ Gkm1byGk_elem_reps := List(Enumerator(Gkm1byGk),x -> PreImagesRepresentative(phi_Gkm1byGk,x));
+ g0 := ShallowCopy(mingenset_k_reps);
+ g1 := ShallowCopy(mingenset_k_reps);
+ Add(g1,Gkm1byGk_elem_reps[1]);
+ for g in [g0,g1] do
+ if stop then break;fi;
+ l := Length(g);
+ L := Length(Gkm1byGk_elem_reps);
+ s := L^l;
+ prev := [];
+ for i in [l,l-1..1] do prev[i] := 1; od;
+ gmod := ShallowCopy(g);
+ for x in [0..s-1] do
+ xl := [];
+ for i in [1..l] do xl[i] := 0; od;
+ i := 1;
+ while x > 0 do
+ r := RemInt(x,L);
+ x := QuoInt(x,L);
+ xl[i]:=r;
+ i:= i+1;
+ od;
+ for i in [1..l] do
+ if xl[i] <> prev[i] then
+ gmod[i] := g[i] * Gkm1byGk_elem_reps[xl[i]+1];
+ fi;
+ od;
+ if check(gmod) then
+ mingenset_k_reps := gmod;
+ stop := true;
+ break;
+ fi;
+ prev := xl;
+ od;
+ od;
+ fi;
+ od;
+ return mingenset_k_reps;
+end);
#############################################################################
##
diff --git a/tst/testinstall/opers/MinimalGeneratingSetUsingChiefSeries.tst b/tst/testinstall/opers/MinimalGeneratingSetUsingChiefSeries.tst
new file mode 100644
index 0000000000..4c6063e48b
--- /dev/null
+++ b/tst/testinstall/opers/MinimalGeneratingSetUsingChiefSeries.tst
@@ -0,0 +1,45 @@
+gap> START_TEST("MinimalGeneratingSetUsingChiefSeries.tst");
+gap> CrossVerifyMinimalGeneratingSetUsingChiefSeries := function(startsize,endsize)
+> local G,size,gens1,gens2,G1,G2,i;
+> for size in [startsize..endsize] do
+> i := 0;
+> for G in AllSmallGroups(size) do
+> i := i + 1;
+> gens1:= MinimalGeneratingSet(G);
+> gens2:= MinimalGeneratingSetUsingChiefSeries(G);
+> if Length(gens1) = 0 then
+> if IsTrivial(G) then
+> if Length(gens2) > 0 then
+> return Concatenation("FAILED on AllSmallGroups(",String(size),")[",String(i),"]");
+> else
+> continue;
+> fi;
+> else
+> return Concatenation("MinimalGeneratingSet is failing on AllSmallGroups(",String(size),")[",String(i),"]");
+> fi;
+> fi;
+> G1 := GroupByGenerators(gens1);
+> if not G = G1 then
+> return Concatenation("MinimalGeneratingSet is failing on AllSmallGroups(",String(size),")[",String(i),"]");
+> fi;
+> G2 := GroupByGenerators(gens2);
+> if (not G = G2) or Length(gens1) < Length(gens2) then
+> return Concatenation("FAILED on AllSmallGroups(",String(size),")[",String(i),"]");
+> fi;
+> od;
+> od;
+> return "PASSED";
+> end;
+function( startsize, endsize ) ... end
+gap> CrossVerifyMinimalGeneratingSetUsingChiefSeries(1,60);
+"PASSED"
+gap> CrossVerifyMinimalGeneratingSetUsingChiefSeries(115,125);
+"PASSED"
+gap> G := AlternatingGroup(5);
+Alt( [ 1 .. 5 ] )
+gap> G := DirectProduct(G,G);;
+gap> mu := MinimalGeneratingSetUsingChiefSeries(G);;
+gap> G = GroupByGenerators(mu);
+true
+gap> Length(mu);
+2