Based on the idea here, I wrote the following code snippet to generate all non-equivalent elements of an affine crystallographic group:
AffOnLeftModOne[x_,y_]:=Module[{dim},
dim=Dimensions[x,1][[1]]-1;
(*TransformationMatrix[AffineTransform[{#[[1;;dim,1;;dim]],Mod[#[[1;;dim,dim+1]],1]}]&@Dot[x,y]]*)
TransformationMatrix[
AffineTransform[{#[[1 ;; dim, 1 ;; dim]],
Mod[#[[1 ;; dim, dim + 1]], 1]}] &@Dot[x, y]] // Expand //
Together // FullSimplify
]
AffCrystGroupOnLeft[gens_]:=Module[{dim,count,ge},
If[Length[Dimensions[gens]]==3 && Dimensions[gens][[2]]==Dimensions[gens][[3]],
dim=Dimensions[gens][[2]]-1;,Abort[]];
count=0;
ge = NestWhile[ (count++;
Union[Join[#1,
(*TransformationMatrix/@(AffineTransform[{#[[1;;dim,1;;dim]],Mod[#[[1;;dim,dim+1]],1]}]&/@Flatten[Outer[Dot, gens, #1, 1], 1])*)
Flatten[Outer[AffOnLeftModOne, gens, #1, 1], 1]
]]) &
,
{AffineTransform[{IdentityMatrix[dim],ConstantArray[0, dim]}]//TransformationMatrix}
,
Length[#2] != Length[#1]&
,
2
,
99
];
(*Return[{ge,count}]*)
Return[ge]
]
M1={{0,0,1,1/4},{1,0,0,1/4},{0,-1,0,1/4},{0,0,0,1}};
M2={{0,0,-1,0},{0,-1,0,0},{1,0,0,0},{0,0,0,1}};
SGGenElemAK227LeftS1={M1,M2};
In[172]:= AffCrystGroupOnLeft[SGGenElemAK227LeftS1]//Length//Timing
Out[172]= {1.3305, 192}
However, for the above method, I have the following problems need to be solved or further improvements:
- Here I use 99 as the most times to apply the function and a variable count to stores the number of function executions. I want to know how to automatically throw an error or prompt message when this condition is violated, so that I know that the task has not been completed normally.
- Outer is the core command of this method. I want to know if there are any other methods to further improve efficiency.
Regards,
Zhao