NxNxN cubes in GAP
Since defining GAP definitions for large cube sizes can be very tedious, I have implemented some GAP code for defining NxNxN cubes. The main function is called GenCube and returns a group representing a cube of the size specified by the parameter n. This function has a 2nd parameter (center_ori) used for odd cubes that allows specifying whether or not you wish to have the orientation of the most central pieces on each face to be considered significant.
The code uses a face-based numbering system. The facelets on the U face are numbered 1 to n2, the L face uses numbers n2 + 1 to 2n2, and the remaining faces are similarly numbered in the order F, R, B, D. For handling orientation of the most central pieces on each face, 18 additional numbers are used, starting at 6n2 + 1.
For 4x4x4 cubes, the inner layers have typically been given lower case letters to distinguish them from the face layers. For large size cubes, it becomes awkward defining distinct symbols for each layer. Therefore, my code uses lists for each of the three axes. So U[1] represents the U face layer, U[2] represents the layer below it, and so on for all the layers for that axis. Similarly, lists L and F are used to represent the layers of the other two axes. Whole cube rotations are also represented through variables x, y, and z using the standard definitions used in the speedcubing community. x is a cube rotation in the same direction as R, y is a cube rotation in the same direction as U, and z is a cube rotation in the same direction as F.
I note that turns of all layers are for the same direction as U, L, or F. So, for instance, the R turn for a 6x6x6 cube would be represented by L[6]^-1. I also note that for both even and odd size cubes, the code supports representing 24 orientations of the cube, so the number of elements in the group may be 24 times larger than what you might expect. You can always create your own groups from the elements of the U, L, and F lists as in the examples below.
Examples:
Standard 5x5x5 supercube group:
C555 := GenCube (5, true); Super555 := Group (U[1], U[2], U[4]^-1, U[5]^-1, L[1], L[2], L[4]^-1, L[5]^-1, F[1], F[2], F[4]^-1, F[5]^-1);
Group with Fixed DLB corner for 4x4x4 cube:
C444 := GenCube (4, false); FixedDLB444 := Group (U[1], U[2], U[3]^-1, U[1]*U[2]*U[3], L[4]^-1, L[3]^-1, L[2], (L[4]*L[3]*L[2])^-1, F[1], F[2], F[3]^-1, F[1]*F[2]*F[3]);
(Of course, these examples work without using "^-1" where indicated; but this way, the generators are consistently represented using what we generally consider clockwise turns.)
In large cubes, the face pieces (typically called centers) of the same color and orbit are generally considered indistinguishable. Modelling the puzzle as a permutation group in GAP does not directly allow these pieces to be considered indistinguishable. So the size of the group will generally be much larger than the actual number of positions for non-supercube puzzles.
So, finally, the GAP source code is given below. Let me know if you think you find any bugs.
#GenCube #Globals used U := []; L := []; F := []; x := (); y := (); z := (); GenFaceCycle := function (n, face, ring, orb, dir) local base, n1, n2, n3, n4, g; base := n*n*(face - 1); n1 := base + 1 + ring*n + ring + orb; n2 := base + n + ring*n - ring + orb*n; n3 := base + n*n - ring*n - ring - orb; n4 := base + n*n - n + 1 - ring*n + ring - orb*n; g := (n1, n2, n3, n4); if dir then g := g^-1; fi; return g; end; GenHorizLayerCycle := function (n, layer, orb) local n1, n2, n3, n4, g; n1 := n*n + 1 + layer*n + orb; n2 := 4*n*n + 1 + layer*n + orb; n3 := 3*n*n + 1 + layer*n + orb; n4 := 2*n*n + 1 + layer*n + orb; g := (n1, n2, n3, n4); return g; end; GenVertLayerCycle := function (n, layer, orb) local n1, n2, n3, n4, g; n1 := 1 + orb*n + layer; n2 := 2*n*n + 1 + orb*n + layer; n3 := 5*n*n + 1 + orb*n + layer; n4 := 5*n*n - orb*n - layer; g := (n1, n2, n3, n4); return g; end; FaceCycles := function (n, face, center_ori, g) local i, j, r, b, n2, xc, nb, h; h := g; n2 := Int (n/2); r := 0; while r < n2 do nb := n - 2*r - 1; # for even n, at least b := 0; while b < nb do h := h*GenFaceCycle (n, face, r, b, face >= 4); b := b + 1; od; r := r + 1; od; if center_ori then i := (face-1)*(n^2) + (n^2 + 1)/2; if i = Int (i) then #odd size cube xc := 6*(n^2) + 1; j := xc + (face-1)*3; if face >= 4 then h := h*(i,j+2,j+1,j); else h := h*(i,j,j+1,j+2); fi; fi; fi; return h; end; LayerCycles := function (n, face, layer, center_ori, g) local i, b, n2, xc, c1, c2, c3, c4, h, c4list; n2 := Int (n/2); h := g; b := 0; while b < n do if face = 1 then h := h*GenHorizLayerCycle (n, layer, b); fi; if face = 2 then h := h*GenVertLayerCycle (n, layer, b); fi; b := b + 1; od; if center_ori and (2*n2 < n) then if layer = n2 then xc := 6*(n^2) + 1; if face = 1 then c1 := xc + 3; c2 := xc + 12; c3 := xc + 9; c4 := xc + 6; fi; if face = 2 then c1 := (n^2 + 1)/2; c2 := 4*(n^2) + (n^2 + 1)/2; c3 := xc + 13; h := h*(c1,c2,c3); #correction to cycle for non-rotating case c1 := xc + 0; c2 := xc + 6; c3 := xc + 15; c4list := [xc + 14, 4*(n^2) + (n^2 + 1)/2, xc + 12]; fi; i := 0; while i < 3 do if face = 1 then h := h*(c1+i,c2+i,c3+i,c4+i); fi; if face = 2 then h := h*(c1+i,c2+i,c3+i,c4list[i+1]); fi; i := i + 1; od; fi; fi; return h; end; GenCube := function (n, center_ori) local layer, g; #initialize globals (except z which will be assigned directly using x and y later) U := []; L := []; F := []; x := (); y := (); #U-axis layers layer := 0; while layer < n do g := (); if layer = 0 then g := FaceCycles (n, 1, center_ori, g); fi; if layer = n - 1 then g := FaceCycles (n, 6, center_ori, g); fi; g := LayerCycles (n, 1, layer, center_ori, g); Add (U, g); y := y*g; layer := layer + 1; od; #L-axis layers x := (); layer := 0; while layer < n do g := (); if layer = 0 then g := FaceCycles (n, 2, center_ori, g); fi; if layer = n - 1 then g := FaceCycles (n, 4, center_ori, g); fi; g := LayerCycles (n, 2, layer, center_ori, g); Add (L, g); x := x*(g^-1); layer := layer + 1; od; #F-axis layers layer := 1; while layer <= n do Add (F, x*(y^-1)*U[layer]*y*(x^-1)); layer := layer + 1; od; z := x*y*(x^-1); return Group (Concatenation (U, L, F)); end;