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 68 kB image not shown  

Quelle  CategoryMorphismsOperations.gd   Sprache: unbekannt

 
# SPDX-License-Identifier: GPL-2.0-or-later
# CAP: Categories, Algorithms, Programming
#
# Declarations
#
#! @Chapter Morphisms

###################################
##
#! @Section Morphism constructors
##
###################################

#! @Description
#! The arguments are two objects $S$ and $T$ in a category,
#! and a morphism datum $a$ (type and semantics of the morphism datum depend on the category).
#! The output is a morphism in $\mathrm{Hom}(S,T)$ defined by $a$.
#! Note that by default this CAP operation is not cached. You can change this behaviour
#! by calling `SetCachingToWeak( C, "MorphismConstructor" )` resp. `SetCachingToCrisp( C, "MorphismConstructor" )`.
#! @Returns a morphism in $\mathrm{Hom}(S,T)$
#! @Arguments S, a, T
DeclareOperation( "MorphismConstructor",
                  [ IsCapCategoryObject, IsObject, IsCapCategoryObject ] );

#! @Description
#! The argument is a CAP category morphism <A>mor</A>.
#! The output is a datum which can be used to construct <A>mor</A>, that is,
#! `IsEqualForMorphisms( `<A>mor</A>`, MorphismConstructor( Source( `<A>mor</A>` ), MorphismDatum( `<A>mor</A>` ), Range( `<A>mor</A>` ) ) )`.
#! Note that by default this CAP operation is not cached. You can change this behaviour
#! by calling `SetCachingToWeak( C, "MorphismDatum" )` resp. `SetCachingToCrisp( C, "MorphismDatum" )`.
#! @Returns depends on the category
#! @Arguments mor
DeclareAttribute( "MorphismDatum",
                  IsCapCategoryMorphism );

###################################
##
#! @Section Categorical Properties of Morphisms
##
###################################

#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is a monomorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsMonomorphism",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is an epimorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsEpimorphism",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is an isomorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsIsomorphism",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is a split monomorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsSplitMonomorphism",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is a split epimorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsSplitEpimorphism",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha: a \rightarrow a$.
#! The output is <C>true</C> if $\alpha$ is congruent to the identity of $a$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsOne",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha: a \rightarrow a$.
#! The output is <C>true</C> if $\alpha^2 \sim_{a,a} \alpha$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsIdempotent",
                 IsCapCategoryMorphism );

###################################
##
#! @Section Random Morphisms
##
###################################

#! CAP provides two principal methods to generate random morphisms with or without fixed source and range:
#!  * <E>By integers</E>: The integer is simply a parameter that can be used to create a random morphism.
#!  * <E>By lists</E>: The list is used when creating a random morphism would need more than one parameter. Lists offer more
#!    flexibility at the expense of the genericity of the methods. This happens because lists that are valid as input in
#!    some category may be not valid for other categories. Hence, these operations are not thought to be used in
#!    generic categorical algorithms.

#! @Description
#! The arguments are an object $a$ in a category $C$ and an integer $n$.
#! The output is a random morphism $\alpha: a \rightarrow b$ for some object $b$ in $C$.
#! If $C$ is equipped with the methods <C>RandomObjectByInteger</C> and <C>RandomMorphismWithFixedSourceAndRangeByInteger</C>
#! and $C$ is an Ab-category, then <C>RandomMorphismWithFixedSourceByInteger</C>$(C,a,n)$ can be derived as
#! <C>RandomMorphismWithFixedSourceAndRangeByInteger</C>($C$,$a$,$b$,$1$+<C>Log2Int</C>($n$)) where
#! $b$ is computed via <C>RandomObjectByInteger</C>($C$,$n$).
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments a, n
DeclareOperation( "RandomMorphismWithFixedSourceByInteger",
                  [ IsCapCategoryObject, IsInt ] );

#! @Description
#! The arguments are an object $a$ in a category $C$ and a list $L$.
#! The output is a random morphism $\alpha: a \rightarrow b$ for some object $b$ in $C$.
#! If $C$ is equipped with the methods <C>RandomObjectByList</C> and <C>RandomMorphismWithFixedSourceAndRangeByList</C>
#! and $C$ is an Ab-category, then <C>RandomMorphismWithFixedSourceByList</C>$(C,a,L)$ can be derived as
#! <C>RandomMorphismWithFixedSourceAndRangeByList</C>($C,a,b,L[2]$) where
#! $b$ is computed via <C>RandomObjectByList</C>($C,L[1]$).
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments a, L
DeclareOperation( "RandomMorphismWithFixedSourceByList",
                  [ IsCapCategoryObject, IsList ] );

#! @Description
#! The arguments are an object $b$ in a category $C$ and an integer $n$.
#! The output is a random morphism $\alpha: a \rightarrow b$ for some object $a$ in $C$.
#! If $C$ is equipped with the methods <C>RandomObjectByInteger</C> and <C>RandomMorphismWithFixedSourceAndRangeByInteger</C>
#! and $C$ is an Ab-category, then <C>RandomMorphismWithFixedRangeByInteger</C>$(C,b,n)$ can be derived as
#! <C>RandomMorphismWithFixedSourceAndRangeByInteger</C>($C$,$a$,$b$,$1$+<C>Log2Int</C>($n$)) where
#! $a$ is computed via <C>RandomObjectByInteger</C>($C$,$n$).
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments b, n
DeclareOperation( "RandomMorphismWithFixedRangeByInteger",
                  [ IsCapCategoryObject, IsInt ] );

#! @Description
#! The arguments are an object $b$ in a category $C$ and a list $L$.
#! The output is a random morphism $\alpha: a \rightarrow b$ for some object $a$ in $C$.
#! If $C$ is equipped with the methods <C>RandomObjectByList</C> and <C>RandomMorphismWithFixedSourceAndRangeByList</C>
#! and $C$ is an Ab-category, then <C>RandomMorphismWithFixedRangeByList</C>$(C,b,L)$ can be derived as
#! <C>RandomMorphismWithFixedSourceAndRangeByList</C>($C,a,b,L[2]$) where
#! $a$ is computed via <C>RandomObjectByList</C>($C,L[1]$).
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments b, L
DeclareOperation( "RandomMorphismWithFixedRangeByList",
                  [ IsCapCategoryObject, IsList ] );

#! @Description
#! The arguments are two objects $a$ and $b$ in a category $C$ and an integer $n$.
#! The output is a random morphism $\alpha: a \rightarrow b$ in $C$.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments a, b, n
DeclareOperation( "RandomMorphismWithFixedSourceAndRangeByInteger",
                  [ IsCapCategoryObject, IsCapCategoryObject, IsInt ] );

#! @Description
#! This operation is not a CAP basic operation
#! The arguments are two objects $a$ and $b$ in a category $C$ and a list $L$.
#! The output is a random morphism $\alpha: a \rightarrow b$ in $C$.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments a, b, L
DeclareOperation( "RandomMorphismWithFixedSourceAndRangeByList",
                  [ IsCapCategoryObject, IsCapCategoryObject, IsList ] );

#! @Description
#! The arguments are a category $C$ and an integer $n$.
#! The output is a random morphism in $C$.
#! The operation can be derived in three different ways:
#! - If $C$ is equipped with the methods <C>RandomObjectByInteger</C> and <C>RandomMorphismWithFixedSourceAndRangeByInteger</C>
#!   and $C$ is an Ab-category, then <C>RandomMorphism</C>$(C,n)$ can be derived as
#!   <C>RandomMorphismWithFixedSourceAndRangeByInteger</C>($C,a,b$,$1$+<C>Log2Int</C>($n$)) where
#!   $a$ and $b$ are computed via <C>RandomObjectByInteger</C>($C,n$).
#! - If $C$ is equipped with the methods <C>RandomObjectByInteger</C> and <C>RandomMorphismWithFixedSourceByInteger</C>,
#!   then <C>RandomMorphism</C>$(C,n)$ can be derived as
#!   <C>RandomMorphismWithFixedSourceByInteger</C>($C,a,1$+<C>Log2Int</C>($n$)) where
#!   $a$ is computed via <C>RandomObjectByInteger</C>($C,n$).
#! - If $C$ is equipped with the methods <C>RandomObjectByInteger</C> and <C>RandomMorphismWithFixedRangeByInteger</C>,
#!   then <C>RandomMorphism</C>$(C,n)$ can be derived as
#!   <C>RandomMorphismWithFixedRangeByInteger</C>($C,b,1$+<C>Log2Int</C>($n$)) where
#!   $b$ is computed via <C>RandomObjectByInteger</C>($C,n$).
#! @Returns a morphism in $C$
#! @Arguments C, n
DeclareOperation( "RandomMorphismByInteger",
                  [ IsCapCategory, IsInt ] );

