Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  HomalgFunctor.gi   Sprache: unbekannt

 
# SPDX-License-Identifier: GPL-2.0-or-later
# homalg: A homological algebra meta-package for computable Abelian categories
#
# Implementations
#

##  Implementations for functors.

##  <#GAPDoc Label="Functors:intro">
##    Functors and their natural transformations form the heart of the &homalg; package. Usually, a functor is realized
##    in computer algebra systems as a procedure which can be applied to a certain type of objects. In <Cite Key="BR"/>
##    it was explained how to implement a functor of Abelian categories -- by itself -- as an object which can be
##    further manipulated (composed, derived, ...).
##    So in addition to the constructor <Ref Oper="CreateHomalgFunctor" Label="constructor for functors"/>
##    which is used to create functors from scratch, &homalg; provides further easy-to-use constructors
##    to create new functors out of existing ones:
##    <List>
##      <Item><Ref Oper="InsertObjectInMultiFunctor" Label="constructor for functors given a multi-functor and an object"/></Item>
##      <Item><Ref Oper="RightSatelliteOfCofunctor" Label="constructor of the right satellite of a contravariant functor"/></Item>
##      <Item><Ref Oper="LeftSatelliteOfFunctor" Label="constructor of the left satellite of a covariant functor"/></Item>
##      <Item><Ref Oper="RightDerivedCofunctor" Label="constructor of the right derived functor of a contravariant functor"/></Item>
##      <Item><Ref Oper="LeftDerivedFunctor" Label="constructor of the left derived functor of a covariant functor"/></Item>
##      <Item><Ref Oper="ComposeFunctors" Label="constructor for functors given two functors"/></Item>
##    </List>
##    In &homalg; each functor is implemented as a &GAP4; object.
##    <P/>
##    So-called installers (&see; <Ref Oper="InstallFunctor"/> and <Ref Oper="InstallDeltaFunctor"/>)
##    take such a functor object and create operations in order to apply the functor on objects, morphisms,
##    complexes (of objects or again of complexes), and chain morphisms. The installer <Ref Oper="InstallDeltaFunctor"/>
##    creates additional operations for <M>\delta</M>-functors in order to compute connecting homomorphisms,
##    exact triangles, and associated long exact sequences by starting with a short exact sequence.
##    <P/>
##    In &homalg; special emphasis is laid on the action of functors on <E>morphisms</E>, as an essential part of the
##    very definition of a functor. This is for no obvious reason often neglected in computer algebra systems.
##    Starting from a functor where the action on morphisms is also defined, all the above constructors
##    again create functors with actions both on objects and on morphisms (and hence on chain complexes and chain morphisms).
##    <P/>
##    It turned out that in a variety of situations a caching mechanism for functors is not only extremely
##    useful (e.g. to avoid repeated expensive computations) but also an absolute necessity for the coherence of data.
##    Functors in &homalg; are therefore endowed with a caching mechanism.
##    <P/>
##    If <M>R</M> is a &homalg; ring in which the component <M>R</M>!.<C>ByASmallerPresentation</C> is set to true
##    <Br/><Br/>
##    <C>R!.ByASmallerPresentation := true</C>;
##    <Br/><Br/>
##    any functor which returns an object over <M>R</M> will first apply
##    <C>ByASmallerPresentation</C> to its result before returning it. <P/>
##    One of the highlights in &homalg; is the computation of Grothendieck's spectral sequences connecting
##    the composition of the derivations of two functors with the derived functor of their composite.
##  <#/GAPDoc>

####################################
#
# representations:
#
####################################

# a new representation for the GAP-category IsHomalgFunctor:

##  <#GAPDoc Label="IsHomalgFunctorRep">
##  <ManSection>
##    <Filt Type="Representation" Arg="E" Name="IsHomalgFunctorRep"/>
##    <Returns><C>true</C> or <C>false</C></Returns>
##    <Description>
##      The &GAP; representation of &homalg; (multi-)functors. <P/>
##      (It is a representation of the &GAP; category <Ref Filt="IsHomalgFunctor"/>.)
##    </Description>
##  </ManSection>
##  <#/GAPDoc>
##
DeclareRepresentation( "IsHomalgFunctorRep",
        IsHomalgFunctor,
        [ ] );

# a new subrepresentation of the representation IsContainerForWeakPointersRep:

##
DeclareRepresentation( "IsContainerForWeakPointersOnComputedValuesOfFunctorRep",
        IsContainerForWeakPointersOnObjectsRep,
        [ "weak_pointers", "active", "deleted", "counter", "accessed", "cache_misses", "cache_hits" ] );

####################################
#
# families and types:
#
####################################

# a new family:
BindGlobal( "TheFamilyOfHomalgFunctors",
        NewFamily( "TheFamilyOfHomalgFunctors" ) );

# a new type:
BindGlobal( "TheTypeHomalgFunctor",
        NewType(  TheFamilyOfHomalgFunctors,
                IsHomalgFunctorRep ) );

# a new type:
BindGlobal( "TheTypeContainerForWeakPointersOnComputedValuesOfFunctor",
        NewType( TheFamilyOfContainersForWeakPointers,
                IsContainerForWeakPointersOnComputedValuesOfFunctorRep ) );

####################################
#
# global values:
#
####################################

HOMALG.FunctorOn :=
  [ IsStructureObjectOrFinitelyPresentedObjectRep,
    IsStaticMorphismOfFinitelyGeneratedObjectsRep,
    [ IsComplexOfFinitelyPresentedObjectsRep, IsCocomplexOfFinitelyPresentedObjectsRep ],
    [ IsChainMorphismOfFinitelyPresentedObjectsRep, IsCochainMorphismOfFinitelyPresentedObjectsRep ] ];
  
####################################
#
# methods for operations:
#
####################################

##
InstallMethod( NaturalGeneralizedEmbedding,
        "for homalg objects being values of functors on objects",
        [ IsStaticFinitelyPresentedObjectRep ],
        
  function( FM )
    
    if not IsBound(FM!.NaturalGeneralizedEmbedding) then
        Error( "the object does not have a component \"NaturalGeneralizedEmbedding\"; either the object is not the result of a functor or the functor is not properly implemented (cf. arXiv:math/0701146)\n" );
    fi;
    
    return FM!.NaturalGeneralizedEmbedding;
    
end );

##
InstallMethod( NameOfFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    if not IsBound( Functor!.name ) then
        Error( "the provided functor is nameless\n" );
    fi;
    
    return Functor!.name;
    
end );

##
InstallMethod( OperationOfFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    local functor_operation;
    
    if not IsBound( Functor!.operation ) then
        Error( "unable to find the functor component \"operation\"\n" );
    fi;
    
    functor_operation := ValueGlobal( Functor!.operation );
    
    ## for this to work you need to declare one instance of the functor,
    ## although all methods will be installed using InstallOtherMethod!
    if not IsOperation( functor_operation ) and
       not IsFunction( functor_operation ) then
        Error( "the functor ", NameOfFunctor( Functor ), " neither points to an operation nor to a function\n" );
    fi;
    
    return functor_operation;
    
end );

