gap-packages / cryst

Computing with crystallographic groups
https://www.math.uni-bielefeld.de/~gaehler/gap/packages.php#Cryst
Other
3 stars 6 forks source link

Support IO_Pickle/IO_Unpickle of package IO for AffineCrystGroups #30

Open kiryph opened 2 years ago

kiryph commented 2 years ago

Generating all space groups is quite slow. On my machine it takes 21 seconds (3,2 GHz 6-Core Intel Core i7-8700B):

gap> SGList := List([1..230], l -> SpaceGroupOnRightIT( 3, l) );
gap> time/1000.;
21.x

I could speed up by using the six cores.

However, I would like to restore them from a pickled file, since doing the same computation all the time is a waste of resources.

The functions IO_Pickle and IO_Unpickle of the gap package IO can be executed

LoadPackage("IO");
fname := "SG3List.guck";
if IsReadableFile(fname) then
  f := IO_File(fname);
  SGList := IO_Unpickle(f);
  IO_Close(f);
else
  SGList := List([1..230], l -> SpaceGroupOnRightIT( 3, l) );
  f := IO_File(fname, "w");
  IO_Pickle(f, SGList);
  IO_Close(f);
fi;

but the unpickled object is actually is not the identical object. I have to call AsAffineCrystGroupOnRight to get AffineCrystGroups:

gap> SG := List(SGList, S -> AsAffineCrystGroupOnRight(S) );; time/1000.;
21.x

As you can see, this as slow as generating them again.

Can the support of IO_Pickle/IO_Unpickle for AffineCrystGroups be improved?

I assume IO_Pickle currently falls back to matrix groups:

InstallMethod( IO_Pickle, "for a matrix group",
  [ IsFile, IsMatrixGroup ],
  function( f, g )
    return IO_GenericObjectPickler(f,"MATG",[GeneratorsOfGroup(g)],g,
               [Name,Size,DimensionOfMatrixGroup,FieldOfMatrixGroup],[],[]);
  end );

IO_Unpicklers.MATG :=
  function(f)
    local g,gens;
    gens := IO_Unpickle(f); if gens = IO_Error then return IO_Error; fi;
    g := GroupWithGenerators(gens);
    return
    IO_GenericObjectUnpickler(f,g,
                 [Name,Size,DimensionOfMatrixGroup,FieldOfMatrixGroup],[]);
    return g;
  end;

taken from https://github.com/gap-packages/io/blob/master/gap/pickle.gi#L1193-L1209

As you can see the group is reconstructed by calling GroupWithGenerators(gens) which explains the behaviour.

I assume to be faster the AffineCrystGroup should be reconstructed by the underlying objects:

gap> KnownAttributesOfObject(SGList[230]);
[ "Name", "OneImmutable", "GeneratorsOfMagmaWithInverses", "MultiplicativeNeutralElement", "DimensionOfMatrixGroup", "PointGroup",
  "PointHomomorphism", "TranslationBasis", "InternalBasis" ]

such as PointGroup, PointHomomorphism, TranslationBasis, InternalBasis

How should the IO_Pickle method look like?

InstallMethod( IO_Pickle, "for a affine cryst group",
  [ IsFile, IsAffineCrystGroup ],
  function( f, g )
    return IO_GenericObjectPickler(f,"AFFCG",[???],g,
               [Name,Size,DimensionOfMatrixGroup,FieldOfMatrixGroup,???],[],[]);
  end );

and how can one create an AffineCrystGroup on a lower level:

IO_Unpicklers.AFFCG :=
  function(f)
    local g,gens;
    gens := IO_Unpickle(f); if gens = IO_Error then return IO_Error; fi;
    g := # UNCLEAR
    return
    IO_GenericObjectUnpickler(f,g,
                 [Name,Size,DimensionOfMatrixGroup,FieldOfMatrixGroup,???],[]);
    return g;
  end;

What about using ObjectifyWithAttributes? What is the family of AffineCrystGroup?

kiryph commented 2 years ago

This issue is also related to the gap package Memoisation which cannot be used for AffineCrystGroups, e.g.:

gap> LoadPackage("Memoisation");
gap> MSpaceGroupIT := MemoisedFunction(SpaceGroupIT);
gap> PointGroup(MSpaceGroupIT(3,22));
#I  Memo key: [ 3, 22 ]
#I  Key unknown.  Computing result...
Group([ [ [ -1, 0, 0 ], [ 0, -1, 0 ], [ 0, 0, 1 ] ], [ [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, -1 ] ] ])
gap> PointGroup(MSpaceGroupIT(3,22));
#I  Memo key: [ 3, 22 ]
#I  Key known!  Loading result from cache...
Error, no method found! For debugging hints type ?Recovery from NoMethodFound
Error, no 2nd choice method found for `IsAffineCrystGroupOnLeftOrRight' on 1 arguments at /usr/local/Cellar/gap/4.12.0/libexec/lib/methsel2.g:249 called from
<<compiled GAP code>> from GAPROOT/lib/oper1.g:736 in function PointGroup default method requiring categories and checking properties called from
<function "PointGroup default method requiring categories and checking properties">( <arguments> )
 called from read-eval loop at *stdin*:48
type 'quit;' to quit to outer loop
brk>