1###########################################################
2##
3##  nearring ideals and related functions
4##  (mainly for function nearrings)
5##
6##  v0.01 4.12.1996
7##
8##  Author: Juergen Ecker
9##
10
11#****************************************************************************
12# ideals.g
13#
14# computes the ideals of a near-ring.
15#
16# Author: Erhard Aichinger
17#
18# Date : 06 June 1995
19#
20#****************************************************************************
21
22#############################################################################
23##
24#I  Ideal <=> LeftIdeal & RightIdeal
25
26InstallTrueMethod( IsNearRingIdeal, IsNearRingLeftIdeal and IsNearRingRightIdeal );
27InstallTrueMethod( IsNearRingLeftIdeal, IsNearRingIdeal );
28InstallTrueMethod( IsNearRingRightIdeal, IsNearRingIdeal );
29
30#############################################################################
31##
32#M  ViewObj				For NRIdeals
33
34InstallMethod(
35	ViewObj,
36	"ideal",
37	true,
38	[IsNearRingIdeal and HasSize],
39	1,			# if it's 2-sided write it
40  function ( i )
41    Print("< nearring ideal of size ", Size(i), " >" );
42  end );
43
44InstallMethod(
45	ViewObj,
46	"ideal",
47	true,
48	[IsNearRingIdeal],
49	1,			# if it's 2-sided write it
50  function ( i )
51    Print("< nearring ideal >");
52  end );
53
54InstallMethod(
55	ViewObj,
56	"ideal",
57	true,
58	[IsNearRingLeftIdeal and HasSize],
59	0,
60  function ( i )
61    Print("< nearring left ideal of size ", Size(i), " >" );
62  end );
63
64InstallMethod(
65	ViewObj,
66	"ideal",
67	true,
68	[IsNearRingLeftIdeal],
69	0,
70  function ( i )
71    Print("< nearring left ideal >" );
72  end );
73
74InstallMethod(
75	ViewObj,
76	"ideal",
77	true,
78	[IsNearRingRightIdeal and HasSize],
79	0,
80  function ( i )
81    Print("< nearring right ideal of size ", Size(i), " >" );
82  end );
83
84InstallMethod(
85	ViewObj,
86	"ideal",
87	true,
88	[IsNearRingRightIdeal],
89	0,
90  function ( i )
91    Print("< nearring right ideal >" );
92  end );
93
94#############################################################################
95##
96#M  PrintObj				For NRIdeals
97
98InstallMethod(
99	PrintObj,
100	"ideal",
101	true,
102	[IsNearRingIdeal and HasSize],
103	1,			# if it's 2-sided write it
104  function ( i )
105    Print("< nearring ideal of size ", Size(i), " >" );
106  end );
107
108InstallMethod(
109	PrintObj,
110	"ideal",
111	true,
112	[IsNearRingIdeal],
113	1,			# if it's 2-sided write it
114  function ( i )
115    Print("< nearring ideal >");
116  end );
117
118InstallMethod(
119	PrintObj,
120	"ideal",
121	true,
122	[IsNearRingLeftIdeal and HasSize],
123	0,
124  function ( i )
125    Print("< nearring left ideal of size ", Size(i), " >" );
126  end );
127
128InstallMethod(
129	PrintObj,
130	"ideal",
131	true,
132	[IsNearRingLeftIdeal],
133	0,
134  function ( i )
135    Print("< nearring left ideal >" );
136  end );
137
138InstallMethod(
139	PrintObj,
140	"ideal",
141	true,
142	[IsNearRingRightIdeal and HasSize],
143	0,
144  function ( i )
145    Print("< nearring right ideal of size ", Size(i), " >" );
146  end );
147
148InstallMethod(
149	PrintObj,
150	"ideal",
151	true,
152	[IsNearRingRightIdeal],
153	0,
154  function ( i )
155    Print("< nearring right ideal >" );
156  end );
157
158#############################################################################
159##
160#M  \=				For nearring ideals
161
162InstallMethod(
163	\=,
164	"different size",
165	IsIdenticalObj,
166	[IsNRI, IsNRI],
167	100,
168  function ( i, j )
169    if Size(i) <> Size(j) then
170	return false;
171    else
172	TryNextMethod();
173    fi;
174  end );
175
176#BindGlobal( "xor", function ( a, b )
177#	return ( ( a and ( not b ) ) or ( ( not a ) and b ) );
178#end );
179
180InstallMethod(
181	\=,
182	"left <-> not left",
183	IsIdenticalObj,
184	[IsNRI and HasIsNearRingLeftIdeal,
185		IsNRI and HasIsNearRingLeftIdeal],
186	100,
187  function ( i, j )
188#    if xor( IsNearRingLeftIdeal(i), IsNearRingLeftIdeal(j) )
189    if IsNearRingLeftIdeal(i) <> IsNearRingLeftIdeal(j)
190		then
191		return false;
192    else
193	TryNextMethod();
194    fi;
195  end );
196
197InstallMethod(
198	\=,
199	"right <-> not right",
200	IsIdenticalObj,
201	[IsNRI and HasIsNearRingRightIdeal,
202		IsNRI and HasIsNearRingRightIdeal],
203	100,
204  function ( i, j )
205#    if xor( IsNearRingRightIdeal(i), IsNearRingRightIdeal(j) )
206    if IsNearRingRightIdeal(i) <> IsNearRingRightIdeal(j)
207	then
208		return false;
209    else
210	TryNextMethod();
211    fi;
212  end );
213
214InstallMethod(
215	\=,
216	"ideal <-> not ideal",
217	IsIdenticalObj,
218	[IsNRI and HasIsNearRingIdeal,
219		IsNRI and HasIsNearRingIdeal],
220	100,
221  function ( i, j )
222#    if xor( IsNearRingIdeal(i), IsNearRingIdeal(j) )
223    if IsNearRingIdeal(i) <> IsNearRingIdeal(j)
224	then
225		return false;
226    else
227	TryNextMethod();
228    fi;
229  end );
230
231InstallMethod(
232	\=,
233	"with known additive group",
234	IsIdenticalObj,
235	[IsNRI , IsNRI ],
236	0,
237  function ( i , j )
238    return AsSSortedList(GroupReduct(i)) = AsSSortedList(GroupReduct(j));
239  end );
240
241#############################################################################
242##
243#M  \<  compare sizes of near-ring ideals (required for AsSSortedList)
244
245InstallMethod(
246	\<,
247	"compare group reducts",
248	IsIdenticalObj,
249	[IsNRI , IsNRI ],
250	0,
251  function ( i , j )
252    return GroupReduct(i) < GroupReduct(j);
253  end );
254
255#############################################################################
256##
257#M  AsList			For nearring ideals
258
259InstallMethod(
260	AsList,
261	"with known additive group",
262	true,
263	[IsNRI],
264	0,
265  function ( i )
266    return List( GroupReduct(i), x -> NearRingElementByGroupRep( i!.elementsInfo, x ) );
267  end );
268
269#############################################################################
270##
271#M  Size			For nearring ideals
272
273InstallMethod(
274	Size,
275	"with known additive group",
276	true,
277	[IsNRI ],
278	0,
279  function ( i )
280    return Size( GroupReduct(i) );
281  end );
282
283#############################################################################
284##
285#M  \in				For nearring ideals
286
287InstallMethod(
288	\in,
289	"with known additive group",
290	IsElmsColls,
291	[IsNearRingElement, IsNRI ],
292	0,
293  function ( x , i )
294    return GroupElementRepOfNearRingElement(x) in GroupReduct(i);
295  end );
296
297#############################################################################
298##
299#M  Random			For nearring ideals
300
301InstallMethod(
302	Random,
303	"with known additive group",
304	true,
305	[IsNRI ],
306	0,
307  function ( i )
308    return NearRingElementByGroupRep( i!.elementsInfo, Random( GroupReduct(i) ) );
309  end );
310
311##########################################################################
312## closure algorithms
313##########################################################################
314
315#############################################################################
316##
317#M  NearRingLeftIdealClosureOfSubgroup
318
319NearRingLeftIdealClosureOfSubgroupDefault := function (
320			F,
321			S
322		       )
323#*********************************************************
324# returns the smallest leftt ideal containing the elements
325# of the subgroup S of the nearring F as a normal subgroup
326# of the additive group of F
327#*********************************************************
328#
329   local G, L, fam, g, g_add, f, leftProd;
330
331   G := GroupReduct(F);
332   L := ShallowCopy(S);
333   fam := F!.elementsInfo;
334
335   L := NormalClosure( G, L );
336   if Size(L)=Size(G) then return G; fi;
337
338   for g_add in GeneratorsOfGroup(L) do
339	g := NearRingElementByGroupRep(fam,g_add);
340	for f in G do
341	    leftProd := GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,f) * g );
342	    if not leftProd in L then
343		L := NormalClosure( G, ClosureGroup( L, leftProd ));
344		if Size(L) = Size(G) then return G; fi;
345	    fi;
346	od;
347   od;
348
349   return L;
350end;
351
352InstallMethod(
353	NearRingLeftIdealClosureOfSubgroup,
354	"generic",
355	true,
356	[IsNearRing, IsGroup],
357	0,
358  NearRingLeftIdealClosureOfSubgroupDefault );
359
360#############################################################################
361##
362#M  NearRingIdealClosureOfSubgroup
363
364TransformationNearRingIdealClosureOfSubgroup := function(
365                        F,
366                        S
367                       )
368#*********************************************************
369# returns the smallest ideal containing the elements of the
370# subgroup S of the additive group of the nearring F again
371# as a subgroup of the additive group of F
372#*********************************************************
373#
374   local I, fam, a, f, i, generators, G, rightProd, pos, visited,
375	 additivelyGeneratingTrafos, distributiveGeneratingTrafos,
376	 distributiveGenerators, nonDistributiveGenerators,
377	 newGens;
378#
379   fam := F!.elementsInfo;
380
381   I := NormalClosure( GroupReduct(F), S );
382
383#  subgroup is the whole additive group?
384   if Size(I)=Size(F) then return GroupReduct(F); fi;
385
386   G := GroupReduct(F);
387
388   additivelyGeneratingTrafos :=
389	List( GeneratorsOfGroup( G ), gen -> NearRingElementByGroupRep( fam, gen ) );
390
391   # constant generators need not be tested
392
393   additivelyGeneratingTrafos :=
394	Filtered( additivelyGeneratingTrafos,
395			tfm -> not IsConstantEndoMapping(tfm) );
396   distributiveGeneratingTrafos :=
397     Filtered( additivelyGeneratingTrafos, IsGroupHomomorphism );
398
399   generators := Set( List( additivelyGeneratingTrafos, GroupElementRepOfNearRingElement ) );
400   distributiveGenerators :=
401		 Set( List( distributiveGeneratingTrafos, GroupElementRepOfNearRingElement ) );
402   nonDistributiveGenerators :=
403		 Difference( generators, distributiveGenerators );
404
405   visited := []; pos := 1;
406   while pos <= Size(I) do
407     i := Enumerator(I)[pos];
408     pos := pos + 1;
409     newGens := [];
410     if not i in visited then
411       AddSet( visited, i );
412
413       # case 1: distributive generators
414
415       for a in distributiveGenerators do
416	 # rightProd := i * a
417	 rightProd := GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,i) * NearRingElementByGroupRep(fam,a));
418	 if not rightProd in I then
419	   AddSet( newGens, rightProd );
420	 fi;
421       od;
422
423       # case 2: nondistributive generators
424
425       for f in G do
426         for a in nonDistributiveGenerators do
427	   # rightProd := ( f + i ) * a - f * a
428	   rightProd := GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,f*i) * a ) /
429		       GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,f) * a );
430	   if not rightProd in I then
431	     AddSet( newGens, rightProd );
432	   fi;
433	 od;
434       od;
435
436       # is there a new element ?
437
438       if newGens <> [] then
439	 I := NearRingLeftIdealClosureOfSubgroup( F,
440		ClosureGroup( I, SubgroupNC( G, newGens ) ) );
441	 pos := 1;				# start anew
442	 # the ideal is the whole nearring ?
443	 if Size(I)=Size(G) then return G; fi;
444       fi;
445
446     fi;
447   od;
448
449   return I;
450end;
451
452ExpMultNearRingIdealClosureOfSubgroup := function(
453                        F,
454                        S
455                       )
456#*********************************************************
457# returns the smallest ideal containing the elements of the
458# subgroup S of the additive group of the nearring F again
459# as a subgroup of the additive group of F
460#*********************************************************
461#
462   local I, a, f, i, generators, G, rightProd, pos, visited, mult, newGens;
463
464   mult := NRMultiplication(F);
465
466   I := NormalClosure( GroupReduct(F), S );
467
468#  subgroup is the whole additive group?
469   if Size(I)=Size(F) then return GroupReduct(F); fi;
470
471   G := GroupReduct(F);
472   generators := GeneratorsOfGroup( G );
473
474   visited := []; pos := 1;
475   while pos <= Size(I) do
476     i := Enumerator(I)[pos];
477     pos := pos + 1;
478     newGens := [];
479     if not i in visited then
480       AddSet( visited, i );
481       for a in generators do
482	 for f in G do
483	   rightProd := mult( f*i, a ) / mult( f, a );
484	   if not rightProd in I then
485	     AddSet( newGens, rightProd );
486	   fi;
487	 od;
488       od;
489       if newGens <> [] then
490	 I := NearRingLeftIdealClosureOfSubgroup( F,
491			ClosureGroup( I, SubgroupNC( G, newGens ) ) );
492	 pos := 1;
493	 # the ideal is the whole nearring ?
494	 if Size(I)=Size(G) then return G; fi;
495       fi;
496     fi;
497   od;
498
499   return I;
500end;
501
502InstallMethod(
503	NearRingIdealClosureOfSubgroup,
504	"for TfmNRs",
505	true,
506	[IsTransformationNearRing, IsGroup],
507	0,
508  TransformationNearRingIdealClosureOfSubgroup );
509
510InstallMethod(
511	NearRingIdealClosureOfSubgroup,
512	"for ExpMulNRs",
513	true,
514	[IsExplicitMultiplicationNearRing, IsGroup],
515	0,
516  ExpMultNearRingIdealClosureOfSubgroup );
517
518# the following method replaces the 2 methods above and is much faster
519# probably the 2 methods above will die sooner or later
520InstallMethod(
521	NearRingIdealClosureOfSubgroup,
522	"for TfmNRs",
523	true,
524	[IsNearRing, IsGroup],
525	50,
526  function ( nr, group )
527    # see Prop. 1.52 in Pilz, NearRings
528    return NearRingRightIdealClosureOfSubgroup( nr,
529		NearRingLeftIdealClosureOfSubgroup( nr, group ) );
530  end );
531
532#############################################################################
533##
534#M  NearRingRightIdealClosureOfSubgroup
535
536TransformationNearRingRightIdealClosureOfSubgroup := function(
537                        F,
538                        S
539                       )
540#*********************************************************
541# returns the smallest right ideal containing the elements
542# of the subgroup S of the additive group of the nearring F
543# as a normal subgroup of the additive group of F
544#*********************************************************
545#
546   local I, fam, a, f, i, generators, G, rightProd, pos, visited,
547	 additivelyGeneratingTrafos, distributiveGeneratingTrafos,
548	 distributiveGenerators, nonDistributiveGenerators, idtfm,
549	 newGens;
550#
551   fam := F!.elementsInfo;
552
553   I := NormalClosure( GroupReduct(F), S );
554
555#  subgroup is the whole additive group?
556   if Size(I)=Size(F) then return GroupReduct(F); fi;
557
558   G := GroupReduct(F);
559
560   additivelyGeneratingTrafos :=
561	List( GeneratorsOfGroup( G ), gen -> NearRingElementByGroupRep( fam, gen ) );
562
563   # constant generators need not be tested
564
565   additivelyGeneratingTrafos :=
566	Filtered( additivelyGeneratingTrafos,
567			tfm -> not IsConstantEndoMapping(tfm) );
568   distributiveGeneratingTrafos :=
569     Filtered( additivelyGeneratingTrafos, IsGroupHomomorphism );
570
571   generators := Set( List( additivelyGeneratingTrafos, GroupElementRepOfNearRingElement ) );
572   distributiveGenerators :=
573		 Set( List( distributiveGeneratingTrafos, GroupElementRepOfNearRingElement ) );
574   nonDistributiveGenerators :=
575		 Difference( generators, distributiveGenerators );
576
577   visited := []; pos := 1;
578   while pos <= Size(I) do
579     i := Enumerator(I)[pos];
580     pos := pos + 1;
581     newGens := [];
582     if not i in visited then
583       AddSet( visited, i );
584
585       # case 1: distributive generators
586
587       for a in distributiveGenerators do
588	 # rightProd := i * a
589	 rightProd := GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,i) * NearRingElementByGroupRep(fam,a) );
590	 if not rightProd in I then
591	   AddSet( newGens, rightProd );
592	 fi;
593       od;
594
595       # case 2: nondistributive generators
596
597       for f in G do
598         for a in nonDistributiveGenerators do
599	   # rightProd := ( f + i ) * a - f * a
600	   rightProd := GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,f*i) * NearRingElementByGroupRep(fam,a) ) /
601		       GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam,f) * NearRingElementByGroupRep(fam,a) );
602	   if not rightProd in I then
603	     AddSet( newGens, rightProd );
604	   fi;
605	 od;
606       od;
607
608       # is there a new element ?
609
610       if newGens <> [] then
611	 I := NormalClosure( G, ClosureGroup( I, SubgroupNC( G, newGens ) ) );
612	 pos := 1;				# start anew
613	 # the ideal is the whole nearring ?
614	 if Size(I)=Size(G) then return G; fi;
615       fi;
616
617     fi;
618   od;
619
620   return I;
621end;
622
623ExpMultNearRingRightIdealClosureOfSubgroup := function(
624                        F,
625                        S
626                       )
627#*********************************************************
628# returns the smallest right ideal containing the elements of the
629# subgroup S of the additive group of the nearring F again
630# as a subgroup of the additive group of F
631#*********************************************************
632#
633   local I, a, f, i, generators, G, rightProd, pos, visited, mult, newGens;
634
635   mult := NRMultiplication(F);
636
637   I := NormalClosure( GroupReduct(F), S );
638
639#  subgroup is the whole additive group?
640   if Size(I)=Size(F) then return GroupReduct(F); fi;
641
642   G := GroupReduct(F);
643   generators := GeneratorsOfGroup( G );
644
645   visited := []; pos := 1;
646   while pos <= Size(I) do
647     i := Enumerator(I)[pos];
648     pos := pos + 1;
649     newGens := [];
650     if not i in visited then
651       AddSet( visited, i );
652       for a in generators do
653	 for f in G do
654	   rightProd := mult( f*i, a ) / mult( f, a );
655	   if not rightProd in I then
656	     AddSet( newGens, rightProd );
657	   fi;
658	 od;
659       od;
660       if newGens <> [] then
661	 I := NormalClosure( G, ClosureGroup( I, SubgroupNC( G, newGens ) ) );
662	 pos := 1;
663	 # the ideal is the whole nearring ?
664	 if Size(I)=Size(G) then return G; fi;
665       fi;
666     fi;
667   od;
668
669   return I;
670end;
671
672InstallMethod(
673	NearRingRightIdealClosureOfSubgroup,
674	"for TfmNRs",
675	true,
676	[IsTransformationNearRing, IsGroup],
677	0,
678  TransformationNearRingRightIdealClosureOfSubgroup );
679
680InstallMethod(
681	NearRingRightIdealClosureOfSubgroup,
682	"for ExpMulNRs",
683	true,
684	[IsExplicitMultiplicationNearRing, IsGroup],
685	0,
686  ExpMultNearRingRightIdealClosureOfSubgroup );
687
688#############################################################################
689##
690#F  NRI constructs an object that can be a one or two sided ideal of a
691##	nearring
692
693InstallMethod(
694	NRI,
695	"for EMNRs",
696	true,
697	[IsNearRing and IsExplicitMultiplicationNearRing],
698	0,
699  function ( nr )
700  local fam, nri;
701
702    fam := nr!.elementsInfo;
703    nri := Objectify(
704		NewType(CollectionsFamily(fam),
705		IsNRIDefaultRep),
706		rec() );
707
708    nri!.elementsInfo := fam;
709
710    return nri;
711end );
712
713InstallMethod(
714	NRI,
715	"for TfmNRs",
716	true,
717	[IsNearRing and IsTransformationNearRing],
718	0,
719  function ( nr )
720  local nri;
721    nri := Objectify(
722		NewType(CollectionsFamily(EndoMappingFamily(Gamma(nr))),
723		IsNRIDefaultRep),
724		rec() );
725
726    nri!.elementsInfo := nr!.elementsInfo;
727
728    return nri;
729end );
730
731#############################################################################
732##
733#M  NearRingIdealByGenerators		two sided ideal
734
735InstallMethod(
736	NearRingIdealByGenerators,
737	"known ideals",
738	true,
739	[IsNearRing and HasNearRingIdeals, IsList],
740	0,
741  function ( nr , gens )
742  local ideals;
743    ideals := Filtered( NearRingIdeals(nr), ideal ->
744				ForAll( gens, gen -> gen in ideal ) );
745
746    return Intersection( ideals );
747  end );
748
749InstallMethod(
750	NearRingIdealByGenerators,
751	"two-sided ideal by gens",
752	true,		# bad style
753	[IsNearRing,IsList],
754	0,
755  function ( nr , gens )
756  local groupgens, subgroup, ideal;
757
758    ideal := NRI( nr );
759    SetGeneratorsOfNearRingIdeal( ideal, gens );
760    SetParent( ideal, nr );
761    SetIsNearRingIdeal( ideal, true );
762
763    return ideal;
764  end );
765
766#############################################################################
767##
768#M  NearRingRightIdealByGenerators		right ideal
769
770InstallMethod(
771	NearRingRightIdealByGenerators,
772	"known right ideals",
773	true,
774	[IsNearRing and HasNearRingRightIdeals, IsList],
775	0,
776  function ( nr , gens )
777  local ideals;
778    ideals := Filtered( NearRingRightIdeals(nr), ideal ->
779				ForAll( gens, gen -> gen in ideal ) );
780
781    return Intersection( ideals );
782  end );
783
784InstallMethod(
785	NearRingRightIdealByGenerators,
786	"right ideal by gens",
787	true,		# bad style
788	[IsNearRing,IsList],
789	0,
790  function ( nr , gens )
791  local groupgens, subgroup, ideal;
792
793    ideal := NRI( nr );
794    SetGeneratorsOfNearRingRightIdeal( ideal, gens );
795    SetParent( ideal, nr );
796    SetIsNearRingRightIdeal( ideal, true );
797
798    return ideal;
799  end );
800
801#############################################################################
802##
803#M  NearRingLeftIdealByGenerators		right ideal
804
805InstallMethod(
806	NearRingLeftIdealByGenerators,
807	"known left ideals",
808	true,
809	[IsNearRing and HasNearRingLeftIdeals, IsList],
810	0,
811  function ( nr , gens )
812  local ideals;
813    ideals := Filtered( NearRingLeftIdeals(nr), ideal ->
814				ForAll( gens, gen -> gen in ideal ) );
815
816    return Intersection( ideals );
817  end );
818
819InstallMethod(
820	NearRingLeftIdealByGenerators,
821	"left ideal by gens",
822	true,		# bad style
823	[IsNearRing,IsList],
824	0,
825  function ( nr , gens )
826  local groupgens, subgroup, ideal;
827
828    ideal := NRI( nr );
829    SetGeneratorsOfNearRingLeftIdeal( ideal, gens );
830    SetParent( ideal, nr );
831    SetIsNearRingLeftIdeal( ideal, true );
832
833    return ideal;
834  end );
835
836###########################################
837##
838## testing subgroups of the additive group
839##
840
841###########################################
842
843#############################################################################
844##
845#M  IsSubgroupNearRingRightIdeal
846
847IsSubgroupTransformationNearRingRightIdeal := function(
848                        F,
849                        R
850                       )
851#*********************************************************
852# returns true iff the normal subgroup R of F is a right
853# ideal of F.
854#*********************************************************
855
856   local a, a_add, f, isIdeal, lengthAddGs, fam, actualGen, generators;
857
858   if not IsSubgroup(GroupReduct(F),R) then
859	Error("<R> has to be a subgroup of the additive group of <F>");
860   fi;
861
862   if not IsNormal(GroupReduct(F),R) then
863	return false;
864   fi;
865
866   isIdeal := true;
867   generators := GeneratorsOfGroup (GroupReduct(F));
868   lengthAddGs := Length (generators);
869   fam := F!.elementsInfo;
870
871   actualGen := 0;
872   while isIdeal and (actualGen < lengthAddGs) do
873#                            at this place, the condition is ok
874#                            for all generators up to actualGen.
875      actualGen := actualGen + 1;
876      a_add := generators [actualGen];
877      a := NearRingElementByGroupRep(fam, a_add);
878      if IsGroupHomomorphism (a) then
879         if IsIdentityMapping (a) then
880#                            since R is a normal subgroup,
881#                            we do already know that (f + R - f) \subseteq R
882            isIdeal := true;
883         else
884            isIdeal := ForAll (R,
885                       r -> (GroupElementRepOfNearRingElement( NearRingElementByGroupRep(fam, r) * a ) in R)
886                            );
887         fi;
888      elif IsConstantEndoMapping(a) then  # a-a=0 is the always in R
889         isIdeal := true;
890      else
891         isIdeal := ForAll (F, f -> ForAll (R, r ->
892				( GroupElementRepOfNearRingElement((f+NearRingElementByGroupRep(fam,r))*a)
893				/
894				(GroupElementRepOfNearRingElement(f*a)) ) in R
895			));
896      fi;
897   od;
898
899   return isIdeal;
900end;
901
902IsSubgroupNearRingRightIdealDefault := function(
903                        F,
904                        R
905                       )
906#*********************************************************
907# returns true iff the normal subgroup R of F is a right
908# ideal of F.
909#*********************************************************
910
911   local a, a_add, f, l, isIdeal, lengthAddGs, fam, actualGen, generators;
912
913   if not IsSubgroup(GroupReduct(F),R) then
914	Error("<R> has to be a subgroup of the additive group of <F>");
915   fi;
916
917   if not IsNormal(GroupReduct(F),R) then
918	return false;
919   fi;
920
921   isIdeal := true;
922   generators := GeneratorsOfGroup (GroupReduct(F));
923   lengthAddGs := Length (generators);
924   fam := F!.elementsInfo;
925
926   actualGen := 0;
927   while isIdeal and (actualGen < lengthAddGs) do
928#                            at this place, the condition is ok
929#                            for all generators up to actualGen.
930      actualGen := actualGen + 1;
931
932      a_add := generators [actualGen];
933      a := NearRingElementByGroupRep(fam, a_add);
934
935         isIdeal := ForAll (F,
936                       f -> ForAll (R,
937                            r -> ( GroupElementRepOfNearRingElement((f+NearRingElementByGroupRep(fam,r))*a)
938					/
939				   (GroupElementRepOfNearRingElement(f*a)) ) in R
940			));
941   od;
942
943   return isIdeal;
944end;
945
946InstallMethod(
947	IsSubgroupNearRingRightIdeal,
948	"for NearRings",
949	true,
950	[IsNearRing, IsGroup],
951	0,
952  IsSubgroupNearRingRightIdealDefault );
953
954InstallMethod(
955	IsSubgroupNearRingRightIdeal,
956	"for transformation nearrings",
957	true,
958	[IsTransformationNearRing, IsGroup],
959	0,
960  IsSubgroupTransformationNearRingRightIdeal );
961
962InstallMethod(
963	IsSubgroupNearRingRightIdeal,
964	"ExpMulNR",
965	true,
966	[IsExplicitMultiplicationNearRing, IsGroup],
967	0,
968  function ( N, S )
969  local addGroup, mul;
970    addGroup := GroupReduct(N);
971
972    if not IsNormal(addGroup,S) then
973	return false;
974    fi;
975
976    mul := NRMultiplication(N);
977
978    return ForAll( GeneratorsOfGroup(addGroup), m ->
979	   ForAll( addGroup, n ->
980	   ForAll( S, s ->
981			( mul( n * s, m ) / mul( n, m ) ) in S ) ) );
982
983  end );
984
985#############################################################################
986##
987#M  IsSubgroupNearRingLeftIdeal
988
989IsSubgroupNearRingLeftIdealDefault := function (
990                          F,         # near-ring
991                          L
992                         )
993#**************************************************
994# true iff the subgroup L is a left ideal of F
995#*************************************************
996
997  local generatorsL, fam;
998
999   if not IsSubgroup(GroupReduct(F),L) then
1000	Error("<L> has to be a subgroup of the additive group of <F>");
1001   fi;
1002
1003   if not IsNormal(GroupReduct(F),L) then
1004	return false;
1005   fi;
1006
1007   fam := F!.elementsInfo;
1008   generatorsL := GeneratorsOfGroup (L);
1009
1010   return (ForAll (F,
1011              f -> ForAll (generatorsL,
1012                      l -> (GroupElementRepOfNearRingElement( f * NearRingElementByGroupRep(fam,l) ) in L)
1013                          )
1014                  )
1015          );
1016end;
1017
1018InstallMethod(
1019	IsSubgroupNearRingLeftIdeal,
1020	"for transformation nearrings",
1021	true,
1022	[IsNearRing, IsGroup],
1023	0,
1024  IsSubgroupNearRingLeftIdealDefault );
1025
1026InstallMethod(
1027	IsSubgroupNearRingLeftIdeal,
1028	"ExpMulNR",
1029	true,
1030	[IsExplicitMultiplicationNearRing, IsGroup],
1031	0,
1032  function ( N, S )
1033  local addGroup, mul;
1034    addGroup := GroupReduct(N);
1035
1036    if not IsSubgroup(GroupReduct(N),S) then
1037	Error("<S> has to be a subgroup of the additive group of <N>");
1038    fi;
1039
1040    if not IsNormal(addGroup,S) then
1041	return false;
1042    fi;
1043
1044    mul := NRMultiplication(N);
1045
1046    return ForAll( addGroup, n -> ForAll( S, s ->
1047             mul( n, s ) in S ) );
1048  end );
1049
1050#############################################################################
1051##
1052#M  IsNearRingRightIdeal		for NR left ideals
1053
1054InstallMethod(
1055	IsNearRingRightIdeal,
1056	"NR left ideals",
1057	true,
1058	[IsNRI and HasIsNearRingLeftIdeal],
1059	0,
1060  function ( l )
1061  local addGroup;
1062    addGroup := GroupReduct(l);
1063
1064    return IsSubgroupNearRingRightIdeal( Parent(l), addGroup );
1065  end );
1066
1067#############################################################################
1068##
1069#M  IsNearRingLeftIdeal		for NR right ideals
1070
1071InstallMethod(
1072	IsNearRingLeftIdeal,
1073	"NR right ideals",
1074	true,
1075	[IsNRI and HasIsNearRingRightIdeal],
1076	0,
1077  function ( r )
1078  local addGroup;
1079    addGroup := GroupReduct(r);
1080
1081    return IsSubgroupNearRingLeftIdeal( Parent(r), addGroup );
1082  end );
1083
1084#############################################################################
1085##
1086#M  IsNearRingIdeal		for NR left and right ideals
1087
1088InstallMethod(
1089	IsNearRingIdeal,
1090	"NR right ideals",
1091	true,
1092	[IsNRI and HasIsNearRingRightIdeal and
1093		IsNearRingRightIdeal],
1094	0,
1095  function ( r )
1096    return IsNearRingLeftIdeal( r );
1097  end );
1098
1099InstallMethod(
1100	IsNearRingIdeal,
1101	"NR left ideals",
1102	true,
1103	[IsNRI and HasIsNearRingLeftIdeal and
1104		IsNearRingLeftIdeal],
1105	0,
1106  function ( l )
1107    return IsNearRingRightIdeal( l );
1108  end );
1109
1110#############################################################################
1111##
1112#M  GroupReduct		For left near ring ideals
1113
1114InstallMethod(
1115	GroupReduct,
1116	"for left near ring ideals",
1117	true,
1118	[IsNRI and HasGeneratorsOfNearRingLeftIdeal],
1119	2,
1120  function ( I )
1121  local subgroup, parent;
1122    parent := Parent(I);
1123    subgroup := SubgroupNC( GroupReduct(parent),
1124			List(GeneratorsOfNearRingLeftIdeal(I),GroupElementRepOfNearRingElement) );
1125    subgroup := NearRingLeftIdealClosureOfSubgroup( parent, subgroup );
1126
1127    return subgroup;
1128
1129  end );
1130
1131#############################################################################
1132##
1133#M  GroupReduct		For right near ring ideals
1134
1135InstallMethod(
1136	GroupReduct,
1137	"for right near ring ideals",
1138	true,
1139	[IsNRI and HasGeneratorsOfNearRingRightIdeal],
1140	1,
1141  function ( I )
1142  local subgroup, parent;
1143    parent := Parent(I);
1144    subgroup := SubgroupNC( GroupReduct(parent),
1145			List(GeneratorsOfNearRingRightIdeal(I),GroupElementRepOfNearRingElement) );
1146    subgroup := NearRingRightIdealClosureOfSubgroup( parent, subgroup );
1147
1148    return subgroup;
1149
1150  end );
1151
1152#############################################################################
1153##
1154#M  GroupReduct		For near ring ideals
1155
1156InstallMethod(
1157	GroupReduct,
1158	"for near ring ideals",
1159	true,
1160	[IsNRI and HasGeneratorsOfNearRingIdeal],
1161	0,
1162  function ( I )
1163  local subgroup, parent;
1164    parent := Parent(I);
1165    subgroup := SubgroupNC( GroupReduct(parent),
1166			List(GeneratorsOfNearRingIdeal(I),GroupElementRepOfNearRingElement) );
1167    subgroup := NearRingIdealClosureOfSubgroup( parent, subgroup );
1168
1169    return subgroup;
1170
1171  end );
1172
1173###########
1174# subnearrings
1175
1176#############################################################################
1177##
1178#M  SubNearRing			by generators
1179
1180InstallMethod(
1181	SubNearRing,
1182	"TfmNRs",
1183	true,
1184	[IsTransformationNearRing, IsCollection],
1185	0,
1186  function ( nr , gens )
1187  local SubNR;
1188    if not ForAll(gens, g -> g in nr) then
1189	Error("generators have to be from the near ring");
1190    fi;
1191    SubNR := TransformationNearRingByGenerators(Gamma(nr),gens);
1192    SetParent( SubNR, nr );
1193
1194    return SubNR;
1195  end );
1196
1197InstallMethod(
1198	SubNearRing,
1199	"ExplicitMultiplicationNearRings",
1200	true,
1201	[IsExplicitMultiplicationNearRing, IsCollection],
1202	0,
1203  function ( nr , gens )
1204  local SubNR;
1205    Error("not yet implemented");
1206  end );
1207
1208#############################################################################
1209##
1210#M  AsSubNearRing
1211
1212InstallMethod(
1213	AsSubNearRing,
1214	"for ideals",
1215	true,
1216	[IsNearRing, IsNRI],
1217	0,
1218  function ( nr, i )
1219  local subNR, parent, addGroup, fam;
1220    addGroup := GroupReduct(i);
1221    fam := i!.elementsInfo;
1222    subNR := SubNearRing( nr,
1223		List(GeneratorsOfGroup(addGroup), g -> NearRingElementByGroupRep(fam, g) ) );
1224    SetGroupReduct( subNR, addGroup );
1225
1226    return subNR;
1227  end );
1228
1229#############################################################################
1230##
1231#F  NearRingIdealBySubgroupNC( <nr>, <group> )	constructs an ideal of the
1232##						nearring <nr> the additive
1233##						group of which is <group>
1234##
1235##		No Check!
1236
1237NearRingIdealBySubgroupNC := function ( nr, group )
1238local fam, gens, ideal;
1239  fam := nr!.elementsInfo;
1240  gens := List( GeneratorsOfGroup(group), gen -> NearRingElementByGroupRep(fam, gen) );
1241  ideal := NRI( nr );
1242  SetGeneratorsOfNearRingIdeal( ideal, gens );
1243  SetParent( ideal, nr );
1244  SetIsNearRingIdeal( ideal, true );
1245  SetGroupReduct( ideal, group );
1246
1247  return ideal;
1248end;
1249
1250#############################################################################
1251##
1252#F  NearRingLeftIdealBySubgroupNC( <nr>, <group> )	constructs a left
1253##						ideal of the nearring <nr>
1254##						the additive group of which is
1255##						<group>
1256##		No Check!
1257
1258NearRingLeftIdealBySubgroupNC := function ( nr, group )
1259local fam, gens, ideal;
1260  fam := nr!.elementsInfo;
1261  gens := List( GeneratorsOfGroup(group), gen -> NearRingElementByGroupRep(fam, gen) );
1262  ideal := NRI( nr );
1263  SetGeneratorsOfNearRingLeftIdeal( ideal, gens );
1264  SetParent( ideal, nr );
1265  SetIsNearRingLeftIdeal( ideal, true );
1266  SetGroupReduct( ideal, group );
1267
1268  return ideal;
1269end;
1270
1271#############################################################################
1272##
1273#F  NearRingRightIdealBySubgroupNC( <nr>, <group> )	constructs a right
1274##						ideal of the nearring <nr>
1275##						the additive group of which is
1276##						<group>
1277##		No Check!
1278
1279NearRingRightIdealBySubgroupNC := function ( nr, group )
1280local fam, gens, ideal;
1281  fam := nr!.elementsInfo;
1282  gens := List( GeneratorsOfGroup(group), gen -> NearRingElementByGroupRep(fam, gen) );
1283  ideal := NRI( nr );
1284  SetGeneratorsOfNearRingRightIdeal( ideal, gens );
1285  SetParent( ideal, nr );
1286  SetIsNearRingRightIdeal( ideal, true );
1287  SetGroupReduct( ideal, group );
1288
1289  return ideal;
1290end;
1291
1292#############################################################################
1293##
1294#M  NearRingLeftIdeals( <nr> )	computes a list of all left ideals of <nr>
1295##
1296
1297InstallMethod(
1298	NearRingLeftIdeals,
1299	"filter normal subgroups",
1300	true,
1301	[IsNearRing],
1302	5,
1303  function ( nr )
1304    return List(
1305	Filtered( NormalSubgroups( GroupReduct(nr) ),
1306			s -> IsSubgroupNearRingLeftIdeal( nr,s ) ),
1307	sg -> NearRingLeftIdealBySubgroupNC( nr, sg )
1308		);
1309  end );
1310
1311#############################################################################
1312##
1313#M  NearRingRightIdeals( <nr> )	computes a list of all right ideals of <nr>
1314##
1315
1316InstallMethod(
1317	NearRingRightIdeals,
1318	"filter normal subgroups",
1319	true,
1320	[IsNearRing],
1321	5,
1322  function ( nr )
1323    return List(
1324	Filtered( NormalSubgroups( GroupReduct(nr) ),
1325			s -> IsSubgroupNearRingRightIdeal( nr,s ) ),
1326	sg -> NearRingRightIdealBySubgroupNC( nr, sg )
1327		);
1328  end );
1329
1330#############################################################################
1331##
1332#M  NearRingIdeals( <nr> )		computes a list of all ideals of <nr>
1333##
1334
1335InstallImmediateMethod(
1336	NearRingIdeals,
1337	IsSimpleNearRing,
1338	0,
1339  function ( nr )
1340  local addGroup, ideals;
1341    addGroup := GroupReduct( nr );
1342    ideals := [ TrivialSubgroup( addGroup ), addGroup ];
1343
1344    return List( ideals, id -> NearRingIdealBySubgroupNC( nr, id ) );
1345  end );
1346
1347InstallMethod(
1348	NearRingIdeals,
1349	"known left ideals",
1350	true,
1351	[IsNearRing and HasNearRingLeftIdeals],
1352	100,
1353  function ( nr )
1354    return Filtered( NearRingLeftIdeals(nr),
1355			l -> IsNearRingIdeal(l) );
1356  end );
1357
1358InstallMethod(
1359	NearRingIdeals,
1360	"known right ideals",
1361	true,
1362	[IsNearRing and HasNearRingRightIdeals],
1363	100,
1364  function ( nr )
1365    return Filtered( NearRingRightIdeals(nr),
1366			l -> IsNearRingIdeal(l) );
1367  end );
1368
1369InstallMethod(
1370	NearRingIdeals,
1371	"filter normal subgroups",
1372	true,
1373	[IsNearRing],
1374	5,
1375  function ( nr )
1376    return List(
1377	Filtered( NormalSubgroups( GroupReduct(nr) ),
1378			s -> IsSubgroupNearRingLeftIdeal( nr,s ) and
1379				IsSubgroupNearRingRightIdeal( nr,s ) ),
1380	sg -> NearRingIdealBySubgroupNC( nr, sg )
1381		);
1382  end );
1383
1384##### faster ######
1385
1386#################################################################
1387##
1388#F  NearRingLeftIdeals ( <R> ) ... compute a list of all left ideals
1389##
1390
1391InstallMethod(
1392	NearRingLeftIdeals,
1393	"from the subgroup lattice",
1394	true,
1395	[IsNearRing],
1396	2,		# slightly better than the original one
1397  function ( NR )
1398    local addGroup, lattice, upInclusions, downInclusions, CantorList,
1399        cl, sum, NumberOfSubgroups, idealLattice,
1400	vertex, idealInclusions, candidate,
1401	maxsubgrlist, vertexset, LCCS, ideals;
1402
1403    addGroup := GroupReduct(NR);
1404    lattice := LatticeSubgroups( addGroup );
1405    LCCS := lattice!.conjugacyClassesSubgroups;
1406
1407    # [i,j] = AsList( LCCS[i] ) [j]
1408
1409    upInclusions := MinimalSupergroupsLattice(lattice);
1410    downInclusions := MaximalSubgroupsLattice(lattice);
1411
1412    # the CantorList represents a bijection between [i,j] and
1413    # the place of [i,j] in the lists up/downInclusions
1414
1415    CantorList := [0]; sum := 0;
1416    for cl in LCCS do
1417        sum := sum + Size(cl);
1418        Add(CantorList,sum);
1419    od;
1420    NumberOfSubgroups := CantorList[Length(CantorList)];
1421
1422    idealLattice := [true];                    # (0) is an ideal
1423    idealLattice[NumberOfSubgroups] := true;   #  NR is an ideal
1424    ideals := [ TrivialSubgroup(addGroup), addGroup ];
1425
1426    for vertexset in upInclusions do
1427     for vertex in vertexset do
1428
1429      if Size( LCCS [vertex[1]] ) = 1 and	# normal subgroup
1430	 not IsBound(idealLattice[CantorList[vertex[1]]+vertex[2]]) then
1431
1432        candidate := AsList( LCCS [vertex[1]] ) [vertex[2]];
1433	maxsubgrlist := downInclusions[vertex[1]];
1434
1435	if Length(Filtered(maxsubgrlist,
1436		x -> idealLattice[CantorList[x[1]]+x[2]])) > 1 then
1437
1438	# if at least 2 max subgroups are ideals, we have an ideal
1439
1440	     idealLattice[CantorList[vertex[1]]+vertex[2]] := true;
1441	     Add( ideals, candidate );
1442
1443	else
1444
1445	# otherwise we have to check
1446
1447	     idealLattice[CantorList[vertex[1]]+vertex[2]] :=
1448		IsSubgroupNearRingLeftIdeal( NR, candidate );
1449	     if idealLattice[CantorList[vertex[1]]+vertex[2]] then
1450		Add( ideals, candidate );
1451	     fi;
1452
1453	fi;
1454      fi;
1455     od;
1456    od;
1457
1458    # transform subgroups into ideals
1459    ideals := List( ideals, I -> NearRingLeftIdealBySubgroupNC( NR, I ) );
1460    return ideals;
1461  end );
1462
1463#################################################################
1464##
1465#F  NearRingRightIdeals ( <R> ) ... compute a list of all right ideals
1466##
1467
1468InstallMethod(
1469	NearRingRightIdeals,
1470	"from the subgroup lattice",
1471	true,
1472	[IsNearRing],
1473	2,		# slightly better than the original one
1474  function ( NR )
1475    local addGroup, lattice, upInclusions, downInclusions, CantorList,
1476        cl, sum, NumberOfSubgroups, idealLattice,
1477	vertex, idealInclusions, candidate,
1478	maxsubgrlist, vertexset, LCCS, ideals;
1479
1480    addGroup := GroupReduct(NR);
1481    lattice := LatticeSubgroups( addGroup );
1482    LCCS := lattice!.conjugacyClassesSubgroups;
1483
1484    # [i,j] = AsList( LCCS[i] ) [j]
1485
1486    upInclusions := MinimalSupergroupsLattice(lattice);
1487    downInclusions := MaximalSubgroupsLattice(lattice);
1488
1489    # the CantorList represents a bijection between [i,j] and
1490    # the place of [i,j] in the lists up/downInclusions
1491
1492    CantorList := [0]; sum := 0;
1493    for cl in LCCS do
1494        sum := sum + Size(cl);
1495        Add(CantorList,sum);
1496    od;
1497    NumberOfSubgroups := CantorList[Length(CantorList)];
1498
1499    idealLattice := [true];                    # (0) is an ideal
1500    idealLattice[NumberOfSubgroups] := true;   #  NR is an ideal
1501    ideals := [ TrivialSubgroup(addGroup), addGroup ];
1502
1503    for vertexset in upInclusions do
1504     for vertex in vertexset do
1505
1506      if Size( LCCS [vertex[1]] ) = 1 and	# normal subgroup
1507	 not IsBound(idealLattice[CantorList[vertex[1]]+vertex[2]]) then
1508
1509        candidate := AsList( LCCS [vertex[1]] ) [vertex[2]];
1510	maxsubgrlist := downInclusions[vertex[1]];
1511
1512	if Length(Filtered(maxsubgrlist,
1513		x -> idealLattice[CantorList[x[1]]+x[2]])) > 1 then
1514
1515	# if at least 2 max subgroups are ideals, we have an ideal
1516
1517	     idealLattice[CantorList[vertex[1]]+vertex[2]] := true;
1518	     Add( ideals, candidate );
1519
1520	else
1521
1522	# otherwise we have to check
1523
1524	     idealLattice[CantorList[vertex[1]]+vertex[2]] :=
1525		IsSubgroupNearRingRightIdeal( NR, candidate );
1526	     if idealLattice[CantorList[vertex[1]]+vertex[2]] then
1527		Add( ideals, candidate );
1528	     fi;
1529
1530	fi;
1531      fi;
1532     od;
1533    od;
1534
1535    # transform subgroups into right ideals
1536    ideals := List( ideals, I -> NearRingRightIdealBySubgroupNC( NR, I ) );
1537
1538    # lattice info in idealLattice
1539    return ideals;
1540  end );
1541
1542#################################################################
1543##
1544#F  NearRingIdeals ( <R> ) ... compute a list of all ideals
1545##
1546
1547InstallMethod(
1548	NearRingIdeals,
1549	"from the subgroup lattice",
1550	true,
1551	[IsNearRing],
1552	2,		# slightly better than the original one
1553  function ( NR )
1554    local addGroup, lattice, upInclusions, downInclusions, CantorList,
1555        cl, sum, NumberOfSubgroups, idealLattice,
1556	vertex, idealInclusions, candidate,
1557	maxsubgrlist, vertexset, LCCS, ideals;
1558
1559    addGroup := GroupReduct(NR);
1560    lattice := LatticeSubgroups( addGroup );
1561    LCCS := lattice!.conjugacyClassesSubgroups;
1562
1563    # [i,j] = AsList( LCCS[i] ) [j]
1564
1565    upInclusions := MinimalSupergroupsLattice(lattice);
1566    downInclusions := MaximalSubgroupsLattice(lattice);
1567
1568    # the CantorList represents a bijection between [i,j] and
1569    # the place of [i,j] in the lists up/downInclusions
1570
1571    CantorList := [0]; sum := 0;
1572    for cl in LCCS do
1573        sum := sum + Size(cl);
1574        Add(CantorList,sum);
1575    od;
1576    NumberOfSubgroups := CantorList[Length(CantorList)];
1577
1578    idealLattice := [true];                    # (0) is an ideal
1579    idealLattice[NumberOfSubgroups] := true;   #  NR is an ideal
1580    ideals := [ TrivialSubgroup(addGroup), addGroup ];
1581
1582    for vertexset in upInclusions do
1583     for vertex in vertexset do
1584
1585      if Size( LCCS [vertex[1]] ) = 1 and	# normal subgroup
1586	 not IsBound(idealLattice[CantorList[vertex[1]]+vertex[2]]) then
1587
1588        candidate := AsList( LCCS [vertex[1]] ) [vertex[2]];
1589	maxsubgrlist := downInclusions[vertex[1]];
1590
1591	if Length(Filtered(maxsubgrlist,
1592		x -> idealLattice[CantorList[x[1]]+x[2]])) > 1 then
1593
1594	# if at least 2 max subgroups are ideals, we have an ideal
1595
1596	     idealLattice[CantorList[vertex[1]]+vertex[2]] := true;
1597	     Add( ideals, candidate );
1598
1599	else
1600
1601	# otherwise we have to check
1602
1603	     idealLattice[CantorList[vertex[1]]+vertex[2]] :=
1604		IsSubgroupNearRingLeftIdeal( NR, candidate ) and
1605		IsSubgroupNearRingRightIdeal( NR, candidate );
1606	     if idealLattice[CantorList[vertex[1]]+vertex[2]] then
1607		Add( ideals, candidate );
1608	     fi;
1609
1610	fi;
1611      fi;
1612     od;
1613    od;
1614
1615    # transform subgroups into ideals
1616    ideals := List( ideals, I -> NearRingIdealBySubgroupNC( NR, I ) );
1617
1618    # lattice info in idealLattice
1619    return ideals;
1620  end );
1621
1622#### end: faster #####
1623
1624
1625#############################################################################
1626##
1627#M  Enumerator						For FNRs
1628
1629InstallMethod(
1630	Enumerator,
1631	true,
1632	[ IsNRI ],
1633	0,
1634  function( nri )
1635    return Objectify( NewType( FamilyObj( nri ),
1636			IsList and IsNearRingIdealEnumerator ),
1637           rec( additiveGroup := GroupReduct(nri),
1638		elementsInfo := nri!.elementsInfo ) );
1639  end );
1640
1641InstallMethod(
1642	Length,
1643	true,
1644	[ IsList and IsNearRingIdealEnumerator ],
1645	1,
1646    e -> Size( e!.additiveGroup ) );
1647
1648InstallMethod(
1649	\[\],
1650	true,
1651	[ IsList and IsNearRingIdealEnumerator, IsPosInt ],
1652	1,
1653  function( e, pos )
1654  local groupElement, group, mult, fam;
1655    group := e!.additiveGroup;
1656    fam := e!.elementsInfo;
1657
1658    groupElement := Enumerator(group)[pos];
1659
1660    return NearRingElementByGroupRep( fam, groupElement );
1661  end );
1662
1663InstallMethod(
1664	Position,
1665	true,
1666	[ IsList and IsNearRingIdealEnumerator,
1667		IsNearRingElement, IsZeroCyc ],
1668	1,
1669  function( e, emnrelm, zero )
1670    return Position(Enumerator(e!.additiveGroup),emnrelm![1],zero);
1671  end );
1672
1673InstallMethod(
1674	ViewObj,
1675	true,
1676	[ IsNearRingIdealEnumerator ],
1677	1,
1678  function( G )
1679    Print( "<enumerator of near-ring ideal>" );
1680  end );
1681
1682InstallMethod(
1683	PrintObj,
1684	true,
1685	[ IsNearRingIdealEnumerator ],
1686	1,
1687  function( G )
1688    Print( "<enumerator of near-ring ideal>" );
1689  end );
1690
1691#############################################################################
1692##
1693#M  IsPrimeNearRingIdeal			For NearRing ideals
1694
1695InstallMethod(
1696	IsPrimeNearRingIdeal,
1697	"brute force method",
1698	true,
1699	[IsNRI and IsNearRingIdeal ],
1700	0,
1701  function ( ideal )
1702
1703  local ideal_list, size, N;
1704
1705  size := Size( ideal );
1706  N := Parent( ideal );
1707  ideal_list := Filtered( AsSSortedList( NearRingIdeals( N ) ),
1708    id -> Size( id ) >= size and id <> ideal );
1709
1710  return
1711  ForAll( ideal_list, I1 ->
1712    ForAll( ideal_list, I2 ->
1713      ForAny( I1, e1 ->
1714        ForAny( I2, e2 ->
1715          not ( e1 * e2 in ideal )  ) ) ) );
1716
1717  end );
1718
1719#############################################################################
1720##
1721#M  IsMaximalNearRingIdeal			For nearring ideals
1722
1723InstallMethod(
1724	IsMaximalNearRingIdeal,
1725	"simple factor?",
1726	true,
1727	[IsNRI and IsNearRingIdeal ],
1728	20,
1729  function ( ideal )
1730    if Size(ideal)=0 or Size(ideal)=Size(Parent(ideal)) then
1731	return false;
1732    else
1733	TryNextMethod();
1734    fi;
1735  end );
1736
1737InstallMethod(
1738	IsMaximalNearRingIdeal,
1739	"simple factor?",
1740	true,
1741	[IsNRI and IsNearRingIdeal ],
1742	10,
1743  function ( ideal )
1744    return IsSimpleNearRing ( FactorNearRing( Parent( ideal ), ideal ) );
1745  end );
1746
1747InstallMethod(
1748	IsMaximalNearRingIdeal,
1749	"brute force method",
1750	true,
1751	[IsNRI and IsNearRingIdeal ],
1752	0,
1753  function ( ideal )
1754
1755  local ideal_list, size, N;
1756
1757  size := Size( ideal );
1758  N := Parent( ideal );
1759  ideal_list := AsSSortedList( NearRingIdeals( N ) );
1760
1761  return
1762  not ForAny( ideal_list, id -> Size( id ) > size and Size( id ) < Size( N ) and
1763        ForAll( ideal, e -> e in id ) );
1764
1765  end );
1766
1767#############################################################################
1768##
1769#M  NoetherianQuotient2( <NR>, <L>, <SubNR> )
1770##
1771#
1772#InstallMethod(
1773#	NoetherianQuotient2,
1774#	"left ideals",
1775#	true,
1776#	[IsNearRing, IsNRI and IsNearRingLeftIdeal, IsNearRing],
1777#	0,
1778#  function ( NR, L, SubNR )
1779#  local nq;
1780#    nq := Filtered( NR, n -> ForAll( SubNR, s -> n*s in L ) );
1781#    nq := Subgroup( GroupReduct(NR), List( nq, GroupElementRepOfNearRingElement ) );
1782#
1783#    return NearRingIdealBySubgroupNC( NR, nq );
1784#  end );
1785
1786#############################################################################
1787##
1788#M  IsSubset
1789##
1790
1791InstallMethod(
1792	IsSubset,
1793	"two NRIs second has right generators",
1794	IsIdenticalObj,
1795	[IsNRI and IsNearRingIdeal,
1796		IsNRI and HasGeneratorsOfNearRingRightIdeal],
1797	0,
1798  function ( I, S )
1799    return ForAll( GeneratorsOfNearRingLeftIdeal( S ), gen -> gen in I );
1800  end );
1801
1802InstallMethod(
1803	IsSubset,
1804	"two NRIs second has right generators",
1805	IsIdenticalObj,
1806	[IsNRI and IsNearRingRightIdeal,
1807		IsNRI and HasGeneratorsOfNearRingRightIdeal],
1808	0,
1809  function ( I, S )
1810    return ForAll( GeneratorsOfNearRingRightIdeal( S ), gen -> gen in I );
1811  end );
1812
1813InstallMethod(
1814	IsSubset,
1815	"two NRIs second has left generators",
1816	IsIdenticalObj,
1817	[IsNRI and IsNearRingIdeal,
1818		IsNRI and HasGeneratorsOfNearRingLeftIdeal],
1819	0,
1820  function ( I, S )
1821    return ForAll( GeneratorsOfNearRingLeftIdeal( S ), gen -> gen in I );
1822  end );
1823
1824InstallMethod(
1825	IsSubset,
1826	"two NRIs second has left generators",
1827	IsIdenticalObj,
1828	[IsNRI and IsNearRingLeftIdeal,
1829		IsNRI and HasGeneratorsOfNearRingLeftIdeal],
1830	0,
1831  function ( I, S )
1832    return ForAll( GeneratorsOfNearRingLeftIdeal( S ), gen -> gen in I );
1833  end );
1834
1835InstallMethod(
1836	IsSubset,
1837	"two NRIs second has ideal generators",
1838	IsIdenticalObj,
1839	[IsNRI and IsNearRingIdeal,
1840		IsNRI and HasGeneratorsOfNearRingIdeal],
1841	0,
1842  function ( I, S )
1843    return ForAll( GeneratorsOfNearRingIdeal( S ), gen -> gen in I );
1844  end );
1845
1846#############################################################################
1847##
1848#M  GeneratorsOfNearRingIdeal
1849
1850InstallMethod(
1851	GeneratorsOfNearRingIdeal,
1852	"default",
1853	true,
1854	[IsNRI and IsNearRingIdeal],
1855	0,
1856  function( I )
1857    return List( GeneratorsOfGroup( GroupReduct( I ) ),
1858			g -> AsNearRingElement( Parent(I), g ) );
1859end );
1860
1861#############################################################################
1862##
1863#M  GeneratorsOfNearRingLeftIdeal
1864
1865InstallMethod(
1866	GeneratorsOfNearRingLeftIdeal,
1867	"default",
1868	true,
1869	[IsNRI and IsNearRingLeftIdeal],
1870	0,
1871  function( I )
1872    return List( GeneratorsOfGroup( GroupReduct( I ) ),
1873			g -> AsNearRingElement( Parent(I), g ) );
1874end );
1875
1876#############################################################################
1877##
1878#M  GeneratorsOfNearRingRightIdeal
1879
1880InstallMethod(
1881	GeneratorsOfNearRingRightIdeal,
1882	"default",
1883	true,
1884	[IsNRI and IsNearRingRightIdeal],
1885	0,
1886  function( I )
1887    return List( GeneratorsOfGroup( GroupReduct( I ) ),
1888			g -> AsNearRingElement( Parent(I), g ) );
1889end );
1890
1891#############################################################################
1892##
1893#M  AdditiveGenerators			for NRI's
1894
1895InstallMethod(
1896	AdditiveGenerators,
1897	"NRI",
1898	true,
1899	[IsNRI],
1900	0,
1901  function( I )
1902  local fam;
1903    fam := Parent( I )!.elementsInfo;
1904    return List( GeneratorsOfGroup( GroupReduct( I ) ),
1905			g -> NearRingElementByGroupRep( fam, g ) );
1906  end );
1907
1908
1909
1910
1911