##
InstallMethod( CategoryOfFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    if not IsBound( Functor!.category ) then
        Error( "unable to find the functor component \"category\"\n" );
    fi;
    
    return Functor!.category;
    
end );

##
InstallMethod( DescriptionOfCategory,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    local category;
    
    category := CategoryOfFunctor( Functor );
    
    if not IsBound( category!.description ) then
        Error( "unable to find the category component \"description\"\n" );
    fi;
    
    return category!.description;
    
end );

##
InstallMethod( ShortDescriptionOfCategory,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    local category;
    
    category := CategoryOfFunctor( Functor );
    
    if not IsBound( category!.short_description ) then
        Error( "unable to find the category component \"short_description\"\n" );
    fi;
    
    return category!.short_description;
    
end );

##
InstallMethod( IsSpecialFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    if IsBound( Functor!.special ) and Functor!.special = true then
        return true;
    fi;
    
    return false;
    
end );

##
InstallMethod( MultiplicityOfFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    if IsBound( Functor!.number_of_arguments ) then
        return Functor!.number_of_arguments;
    fi;
    
    return 1;
    
end );

##
InstallMethod( IsCovariantFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsInt ],
        
  function( Functor, pos )
    
    if pos < 1 then
        Error( "the second argument must be a positive integer\n" );
    fi;
    
    if IsBound( Functor!.(pos) ) then
        if Functor!.( pos )[1][1] = "covariant" then
            return true;
        elif Functor!.( pos )[1][1] = "contravariant" then
            return false;
        fi;
    fi;
    
    return fail;
    
end );

##
InstallMethod( IsCovariantFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    return IsCovariantFunctor( Functor, 1 );
    
end );

##
InstallMethod( IsDistinguishedArgumentOfFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsPosInt ],
        
  function( Functor, pos )
    local l;
    
    if IsBound( Functor!.(String( pos )) ) and IsBound( Functor!.(String( pos ))[1] ) then
        l := Length( Functor!.(String( pos ))[1] );
        
        if l > 1 and Functor!.(String( pos ))[1][l] = "distinguished" then
            return true;
        fi;
    fi;
    
    return false;
    
end );

##
InstallMethod( IsDistinguishedFirstArgumentOfFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    return IsDistinguishedArgumentOfFunctor( Functor, 1 );
    
end );

##
InstallMethod( IsAdditiveFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsPosInt ],
        
  function( Functor, pos )
    local prop;
    
    if IsBound( Functor!.(pos) ) and Length( Functor!.( pos )[1] ) > 1 then
        prop := Functor!.( pos )[1][2];
        if prop in [ "additive", "left exact", "right exact", "exact", "right adjoint", "left adjoint" ] then
            return true;
        fi;
    fi;
    
    return fail;
    
end );

##
InstallMethod( IsAdditiveFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    return IsAdditiveFunctor( Functor, 1 );
    
end );

##
InstallMethod( IsLeftExactFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsPosInt ],
        
  function( Functor, pos )
    local prop;
    
    if IsBound( Functor!.(pos) ) and Length( Functor!.( pos )[1] ) > 1 then
        prop := Functor!.( pos )[1][2];
        if prop in [ "left exact", "exact", "right adjoint" ] then
            return true;
        fi;
    fi;
    
    return fail;
    
end );

##
InstallMethod( IsLeftExactFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    return IsLeftExactFunctor( Functor, 1 );
    
end );

##
InstallMethod( IsRightExactFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsPosInt ],
        
  function( Functor, pos )
    local prop;
    
    if IsBound( Functor!.(pos) ) and Length( Functor!.( pos )[1] ) > 1 then
        prop := Functor!.( pos )[1][2];
        if prop in [ "right exact", "exact", "left adjoint" ] then
            return true;
        fi;
    fi;
    
    return fail;
    
end );

##
InstallMethod( IsRightExactFunctor,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    
    return IsRightExactFunctor( Functor, 1 );
    
end );

##
InstallMethod( IsIdenticalObjForFunctors,
        "for two objects",
        [ IsObject, IsObject ],
        
  function( o1, o2 )
    local l1, l2;
    
    if IsHomalgObjectOrMorphism( o1 ) then
        return IsIdenticalObj( o1, o2 );
    elif IsString( o1 ) and IsString( o2 ) then
        return o1 = o2;
    elif IsList( o1 ) and IsList( o2 ) then
        l1 := Length( o1 );
        l2 := Length( o2 );
        return l1 = l2 and
               ForAll( [ 1 .. l1 ], i -> IsIdenticalObjForFunctors( o1[i], o2[i] ) );
    fi;
    
    return IsIdenticalObj( o1, o2 );
    
end );

##
InstallMethod( GetContainerForWeakPointersOfFunctorCachedValue,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsHomalgCategory, IsString ],
        
  function( Functor, category, container )
    local name, containers;
    
    ## first we ask the functor
    if not IsBound( Functor!.( container ) ) then
        return fail;
    elif Functor!.( container ) = false and
      IsBound( category!.do_not_cache_values_of_some_functors ) and
      category!.do_not_cache_values_of_some_functors = true then
        return fail;
    fi;
    
    name := Concatenation( NameOfFunctor( Functor ), "_", container );
    
    containers := category!.containers;
    
    if IsBound( containers!.( name ) ) then
        container := containers!.( name );
        if IsContainerForWeakPointersRep( container ) then
            return container;
        fi;
        return fail;
    elif IsBound( category!.do_not_cache_values_of_functors ) then
        return fail;
    fi;
    
    container := ContainerForWeakPointers( TheTypeContainerForWeakPointersOnComputedValuesOfFunctor );
    
    containers!.( name ) := container;
    
    return container;
    
end );

##
InstallMethod( SetFunctorObjCachedValue,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsList, IsObject ],
        
  function( Functor, args_of_functor, obj )
    local arguments_of_functor, p, l, context_of_arguments, arg_all,
          genesis, a, category, container;
    
    ## convert subobjects into objects
    arguments_of_functor :=
      List( args_of_functor,
            function( a )
              if IsStaticFinitelyPresentedSubobjectRep( a ) then
                  return UnderlyingObject( a );
              else
                  return a;
              fi;
            end );
    
    if IsBound( Functor!.0 ) then
        p := 1;
    else
        p := 0;
    fi;
    l := Length( arguments_of_functor );
    
    context_of_arguments := List( arguments_of_functor{[ 1 + p .. l ]}, PositionOfTheDefaultPresentation );
    
    arg_all := rec( );
    
    arg_all.("arguments_of_functor") := arguments_of_functor;
    arg_all.("context_of_arguments") := context_of_arguments;
    arg_all.("Functor") := Functor;
    arg_all.("PositionOfTheDefaultPresentationOfTheOutput")
      := PositionOfTheDefaultPresentation( obj );
    
    arg_all := [ arg_all, obj ];
    
    if not HasGenesis( obj ) then
        SetGenesis( obj, [ arg_all ] );
    else
        genesis := Genesis( obj );
        if IsList( genesis ) then
            Add( genesis, arg_all );
        fi;
    fi;
    
    for a in args_of_functor do
        category := HomalgCategory( a );
        if category <> fail then
            break;
        fi;
    od;
    
    container := GetContainerForWeakPointersOfFunctorCachedValue(
                         Functor,
                         category,
                         "ContainerForWeakPointersOnComputedBasicObjects" );
    
    if container <> fail then
        _AddElmWPObj_ForHomalg( container, arg_all );
    fi;
    
    return obj;
    
