1#############################################################################
2##
3##  GradedModule.gi             GradedModules package
4##
5##  Copyright 2007-2010, Mohamed Barakat, University of Kaiserslautern
6##                       Markus Lange-Hegermann, RWTH Aachen
7##
8##  Implementations for graded homalg modules.
9##
10#############################################################################
11
12####################################
13#
14# global variables:
15#
16####################################
17
18# a central place for configuration variables:
19
20InstallValue( HOMALG_GRADED_MODULES,
21        rec(
22            category := rec(
23                            description := "f.p. graded modules and their maps over computable graded rings",
24                            short_description := "_for_fp_graded_modules",
25                            TryPostDivideWithoutAids := true, # see homalg/ToolFunctors.gi
26                            MorphismConstructor := GradedMap,
27                            TypeOfElements := TheTypeHomalgModuleElement,
28                            InternalHom := GradedHom,
29                            InternalExt := GradedExt,
30                            ),
31            ModulesSave := [ ],
32            MorphismsSave := [ ],
33            # this sets the bound at which modules are cut of when computing ModuleOfGlobalSections.
34            # it should be zero to ensure that global sections sets the correct transformation
35            LowerTruncationBound := 0
36           )
37);
38
39####################################
40#
41# representations:
42#
43####################################
44
45DeclareRepresentation( "IsGradedModuleOrGradedSubmoduleRep",
46        IsHomalgGradedModule and
47        IsStaticFinitelyPresentedObjectOrSubobjectRep and
48        IsHomalgGradedRingOrGradedModuleRep,
49        [ ] );
50
51DeclareRepresentation( "IsGradedModuleRep",
52        IsGradedModuleOrGradedSubmoduleRep and
53        IsStaticFinitelyPresentedObjectRep,
54        [ "UnderlyingModule", "SetOfDegreesOfGenerators" ] );
55
56##
57DeclareRepresentation( "IsCategoryOfFinitelyPresentedGradedLeftModulesRep",
58        IsHomalgCategoryOfLeftObjectsRep and
59        IsCategoryOfGradedModules,
60        [ ] );
61
62##
63DeclareRepresentation( "IsCategoryOfFinitelyPresentedGradedRightModulesRep",
64        IsHomalgCategoryOfRightObjectsRep and
65        IsCategoryOfGradedModules,
66        [ ] );
67
68####################################
69#
70# families and types:
71#
72####################################
73
74# a new family:
75BindGlobal( "TheFamilyOfHomalgGradedModules",
76        NewFamily( "TheFamilyOfHomalgGradedModules" ) );
77
78# two new types:
79BindGlobal( "TheTypeHomalgGradedLeftModule",
80           NewType( TheFamilyOfHomalgGradedModules, IsHomalgLeftObjectOrMorphismOfLeftObjects and IsGradedModuleRep )
81          );
82
83BindGlobal( "TheTypeHomalgGradedRightModule",
84           NewType( TheFamilyOfHomalgGradedModules, IsHomalgRightObjectOrMorphismOfRightObjects and IsGradedModuleRep )
85          );
86
87# two new types:
88BindGlobal( "TheTypeCategoryOfFinitelyPresentedGradedLeftModules",
89        NewType( TheFamilyOfHomalgCategories,
90                IsCategoryOfFinitelyPresentedGradedLeftModulesRep ) );
91
92BindGlobal( "TheTypeCategoryOfFinitelyPresentedGradedRightModules",
93        NewType( TheFamilyOfHomalgCategories,
94                IsCategoryOfFinitelyPresentedGradedRightModulesRep ) );
95
96####################################
97#
98# methods for operations:
99#
100####################################
101
102##
103InstallMethod( MapHavingCertainGeneratorsAsItsImage,
104        "for two homalg modules, submodules, or maps",
105        [ IsGradedModuleRep, IsList ],
106
107  function( M, l )
108    local n, certain_part, mat;
109
110    return GradedMap( MapHavingCertainGeneratorsAsItsImage( UnderlyingModule( M ), l ), "create", M );
111
112end );
113
114##
115InstallMethod( LockObjectOnCertainPresentation,
116        "for homalg graded modules",
117        [ IsGradedModuleRep, IsInt ],
118
119  function( M, p )
120
121    ## first save the current setting
122    M!.LockObjectOnCertainPresentation := PositionOfTheDefaultPresentation( M );
123
124    SetPositionOfTheDefaultPresentation( M, p );
125
126    LockObjectOnCertainPresentation( UnderlyingModule( M ), p );
127
128end );
129
130##
131InstallMethod( LockObjectOnCertainPresentation,
132        "for homalg graded modules",
133        [ IsGradedModuleRep ],
134
135  function( M )
136
137    LockObjectOnCertainPresentation( M, PositionOfTheDefaultPresentation( M ) );
138
139end );
140
141##
142InstallMethod( UnlockObject,
143        "for homalg graded modules",
144        [ IsGradedModuleRep ],
145
146  function( M )
147
148    UnlockObject( UnderlyingModule( M ) );
149
150    ## first restore the saved settings
151    if IsBound( M!.LockObjectOnCertainPresentation ) then
152        SetPositionOfTheDefaultPresentation( M, M!.LockObjectOnCertainPresentation );
153        Unbind( M!.LockObjectOnCertainPresentation );
154    fi;
155
156end );
157
158##
159InstallMethod( UnderlyingModule,
160        "for homalg graded modules",
161        [ IsGradedModuleRep ],
162
163  function( M )
164
165    return M!.UnderlyingModule;
166
167end );
168
169##
170InstallMethod( SetOfDegreesOfGenerators,
171        "for homalg graded modules",
172        [ IsGradedModuleRep ],
173
174  function( M )
175
176    return  M!.SetOfDegreesOfGenerators;
177
178end );
179
180##
181InstallMethod( AnyParametrization,
182        "for homalg graded modules",
183        [ IsGradedModuleRep ],
184
185  function( M )
186    local par;
187
188    par := AnyParametrization( UnderlyingModule( M ) );
189    par := GradedMap( par, M, "create", HomalgRing( M ) );
190
191    Assert( 4, IsMorphism );
192    SetIsMorphism( par, true );
193
194    return par;
195
196end );
197
198##
199InstallMethod( MinimalParametrization,
200        "for homalg graded modules",
201        [ IsGradedModuleRep ],
202
203  function( M )
204    local par;
205
206    par := MinimalParametrization( UnderlyingModule( M ) );
207    par := GradedMap( par, M, "create", HomalgRing( M ) );
208
209    Assert( 4, IsMorphism );
210    SetIsMorphism( par, true );
211
212    return par;
213
214end );
215
216##
217InstallMethod( CurrentResolution,
218        "for graded modules",
219        [ IsInt, IsGradedModuleRep ],
220
221  function( q, M )
222  local S, res, degrees, deg, len, CEpi, d_j, F_j, graded_res, j;
223
224    S := HomalgRing( M );
225
226    res := Resolution( q, UnderlyingModule( M ) );
227    degrees := ObjectDegreesOfComplex( res );
228    len := Length( degrees );
229
230    if HasCurrentResolution( M ) then
231      graded_res := CurrentResolution( M );
232      deg := ObjectDegreesOfComplex( graded_res );
233      j := Length( deg );
234      j := deg[j];
235      d_j := CertainMorphism( graded_res, j );
236    else
237      j := res!.degrees[2];
238      CEpi := GradedMap( CokernelEpi( res!.(j) ), "create", M );
239      Assert( 3, IsMorphism( CEpi ) );
240      SetIsMorphism( CEpi, true );
241      d_j := GradedMap( res!.(j), "create", Source( CEpi ), S );
242      Assert( 3, IsMorphism( d_j ) );
243      SetIsMorphism( d_j, true );
244      SetCokernelEpi( d_j, CEpi );
245      graded_res := HomalgComplex( d_j );
246      SetCurrentResolution( M, graded_res );
247    fi;
248
249    F_j := Source( d_j );
250
251    if len >= j+2 then
252      for j in [ res!.degrees[j+2] .. res!.degrees[len] ] do
253        if IsIdenticalObj( F_j, 0 * S ) or IsIdenticalObj( F_j, S * 0 ) then
254          # take care not to create the graded zero morphism between distinguished zero modules again each step
255          d_j := TheZeroMorphism( F_j, F_j );
256          Add( graded_res, d_j );
257          # no need for resetting F_j, since all other modules will be zero, too
258        else
259          d_j := GradedMap( res!.(j), "create", F_j, S );
260          Assert( 3, IsMorphism( d_j ) );
261          SetIsMorphism( d_j, true );
262          Add( graded_res, d_j );
263          F_j := Source( d_j );
264        fi;
265      od;
266    fi;
267
268    if HasIsAcyclic( res ) and IsAcyclic( res ) then
269      SetIsAcyclic( graded_res, true );
270    fi;
271    if HasIsRightAcyclic( res ) and HasIsRightAcyclic( res ) then
272      SetIsRightAcyclic( graded_res, true );
273    fi;
274
275    if IsBound( res!.LengthOfResolution ) then
276      graded_res!.LengthOfResolution := res!.LengthOfResolution;
277    fi;
278
279    return graded_res;
280
281end );
282
283##
284InstallMethod( PresentationMorphism,
285        "for homalg modules",
286        [ IsGradedModuleRep, IsPosInt ],
287
288  function( M, pos )
289    local rel, pres, epi;
290
291    if IsBound(M!.PresentationMorphisms.( pos )) then
292        return M!.PresentationMorphisms.( pos );
293    fi;
294
295    pres := PresentationMorphism( UnderlyingModule( M ), pos );
296
297    epi := GradedMap( CokernelEpi( pres ), "create", M );
298
299    Assert( 4, IsMorphism( epi ) );
300    SetIsMorphism( epi, true );
301
302    pres := GradedMap( pres, "create", Source( epi ) );
303
304    Assert( 4, IsMorphism( pres ) );
305    SetIsMorphism( pres, true );
306
307    SetCokernelEpi( pres, epi );
308
309    M!.PresentationMorphisms.( pos ) := pres;
310
311    return pres;
312
313end );
314
315##  <#GAPDoc Label="MonomialMap">
316##  <ManSection>
317##    <Oper Arg="d, M" Name="MonomialMap"/>
318##    <Returns>a &homalg; map</Returns>
319##    <Description>
320##      The map from a free graded module onto all degree <A>d</A> monomial generators
321##      of the finitely generated &homalg; module <A>M</A>.
322##      <#Include Label="MonomialMap:example">
323##    </Description>
324##  </ManSection>
325##  <#/GAPDoc>
326InstallMethod( MonomialMap,
327        "for homalg modules",
328        [ IsInt, IsGradedModuleRep ],
329
330  function( d, M )
331    local S, degrees, mon, i, result;
332
333    S := HomalgRing( M );
334
335    degrees := DegreesOfGenerators( M );
336
337    degrees := List( degrees, HomalgElementToInteger );
338
339    mon := rec( );
340
341    for i in Set( degrees ) do
342        mon.(String( d - i )) := MonomialMatrix( d - i, S );
343    od;
344
345    mon := List( degrees, i -> mon.(String(d - i)) );
346
347    if IsHomalgRightObjectOrMorphismOfRightObjects( M ) then
348        mon := List( mon, Involution );
349    fi;
350
351    if mon <> [ ] then
352        mon := DiagMat( mon );
353    else
354        mon := HomalgZeroMatrix( 0, 0, UnderlyingNonGradedRing( S ) );
355    fi;
356
357    mon := MatrixOverGradedRing( mon, S );
358
359    result:= GradedMap( mon, "free", M );
360
361    Assert( 4, IsMorphism( result ) );
362    SetIsMorphism( result, true );
363
364    return result;
365
366end );
367
368##
369InstallMethod( MonomialMap,
370        "for homalg modules",
371        [ IsHomalgElement, IsGradedModuleRep ],
372
373  function( d, M )
374
375    return MonomialMap( HomalgElementToInteger( d ), M );
376
377end );
378
379##  <#GAPDoc Label="RandomMatrix">
380##  <ManSection>
381##    <Oper Arg="S,T" Name="RandomMatrix"/>
382##    <Returns>a &homalg; matrix</Returns>
383##    <Description>
384##      A random matrix between the graded source module <A>S</A> and the graded target module <A>T</A>.
385##      <#Include Label="RandomMatrix:example">
386##    </Description>
387##  </ManSection>
388##  <#/GAPDoc>
389##
390InstallMethod( RandomMatrix,
391        "for homalg modules",
392        [ IsHomalgGradedModule, IsHomalgGradedModule ],
393
394  function( S, T )
395    local left, degreesS, degreesT, R;
396
397    left := IsHomalgLeftObjectOrMorphismOfLeftObjects( S );
398
399    if IsHomalgLeftObjectOrMorphismOfLeftObjects( T ) <> left then
400        Error( "both modules must either be left or either be right modules" );
401    fi;
402
403    degreesS := DegreesOfGenerators( S );
404    degreesT := DegreesOfGenerators( T );
405
406    R := HomalgRing( S );
407
408    if left then
409        return RandomMatrixBetweenGradedFreeLeftModules( degreesS, degreesT, R );
410    else
411        return RandomMatrixBetweenGradedFreeRightModules( degreesT, degreesS, R );
412    fi;
413
414end );
415
416##
417InstallMethod( \/,        ### defines: / (SubfactorModule)
418        "for a homalg matrix and a graded module",
419        [ IsHomalgMatrix, IsGradedModuleOrGradedSubmoduleRep ], 10000,
420
421  function( mat, M )
422#     local B, N, gen, S, SF;
423    local mat2, res;
424
425    if IsHomalgMatrixOverGradedRingRep( mat ) then
426      mat2 := UnderlyingMatrixOverNonGradedRing( mat );
427    else
428      mat2 := mat;
429    fi;
430
431    res := mat2 / UnderlyingModule( M );
432
433    return GradedModule( res, HomalgRing( M ) );
434
435end );
436
437##
438InstallMethod( \/,        ## needed by _Functor_Kernel_OnObjects since SyzygiesGenerators returns a set of relations
439        "for a set of homalg relations and a graded module",
440        [ IsHomalgRelations, IsGradedModuleOrGradedSubmoduleRep ], 10000,
441
442  function( rel, M )
443
444    return MatrixOfRelations( rel ) / M;
445
446end );
447
448##
449InstallMethod( Annihilator,
450        "for homalg relations",
451        [ IsHomalgMatrixOverGradedRingRep, IsHomalgRelations ],
452
453  function( mat, rel )
454
455    return GradedModule( Annihilator( UnderlyingMatrixOverNonGradedRing( mat ), rel ), HomalgRing( mat ) );
456
457end );
458
459##
460InstallMethod( CompleteComplexByLinearResolution,
461        "for homalg cocomplexes",
462        [ IsInt, IsCocomplexOfFinitelyPresentedObjectsRep ],
463
464  function( n, C )
465    local i, phi, S;
466
467    for i in [ 1 .. n ] do
468
469        phi := LowestDegreeMorphism( C );
470
471        S := Source( phi );
472
473        phi := MatrixOfMap( phi );
474
475        if IsHomalgLeftObjectOrMorphismOfLeftObjects( C ) then
476            phi := LinearSyzygiesGeneratorsOfRows( phi );
477        else
478            phi := LinearSyzygiesGeneratorsOfColumns( phi );
479        fi;
480
481        phi := GradedMap( phi, "free", S );
482
483        Assert( 4, IsMorphism( phi ) );
484        SetIsMorphism( phi, true );
485
486        Add( phi, C );
487    od;
488
489    return C;
490
491end );
492
493##
494InstallMethod( FittingIdeal,
495        "for homalg graded modules",
496        [ IsInt, IsGradedModuleRep ],
497
498  function( i, M )
499    local Fitt, Fitt_i;
500
501    if not IsBound( M!.FittingIdeals ) then
502        M!.FittingIdeals := rec( );
503    fi;
504
505    Fitt := M!.FittingIdeals;
506
507    if IsBound( Fitt.(String( i )) ) then
508        return Fitt.(String( i ));
509    fi;
510
511    Fitt_i := FittingIdeal( i, UnderlyingModule( M ) );
512
513    Fitt_i := GradedModule( Fitt_i, HomalgRing( M ) );
514
515    Fitt.(String( i )) := Fitt_i;
516
517    return Fitt_i;
518
519end );
520
521####################################
522#
523# constructors:
524#
525####################################
526
527##
528InstallMethod( HomalgCategory,
529        "constructor for module categories",
530        [ IsHomalgGradedRing, IsString ],
531
532  function( R, parity )
533    local A;
534
535    if parity = "right" and IsBound( R!.category_of_fp_graded_right_modules ) then
536        return R!.category_of_fp_graded_right_modules;
537    elif IsBound( R!.category_of_fp_graded_left_modules ) then
538        return R!.category_of_fp_graded_left_modules;
539    fi;
540
541    A := ShallowCopy( HOMALG_GRADED_MODULES.category );
542    A.containers := rec( );
543    A.ring := R;
544
545    if parity = "right" then
546        Objectify( TheTypeCategoryOfFinitelyPresentedGradedRightModules, A );
547        R!.category_of_fp_graded_right_modules := A;
548    else
549        Objectify( TheTypeCategoryOfFinitelyPresentedGradedLeftModules, A );
550        R!.category_of_fp_graded_left_modules := A;
551    fi;
552
553    return A;
554
555end );
556
557##
558InstallMethod( GradedModule,
559        "for a homalg module",
560        [ IsFinitelyPresentedModuleRep, IsList, IsHomalgGradedRingRep ],
561
562  function( module, degrees, S )
563    local degree_group, weights, i, GradedModule, setofdegrees, type, ring;
564
565    if IsGradedModuleRep( module ) then
566        return module;
567    fi;
568
569#     if not Length( degrees ) = 0 then
570#
571#         if not IsHomalgElement( degrees[ 1 ] ) and not Set( degrees ) = [ 0 ] then
572#
573#             weights := GeneratingElements( DegreeGroup( S ) );
574#
575#             if not IsInt( degrees[ 1 ] ) then
576#
577#                 if not Length( weights ) = Length( degrees[ 1 ] ) then
578#                     Error(" number of generators of DegreeGroup does not match length of degrees.");
579#                 fi;
580#
581#             fi;
582#
583#             for i in [ 1 .. Length( weights ) ] do
584#
585#                 degrees[ i ] := degrees[ i ] * weights[ i ];
586#
587#             od;
588#
589#             degrees := Flat( degrees );
590#
591#         fi;
592#
593#     fi;
594
595    degree_group := DegreeGroup( S );
596
597    if not Length( degrees ) = 0 then
598
599        weights := GeneratingElements( degree_group );
600
601        if IsInt( degrees[ 1 ] ) then
602
603            if Set( degrees ) = [ 0 ] then
604
605                degrees := ListWithIdenticalEntries( Length( degrees ), TheZeroElement( degree_group ) );
606
607            elif Length( weights ) = 1 then
608
609                degrees := List( degrees, HomalgElementToInteger );
610
611                degrees := List( degrees, i -> i * weights[ 1 ] );
612
613            else
614
615                Error( "input weights do not match generators of degree group" );
616
617            fi;
618
619        elif IsList( degrees[ 1 ] ) then
620
621            if Length( degrees[ 1 ] ) = Length( weights ) then
622
623                degrees := List( degrees, i -> HomalgModuleElement( i, degree_group ) );
624
625            else
626
627                Error( "something went terribly wrong" );
628
629            fi;
630
631        elif not IsHomalgElement( degrees[ 1 ] ) then
632
633            Error( "wrong input degrees" );
634
635        fi;
636
637    fi;
638
639    if IsBound( module!.GradedVersions ) then
640        for i in module!.GradedVersions do
641            if IsIdenticalObj( HomalgRing( i ), S ) and degrees = DegreesOfGenerators( i ) then
642                return i;
643            fi;
644        od;
645    fi;
646
647    if not IsIdenticalObj( UnderlyingNonGradedRing( S ), HomalgRing( module ) ) and
648       not IsIdenticalObj( S, HomalgRing( module ) ) then
649        Error( "Underlying rings do not match" );
650    fi;
651
652    if not ( Length( degrees ) = NrGenerators( module ) ) then
653        Error( "The number of degrees ", Length( degrees ),
654               " has to equal the number of Generators ", NrGenerators( module ), "\n" );
655    fi;
656
657    if IsBound( module!.distinguished ) and module!.distinguished and HasIsZero( module ) and IsZero( module ) then
658        if IsHomalgLeftObjectOrMorphismOfLeftObjects( module ) then
659            if IsBound( S!.ZeroLeftModule ) then
660                return S!.ZeroLeftModule;
661            fi;
662        else
663            if IsBound( S!.ZeroRightModule ) then
664                return S!.ZeroRightModule;
665            fi;
666        fi;
667    fi;
668
669    setofdegrees := CreateSetOfDegreesOfGenerators( degrees, PositionOfTheDefaultPresentation( module ) );
670
671    GradedModule := rec(
672                        adjective := "graded",
673                        string := "module",
674                        string_plural := "modules",
675                        ring := S,
676                        Resolutions := rec( ),
677                        PresentationMorphisms := rec(),
678                        SetOfDegreesOfGenerators := setofdegrees
679                        );
680
681    if IsHomalgLeftObjectOrMorphismOfLeftObjects( module ) then
682        type := TheTypeHomalgGradedLeftModule;
683        ring := LeftActingDomain;
684        GradedModule.category := HomalgCategory( S, "left" );
685    else
686        type := TheTypeHomalgGradedRightModule;
687        ring := RightActingDomain;
688        GradedModule.category := HomalgCategory( S, "right" );
689    fi;
690
691    ## Objectify:
692    ObjectifyWithAttributes(
693            GradedModule, type,
694            UnderlyingModule, module,
695            ring, S
696            );
697
698    if IsBound( module!.distinguished ) and module!.distinguished and HasIsZero( module ) and IsZero( module ) then
699        if IsHomalgLeftObjectOrMorphismOfLeftObjects( module ) then
700            GradedModule!.distinguished := true;
701            S!.ZeroLeftModule := GradedModule;
702        else
703            GradedModule!.distinguished := true;
704            S!.ZeroRightModule := GradedModule;
705        fi;
706    fi;
707
708    MatchPropertiesAndAttributes( GradedModule, module, LIGrMOD.exchangeable_properties, LIGrMOD.exchangeable_attributes );
709
710#    if AssertionLevel() >= 10 then
711#        for i in [ 1 .. Length( HOMALG_GRADED_MODULES.ModulesSave ) ] do
712#            Assert( 10,
713#              not IsIdenticalObj( UnderlyingModule( HOMALG_GRADED_MODULES.ModulesSave[i] ), UnderlyingModule( GradedModule ) )
714#              or IsIdenticalObj( HOMALG_GRADED_MODULES.ModulesSave[i], GradedModule ),
715#            "a module is about to be graded (at least) twice. This might be intentionally. Set AssertionLevel to 11 to get an error message" );
716#            Assert( 11,
717#              not IsIdenticalObj( UnderlyingModule( HOMALG_GRADED_MODULES.ModulesSave[i] ), UnderlyingModule( GradedModule ) )
718#              or IsIdenticalObj( HOMALG_GRADED_MODULES.ModulesSave[i], GradedModule ) );
719#        od;
720#        Add( HOMALG_GRADED_MODULES.ModulesSave, GradedModule );
721#    fi;
722
723    if not IsBound( module!.GradedVersions ) then
724        module!.GradedVersions := [ GradedModule ];
725    else
726        Add( module!.GradedVersions, GradedModule );
727    fi;
728
729    return GradedModule;
730
731end );
732
733##
734InstallMethod( GradedModule,
735        "for a homalg module",
736        [ IsFinitelyPresentedModuleRep, IsInt, IsHomalgGradedRingRep ],
737
738  function( module, d, S )
739    local gens;
740
741    gens := GeneratingElements( DegreeGroup( S ) );
742
743    if Length( gens ) > 0 then
744
745        gens := gens[ 1 ];
746
747    else
748
749        gens := TheZeroElement( DegreeGroup( S ) );
750
751    fi;
752
753    return GradedModule( module, ListWithIdenticalEntries( NrGenerators( module ), d * gens ), S );
754end );
755
756##
757InstallMethod( GradedModule,
758        "for a homalg module",
759        [ IsFinitelyPresentedModuleRep, IsHomalgElement, IsHomalgGradedRingRep ],
760
761  function( module, d, S )
762
763    ## User should take care that d is element in the DegreeGroup of s.
764    return GradedModule( module, ListWithIdenticalEntries( NrGenerators( module ), d ), S );
765end );
766
767##
768InstallMethod( GradedModule,
769        "for a homalg module",
770        [ IsFinitelyPresentedModuleRep, IsHomalgGradedRingRep ],
771
772  function( module, S )
773    return GradedModule( module, TheZeroElement( DegreeGroup( S ) ), S );
774end );
775
776##
777InstallMethod( GradedModule,
778        "for a homalg submodule",
779        [ IsFinitelyPresentedSubmoduleRep, IsHomalgGradedRingRep ],
780
781  function( J, S )
782    local map;
783
784    map := MorphismHavingSubobjectAsItsImage( J );
785
786    map := GradedMap( map, "create", ListWithIdenticalEntries( NrGenerators( Range( map ) ), TheZeroElement( DegreeGroup( S ) ) ), S );
787
788    return ImageSubobject( map );
789
790end );
791
792##
793InstallMethod( LeftPresentationWithDegrees,
794        "constructor for homalg graded modules",
795        [ IsHomalgMatrix, IsList, IsHomalgGradedRingRep ],
796
797  function( mat, degrees, S )
798    local M;
799
800    if Length( degrees ) <> NrColumns( mat ) then
801        Error( "the number of degrees must coincide with the number of columns\n" );
802    fi;
803
804    if IsHomalgMatrixOverGradedRingRep( mat ) then
805        M := LeftPresentation( UnderlyingMatrixOverNonGradedRing( mat ) );
806    else
807        M := LeftPresentation( mat );
808    fi;
809
810    return GradedModule( M, degrees, S );
811
812end );
813
814##
815InstallMethod( LeftPresentationWithDegrees,
816        "constructor for homalg graded modules",
817        [ IsHomalgMatrixOverGradedRingRep, IsList ],
818
819  function( mat, degrees )
820
821    return LeftPresentationWithDegrees( mat, degrees, HomalgRing( mat ) );
822
823end );
824
825##
826InstallMethod( LeftPresentationWithDegrees,
827        "constructor for homalg graded modules",
828        [ IsHomalgMatrix, IsInt, IsHomalgGradedRingRep ],
829
830  function( mat, degree, S )
831    local gens;
832
833    gens := GeneratingElements( DegreeGroup( S ) );
834
835    if Length( gens ) > 0 then
836
837        gens := gens[ 1 ];
838
839    else
840
841        gens := TheZeroElement( DegreeGroup( S ) );
842
843    fi;
844
845    return LeftPresentationWithDegrees( mat, ListWithIdenticalEntries( NrColumns( mat ), degree * gens ), S );
846
847end );
848
849##
850InstallMethod( LeftPresentationWithDegrees,
851        "constructor for homalg graded modules",
852        [ IsHomalgMatrix, IsHomalgElement, IsHomalgGradedRingRep ],
853
854  function( mat, degree, S )
855
856    return LeftPresentationWithDegrees( mat, ListWithIdenticalEntries( NrColumns( mat ), degree ), S );
857
858end );
859
860##
861InstallMethod( LeftPresentationWithDegrees,
862        "constructor for homalg graded modules",
863        [ IsHomalgMatrixOverGradedRingRep, IsInt ],
864
865  function( mat, degree )
866    local ring, gens;
867
868    ring := HomalgRing( mat );
869
870    gens := GeneratingElements( DegreeGroup( ring ) );
871
872    if Length( gens ) > 0 then
873
874        gens := gens[ 1 ];
875
876    else
877
878        gens := TheZeroElement( DegreeGroup( ring ) );
879
880    fi;
881
882    return LeftPresentationWithDegrees( mat, degree * gens, ring );
883
884end );
885
886##
887InstallMethod( LeftPresentationWithDegrees,
888        "constructor for homalg graded modules",
889        [ IsHomalgMatrixOverGradedRingRep, IsHomalgElement ],
890
891  function( mat, degree )
892
893    return LeftPresentationWithDegrees( mat, degree, HomalgRing( mat ) );
894
895end );
896
897##
898InstallMethod( LeftPresentationWithDegrees,
899        "constructor for homalg graded modules",
900        [ IsHomalgMatrix, IsHomalgGradedRingRep ],
901
902  function( mat, S )
903
904    return LeftPresentationWithDegrees( mat, ListWithIdenticalEntries( NrColumns( mat ), TheZeroElement( DegreeGroup( S ) ) ), S );
905
906end );
907
908##
909InstallMethod( LeftPresentationWithDegrees,
910        "constructor for homalg graded modules",
911        [ IsHomalgMatrixOverGradedRingRep ],
912
913  function( mat )
914
915    return LeftPresentationWithDegrees( mat, HomalgRing( mat ) );
916
917end );
918
919##
920InstallMethod( RightPresentationWithDegrees,
921        "constructor for homalg graded modules",
922        [ IsHomalgMatrix, IsList, IsHomalgGradedRingRep ],
923
924  function( mat, degrees, S )
925    local M;
926
927    if Length( degrees ) <> NrRows( mat ) then
928        Error( "the number of degrees must coincide with the number of rows\n" );
929    fi;
930
931    if IsHomalgMatrixOverGradedRingRep( mat ) then
932        M := RightPresentation( UnderlyingMatrixOverNonGradedRing( mat ) );
933    else
934        M := RightPresentation( mat );
935    fi;
936
937    return GradedModule( M, degrees, S );
938
939end );
940
941##
942InstallMethod( RightPresentationWithDegrees,
943        "constructor for homalg graded modules",
944        [ IsHomalgMatrixOverGradedRingRep, IsList ],
945
946  function( mat, degrees )
947
948    return RightPresentationWithDegrees( mat, degrees, HomalgRing( mat ) );
949
950end );
951
952##
953InstallMethod( RightPresentationWithDegrees,
954        "constructor for homalg graded modules",
955        [ IsHomalgMatrix, IsInt, IsHomalgGradedRingRep ],
956
957  function( mat, degree, S )
958    local gens;
959
960    gens := GeneratingElements( DegreeGroup( S ) );
961
962    if Length( gens ) > 0 then
963
964        gens := gens[ 1 ];
965
966    else
967
968        gens := TheZeroElement( DegreeGroup( S ) );
969
970    fi;
971
972    return RightPresentationWithDegrees( mat, ListWithIdenticalEntries( NrRows( mat ), degree * gens ), S );
973
974end );
975
976##
977InstallMethod( RightPresentationWithDegrees,
978        "constructor for homalg graded modules",
979        [ IsHomalgMatrix, IsHomalgElement, IsHomalgGradedRingRep ],
980
981  function( mat, degree, S )
982
983    return RightPresentationWithDegrees( mat, ListWithIdenticalEntries( NrRows( mat ), degree ), S );
984
985end );
986
987##
988InstallMethod( RightPresentationWithDegrees,
989        "constructor for homalg graded modules",
990        [ IsHomalgMatrixOverGradedRingRep, IsInt ],
991
992  function( mat, degree )
993
994    return RightPresentationWithDegrees( mat, degree, HomalgRing( mat ) );
995
996end );
997
998##
999InstallMethod( RightPresentationWithDegrees,
1000        "constructor for homalg graded modules",
1001        [ IsHomalgMatrix, IsHomalgGradedRingRep ],
1002
1003  function( mat, S )
1004
1005    return RightPresentationWithDegrees( mat, ListWithIdenticalEntries( NrRows( mat ), TheZeroElement( DegreeGroup( S ) ) ), S );
1006
1007end );
1008
1009##
1010InstallMethod( RightPresentationWithDegrees,
1011        "constructor for homalg graded modules",
1012        [ IsHomalgMatrixOverGradedRingRep ],
1013
1014  function( mat )
1015
1016    return RightPresentationWithDegrees( mat, HomalgRing( mat ) );
1017
1018end );
1019
1020##
1021InstallMethod( FreeLeftModuleWithDegrees,
1022        "constructor for homalg graded free modules",
1023        [ IsHomalgGradedRingRep, IsList ],
1024
1025  function( S, degrees )
1026
1027    return GradedModule( HomalgFreeLeftModule( Length( degrees ), UnderlyingNonGradedRing( S ) ), degrees, S );
1028
1029end );
1030
1031##
1032InstallMethod( FreeLeftModuleWithDegrees,
1033        "constructor for homalg graded free modules",
1034        [ IsList, IsHomalgGradedRingRep ],
1035
1036  function( degrees, S )
1037
1038    return GradedModule( HomalgFreeLeftModule( Length( degrees ), UnderlyingNonGradedRing( S ) ), degrees, S );
1039
1040end );
1041
1042##
1043InstallMethod( FreeLeftModuleWithDegrees,
1044        "constructor for homalg graded free modules",
1045        [ IsHomalgRing, IsList ],
1046
1047  function( S, degrees )
1048
1049    return LeftPresentationWithDegrees( HomalgZeroMatrix( 0, Length( degrees ), S ), degrees );
1050
1051end );
1052
1053##
1054InstallMethod( FreeLeftModuleWithDegrees,
1055        "constructor for homalg graded free modules",
1056        [ IsInt, IsHomalgRing, IsInt ],
1057
1058  function( rank, S, degree )
1059
1060    return FreeLeftModuleWithDegrees( S, ListWithIdenticalEntries( rank, degree ) );
1061
1062end );
1063
1064InstallMethod( FreeLeftModuleWithDegrees,
1065        "constructor for homalg graded free modules",
1066        [ IsInt, IsHomalgRing, IsHomalgElement ],
1067
1068  function( rank, S, degree )
1069
1070    return FreeLeftModuleWithDegrees( S, ListWithIdenticalEntries( rank, degree ) );
1071
1072end );
1073
1074##
1075InstallMethod( FreeLeftModuleWithDegrees,
1076        "constructor for homalg graded free modules",
1077        [ IsInt, IsHomalgRing ],
1078
1079  function( rank, S )
1080
1081    return FreeLeftModuleWithDegrees( rank, S, 0 );
1082
1083end );
1084
1085##
1086InstallMethod( FreeRightModuleWithDegrees,
1087        "constructor for homalg graded free modules",
1088        [ IsHomalgGradedRingRep, IsList ],
1089
1090  function( S, degrees )
1091
1092    return GradedModule( HomalgFreeRightModule( Length( degrees ), UnderlyingNonGradedRing( S ) ), degrees, S );
1093
1094end );
1095
1096##
1097InstallMethod( FreeRightModuleWithDegrees,
1098        "constructor for homalg graded free modules",
1099        [ IsList, IsHomalgGradedRingRep ],
1100
1101  function( degrees, S )
1102
1103    return GradedModule( HomalgFreeRightModule( Length( degrees ), UnderlyingNonGradedRing( S ) ), degrees, S );
1104
1105end );
1106
1107##
1108InstallMethod( FreeRightModuleWithDegrees,
1109        "constructor for homalg graded free modules",
1110        [ IsHomalgRing, IsList ],
1111
1112  function( S, degrees )
1113
1114    return RightPresentationWithDegrees( HomalgZeroMatrix( Length( degrees ), 0, S ), degrees );
1115
1116end );
1117
1118##
1119InstallMethod( FreeRightModuleWithDegrees,
1120        "constructor for homalg graded free modules",
1121        [ IsInt, IsHomalgRing, IsInt ],
1122
1123  function( rank, S, degree )
1124
1125    return FreeRightModuleWithDegrees( S, ListWithIdenticalEntries( rank, degree ) );
1126
1127end );
1128
1129InstallMethod( FreeRightModuleWithDegrees,
1130        "constructor for homalg graded free modules",
1131        [ IsInt, IsHomalgRing, IsHomalgElement ],
1132
1133  function( rank, S, degree )
1134
1135    return FreeRightModuleWithDegrees( S, ListWithIdenticalEntries( rank, degree ) );
1136
1137end );
1138
1139##
1140InstallMethod( FreeRightModuleWithDegrees,
1141        "constructor for homalg graded free modules",
1142        [ IsInt, IsHomalgRing ],
1143
1144  function( rank, S )
1145
1146    return FreeRightModuleWithDegrees( rank, S, 0 );
1147
1148end );
1149
1150##
1151InstallMethod( ZeroLeftModule,
1152        "for homalg rings",
1153        [ IsHomalgGradedRingRep ],
1154
1155  function( S )
1156
1157    if IsBound(S!.ZeroLeftModule) then
1158        return S!.ZeroLeftModule;
1159    fi;
1160
1161    return GradedModule( 0 * UnderlyingNonGradedRing( S ), S );
1162
1163end );
1164
1165##
1166InstallMethod( ZeroRightModule,
1167        "for homalg rings",
1168        [ IsHomalgGradedRingRep ],
1169
1170  function( S )
1171
1172    if IsBound(S!.ZeroRightModule) then
1173        return S!.ZeroRightModule;
1174    fi;
1175
1176    return GradedModule( UnderlyingNonGradedRing( S ) * 0, S );
1177
1178end );
1179
1180##
1181InstallMethod( PresentationWithDegrees,
1182        "constructor for homalg graded modules",
1183        [ IsGeneratorsOfFinitelyGeneratedModuleRep,
1184          IsRelationsOfFinitelyPresentedModuleRep,
1185          IsList,
1186          IsHomalgGradedRingRep ],
1187
1188  function( gen, rel, degrees, S )
1189    local module;
1190
1191    module := Presentation( gen, rel );
1192
1193    return GradedModule( module, degrees, S );
1194
1195end );
1196
1197##
1198InstallMethod( PresentationWithDegrees,
1199        "constructor for homalg graded modules",
1200        [ IsGeneratorsOfFinitelyGeneratedModuleRep,
1201          IsRelationsOfFinitelyPresentedModuleRep,
1202          IsInt,
1203          IsHomalgGradedRingRep ],
1204
1205  function( gen, rel, degree, S )
1206    local module, degree_group;
1207
1208    degree_group := DegreeGroup( S );
1209
1210    module := Presentation( gen, rel );
1211
1212    return GradedModule( module, HomalgModuleElement( [ degree ], degree_group ), S );
1213
1214end );
1215
1216##
1217InstallMethod( PresentationWithDegrees,
1218        "constructor for homalg graded modules",
1219        [ IsGeneratorsOfFinitelyGeneratedModuleRep,
1220          IsRelationsOfFinitelyPresentedModuleRep,
1221          IsHomalgElement,
1222          IsHomalgGradedRingRep ],
1223
1224  function( gen, rel, degree, S )
1225    local module;
1226
1227    module := Presentation( gen, rel );
1228
1229    return GradedModule( module, degree, S );
1230
1231end );
1232
1233##
1234InstallMethod( PresentationWithDegrees,
1235        "constructor for homalg graded modules",
1236        [ IsGeneratorsOfFinitelyGeneratedModuleRep,
1237          IsRelationsOfFinitelyPresentedModuleRep,
1238          IsHomalgGradedRingRep ],
1239
1240  function( gen, rel, S )
1241    local module;
1242
1243    module := Presentation( gen, rel );
1244
1245    return GradedModule( module, S );
1246
1247end );
1248
1249##
1250InstallOtherMethod( Zero,
1251        "for homalg modules",
1252        [ IsGradedModuleRep and IsHomalgRightObjectOrMorphismOfRightObjects ], 10001,  ## FIXME: is it O.K. to use such a high ranking
1253
1254  function( M )
1255
1256    return ZeroRightModule( HomalgRing( M ) );
1257
1258end );
1259
1260##
1261InstallOtherMethod( Zero,
1262        "for homalg modules",
1263        [ IsGradedModuleRep and IsHomalgLeftObjectOrMorphismOfLeftObjects ], 10001,  ## FIXME: is it O.K. to use such a high ranking
1264
1265  function( M )
1266
1267    return ZeroLeftModule( HomalgRing( M ) );
1268
1269end );
1270
1271##
1272InstallMethod( \*,
1273        "constructor for homalg free graded modules",
1274        [ IsInt, IsHomalgGradedRingRep ],
1275
1276  function( rank, S )
1277
1278    if rank = 0 then
1279        return ZeroLeftModule( S );
1280    elif rank = 1 then
1281        return AsLeftObject( S );
1282    elif rank > 1 then
1283        return FreeLeftModuleWithDegrees( rank, S );
1284    fi;
1285
1286    Error( "virtual modules are not supported (yet)\n" );
1287
1288end );
1289
1290##
1291InstallMethod( \*,
1292        "constructor for homalg free graded modules",
1293        [ IsHomalgGradedRingRep, IsInt ],
1294
1295  function( S, rank )
1296
1297    if rank = 0 then
1298        return ZeroRightModule( S );
1299    elif rank = 1 then
1300        return AsRightObject( S );
1301    elif rank > 1 then
1302        return FreeRightModuleWithDegrees( rank, S );
1303    fi;
1304
1305    Error( "virtual modules are not supported (yet)\n" );
1306
1307end );
1308
1309##
1310InstallMethod( AsLeftObject,
1311        "for homalg graded rings",
1312        [ IsHomalgGradedRingRep ],
1313
1314  function( S )
1315    local left;
1316
1317    if IsBound(S!.AsGradedLeftObject) then
1318        return S!.AsGradedLeftObject;
1319    fi;
1320
1321    left := GradedModule( 1 * UnderlyingNonGradedRing( S ), S );
1322
1323    left!.distinguished := true;
1324
1325    left!.not_twisted := true;
1326
1327    S!.AsGradedLeftObject := left;
1328
1329    return left;
1330
1331end );
1332
1333##
1334InstallMethod( AsRightObject,
1335        "for homalg rings",
1336        [ IsHomalgGradedRingRep ],
1337
1338  function( S )
1339    local right;
1340
1341    if IsBound(S!.AsRightObject) then
1342        return S!.AsRightObject;
1343    fi;
1344
1345    right := GradedModule( UnderlyingNonGradedRing( S ) * 1, S );
1346
1347    right!.distinguished := true;
1348
1349    right!.not_twisted := true;
1350
1351    S!.AsRightObject := right;
1352
1353    return right;
1354
1355end );
1356
1357
1358##
1359InstallMethod( POW,
1360        "constructor for homalg graded free modules of rank 1",
1361        [ IsGradedModuleRep, IsInt ],
1362
1363  function( M, twist )    ## M must be either 1 * R or R * 1
1364    local S, G, w1, t, On;
1365
1366    S := HomalgRing( M );
1367
1368    G := DegreeGroup( S );
1369
1370    t := HomalgModuleElement( ListWithIdenticalEntries( NrGenerators( G ), twist ), G );
1371
1372    if IsIdenticalObj( M, 1 * S ) then
1373
1374        if not IsBound( S!.left_twists ) then
1375            S!.left_twists := rec( );
1376        fi;
1377
1378        if not IsBound( S!.left_twists.(String( t )) ) then
1379
1380            On := GradedModule( 1 * UnderlyingNonGradedRing( S ), -t, S );
1381
1382            On!.distinguished := true;
1383
1384            if twist = 0 then
1385                On!.not_twisted := true;
1386            fi;
1387
1388            S!.left_twists.(String( t )) := On;
1389
1390        fi;
1391
1392        return S!.left_twists.(String( t ));
1393
1394    elif IsIdenticalObj( M, S * 1 ) then
1395
1396        if not IsBound( S!.right_twists ) then
1397            S!.right_twists := rec( );
1398        fi;
1399
1400        if not IsBound( S!.right_twists.(String( t )) ) then
1401
1402            On := GradedModule( UnderlyingNonGradedRing( S ) * 1, -t, S );
1403
1404            On!.distinguished := true;
1405
1406            if twist = 0 then
1407                On!.not_twisted := true;
1408            fi;
1409
1410            S!.right_twists.(String( t )) := On;
1411
1412        fi;
1413
1414        return S!.right_twists.(String( t ));
1415
1416    fi;
1417
1418    TryNextMethod( );
1419
1420end );
1421
1422##
1423InstallMethod( POW,
1424        "constructor for homalg graded free modules",
1425        [ IsGradedModuleRep, IsList ],
1426
1427  function( M, twist )
1428    local S, G, twist_set, weights, On;
1429
1430    S := HomalgRing( M );
1431
1432    G := DegreeGroup( S );
1433
1434    twist_set := Set( Flat( twist ) );
1435
1436    weights := GeneratingElements( G );
1437
1438    if Length( twist ) <> NrGenerators( G ) then
1439
1440        Error( "something went terribly wrong\n" );
1441
1442    fi;
1443
1444    twist := HomalgModuleElement( twist, G );
1445
1446    if IsIdenticalObj( M, 1 * S ) then
1447
1448        if not IsBound( S!.left_twists ) then
1449            S!.left_twists := rec( );
1450        fi;
1451
1452        if not IsBound( S!.left_twists.(String( twist )) ) then
1453
1454            On := FreeLeftModuleWithDegrees( S, -twist );
1455
1456            On!.distinguished := true;
1457
1458            if twist_set = [ 0 ] then
1459                On!.not_twisted := true;
1460            fi;
1461
1462            S!.left_twists.(String( twist )) := On;
1463
1464        fi;
1465
1466        return S!.left_twists.(String( twist ));
1467
1468    elif IsIdenticalObj( M, S * 1 ) then
1469
1470        if not IsBound( S!.right_twists ) then
1471            S!.right_twists := rec( );
1472        fi;
1473
1474        if not IsBound( S!.right_twists.(String( twist )) ) then
1475
1476            On := FreeRightModuleWithDegrees( S, -twist );
1477
1478            On!.distinguished := true;
1479
1480            if twist_set = [ 0 ] then
1481                On!.not_twisted := true;
1482            fi;
1483
1484            S!.right_twists.(String( twist )) := On;
1485
1486        fi;
1487
1488        return S!.right_twists.(String( twist ));
1489
1490    fi;
1491
1492    TryNextMethod( );
1493
1494end );
1495
1496InstallMethod( POW,
1497        "constructor for homalg graded free modules",
1498        [ IsGradedModuleRep, IsHomalgElement ],
1499
1500  function( M, twist )
1501    local S, G, w1, t, On;
1502
1503    S := HomalgRing( M );
1504
1505    t := twist;
1506
1507    if IsIdenticalObj( M, 1 * S ) then
1508
1509        if not IsBound( S!.left_twists ) then
1510            S!.left_twists := rec( );
1511        fi;
1512
1513        if not IsBound( S!.left_twists.(String( t )) ) then
1514
1515            On := GradedModule( 1 * UnderlyingNonGradedRing( S ), -t, S );
1516
1517            On!.distinguished := true;
1518
1519            if twist = 0 then
1520                On!.not_twisted := true;
1521            fi;
1522
1523            S!.left_twists.(String( t )) := On;
1524
1525        fi;
1526
1527        return S!.left_twists.(String( t ));
1528
1529    elif IsIdenticalObj( M, S * 1 ) then
1530
1531        if not IsBound( S!.right_twists ) then
1532            S!.right_twists := rec( );
1533        fi;
1534
1535        if not IsBound( S!.right_twists.(String( t )) ) then
1536
1537            On := GradedModule( UnderlyingNonGradedRing( S ) * 1, -t, S );
1538
1539            On!.distinguished := true;
1540
1541            if twist = 0 then
1542                On!.not_twisted := true;
1543            fi;
1544
1545            S!.right_twists.(String( t )) := On;
1546
1547        fi;
1548
1549        return S!.right_twists.(String( t ));
1550
1551    fi;
1552
1553    TryNextMethod( );
1554
1555end );
1556
1557##
1558InstallMethod( POW,
1559        "constructor for homalg graded free modules of rank 1",
1560        [ IsHomalgGradedRingRep, IsInt ],
1561
1562  function( S, twist )
1563
1564    return ( 1 * S )^twist;
1565
1566end );
1567
1568##
1569InstallMethod( POW,
1570        "constructor for homalg graded free modules",
1571        [ IsHomalgGradedRingRep, IsList ],
1572
1573  function( S, twist )
1574
1575    return ( 1 * S )^twist;
1576
1577end );
1578
1579
1580##
1581InstallMethod( POW,
1582        "constructor for homalg graded free modules",
1583        [ IsHomalgGradedRingRep, IsHomalgElement ],
1584
1585  function( S, twist )
1586
1587    return ( 1 * S )^twist;
1588
1589end );
1590##
1591InstallMethod( Pullback,
1592        "for a ring map and a graded module",
1593        [ IsHomalgRingMap, IsGradedModuleRep ],
1594
1595  function( phi, M )
1596    local rel, degrees, weights;
1597
1598    rel := MatrixOfRelations( M );
1599
1600    rel := Pullback( phi, rel );
1601
1602    degrees := DegreesOfGenerators( M );
1603
1604    weights := Set( List( ImagesOfRingMap( phi ), Degree ) );
1605
1606    if Length( weights ) <> 1 then
1607        Error( "different weights are not supported yet\n" );
1608    fi;
1609
1610    weights := HomalgElementToInteger( weights[1] );
1611
1612    degrees := List( degrees, i -> HomalgElementToInteger( i ) * weights );
1613
1614    if IsHomalgLeftObjectOrMorphismOfLeftObjects( M ) then
1615        return LeftPresentationWithDegrees( rel, degrees );
1616    else
1617        return RightPresentationWithDegrees( rel, degrees );
1618    fi;
1619
1620end );
1621
1622####################################
1623#
1624# View, Print, and Display methods:
1625#
1626####################################
1627
1628##
1629InstallMethod( ViewObj,
1630        "for categories of graded modules",
1631        [ IsCategoryOfGradedModules ],
1632
1633  function( C )
1634    local parity;
1635
1636    if IsCategoryOfFinitelyPresentedGradedLeftModulesRep( C ) then
1637        parity := "left";
1638    else
1639        parity := "right";
1640    fi;
1641
1642    Print( "<The Abelian category of f.p. graded ", parity, " modules over the ring " );
1643    ViewObj( C!.ring );
1644    Print( ">" );
1645
1646end );
1647
1648##
1649InstallMethod( ViewObj,
1650        "for graded homalg modules",
1651        [ IsGradedModuleOrGradedSubmoduleRep ],
1652
1653  function( o )
1654
1655    if IsBound( o!.distinguished ) then
1656        Print( "<The graded" );
1657    else
1658        Print( "<A graded" );
1659    fi;
1660
1661    Print( ViewString( UnderlyingModule( o ) ) );
1662
1663    Print( ">" );
1664
1665end );
1666
1667##
1668InstallMethod( Display,
1669        "for graded homalg modules",
1670        [ IsGradedModuleOrGradedSubmoduleRep ],
1671
1672  function( o )
1673    local deg;
1674
1675    deg := DegreesOfGenerators( o );
1676
1677    if Length( deg ) > 1 then
1678        Display( UnderlyingModule( o ) );
1679        Print( "\n(graded, degrees of generators: ");
1680        ViewObj( deg );
1681        Print( ")\n" );
1682    elif Length( deg ) = 1 then
1683        Display( UnderlyingModule( o ) );
1684        Print( "\n(graded, degree of generator: ");
1685        ViewObj( deg[ 1 ] );
1686        Print( ")\n" );
1687    else
1688        Display( UnderlyingModule( o ) );
1689        Print( "\n(graded)\n" );
1690    fi;
1691
1692end );
1693