#! @Description
#! The arguments are a category $C$ and a list $L$.
#! The output is a random morphism in $C$.
#! The operation can be derived in three different ways:
#! - If $C$ is equipped with the methods <C>RandomObjectByList</C> and <C>RandomMorphismWithFixedSourceAndRangeByList</C>
#!   and $C$ is an Ab-category, then <C>RandomMorphism</C>$(C,L)$ can be derived as
#!   <C>RandomMorphismWithFixedSourceAndRangeByList</C>($C,a,b,L[3]$)) where
#!   $a$ and $b$ are computed via <C>RandomObjectByList</C>($C,L[i]$) for $i=1,2$ respectively.
#! - If $C$ is equipped with the methods <C>RandomObjectByList</C> and <C>RandomMorphismWithFixedSourceByList</C>,
#!   then <C>RandomMorphism</C>$(C,L)$ can be derived as
#!   <C>RandomMorphismWithFixedSourceByList</C>($C,a,L[2]$) where
#!   $a$ is computed via <C>RandomObjectByList</C>($C,L[1]$).
#! - If $C$ is equipped with the methods <C>RandomObjectByList</C> and <C>RandomMorphismWithFixedRangeByList</C>,
#!   then <C>RandomMorphism</C>$(C,L)$ can be derived as
#!   <C>RandomMorphismWithFixedRangeByList</C>($C,b,L[2]$) where
#!   $b$ is computed via <C>RandomObjectByList</C>($C,L[1]$).
#! @Returns a morphism in $C$
#! @Arguments C, L
DeclareOperation( "RandomMorphismByList",
                  [ IsCapCategory, IsList ] );

#! @BeginGroup
#! @Description
#! These are convenient methods and they, depending on the input, delegate to one of the above methods.
# @Returns an object, morphism in $C$
#! @Arguments a, n
DeclareOperation( "RandomMorphismWithFixedSource", [ IsCapCategoryObject, IsInt ] );
#! @Arguments a, L
DeclareOperation( "RandomMorphismWithFixedSource", [ IsCapCategoryObject, IsList ] );
#! @Arguments b, n
DeclareOperation( "RandomMorphismWithFixedRange", [ IsCapCategoryObject, IsInt ] );
#! @Arguments b, L
DeclareOperation( "RandomMorphismWithFixedRange", [ IsCapCategoryObject, IsList ] );
#! @Arguments a, b, n
DeclareOperation( "RandomMorphismWithFixedSourceAndRange", [ IsCapCategoryObject, IsCapCategoryObject, IsInt ] );
#! @Arguments a, b, L
DeclareOperation( "RandomMorphismWithFixedSourceAndRange", [ IsCapCategoryObject, IsCapCategoryObject, IsList ] );
#! @Arguments a, b, n
DeclareOperation( "RandomMorphism", [ IsCapCategoryObject, IsCapCategoryObject, IsInt ] );
#! @Arguments a, b, L
DeclareOperation( "RandomMorphism", [ IsCapCategoryObject, IsCapCategoryObject, IsList ] );
#! @Arguments C, n
DeclareOperation( "RandomMorphism", [ IsCapCategory, IsInt ] );
#! @Arguments C, L
DeclareOperation( "RandomMorphism", [ IsCapCategory, IsList ] );
#! @EndGroup

###################################
##
#! @Section Non-Categorical Properties of Morphisms
##
###################################

#! Non-categorical properties are not stable under equivalences of categories.

#! @Description
#! The argument is a morphism $\alpha: a \rightarrow b$.
#! The output is <C>true</C> if $\alpha = \mathrm{id}_a$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsEqualToIdentityMorphism",
                 IsCapCategoryMorphism );

#! @Description
#! The argument is a morphism $\alpha: a \rightarrow b$.
#! The output is <C>true</C> if $\alpha = 0$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsEqualToZeroMorphism",
                 IsCapCategoryMorphism );

## This is not a categorical property because non-endomorphisms 
## can be mapped to endomorphisms under equivalences of categories.
#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is an endomorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsEndomorphism",
                 IsCapCategoryMorphism );

## This is not a categorical property because non-endomorphisms 
## can be mapped to endomorphisms under equivalences of categories.
#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is an automorphism,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsAutomorphism",
                 IsCapCategoryMorphism );

###################################
##
#! @Section Equality and Congruence for Morphisms
##
###################################


#! @Description
#! The arguments are two morphisms $\alpha, \beta: a \rightarrow b$.
#! The output is <C>true</C> if $\alpha \sim_{a,b} \beta$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsCongruentForMorphisms",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


#! @Description
#! The arguments are two morphisms $\alpha, \beta: a \rightarrow b$.
#! The output is <C>true</C> if $\alpha = \beta$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsEqualForMorphisms",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow b, \beta: c \rightarrow d$.
#! The output is <C>true</C> if $\alpha = \beta$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsEqualForMorphismsOnMor",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


###################################
##
#! @Section Basic Operations for Morphisms in Ab-Categories
##
###################################

#! @Description
#! The argument is a morphism $\alpha: a \rightarrow b$.
#! The output is <C>true</C> if $\alpha \sim_{a,b} 0$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareProperty( "IsZeroForMorphisms",
                 IsCapCategoryMorphism );

DeclareProperty( "IsZero", IsCapCategoryMorphism );