end );

##
InstallMethod( GetFunctorObjCachedValue,
        "for homalg functors",
        [ IsHomalgFunctorRep, IsList ],
        
  function( Functor, args_of_functor )
    local a, category, container, weak_pointers, lp, active, l_active,
          arguments_of_functor, functor_name, p, l, context_of_arguments,
          cache_hit, i, arg_old_obj, context, arg_old, obj;
    
    for a in args_of_functor do
        category := HomalgCategory( a );
        if category <> fail then
            break;
        fi;
    od;
    
    container := GetContainerForWeakPointersOfFunctorCachedValue(
                         Functor,
                         category,
                         "ContainerForWeakPointersOnComputedBasicObjects" );
    
    if container = fail then
        return fail;
    fi;
    
    weak_pointers := container!.weak_pointers;
    
    lp := LengthWPObj( weak_pointers );
    
    active := Filtered( container!.active, i -> i <= lp );
    
    l_active := Length( active );
    
    ## convert subobjects into objects
    arguments_of_functor :=
      List( args_of_functor,
            function( a )
              if IsStaticFinitelyPresentedSubobjectRep( a ) then
                  return UnderlyingObject( a );
              else
                  return a;
              fi;
            end );
    
    #=====# begin of the core procedure #=====#
    
    functor_name := NameOfFunctor( Functor );
    
    if IsBound( Functor!.0 ) then
        p := 1;
    else
        p := 0;
    fi;
    l := Length( arguments_of_functor );
    context_of_arguments := List( arguments_of_functor{[ 1 + p .. l ]}, PositionOfTheDefaultPresentation );
    
    cache_hit := false;
    i := 1;
    while i <= l_active do
        arg_old_obj := ElmWPObj( weak_pointers, active[i] );
        if arg_old_obj <> fail then
            arg_old := arg_old_obj[1];
            context := arg_old.("context_of_arguments");
            arg_old := arg_old.("arguments_of_functor");
            obj := arg_old_obj[2];
            if l = Length( arg_old ) then
                
                if ForAny( arguments_of_functor, IsHomalgStaticObject ) then
                    
                    if ForAll( [ 1 .. l ], j -> IsIdenticalObjForFunctors( arg_old[j], arguments_of_functor[j] ) ) then
                        
                        if ForAll( [ 1 .. l - p ], j -> context[j] = context_of_arguments[j] ) then
                            
                            cache_hit := true;
                            break;
                            
                        elif ForAll( [ 1 .. l - p ],
                                function( j )
                                  if context[j] = context_of_arguments[j] then
                                      return true;
                                  else
                                      return IsIdenticalObj(
                                                      PartOfPresentationRelevantForOutputOfFunctors( arg_old[j+p], context[j] ),
                                                      PartOfPresentationRelevantForOutputOfFunctors( arguments_of_functor[j+p], context_of_arguments[j] ) );
                                  fi;
                                end ) then
                            
                            cache_hit := true;
                            break;
                            
                        elif ForAll( [ 1 .. l - p ],
                                function( j )
                                  return ComparePresentationsForOutputOfFunctors( arguments_of_functor[j+p], context_of_arguments[j], context[j] );
                                end ) then
                            
                            cache_hit := true;
                            break;
                            
                        elif IsBound( obj!.IgnoreContextOfArgumentsOfFunctor ) and
                          obj!.IgnoreContextOfArgumentsOfFunctor = true then
                            
                            cache_hit := true;
                            break;
                            
                        elif IsBound( Functor!.CompareArgumentsForFunctorObj ) and  ## no static objects
                          Functor!.CompareArgumentsForFunctorObj( arg_old, arguments_of_functor ) then
                            
                            cache_hit := true;
                            break;
                            
                        ##elif IsBound( Functor!.OnMorphisms ) then
                        ##    Error( "TODO: merge the new output with the old one\n" );
                        fi;
                    fi;
                    
                elif not ( IsBound( Functor!.DontCompareEquality ) and Functor!.DontCompareEquality ) and
                  ForAll( [ 1 .. l ], j -> arg_old[j] = arguments_of_functor[j] ) then ## no static objects
                    
                    ## this "elif" is extremely important:
                    ## To apply a certain functor (e.g. derived ones) to an object
                    ## we might need to apply another functor to a morphism A. This
                    ## morphisms could be the outcome of a third functor applied to another
                    ## morphism B, and although there is a caching for functors applied
                    ## to morphisms, B often becomes obsolete since it was only used in an
                    ## intermediat step and gets deleted after a while
                    ## (e.g. CompleteImageSquare( alpha1, Functor(morphism), beta1 )).
                    ## Hence B has to be recomputed to get B' and A has to be recomputed
                    ## using B' to get A'. Now A=A' but not identical!
                    
                    cache_hit := true;
                    break;
                    
                elif IsBound( Functor!.CompareArgumentsForFunctorObj ) and  ## no static objects
                  Functor!.CompareArgumentsForFunctorObj( arg_old, arguments_of_functor ) then
                    
                    cache_hit := true;
                    break;
                    
                fi;
                
            fi;
            i := i + 1;
        else  ## active[i] is no longer active
            Remove( active, i );
            l_active := l_active - 1;
        fi;
    od;
    
    container!.active := active;
    container!.deleted := Difference( [ 1 .. lp ], active );
    
    container!.accessed := container!.accessed + 1;
    container!.cache_misses := container!.cache_misses + i - 1;
    
    if cache_hit then
        container!.cache_hits := container!.cache_hits + 1;
        return obj;
    fi;
    
    return fail;
    
end );

