GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
# The GAP code in this function has been taken, essentially verbatim, from # an appendix to the paper # Hulpke, Stanovsky, Vojtechovsky: Connected quandles and transitive groups ############################################################ ############################################################ InstallGlobalFunction(QuandleIsomorphismRepresentatives, function(L) local C,R, P, Q, invariant, ExtendHomomorphismByClosingSource, ExtendIsomorphism, IsomorphismQuandles, QuandlesUpToIsomorphism, QuandleGenerators, T, Subquandle; ######################### invariant:=function(QQ) local rt, A, F, Q; Q:=MagmaByMultiplicationTable(QQ); rt:=RightMultiplicationGroupOfQuandle(Q); if HasIdGroup(rt) then rt:=IdGroup(rt); else rt:=false; fi; A:=[rt]; return A; end; ######################### ######################### Subquandle := function( Q, gens ) # returns the subquandle of Q generated by gens as a list of elements local sub, i, j; sub := ShallowCopy( gens ); repeat gens := ShallowCopy( sub ); for i in gens do for j in gens do AddSet( sub, Q[i][j] ); od; od; until Length( sub ) = Length( gens ); return sub; end; ######################### ######################### QuandleGenerators := function( Q ) # returns a small generating set of Q local gens, diff, n; gens := [ ]; n := Length( Q ); diff := [1..n]; while diff <> [ ] do AddSet( gens, diff[ 1 ] ); diff := Difference( diff, Subquandle( Q, gens ) ); od; return Set( gens ); end; ######################### ExtendHomomorphismByClosingSource := function( f, L, M ) # <L>, <M> are multiplication tables, <f> is a partial map from a subset of elements of <L> # to a subset of elements of <M>. This function attempts to extend <f> into a homomorphism # by extending the source of <f> into (the smallest possible) subquandle of <L>. local oldS, newS, pairs, x, y, newNow, p, z, fz; oldS := [ ]; newS := f[ 2 ]; repeat pairs := []; for x in oldS do for y in newS do Add( pairs, [ x, y ] ); Add( pairs, [ y, x ] ); od; od; for x in newS do for y in newS do Add( pairs, [ x, y ] ); od; od; newNow := []; for p in pairs do x := p[ 1 ]; y := p[ 2 ]; z := L[ x ][ y ]; fz := M[ f[ 1 ][ x ] ][ f[ 1 ][ y ] ]; if f[ 1 ][ z ] = 0 then f[ 1 ][ z ] := fz; AddSet( f[ 2 ], z ); AddSet( f[ 3 ], fz ); Add( newNow, z ); else if not f[ 1 ][ z ] = fz then return fail; fi; fi; od; oldS := Union( oldS, newS ); newS := ShallowCopy( newNow ); until IsEmpty( newS ); return f; end; ExtendIsomorphism := function( f, L, GenL, M ) # Given a partial map <f> from quandle <L> to quandle <M>, it attempts to extend # <f> into an isomorphism betweem <L> and <M>. # <GenL> is a small generating set of <L>. local x, possible_images, y, g, n; n := Length( L ); f := ExtendHomomorphismByClosingSource( f, L, M ); if f = fail or Length( f[ 2 ] ) > Length( f[ 3 ] ) then return fail; fi; if Length( f[ 2 ] ) = Length( L ) then return f; fi; #isomorphism found x := GenL[ 1 ]; GenL := List( [ 2..Length( GenL ) ], i -> GenL[ i ] ); possible_images := Filtered( [1..n], y -> not y in f[ 3 ] ); for y in possible_images do g := StructuralCopy( f ); g[ 1 ][ x ] := y; AddSet( g[ 2 ], x ); AddSet( g[ 3 ], y ); g := ExtendIsomorphism( g, L, GenL, M ); if not g = fail then return g; fi; #isomorphism found od; return fail; end; IsomorphismQuandles := function( L, M ) # returns an isomorphism of L to M if such exists, else returns fail. local GenL, map, iso; GenL := QuandleGenerators( L ); map := 0 * [ 1.. Length( L ) ]; map[ 1 ] := 1; # THIS IS ONLY OK IN INDECOMPOSABLE QUANDLES iso := ExtendIsomorphism( [ map, [ 1 ], [ 1 ] ], L, GenL, M); if not iso = fail then return SortingPerm( iso[ 1 ] ); fi; return fail; end; QuandlesUpToIsomorphism := function( ls ) # given a list of quandles ls, returns representatives up to isomorphism local qs, L, D, G, with_same_D, is_new, K; qs := []; for L in ls do D := invariant( L ); G := QuandleGenerators( L ); # will be testing only quandles with the same discriminator with_same_D := Filtered( qs, K -> K[2] = D ); is_new := true; for K in with_same_D do # K is a set of ordered tuples [quandle, discriminator] if not IsomorphismQuandles( L, K[1] ) = fail then is_new := false; break; fi; od; if is_new then Add( qs, [ L, D ] ); fi; od; # returning only quandles, not their discriminators return List( qs, L -> L[1] ); end; T:=List(L,x->MultiplicationTable(Elements(x))); return List(QuandlesUpToIsomorphism(T), x->MagmaByMultiplicationTable(x)); end); ############################################################ ############################################################