Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/pkg/cap/gap/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 22.8.2025 mit Größe 134 kB image not shown  

Quelle  DerivedMethods.gi   Sprache: unbekannt

 
# SPDX-License-Identifier: GPL-2.0-or-later
# CAP: Categories, Algorithms, Programming
#
# Implementations
#

###########################
##
## In a terminal category
##
###########################

AddDerivationToCAP( IsLiftable,
                    "Two morphisms with equal targets are mutually liftable in a terminal category",
                    [  ],
                    
  function( cat, morphism1, morphism2 )
        
    ## equality of targets is part of the specification of the input and checked by the pre-function
    return true;
    
end : CategoryFilter := IsTerminalCategory );

###########################
##
## In a finite category
##
###########################

##
AddDerivationToCAP( SetOfMorphismsOfFiniteCategory,
        "SetOfMorphismsOfFiniteCategory using SetOfObjectsOfCategory and MorphismsOfExternalHom",
        [ [ SetOfObjectsOfCategory, 1 ],
          [ MorphismsOfExternalHom, 4 ] ],
        
  function( C )
    local objs;
    
    objs := SetOfObjectsOfCategory( C );
    
    ## varying the target (column-index) before varying the source ("row"-index)
    ## in the for-loops below is enforced by SetOfMorphismsOfFiniteCategory for IsCategoryFromNerveData,
    ## which in turn is enforced by our convention for ProjectionInFactorOfDirectProduct in SkeletalFinSets,
    ## which is the "double-reverse" convention of the GAP command Cartesian:
    
    # gap> A := FinSet( 3 );
    # |3|
    # gap> B := FinSet( 4 );
    # |4|
    # gap> data := List( [ A, B ], AsList );
    # [ [ 0 .. 2 ], [ 0 .. 3 ] ]
    # gap> pi1 := ProjectionInFactorOfDirectProduct( [ A, B ], 1 );
    # |12| → |3|
    # gap> pi2 := ProjectionInFactorOfDirectProduct( [ A, B ], 2 );
    # |12| → |4|
    # gap> List( [ 0 .. 11 ], i -> [ pi1(i), pi2(i) ] );
    # [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ], [ 0, 1 ], [ 1, 1 ], [ 2, 1 ], [ 0, 2 ], [ 1, 2 ], [ 2, 2 ], [ 0, 3 ], [ 1, 3 ], [ 2, 3 ] ]
    # gap> List( Cartesian( Reversed( data ) ), Reversed );
    # [ [ 0, 0 ], [ 1, 0 ], [ 2, 0 ], [ 0, 1 ], [ 1, 1 ], [ 2, 1 ], [ 0, 2 ], [ 1, 2 ], [ 2, 2 ], [ 0, 3 ], [ 1, 3 ], [ 2, 3 ] ]
    # gap> L1 = L2;
    # true
    # gap> Cartesian( data );
    # [ [ 0, 0 ], [ 0, 1 ], [ 0, 2 ], [ 0, 3 ], [ 1, 0 ], [ 1, 1 ], [ 1, 2 ], [ 1, 3 ], [ 2, 0 ], [ 2, 1 ], [ 2, 2 ], [ 2, 3 ] ]
    # gap> L1 = L3;
    # false
    
    return Concatenation( List( objs, t ->
                   Concatenation( List( objs, s ->
                           MorphismsOfExternalHom( C, s, t ) ) ) ) );
    
end : CategoryFilter := cat -> HasIsFiniteCategory( cat ) and IsFiniteCategory( cat ) );

###########################
##
## WithGiven pairs
##
###########################