##
InstallMethod( FunctorObj,
        "for homalg morphisms",
        [ IsHomalgFunctorRep, IsList ],
        
  function( Functor, args_of_functor )
    local arguments_of_functor, obj, genesis, Functor_orig, arg_pos,
          Functor_arg, Functor_post, Functor_pre, post_arg_pos,
          functor_orig_operation, m_orig, arg_orig,
          functor_pre_operation, m_pre, functor_post_operation, m_post,
          arg_pre, arg_post, R;
    
    ## convert subobjects into objects
    arguments_of_functor :=
      List( args_of_functor,
            function( a )
              if IsStaticFinitelyPresentedSubobjectRep( a ) then
                  return UnderlyingObject( a );
              else
                  return a;
              fi;
            end );
    
    obj := GetFunctorObjCachedValue( Functor, args_of_functor );
    if obj <> fail then
        return obj;
    fi;
    
    #=====# begin of the core procedure #=====#
    
    if HasGenesis( Functor ) then
        genesis := Genesis( Functor );
        if genesis[1] = "InsertObjectInMultiFunctor" then
            Functor_orig := genesis[2];
            arg_pos := genesis[3];
            Functor_arg := genesis[4];
        elif genesis[1] = "ComposeFunctors" then
            Functor_post := genesis[2][1];
            Functor_pre := genesis[2][2];
            post_arg_pos := genesis[3];
        fi;
    fi;
    
    if IsBound( Functor_orig ) then
        ## the functor is specialized: Functor := Functor_orig( ..., Functor_arg, ... )
        
        functor_orig_operation := OperationOfFunctor( Functor_orig );
        
        m_orig := MultiplicityOfFunctor( Functor_orig );
        
        if IsBound( Functor_orig!.0 ) then
            arg_orig := arguments_of_functor{[ 1 .. arg_pos ]};
        else
            arg_orig := arguments_of_functor{[ 1 .. arg_pos - 1 ]};
        fi;
        
        Add( arg_orig, Functor_arg );
        Append( arg_orig, arguments_of_functor{[ arg_pos + 1 .. m_orig ]} );
        
        obj := CallFuncList( functor_orig_operation, arg_orig );
        
    elif IsBound( Functor_post ) then
        ## the functor is composed: Functor := Functor_post @ Functor_pre
        
        functor_pre_operation := OperationOfFunctor( Functor_pre );
        
        functor_post_operation := OperationOfFunctor( Functor_post );
        
        m_pre := MultiplicityOfFunctor( Functor_pre );
        
        m_post := MultiplicityOfFunctor( Functor_post );
        
        arg_pre := arguments_of_functor{[ post_arg_pos .. post_arg_pos + m_pre - 1 ]};
        
        arg_post := Concatenation(
                            arguments_of_functor{[ 1 .. post_arg_pos - 1 ]},
                            [ CallFuncList( functor_pre_operation, arg_pre ) ],
                            arguments_of_functor{[ post_arg_pos + m_pre .. m_post + m_pre - 1 ]}
                            );
        
        obj := CallFuncList( functor_post_operation, arg_post );
        
    else
        
        obj := CallFuncList( Functor!.OnObjects, arguments_of_functor );
        
    fi;
    
    if IsHomalgStaticObject( obj ) then
        R := StructureObject( obj );
        if IsBound( R!.ByASmallerPresentation ) then
            ByASmallerPresentation( obj );
        fi;
    fi;
    
    #=====# end of the core procedure #=====#
    
    SetFunctorObjCachedValue( Functor, arguments_of_functor, obj );
    
    return obj;
    
end );

