1#############################################################################
2##
3#W  classes.gi  Testing properties/varieties [loops]
4##
5##
6#Y  Copyright (C)  2004,  G. P. Nagy (University of Szeged, Hungary),
7#Y                        P. Vojtechovsky (University of Denver, USA)
8##
9
10#############################################################################
11##  ASSOCIATIVITY, COMMUTATIVITY AND GENERALIZATIONS
12##  -------------------------------------------------------------------------
13
14# (PROG) IsAssociative is already implemented for magmas, but we provide
15# a new method based on sections. This new method is much faster for groups,
16# and a bit slower for nonassociative loops.
17
18InstallOtherMethod( IsAssociative, "for loops",
19    [ IsLoop ], 0,
20function( Q )
21    local sLS, x, y;
22    sLS := Set( LeftSection( Q ) );
23    for x in LeftSection( Q ) do
24        for y in LeftSection( Q ) do
25            if not x*y in sLS then return false; fi;
26        od;
27    od;
28    return true;
29end);
30
31# implies
32# InstallTrueMethod( IsExtraLoop, IsAssociative and IsLoop );
33
34#############################################################################
35##
36#P  IsCommutative( Q )
37##
38##  Returns true if <Q> is commutative.
39
40InstallOtherMethod( IsCommutative, "for quasigroup",
41    [ IsQuasigroup ],
42function( Q )
43    return LeftSection( Q ) = RightSection( Q );
44end );
45
46#############################################################################
47##
48#P  IsPowerAssociative( Q )
49##
50##  Returns true if <Q> is a power associative quasigroup.
51
52InstallOtherMethod( IsPowerAssociative, "for quasigroup",
53    [ IsQuasigroup ],
54function( Q )
55    local checked, x, S;
56    checked := [];
57    repeat
58        x := Difference( Elements(Q), checked );
59        if IsEmpty( x ) then
60            return true;
61        fi;
62        S := Subquasigroup( Q, [x[1]] );
63        if not IsAssociative( S ) then
64            return false;
65        fi;
66        checked := Union( checked, Elements( S ) ); # S is a group, so every subquasigroup of S is a group
67    until 0=1;
68end );
69
70# implies
71# InstallTrueMethod( HasTwosidedInverses, IsPowerAssociative and IsLoop );
72
73#############################################################################
74##
75#P  IsDiassociative( Q )
76##
77##  Returns true if <Q> is a diassociative quasigroup.
78
79InstallOtherMethod( IsDiassociative, "for quasigroup",
80    [ IsQuasigroup ],
81function( Q )
82    local checked, all_pairs, x, S;
83    checked := [];
84    all_pairs := Combinations( PosInParent( Elements( Q ) ), 2 ); # it is faster to work with integers
85    repeat
86        x := Difference( all_pairs, checked );
87        if IsEmpty( x ) then
88            return true;
89        fi;
90        S := Subquasigroup( Q, x[1] );
91        if not IsAssociative( S ) then
92            return false;
93        fi;
94        checked := Union( checked, Combinations( PosInParent( Elements( S ) ), 2 ) );
95    until 0=1;
96end );
97
98# implies
99# InstallTrueMethod( IsPowerAlternative, IsDiassociative );
100# InstallTrueMethod( IsFlexible, IsDiassociative );
101
102#############################################################################
103##  INVERSE PROPERTIES
104##  -------------------------------------------------------------------------
105
106#############################################################################
107##
108#P  HasLeftInverseProperty( L )
109##
110##  Returns true if <L> has the left inverse property.
111
112InstallMethod( HasLeftInverseProperty, "for loop",
113    [ IsLoop ],
114function( L )
115    return ForAll( LeftSection( L ), a -> a^-1 in LeftSection( L ) );
116end );
117
118#############################################################################
119##
120#P  HasRightInverseProperty( L )
121##
122##  Returns true if <L> has the right inverse property.
123
124InstallMethod( HasRightInverseProperty, "for loop",
125    [ IsLoop ],
126function( L )
127    return ForAll( RightSection( L ), a -> a^-1 in RightSection( L ) );
128end );
129
130#############################################################################
131##
132#P  HasInverseProperty( L )
133##
134##  Returns true if <L> has the inverse property.
135
136InstallMethod( HasInverseProperty, "for loop",
137    [ IsLoop ],
138function( L )
139    return HasLeftInverseProperty( L ) and HasRightInverseProperty( L );
140end );
141
142#############################################################################
143##
144#P  HasWeakInverseProperty( L )
145##
146##  Returns true if <L> has the weak inverse property.
147
148InstallMethod( HasWeakInverseProperty, "for loop",
149    [ IsLoop ],
150function( L )
151    return ForAll( L, x -> ForAll( L, y -> LeftInverse(x*y)*x=LeftInverse(y) ));
152end );
153
154#############################################################################
155##
156#P  HasTwosidedInverses( L )
157##
158##  Returns true if <L> has two-sided inverses.
159
160InstallMethod( HasTwosidedInverses, "for loop",
161    [ IsLoop ],
162function( L )
163    return ForAll( L, x -> LeftInverse( x ) = RightInverse( x ) );
164end );
165
166#############################################################################
167##
168#P  HasAutomorphicInverseProperty( L )
169##
170##  Returns true if <L> has the automorphic inverse property.
171
172InstallMethod( HasAutomorphicInverseProperty, "for loop",
173    [ IsLoop ],
174function( L )
175    return ForAll( L, x -> ForAll( L, y ->
176        LeftInverse( x*y ) = LeftInverse( x )*LeftInverse( y ) ) );
177end );
178
179#############################################################################
180##
181#P  HasAntiautomorphicInverseProperty( L )
182##
183##  Returns true if <L> has the antiautomorphic inverse property.
184
185InstallMethod( HasAntiautomorphicInverseProperty, "for loop",
186    [ IsLoop ],
187function( L )
188    return ForAll( L, x -> ForAll( L, y ->
189        LeftInverse( x*y ) = LeftInverse( y )*LeftInverse( x ) ) );
190end );
191
192# implies and is implied by (for inverse properties)
193# InstallTrueMethod( HasAntiautomorphicInverseProperty, HasAutomorphicInverseProperty and IsCommutative );
194# InstallTrueMethod( HasAutomorphicInverseProperty, HasAntiautomorphicInverseProperty and IsCommutative );
195# InstallTrueMethod( HasLeftInverseProperty, HasInverseProperty );
196# InstallTrueMethod( HasRightInverseProperty, HasInverseProperty );
197# InstallTrueMethod( HasWeakInverseProperty, HasInverseProperty );
198# InstallTrueMethod( HasAntiautomorphicInverseProperty, HasInverseProperty );
199# InstallTrueMethod( HasTwosidedInverses, HasAntiautomorphicInverseProperty );
200# InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and IsCommutative );
201# InstallTrueMethod( HasInverseProperty, HasRightInverseProperty and IsCommutative );
202# InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and HasRightInverseProperty );
203# InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and HasWeakInverseProperty );
204# InstallTrueMethod( HasInverseProperty, HasRightInverseProperty and HasWeakInverseProperty );
205# InstallTrueMethod( HasInverseProperty, HasLeftInverseProperty and HasAntiautomorphicInverseProperty );
206# InstallTrueMethod( HasInverseProperty, HasRightInverseProperty and HasAntiautomorphicInverseProperty );
207# InstallTrueMethod( HasInverseProperty, HasWeakInverseProperty and HasAntiautomorphicInverseProperty );
208# InstallTrueMethod( HasTwosidedInverses, HasLeftInverseProperty );
209# InstallTrueMethod( HasTwosidedInverses, HasRightInverseProperty );
210# InstallTrueMethod( HasTwosidedInverses, IsFlexible and IsLoop );
211
212
213#############################################################################
214##  PROPERTIES OF QUASIGROUPS
215##  -------------------------------------------------------------------------
216
217#############################################################################
218##
219#P  IsSemisymmetric( Q )
220##
221##  Returns true if the quasigroup <Q> is semisymmetric, i.e., (xy)x=y.
222
223InstallMethod( IsSemisymmetric, "for quasigroup",
224    [ IsQuasigroup ],
225function( Q )
226    return ForAll( Q, x ->
227        LeftTranslation( Q, x ) * RightTranslation( Q, x ) = () );
228end );
229
230#############################################################################
231##
232#P  IsTotallySymmetric( Q )
233##
234##  Returns true if the quasigroup <Q> is totally symmetric, i.e,
235##  commutative and semisymmetric.
236
237InstallMethod( IsTotallySymmetric, "for quasigroup",
238    [ IsQuasigroup ],
239function( Q )
240    return IsCommutative( Q ) and IsSemisymmetric( Q );
241end );
242
243#############################################################################
244##
245#P  IsIdempotent( Q )
246##
247##  Returns true if the quasigroup <Q> is idempotent, i.e., x*x=x.
248
249InstallMethod( IsIdempotent, "for quasigroup",
250    [ IsQuasigroup ],
251function( Q )
252    return ForAll( Q, x -> x*x = x );
253end );
254
255#############################################################################
256##
257#P  IsSteinerQuasigroup( Q )
258##
259##  Returns true if the quasigroup <Q> is a Steiner quasigroup, i.e.,
260##  idempotent and totally symmetric.
261
262InstallMethod( IsSteinerQuasigroup, "for quasigroup",
263    [ IsQuasigroup ],
264function( Q )
265    return IsIdempotent( Q ) and IsTotallySymmetric( Q );
266end );
267
268#############################################################################
269##
270#P  IsUnipotent( Q )
271##
272##  Returns true if the quasigroup <Q> is unipotent, i.e., x*x=y*y.
273
274InstallMethod( IsUnipotent, "for quasigroup",
275    [ IsQuasigroup ],
276function( Q )
277    local square;
278    if IsLoop( Q ) then return IsIdempotent( Q ); fi;
279    square :=  Elements( Q )[ 1 ]^2;
280    return ForAll( Q, y -> y^2 = square );
281end );
282
283#############################################################################
284##
285#P  IsLDistributive( Q )
286##
287##  Returns true if the quasigroup <Q> is left distributive.
288
289InstallOtherMethod( IsLDistributive, "for Quasigroup",
290    [ IsQuasigroup ],
291function( Q )
292    # BETTER ALGORITHM LATER?
293    local x, y, z;
294    for x in Q do for y in Q do for z in Q do
295        if not x*(y*z) = (x*y)*(x*z) then return false; fi;
296    od; od; od;
297    return true;
298end );
299
300#############################################################################
301##
302#P  IsRDistributive( Q )
303##
304##  Returns true if the quasigroup <Q> is right distributive.
305
306InstallOtherMethod( IsRDistributive, "for Quasigroup",
307    [ IsQuasigroup ],
308function( Q )
309    # BETTER ALGORITHM LATER?
310    local x, y, z;
311    for x in Q do for y in Q do for z in Q do
312        if not (x*y)*z = (x*z)*(y*z) then return false; fi;
313    od; od; od;
314    return true;
315end );
316
317#############################################################################
318##
319#P  IsEntropic( Q )
320##
321##  Returns true if the quasigroup <Q> is entropic.
322
323InstallMethod( IsEntropic, "for quasigroup",
324    [ IsQuasigroup ],
325function( Q )
326    # BETTER ALGORITHM LATER?
327    local x, y, z, w;
328    for x in Q do for y in Q do for z in Q do for w in Q do
329        if not (x*y)*(z*w) = (x*z)*(y*w) then return false; fi;
330    od; od; od; od;
331    return true;
332end );
333
334#############################################################################
335##  LOOPS OF BOL-MOUFANG
336##  -------------------------------------------------------------------------
337
338#############################################################################
339##
340#P  IsExtraLoop( L )
341##
342##  Returns true if <L> is an extra loop.
343
344InstallMethod( IsExtraLoop, "for loop",
345    [ IsLoop ],
346function( L )
347    return IsMoufangLoop( L ) and IsNuclearSquareLoop( L );
348end );
349
350# implies
351# InstallTrueMethod( IsMoufangLoop, IsExtraLoop );
352# InstallTrueMethod( IsCLoop, IsExtraLoop );
353
354# is implied by
355# InstallTrueMethod( IsExtraLoop, IsMoufangLoop and IsLeftNuclearSquareLoop );
356# InstallTrueMethod( IsExtraLoop, IsMoufangLoop and IsMiddleNuclearSquareLoop );
357# InstallTrueMethod( IsExtraLoop, IsMoufangLoop and IsRightNuclearSquareLoop );
358
359#############################################################################
360##
361#P  IsMoufangLoop( L )
362##
363##  Returns true if <L> is a Moufang loop.
364
365InstallMethod( IsMoufangLoop, "for loop",
366    [ IsLoop ],
367function( L )
368    return IsLeftBolLoop( L ) and HasRightInverseProperty( L );
369end );
370
371# implies
372# InstallTrueMethod( IsLeftBolLoop, IsMoufangLoop );
373# InstallTrueMethod( IsRightBolLoop, IsMoufangLoop );
374# InstallTrueMethod( IsDiassociative, IsMoufangLoop );
375
376# is implied by
377# InstallTrueMethod( IsMoufangLoop, IsLeftBolLoop and IsRightBolLoop );
378
379#############################################################################
380##
381#P  IsCLoop( L )
382##
383##  Returns true if <L> is a C-loop.
384
385InstallMethod( IsCLoop, "for loop",
386    [ IsLoop ],
387function( L )
388    return IsLCLoop( L ) and IsRCLoop( L );
389end );
390
391# implies
392# InstallTrueMethod( IsLCLoop, IsCLoop );
393# InstallTrueMethod( IsRCLoop, IsCLoop );
394# InstallTrueMethod( IsDiassociative, IsCLoop and IsFlexible);
395
396# is implied by
397# InstallTrueMethod( IsCLoop, IsLCLoop and IsRCLoop );
398
399#############################################################################
400##
401#P  IsLeftBolLoop( L )
402##
403##  Returns true if <L> is a left Bol loop.
404
405InstallMethod( IsLeftBolLoop, "for loop",
406    [ IsLoop ],
407function( L )
408    return ForAll( LeftSection( L ), a ->
409        ForAll( LeftSection( L ), b -> a*b*a in LeftSection( L ) ) );
410end );
411
412# implies
413# InstallTrueMethod( IsRightBolLoop, IsLeftBolLoop and IsCommutative );
414# InstallTrueMethod( IsLeftPowerAlternative, IsLeftBolLoop );
415
416#############################################################################
417##
418#P  IsRightBolLoop( L )
419##
420##  Returns true if <L> is a right Bol loop.
421
422InstallMethod( IsRightBolLoop, "for loop",
423    [ IsLoop ],
424function( L )
425    return ForAll( RightSection( L ), a ->
426        ForAll( RightSection( L ), b -> a*b*a in RightSection( L ) ) );
427end );
428
429# implies
430# InstallTrueMethod( IsLeftBolLoop, IsRightBolLoop and IsCommutative );
431# InstallTrueMethod( IsRightPowerAlternative, IsRightBolLoop );
432
433#############################################################################
434##
435#P  IsLCLoop( L )
436##
437##  Returns true if <L> is an LC-loop.
438
439InstallMethod( IsLCLoop, "for loop",
440    [ IsLoop ],
441function( L )
442    return ForAll( LeftSection( L ), a ->
443        ForAll( RightSection( L ), b -> b^(-1)*a*a*b in LeftSection( L ) ) );
444end );
445
446# implies
447# InstallTrueMethod( IsLeftPowerAlternative, IsLCLoop );
448# InstallTrueMethod( IsLeftNuclearSquareLoop, IsLCLoop );
449# InstallTrueMethod( IsMiddleNuclearSquareLoop, IsLCLoop );
450# InstallTrueMethod( IsRCLoop, IsLCLoop and IsCommutative );
451
452#############################################################################
453##
454#P  IsRCLoop( L )
455##
456##  Returns true if <L> is an RC-loop.
457
458InstallMethod( IsRCLoop, "for loop",
459    [ IsLoop ],
460function( L )
461    return ForAll( LeftSection( L ), a ->
462        ForAll( RightSection( L ), b -> a^(-1)*b*b*a in RightSection( L ) ) );
463end );
464
465# implies
466# InstallTrueMethod( IsRightPowerAlternative, IsRCLoop );
467# InstallTrueMethod( IsRightNuclearSquareLoop, IsRCLoop );
468# InstallTrueMethod( IsMiddleNuclearSquareLoop, IsRCLoop );
469# InstallTrueMethod( IsLCLoop, IsRCLoop and IsCommutative );
470
471#############################################################################
472##
473#P  IsLeftNuclearSquareLoop( L )
474##
475##  Returns true if <L> is a left nuclear square loop.
476
477InstallMethod( IsLeftNuclearSquareLoop, "for loop",
478    [ IsLoop ],
479function( L )
480    return ForAll( L, x -> x^2 in LeftNucleus( L ) );
481end );
482
483#implies
484# InstallTrueMethod( IsRightNuclearSquareLoop, IsLeftNuclearSquareLoop and IsCommutative );
485
486#############################################################################
487##
488#P  IsMiddleNuclearSquareLoop( L )
489##
490##  Returns true if <L> is a middle nuclear square loop.
491
492InstallMethod( IsMiddleNuclearSquareLoop, "for loop",
493    [ IsLoop ],
494function( L )
495    return ForAll( L, x -> x^2 in MiddleNucleus( L ) );
496end );
497
498#############################################################################
499##
500#P  IsRightNuclearSquareLoop( L )
501##
502##  Returns true if <L> is a right nuclear square loop.
503
504InstallMethod( IsRightNuclearSquareLoop, "for loop",
505    [ IsLoop ],
506function( L )
507    return ForAll( L, x -> x^2 in RightNucleus( L ) );
508end );
509
510# implies
511# InstallTrueMethod( IsLeftNuclearSquareLoop, IsRightNuclearSquareLoop and IsCommutative );
512
513#############################################################################
514##
515#P  IsNuclearSquareLoop( L )
516##
517##  Returns true if <L> is a nuclear square loop.
518
519InstallMethod( IsNuclearSquareLoop, "for loop",
520    [ IsLoop ],
521function( L )
522    return IsLeftNuclearSquareLoop( L ) and IsRightNuclearSquareLoop( L )
523        and IsMiddleNuclearSquareLoop( L );
524end );
525
526# implies
527# InstallTrueMethod( IsLeftNuclearSquareLoop, IsNuclearSquareLoop );
528# InstallTrueMethod( IsRightNuclearSquareLoop, IsNuclearSquareLoop );
529# InstallTrueMethod( IsMiddleNuclearSquareLoop, IsNuclearSquareLoop );
530
531# is implied by
532# InstallTrueMethod( IsNuclearSquareLoop, IsLeftNuclearSquareLoop
533#    and IsRightNuclearSquareLoop and IsMiddleNuclearSquareLoop );
534
535#############################################################################
536##
537#P  IsFlexible( Q )
538##
539##  Returns true if <Q> is a flexible quasigroup.
540
541InstallMethod( IsFlexible, "for quasigroup",
542    [ IsQuasigroup ],
543function( Q )
544    local LS, RS;
545    LS := LeftSection( Q );
546    RS := RightSection( Q );
547    return ForAll( [1..Size( Q )], i -> LS[ i ] * RS[ i ] = RS[ i ] * LS[ i ] );
548end );
549
550# is implied by
551# InstallTrueMethod( IsFlexible, IsCommutative );
552
553#############################################################################
554##
555#P  IsLeftAlternative( Q )
556##
557##  Returns true if <Q> is a left alternative quasigroup.
558
559InstallMethod( IsLeftAlternative, "for quasigroup",
560    [ IsQuasigroup],
561function( Q )
562    if IsLoop( Q ) then
563        return ForAll( LeftSection( Q ), a -> a*a in LeftSection( Q ) );
564    fi;
565    return ForAll( Q, x -> ForAll( Q, y -> x*(x*y) = (x*x)*y ) );
566end );
567
568# implies
569# InstallTrueMethod( IsRightAlternative, IsLeftAlternative and IsCommutative );
570
571#############################################################################
572##
573#P  IsRightAlternative( Q )
574##
575##  Returns true if <Q> is a right alternative quasigroup.
576
577InstallMethod( IsRightAlternative, "for quasigroup",
578    [ IsQuasigroup ],
579function( Q )
580    if IsLoop( Q ) then
581        return ForAll( RightSection( Q ), a -> a*a in RightSection( Q ) );
582    fi;
583    return ForAll( Q, x -> ForAll( Q, y -> (x*y)*y = x*(y*y) ) );
584end );
585
586# implies
587# InstallTrueMethod( IsLeftAlternative, IsRightAlternative and IsCommutative );
588
589#############################################################################
590##
591#P  IsAlternative( Q )
592##
593##  Returns true if <Q> is an alternative quasigroup.
594
595InstallMethod( IsAlternative, "for quasigroup",
596    [ IsQuasigroup ],
597function( Q )
598    return IsLeftAlternative( Q ) and IsRightAlternative( Q );
599end );
600
601# implies
602# InstallTrueMethod( IsLeftAlternative, IsAlternative );
603# InstallTrueMethod( IsRightAlternative, IsAlternative );
604
605# is implied by
606# InstallTrueMethod( IsAlternative, IsLeftAlternative and IsRightAlternative );
607
608#############################################################################
609##  POWER ALTERNATIVE LOOPS
610##  -------------------------------------------------------------------------
611
612#############################################################################
613##
614#P  IsLeftPowerAlternative( L )
615##
616##  Returns true if <L> is a left power alternative loop.
617
618InstallMethod( IsLeftPowerAlternative, "for loop",
619    [ IsLoop ],
620function( L )
621    local i, M;
622    if Size( L ) = 1 then return true; fi;
623    for i in [ 2..Size( L )] do
624        M := Subloop( L, [ Elements( L )[ i ] ]);
625        if not Size( RelativeLeftMultiplicationGroup( L, M ) ) = Size( M ) then
626            return false;
627        fi;
628    od;
629    return true;
630end );
631
632# implies
633# InstallTrueMethod( IsLeftAlternative, IsLeftPowerAlternative );
634# InstallTrueMethod( HasLeftInverseProperty, IsLeftPowerAlternative );
635# InstallTrueMethod( IsPowerAssociative, IsLeftPowerAlternative );
636
637#############################################################################
638##
639#P  IsRightPowerAlternative( L )
640##
641##  Returns true if <L> is a right power alternative loop.
642
643InstallMethod( IsRightPowerAlternative, "for loop",
644    [ IsLoop ],
645function( L )
646    local i, M;
647    if Size( L ) = 1 then return true; fi;
648    for i in [ 2..Size( L ) ] do
649        M := Subloop( L, [ Elements( L )[ i ] ] );
650        if not Size( RelativeRightMultiplicationGroup( L, M ) ) = Size( M ) then
651            return false;
652        fi;
653    od;
654    return true;
655end );
656
657# implies
658# InstallTrueMethod( IsRightAlternative, IsRightPowerAlternative );
659# InstallTrueMethod( HasRightInverseProperty, IsRightPowerAlternative );
660# InstallTrueMethod( IsPowerAssociative, IsRightPowerAlternative );
661
662#############################################################################
663##
664#P  IsPowerAlternative( L )
665##
666##  Returns true if <L> is a power alternative loop.
667
668InstallMethod( IsPowerAlternative, "for loop",
669    [ IsLoop ],
670function( L )
671    return ( IsLeftPowerAlternative( L ) and IsRightPowerAlternative( L ) );
672end );
673
674# implies
675# InstallTrueMethod( IsLeftPowerAlternative, IsPowerAlternative );
676# InstallTrueMethod( IsRightPowerAlternative, IsPowerAlternative );
677
678#############################################################################
679##  CC-LOOPS AND RELATED PROPERTIES
680##  -------------------------------------------------------------------------
681
682#############################################################################
683##
684#P  IsLCCLoop( L )
685##
686##  Returns true if <L> is a left conjugacy closed loop.
687
688InstallMethod( IsLCCLoop, "for loop",
689    [ IsLoop ],
690function( L )
691    return ForAll( LeftSection( L ), a ->
692        ForAll( LeftSection( L ), b -> b*a*b^(-1) in LeftSection( L ) ) );
693end );
694
695# implies
696# InstallTrueMethod( IsAssociative, IsLCCLoop and IsCommutative );
697# InstallTrueMethod( IsExtraLoop, IsLCCLoop and IsMoufangLoop );
698
699#############################################################################
700##
701#P  IsRCCLoop( L )
702##
703##  Returns true if <L> is a right conjugacy closed loop.
704
705InstallMethod( IsRCCLoop, "for loop",
706    [ IsLoop ],
707function( L )
708    return ForAll( RightSection( L ), a ->
709        ForAll( RightSection( L ), b -> b*a*b^(-1) in RightSection( L ) ) );
710end );
711
712# implies
713# InstallTrueMethod( IsAssociative, IsRCCLoop and IsCommutative );
714# InstallTrueMethod( IsExtraLoop, IsRCCLoop and IsMoufangLoop );
715
716#############################################################################
717##
718#P  IsCCLoop( L )
719##
720##  Returns true if <L> is a conjugacy closed loop.
721
722InstallMethod( IsCCLoop, "for loop",
723    [ IsLoop ],
724function( L )
725    return IsLCCLoop( L ) and IsRCCLoop( L );
726end );
727
728# implies
729# InstallTrueMethod( IsLCCLoop, IsCCLoop );
730# InstallTrueMethod( IsRCCLoop, IsCCLoop );
731
732# is implied by
733# InstallTrueMethod( IsCCLoop, IsLCCLoop and IsRCCLoop );
734
735#############################################################################
736##
737#P  IsOsbornLoop( L )
738##
739##  Returns true if <L> is an Osborn loop.
740
741InstallMethod( IsOsbornLoop, "for loop",
742    [ IsLoop ],
743function( L )
744    # MIGHT REDO LATER
745    return ForAll(L, x-> ForAll(L, y->
746        ForAll(L, z-> x*((y*z)*x) = LeftDivision(LeftInverse(x),y)*(z*x))
747    ));
748end );
749
750# is implied by
751# InstallTrueMethod( IsOsbornLoop, IsMoufangLoop );
752# InstallTrueMethod( IsOsbornLoop, IsCCLoop );
753
754#############################################################################
755##  ADDITIONAL VARIETIES OF LOOPS
756##  -------------------------------------------------------------------------
757
758#############################################################################
759##
760#P  IsCodeLoop( L )
761##
762##  Returns true if <L> is an even code loop.
763
764InstallMethod( IsCodeLoop, "for loop",
765    [ IsLoop ],
766function( L )
767    # even code loops are precisely Moufang 2-loops with Frattini subloop of order 1, 2
768    return Set( Factors( Size( L ) ) ) = [ 2 ]
769        and IsMoufangLoop( L )
770        and Size( FrattiniSubloop( L ) ) in [1, 2];
771end );
772
773# implies
774# InstallTrueMethod( IsExtraLoop, IsCodeLoop );
775# InstallTrueMethod( IsCCLoop, IsCodeLoop );
776
777#############################################################################
778##
779#P  IsSteinerLoop( L )
780##
781##  Returns true if <L> is a Steiner loop.
782
783InstallMethod( IsSteinerLoop, "for loop",
784    [ IsLoop ],
785function( L )
786    # Steiner loops are inverse property loops of exponent at most 2.
787    return HasInverseProperty( L ) and Exponent( L )<=2;
788end );
789
790# implies
791# InstallTrueMethod( IsCommutative, IsSteinerLoop );
792# InstallTrueMethod( IsCLoop, IsSteinerLoop );
793
794#############################################################################
795##
796#P  IsLeftBruckLoop( L )
797##
798##  Returns true if <L> is a left Bruck loop.
799
800InstallMethod( IsLeftBruckLoop, "for loop",
801    [ IsLoop ],
802function( L )
803    return IsLeftBolLoop( L ) and HasAutomorphicInverseProperty( L );
804end );
805
806# implies
807# InstallTrueMethod( HasAutomorphicInverseProperty, IsLeftBruckLoop );
808# InstallTrueMethod( IsLeftBolLoop, IsLeftBruckLoop );
809# InstallTrueMethod( IsRightBruckLoop, IsLeftBruckLoop and IsCommutative );
810
811# is implied by
812# InstallTrueMethod( IsLeftBruckLoop, IsLeftBolLoop and HasAutomorphicInverseProperty );
813
814#############################################################################
815##
816#P  IsRightBruckLoop( L )
817##
818##  Returns true if <L> is a right Bruck loop.
819
820InstallMethod( IsRightBruckLoop, "for loop",
821    [ IsLoop ],
822function( L )
823    return IsRightBolLoop( L ) and HasAutomorphicInverseProperty( L );
824end );
825
826# implies
827# InstallTrueMethod( HasAutomorphicInverseProperty, IsRightBruckLoop );
828# InstallTrueMethod( IsRightBolLoop, IsRightBruckLoop );
829# InstallTrueMethod( IsLeftBruckLoop, IsRightBruckLoop and IsCommutative );
830
831# is implied by
832# InstallTrueMethod( IsRightBruckLoop, IsRightBolLoop and HasAutomorphicInverseProperty );
833
834#############################################################################
835##
836#P  IsLeftALoop( L )
837##
838##  Returns true if <L> is a left A-loop, that is if
839##  all left inner mappings are automorphisms of <L>.
840
841InstallMethod( IsLeftALoop, "for loop",
842   [ IsLoop ],
843function( L )
844   local gens;
845   gens := GeneratorsOfGroup( LeftInnerMappingGroup( L ) );
846   return ForAll(gens, f -> ForAll(L, x -> ForAll(L, y -> (x * y)^f = x^f * y^f )));
847end);
848
849#############################################################################
850##
851#P  IsRightALoop( L )
852##
853##  Returns true if <L> is a right A-loop, that is if
854##  all right inner mappings are automorphisms of <L>.
855
856InstallMethod( IsRightALoop, "for loop",
857   [ IsLoop ],
858function( L )
859   local gens;
860   gens := GeneratorsOfGroup( RightInnerMappingGroup( L ) );
861   return ForAll(gens, f -> ForAll(L, x -> ForAll(L, y -> (x * y)^f = x^f * y^f )));
862end);
863
864#############################################################################
865##
866#P  IsMiddleALoop( L )
867##
868##  Returns true if <L> is a middle A-loop, that is if
869##  all middle inner mappings (conjugations) are automorphisms of <L>.
870
871InstallMethod( IsMiddleALoop, "for loop",
872   [ IsLoop ],
873function( L )
874   local gens;
875   gens := GeneratorsOfGroup( MiddleInnerMappingGroup( L ) );
876   return ForAll(gens, f -> ForAll(L, x -> ForAll(L, y -> (x * y)^f = x^f * y^f )));
877end);
878
879#############################################################################
880##
881#P  IsALoop( L )
882##
883##  Returns true if <L> is an A-loop, that is if
884##  all inner mappings are automorphisms of <L>.
885
886InstallMethod( IsALoop, "for loop",
887   [ IsLoop ],
888function( Q )
889   return IsRightALoop(Q) and IsMiddleALoop(Q);
890   # Theorem: rigth A-loop + middle A-loop implies left A-loop
891end);
892
893# implies
894# InstallTrueMethod( IsLeftALoop, IsALoop );
895# InstallTrueMethod( IsRightALoop, IsALoop );
896# InstallTrueMethod( IsMiddleALoop, IsALoop );
897# InstallTrueMethod( IsLeftALoop, IsRightALoop and HasAntiautomorphicInverseProperty );
898# InstallTrueMethod( IsRightALoop, IsLeftALoop and HasAntiautomorphicInverseProperty );
899# InstallTrueMethod( IsFlexible, IsMiddleALoop );
900# InstallTrueMethod( HasAntiautomorphicInverseProperty, IsFlexible and IsLeftALoop );
901# InstallTrueMethod( HasAntiautomorphicInverseProperty, IsFlexible and IsRightALoop );
902# InstallTrueMethod( IsMoufangLoop, IsALoop and IsLeftAlternative );
903# InstallTrueMethod( IsMoufangLoop, IsALoop and IsRightAlternative );
904# InstallTrueMethod( IsMoufangLoop, IsALoop and HasLeftInverseProperty );
905# InstallTrueMethod( IsMoufangLoop, IsALoop and HasRightInverseProperty );
906# InstallTrueMethod( IsMoufangLoop, IsALoop and HasWeakInverseProperty );
907
908# is implied by
909# InstallTrueMethod( IsMiddleALoop, IsCommutative and IsLoop);
910# InstallTrueMethod( IsLeftALoop, IsLeftBruckLoop );
911# InstallTrueMethod( IsLeftALoop, IsLCCLoop );
912# InstallTrueMethod( IsRightALoop, IsRightBruckLoop );
913# InstallTrueMethod( IsRightALoop, IsRCCLoop );
914# InstallTrueMethod( IsALoop, IsCommutative and IsMoufangLoop );
915# InstallTrueMethod( IsALoop, IsLeftALoop and IsMiddleALoop );
916# InstallTrueMethod( IsALoop, IsRightALoop and IsMiddleALoop );
917# InstallTrueMethod( IsALoop, IsAssociative and IsLoop);
918