AddDerivationToCAP( MorphismFromKernelObjectToSink,
                    "MorphismFromKernelObjectToSink as zero morphism from kernel object to range",
                    [ [ KernelObject, 1 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat, alpha )
    local K;
    
    K := KernelObject( cat, alpha );
    
    return ZeroMorphism( cat, K, Range( alpha ) );
    
  end );

##
AddDerivationToCAP( KernelLift,
                    "KernelLift using LiftAlongMonomorphism and KernelEmbedding",
                    [ [ LiftAlongMonomorphism, 1 ],
                      [ KernelEmbedding, 1 ] ],
                    
  function( cat, mor, test_object, test_morphism )
    
    return LiftAlongMonomorphism( cat, KernelEmbedding( cat, mor ), test_morphism );
    
  end );

##
AddDerivationToCAP( KernelLiftWithGivenKernelObject,
                    "KernelLift using LiftAlongMonomorphism and KernelEmbedding",
                    [ [ LiftAlongMonomorphism, 1 ],
                      [ KernelEmbeddingWithGivenKernelObject, 1 ] ],
                    
  function( cat, mor, test_object, test_morphism, kernel )
    
    return LiftAlongMonomorphism( cat, KernelEmbeddingWithGivenKernelObject( cat, mor, kernel ), test_morphism );
    
end );

##
AddDerivationToCAP( UniversalMorphismIntoDirectSum,
                    "UniversalMorphismIntoDirectSum using the injections of the direct sum",
                    [ [ PreCompose, 2 ],
                      [ InjectionOfCofactorOfDirectSum, 2 ],
                      [ SumOfMorphisms, 1 ],
                      [ DirectSum, 1 ] ],
                    
  function( cat, diagram, test_object, source )
    local nr_components;
    
    nr_components := Length( source );
    
    return SumOfMorphisms( cat,
        test_object,
        List( [ 1 .. nr_components ], i -> PreCompose( cat, source[ i ], InjectionOfCofactorOfDirectSum( cat, diagram, i ) ) ),
        DirectSum( cat, diagram )
    );
    
  end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( UniversalMorphismIntoDirectSumWithGivenDirectSum,
                    "UniversalMorphismIntoDirectSum using the injections of the direct sum",
                    [ [ PreCompose, 2 ],
                      [ InjectionOfCofactorOfDirectSumWithGivenDirectSum, 2 ],
                      [ SumOfMorphisms, 1 ] ],
                    
  function( cat, diagram, test_object, source, direct_sum )
    local nr_components;
    
    nr_components := Length( source );
  
    return SumOfMorphisms( cat,
        test_object,
        List( [ 1 .. nr_components ], i -> PreCompose( cat, source[ i ], InjectionOfCofactorOfDirectSumWithGivenDirectSum( cat, diagram, i, direct_sum ) ) ),
        direct_sum
    );
  
end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( ProjectionInFactorOfDirectSum,
                    "ProjectionInFactorOfDirectSum using UniversalMorphismFromDirectSum",
                    [ [ IdentityMorphism, 1 ],
                      [ ZeroMorphism, 2 ],
                      [ UniversalMorphismFromDirectSum, 1 ] ],
                    
  function( cat, list, projection_number )
    local id, morphisms;
    
    id := IdentityMorphism( cat, list[projection_number] );
    
    morphisms := List( [ 1 .. Length( list ) ], function( i )
        
        if i = projection_number then
            
            return id;
            
        else
            
            return ZeroMorphism( cat, list[i], list[projection_number] );
            
        fi;
        
    end );
    
    return UniversalMorphismFromDirectSum( cat, list, list[projection_number], morphisms );
    
  end );

##
AddDerivationToCAP( ProjectionInFactorOfDirectSumWithGivenDirectSum,
                    "ProjectionInFactorOfDirectSum using UniversalMorphismFromDirectSum",
                    [ [ IdentityMorphism, 1 ],
                      [ ZeroMorphism, 2 ],
                      [ UniversalMorphismFromDirectSumWithGivenDirectSum, 1 ] ],
                    
  function( cat, list, projection_number, direct_sum_object )
    local id, morphisms;
    
    id := IdentityMorphism( cat, list[projection_number] );
    
    morphisms := List( [ 1 .. Length( list ) ], function( i )
        
        if i = projection_number then
            
            return id;
            
        else
            
            return ZeroMorphism( cat, list[i], list[projection_number] );
            
        fi;
        
    end );
    
    return UniversalMorphismFromDirectSumWithGivenDirectSum( cat, list, list[projection_number], morphisms, direct_sum_object );
    
end );

##
AddDerivationToCAP( UniversalMorphismIntoTerminalObject,
                    "UniversalMorphismIntoTerminalObject computing the zero morphism",
                    [ [ TerminalObject, 1 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat, test_source )
    local terminal_object;
    
    terminal_object := TerminalObject( cat );
    
    return ZeroMorphism( cat, test_source, terminal_object );
    
  end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( UniversalMorphismIntoTerminalObjectWithGivenTerminalObject,
                    "UniversalMorphismIntoTerminalObject computing the zero morphism",
                    [ [ ZeroMorphism, 1 ] ],
                    
  function( cat, test_source, terminal_object )
    
    return ZeroMorphism( cat, test_source, terminal_object );
    
end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( UniversalMorphismIntoZeroObject,
                    "UniversalMorphismIntoZeroObject computing the zero morphism",
                    [ [ ZeroObject, 1 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat, test_source )
    local zero_object;
    
    zero_object := ZeroObject( cat );
    
    return ZeroMorphism( cat, test_source, zero_object );
    
  end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( UniversalMorphismIntoZeroObjectWithGivenZeroObject,
                    "UniversalMorphismIntoZeroObject computing the zero morphism",
                    [ [ ZeroMorphism, 1 ] ],
                    
  function( cat, test_source, zero_object )
    
    return ZeroMorphism( cat, test_source, zero_object );
    
end : CategoryFilter := IsAdditiveCategory );

## FiberProduct from DirectProduct and Equalizer

##
AddDerivationToCAP( FiberProduct,
                    "FiberProduct as the source of IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram",
                    [ [ IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram, 1 ] ],
                    
  function( cat, diagram )
    
    return Source( IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram( cat, diagram ) );
    
end );

##
AddDerivationToCAP( ProjectionInFactorOfFiberProduct,
                    "ProjectionInFactorOfFiberProduct by composing the embedding of equalizer with the direct product projection",
                    [ [ ProjectionInFactorOfDirectProductWithGivenDirectProduct, 2 ],
                      [ PreCompose, 3 ],
                      [ EmbeddingOfEqualizer, 1 ],
                      [ DirectProduct, 1 ],
                      [ ComponentOfMorphismIntoDirectProduct, 1 ],
                      [ IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram, 1 ] ],
                    
  function( cat, diagram, projection_number )
    local D, direct_product, diagram_of_equalizer, iota;
    
    D := List( diagram, Source );
    
    direct_product := DirectProduct( cat, D );
    
    diagram_of_equalizer := List( [ 1 .. Length( D ) ], i -> PreCompose( cat, ProjectionInFactorOfDirectProductWithGivenDirectProduct( cat, D, i, direct_product ), diagram[i] ) );
    
    iota := EmbeddingOfEqualizer( cat, direct_product, diagram_of_equalizer );
    
    return PreCompose( cat, IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram( cat, diagram ), ComponentOfMorphismIntoDirectProduct( cat, iota, D, projection_number ) );
    
  end );

##
AddDerivationToCAP( UniversalMorphismIntoFiberProduct,
                    "UniversalMorphismIntoFiberProduct as the universal morphism into equalizer of a univeral morphism into direct product",
                    [ [ ProjectionInFactorOfDirectProductWithGivenDirectProduct, 2 ],
                      [ PreCompose, 3 ],
                      [ UniversalMorphismIntoDirectProduct, 1 ],
                      [ UniversalMorphismIntoEqualizer, 1 ],
                      [ DirectProduct, 1 ],
                      [ IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct, 1 ] ],
                    
  function( cat, diagram, test_object, tau )
    local D, direct_product, diagram_of_equalizer, chi, psi;
    
    D := List( diagram, Source );
    
    direct_product := DirectProduct( cat, D );
    
    diagram_of_equalizer := List( [ 1 .. Length( D ) ], i -> PreCompose( cat, ProjectionInFactorOfDirectProductWithGivenDirectProduct( cat, D, i, direct_product ), diagram[i] ) );
    
    chi := UniversalMorphismIntoDirectProduct( cat, D, test_object, tau );

    psi := UniversalMorphismIntoEqualizer( cat, direct_product, diagram_of_equalizer, test_object, chi );
    
    return PreCompose( cat, psi, IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct( cat, diagram ) );
    
  end );

##
AddDerivationToCAP( MorphismFromFiberProductToSink,
                    "MorphismFromFiberProductToSink by composing the first projection with the first morphism in the diagram",
                    [ [ ProjectionInFactorOfFiberProduct, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, diagram )
    local pi_1;
    
    pi_1 := ProjectionInFactorOfFiberProduct( cat, diagram, 1 );
    
    return PreCompose( cat, pi_1, diagram[1] );
    
  end );

##
AddDerivationToCAP( UniversalMorphismIntoZeroObject,
                    "UniversalMorphismIntoZeroObject using UniversalMorphismIntoTerminalObject",
                    [ [ UniversalMorphismIntoTerminalObject, 1 ],
                      [ IsomorphismFromTerminalObjectToZeroObject, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, obj )
    
    return PreCompose( cat, UniversalMorphismIntoTerminalObject( cat, obj ),
                       IsomorphismFromTerminalObjectToZeroObject( cat ) );
  end );

##
AddDerivationToCAP( ProjectionInFactorOfDirectSum,
                    "ProjectionInFactorOfDirectSum using ProjectionInFactorOfDirectProduct",
                    [ [ IsomorphismFromDirectSumToDirectProduct, 1 ],
                      [ ProjectionInFactorOfDirectProduct, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, diagram, projection_number )
    
    return PreCompose( cat, IsomorphismFromDirectSumToDirectProduct( cat, diagram ),
                       ProjectionInFactorOfDirectProduct( cat, diagram, projection_number ) );
    
  end );

##
AddDerivationToCAP( UniversalMorphismIntoDirectSum,
                    "UniversalMorphismIntoDirectSum using UniversalMorphismIntoDirectProduct",
                    [ [ UniversalMorphismIntoDirectProduct, 1 ],
                      [ IsomorphismFromDirectProductToDirectSum, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, diagram, test_object, source )
    
    return PreCompose( cat, UniversalMorphismIntoDirectProduct( cat, diagram, test_object, source ),
                       IsomorphismFromDirectProductToDirectSum( cat, diagram ) );
  end );

##
AddDerivationToCAP( ComponentOfMorphismIntoDirectSum,
                    "ComponentOfMorphismIntoDirectSum using ComponentOfMorphismIntoDirectProduct",
                    [ [ IsomorphismFromDirectSumToDirectProduct, 1 ],
                      [ ComponentOfMorphismIntoDirectProduct, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, alpha, summands, nr )
    
    return ComponentOfMorphismIntoDirectProduct( cat,
        PreCompose( cat, alpha, IsomorphismFromDirectSumToDirectProduct( cat, summands ) ),
        summands,
        nr
    );
    
  end );

##
AddDerivationToCAP( UniversalMorphismIntoTerminalObject,
                    "UniversalMorphismFromInitialObject using UniversalMorphismFromZeroObject",
                    [ [ UniversalMorphismIntoZeroObject, 1 ],
                      [ IsomorphismFromZeroObjectToTerminalObject, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, obj )
    
    return PreCompose( cat, UniversalMorphismIntoZeroObject( cat, obj ),
                       IsomorphismFromZeroObjectToTerminalObject( cat ) );
    
  end );

##
AddDerivationToCAP( ProjectionInFactorOfDirectProduct,
                    "ProjectionInFactorOfDirectProduct using ProjectionInFactorOfDirectSum",
                    [ [ IsomorphismFromDirectProductToDirectSum, 1 ],
                      [ ProjectionInFactorOfDirectSum, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, diagram, projection_number )
    
    return PreCompose( cat, IsomorphismFromDirectProductToDirectSum( cat, diagram ),
                       ProjectionInFactorOfDirectSum( cat, diagram, projection_number ) );
  end );

##
AddDerivationToCAP( UniversalMorphismIntoDirectProduct,
                    "UniversalMorphismIntoDirectProduct using UniversalMorphismIntoDirectSum",
                    [ [ UniversalMorphismIntoDirectSum, 1 ],
                      [ IsomorphismFromDirectSumToDirectProduct, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, diagram, test_object, source )
    
    return PreCompose( cat, UniversalMorphismIntoDirectSum( cat, diagram, test_object, source ),
                       IsomorphismFromDirectSumToDirectProduct( cat, diagram ) );
    
  end );

##
AddDerivationToCAP( ComponentOfMorphismIntoDirectProduct,
                    "ComponentOfMorphismIntoDirectProduct using ComponentOfMorphismIntoDirectSum",
                    [ [ IsomorphismFromDirectProductToDirectSum, 1 ],
                      [ ComponentOfMorphismIntoDirectSum, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, alpha, factors, nr )
    
    return ComponentOfMorphismIntoDirectSum( cat,
        PreCompose( cat, alpha, IsomorphismFromDirectProductToDirectSum( cat, factors ) ),
        factors,
        nr
    );
    
  end );

##
AddDerivationToCAP( UniversalMorphismIntoEqualizer,
                    "UniversalMorphismIntoEqualizer using the universality of the kernel representation of the equalizer",
                    [ [ JointPairwiseDifferencesOfMorphismsIntoDirectProduct, 1 ],
                      [ KernelLift, 1 ],
                      [ IsomorphismFromKernelOfJointPairwiseDifferencesOfMorphismsIntoDirectProductToEqualizer, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, A, diagram, test_object, tau )
    local joint_pairwise_differences, kernel_lift;
    
    joint_pairwise_differences := JointPairwiseDifferencesOfMorphismsIntoDirectProduct( cat, A, diagram );
    
    kernel_lift := KernelLift( cat, joint_pairwise_differences, test_object, tau );
    
    return PreCompose( cat,
             kernel_lift,
             IsomorphismFromKernelOfJointPairwiseDifferencesOfMorphismsIntoDirectProductToEqualizer( cat, A, diagram )
           );
    
  end );

##
AddDerivationToCAP( ImageEmbedding,
                    "ImageEmbedding as the kernel embedding of the cokernel projection",
                    [ [ CokernelProjection, 1 ],
                      [ KernelEmbedding, 1 ],
                      [ IsomorphismFromImageObjectToKernelOfCokernel, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, mor )
    local image_embedding;
    
    image_embedding := KernelEmbedding( cat, CokernelProjection( cat, mor ) );
    
    return PreCompose( cat, IsomorphismFromImageObjectToKernelOfCokernel( cat, mor ),
                       image_embedding );
  
  end : CategoryFilter := IsPreAbelianCategory );

##
AddDerivationToCAP( CoastrictionToImage,
                    "CoastrictionToImage using that image embedding can be seen as a kernel",
                    [ [ ImageEmbedding, 1 ],
                      [ LiftAlongMonomorphism, 1 ] ],
                    
  function( cat, morphism )
    local image_embedding;
    
    image_embedding := ImageEmbedding( cat, morphism );
    
    return LiftAlongMonomorphism( cat, image_embedding, morphism );
  
  end );

##
AddDerivationToCAP( CoastrictionToImageWithGivenImageObject,
                    "CoastrictionToImage using that image embedding can be seen as a kernel",
                    [ [ ImageEmbeddingWithGivenImageObject, 1 ],
                      [ LiftAlongMonomorphism, 1 ] ],
                    
  function( cat, morphism, image )
    local image_embedding;
    
    image_embedding := ImageEmbeddingWithGivenImageObject( cat, morphism, image );
    
    return LiftAlongMonomorphism( cat, image_embedding, morphism );
  
end );

##
AddDerivationToCAP( UniversalMorphismFromImage,
                    "UniversalMorphismFromImage using ImageEmbedding and LiftAlongMonomorphism",
                    [ [ ImageEmbedding, 1 ],
                      [ LiftAlongMonomorphism, 1 ] ],
                    
  function( cat, morphism, test_factorization )
    local image_embedding;
    
    image_embedding := ImageEmbedding( cat, morphism );
    
    return LiftAlongMonomorphism( cat, test_factorization[2], image_embedding );
    
  end );

##
AddDerivationToCAP( UniversalMorphismFromImageWithGivenImageObject,
                    "UniversalMorphismFromImageWithGivenImageObject using ImageEmbeddingWithGivenImageObject and LiftAlongMonomorphism",
                    [ [ ImageEmbeddingWithGivenImageObject, 1 ],
                      [ LiftAlongMonomorphism, 1 ] ],
                    
  function( cat, morphism, test_factorization, image )
    local image_embedding;
    
    image_embedding := ImageEmbeddingWithGivenImageObject( cat, morphism, image );
    
    return LiftAlongMonomorphism( cat, test_factorization[2], image_embedding );
    
end );

##
AddDerivationToCAP( UniversalMorphismIntoEqualizer,
                    "UniversalMorphismIntoEqualizer using LiftAlongMonomorphism and EmbeddingOfEqualizer",
                    [ [ LiftAlongMonomorphism, 1 ],
                      [ EmbeddingOfEqualizer, 1 ] ],
                    
  function( cat, A, diagram, test_object, test_morphism )
    
    return LiftAlongMonomorphism( cat, EmbeddingOfEqualizer( cat, A, diagram ), test_morphism );
    
  end );

##
AddDerivationToCAP( UniversalMorphismIntoEqualizerWithGivenEqualizer,
                    "UniversalMorphismIntoEqualizer using LiftAlongMonomorphism and EmbeddingOfEqualizer",
                    [ [ LiftAlongMonomorphism, 1 ],
                      [ EmbeddingOfEqualizerWithGivenEqualizer, 1 ] ],
                    
  function( cat, A, diagram, test_object, test_morphism, equalizer )
    
    return LiftAlongMonomorphism( cat, EmbeddingOfEqualizerWithGivenEqualizer( cat, A, diagram, equalizer ), test_morphism );
    
end );

##
AddDerivationToCAP( MorphismFromEqualizerToSink,
                    "MorphismFromEqualizerToSink by composing the embedding with the first morphism in the diagram",
                    [ [ EmbeddingOfEqualizer, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, A, diagram )
    local iota;
    
    iota := EmbeddingOfEqualizer( cat, A, diagram );
    
    return PreCompose( cat, iota, diagram[1] );
    
  end );

##
AddDerivationToCAP( ImageObjectFunctorialWithGivenImageObjects,
                    "ImageObjectFunctorialWithGivenImageObjects using the universality",
                    [ [ LiftAlongMonomorphism, 1 ],
                      [ ImageEmbeddingWithGivenImageObject, 2 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, I, alpha, nu, alphap, Ip )
    
    return LiftAlongMonomorphism( cat,
                   ImageEmbeddingWithGivenImageObject( cat, alphap, Ip ),
                   PreCompose( cat, ImageEmbeddingWithGivenImageObject( cat, alpha, I ), nu ) );
    
end );

##
AddDerivationToCAP( ProjectiveCoverObject,
                    "ProjectiveCoverObject as the source of EpimorphismFromProjectiveCoverObject",
                    [ [ EpimorphismFromProjectiveCoverObject, 1 ] ],
                    
  function( cat, obj )
    
    return Source( EpimorphismFromProjectiveCoverObject( cat, obj ) );
    
end );

###########################
##
## Methods returning a boolean
##
###########################

##
AddDerivationToCAP( IsEqualForObjects,
                    "skeletality",
                    [ [ IsIsomorphicForObjects, 1 ] ],
                    
  function( cat, object_1, object_2 )
    
    return IsIsomorphicForObjects( cat, object_1, object_2 );
    
end : CategoryFilter := IsSkeletalCategory );

##
AddDerivationToCAP( IsIsomorphicForObjects,
                    "skeletality",
                    [ [ IsEqualForObjects, 1 ] ],
                    
  function( cat, object_1, object_2 )
    
    return IsEqualForObjects( cat, object_1, object_2 );
    
end : CategoryFilter := IsSkeletalCategory );

##
AddDerivationToCAP( IsBijectiveObject,
                    "IsBijectiveObject by checking if the object is both projective and injective",
                    [ [ IsProjective, 1 ],
                      [ IsInjective, 1 ] ],
                    
  function( cat, object )
    
    return IsProjective( cat, object ) and IsInjective( cat, object );
    
end );

##
AddDerivationToCAP( IsProjective,
                    "IsProjective by checking if the object is a retract of some projective object",
                    [ [ EpimorphismFromSomeProjectiveObject, 1 ],
                      [ IsSplitEpimorphism, 1 ] ],
                    
  function( cat, object )
    
    return IsSplitEpimorphism( cat, EpimorphismFromSomeProjectiveObject( cat, object ) );
    
end );

##
AddDerivationToCAP( IsOne,
                    "IsOne by comparing with the identity morphism",
                    [ [ IdentityMorphism, 1 ],
                      [ IsCongruentForMorphisms, 1 ] ],
                    
  function( cat, morphism )
    local object;
    
    object := Source( morphism );
    
    return IsCongruentForMorphisms( cat, IdentityMorphism( cat, object ), morphism );
    
end );

##
AddDerivationToCAP( IsEndomorphism,
                    "IsEndomorphism by deciding whether source and range are equal as objects",
                    [ [ IsEqualForObjects, 1 ] ],
                    
  function( cat, morphism )
    
    return IsEqualForObjects( cat, Source( morphism ), Range( morphism ) );
    
end );

##
AddDerivationToCAP( IsAutomorphism,
                    "IsAutomorphism by checking IsEndomorphism and IsIsomorphism",
                    [ [ IsEndomorphism, 1 ],
                      [ IsIsomorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsEndomorphism( cat, morphism ) and IsIsomorphism( cat, morphism );
    
end );

##
AddDerivationToCAP( IsZeroForMorphisms,
                    "IsZeroForMorphisms by deciding whether the given morphism is congruent to the zero morphism",
                    [ [ ZeroMorphism, 1 ],
                      [ IsCongruentForMorphisms, 1 ] ],
                    
  function( cat, morphism )
    local zero_morphism;
    
    zero_morphism := ZeroMorphism( cat, Source( morphism ), Range( morphism ) );
    
    return IsCongruentForMorphisms( cat, zero_morphism, morphism );
    
end );

##
AddDerivationToCAP( IsEqualToIdentityMorphism,
                    "IsEqualToIdentityMorphism using IsEqualForMorphismsOnMor and IdentityMorphism",
                    [ [ IsEqualForMorphismsOnMor, 1 ],
                      [ IdentityMorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsEqualForMorphismsOnMor( cat, morphism, IdentityMorphism( cat, Source( morphism ) ) );
    
end );

##
AddDerivationToCAP( IsEqualToZeroMorphism,
                    "IsEqualToZeroMorphism using IsEqualForMorphisms and ZeroMorphism",
                    [ [ IsEqualForMorphisms, 1 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsEqualForMorphisms( cat, morphism, ZeroMorphism( cat, Source( morphism ), Range( morphism ) ) );
    
end );

##
AddDerivationToCAP( IsZeroForObjects,
                    "IsZeroForObjects by comparing identity morphism with zero morphism",
                    [ [ IsCongruentForMorphisms, 1 ],
                      [ IdentityMorphism, 1 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat, object )
  
    return IsCongruentForMorphisms( cat, IdentityMorphism( cat, object ), ZeroMorphism( cat, object, object ) );
    
end );

##
AddDerivationToCAP( IsTerminal,
                    "IsTerminal using IsZeroForObjects",
                    [ [ IsZeroForObjects, 1 ] ],
                    
  function( cat, object )
    
    return IsZeroForObjects( cat, object );
    
end : CategoryFilter := IsAdditiveCategory ); #Ab-Category?

##
AddDerivationToCAP( IsTerminal,
                    "IsTerminal using IsIsomorphism( cat, UniversalMorphismIntoTerminalObject )",
                    [ [ IsIsomorphism, 1 ],
                      [ UniversalMorphismIntoTerminalObject, 1 ] ],
                    
  function( cat, object )
    
    return IsIsomorphism( cat, UniversalMorphismIntoTerminalObject( cat, object ) );
    
end );

##
AddDerivationToCAP( IsWellDefinedForMorphismsWithGivenSourceAndRange,
                    "checking that source and range coincide with the given ones and then checking well-definedness as usual",
                    [ [ IsEqualForObjects, 2 ],
                      [ IsWellDefinedForMorphisms, 1 ] ],
                    
  function( cat, source, morphism, range )
    
    # Mathematically, we would first like to check if `morphism` has the expected source and range.
    # However, `IsEqualForObjects` expects well-defined objects, so we first have to check if source and range
    # of `morphism` are well-defined. We do this via `IsWellDefinedForMorphisms`, which checks well-definedness of
    # source and range via a redirect function.
    return IsWellDefinedForMorphisms( cat, morphism ) and
           IsEqualForObjects( cat, Source( morphism ), source ) and
           IsEqualForObjects( cat, Range( morphism ), range );
    
end );

##
AddDerivationToCAP( IsEqualForMorphismsOnMor,
                    "IsEqualForMorphismsOnMor using IsEqualForMorphisms",
                    [ [ IsEqualForMorphisms, 1 ],
                      [ IsEqualForObjects, 2 ] ],
                    
  function( cat, morphism_1, morphism_2 )
    local value_1, value_2;
    
    value_1 := IsEqualForObjects( cat, Source( morphism_1 ), Source( morphism_2 ) );
    
    value_2 := IsEqualForObjects( cat, Range( morphism_1 ), Range( morphism_2 ) );
    
    if value_1 and value_2 then
        
        return IsEqualForMorphisms( cat, morphism_1, morphism_2 );
        
    else
        
        return false;
        
    fi;
    
end );

##
AddDerivationToCAP( IsIdempotent,
                    "IsIdempotent by comparing the square of the morphism with itself",
                    [ [ IsCongruentForMorphisms, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, morphism )
    
    return IsCongruentForMorphisms( cat, PreCompose( cat, morphism, morphism ), morphism );
    
end );

##
AddDerivationToCAP( IsMonomorphism,
                    "IsMonomorphism by deciding if the kernel is a zero object",
                    [ [ IsZeroForObjects, 1 ],
                      [ KernelObject, 1 ] ],
                    
  function( cat, morphism )
    
    return IsZeroForObjects( cat, KernelObject( cat, morphism ) );
    
end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( IsMonomorphism,
                    "IsMonomorphism by deciding if the diagonal morphism is an isomorphism",
                    [ [ IsIsomorphism, 1 ],
                      [ IdentityMorphism, 1 ],
                      [ UniversalMorphismIntoFiberProduct, 1 ] ],
                    
  function( cat, morphism )
    local pullback_diagram, pullback_projection_1, pullback_projection_2, identity, diagonal_morphism;
      
      pullback_diagram := [ morphism, morphism ];
      
      identity := IdentityMorphism( cat, Source( morphism ) );
      
      diagonal_morphism := UniversalMorphismIntoFiberProduct( cat, pullback_diagram, Source( morphism ), [ identity, identity ] );
      
      return IsIsomorphism( cat, diagonal_morphism );
    
end );

##
AddDerivationToCAP( IsIsomorphism,
                    "IsIsomorphism by deciding if it is a mono and an epi",
                    [ [ IsMonomorphism, 1 ],
                      [ IsEpimorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsMonomorphism( cat, morphism ) and IsEpimorphism( cat, morphism );
    
end : CategoryFilter := IsAbelianCategory );

##
AddDerivationToCAP( IsIsomorphism,
                    "IsIsomorphism by deciding if it is a split mono and a split epi",
                    [ [ IsSplitMonomorphism, 1 ],
                      [ IsSplitEpimorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsSplitMonomorphism( cat, morphism ) and IsSplitEpimorphism( cat, morphism );
    
end );

##
AddDerivationToCAP( IsIsomorphism,
                    "IsIsomorphism by deciding if it is a split mono and an epi",
                    [ [ IsSplitMonomorphism, 1 ],
                      [ IsEpimorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsSplitMonomorphism( cat, morphism ) and IsEpimorphism( cat, morphism );
    
end );

##
AddDerivationToCAP( IsSplitMonomorphism,
                    "IsSplitMonomorphism by using IsColiftable",
                    [ [ IsColiftable, 1 ],
                      [ IdentityMorphism, 1 ] ],
                    
  function( cat, morphism )
    
    return IsColiftable( cat, morphism, IdentityMorphism( cat, Source( morphism ) ) );
  
end );

##
AddDerivationToCAP( IsEqualAsSubobjects,
                    "IsEqualAsSubobjects(sub1, sub2) if sub1 dominates sub2 and vice versa",
                    [ [ IsDominating, 2 ] ],
                    
  function( cat, sub1, sub2 )
    
    return IsDominating( cat, sub1, sub2 ) and IsDominating( cat, sub2, sub1 );
    
end );

##
AddDerivationToCAP( IsDominating,
                    "IsDominating using IsLiftableAlongMonomorphism",
                    [ [ IsLiftableAlongMonomorphism, 1 ] ],
                    
  function( cat, sub1, sub2 )
    
    return IsLiftableAlongMonomorphism( cat, sub2, sub1 );
    
end );

##
AddDerivationToCAP( IsDominating,
                    "IsDominating using IsCodominating and duality by cokernel",
                    [ [ CokernelProjection, 2 ],
                      [ IsCodominating, 1 ] ],
                    
  function( cat, sub1, sub2 )
    local cokernel_projection_1, cokernel_projection_2;
    
    cokernel_projection_1 := CokernelProjection( cat, sub1 );
    
    cokernel_projection_2 := CokernelProjection( cat, sub2 );
    
    return IsCodominating( cat, cokernel_projection_2, cokernel_projection_1 );
    
end : CategoryFilter := IsAbelianCategory );

##
AddDerivationToCAP( IsDominating,
                    "IsDominating(sub1, sub2) by deciding if sub1 composed with CokernelProjection(cat, sub2) is zero",
                    [ [ CokernelProjection, 1 ],
                      [ PreCompose, 1 ],
                      [ IsZeroForMorphisms, 1 ] ],
                    
  function( cat, sub1, sub2 )
    local cokernel_projection, composition;
    
    cokernel_projection := CokernelProjection( cat, sub2 );
    
    composition := PreCompose( cat, sub1, cokernel_projection );
    
    return IsZeroForMorphisms( cat, composition );
    
end );

##
AddDerivationToCAP( IsLiftableAlongMonomorphism,
                    "IsLiftableAlongMonomorphism using IsLiftable",
                    [ [ IsLiftable, 1 ] ],
                    
  function( cat, iota, tau )
    
    return IsLiftable( cat, tau, iota );
    
end );

##
AddDerivationToCAP( IsProjective,
                    "",
                    [ [ EpimorphismFromProjectiveCoverObject, 1 ],
                      [ IsIsomorphism, 1 ] ],
                    
  function( cat, alpha )
    
    return IsIsomorphism( cat, EpimorphismFromProjectiveCoverObject( cat, alpha ) );
    
end );

###########################
##
## Methods returning a morphism where the source and range can directly be read of from the input
##
###########################

##
AddDerivationToCAP( SomeIsomorphismBetweenObjects,
                    "skeletality",
                    [ [ IdentityMorphism, 1 ] ],
                    
  function( cat, object_1, object_2 )
    
    return IdentityMorphism( cat, object_1 );
    
end : CategoryFilter := IsSkeletalCategory );

##
AddDerivationToCAP( ZeroMorphism,
                    "Zero morphism by composition of morphism into and from zero object",
                    [ [ PreCompose, 1 ],
                      [ UniversalMorphismIntoZeroObject, 1 ],
                      [ UniversalMorphismFromZeroObject, 1 ] ],
                    
  function( cat, obj_source, obj_range )
    
    return PreCompose( cat, UniversalMorphismIntoZeroObject( cat, obj_source ), UniversalMorphismFromZeroObject( cat, obj_range ) );
    
  end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( ZeroMorphism,
                    "computing the empty sum of morphisms",
                    [ [ SumOfMorphisms, 1 ] ],
                    
  function( cat, obj_source, obj_range )
    
    return SumOfMorphisms( cat, obj_source, [ ], obj_range );
    
  end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( PreCompose,
                    "PreCompose using PostCompose and swapping arguments",
                    [ [ PostCompose, 1 ] ],
                    
  function( cat, pre_mor, post_mor )
    
    return PostCompose( cat, post_mor, pre_mor );
    
end );

##
AddDerivationToCAP( PreCompose,
                    "PreCompose by wrapping the arguments in a list",
                    [ [ PreComposeList, 1 ] ],
                    
  function( cat, pre_mor, post_mor )
    
    return PreComposeList( cat, Source( pre_mor ), [ pre_mor, post_mor ], Range( post_mor ) );
    
end );

##
AddDerivationToCAP( PreComposeList,
                    "PreComposeList by iterating PreCompose",
                    [ [ IdentityMorphism, 2 ],
                      [ PreCompose, 2 ] ],
                    
  function( cat, source, morphism_list, range )
    local id_source, id_range;
    
    id_source := IdentityMorphism( cat, source );
    
    id_range := IdentityMorphism( cat, range );
    
    return Iterated( morphism_list, { alpha, beta } -> PreCompose( cat, alpha, beta ), id_source, id_range );
    
end );

##
AddDerivationToCAP( InverseForMorphisms,
                    "InverseForMorphisms using LiftAlongMonomorphism of an identity morphism",
                    [ [ IdentityMorphism, 1 ],
                      [ LiftAlongMonomorphism, 1 ] ],
                    
  function( cat, mor )
    local identity_of_range;
        
        identity_of_range := IdentityMorphism( cat, Range( mor ) );
        
        return LiftAlongMonomorphism( cat, mor, identity_of_range );
        
end );

##
AddDerivationToCAP( PreInverseForMorphisms,
                    "PreInverseForMorphisms using IdentityMorphism and Lift",
                    [ [ IdentityMorphism, 1 ],
                      [ Lift, 1 ] ],
                    
  function( cat, mor )
    
    return Lift( cat, IdentityMorphism( cat, Range( mor ) ), mor );
    
end );

##
AddDerivationToCAP( AdditionForMorphisms,
                    "AdditionForMorphisms using SumOfMorphisms",
                    [ [ SumOfMorphisms, 1 ] ],
                    
  function( cat, mor1, mor2 )
    
    return SumOfMorphisms( cat, Source( mor1 ), [ mor1, mor2 ], Range( mor1 ) );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( AdditionForMorphisms,
                    "AdditionForMorphisms(mor1, mor2) as the composition of (mor1,mor2) with the codiagonal morphism",
                    [ [ UniversalMorphismIntoDirectSum, 1 ],
                      [ IdentityMorphism, 1 ],
                      [ UniversalMorphismFromDirectSum, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, mor1, mor2 )
    local return_value, B, identity_morphism_B, componentwise_morphism, addition_morphism;
    
    B := Range( mor1 );
    
    componentwise_morphism := UniversalMorphismIntoDirectSum( cat, [ B, B ], Source( mor1 ), [ mor1, mor2 ] );
    
    identity_morphism_B := IdentityMorphism( cat, B );
    
    addition_morphism := UniversalMorphismFromDirectSum( cat, [ B, B ], B, [ identity_morphism_B, identity_morphism_B ] );
    
    return PreCompose( cat, componentwise_morphism, addition_morphism );
    
end : CategoryFilter := IsAdditiveCategory );

##
AddDerivationToCAP( SubtractionForMorphisms,
                    "SubtractionForMorphisms(mor1, mor2) as the sum of mor1 and the additive inverse of mor2",
                    [ [ AdditionForMorphisms, 1 ],
                      [ AdditiveInverseForMorphisms, 1 ] ],
                    
  function( cat, mor1, mor2 )
    
    return AdditionForMorphisms( cat, mor1, AdditiveInverseForMorphisms( cat, mor2 ) );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( SumOfMorphisms,
                    "SumOfMorphisms using AdditionForMorphisms and ZeroMorphism",
                    [ [ AdditionForMorphisms, 2 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat, obj1, mors, obj2 )
    local zero_morphism;
    
    zero_morphism := ZeroMorphism( cat, obj1, obj2 );
    
    return Iterated( mors, { alpha, beta } -> AdditionForMorphisms( cat, alpha, beta ), zero_morphism );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( LinearCombinationOfMorphisms,
                    "LinearCombinationOfMorphisms using SumOfMorphisms and MultiplyWithElementOfCommutativeRingForMorphisms",
                    [ [ MultiplyWithElementOfCommutativeRingForMorphisms, 2 ],
                      [ SumOfMorphisms, 1 ] ],
                    
  function( cat, obj1, coeffs, mors, obj2 )
    local morphisms;
    
    morphisms := ListN( coeffs, mors, { r, alpha } -> MultiplyWithElementOfCommutativeRingForMorphisms( cat, r, alpha ) );
    
    return SumOfMorphisms( cat, obj1, morphisms, obj2 );
    
end : CategoryFilter := IsLinearCategoryOverCommutativeRing );

##
AddDerivationToCAP( LiftAlongMonomorphism,
                    "LiftAlongMonomorphism using Lift",
                    [ [ Lift, 1 ] ],
                    
  function( cat, alpha, beta )
    
    ## Caution with the order of the arguments!
    return Lift( cat, beta, alpha );
    
end );

##
AddDerivationToCAP( ProjectiveLift,
                    "ProjectiveLift using Lift",
                    [ [ Lift, 1 ] ],
                    
  function( cat, alpha, beta )
    
    return Lift( cat, alpha, beta );
    
end );

##
AddDerivationToCAP( RandomMorphismByInteger,
                    "RandomMorphismByInteger using RandomObjectByInteger and RandomMorphismWithFixedSourceByInteger",
                    [ [ RandomObjectByInteger, 1 ],
                      [ RandomMorphismWithFixedSourceByInteger, 1 ] ],
                    
  function( cat, n )
    
    return RandomMorphismWithFixedSourceByInteger( cat, RandomObjectByInteger( cat, n ), 1 + Log2Int( n ) );
    
end );

##
AddDerivationToCAP( RandomMorphismByInteger,
                    "RandomMorphismByInteger using RandomObjectByInteger and RandomMorphismWithFixedRangeByInteger",
                    [ [ RandomObjectByInteger, 1 ],
                      [ RandomMorphismWithFixedRangeByInteger, 1 ] ],
                    
  function( cat, n )
    
    return RandomMorphismWithFixedRangeByInteger( cat, RandomObjectByInteger( cat, n ),  1 + Log2Int( n ) );
    
end );

##
AddDerivationToCAP( RandomMorphismWithFixedSourceByInteger,
                    "RandomMorphismWithFixedSourceByInteger using RandomObjectByInteger and RandomMorphismWithFixedSourceAndRangeByInteger",
                    [ [ RandomObjectByInteger, 1 ],
                      [ RandomMorphismWithFixedSourceAndRangeByInteger, 1 ] ],
                    
  function( cat, S, n )
    
    return RandomMorphismWithFixedSourceAndRangeByInteger( cat, S, RandomObjectByInteger( cat, n ), 1 + Log2Int( n ) );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( RandomMorphismWithFixedRangeByInteger,
                    "RandomMorphismWithFixedRangeByInteger using RandomObjectByInteger and RandomMorphismWithFixedSourceAndRangeByInteger",
                    [ [ RandomObjectByInteger, 1 ],
                      [ RandomMorphismWithFixedSourceAndRangeByInteger, 1 ] ],
                    
  function( cat, R, n )
    
    return RandomMorphismWithFixedSourceAndRangeByInteger( cat, RandomObjectByInteger( cat, n ), R, 1 + Log2Int( n ) );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( RandomMorphismByInteger,
                    "RandomMorphismByInteger using RandomObjectByInteger and RandomMorphismWithFixedSourceAndRangeByInteger",
                    [ [ RandomObjectByInteger, 2 ],
                      [ RandomMorphismWithFixedSourceAndRangeByInteger, 1 ] ],
                    
  function( cat, n )
    
    return RandomMorphismWithFixedSourceAndRangeByInteger( cat, RandomObjectByInteger( cat, n ), RandomObjectByInteger( cat, n ), 1 + Log2Int( n ) );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( RandomMorphismByList,
                    "RandomMorphismByList using RandomObjectByList and RandomMorphismWithFixedSourceByList",
                    [ [ RandomObjectByList, 1 ],
                      [ RandomMorphismWithFixedSourceByList, 1 ] ],
                    
  function( cat, L )
    
    if Length( L ) <> 2 or not ForAll( L, IsList ) then
        Error( "the list passed to 'RandomMorphismByList' in ", Name( cat ), " must be a list consisting of two lists!\n" );
    fi;
    
    return RandomMorphismWithFixedSourceByList( cat, RandomObjectByList( cat, L[1] ), L[2] );
    
end );

##
AddDerivationToCAP( RandomMorphismByList,
                    "RandomMorphismByList using RandomObjectByList and RandomMorphismWithFixedRangeByList",
                    [ [ RandomObjectByList, 1 ],
                      [ RandomMorphismWithFixedRangeByList, 1 ] ],
                    
  function( cat, L )
    
    if Length( L ) <> 2 or not ForAll( L, IsList ) then
        Error( "the list passed to 'RandomMorphismByList' in ", Name( cat ), " must be a list consisting of two lists!\n" );
    fi;
    
    return RandomMorphismWithFixedRangeByList( cat, RandomObjectByList( cat, L[1] ), L[2] );
    
end );

##
AddDerivationToCAP( RandomMorphismWithFixedSourceByList,
                    "RandomMorphismWithFixedSourceByList using RandomObjectByList and RandomMorphismWithFixedSourceAndRangeByList",
                    [ [ RandomObjectByList, 1 ],
                      [ RandomMorphismWithFixedSourceAndRangeByList, 1 ] ],
                    
  function( cat, S, L )
    
    if Length( L ) <> 2 or not ForAll( L, IsList ) then
        Error( "the list passed to 'RandomMorphismWithFixedSourceByList' in ", Name( cat ), " must be a list consisting of two lists!\n" );
    fi;
    
    return RandomMorphismWithFixedSourceAndRangeByList( cat, S, RandomObjectByList( cat, L[1] ), L[2] );
    
end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( RandomMorphismWithFixedRangeByList,
                    "RandomMorphismWithFixedRangeByList using RandomObjectByList and RandomMorphismWithFixedSourceAndRangeByList",
                    [ [ RandomObjectByList, 1 ],
                      [ RandomMorphismWithFixedSourceAndRangeByList, 1 ] ],
                    
  function( cat, R, L )
    
    if Length( L ) <> 2 or not ForAll( L, IsList ) then
        Error( "the list passed to 'RandomMorphismWithFixedRangeByList' in ", Name( cat ), " must be a list consisting of two lists!\n" );
    fi;
    
    return RandomMorphismWithFixedSourceAndRangeByList( cat, RandomObjectByList( cat, L[1] ), R, L[2] );

end : CategoryFilter := IsAbCategory );

##
AddDerivationToCAP( RandomMorphismByList,
                    "RandomMorphismByList using RandomObjectByList and RandomMorphismWithFixedSourceAndRangeByList",
                    [ [ RandomObjectByList, 2 ],
                      [ RandomMorphismWithFixedSourceAndRangeByList, 1 ] ],
                    
  function( cat, L )
    
    if Length( L ) <> 3 or not ForAll( L, IsList ) then
        Error( "the list passed to 'RandomMorphismByList' in ", Name( cat ), " must be a list consisting of three lists!\n" );
    fi;
    
    return RandomMorphismWithFixedSourceAndRangeByList( cat, RandomObjectByList( cat, L[1] ), RandomObjectByList( cat, L[2] ), L[3] );
    
end : CategoryFilter := IsAbCategory );


##
AddDerivationToCAP( IsomorphismFromKernelOfCokernelToImageObject,
                    "IsomorphismFromKernelOfCokernelToImageObject as the inverse of IsomorphismFromImageObjectToKernelOfCokernel",
                    [ [ InverseForMorphisms, 1 ],
                      [ IsomorphismFromImageObjectToKernelOfCokernel, 1 ] ],
                    
  function( cat, morphism )
    
    return InverseForMorphisms( cat, IsomorphismFromImageObjectToKernelOfCokernel( cat, morphism ) );
    
end );

##
AddDerivationToCAP( IsomorphismFromImageObjectToKernelOfCokernel,
                    "IsomorphismFromImageObjectToKernelOfCokernel as the inverse of IsomorphismFromKernelOfCokernelToImageObject",
                    [ [ InverseForMorphisms, 1 ],
                      [ IsomorphismFromKernelOfCokernelToImageObject, 1 ] ],
                    
  function( cat, morphism )
    
    return InverseForMorphisms( cat, IsomorphismFromKernelOfCokernelToImageObject( cat, morphism ) );
    
end );

##
AddDerivationToCAP( IsomorphismFromImageObjectToKernelOfCokernel,
                    "IsomorphismFromImageObjectToKernelOfCokernel using the universal property of the image",
                    [ [ KernelEmbedding, 1 ],
                      [ CokernelProjection, 1 ],
                      [ LiftAlongMonomorphism, 1 ],
                      [ UniversalMorphismFromImage, 1 ] ],
                    
  function( cat, morphism )
    local kernel_emb, morphism_to_kernel;
    
    kernel_emb := KernelEmbedding( cat, CokernelProjection( cat, morphism ) );
    
    morphism_to_kernel := LiftAlongMonomorphism( cat, kernel_emb, morphism );
    
    return UniversalMorphismFromImage( cat, morphism, Pair( morphism_to_kernel, kernel_emb ) );
    
end : CategoryFilter := IsAbelianCategory );

##
AddDerivationToCAP( IsomorphismFromEqualizerToKernelOfJointPairwiseDifferencesOfMorphismsIntoDirectProduct,
                    "IsomorphismFromEqualizerToKernelOfJointPairwiseDifferencesOfMorphismsIntoDirectProduct using the universal property of the kernel",
                    [ [ JointPairwiseDifferencesOfMorphismsIntoDirectProduct, 1 ],
                      [ Equalizer, 1 ],
                      [ EmbeddingOfEqualizerWithGivenEqualizer, 1 ],
                      [ KernelLift, 1 ] ],
                    
  function( cat, A, diagram )
    local joint_pairwise_differences, equalizer, equalizer_embedding;
    
    joint_pairwise_differences := JointPairwiseDifferencesOfMorphismsIntoDirectProduct( cat, A, diagram );
    
    equalizer := Equalizer( cat, A, diagram );
    
    equalizer_embedding := EmbeddingOfEqualizerWithGivenEqualizer( cat, A, diagram, equalizer );
    
    return KernelLift( cat, joint_pairwise_differences, equalizer, equalizer_embedding );
    
end );

##
AddDerivationToCAP( IsomorphismFromKernelOfJointPairwiseDifferencesOfMorphismsIntoDirectProductToEqualizer,
                    "IsomorphismFromKernelOfJointPairwiseDifferencesOfMorphismsIntoDirectProductToEqualizer using the universal property of the equalizer",
                    [ [ JointPairwiseDifferencesOfMorphismsIntoDirectProduct, 1 ],
                      [ KernelObject, 1 ],
                      [ KernelEmbeddingWithGivenKernelObject, 1 ],
                      [ UniversalMorphismIntoEqualizer, 1 ] ],
                    
  function( cat, A, diagram )
    local joint_pairwise_differences, kernel_object, kernel_embedding;
    
    joint_pairwise_differences := JointPairwiseDifferencesOfMorphismsIntoDirectProduct( cat, A, diagram );
    
    kernel_object := KernelObject( cat, joint_pairwise_differences );
    
    kernel_embedding := KernelEmbeddingWithGivenKernelObject( cat, joint_pairwise_differences, kernel_object );
    
    return UniversalMorphismIntoEqualizer( cat, A, diagram, kernel_object, kernel_embedding );
    
end );

##
AddDerivationToCAP( IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram,
                    "IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram using the universal property of the equalizer",
                    [ [ DirectProduct, 1 ],
                      [ PreCompose, 2 ],
                      [ ProjectionInFactorOfDirectProductWithGivenDirectProduct, 2 ],
                      [ ProjectionInFactorOfFiberProductWithGivenFiberProduct, 2 ],
                      [ UniversalMorphismIntoDirectProductWithGivenDirectProduct, 1 ],
                      [ FiberProduct, 1 ],
                      [ UniversalMorphismIntoEqualizer, 1 ] ],
                    
  function( cat, diagram )
    local sources_of_diagram, direct_product, direct_product_diagram, fiber_product, test_source, fiber_product_embedding;
    
    sources_of_diagram := List( diagram, Source );
    
    direct_product := DirectProduct( cat, sources_of_diagram );
    
    direct_product_diagram := List( [ 1.. Length( sources_of_diagram ) ],
                                    i -> PreCompose( cat, ProjectionInFactorOfDirectProductWithGivenDirectProduct( cat, sources_of_diagram, i, direct_product ), diagram[ i ] ) );
    
    fiber_product := FiberProduct( cat, diagram );
    
    test_source := List( [ 1 .. Length( diagram ) ], i -> ProjectionInFactorOfFiberProductWithGivenFiberProduct( cat, diagram, i, fiber_product ) );
    
    fiber_product_embedding := UniversalMorphismIntoDirectProductWithGivenDirectProduct( cat, sources_of_diagram, fiber_product, test_source, direct_product );
    
    return UniversalMorphismIntoEqualizer( cat, direct_product, direct_product_diagram, fiber_product, fiber_product_embedding );
    
end );

##
AddDerivationToCAP( IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram,
                    "IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram as the inverse of IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct",
                    [ [ IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct, 1 ],
                      [ InverseForMorphisms, 1 ] ],
                    
  function( cat, diagram )
    
    return InverseForMorphisms( cat, IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct( cat, diagram ) );
    
end );

##
AddDerivationToCAP( IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct,
                    "IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct using the universal property of the fiber product",
                    [ [ PreCompose, 4 ],
                      [ ProjectionInFactorOfDirectProductWithGivenDirectProduct, 2 ],
                      [ DirectProduct, 1 ],
                      [ Equalizer, 1 ],
                      [ EmbeddingOfEqualizerWithGivenEqualizer, 1 ],
                      [ UniversalMorphismIntoFiberProduct, 1 ] ],
                    
  function( cat, diagram )
    local sources_of_diagram, direct_product, direct_product_diagram, equalizer, equalizer_embedding, equalizer_of_direct_product_diagram;
    
    sources_of_diagram := List( diagram, Source );
    
    direct_product := DirectProduct( cat, sources_of_diagram );
    
    direct_product_diagram := List( [ 1.. Length( sources_of_diagram ) ],
                                    i -> PreCompose( cat, ProjectionInFactorOfDirectProductWithGivenDirectProduct( cat, sources_of_diagram, i, direct_product ), diagram[ i ] ) );
    
    equalizer := Equalizer( cat, direct_product, direct_product_diagram );
    
    equalizer_embedding := EmbeddingOfEqualizerWithGivenEqualizer( cat, direct_product, direct_product_diagram, equalizer );
    
    equalizer_of_direct_product_diagram := List( [ 1 .. Length( direct_product_diagram ) ], i -> PreCompose( cat, equalizer_embedding, direct_product_diagram[ i ] ) );
    
    return UniversalMorphismIntoFiberProduct( cat, diagram, equalizer, equalizer_of_direct_product_diagram );
    
end );

##
AddDerivationToCAP( IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct,
                    "IsomorphismFromEqualizerOfDirectProductDiagramToFiberProduct as the inverse of IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram",
                    [ [ IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram, 1 ],
                      [ InverseForMorphisms, 1 ] ],
                    
  function( cat, diagram )
    
    return InverseForMorphisms( cat, IsomorphismFromFiberProductToEqualizerOfDirectProductDiagram( cat, diagram ) );
    
end );

##
AddDerivationToCAP( LiftAlongMonomorphism,
                    "LiftAlongMonomorphism by inverting the kernel lift from the source to the kernel of the cokernel of a given monomorphism",
                    [ [ CokernelProjection, 1 ],
                      [ KernelLift, 2 ],
                      [ PreCompose, 1 ],
                      [ InverseForMorphisms, 1 ] ],
                    
  function( cat, monomorphism, test_morphism )
    local cokernel_proj, kernel_lift_from_source_of_monomorphism, kernel_lift_from_source_of_test_morphism;
    
    cokernel_proj := CokernelProjection( cat, monomorphism );
    
    kernel_lift_from_source_of_monomorphism :=
      KernelLift( cat, cokernel_proj, Source( monomorphism ), monomorphism );
      
    kernel_lift_from_source_of_test_morphism :=
      KernelLift( cat, cokernel_proj, Source( test_morphism ), test_morphism );
    
    return PreCompose( cat, kernel_lift_from_source_of_test_morphism, InverseForMorphisms( cat, kernel_lift_from_source_of_monomorphism ) );
    
end : CategoryFilter := IsAbelianCategory );

##
AddDerivationToCAP( ComponentOfMorphismIntoDirectProduct,
                    "ComponentOfMorphismIntoDirectProduct by composing with the direct product projection",
                    [ [ ProjectionInFactorOfDirectProduct, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, alpha, factors, nr )
    
    return PreCompose( cat, alpha, ProjectionInFactorOfDirectProduct( cat, factors, nr ) );
    
end );

##
AddDerivationToCAP( ComponentOfMorphismIntoDirectSum,
                    "ComponentOfMorphismIntoDirectSum by composing with the direct sum projection",
                    [ [ ProjectionInFactorOfDirectSum, 1 ],
                      [ PreCompose, 1 ] ],
                    
  function( cat, alpha, summands, nr )
    
    return PreCompose( cat, alpha, ProjectionInFactorOfDirectSum( cat, summands, nr ) );
    
end );

##
AddDerivationToCAP( MorphismBetweenDirectSumsWithGivenDirectSums,
                    "MorphismBetweenDirectSumsWithGivenDirectSums using universal morphisms of direct sums (without support for empty limits)",
                    [ [ ZeroMorphism, 1 ],
                      [ UniversalMorphismIntoDirectSumWithGivenDirectSum, 2 ],
                      [ UniversalMorphismFromDirectSumWithGivenDirectSum, 1 ] ],
                    
  function( cat, S, diagram_S, morphism_matrix, diagram_T, T )
    local test_diagram_product, test_diagram_coproduct;
    
    if morphism_matrix = [ ] or morphism_matrix[1] = [ ] then
        return ZeroMorphism( cat, S, T );
    fi;
    
    test_diagram_coproduct := ListN( diagram_S, morphism_matrix,
        { source, row } -> UniversalMorphismIntoDirectSumWithGivenDirectSum( cat, diagram_T, source, row, T )
    );
    
    return UniversalMorphismFromDirectSumWithGivenDirectSum( cat, diagram_S, T, test_diagram_coproduct, S );
    
end : CategoryFilter := cat -> not ( IsBound( cat!.supports_empty_limits ) and cat!.supports_empty_limits = true ) );

##
AddDerivationToCAP( MorphismBetweenDirectSumsWithGivenDirectSums,
                    "MorphismBetweenDirectSumsWithGivenDirectSums using universal morphisms of direct sums (with support for empty limits)",
                    [ [ UniversalMorphismIntoDirectSumWithGivenDirectSum, 2 ],
                      [ UniversalMorphismFromDirectSumWithGivenDirectSum, 1 ] ],
                    
  function( cat, S, diagram_S, morphism_matrix, diagram_T, T )
    local test_diagram_product, test_diagram_coproduct;
    
    test_diagram_coproduct := ListN( diagram_S, morphism_matrix,
        { source, row } -> UniversalMorphismIntoDirectSumWithGivenDirectSum( cat, diagram_T, source, row, T )
    );
    
    return UniversalMorphismFromDirectSumWithGivenDirectSum( cat, diagram_S, T, test_diagram_coproduct, S );
    
end : CategoryFilter := cat -> IsBound( cat!.supports_empty_limits ) and cat!.supports_empty_limits = true );

##
AddDerivationToCAP( HomologyObjectFunctorialWithGivenHomologyObjects,
                    "HomologyObjectFunctorialWithGivenHomologyObjects using functoriality of (co)kernels and images in abelian categories",
                    [ [ ImageEmbedding, 2 ],
                      [ PreCompose, 3 ],
                      [ KernelEmbedding, 2 ],
                      [ CokernelProjection, 2 ],
                      [ CokernelObjectFunctorial, 1 ],
                      [ LiftAlongMonomorphism, 1 ],
                      [ PreComposeList, 1 ],
                      [ IsomorphismFromHomologyObjectToItsConstructionAsAnImageObject, 1 ],
                      [ IsomorphismFromItsConstructionAsAnImageObjectToHomologyObject, 1 ] ],
                    
  function( cat, homology_source, mor_list, homology_range )
    local alpha, beta, epsilon, gamma, delta, image_emb_source, image_emb_range, cok_functorial, functorial_mor;
    
    alpha := mor_list[1];
    
    beta := mor_list[2];
    
    epsilon := mor_list[3];
    
    gamma := mor_list[4];
    
    delta := mor_list[5];
    
    image_emb_source := ImageEmbedding( cat,
      PreCompose( cat, KernelEmbedding( cat, beta ), CokernelProjection( cat, alpha ) )
    );
    
    image_emb_range := ImageEmbedding( cat,
      PreCompose( cat, KernelEmbedding( cat, delta ), CokernelProjection( cat, gamma ) )
    );
    
    cok_functorial := CokernelObjectFunctorial( cat, alpha, epsilon, gamma );
    
    functorial_mor :=
      LiftAlongMonomorphism( cat,
        image_emb_range, PreCompose( cat, image_emb_source, cok_functorial )
      );
    
    return PreComposeList( cat,
        homology_source,
        [
            IsomorphismFromHomologyObjectToItsConstructionAsAnImageObject( cat, alpha, beta ),
            functorial_mor,
            IsomorphismFromItsConstructionAsAnImageObjectToHomologyObject( cat, gamma, delta ),
        ],
        homology_range
    );
    
end : CategoryFilter := IsAbelianCategory );


###########################
##
## Methods returning a morphism with source or range constructed within the method!
## If there is a method available which only constructs this source or range,
## one has to be sure that this source is equal to that construction (by IsEqualForObjects)
##
###########################

##
AddDerivationToCAP( ZeroObjectFunctorial,
                    "ZeroObjectFunctorial using ZeroMorphism",
                    [ [ ZeroObject, 1 ],
                      [ ZeroMorphism, 1 ] ],
                    
  function( cat )
    local zero_object;
    
    zero_object := ZeroObject( cat );
    
    return ZeroMorphism( cat, zero_object, zero_object );
    
end );

##
AddDerivationToCAP( JointPairwiseDifferencesOfMorphismsIntoDirectProduct,
                    "JointPairwiseDifferencesOfMorphismsIntoDirectProduct using the operations defining this morphism (without support for empty limits)",
                    [ [ UniversalMorphismIntoTerminalObject, 1 ],
                      [ UniversalMorphismIntoDirectProduct, 2 ],
                      [ SubtractionForMorphisms, 1 ] ],
                    
  function( cat, A, diagram )
    local number_of_morphisms, ranges, mor1, mor2;
    
    number_of_morphisms := Length( diagram );
    
    if number_of_morphisms = 1 then
        
        return UniversalMorphismIntoTerminalObject( cat, A );
        
    fi;
    
    ranges := List( diagram, Range );
    
    mor1 := UniversalMorphismIntoDirectProduct( cat, ranges{[ 1 .. number_of_morphisms - 1 ]}, A, diagram{[ 1 .. number_of_morphisms - 1 ]} );
    
    mor2 := UniversalMorphismIntoDirectProduct( cat, ranges{[ 2 .. number_of_morphisms ]}, A, diagram{[ 2 .. number_of_morphisms ]} );
    
    return SubtractionForMorphisms( cat, mor1, mor2 );
    
end : CategoryFilter := cat -> not ( IsBound( cat!.supports_empty_limits ) and cat!.supports_empty_limits = true ) );

##
AddDerivationToCAP( JointPairwiseDifferencesOfMorphismsIntoDirectProduct,
                    "JointPairwiseDifferencesOfMorphismsIntoDirectProduct using the operations defining this morphism (with support for empty limits)",
                    [ [ UniversalMorphismIntoDirectProduct, 2 ],
                      [ SubtractionForMorphisms, 1 ] ],
                    
  function( cat, A, diagram )
    local number_of_morphisms, ranges, mor1, mor2;
    
    number_of_morphisms := Length( diagram );
    
    ranges := List( diagram, Range );
    
    mor1 := UniversalMorphismIntoDirectProduct( cat, ranges{[ 1 .. number_of_morphisms - 1 ]}, A, diagram{[ 1 .. number_of_morphisms - 1 ]} );
    
    mor2 := UniversalMorphismIntoDirectProduct( cat, ranges{[ 2 .. number_of_morphisms ]}, A, diagram{[ 2 .. number_of_morphisms ]} );
    
    return SubtractionForMorphisms( cat, mor1, mor2 );
    
end : CategoryFilter := cat -> IsBound( cat!.supports_empty_limits ) and cat!.supports_empty_limits = true );

##
--> --------------------

--> maximum size reached

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

[ Dauer der Verarbeitung: 0.54 Sekunden  (vorverarbeitet)  ]