##
InstallMethod( FunctorMor,
        "for homalg morphisms",
        [ IsHomalgFunctorRep, IsMorphismOfFinitelyGeneratedObjectsRep, IsList ],
        
  function( Functor, phi, fixed_arguments_of_multi_functor )
    local container, weak_pointers, lp, active, l_active, functor_name,
          number_of_arguments, pos0, arg_positions, S, T, pos,
          arg_before_pos, arg_behind_pos, arg_all, cache_hit, i, l,
          arg_old_mor, arg_old, arg_source, arg_target, functor_operation,
          F_source, F_target, genesis, Functor_orig, arg_pos, Functor_arg,
          Functor_post, Functor_pre, post_arg_pos,
          functor_orig_operation, m_orig, arg_orig,
          functor_pre_operation, m_pre, functor_post_operation, m_post,
          arg_pre, arg_post, emb_source, emb_target, arg_phi, hull_phi, mor;
    
    if not fixed_arguments_of_multi_functor = [ ] and
       not ( ForAll( fixed_arguments_of_multi_functor, a -> IsList( a ) and Length( a ) = 2 and IsPosInt( a[1] ) ) ) then
        Error( "the last argument has a wrong syntax\n" );
    fi;
    
    container := GetContainerForWeakPointersOfFunctorCachedValue(
                         Functor,
                         HomalgCategory( phi ),
                         "ContainerForWeakPointersOnComputedBasicMorphisms" );
    if container <> fail then
        
        weak_pointers := container!.weak_pointers;
        
        lp := LengthWPObj( weak_pointers );
        
        active := Filtered( container!.active, i -> i <= lp );
        
        l_active := Length( active );
        
    fi;
    
    #=====# begin of the core procedure #=====#
    
    functor_name := NameOfFunctor( Functor );
    
    number_of_arguments := MultiplicityOfFunctor( Functor );
    
    if IsBound( Functor!.0 ) and IsList( Functor!.0 ) then
        number_of_arguments := number_of_arguments + 1;
        pos0 := 1;
    else
        pos0 := 0;
    fi;
    
    arg_positions := List( fixed_arguments_of_multi_functor, a -> a[1] );
    
    if Length( arg_positions ) <> number_of_arguments - 1 then
        Error( "the number of fixed arguments provided for the functor must be one less than the total number\n" );
    elif not IsDuplicateFree( arg_positions ) then
        Error( "the provided list of positions is not duplicate free: ", arg_positions, "\n" );
    elif arg_positions <> [ ] and Maximum( arg_positions ) > number_of_arguments then
        Error( "the list of positions must be a subset of [ 1 .. ", number_of_arguments, " ], but received: :",  arg_positions, "\n" );
    fi;
    
    S := Source( phi );
    T := Range( phi );
    
    pos := Filtered( [ 1 .. number_of_arguments ], a -> not a in arg_positions )[1];
    
    arg_positions := fixed_arguments_of_multi_functor;
    
    Sort( arg_positions, function( v, w ) return v[1] < w[1]; end );
    
    arg_before_pos := List( arg_positions{[ 1 .. pos - 1 ]}, a -> a[2] );
    arg_behind_pos := List( arg_positions{[ pos .. number_of_arguments - 1 ]}, a -> a[2] );
    
    arg_all := Concatenation( arg_before_pos, [ phi ], arg_behind_pos );
    
    if container <> fail then
        cache_hit := false;
        i := 1;
        while i <= l_active do
            arg_old_mor := ElmWPObj( weak_pointers, active[i] );
            if arg_old_mor <> fail then
                arg_old := arg_old_mor[1];
                l := Length( arg_old );
                if l = Length( arg_all ) then
                    if ForAll( [ 1 .. l ], j -> IsIdenticalObjForFunctors( arg_old[j], arg_all[j] ) ) then
                        cache_hit := true;
                        break;
                    fi;
                fi;
                i := i + 1;
            else ## active[i] is no longer active
                Remove( active, i );
                l_active := l_active - 1;
            fi;
        od;
        
        container!.active := active;
        container!.deleted := Difference( [ 1 .. lp ], active );
        
        container!.accessed := container!.accessed + 1;
        container!.cache_misses := container!.cache_misses + i - 1;
        
        if cache_hit then
            container!.cache_hits := container!.cache_hits + 1;
            return arg_old_mor[2];
        fi;
        
    fi;
    
    pos := pos - pos0;
    
    if IsCovariantFunctor( Functor, pos ) = true then
        arg_source := Concatenation( arg_before_pos, [ S ], arg_behind_pos );
        arg_target := Concatenation( arg_before_pos, [ T ], arg_behind_pos );
    elif IsCovariantFunctor( Functor, pos ) = false then ## not fail
        arg_source := Concatenation( arg_before_pos, [ T ], arg_behind_pos );
        arg_target := Concatenation( arg_before_pos, [ S ], arg_behind_pos );
    else
        Error( "the functor ", functor_name, " must be either co- or contravriant in its argument number ", pos, "\n" );
    fi;
    
    functor_operation := OperationOfFunctor( Functor );
    
    F_source := CallFuncList( functor_operation, arg_source );
    F_target := CallFuncList( functor_operation, arg_target );

    if ( HasIsZero( F_source ) and IsZero( F_source ) ) or ( HasIsZero( F_target ) and IsZero( F_target ) ) or ( HasIsZero( phi ) and IsZero( phi ) ) then

        mor := TheZeroMorphism( F_source, F_target );

    elif HasIsOne( phi ) and IsOne( phi ) then

        mor := TheIdentityMorphism( F_source );

    else
    
        if HasGenesis( Functor ) then
            genesis := Genesis( Functor );
            if genesis[1] = "InsertObjectInMultiFunctor" then
                Functor_orig := genesis[2];
                arg_pos := genesis[3];
                Functor_arg := genesis[4];
            elif genesis[1] = "ComposeFunctors" then
                Functor_post := genesis[2][1];
                Functor_pre := genesis[2][2];
                post_arg_pos := genesis[3];
            fi;
        fi;
    
        if IsBound( Functor_orig ) then
            ## the functor is specialized: Functor := Functor_orig( ..., Functor_arg, ... )
        
            functor_orig_operation := OperationOfFunctor( Functor_orig );
        
            m_orig := MultiplicityOfFunctor( Functor_orig );
        
            if IsBound( Functor_orig!.0 ) then
                arg_orig := arg_all{[ 1 .. arg_pos ]};
            else
                arg_orig := arg_all{[ 1 .. arg_pos - 1 ]};
            fi;
        
            Add( arg_orig, Functor_arg );
            Append( arg_orig, arg_all{[ arg_pos + 1 .. m_orig ]} );
        
            mor := CallFuncList( functor_orig_operation, arg_orig );
        
        elif IsBound( Functor_post ) then
            ## the functor is composed: Functor := Functor_post @ Functor_pre
        
            functor_pre_operation := OperationOfFunctor( Functor_pre );
        
            functor_post_operation := OperationOfFunctor( Functor_post );
        
            m_pre := MultiplicityOfFunctor( Functor_pre );
        
            m_post := MultiplicityOfFunctor( Functor_post );
        
            arg_pre := arg_all{[ post_arg_pos .. post_arg_pos + m_pre - 1 ]};
        
            arg_post := Concatenation(
                            arg_all{[ 1 .. post_arg_pos - 1 ]},
                            [ CallFuncList( functor_pre_operation, arg_pre ) ],
                            arg_all{[ post_arg_pos + m_pre .. m_post + m_pre - 1 ]}
                            );
        
            mor := CallFuncList( functor_post_operation, arg_post );
        
        elif IsBound( Functor!.IsIdentityOnObjects ) and Functor!.IsIdentityOnObjects then
        
            if IsBound( Functor!.OnMorphisms ) then
                arg_phi := Concatenation( arg_before_pos, [ phi ], arg_behind_pos );
                mor := CallFuncList( Functor!.OnMorphisms, arg_phi );
            
                if IsBound( Functor!.MorphismConstructor ) then
                    mor := Functor!.MorphismConstructor( mor, F_source, F_target );
                
                    ## otherwise the result mor cannot automatically be marked IsMorphism
                    SetIsMorphism( mor, true );
                fi;
            else
                mor := phi;
            fi;
        
        elif IsBound( Functor!.OnMorphisms ) then
        
            mor := Functor!.OnMorphisms( F_source, F_target, arg_before_pos, phi, arg_behind_pos );
        
        else ## old style, will be eliminated soon
        
            emb_source := NaturalGeneralizedEmbedding( F_source );
            emb_target := NaturalGeneralizedEmbedding( F_target );
        
            if IsBound( Functor!.OnMorphismsHull ) then
                arg_phi := Concatenation( arg_before_pos, [ phi ], arg_behind_pos );
                hull_phi := CallFuncList( Functor!.OnMorphismsHull, arg_phi );
            
                if IsBound( Functor!.MorphismConstructor ) then
                    hull_phi := Functor!.MorphismConstructor( hull_phi, Range( emb_source ), Range( emb_target ) );
                
                    ## otherwise the result mor cannot automatically be marked IsMorphism
                    SetIsMorphism( hull_phi, true );
                fi;
            else
                hull_phi := phi;
            fi;
        
            mor := CompleteImageSquare( emb_source, hull_phi, emb_target );
        
            ## CAUTION: this is experimental!!!
            if HasIsGeneralizedMonomorphism( emb_source ) and IsGeneralizedMonomorphism( emb_source ) and
               HasIsGeneralizedMonomorphism( emb_target ) and IsGeneralizedMonomorphism( emb_target ) and
               HasIsMorphism( phi ) and IsMorphism( phi ) then
            
                ## check assertion
                Assert( 3, IsMorphism( mor ) );
            
                SetIsMorphism( mor, true );
            fi;
        
        fi;
    
    fi;

    SetPropertiesOfFunctorMor( Functor, phi, mor, pos, arg_before_pos, arg_behind_pos );
    
    #=====# end of the core procedure #=====#
    
    arg_all := [ arg_all, mor ];
    
    if not HasGenesis( mor ) then
        SetGenesis( mor, [ arg_all ] );
    else
        Add( Genesis( mor ), arg_all );
    fi;
    
    if container <> fail then
        _AddElmWPObj_ForHomalg( container, arg_all );
    fi;
    
    return mor;
    
end );

##
InstallMethod( FunctorMor,
        "for homalg morphisms",
        [ IsHomalgFunctorRep, IsStaticMorphismOfFinitelyGeneratedObjectsRep ],
        
  function( Functor, phi )
    
    return FunctorMor( Functor, phi, [ ] );
    
end );