DeclareOperation( "+", [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

DeclareOperation( "-", [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two morphisms $\alpha, \beta: a \rightarrow b$.
#! The output is the addition $\alpha + \beta$.
#! Note: The addition has to be compatible with the congruence of morphisms.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments alpha, beta
DeclareOperation( "AdditionForMorphisms",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two morphisms $\alpha, \beta: a \rightarrow b$.
#! The output is the addition $\alpha - \beta$.
#! Note: The addition has to be compatible with the congruence of morphisms.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments alpha, beta
DeclareOperation( "SubtractionForMorphisms",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The argument is a morphism $\alpha: a \rightarrow b$.
#! The output is its additive inverse $-\alpha$.
#! Note: The addition has to be compatible with the congruence of morphisms.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments alpha
DeclareAttribute( "AdditiveInverseForMorphisms",
                  IsCapCategoryMorphism );

DeclareAttribute( "AdditiveInverse",
                  IsCapCategoryMorphism );

#! @Description
#! The arguments are an element $r$ of a commutative ring
#! and a morphism $\alpha: a \rightarrow b$.
#! The output is the multiplication with the ring element $r \cdot \alpha$.
#! Note: The multiplication has to be compatible with the congruence of morphisms.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments r, alpha
DeclareOperation( "MultiplyWithElementOfCommutativeRingForMorphisms",
                  [ IsRingElement, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method. It has two arguments.
#! The first argument is either a rational number $q$
#! or an element $r$ of a commutative ring $R$.
#! The second argument is a morphism $\alpha: a \rightarrow b$ in a linear category
#! over the commutative ring $R$.
#! In the case where the first element is a rational number, this method tries to interpret $q$ as an element $r$ of $R$ via
#! <C>R!.interpret_rationals_func</C>. If no such interpretation
#! exists, this method throws an error.
#! The output is the multiplication with the ring element $r \cdot \alpha$.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments r, alpha
DeclareOperation( "*",
                  [ IsRingElement, IsCapCategoryMorphism ] );

DeclareOperation( "*",
                  [ IsCapCategoryMorphism, IsRingElement ] );


###################################
##
## Zero Morphism
##
###################################

#! @Description
#! The arguments are two objects $a$ and $b$.
#! The output is the zero morphism $0: a \rightarrow b$.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments a, b
DeclareOperation( "ZeroMorphism",
                  [ IsCapCategoryObject, IsCapCategoryObject ] );


###################################
##
#! @Section Subobject and Factorobject Operations
##
###################################

#! Subobjects of an object $c$ are monomorphisms
#! with range $c$ and a special function for comparision.
#! Similarly, factorobjects of an object $c$ are epimorphisms
#! with source $c$ and a special function for comparision.

## TODO
# @Description
# This is a synonym for <C>IsMonomorphism</C>.
DeclareSynonymAttr( "IsSubobject",
                    IsMonomorphism );

## TODO
# @Description
# This is a synonym for <C>IsEpimorphism</C>.
DeclareSynonymAttr( "IsFactorobject",
                    IsEpimorphism );

#! @Description
#! The arguments are two subobjects $\alpha: a \rightarrow c$, $\beta: b \rightarrow c$.
#! The output is <C>true</C> if there exists an isomorphism $\iota: a \rightarrow b$
#! such that $\beta \circ \iota \sim_{a,c} \alpha$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsEqualAsSubobjects",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two factorobjects $\alpha: c \rightarrow a$, $\beta: c \rightarrow b$.
#! The output is <C>true</C> if there exists an isomorphism $\iota: b \rightarrow a$
#! such that $\iota \circ \beta \sim_{c,a} \alpha$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsEqualAsFactorobjects",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


#! @Description
#! @BeginLatexOnly
#! \begin{center}
#! \begin{tikzpicture}
#! \def\w{2}
#! \def\h{1}
#! \node (a) at (0,\h) {$a$};
#! \node (b) at (0,-\h) {$b$};
#! \node (c) at (\w,0) {$c$};
#! \draw[right hook-latex] (a) to node[pos=0.45, above] {$\alpha$} (c);
#! \draw[right hook-latex] (b) to node[pos=0.45, below] {$\beta$} (c);
#! \draw[-latex, dashed] (a) to node[pos=0.45, left] {$\exists \iota$} (b);
#! \end{tikzpicture}
#! \end{center}
#! @EndLatexOnly
#! In short: Returns <C>true</C> iff $\alpha$ is smaller than $\beta$.
#! Full description: The arguments are two subobjects $\alpha: a \rightarrow c$, $\beta: b \rightarrow c$.
#! The output is <C>true</C> if there exists a morphism $\iota: a \rightarrow b$
#! such that $\beta \circ \iota \sim_{a,c} \alpha$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsDominating",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


#! @Description
#! @BeginLatexOnly
#! \begin{center}
#! \begin{tikzpicture}
#! \def\w{2}
#! \def\h{1}
#! \node (c) at (0,0) {$c$};
#! \node (a) at (\w,\h) {$a$};
#! \node (b) at (\w,-\h) {$b$};
#! \draw[-twohead] (c) to node[pos=0.45, above] {$\alpha$} (a);
#! \draw[-twohead] (c) to node[pos=0.45, below] {$\beta$} (b);
#! \draw[-latex, dashed] (b) to node[pos=0.45, right] {$\exists \iota$} (a);
#! \end{tikzpicture}
#! \end{center}
#! @EndLatexOnly
#! In short: Returns <C>true</C> iff $\alpha$ is smaller than $\beta$.
#! Full description: 
#! The arguments are two factorobjects $\alpha: c \rightarrow a$, $\beta: c \rightarrow b$.
#! The output is <C>true</C> if there exists a morphism $\iota: b \rightarrow a$
#! such that $\iota \circ \beta \sim_{c,a} \alpha$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsCodominating",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


###################################
##
#! @Section Identity Morphism and Composition of Morphisms
##
###################################

#! @Description
#! The argument is an object $a$.
#! The output is its identity morphism $\mathrm{id}_a$.
#! @Returns a morphism in $\mathrm{Hom}(a,a)$
#! @Arguments a
DeclareAttribute( "IdentityMorphism",
                                          IsCapCategoryObject );


#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow b$, $\beta: b \rightarrow c$.
#! The output is the composition $\beta \circ \alpha: a \rightarrow c$.
#! @Returns a morphism in $\mathrm{Hom}( a, c )$
#! @Arguments alpha, beta
DeclareOperation( "PreCompose",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method.
#! The argument is a list of morphisms
#! $L = ( \alpha_1: a_1 \rightarrow a_2, \alpha_2: a_2 \rightarrow a_3, \dots, \alpha_n: a_n \rightarrow a_{n+1} )$.
#! The output is the composition
#! $\alpha_{n} \circ ( \alpha_{n-1} \circ ( \dots ( \alpha_2 \circ \alpha_1 ) ) )$.
#! @Returns a morphism in $\mathrm{Hom}(a_1, a_{n+1})$
#! @Arguments L
DeclareOperation( "PreCompose",
                  [ IsList ] );

#! @Description
#! The arguments are two objects <A>s</A> = $a_1$, <A>r</A> = $a_{n+1}$, and a list of morphisms
#! $L = ( \alpha_1: a_1 \rightarrow a_2, \alpha_2: a_2 \rightarrow a_3, \dots, \alpha_n: a_n \rightarrow a_{n+1} )$ in $C$.
#! The output is the composition
#! $\alpha_{n} \circ ( \alpha_{n-1} \circ ( \dots ( \alpha_2 \circ \alpha_1 ) ) )$.
#! If $L$ is empty, then $s$ must be equal to $r$ and the output is congruent to the identity morphism of $s$.
#! @Returns a morphism in $\mathrm{Hom}(s, r)$
#! @Arguments s, L, r
DeclareOperation( "PreComposeList",
                  [ IsCapCategoryObject, IsList, IsCapCategoryObject ] );


#! @Description
#! The arguments are two morphisms $\beta: b \rightarrow c$, $\alpha: a \rightarrow b$.
#! The output is the composition $\beta \circ \alpha: a \rightarrow c$.
#! @Returns a morphism in $\mathrm{Hom}( a, c )$
#! @Arguments beta, alpha
DeclareOperation( "PostCompose",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method.
#! The argument is a list of morphisms
#! $L = ( \alpha_n: a_n \rightarrow a_{n+1}, \alpha_{n-1}: a_{n-1} \rightarrow a_n, \dots, \alpha_1: a_1 \rightarrow a_2 )$.
#! The output is the composition
#! $((\alpha_{n} \circ  \alpha_{n-1}) \circ \dots  \alpha_2) \circ \alpha_1$.
#! @Returns a morphism in $\mathrm{Hom}(a_1, a_{n+1})$
#! @Arguments L
DeclareOperation( "PostCompose",
                  [ IsList ] );

#! @Description
#! The arguments are two objects <A>s</A> = $a_1$, <A>r</A> = $a_{n+1}$, and a list of morphisms
#! $L = ( \alpha_n: a_n \rightarrow a_{n+1}, \alpha_{n-1}: a_{n-1} \rightarrow a_n, \dots, \alpha_1: a_1 \rightarrow a_2 )$.
#! The output is the composition
#! $((\alpha_{n} \circ  \alpha_{n-1}) \circ \dots  \alpha_2) \circ \alpha_1$.
#! If $L$ is empty, then $s$ must be equal to $r$ and the output is congruent to the identity morphism of $s$.
#! @Returns a morphism in $\mathrm{Hom}(s, r)$
#! @Arguments s, L, r
DeclareOperation( "PostComposeList",
                  [ IsCapCategoryObject, IsList, IsCapCategoryObject ] );

#! @Description
#! The arguments are two objects <A>s</A>, <A>r</A> and a list <A>morphisms</A> of morphisms from <A>s</A> to <A>r</A>.
#! The output is the sum of all elements in <A>morphisms</A>, or the zero-morphism from <A>s</A> to <A>r</A> 
#! if <A>morphisms</A> is empty.
#! @Returns a morphism in $\mathrm{Hom}(s,r)$
#! @Arguments s, morphisms, r
DeclareOperation( "SumOfMorphisms",
                  [ IsCapCategoryObject, IsList, IsCapCategoryObject ] );

#! @Description
#! The arguments are two objects <A>s</A>, <A>r</A> in some linear category over a ring $R$,
#! a list <A>coeffs</A> of ring elements in $R$ and a list <A>mors</A> of morphisms from <A>s</A> to <A>r</A>.
#! The output is the linear combination of the morphisms in <A>mors</A> with respect to the coefficients list <A>coeffs</A>,
#! or the zero morphism from <A>s</A> to <A>r</A> if <A>coeffs</A> and <A>mors</A> are the empty lists.
#! @Returns a morphism in $\mathrm{Hom}(s,r)$
#! @Arguments s, coeffs, mors, r
DeclareOperation( "LinearCombinationOfMorphisms",
                  [ IsCapCategoryObject, IsList, IsList, IsCapCategoryObject ] );

###################################
##
#! @Section Well-Definedness of Morphisms
##
###################################

#! @Description
#! The argument is a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is well-defined,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha
DeclareOperation( "IsWellDefinedForMorphisms",
                  [ IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two well-defined objects $S$ and $T$ and a morphism $\alpha$.
#! The output is <C>true</C> if $\alpha$ is a well-defined morphism from $S$ to $T$,
#! otherwise the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments source, alpha, range
DeclareOperation( "IsWellDefinedForMorphismsWithGivenSourceAndRange",
                  [ IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryObject ] );

###################################
##
#! @Section Lift/Colift
##
###################################

#! * For any pair of morphisms $\alpha: a \rightarrow c$, $\beta: b \rightarrow c$,
#!  we call each morphism $\alpha / \beta: a \rightarrow b$ such that
#!  $\beta \circ (\alpha / \beta) \sim_{a,c} \alpha$ a <Emph>lift of $\alpha$ along $\beta$</Emph>.
#! @BeginLatexOnly
#! \begin{center}
#! \begin{tikzpicture}
#! \def\w{2}
#! \def\h{1}
#! \node (a) at (0,\h) {$a$};
#! \node (b) at (0,-\h) {$b$};
#! \node (c) at (\w,0) {$c$};
#! \draw[-latex] (a) to node[pos=0.45, above] {$\alpha$} (c);
#! \draw[-latex] (b) to node[pos=0.45, below] {$\beta$} (c);
#! \draw[-latex, dashed] (a) to node[pos=0.45, left] {$\alpha/\beta$} (b);
#! \end{tikzpicture}
#! \end{center}
#! @EndLatexOnly
#! * For any pair of morphisms $\alpha: a \rightarrow c$, $\beta: a \rightarrow b$,
#!  we call each morphism $\alpha \backslash \beta: c \rightarrow b$ such that
#!  $(\alpha \backslash \beta) \circ \alpha \sim_{a,b} \beta$ a <Emph> colift of $\beta$ along $\alpha$</Emph>.
#! @BeginLatexOnly
#! \begin{center}
#! \begin{tikzpicture}
#! \def\w{2}
#! \def\h{1}
#! \node (a) at (0,0) {$a$};
#! \node (c) at (\w,\h) {$c$};
#! \node (b) at (\w,-\h) {$b$};
#! \draw[-latex] (a) to node[pos=0.45, above] {$\alpha$} (c);
#! \draw[-latex] (a) to node[pos=0.45, below] {$\beta$} (b);
#! \draw[-latex, dashed] (c) to node[pos=0.45, right] {$\alpha \backslash \beta$} (b);
#! \end{tikzpicture}
#! \end{center}
#! @EndLatexOnly

#! Note that such lifts (or colifts) do not have to be unique. So in general,
#! we do not expect that algorithms computing lifts (or colifts) do this in a functorial way.
#! Thus the operations $\mathtt{Lift}$ and $\mathtt{Colift}$ are not regarded as 
#! categorical operations, but only as set-theoretic operations.

#! @Description
#! The arguments are a monomorphism $\iota: k \hookrightarrow a$
#! and a morphism $\tau: t \rightarrow a$
#! such that there is a morphism $u: t \rightarrow k$ with
#! $\iota \circ u \sim_{t,a} \tau$.
#! The output is such a $u$.
#! @Returns a morphism in $\mathrm{Hom}(t,k)$
#! @Arguments iota, tau
DeclareOperation( "LiftAlongMonomorphism",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are an epimorphism $\epsilon: a \rightarrow c$
#! and a morphism $\tau: a \rightarrow t$
#! such that there is a morphism $u: c \rightarrow t$ with
#! $u \circ \epsilon \sim_{a,t} \tau$.
#! The output is such a $u$.
#! @Returns a morphism in $\mathrm{Hom}(c,t)$
#! @Arguments epsilon, tau
DeclareOperation( "ColiftAlongEpimorphism",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are a monomorphism $\iota: k \hookrightarrow a$
#! and a morphism $\tau: t \rightarrow a$.
#! The output is <C>true</C> if there exists
#! a morphism $u: t \rightarrow k$ with
#! $\iota \circ u \sim_{t,a} \tau$.
#! Otherwise, the output is  <C>false</C>.
#! @Returns a boolean
#! @Arguments iota, tau
DeclareOperation( "IsLiftableAlongMonomorphism",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are an epimorphism $\epsilon: a \rightarrow c$
#! and a morphism $\tau: a \rightarrow t$.
#! The output is <C>true</C> if there exists
#! a morphism $u: c \rightarrow t$ with
#! $u \circ \epsilon \sim_{a,t} \tau$.
#! Otherwise, the output is  <C>false</C>.
#! @Returns a boolean
#! @Arguments epsilon, tau
DeclareOperation( "IsColiftableAlongEpimorphism",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow c$, $\beta: b \rightarrow c$
#! such that a lift $\alpha / \beta: a \rightarrow b$ of $\alpha$ along $\beta$ exists.
#! The output is such a lift $\alpha / \beta: a \rightarrow b$.
#! Recall that a lift $\alpha / \beta: a \rightarrow b$ of $\alpha$ along $\beta$ is
#! a morphism such that $\beta \circ (\alpha / \beta) \sim_{a,c} \alpha$.
#! @Returns a morphism in $\mathrm{Hom}(a,b)$
#! @Arguments alpha, beta
DeclareOperation( "Lift",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience operation.
#! The arguments are two morphisms $\alpha: a \rightarrow c$, $\beta: b \rightarrow c$.
#! The output is a lift $\alpha / \beta: a \rightarrow b$ of $\alpha$ along $\beta$
#! if such a lift exists or $\mathtt{fail}$ if it doesn't.
#! Recall that a lift $\alpha / \beta: a \rightarrow b$ of $\alpha$ along $\beta$ is
#! a morphism such that $\beta \circ (\alpha / \beta) \sim_{a,c} \alpha$.
#! @Returns a morphism in $\mathrm{Hom}(a,b) + \{ \mathtt{fail} \}$
#! @Arguments alpha, beta
DeclareOperation( "LiftOrFail",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow c$, $\beta: b \rightarrow c$.
#! The output is <C>true</C> if there exists
#!  a lift $\alpha / \beta: a \rightarrow b$ of $\alpha$ along $\beta$, i.e.,
#! a morphism such that $\beta \circ (\alpha / \beta) \sim_{a,c} \alpha$.
#! Otherwise, the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsLiftable",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow c$, $\beta: a \rightarrow b$
#! such that a colift $\alpha \backslash \beta: c \rightarrow b$ of $\beta$ along $\alpha$ exists.
#! The output is such a colift $\alpha \backslash \beta: c \rightarrow b$.
#! Recall that a colift $\alpha \backslash \beta: c \rightarrow b$ of $\beta$ along $\alpha$ is
#! a morphism such that $(\alpha \backslash \beta) \circ \alpha \sim_{a,b} \beta$.
#! @Returns a morphism in $\mathrm{Hom}(c,b)$
#! @Arguments alpha, beta
DeclareOperation( "Colift",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


#! @Description
#! This is a convenience operation.
#! The arguments are two morphisms $\alpha: a \rightarrow c$, $\beta: a \rightarrow b$.
#! The output is a colift $\alpha \backslash \beta: c \rightarrow b$ of $\beta$ along $\alpha$
#! if such a colift exists or $\mathtt{fail}$ if it doesn't.
#! Recall that a colift $\alpha \backslash \beta: c \rightarrow b$ of $\beta$ along $\alpha$ is
#! a morphism such that $(\alpha \backslash \beta) \circ \alpha \sim_{a,b} \beta$.
#! @Returns a morphism in $\mathrm{Hom}(c,b) + \{ \mathtt{fail} \}$
#! @Arguments alpha, beta
DeclareOperation( "ColiftOrFail",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );


#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow c$, $\beta: a \rightarrow b$.
#! The output is <C>true</C> if there exists
#! a colift $\alpha \backslash \beta: c \rightarrow b$ of $\beta$ along $\alpha$., i.e.,
#! a morphism such that $(\alpha \backslash \beta) \circ \alpha \sim_{a,b} \beta$.
#! Otherwise, the output is <C>false</C>.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "IsColiftable",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

####################################
##
#! @Section Inverses
##
####################################

#! Let $\alpha: a \rightarrow b$ be a morphism. An inverse of $\alpha$
#! is a morphism $\alpha^{-1}: b \rightarrow a$ such that
#! $\alpha \circ \alpha^{-1} \sim_{b,b} \mathrm{id}_b$
#! and $\alpha^{-1} \circ \alpha \sim_{a,a} \mathrm{id}_a$.

#! @BeginLatexOnly
#! \begin{center}
#! \begin{tikzpicture}
#! \def\w{2}
#! \def\h{1}
#! \node (a) at (0,0) {$a$};
#! \node (b) at (\w,0) {$b$};
#! \draw[-latex] (a) to node[pos=0.45, above] {$\alpha$} (b);
#! \draw[-latex] (b) to [out = -135, in = -45] node[pos=0.45, below] {$\alpha^{-1}$} (a);
#! \draw [-latex] (a.135) arc (45:45+280:4mm) node[pos=0.5,left] {$\mathrm{id}_a$} (a);
#! \draw [-latex] (b.45) arc (-240:-240-280:4mm) node[pos=0.5,right] {$\mathrm{id}_b$} (b);
#! \end{tikzpicture}
#! \end{center}
#! @EndLatexOnly

#! @Description
#! The argument is an isomorphism $\alpha: a \rightarrow b$.
#! The output is its inverse $\alpha^{-1}: b \rightarrow a$.
#! @Returns a morphism in $\mathrm{Hom}(b,a)$
#! @Arguments alpha
DeclareOperation( "InverseForMorphisms",
                  [ IsCapCategoryMorphism ] );

#! @Description
#! The argument is a split-epimorphism $\alpha: a \rightarrow b$.
#! The output is a pre-inverse $\iota: b \rightarrow a$ of $\alpha$,
#! i.e., $\iota$ satisfies $\alpha \circ \iota \sim_{b,b} \mathrm{id}_b$.
#! The morphism $\iota$ is also known as a section or a right-inverse of $\alpha$.
#! @Returns a morphism in $\mathrm{Hom}(b,a)$
#! @Arguments alpha
DeclareOperation( "PreInverseForMorphisms",
                  [ IsCapCategoryMorphism ] );

#! @Description
#! The argument is a split-monomorphism $\alpha: a \rightarrow b$.
#! The output is a post-inverse $\pi: b \rightarrow a$ of $\alpha$,
#! i.e., $\pi$ satisfies $\pi \circ \alpha \sim_{a,a} \mathrm{id}_a$.
#! The morphism $\pi$ is also known as a contraction or a left-inverse of $\alpha$.
#! @Returns a morphism in $\mathrm{Hom}(b,a)$
#! @Arguments alpha
DeclareOperation( "PostInverseForMorphisms",
                  [ IsCapCategoryMorphism ] );

###################################
##
#! @Section Tool functions for caches
##
###################################

#! @Description
#!  By default, CAP uses caches to store the values of Categorical operations.
#!  To get a value out of the cache, one needs to compare the input of a basic operation
#!  with its previous input. To compare morphisms in the category, IsEqualForCacheForMorphisms is
#!  used. By default, IsEqualForCacheForMorphisms falls back to IsEqualForCache (see ToolsForHomalg),
#!  which in turn defaults to recursive comparison for lists and `IsIdenticalObj` in all other cases.
#!  If you add a function via `AddIsEqualForCacheForMorphisms`, that function is used instead.
#!  A function $F: a,b \mapsto bool$ is expected there. The output has to be
#!  true or false. Fail is not allowed in this context.
#! @Arguments phi, psi
#! @Returns true or false
DeclareOperation( "IsEqualForCacheForMorphisms",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

###################################
##
#! @Section Transport Operations
##
###################################

## mor: x -> y
## equality_source: x -> x'
## equality_range: y -> y'
## TransportHom( mor, equality_source, equality_range ): x' -> y'
DeclareOperation( "TransportHom",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism, IsCapCategoryMorphism ] );

###################################
##
#! @Section IsHomSetInhabited
##
###################################

#! @Description
#!  The arguments are two objects <A>A</A> and <A>B</A>.
#!  The output is <C>true</C> if there exists a morphism from <A>A</A> to <A>B</A>,
#!  otherwise the output is <C>false</C>.
#! @Arguments A, B
#! @Returns a boolean
DeclareOperation( "IsHomSetInhabited",
        [ IsCapCategoryObject, IsCapCategoryObject ] );

###################################
##
#! @Section SetOfMorphisms
##
###################################

#! @Description
#!  Return a duplicate free list of morphisms of the finite category <A>C</A>.
#! @Arguments C
#! @Returns a list of a &CAP; category morphisms
DeclareAttribute( "SetOfMorphismsOfFiniteCategory",
        IsCapCategory );

#! @Description
#!  Return a duplicate free list of morphisms of the finite category <A>C</A>.
#!  The corresponding &CAP; operation is <C>SetOfMorphismsOfFiniteCategory</C>.
#! @Arguments C
#! @Returns a list of &CAP; category objects
DeclareAttribute( "SetOfMorphisms", IsCapCategory );

###################################
##
#! @Section Homomorphism structures
##
###################################

#! Homomorphism structures are way to "oversee" the homomorphisms between two given objects.
#! Let $C$, $D$ be categories.
#! A $D$-homomorphism structure for $C$ consists of the following data:
#! * a functor $H: C^{\mathrm{op}} \times C \rightarrow D$ (when $C$ and $D$ are Ab-categories, $H$ is assumed to be bilinear).
#! * an object $1 \in D$, called the distinguished object,
#! * a bijection $\nu: \mathrm{Hom}_{C}(a,b) \simeq \mathrm{Hom}_{D}(1, H(a,b))$ natural in $a,b \in C$.

#! @Description
#! The arguments are two objects $a, b$ in $C$.
#! The output is the value of the homomorphism structure on objects $H(a,b)$.
#! @Returns an object in $D$
#! @Arguments a,b
DeclareOperation( "HomomorphismStructureOnObjects",
                  [ IsCapCategoryObject, IsCapCategoryObject ] );

#! @Description
#! The arguments are two morphisms $\alpha: a \rightarrow a', \beta: b \rightarrow b'$ in $C$.
#! The output is the value of the homomorphism structure on morphisms $H(\alpha, \beta )$.
#! @Returns a morphism in $\mathrm{Hom}_{D}(H(a',b), H(a,b'))$
#! @Arguments alpha, beta
DeclareOperation( "HomomorphismStructureOnMorphisms",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are an object $s = H(a',b)$ in $D$,
#! two morphisms $\alpha: a \rightarrow a', \beta: b \rightarrow b'$ in $C$,
#! and an object $r = H(a,b')$ in $D$.
#! The output is the value of the homomorphism structure on morphisms $H(\alpha, \beta )$.
#! @Returns a morphism in $\mathrm{Hom}_{D}(H(a',b), H(a,b'))$
#! @Arguments s, alpha, beta, r
DeclareOperation( "HomomorphismStructureOnMorphismsWithGivenObjects",
                  [ IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryMorphism, IsCapCategoryObject ] );

#! @Description
#! The argument is a category $C$.
#! The output is the distinguished object $1$ in $D$ of the homomorphism structure.
#! @Returns an object in $D$
#! @Arguments C
DeclareAttribute( "DistinguishedObjectOfHomomorphismStructure",
                  IsCapCategory );

#! @Description
#! The argument is a morphism  $\alpha: a \rightarrow a'$ in $C$.
#! The output is the corresponding morphism
#! $\nu( \alpha ): 1 \rightarrow H(a,a')$ in $D$ of the homomorphism structure.
#! @Returns a morphism in $\mathrm{Hom}_{D}(1, H(a,a'))$
#! @Arguments alpha
DeclareAttribute( "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructure",
                  IsCapCategoryMorphism );

#! @Description
#! The arguments are the distinguished object $1$, a morphism  $\alpha: a \rightarrow a'$, and the object $r = H(a,a')$.
#! The output is the corresponding morphism
#! $\nu( \alpha ): 1 \rightarrow r$ in $D$ of the homomorphism structure.
#! @Returns a morphism in $\mathrm{Hom}_{D}(1, r)$
#! @Arguments distinguished_object, alpha, r
DeclareOperation( "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureWithGivenObjects",
                  [ IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryObject ] );

#! @Description
#! The arguments are
#! objects $a,a'$ in $C$
#! and a morphism $\iota: 1 \rightarrow H(a,a')$ in $D$.
#! The output is the corresponding morphism
#! $\nu^{-1}(\iota): a \rightarrow a'$ in $C$ of the homomorphism structure.
#! @Returns a morphism in $\mathrm{Hom}_{C}(a,a')$
#! @Arguments a,a',iota
DeclareOperation( "InterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphism",
                  [ IsCapCategoryObject, IsCapCategoryObject, IsCapCategoryMorphism ] );

#! @Description
#! The arguments are three lists $\alpha$, $\beta$, and $\gamma$.
#! The first list $\alpha$ (the left coefficients) is a list of list of morphisms $\alpha_{ij}: A_i \rightarrow B_j$,
#! where $i = 1 \dots m$ and $j = 1 \dots n$ for integers $m,n \geq 1$.
#! The second list $\beta$ (the right coefficients) is a list of list of morphisms $\beta_{ij}: C_j \rightarrow D_i$,
#! where $i = 1 \dots m$ and $j = 1 \dots n$.
#! The third list $\gamma$ (the right side) is a list of morphisms $\gamma_i: A_i \rightarrow D_i$,
#! where $i = 1, \dots, m$.
#! Assumes that a solution to the linear system defined by $\alpha$, $\beta$, $\gamma$ exists, i.e.,
#! there exist morphisms $X_j: B_j \rightarrow C_j$ for $j=1\dots n$ such that
#! $\sum_{j = 1}^n \alpha_{ij}\cdot X_j \cdot \beta_{ij} = \gamma_i$
#! for all $i = 1 \dots m$.
#! The output is list of such morphisms $X_j: B_j \rightarrow C_j$ for $j=1\dots n$.
#! @Returns a list of morphisms $[X_1, \dots, X_n]$
#! @Arguments alpha, beta, gamma
DeclareOperation( "SolveLinearSystemInAbCategory",
                   [ IsList, IsList, IsList ] );

#! @Description
#! This is a convenience operation.
#! Like <C>SolveLinearSystemInAbCategory</C>,
#! but without the assumption that a solution exists.
#! If no solution exists, `fail` is returned.
#! @Returns a list of morphisms $[X_1, \dots, X_n]$ or `fail`
#! @Arguments alpha, beta, gamma
DeclareOperation( "SolveLinearSystemInAbCategoryOrFail",
                   [ IsList, IsList, IsList ] );

#! @Description
#! Like <C>SolveLinearSystemInAbCategory</C>,
#! but the output is simply <C>true</C> if a solution exists,
#! <C>false</C> otherwise.
#! @Returns a boolean
#! @Arguments alpha, beta, gamma
DeclareOperation( "MereExistenceOfSolutionOfLinearSystemInAbCategory",
                   [ IsList, IsList, IsList ] );

#! @Description
#! Like <C>SolveLinearSystemInAbCategory</C>,
#! but the output is simply <C>true</C> if a unique solution exists,
#! and <C>false</C> otherwise.
#! @Returns a boolean
#! @Arguments alpha, beta, gamma
DeclareOperation( "MereExistenceOfUniqueSolutionOfLinearSystemInAbCategory",
                   [ IsList, IsList, IsList ] );

#! @Description
#! Like <C>SolveLinearSystemInAbCategory</C>
#! but the output is <C>true</C> if the homogeneous system has only the trivial zero solution,
#! and <C>false</C> otherwise.
#! @Returns a boolean
#! @Arguments alpha, beta
DeclareOperation( "MereExistenceOfUniqueSolutionOfHomogeneousLinearSystemInAbCategory",
                   [ IsList, IsList ] );

#! @Description
#! The arguments are two lists of lists $\alpha$ and $\beta$ of morphisms in a linear category over a commutative ring $k$.
#! The first list $\alpha$ (the left coefficients) is a list of list of morphisms $\alpha_{ij}: A_i \rightarrow B_j$,
#! where $i = 1, \dots, m$ and $j = 1, \dots, n$ for integers $m,n \geq 1$.
#! The second list $\beta$ (the right coefficients) is a list of list of morphisms $\beta_{ij}: C_j \rightarrow D_i$,
#! where $i = 1, \dots, m$ and $j = 1, \dots, n$.
#! The output is a generating set $[X^1,\dots,X^t]$ for the solutions of the homogeneous linear system:
#! $\sum_{j = 1}^n \alpha_{ij}\cdot X_{j} \cdot \beta_{ij} = 0, ~i = 1, \dots, m$.
#! Particularly, each $X^k$ is a list (of length $n$) of morphisms $X^k_j:B_j \to C_j, j=1,\dots,n$.
#! @Returns a list of lists of morphisms $[X^1, \dots, X^t]$
#! @Arguments alpha, beta
DeclareOperation( "BasisOfSolutionsOfHomogeneousLinearSystemInLinearCategory",
                   [ IsList, IsList ] );

#! @Description
#! The arguments are four lists of lists $\alpha$, $\beta$, $\gamma$, $\delta$ of morphisms in some linear category over commutative ring.
#! Each of $\alpha$ and $\gamma$ is a list of list of morphisms $\alpha_{ij}, \gamma_{ij}: A_i \rightarrow B_j$,
#! where $i = 1, \dots, m$ and $j = 1, \dots, n$ for integers $m,n \geq 1$.
#! Each of $\beta$ and $\delta$ is also a list of list of morphisms $\beta_{ij}, \delta_{ij}: C_j \rightarrow D_i$,
#! where $i = 1, \dots, m$ and $j = 1, \dots, n$.
#! The output is a generating set $[X^1,\dots,X^t]$ for the solutions of the homogeneous linear system
#! defined by $\alpha$, $\beta$, $\gamma$ and $\delta$, i.e.,
#! $\sum_{j = 1}^n \alpha_{ij}\cdot X^{k}_{j} \cdot \beta_{ij} = \sum_{j = 1}^n \gamma_{ij}\cdot X^{k}_{j} \cdot \delta_{ij}$
#! for all $i = 1, \dots, m$ and all $k = 1, \dots, t$.
#! @Returns a list of lists of morphisms $[X^1, \dots, X^t]$
#! @Arguments alpha, beta, gamma, delta
DeclareOperation( "BasisOfSolutionsOfHomogeneousDoubleLinearSystemInLinearCategory",
                   [ IsList, IsList, IsList, IsList ] );

#! @Description
#! The arguments are two lists of lists $\alpha$, $\delta$ morphisms in some linear category
#! over commutative ring.
#! $\alpha$ is a list of list of morphisms $\alpha_{ij}:A_i \rightarrow B_j$ and
#! $\delta$ is a list of list of morphisms $\delta_{ij}:C_j \rightarrow D_i$,
#! where $i = 1, \dots, m$ and $j = 1, \dots, n$ for integers $m,n \geq 1$.
#! The method delegates to <C>BasisOfSolutionsOfHomogeneousDoubleLinearSystemInLinearCategory</C> applied on $\alpha$, $\beta$, $\gamma$, $\delta$ where
#! * $\beta_{ij}$ equals <C>IdentityMorphism</C>(<C>Source</C>($\delta_{ij}$)) if $\delta_{ij}$ is an endomorphism,
#!   and <C>ZeroMorphism</C>(<C>Source</C>($\delta_{ij}$), <C>Range</C>($\delta_{ij}$)) otherwise,
#! * $\gamma_{ij}$ equals <C>IdentityMorphism</C>(<C>Source</C>($\alpha_{ij}$)) if $\alpha_{ij}$ is an endomorphism,
#!    and <C>ZeroMorphism</C>(<C>Source</C>($\alpha_{ij}$), <C>Range</C>($\alpha_{ij}$)) otherwise;
#! for all $i = 1, \dots, m$ and $j = 1, \dots, n$.
#! @Returns a list of lists of morphisms $[X^1, \dots, X^t]$
#! @Arguments alpha, delta
DeclareOperation( "BasisOfSolutionsOfHomogeneousDoubleLinearSystemInLinearCategory",
                   [ IsList, IsList ] );

#! @Description
#! This is a convenience method.
#! The arguments are two morphisms $\alpha: a \rightarrow a', \beta: b \rightarrow b'$ in $C$.
#! The output is <C>HomomorphismStructureOnMorphisms</C> called on $\alpha$, $\beta$.
#! @Returns a morphism in $\mathrm{Hom}_{D}(H(a',b), H(a,b'))$
#! @Arguments alpha, beta
DeclareOperation( "HomStructure",
                  [ IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method.
#! The arguments are a morphism $\alpha: a \rightarrow a'$ and an object $b$ in $C$.
#! The output is <C>HomomorphismStructureOnMorphisms</C> called on $\alpha$, $\mathrm{id}_b$.
#! @Returns a morphism in $\mathrm{Hom}_{D}(H(a',b), H(a,b))$
#! @Arguments alpha, b
DeclareOperation( "HomStructure",
                  [ IsCapCategoryMorphism, IsCapCategoryObject ] );

#! @Description
#! This is a convenience method.
#! The arguments are an object $a$ and a morphism $\beta: b \rightarrow b'$ in $C$.
#! The output is <C>HomomorphismStructureOnMorphisms</C> called on $\mathrm{id}_a$, $\beta$.
#! @Returns a morphism in $\mathrm{Hom}_{D}(H(a,b), H(a,b'))$
#! @Arguments a, beta
DeclareOperation( "HomStructure",
                  [ IsCapCategoryObject, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method.
#! The arguments are two objects $a$ and $b$ in $C$.
#! The output is <C>HomomorphismStructureOnObjects</C> called on $a,b$.
#! @Returns an object
#! @Arguments a, b
DeclareOperation( "HomStructure",
                  [ IsCapCategoryObject, IsCapCategoryObject ] );

#! @Description
#! This is a convenience method for
#! <C>InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructure</C>.
DeclareOperation( "HomStructure",
                  [ IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method for
#! <C>InterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphism</C>.
DeclareOperation( "HomStructure",
                  [ IsCapCategoryObject, IsCapCategoryObject, IsCapCategoryMorphism ] );

#! @Description
#! This is a convenience method for
#! <C>DistinguishedObjectOfHomomorphismStructure</C>.
DeclareOperation( "HomStructure",
                  [ IsCapCategory ] );

#! @BeginGroup
#! @Description
#! If $\iota\colon D \to E$ is a full embedding of categories, every $D$-homomorphism structure for a category $C$
#! extends to a $E$-homomorphism structure for $C$. This operations accepts four functions
#! and installs operations `DistinguishedObjectOfHomomorphismStructureExtendedByFullEmbedding`,
#! `HomomorphismStructureOnObjectsExtendedByFullEmbedding` etc. which correspond to the $E$-homomorphism structure for $C$.
#! Note: To distinguish embeddings in different categories, in addition to $C$ also $E$ is passed to the operations.
#! When using this with different embeddings with the range category $E$, only the last embedding will be used.
#! The arguments are:
#! * `object_function` gets the categories $C$ and $E$ and an object in $D$.
#! * `morphism_function` gets the categories $C$ and $E$, an object in $E$, a morphism in $D$ and another object in $E$.
#!   The objects are the results of `object_function` applied to the source and range of the morphism.
#! * `object_function_inverse` gets the categories $C$ and $E$ and an object in $E$.
#! * `morphism_function_inverse` gets the categories $C$ and $E$, an object in $D$, a morphism in $E$ and another object in $D$.
#!   The objects are the results of `object_function_inverse` applied to the source and range of the morphism.
#! `object_function` and `morphism_function` define the embedding. `object_function_inverse` and `morphism_function_inverse` define
#! the inverse of the embedding on its image.
#! @Returns nothing
#! @Arguments C, E, object_function, morphism_function, object_function_inverse, morphism_function_inverse
DeclareOperation( "ExtendRangeOfHomomorphismStructureByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsFunction, IsFunction, IsFunction, IsFunction ] );

#! @Arguments C, E, a, b
DeclareOperation( "HomomorphismStructureOnObjectsExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryObject ] );

#! @Arguments C, E, alpha, beta
DeclareOperation( "HomomorphismStructureOnMorphismsExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsCapCategoryMorphism, IsCapCategoryMorphism ] );

#! @Arguments C, E, s, alpha, beta, r
DeclareOperation( "HomomorphismStructureOnMorphismsWithGivenObjectsExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryMorphism, IsCapCategoryObject ] );

#! @Arguments C, E
DeclareOperation( "DistinguishedObjectOfHomomorphismStructureExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory ] );

#! @Arguments C, E, alpha
DeclareOperation( "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsCapCategoryMorphism ] );

#! @Arguments C, E, distinguished_object, alpha, r
DeclareOperation( "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureWithGivenObjectsExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryObject ] );

#! @Arguments C, E, a, a', iota
DeclareOperation( "InterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphismExtendedByFullEmbedding",
                  [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryObject, IsCapCategoryMorphism ] );
#! @EndGroup

CapJitAddTypeSignature( "HomomorphismStructureOnObjectsExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryObject ], function ( input_types )
    
    return CapJitDataTypeOfObjectOfCategory( input_types[2].category );
    
end );

CapJitAddTypeSignature( "HomomorphismStructureOnMorphismsExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory, IsCapCategoryMorphism, IsCapCategoryMorphism ], function ( input_types )
    
    return CapJitDataTypeOfMorphismOfCategory( input_types[2].category );
    
end );

CapJitAddTypeSignature( "HomomorphismStructureOnMorphismsWithGivenObjectsExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryMorphism, IsCapCategoryObject ], function ( input_types )
    
    return CapJitDataTypeOfMorphismOfCategory( input_types[2].category );
    
end );

CapJitAddTypeSignature( "DistinguishedObjectOfHomomorphismStructureExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory ], function ( input_types )
    
    return CapJitDataTypeOfObjectOfCategory( input_types[2].category );
    
end );

CapJitAddTypeSignature( "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory, IsCapCategoryMorphism ], function ( input_types )
    
    return CapJitDataTypeOfMorphismOfCategory( input_types[2].category );
    
end );

CapJitAddTypeSignature( "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureWithGivenObjectsExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryMorphism, IsCapCategoryObject ], function ( input_types )
    
    return CapJitDataTypeOfMorphismOfCategory( input_types[2].category );
    
end );

CapJitAddTypeSignature( "InterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphismExtendedByFullEmbedding", [ IsCapCategory, IsCapCategory, IsCapCategoryObject, IsCapCategoryObject, IsCapCategoryMorphism ], function ( input_types )
    
    return CapJitDataTypeOfMorphismOfCategory( input_types[1].category );
    
end );

#! @Description
#! Chooses the identity on $D$ as the full embedding in
#! <Ref Oper="ExtendRangeOfHomomorphismStructureByFullEmbedding" Label="for IsCapCategory, IsCapCategory, IsFunction, IsFunction, IsFunction, IsFunction" />.
#! This is useful to handle this case as a degenerate case of
#! <Ref Oper="ExtendRangeOfHomomorphismStructureByFullEmbedding" Label="for IsCapCategory, IsCapCategory, IsFunction, IsFunction, IsFunction, IsFunction" />.
#! @Returns nothing
#! @Arguments C
DeclareOperation( "ExtendRangeOfHomomorphismStructureByIdentityAsFullEmbedding",
                  [ IsCapCategory ] );

#! @Description
#! The argument are two objects <A>a</A>, <A>b</A>.
#! The output is a list of all morphisms from <A>a</A> to <A>b</A>.
#! @Returns a list of morphisms in $\mathrm{Hom}( a, b )$
#! @Arguments a, b
DeclareOperation( "MorphismsOfExternalHom",
        [ IsCapCategoryObject, IsCapCategoryObject ] );

#! @Description
#! The arguments are objects $a,b$ in a $k$-linear category $C$.
#! The output is a list $L$ of morphisms which is a basis of $\mathrm{Hom}_{C}(a,b)$ in
#! the sense that any given morphism $\alpha: a \to b$ can uniquely be written as a
#! linear combination of $L$ with the coefficients in
#! <C>CoefficientsOfMorphism</C>($\alpha$).
#! @Returns a list of morphisms in $\mathrm{Hom}_{C}(a,b)$
#! @Arguments a, b
DeclareOperation( "BasisOfExternalHom",
                  [ IsCapCategoryObject, IsCapCategoryObject ] );

#! @Description
#! This is a convenience method.
#! The argument is a morphism  $\alpha: a \to b$ in a $k$-linear category $C$.
#! The output is a list of coefficients of $\alpha$ with respect to the list
#! <C>BasisOfExternalHom</C>(<A>a</A>,<A>b</A>).
#! @Returns a list of elements in $k$
#! @Arguments alpha
DeclareAttribute( "CoefficientsOfMorphism",
                  IsCapCategoryMorphism );

###################################
##
#! @Section Simplified Morphisms
##
###################################

#! Let $\phi: A \rightarrow B$ be a morphism.
#! There are several different natural ways to look at $\phi$ as an object in an ambient category:

#! - $\mathrm{Hom}( A, B )$, the set of homomorphisms with the equivalence relation $\mathtt{IsCongruentForMorphisms}$ regarded as a category,
#! - $\sum_{A}\mathrm{Hom}( A, B )$, the category of morphisms where the range is fixed,
#! - $\sum_{B}\mathrm{Hom}( A, B )$, the category of morphisms where the source is fixed,
#! - $\sum_{A,B}\mathrm{Hom}( A, B )$, the category of morphisms where neither source nor range is fixed,

#! and furthermore, if $\phi$ happens to be an endomorphism $A \rightarrow A$,
#! we also have

#! - $\sum_{A}\mathrm{Hom}(A,A)$, the category of endomorphisms.

#! Let $\mathbf{C}$ be one of the categories above in which $\phi$ may reside as an object,
#! and let $i$ be a non-negative integer or $\infty$.
#! CAP provides commands for passing from $\phi$ to $\phi_i$, where $\phi_i$ is isomorphic to $\phi$
#! in $\mathbf{C}$, but "simpler".
#! The idea is that the greater the $i$, the "simpler" the $\phi_i$ (but this could mean the harder the computation),
#! with $\infty$ as a possible value.
#! The case $i = 0$ defaults to the identity operator for all simplifications.
#! For the Add-operatations, only the cases $i \geq 1$ have to be given as functions.
#! 
#! 
#! $\ $
#!
#!
#! If we regard $\phi$ as an object in the category $\mathrm{Hom}( A, B )$,
#! $\phi_i$ is again in $\mathrm{Hom}( A, B )$ such that $\phi \sim_{A,B} \phi_i$.
#! This case is handled by the following commands:

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is a simplified morphism $\phi_i$.
#! @Returns a morphism in $\mathrm{Hom}(A,B)$
#! @Arguments phi, i
DeclareOperation( "SimplifyMorphism",
                  [ IsCapCategoryMorphism, IsObject ] );

#! $\ $
#!
#! If we regard $\phi$ as an object in the category $\sum_{A}\mathrm{Hom}( A, B )$,
#! then $\phi_i$ is a morphism of type $A_i \rightarrow B$ and there is an isomorphism
#! $\sigma_i: A \rightarrow A_i$ such that
#! $\phi_i \circ \sigma_i \sim_{A,B} \phi$.
#! This case is handled by the following commands:

## SimplifySource
#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is a simplified morphism with simplified source $\phi_i: A_i \rightarrow B$.
#! @Returns a morphism in $\mathrm{Hom}(A_i,B)$
#! @Arguments phi, i
DeclareOperation( "SimplifySource",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $(\sigma_i)^{-1}: A_i \rightarrow A$.
#! @Returns a morphism in $\mathrm{Hom}(A_i,A)$
#! @Arguments phi, i
DeclareOperation( "SimplifySource_IsoToInputObject",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $\sigma_i: A \rightarrow A_i$.
#! @Returns a morphism in $\mathrm{Hom}(A,A_i)$
#! @Arguments phi, i
DeclareOperation( "SimplifySource_IsoFromInputObject",
                  [ IsCapCategoryMorphism, IsObject ] );

## SimplifyRange
#! $\ $
#!
#! If we regard $\phi$ as an object in the category $\sum_{B}\mathrm{Hom}( A, B )$,
#! then $\phi_i$ is a morphism of type $A \rightarrow B_i$ and there is an isomorphism
#! $\rho_i: B \rightarrow B_i$ such that
#! $ \rho_i^{-1} \circ \phi_i\sim_{A,B} \phi$.
#! This case is handled by the following commands:

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is a simplified morphism with simplified range $\phi_i: A \rightarrow B_i$.
#! @Returns a morphism in $\mathrm{Hom}(A,B_i)$
#! @Arguments phi, i
DeclareOperation( "SimplifyRange",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $(\rho_i)^{-1}: B_i \rightarrow B$.
#! @Returns a morphism in $\mathrm{Hom}(B_i,B)$
#! @Arguments phi, i
DeclareOperation( "SimplifyRange_IsoToInputObject",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $\rho_i: B \rightarrow B_i$.
#! @Returns a morphism in $\mathrm{Hom}(B,B_i)$
#! @Arguments phi, i
DeclareOperation( "SimplifyRange_IsoFromInputObject",
                  [ IsCapCategoryMorphism, IsObject ] );

## SimplifySourceAndRange*
#! $\ $
#!
#! If we regard $\phi$ as an object in the category $\sum_{A, B}\mathrm{Hom}( A, B )$,
#! then $\phi_i$ is a morphism of type $A_i \rightarrow B_i$ and there is are isomorphisms
#! $\sigma_i: A \rightarrow A_i$ and
#! $\rho_i: B \rightarrow B_i$ such that
#! $ \rho_i^{-1} \circ \phi_i \circ \sigma_i \sim_{A,B} \phi$.
#! This case is handled by the following commands:

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is a simplified morphism with simplified source and range $\phi_i: A_i \rightarrow B_i$.
#! @Returns a morphism in $\mathrm{Hom}(A_i,B_i)$
#! @Arguments phi, i
DeclareOperation( "SimplifySourceAndRange",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $(\rho_i)^{-1}: B_i \rightarrow B$.
#! @Returns a morphism in $\mathrm{Hom}(B_i,B)$
#! @Arguments phi, i
DeclareOperation( "SimplifySourceAndRange_IsoToInputRange",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $\rho_i: B \rightarrow B_i$.
#! @Returns a morphism in $\mathrm{Hom}(B,B_i)$
#! @Arguments phi, i
DeclareOperation( "SimplifySourceAndRange_IsoFromInputRange",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $(\sigma_i)^{-1}: A_i \rightarrow A$.
#! @Returns a morphism in $\mathrm{Hom}(A_i,A)$
#! @Arguments phi, i
DeclareOperation( "SimplifySourceAndRange_IsoToInputSource",
                  [ IsCapCategoryMorphism, IsObject ] );

#! @Description
#! The arguments are a morphism $\phi: A \rightarrow B$ and a non-negative integer $i$ or <C>infinity</C>.
#! The output is the isomorphism $\sigma_i: A \rightarrow A_i$.
#! @Returns a morphism in $\mathrm{Hom}(A,A_i)$
#! @Arguments phi, i
DeclareOperation( "SimplifySourceAndRange_IsoFromInputSource",
                  [ IsCapCategoryMorphism, IsObject ] );

## SimplifyEndo*
#! $\ $
#!
#! If $\phi:A \rightarrow A$ is an endomorphism, we may regard it as an object in the category $\sum_{A}\mathrm{Hom}( A, A )$.
#! In this case
#! $\phi_i$ is a morphism of type $A_i \rightarrow A_i$ and there is an isomorphism
#! $\sigma_i: A \rightarrow A_i$ such that
--> --------------------

--> maximum size reached

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

[ Verzeichnis aufwärts0.29unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]