InstallMethod( SetPropertiesOfFunctorMor,
        "for homalg morphisms",
        [ IsHomalgFunctorRep, IsHomalgMorphism, IsHomalgMorphism, IsInt, IsList, IsList ],
        
  function( Functor, phi, mor, pos, arg_before_pos, arg_behind_pos )
    local alpha;
    
    if HasIsIsomorphism( phi ) and IsIsomorphism( phi ) then
        
        Assert( 3, IsIsomorphism( mor ) );
        SetIsIsomorphism( mor, true );
        
    fi;
        
    if HasIsMorphism( phi ) and IsMorphism( phi ) then
        
        Assert( 3, IsMorphism( mor ) );
        SetIsMorphism( mor, true );
        
    fi;
    
    if IsLeftExactFunctor( Functor, pos ) = true then
        
        if IsCovariantFunctor( Functor, pos ) = true then
            
            if  HasIsMonomorphism( phi ) and IsMonomorphism( phi ) then
                
                Assert( 3, IsMonomorphism( mor ) );
                SetIsMonomorphism( mor, true );
                
            fi;
            
            if HasKernelEmb( phi ) then
                alpha := GetFunctorObjCachedValue( Functor, Concatenation( arg_before_pos, [ KernelEmb( phi ) ], arg_behind_pos ) );
                if alpha <> fail then
                    SetKernelEmb( mor, alpha );
                fi;
            fi;
            
        fi;
        
        if IsCovariantFunctor( Functor, pos ) = false then
            
            if  HasIsEpimorphism( phi ) and IsEpimorphism( phi ) then
                
                Assert( 3, IsMonomorphism( mor ) );
                SetIsMonomorphism( mor, true );
                
            fi;
            
            if HasCokernelEpi( phi ) then
                alpha := GetFunctorObjCachedValue( Functor, Concatenation( arg_before_pos, [ CokernelEpi( phi ) ], arg_behind_pos ) );
                if alpha <> fail then
                    Error( "juhu 2" );
                    SetKernelEmb( mor, alpha );
                fi;
            fi;
            
        fi;
        
    fi;
    
    if IsRightExactFunctor( Functor, pos ) = true then
        
        if IsCovariantFunctor( Functor, pos ) = true then
            
            if  HasIsEpimorphism( phi ) and IsEpimorphism( phi ) then
                
                Assert( 3, IsEpimorphism( mor ) );
                SetIsEpimorphism( mor, true );
                
            fi;
            
            if HasCokernelEpi( phi ) then
                alpha := GetFunctorObjCachedValue( Functor, Concatenation( arg_before_pos, [ CokernelEpi( phi ) ], arg_behind_pos ) );
                if alpha <> fail then
                    SetCokernelEpi( mor, alpha );
                fi;
            fi;
            
        fi;
        
        if IsCovariantFunctor( Functor, pos ) = false then
            
            if  HasIsMonomorphism( phi ) and IsMonomorphism( phi ) then
                
                Assert( 3, IsEpimorphism( mor ) );
                SetIsEpimorphism( mor, true );
                
            fi;
            
            if HasKernelEmb( phi ) then
                alpha := GetFunctorObjCachedValue( Functor, Concatenation( arg_before_pos, [ KernelEmb( phi ) ], arg_behind_pos ) );
                if alpha <> fail then
                    SetCokernelEpi( mor, alpha );
                fi;
            fi;
            
        fi;
        
    fi;
    
    UpdateObjectsByMorphism( mor );
    
    return mor;
    
end );

##
InstallMethod( InstallFunctorOnObjects,
        "for homalg functors",
        [ IsHomalgFunctorRep ],
        
  function( Functor )
    local genesis, der_arg, functor_operation, number_of_arguments,
          natural_transformation,
          natural_transformation1, natural_transformation2,
          natural_transformation3, natural_transformation4,
          filter_obj, filter0, filter1_obj, filter2_obj, filter3_obj;
    
    if HasGenesis( Functor ) then
        genesis := Genesis( Functor );
        if IsBound( genesis[3] ) then
            der_arg := genesis[3];
        fi;
    fi;
    
    functor_operation := OperationOfFunctor( Functor );
    
    number_of_arguments := MultiplicityOfFunctor( Functor );
    
    if number_of_arguments = 1 then
        
        if not IsBound( Functor!.1[2] ) then
            Functor!.1[2] := HOMALG.FunctorOn;
        fi;
        
        if not IsBound( Functor!.1[2][1] ) then
            return fail;
        fi;
        
        filter_obj := Functor!.1[2][1];
        
        if IsFilter( filter_obj ) then
            
            if IsBound( Functor!.0 ) and IsList( Functor!.0 ) then
                
                if Length( Functor!.0 ) = 1 then
                    filter0 := Functor!.0[1];
                else
                    filter0 := IsList;
                fi;
                
                InstallOtherMethod( functor_operation,
                        "for homalg objects",
                        [ filter0, filter_obj ],
                  function( c, o )
                    local obj;
                    
                    if IsStructureObject( o ) then
                        ## I personally prefer left objects:
                        obj := AsLeftObject( o );
                    else
                        obj := o;
                    fi;
                    
                    return FunctorObj( Functor, [ c, obj ] );
                    
                end );
                
            else
                
                if IsBound( Functor!.natural_transformation ) then
                    
                    natural_transformation := ValueGlobal( Functor!.natural_transformation );
                    
                    InstallOtherMethod( natural_transformation,
                            "for homalg objects",
                            [ filter_obj ],
                      function( o )
                        
                        functor_operation( o ); ## this should set the attribute named "natural_transformation"
                        
                        if not Tester( natural_transformation )( o ) then
                            Error( "the functor operation ", functor_operation,
                                   " did not succeed to set the attribute ",
                                   natural_transformation, "\n" );
                        fi;
                        
                        return natural_transformation( o );
                        
                    end );
                    
                fi;
                
                if IsBound( Functor!.natural_transformation1 ) then
                    
                    natural_transformation1 := ValueGlobal( Functor!.natural_transformation1 );
                    
                    InstallOtherMethod( natural_transformation1,
                            "for homalg objects",
                            [ filter_obj ],
                      function( o )
                        
                        functor_operation( o ); ## this should set the attribute named "natural_transformation"
                        
                        if not Tester( natural_transformation1 )( o ) then
                            Error( "the functor operation ", functor_operation,
                                   " did not succeed to set the attribute ",
                                   natural_transformation1, "\n" );
                        fi;
                        
                        return natural_transformation1( o );
                        
                    end );
                    
                fi;
                
                if IsBound( Functor!.natural_transformation2 ) then
                    
                    natural_transformation2 := ValueGlobal( Functor!.natural_transformation2 );
                    
                    InstallOtherMethod( natural_transformation2,
                            "for homalg objects",
                            [ filter_obj ],
                      function( o )
                        
                        functor_operation( o ); ## this should set the attribute named "natural_transformation"
                        
                        if not Tester( natural_transformation2 )( o ) then
                            Error( "the functor operation ", functor_operation,
                                   " did not succeed to set the attribute ",
                                   natural_transformation2, "\n" );
                        fi;
                        
                        return natural_transformation2( o );
                        
                    end );
                    
                fi;
                
                if IsBound( Functor!.natural_transformation3 ) then
                    
                    natural_transformation3 := ValueGlobal( Functor!.natural_transformation3 );
                    
                    InstallOtherMethod( natural_transformation3,
                            "for homalg objects",
                            [ filter_obj ],
                      function( o )
                        
                        functor_operation( o ); ## this should set the attribute named "natural_transformation"
                        
                        if not Tester( natural_transformation3 )( o ) then
                            Error( "the functor operation ", functor_operation,
                                   " did not succeed to set the attribute ",
                                   natural_transformation3, "\n" );
                        fi;
                        
                        return natural_transformation3( o );
                        
                    end );
                    
                fi;
                
                if IsBound( Functor!.natural_transformation4 ) then
                    
                    natural_transformation4 := ValueGlobal( Functor!.natural_transformation4 );
                    
                    InstallOtherMethod( natural_transformation4,
                            "for homalg objects",
                            [ filter_obj ],
                      function( o )
                        
                        functor_operation( o ); ## this should set the attribute named "natural_transformation"
                        
                        if not Tester( natural_transformation4 )( o ) then
                            Error( "the functor operation ", functor_operation,
                                   " did not succeed to set the attribute ",
                                   natural_transformation4, "\n" );
                        fi;
                        
                        return natural_transformation4( o );
                        
                    end );
                    
                fi;
                
                InstallOtherMethod( functor_operation,
                        "for homalg objects",
                        [ filter_obj ],
                  function( o )
                    local obj;
                    
                    if IsStructureObject( o ) then
                        ## I personally prefer left objects:
                        obj := AsLeftObject( o );
                    else
                        obj := o;
                    fi;
                    
                    return FunctorObj( Functor, [ obj ] );
                    
                end );
                
            fi;
            
        else
            
            Error( "wrong syntax: ", filter_obj, "\n" );
            
        fi;
        
    elif number_of_arguments = 2 then
        
        if not IsBound( Functor!.1[2] ) then
            Functor!.1[2] := HOMALG.FunctorOn;
        fi;
        
        if not IsBound( Functor!.2[2] ) then
            Functor!.2[2] := HOMALG.FunctorOn;
        fi;
        
        if not IsBound( Functor!.1[2][1] ) or not IsBound( Functor!.2[2][1] ) then
            return fail;
        fi;
        
        filter1_obj := Functor!.1[2][1];
        filter2_obj := Functor!.2[2][1];
        
        if IsFilter( filter1_obj ) and IsFilter( filter2_obj ) then
            
            if IsBound( Functor!.0 ) and IsList( Functor!.0 ) then
                
                if Length( Functor!.0 ) = 1 then
                    filter0 := Functor!.0[1];
                else
                    filter0 := IsList;
                fi;
                
                if IsDistinguishedFirstArgumentOfFunctor( Functor ) then
                    
                    InstallOtherMethod( functor_operation,
                            "for homalg objects",
                            [ filter0, filter1_obj ],
                      function( c, o )
                        local R;
                        
                        if IsStructureObject( o ) then
                            R := o;
                        else
                            R := StructureObject( o );
                        fi;
                        
                        return functor_operation( c, o, R );
                        
                    end );
                    
                    InstallOtherMethod( functor_operation,
                            "for homalg objects",
                            [ IsInt, filter1_obj, IsString ],
                      function( c, o, s )
                        local R;
                        
                        if IsStructureObject( o ) then
                            R := o;
                        else
                            R := StructureObject( o );
                        fi;
                        
                        return functor_operation( c, o, R, s );
                        
                    end );
                    
                    if IsBound( der_arg ) and der_arg = 1 then
                        
                        InstallOtherMethod( functor_operation,
                                "for homalg objects",
                                [ filter1_obj ],
                          function( o )
                            local R;
                            
                            if IsStructureObject( o ) then
                                R := o;
                            else
                                R := StructureObject( o );
                            fi;
                            
                            return functor_operation( o, R );
                            
                        end );
                        
                    fi;
                    
                fi;
                
                InstallOtherMethod( functor_operation,
                        "for homalg objects",
                        [ filter0, filter1_obj, filter2_obj ],
                  function( c, o1, o2 )
                    local obj1, obj2;
                    
                    if IsHomalgStaticObject( o1 ) and IsHomalgStaticObject( o2 ) then ## the most probable case
                        obj1 := o1;
                        obj2 := o2;
                    elif IsHomalgStaticObject( o1 ) and IsStructureObject( o2 ) then
                        obj1 := o1;
                        
                        if IsHomalgLeftObjectOrMorphismOfLeftObjects( o1 ) then
                            obj2 := AsLeftObject( o2 );
                        else
                            obj2 := AsRightObject( o2 );
                        fi;
                    elif IsStructureObject( o1 ) and IsHomalgStaticObject( o2 ) then
                        obj2 := o2;
                        
                        if IsHomalgLeftObjectOrMorphismOfLeftObjects( o2 ) then
                            obj1 := AsLeftObject( o1 );
                        else
                            obj1 := AsRightObject( o1 );
                        fi;
                    elif IsStructureObject( o1 ) and IsStructureObject( o2 ) then
                        if not IsIdenticalObj( o1, o2 ) then
                            Error( "the two rings are not identical\n" );
                        fi;
                        
                        ## I personally prefer left objects:
                        obj1 := AsLeftObject( o1 );
                        obj2 := obj1;
                    else
                        ## the default:
                        obj1 := o1;
                        obj2 := o2;
                    fi;
                    
                    return FunctorObj( Functor, [ c, obj1, obj2 ] );
                    
                end );
                
                if IsBound( der_arg ) then
                    
                    if IsCovariantFunctor( Functor, der_arg ) then
                        
                        InstallOtherMethod( functor_operation,
                                "for homalg objects",
                                [ IsInt, filter1_obj, filter2_obj, IsString ],
                          function( n, o1, o2, s )
                            local H, C, j;
                            
                            if s <> "a" then
                                TryNextMethod( );
                            fi;
                            
                            H := functor_operation( 0, o1, o2 );
                            
                            C := HomalgComplex( H );
                            
                            for j in [ 1 .. n ] do
                                
                                H := functor_operation( j, o1, o2 );
                                
                                Add( C, H );
                                
                            od;
                            
                            return C;
                            
                        end );
                        
                    else
                        
                        InstallOtherMethod( functor_operation,
                                "for homalg objects",
                                [ IsInt, filter1_obj, filter2_obj, IsString ],
                          function( n, o1, o2, s )
                            local H, C, j;
                            
                            if s <> "a" then
                                TryNextMethod( );
                            fi;
                            
                            H := functor_operation( 0, o1, o2 );
                            
                            C := HomalgCocomplex( H );
                            
                            for j in [ 1 .. n ] do
                                
                                H := functor_operation( j, o1, o2 );
                                
                                Add( C, H );
                                
                            od;
                            
                            return C;
                            
                        end );
                        
                    fi;
                    
                    InstallOtherMethod( functor_operation,
                            "for homalg objects",
                            [ filter1_obj, filter2_obj ],
                      function( o1, o2 )
                        local n;
                        
                        if der_arg = 1 then
                            n := LengthOfResolution( o1 );
                        else
                            n := LengthOfResolution( o2 );
                        fi;
                        
                        return functor_operation( n, o1, o2, "a" );
                        
                    end );
                    
                fi;
                
            else
                
                if IsDistinguishedFirstArgumentOfFunctor( Functor ) then
                    
                    InstallOtherMethod( functor_operation,
                            "for homalg objects",
                            [ filter1_obj ],
                      function( o )
                        local R;
                        
                        if IsStructureObject( o ) then
                            R := o;
                        else
                            R := StructureObject( o );
                        fi;
                        
                        return functor_operation( o, R );
                        
                    end );
                    
                fi;
                
                InstallOtherMethod( functor_operation,
                        "for homalg objects",
                        [ filter1_obj, filter2_obj ],
                  function( o1, o2 )
                    local obj1, obj2;
                    
                    if IsHomalgStaticObject( o1 ) and IsHomalgStaticObject( o2 ) then ## the most probable case
                        obj1 := o1;
                        obj2 := o2;
                    elif IsHomalgStaticObject( o1 ) and IsStructureObject( o2 ) then
                        obj1 := o1;
                        
                        if IsHomalgLeftObjectOrMorphismOfLeftObjects( o1 ) then
                            obj2 := AsLeftObject( o2 );
                        else
                            obj2 := AsRightObject( o2 );
                        fi;
                    elif IsStructureObject( o1 ) and IsHomalgStaticObject( o2 ) then
                        obj2 := o2;
                        
                        if IsHomalgLeftObjectOrMorphismOfLeftObjects( o2 ) then
                            obj1 := AsLeftObject( o1 );
                        else
                            obj1 := AsRightObject( o1 );
                        fi;
                    elif IsStructureObject( o1 ) and IsStructureObject( o2 ) then
                        if not IsIdenticalObj( o1, o2 ) then
                            Error( "the two rings are not identical\n" );
                        fi;
                        
                        ## I personally prefer left objects:
                        obj1 := AsLeftObject( o1 );
                        obj2 := obj1;
                    else
                        ## the default:
                        obj1 := o1;
                        obj2 := o2;
                    fi;
                    
                    return FunctorObj( Functor, [ obj1, obj2 ] );
                    
                end );
                
            fi;
            
        else
            
            Error( "wrong syntax: ", filter1_obj, filter2_obj, "\n" );
            
        fi;
        
    elif number_of_arguments = 3 then
        
        if not IsBound( Functor!.1[2] ) then
            Functor!.1[2] := HOMALG.FunctorOn;
        fi;
        
        if not IsBound( Functor!.2[2] ) then
            Functor!.2[2] := HOMALG.FunctorOn;
        fi;
        
        if not IsBound( Functor!.3[2] ) then
            Functor!.3[2] := HOMALG.FunctorOn;
        fi;
        
        if not IsBound( Functor!.1[2][1] ) or
           not IsBound( Functor!.2[2][1] ) or
           not IsBound( Functor!.3[2][1] ) then
            return fail;
        fi;
        
        filter1_obj := Functor!.1[2][1];
        filter2_obj := Functor!.2[2][1];
        filter3_obj := Functor!.3[2][1];
        
        if IsFilter( filter1_obj ) and
           IsFilter( filter2_obj ) and
           IsFilter( filter3_obj ) then
            
            if IsBound( Functor!.0 ) and IsList( Functor!.0 ) then
                
                if Length( Functor!.0 ) = 1 then
                    filter0 := Functor!.0[1];
                else
                    filter0 := IsList;
                fi;
                
                if IsDistinguishedFirstArgumentOfFunctor( Functor ) then
                    
                    InstallOtherMethod( functor_operation,
                            "for homalg objects",
                            [ filter0, filter1_obj ],
                      function( c, o )
                        local R;
                        
                        if IsStructureObject( o ) then
                            R := o;
                        else
                            R := StructureObject( o );
                        fi;
                        
                        return functor_operation( c, o, R, R );
                        
                    end );
                    
                    InstallOtherMethod( functor_operation,
                            "for homalg objects",
                            [ IsInt, filter1_obj, IsString ],
                      function( c, o, s )
                        local R;
                        
                        if IsStructureObject( o ) then
                            R := o;
                        else
                            R := StructureObject( o );
                        fi;
                        
                        return functor_operation( c, o, R, R, s );
                        
                    end );
                    
                fi;
                
                InstallOtherMethod( functor_operation,
                        "for homalg objects",
                        [ filter0, filter1_obj, filter2_obj, filter3_obj ],
                  function( c, o1, o2, o3 )
                    local obj1, obj2, obj3;
                    
                    if IsHomalgStaticObject( o1 ) and
                       IsHomalgStaticObject( o2 ) and
                       IsHomalgStaticObject( o3 ) then ## the most probable case
                        obj1 := o1;
                        obj2 := o2;
                        obj3 := o3;
                    elif IsHomalgStaticObject( o1 ) and IsStructureObject( o2 ) and IsStructureObject( o3 ) then
                        obj1 := o1;
                        
                        if not IsIdenticalObj( o2, o3 ) then
                            Error( "the last two rings are not identical\n" );
                        fi;
                        
                        if IsHomalgLeftObjectOrMorphismOfLeftObjects( o1 ) then
                            obj2 := AsLeftObject( o2 );
                            obj3 := AsLeftObject( o3 );
                        else
                            obj2 := AsRightObject( o2 );
                            obj3 := AsRightObject( o3 );
                        fi;
                    ## FIXME: there are missing cases
                    elif ForAll( [ o1, o2, o3 ], IsStructureObject ) then
                        if not IsIdenticalObj( o1, o2 ) then
                            Error( "the first two rings are not identical\n" );
                        elif not IsIdenticalObj( o2, o3 ) then
                            Error( "the last two rings are not identical\n" );
                        fi;
                        
                        ## I personally prefer left objects:
                        obj1 := AsLeftObject( o1 );
                        obj2 := obj1;
                        obj3 := obj1;
                    else
                        ## the default:
                        obj1 := o1;
                        obj2 := o2;
                        obj3 := o3;
                    fi;
                    
                    return FunctorObj( Functor, [ c, obj1, obj2, obj3 ] );
                    
                end );
                
                if IsBound( der_arg ) then
                    
                    if IsCovariantFunctor( Functor, der_arg ) then
                        
                        InstallOtherMethod( functor_operation,
                                "for homalg objects",
                                [ IsInt, filter1_obj, filter2_obj, filter3_obj, IsString ],
                          function( n, o1, o2, o3, s )
                            local H, C, j;
                            
                            if s <> "a" then
                                TryNextMethod( );
                            fi;
                            
                            H := functor_operation( 0, o1, o2, o3 );
                            
                            C := HomalgComplex( H );
                            
                            for j in [ 1 .. n ] do
                                
                                H := functor_operation( j, o1, o2, o3 );
                                
                                Add( C, H );
                                
                            od;
                            
                            return C;
                            
                        end );
                        
                    else
                        
--> --------------------

--> maximum size reached

--> --------------------

[ Dauer der Verarbeitung: 0.49 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge