From f61c63afc9f331371dd8344b253f304cf539f2fa Mon Sep 17 00:00:00 2001 From: Tom Kuhmichel Date: Tue, 4 Aug 2026 20:44:32 +0200 Subject: [PATCH] D&I AdditiveClosureOfObjectFiniteCategory --- AdditiveClosuresForCAP/PackageInfo.g | 2 +- AdditiveClosuresForCAP/doc/Doc.autodoc | 16 +- ...eClosureOfObjectFiniteCategory_Kronecker.g | 23 + ...osureOfObjectFiniteCategory_constructors.g | 47 + .../examples/CategoryOfRows.g | 7 + .../AdditiveClosureOfObjectFiniteCategory.gd | 407 +++++ .../AdditiveClosureOfObjectFiniteCategory.gi | 1483 +++++++++++++++++ AdditiveClosuresForCAP/init.g | 3 +- AdditiveClosuresForCAP/makedoc.g | 3 + AdditiveClosuresForCAP/read.g | 3 +- ...itiveClosureOfObjectFiniteCategoryTest.tst | 135 ++ 11 files changed, 2122 insertions(+), 7 deletions(-) create mode 100644 AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_Kronecker.g create mode 100644 AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_constructors.g create mode 100644 AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gd create mode 100644 AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gi create mode 100644 AdditiveClosuresForCAP/tst/AdditiveClosureOfObjectFiniteCategoryTest.tst diff --git a/AdditiveClosuresForCAP/PackageInfo.g b/AdditiveClosuresForCAP/PackageInfo.g index b4cec8bc86..6940a59dde 100644 --- a/AdditiveClosuresForCAP/PackageInfo.g +++ b/AdditiveClosuresForCAP/PackageInfo.g @@ -10,7 +10,7 @@ SetPackageInfo( rec( PackageName := "AdditiveClosuresForCAP", Subtitle := "Additive closures for pre-additive categories", -Version := "2026.07-03", +Version := "2026.08-01", Date := (function ( ) if IsBound( GAPInfo.SystemEnvironment.GAP_PKG_RELEASE_DATE ) then return GAPInfo.SystemEnvironment.GAP_PKG_RELEASE_DATE; else return Concatenation( ~.Version{[ 1 .. 4 ]}, "-", ~.Version{[ 6, 7 ]}, "-01" ); fi; end)( ), License := "GPL-2.0-or-later", diff --git a/AdditiveClosuresForCAP/doc/Doc.autodoc b/AdditiveClosuresForCAP/doc/Doc.autodoc index b1c343a516..6d984f9c18 100644 --- a/AdditiveClosuresForCAP/doc/Doc.autodoc +++ b/AdditiveClosuresForCAP/doc/Doc.autodoc @@ -15,11 +15,23 @@ @Section GAP Categories @Chapter Reinterpret a linear category over a commutative semiring with free f.g. external Homs -@Section Constructors + +@Chapter Example on additive closure + +@Chapter Additive closure of an object finite category +@ChapterLabel AdditiveClosureObjectFinite + +@InsertChunk AddClosureObjFinIntroduction +@InsertChunk AddClosureObjFinConstruction @Section Attributes +@Section Constructors +@Section Operations +@Section Operators @Section GAP Categories +@Section Examples -@Chapter Example on additive closure +@Subsection Test Monoidal +@InsertChunk AddClosureObjFinKronecker @Chapter Category of rows @Section Constructors diff --git a/AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_Kronecker.g b/AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_Kronecker.g new file mode 100644 index 0000000000..3199b7e064 --- /dev/null +++ b/AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_Kronecker.g @@ -0,0 +1,23 @@ +#! @BeginChunk AddClosureObjFinKronecker + +#! @Example +LoadPackage( "AdditiveClosuresForCAP", false ); +#! true +Q := HomalgFieldOfRationals();; +R := RingAsCategory( Q );; +A := AdditiveClosureOfObjectFiniteCategory( R );; +u := TensorUnit( A );; +mor1 := [ [ 1 / R, 2 / R ] ] / A;; +mor2 := [ [ 3 / R, 4 / R ] ] / A;; +T := TensorProduct( mor1, mor2 );; +Display( T ); +#! A 1 x 4 matrix with entries in RingAsCategory( Q ) +#! +#! [1,1]: <3> +#! [1,2]: <4> +#! [1,3]: <6> +#! [1,4]: <8> +Display( Range( T ) ); +#! A formal direct sum consisting of 4 objects: +#! 4 times: * +#! @EndExample diff --git a/AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_constructors.g b/AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_constructors.g new file mode 100644 index 0000000000..30b4497d78 --- /dev/null +++ b/AdditiveClosuresForCAP/examples/AdditiveClosureOfObjectFiniteCategory_constructors.g @@ -0,0 +1,47 @@ +#! @BeginChunk AddClosureObjFinConstruction + +#! @Example +LoadPackage( "LinearClosuresForCAP", false ); +#! true +D := FiniteSkeletalDiscreteCategory( [ 1 .. 4 ] );; +Q := HomalgFieldOfRationals( );; +L := LinearClosure( Q, D );; +A := AdditiveClosureOfObjectFiniteCategory( L );; +source := AdditiveClosureObject( A, [ 3, [ 2, 1, 0, 0 ] ] );; +source = [ D[1] / L, D[2] / L, D[1] / L ] / A; +#! true +Display( source ); +#! A formal direct sum consisting of 3 objects: +#! +#! 2 times: LinearClosureObject() +#! 1 times: LinearClosureObject() +#! 0 times: LinearClosureObject() +#! 0 times: LinearClosureObject() +target := AdditiveClosureObject( A, [ 2, [ 0, 1, 1, 0 ] ] );; +Display( target ); +#! A formal direct sum consisting of 2 objects: +#! +#! 0 times: LinearClosureObject() +#! 1 times: LinearClosureObject() +#! 1 times: LinearClosureObject() +#! 0 times: LinearClosureObject() +id_2 := IdentityMorphism( D[2] / L );; +zero_12 := ZeroMorphism( L, D[1] / L, D[2] / L );; +zero_13 := ZeroMorphism( L, D[1] / L, D[3] / L );; +zero_23 := ZeroMorphism( L, D[2] / L, D[3] / L );; +matrix := [ [ zero_12, zero_13 ], [ zero_12, zero_13 ], [ id_2, zero_23] ];; +m := AdditiveClosureMorphism( A, source, matrix, target );; +m = matrix / A; +#! true +Display( m ); +#! A 3 x 2 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 4 ] ) ) +#! +#! [1,1]: 0 +#! [1,2]: 0 +#! [2,1]: 0 +#! [2,2]: 0 +#! [3,1]: (1*) +#! [3,2]: 0 +#! @EndExample +#! @EndChunk + diff --git a/AdditiveClosuresForCAP/examples/CategoryOfRows.g b/AdditiveClosuresForCAP/examples/CategoryOfRows.g index cb330c707b..574cbabd8e 100644 --- a/AdditiveClosuresForCAP/examples/CategoryOfRows.g +++ b/AdditiveClosuresForCAP/examples/CategoryOfRows.g @@ -21,6 +21,13 @@ obj2 := CategoryOfRowsObject( 8, rows ); #! @Section Constructors of morphisms ##################################### +s := CategoryOfRowsObject( 2, rows );; +t := CategoryOfRowsObject( 0, rows );; +mor := CategoryOfRowsMorphism( s, HomalgMatrix( [ [],[] ], 2, 0, S ), t );; +IsWellDefined( mor ); + +mor := CategoryOfRowsMorphism( s, HomalgMatrix( [ ], 2, 0, S ), t );; + #! @Example obj3 := CategoryOfRowsObject( 1, rows ); #! diff --git a/AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gd b/AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gd new file mode 100644 index 0000000000..a74bd7db04 --- /dev/null +++ b/AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gd @@ -0,0 +1,407 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# FiniteCocompletions: Finite (co)product/(co)limit (co)completions +# +# Declarations +# + +#! @Chapter Additive closure of an object finite category + +#! @BeginChunk AddClosureObjFinIntroduction + +#! Let $C$ be a pre-additive category and $C^\oplus \coloneqq \texttt{AdditiveClosure}( C )$. +#! An object $O = o_1 \oplus \dots \oplus o_n$ of $C^\oplus$ is modeled as a list +#! of objects $[ o_1, \dots, o_n ]$ with $o_i \in C$. If $C$ has only finitely +#! many objects $\{ o_1, \dots, o_n \}$, a shorter data structure for the objects of $C^\oplus$ +#! can be achieved by remembering only the multiplicities of each object $o_j \in C$ in the list $o$. +#! +#! As an example, assume $C$ contains exactly four objects $\{ o_1, o_2, o_3, o_4 \}$ and let +#! @BeginLatexOnly +#! \begin{center} +#! $o \coloneqq o_2 \oplus o_3 \oplus o_1 \oplus o_3 \oplus o_2 \oplus o_2 \in C^\oplus$ +#! \end{center} +#! @EndLatexOnly +#! be modeled by the list $[ o_2, o_3, o_1, o_3, o_2, o_2 ]$. +#! We can abbreviate this by remembering only the list of multiplicities $[ 1, 3, 2, 0 ]$. +#! The object $o_1$ occurs one time, $o_2$ occurs three times, $o_3$ occurs two times +#! and $o_4$ occurs zero times in $o$. +#! For compilation purposes, we additionally store the sum of all multiplicities, which is 6. +#! The final result is thus $o = [ 6, [ 1, 3, 2, 0 ] ]$. +#! Notice, that this requires an ordering on the set of objects of $C$. +#! +#! The morphisms in $C^\oplus$ are given by matrices whose entries are morphisms +#! in $C$ and whose matrix-dimensions are given by the number of objects in the source and +#! range lists. In the case that $C$ has only finitely many objects, +#! this constructor uses the same datastructure, however, the ordering of the +#! underlying objects of $C$ has to be respected. +#! +#! Again, as an example, a morphism $o_1 \oplus o_1 \oplus o_2 \rightarrow o_2 \oplus o_3$ +#! is given by the below matrix. +#! +#! @BeginLatexOnly +#! \begin{center} +#! \[ +#! \begin{array}{c|cc} +#! & o_2 & o_3 \\ +#! \hline +#! o_1 & m_{12} & m_{13} \\ +#! o_1 & m_{12} & m_{13} \\ +#! o_2 & m_{22} & m_{23} +#! \end{array} +#! \] +#! \end{center} +#! @EndLatexOnly +#! +#! If $C$ is skeletal, then this additive closure is also skeletal. + +#! @EndChunk + +#################################### +## +#! @Section GAP Categories +## +#################################### + +#! @Description +#! The &GAP; category of additive closures of object finite Ab-categories. +#! @Arguments object +#! @Returns true or false +DeclareCategory( "IsAdditiveClosureOfObjectFiniteCategory", + IsCapCategory ); + +#! @Description +#! The &GAP; category of objects in additive closures of object finite Ab-categories. +#! @Arguments object +#! @Returns true or false +DeclareCategory( "IsObjectInAdditiveClosureOfObjectFiniteCategory", + IsCapCategoryObject ); + +#! @Description +#! The &GAP; category of morphisms in additive closures of object finite Ab-categories. +#! @Arguments object +#! @Returns true or false +DeclareCategory( "IsMorphismInAdditiveClosureOfObjectFiniteCategory", + IsCapCategoryMorphism ); + +DeclareGlobalFunction( "INSTALL_FUNCTIONS_FOR_ADDITIVE_CLOSURE_OF_OBJECT_FINITE_CATEGORY" ); + +#################################### +## +#! @Section Constructors +## +#################################### + +#! @Description +#! The argument is an object finite pre-additive category $C$. The output is its additive closure $C^\oplus$. +#! @Arguments C +#! @Returns the category $C^\oplus$ +DeclareAttribute( "AdditiveClosureOfObjectFiniteCategory", + IsCapCategory ); + +#! @Description +#! Same as , but as an operation instead of an attribute. +#! @Arguments C +#! @Returns the category $C^\oplus$ +DeclareOperation( "ADDITIVE_CLOSURE_OF_OBJECT_FINITE_CATEGORY", + [ IsCapCategory ] ); + +if false then +#! @Description +#! The input is an additive closure AC := AdditiveClosureOfObjectFiniteCategory( $A$ ) +#! of an object finite pre-additive category A and a list of the format +#! $[ s, [ m_1, ..., m_n ] ]$ representing a direct sum $o_1^{m_1} \oplus \dots \oplus o_n^{m_n}$ where +#! * $o_1, \dots, o_n$ are all of the objects in the underlying category; +#! * $m_1, ..., m_n$ are non-negative integers representing the multiplicties; +#! * $s$ is the sum of integers $m_1 + \dots + m_n$. +#! See also . +#! @Arguments AC, l +#! @Returns an object in $C^\oplus$ +DeclareOperation( "ObjectConstructor", [ IsAdditiveClosureOfObjectFiniteCategory, IsList ] ); +fi; + +#! @Description +#! This method takes the same arguments as ObjectConstructor and delegates to it. +#! @Arguments AC, l +#! @Returns an object in $C^\oplus$ +DeclareOperation( "AdditiveClosureObject", + [ IsAdditiveClosureOfObjectFiniteCategory, IsList ] ); + +CapJitAddTypeSignature( "AdditiveClosureObject", [ IsAdditiveClosureOfObjectFiniteCategory, IsList ], + function ( input_types ) + + return CapJitDataTypeOfObjectOfCategory( input_types[1].category ); + +end ); + +if false then +#! @Description +#! The input is an additive closure AC := AdditiveClosureOfObjectFiniteCategory( $A$ ) +#! of an object finite pre-additive category A, +#! * s is the source object, +#! * matrix is a list of lists of morphisms in A, +#! * t is the target object. +#! See also . +#! @Arguments AC, s, matrix, t +#! @Returns an morphism in $C^\oplus$ +DeclareOperation( "MorphismConstructor", [ IsAdditiveClosureOfObjectFiniteCategory, ] ); +fi; + +#! @Description +#! This method takes the same arguments as MorphismConstructor and delegates to it. +#! @Arguments AC, s, matrix, t +#! @Returns an morphism in $C^\oplus$ +DeclareOperation( "AdditiveClosureMorphism", + [ IsObjectInAdditiveClosureOfObjectFiniteCategory, + IsList, + IsObjectInAdditiveClosureOfObjectFiniteCategory + ] ); + +CapJitAddTypeSignature( "AdditiveClosureMorphism", + [ IsAdditiveClosureOfObjectFiniteCategory, + IsObjectInAdditiveClosureOfObjectFiniteCategory, + IsList, + IsObjectInAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + return CapJitDataTypeOfMorphismOfCategory( input_types[1].category ); + +end ); + +#################################### +# +#! @Section Attributes +# +#################################### + +#! @Description +#! Return the category $A$ underlying the additive closure +#! AC := AdditiveClosureOfObjectFiniteCategory( $A$ ). +#! @Arguments AC +#! @Returns $A$. +DeclareAttribute( "UnderlyingCategory", IsAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "UnderlyingCategory", [ IsAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + return CapJitDataTypeOfCategory( UnderlyingCategory( input_types[1].category ) ); + +end ); + +#! @Description +#! @Arguments AC +#! @Returns a list of objects of the underlying category. +DeclareAttribute( "ListOfObjectsOfUnderlyingCategory", IsAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "ListOfObjectsOfUnderlyingCategory", [ IsAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + return CapJitDataTypeOfListOf( CapJitDataTypeOfObjectOfCategory( UnderlyingCategory( input_types[1].category ) ) ); + +end ); + +#! @Description +#! Return the number of objects in the category $A$ underlying the additive closure +#! AC := AdditiveClosureOfObjectFiniteCategory( $A$ ). +#! @Arguments AC +#! @Returns an integer +DeclareAttribute( "NumberOfObjectsOfUnderlyingCategory", IsAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "NumberOfObjectsOfUnderlyingCategory", [ IsAdditiveClosureOfObjectFiniteCategory ], IsBigInt ); + +#! @Description +#! The argument is an object $O$ in the additive closure of an object finite pre-additive category. +#! It returns a list of the format $[ s, [ m_1, ..., m_n ] ]$ representing a direct sum $o_1^{m_1} \oplus \dots \oplus o_n^{m_n}$ where +#! * $o_1, \dots, o_n$ are all of the objects in the underlying category; +#! * $m_1, ..., m_n$ are non-negative integers representing the multiplicties; +#! * $s$ is the sum of integers $m_1 + \dots + m_n$, i.e., the number of summands of $A$. +#! @Arguments object +#! @Returns a list consisting of an integer and a list of integers. +DeclareAttribute( "NrSummandsAndMultiplicities", IsObjectInAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "NrSummandsAndMultiplicities", [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + Assert( 0, IsAdditiveClosureOfObjectFiniteCategory( input_types[1].category ) ); + + return CapJitDataTypeOfNTupleOf( 2, IsBigInt, CapJitDataTypeOfListOf( IsBigInt ) ); + +end ); + +#! @Description +#! The argument is an object $O$ in the additive closure $C^\oplus$ of an object finite pre-additive category $C$. +#! It returns a list of objects of $C$ in the format +#! $[ \underbrace{o_1, \dots, o_1}_{m_1}, \dots, \underbrace{o_n, \dots, o_n}_{m_n} ]$ +#! corresponding to the list of multiplicties $[ s, [ m_1, ..., m_n ] ]$ of $A$. +#! @Arguments A +#! @Returns a list of objects of the underlying category. +DeclareOperation( "UnderlyingObjectList", [ IsAdditiveClosureOfObjectFiniteCategory, IsObjectInAdditiveClosureOfObjectFiniteCategory ] ); + +CapJitAddTypeSignature( "UnderlyingObjectList", [ IsAdditiveClosureOfObjectFiniteCategory, IsObjectInAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + Assert( 0, IsAdditiveClosureOfObjectFiniteCategory( input_types[2].category ) ); + + return CapJitDataTypeOfListOf( CapJitDataTypeOfObjectOfCategory( UnderlyingCategory( input_types[1].category ) ) ); + +end ); + +#! @Description +#! The argument is a morphism in the additive closure of an object finite pre-additive category. +#! It returns a list of lists representing a matrix of morphisms of the underlying category. +#! @Arguments morphism +#! @Returns a list of lists of morphisms of the underlying category. +DeclareAttribute( "MorphismMatrix", IsMorphismInAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "MorphismMatrix", [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + Assert( 0, IsAdditiveClosureOfObjectFiniteCategory( input_types[1].category ) ); + + return CapJitDataTypeOfListOf( + CapJitDataTypeOfListOf( + CapJitDataTypeOfMorphismOfCategory( UnderlyingCategory( input_types[1].category ) ) ) ); + +end ); + +#! @Description +#! The argument is a morphism $\alpha \colon A \to B$. The output is the number of rows +#! of the morphism matrix of $\alpha$. +#! @Arguments alpha +#! @Returns an integer +DeclareAttribute( "NumberRows", IsMorphismInAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "NumberRows", [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], IsBigInt ); + +#! @Description +#! The argument is a morphism $\alpha \colon A \to B$. The output is the number of columns of the morphism matrix of $\alpha$. +#! @Arguments alpha +#! @Returns an integer +DeclareAttribute( "NumberColumns", + IsMorphismInAdditiveClosureOfObjectFiniteCategory ); + +CapJitAddTypeSignature( "NumberColumns", [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], IsBigInt ); + +#################################### +## +#! @Section Operations +## +#################################### + +#! @Description +#! The argument is an object $O$ in the additive closure $C^\oplus$ of an object finite pre-additive category $C$. +#! It returns the number $s$ of summands of $A$ corresponding to the list of multiplicties +#! $[ s, [ m_1, ..., m_n ] ]$ of $A$. +#! @Arguments A +#! @Returns an integer +DeclareOperation( "NrOfSummands", [ IsObjectInAdditiveClosureOfObjectFiniteCategory ] ); + +CapJitAddTypeSignature( "NrOfSummands", [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], IsBigInt ); + +#! @Description +#! The argument is an object $O$ in the additive closure $C^\oplus$ of an object finite pre-additive category $C$. +#! It returns the list of multiplicties $[ m_1, \dots, m_n ]$ of $A$. +#! @Arguments A +#! @Returns a list of integers. +DeclareOperation( "Multiplicities", [ IsObjectInAdditiveClosureOfObjectFiniteCategory ] ); + +CapJitAddTypeSignature( "Multiplicities", [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], + function ( input_types ) + + Assert( 0, IsAdditiveClosureOfObjectFiniteCategory( input_types[1].category ) ); + + return CapJitDataTypeOfListOf( IsBigInt ); + +end ); + +#! @Description +#! The argument is an object $O$ in an object finite pre-additive category $C$. +#! It returns the mulitplicity list for $A$, i.e., a list of integers +#! $[ 0, \dots, 0, 1, 0, \dots 0]$ where $1$. +#! @Arguments A +#! @Returns a list of integers. +DeclareOperation( "ObjectToMultiplicityList", + [ IsCapCategory and IsObjectFiniteCategory, IsCapCategoryObject ] ); + +CapJitAddTypeSignature( "ObjectToMultiplicityList", + [ IsCapCategory and IsObjectFiniteCategory, IsCapCategoryObject ], + function ( input_types ) + + return CapJitDataTypeOfListOf( IsBigInt ); + +end ); + +#! @Description +#! The argument is a list of objects L in an object finite pre-additive category $C$. +#! It returns the mulitplicity list for the objects in L. +#! @Arguments L +#! @Returns a list of integers. +DeclareOperation( "ObjectsToMultiplicityList", + [ IsCapCategory and IsObjectFiniteCategory, IsList ] ); + +CapJitAddTypeSignature( "ObjectsToMultiplicityList", + [ IsCapCategory and IsObjectFiniteCategory, IsList ], + function ( input_types ) + + return CapJitDataTypeOfListOf( IsBigInt ); + +end ); + +#################################### +## +#! @Section Operators +## +#################################### + +#! @Description +#! The arguments are an object $O$ in an additive closure $C^\oplus$ of +#! an object finite category $C$ and an integer $i$. +#! The output is the $i$'th entry in UnderlyingObjectList($A$). +#! @Arguments A, i +#! @Returns an object in $C$ +DeclareOperation( "[]", [ IsObjectInAdditiveClosureOfObjectFiniteCategory, IsInt ] ); + +CapJitAddTypeSignature( "[]", [ IsObjectInAdditiveClosureOfObjectFiniteCategory, IsInt ], function ( input_types ) + + Assert( 0, IsAdditiveClosureOfObjectFiniteCategory( input_types[1].category ) ); + + return CapJitDataTypeOfObjectOfCategory( UnderlyingCategory( input_types[1].category ) ); + +end ); + +#! @Description +#! The arguments are a morphism $\alpha \colon A \to B$ in the additive closure $C^\oplus$ of +#! an object finite pre-additive category $C$ and two integers $i,j$. +#! The output is the $(i,j)$'th entry in MorphismMatrix($\alpha$). +#! @Arguments alpha, i, j +#! @Returns a morphism $C$ +DeclareOperation( "[,]", [ IsMorphismInAdditiveClosureOfObjectFiniteCategory, IsInt, IsInt ] ); + +CapJitAddTypeSignature( "[,]", [ IsMorphismInAdditiveClosureOfObjectFiniteCategory, IsInt, IsInt ], function ( input_types ) + + Assert( 0, IsAdditiveClosureOfObjectFiniteCategory( input_types[1].category ) ); + + return CapJitDataTypeOfMorphismOfCategory( UnderlyingCategory( input_types[1].category ) ); + +end ); + +#! @Description +#! The input is either +#! * a list of objects or +#! * a list of lists of morphisms +#! in the underlying category. +#! This operation then constructs either an object or a morphism in AdditiveClosureOfObjectFiniteCategory. +#! For a list of objects, the list will be automatically sorted and the underlying +#! order on the objects need not be respected. +#! +#! WARNING: Morphism lists of dimensions $0 \times n$ or $n \times 0$ are not supported. +#! @Arguments list, AC +DeclareOperation( "/", + [ IsList, IsAdditiveClosureOfObjectFiniteCategory ] ); + +#! @Description +#! This is a convenience method for +#! ObjectConstructor and MorphismConstructor. +#! @Arguments object or morphism, AC +#! @Returns an object or morphism in AC. +DeclareOperation( "/", + [ IsCapCategoryCell, IsAdditiveClosureOfObjectFiniteCategory ] ); + diff --git a/AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gi b/AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gi new file mode 100644 index 0000000000..02bf760062 --- /dev/null +++ b/AdditiveClosuresForCAP/gap/AdditiveClosureOfObjectFiniteCategory.gi @@ -0,0 +1,1483 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# FiniteCocompletions: Finite (co)product/(co)limit (co)completions +# +# Implementations +# + +#################################### +## +## Constructors +## +#################################### + +## +InstallOtherMethodForCompilerForCAP( AdditiveClosureObject, + [ IsAdditiveClosureOfObjectFiniteCategory, IsList ], + + function( category, nr_summands_and_multiplicities ) + + return ObjectConstructor( category, nr_summands_and_multiplicities ); + +end ); + +## +InstallMethod( AdditiveClosureMorphism, + [ IsObjectInAdditiveClosureOfObjectFiniteCategory, IsList, IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( source, morphism_matrix, target ) + + return MorphismConstructor( CapCategory( source ), source, morphism_matrix, target ); + +end ); + +## +InstallOtherMethodForCompilerForCAP( AdditiveClosureMorphism, + [ IsAdditiveClosureOfObjectFiniteCategory, + IsObjectInAdditiveClosureOfObjectFiniteCategory, + IsList, + IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( category, source, morphism_matrix, target ) + + return MorphismConstructor( category, source, morphism_matrix, target ); + +end ); + +## +InstallMethod( AdditiveClosureOfObjectFiniteCategory, + [ IsCapCategory ], + ADDITIVE_CLOSURE_OF_OBJECT_FINITE_CATEGORY +); + +## +InstallMethod( ADDITIVE_CLOSURE_OF_OBJECT_FINITE_CATEGORY, + [ IsCapCategory ], + + FunctionWithNamedArguments( + [ + [ "FinalizeCategory", true ], + ], + function( CAP_NAMED_ARGUMENTS, underlying_category ) + local AC_objfin, name, object_datum_type, morphism_datum_type, nr_objects_underlying_category, compare_morphisms, object_function, morphism_function, object_function_inverse, morphism_function_inverse; + + Assert( 0, HasIsAbCategory( underlying_category ) and IsAbCategory( underlying_category ) ); + + Assert( 0, HasIsObjectFiniteCategory( underlying_category ) and IsObjectFiniteCategory( underlying_category ) ); + + name := Concatenation( "AdditiveClosureOfObjectFiniteCategory( ", Name( underlying_category )," )" ); + + object_datum_type := + CapJitDataTypeOfNTupleOf( 2, + IsBigInt, + CapJitDataTypeOfListOf( IsBigInt ) ); + + morphism_datum_type := + CapJitDataTypeOfListOf( + CapJitDataTypeOfListOf( + CapJitDataTypeOfMorphismOfCategory( underlying_category ) ) ); + + AC_objfin := CreateCapCategoryWithDataTypes( name, + IsAdditiveClosureOfObjectFiniteCategory, + IsObjectInAdditiveClosureOfObjectFiniteCategory, + IsMorphismInAdditiveClosureOfObjectFiniteCategory, + IsCapCategoryTwoCell, + object_datum_type, + morphism_datum_type, + fail ); + + AC_objfin!.supports_empty_limits := true; + + AC_objfin!.compiler_hints := + rec( category_attribute_names := + [ "UnderlyingCategory", + "ListOfObjectsOfUnderlyingCategory", + "NumberOfObjectsOfUnderlyingCategory",] ); + + SetIsAdditiveCategory( AC_objfin, true ); + + if HasIsSkeletalCategory( underlying_category ) and IsSkeletalCategory( underlying_category ) then + + SetIsSkeletalCategory( AC_objfin, true ); + + fi; + + if HasIsLinearCategoryOverCommutativeRing( underlying_category ) and + IsLinearCategoryOverCommutativeRing( underlying_category ) and + HasCommutativeSemiringOfLinearCategory( underlying_category ) + then + + SetIsLinearCategoryOverCommutativeRing( AC_objfin, true ); + + SetCommutativeSemiringOfLinearCategory( AC_objfin, CommutativeSemiringOfLinearCategory( underlying_category ) ); + + if HasIsLinearCategoryOverCommutativeRingWithFinitelyGeneratedFreeExternalHoms( underlying_category ) and + IsLinearCategoryOverCommutativeRingWithFinitelyGeneratedFreeExternalHoms( underlying_category ) then + + SetIsLinearCategoryOverCommutativeRingWithFinitelyGeneratedFreeExternalHoms( AC_objfin, true ); + + # BasisOfExternalHom and CoefficientsOfMorphism can possibly be derived from the hom structure + # see https://github.com/homalg-project/CAP_project/pull/652 for a primitive implementation + + fi; + + fi; + + if HasRangeCategoryOfHomomorphismStructure( underlying_category ) then + + SetIsEquippedWithHomomorphismStructure( AC_objfin, true ); + + fi; + + if HasIsStrictMonoidalCategory( underlying_category ) and IsStrictMonoidalCategory( underlying_category ) then + + SetIsStrictMonoidalCategory( AC_objfin, true ); + + elif HasIsMonoidalCategory( underlying_category ) and IsMonoidalCategory( underlying_category ) then + + SetIsMonoidalCategory( AC_objfin, true ); + + fi; + + SetUnderlyingCategory( AC_objfin, underlying_category ); + + SetNumberOfObjectsOfUnderlyingCategory( AC_objfin, Length( SetOfObjectsOfCategory( underlying_category ) ) ); + + INSTALL_FUNCTIONS_FOR_ADDITIVE_CLOSURE_OF_OBJECT_FINITE_CATEGORY( AC_objfin, underlying_category ); + + # HandlePrecompiledTowers( AC_objfin, underlying_category, "AdditiveClosureOfObjectFiniteCategory" ); + + if CAP_NAMED_ARGUMENTS.FinalizeCategory then + + Finalize( AC_objfin ); + + fi; + + return AC_objfin; + +end ) ); + +InstallGlobalFunction( INSTALL_FUNCTIONS_FOR_ADDITIVE_CLOSURE_OF_OBJECT_FINITE_CATEGORY, + + function( AC_objfin, underlying_category ) + local nr_objects_underlying_category, compare_morphisms, object_function, morphism_function, object_function_inverse, morphism_function_inverse, underlying_range_category, range_category; + + nr_objects_underlying_category := NumberOfObjectsOfUnderlyingCategory( AC_objfin ); + + ## + AddObjectConstructor( AC_objfin, + function( AC_objfin, nr_summands_and_multiplicities ) + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, nr_summands_and_multiplicities[1] = Sum( nr_summands_and_multiplicities[2] ) ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, Length( nr_summands_and_multiplicities[2] ) = nr_objects_underlying_category ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, ForAll( nr_summands_and_multiplicities[2], multiplicity -> multiplicity >= 0 ) ); + + return CreateCapCategoryObjectWithAttributes( AC_objfin, + NrSummandsAndMultiplicities, nr_summands_and_multiplicities ); + + end ); + + ## + AddObjectDatum( AC_objfin, + function( AC_objfin, object ) + + return NrSummandsAndMultiplicities( object ); + + end ); + + ## + AddMorphismConstructor( AC_objfin, + function( AC_objfin, source, morphism_matrix, target ) + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, Length( morphism_matrix ) = NrOfSummands( source ) ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, ForAll( morphism_matrix, row -> Length( row ) = NrOfSummands( target ) ) ); + + return CreateCapCategoryMorphismWithAttributes( AC_objfin, + source, + target, + MorphismMatrix, morphism_matrix ); + + end ); + + ## + AddMorphismDatum( AC_objfin, + function( AC_objfin, morphism ) + + return MorphismMatrix( morphism ); + + end ); + + if CanCompute( underlying_category, "IsWellDefinedForObjects" ) then + + ## + AddIsWellDefinedForObjects( AC_objfin, + function( AC_objfin, object ) + local nr_summands_and_multiplicities; + + nr_summands_and_multiplicities := NrSummandsAndMultiplicities( object ); + + if not nr_summands_and_multiplicities[1] = Sum( nr_summands_and_multiplicities[2] ) then + + return false; + + elif not Length( nr_summands_and_multiplicities[2] ) = NumberOfObjectsOfUnderlyingCategory( AC_objfin ) then + + return false; + + elif ForAny( nr_summands_and_multiplicities[2], multiplicity -> multiplicity < 0 ) then + + return false; + + else + + return true; + + fi; + + end ); + + fi; + + if CanCompute( underlying_category, "IsWellDefinedForMorphismsWithGivenSourceAndRange" ) then + + ## + AddIsWellDefinedForMorphisms( AC_objfin, + function( AC_objfin, morphism ) + local source_list, target_list, nr_rows, nr_cols; + + source_list := UnderlyingObjectList( AC_objfin, Source( morphism ) ); + target_list := UnderlyingObjectList( AC_objfin, Target( morphism ) ); + + nr_rows := NumberRows( morphism ); + nr_cols := NumberColumns( morphism ); + + if Length( MorphismMatrix( morphism ) ) <> nr_rows then + + return false; + + elif ForAny( MorphismMatrix( morphism ), row -> Length( row ) <> nr_cols ) then + + return false; + + elif not ForAll( [ 1 .. nr_rows ], i -> + ForAll( [ 1 .. nr_cols ], j -> + # IsWellDefinedForMorphismsWithGivenSourceAndRange + IsWellDefinedForMorphisms( UnderlyingCategory( AC_objfin ), morphism[i,j] #, source_list[i], target_list[j] + ) and + IsEqualForObjects( UnderlyingCategory( AC_objfin ), Source( morphism[i,j] ), source_list[i] ) and + IsEqualForObjects( UnderlyingCategory( AC_objfin ), Target( morphism[i,j] ), target_list[j] ) ) ) + then + + return false; + + else + + return true; + + fi; + + end ); + + fi; + + ## + AddIsEqualForObjects( AC_objfin, + function( AC_objfin, object_1, object_2 ) + + return NrSummandsAndMultiplicities( object_1 ) = NrSummandsAndMultiplicities( object_2 ); + + end ); + + compare_morphisms := function( cat, morphism_1, morphism_2, comparison_function ) + local nr_rows_1, nr_rows_2, nr_cols_1, nr_cols_2; + #% CAP_JIT_RESOLVE_FUNCTION + + nr_rows_1 := NumberRows( morphism_1 ); + nr_rows_2 := NumberRows( morphism_2 ); + + nr_cols_1 := NumberColumns( morphism_1 ); + nr_cols_2 := NumberColumns( morphism_2 ); + + if nr_rows_1 <> nr_rows_2 then + + return false; + + elif nr_cols_1 <> nr_cols_2 then + + return false; + + fi; + + return ForAll( [ 1 .. nr_rows_1 ], i -> + ForAll( [ 1 .. nr_cols_1 ], j -> + comparison_function( UnderlyingCategory( cat ), morphism_1[i, j], morphism_2[i, j] ) ) ); + + end; + + ## + AddIsEqualForMorphisms( AC_objfin, + function( AC_objfin, morphism_1, morphism_2 ) + + return compare_morphisms( AC_objfin, morphism_1, morphism_2, IsEqualForMorphisms ); + + end ); + + ## + AddIsCongruentForMorphisms( AC_objfin, + function( AC_objfin, morphism_1, morphism_2 ) + + return compare_morphisms( AC_objfin, morphism_1, morphism_2, IsCongruentForMorphisms ); + + end ); + + ## + AddIdentityMorphism( AC_objfin, + function( AC_objfin, object ) + local size, object_list, morphism_matrix; + + size := NrOfSummands( object ); + + object_list := UnderlyingObjectList( AC_objfin, object ); + + morphism_matrix := + List( [ 1 .. size ], i -> + List( [ 1 .. size ], function( j ) + if i = j then + return IdentityMorphism( UnderlyingCategory( AC_objfin ), object_list[i] ); + else + return ZeroMorphism( UnderlyingCategory( AC_objfin ), object_list[i], object_list[j] ); + fi; + end ) ); + + return AdditiveClosureMorphism( AC_objfin, object, morphism_matrix, object ); + + end ); + + ## + AddPreCompose( AC_objfin, + function( AC_objfin, morphism_1, morphism_2 ) + local nr_rows_1, nr_cols_1, nr_rows_2, nr_cols_2, morphism_matrix, i, j; + + nr_rows_1 := NumberRows( morphism_1 ); + nr_rows_2 := NumberRows( morphism_2 ); + + nr_cols_1 := NumberColumns( morphism_1 ); + nr_cols_2 := NumberColumns( morphism_2 ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, nr_cols_1 = nr_rows_2 ); + + morphism_matrix := + List( [ 1 .. nr_rows_1 ], i -> + List( [ 1 .. nr_cols_2 ], j -> + SumOfMorphisms( UnderlyingCategory( AC_objfin ), + UnderlyingObjectList( AC_objfin, Source( morphism_1 ) )[i], + List( [ 1 .. nr_cols_1 ], k -> + PreCompose( UnderlyingCategory( AC_objfin ), morphism_1[i, k], morphism_2[k, j] ) ), + UnderlyingObjectList( AC_objfin, Target( morphism_2 ) )[j] ) ) ); + + return AdditiveClosureMorphism( AC_objfin, Source( morphism_1 ), morphism_matrix, Target( morphism_2 ) ); + + end ); + + ## + AddZeroMorphism( AC_objfin, + function( AC_objfin, source, target ) + local size_list_source, size_list_target, object_list_source, object_list_target, morphism_matrix, i, j; + + size_list_source := NrOfSummands( source ); + + size_list_target := NrOfSummands( target ); + + object_list_source := UnderlyingObjectList( AC_objfin, source ); + + object_list_target := UnderlyingObjectList( AC_objfin, target ); + + morphism_matrix := + List( [ 1 .. size_list_source ], i -> + List( [ 1 .. size_list_target ], j -> + ZeroMorphism( UnderlyingCategory( AC_objfin ), object_list_source[i], object_list_target[j] ))); + + return AdditiveClosureMorphism( AC_objfin, source, morphism_matrix, target ); + + end ); + + ## + AddIsZeroForMorphisms( AC_objfin, + function( AC_objfin, morphism ) + + return ForAll( [ 1 .. NumberRows( morphism ) ], i -> + ForAll( [ 1 .. NumberColumns( morphism ) ], j -> + IsZeroForMorphisms( UnderlyingCategory( AC_objfin ), morphism[i, j] ) ) ); + + end ); + + ## + AddAdditionForMorphisms( AC_objfin, + function( AC_objfin, morphism_1, morphism_2 ) + local morphism_matrix; + + morphism_matrix := + List( [ 1 .. NumberRows( morphism_1 ) ], i -> + List( [ 1 .. NumberColumns( morphism_1 ) ], j -> + AdditionForMorphisms( UnderlyingCategory( AC_objfin ), morphism_1[i, j], morphism_2[i, j] ) ) ); + + return AdditiveClosureMorphism( AC_objfin, Source( morphism_1 ), morphism_matrix, Target( morphism_1 ) ); + + end ); + + ## + AddSumOfMorphisms( AC_objfin, + function( AC_objfin, source, morphisms, target ) + local length_source_list, length_target_list, source_object_list, target_object_list, morphism_matrix; + + length_source_list := NrOfSummands( source ); + length_target_list := NrOfSummands( target ); + + source_object_list := UnderlyingObjectList( AC_objfin, source ); + target_object_list := UnderlyingObjectList( AC_objfin, target ); + + morphism_matrix := + List( [ 1 .. length_source_list ], i -> + List( [ 1 .. length_target_list ], j -> + SumOfMorphisms( underlying_category, + source_object_list[i], + List( morphisms, m -> m[i, j] ), + target_object_list[j] ) ) ); + + return AdditiveClosureMorphism( AC_objfin, + source, + morphism_matrix, + target ); + + end ); + + AddAdditiveInverseForMorphisms( AC_objfin, + function( AC_objfin, morphism ) + local morphism_matrix; + + morphism_matrix := + List( [ 1 .. NumberRows( morphism ) ], i -> + List( [ 1 .. NumberColumns( morphism ) ], j -> + AdditiveInverseForMorphisms( UnderlyingCategory( AC_objfin ), morphism[i, j] ) ) ); + + return AdditiveClosureMorphism( AC_objfin, Source( morphism ), morphism_matrix, Target( morphism ) ); + + end ); + + AddZeroObject( AC_objfin, + function( AC_objfin ) + local zero_list; + + zero_list := ListWithIdenticalEntries( NumberOfObjectsOfUnderlyingCategory( AC_objfin ), 0 ); + + return AdditiveClosureObject( AC_objfin, Pair( 0, zero_list ) ); + + end ); + + ## + AddDirectSum( AC_objfin, + function( AC_objfin, diagram ) + local sum; + + sum := Sum( List( diagram, obj -> NrSummandsAndMultiplicities( obj ) ) ); + + return AdditiveClosureObject( AC_objfin, sum ); + + end ); + + ## + AddUniversalMorphismIntoDirectSumWithGivenDirectSum( AC_objfin, + function( AC_objfin, diagram, test_object, morphisms, direct_sum ) + local morphism_matrix; + + morphism_matrix := UnionOfColumnsListList( NrOfSummands( test_object ), + List( morphisms, tau -> MorphismMatrix( tau ) ) ); + + return AdditiveClosureMorphism( AC_objfin, test_object, morphism_matrix, direct_sum ); + + end ); + + ## + AddUniversalMorphismFromDirectSumWithGivenDirectSum( AC_objfin, + function( AC_objfin, diagram, test_object, morphisms, direct_sum ) + local morphism_matrix; + + morphism_matrix := UnionOfRowsListList( NrOfSummands( test_object ), + List( morphisms, tau -> MorphismMatrix( tau ) ) ); + + return AdditiveClosureMorphism( AC_objfin, direct_sum, morphism_matrix, test_object ); + + end ); + + ## + AddComponentOfMorphismIntoDirectSum( AC_objfin, + function( AC_objfin, morphism, summands, nr ) + local lengths, offset, start, stop; + + lengths := List( summands, s -> NrOfSummands( s ) ); + + offset := Sum( lengths{[ 1 .. nr-1 ]} ); + + start := offset + 1; + stop := offset + lengths[nr]; + + return AdditiveClosureMorphism( AC_objfin, + Source( morphism ), + List( MorphismMatrix( morphism ), row -> row{[ start .. stop ]} ), # CertainColumns + summands[nr] ); + + end ); + + ## + AddComponentOfMorphismFromDirectSum( AC_objfin, + function( AC_objfin, morphism, summands, nr ) + local lengths, offset, start, stop; + + lengths := List( summands, s -> NrOfSummands( s ) ); + + offset := Sum( lengths{[ 1 .. nr-1 ]} ); + + start := offset + 1; + stop := offset + lengths[nr]; + + return AdditiveClosureMorphism( AC_objfin, summands[nr], + MorphismMatrix( morphism ){[ start .. stop ]}, # CertainRows + Target( morphism ) ); + + end ); + + if CanCompute( underlying_category, "MultiplyWithElementOfCommutativeSemiringForMorphisms" ) then + + AddMultiplyWithElementOfCommutativeSemiringForMorphisms( AC_objfin, + function( AC_objfin, r, alpha ) + local morphism_matrix; + + morphism_matrix := + List( [ 1 .. NumberRows( alpha ) ], i -> + List( [ 1 .. NumberColumns( alpha ) ], j -> + MultiplyWithElementOfCommutativeSemiringForMorphisms( underlying_category, r, alpha[i, j] ) ) ); + + return AdditiveClosureMorphism( AC_objfin, Source( alpha ), morphism_matrix, Target( alpha ) ); + + end ); + + fi; + + # The homomorphism structure is taken from AdditiveClosuresForCAP/gap/AdditiveClosure.gi + if HasRangeCategoryOfHomomorphismStructure( underlying_category ) then + + underlying_range_category := RangeCategoryOfHomomorphismStructure( underlying_category ); + + # If the range category of the underlying category is not additive but pre-additive, we first apply AdditiveClosure to it. + # See https://arxiv.org/abs/1908.04132 (Sebastian Posur: Methods of constructive category theory), Remark 1.28 + if not (HasIsAdditiveCategory( underlying_range_category ) and IsAdditiveCategory( underlying_range_category )) and + HasIsAbCategory( underlying_range_category ) and IsAbCategory( underlying_range_category ) + then + + if IsIdenticalObj( underlying_category, underlying_range_category ) then + + # prevent infinite recursion + range_category := AC_objfin; + + else + + range_category := AdditiveClosure( underlying_range_category ); + + fi; + + # prepare for ExtendRangeOfHomomorphismStructureByFullEmbedding + object_function := function ( category, range_category, object ) + #% CAP_JIT_RESOLVE_FUNCTION + + return AdditiveClosureObject( range_category, [ object ] ); + + end; + + morphism_function := function ( category, range_category, source, morphism, range ) + #% CAP_JIT_RESOLVE_FUNCTION + + return AdditiveClosureMorphism( range_category, source, [ [ morphism ] ], range ); + + end; + + object_function_inverse := function ( category, range_category, object ) + #% CAP_JIT_RESOLVE_FUNCTION + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, Length( ObjectList( object ) ) = 1 ); + + return ObjectList( object )[1]; + + end; + + morphism_function_inverse := function ( category, range_category, source, morphism, range ) + #% CAP_JIT_RESOLVE_FUNCTION + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, NumberRows( morphism ) = 1 and NumberColumns( morphism ) = 1 ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, IsEqualForObjects( source, Source( morphism[1,1] ) ) ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, IsEqualForObjects( range, Target( morphism[1,1] ) ) ); + + return morphism[1,1]; + + end; + + ExtendRangeOfHomomorphismStructureByFullEmbedding( underlying_category, + range_category, + object_function, + morphism_function, + object_function_inverse, + morphism_function_inverse ); + + else + + range_category := underlying_range_category; + + ExtendRangeOfHomomorphismStructureByIdentityAsFullEmbedding( underlying_category ); + + fi; + + SetRangeCategoryOfHomomorphismStructure( AC_objfin, range_category ); + + if (ForAll( [ "DirectSum" ], f -> CanCompute( range_category, f ) ) or IsIdenticalObj( range_category, AC_objfin ) ) and + ForAll( [ "HomomorphismStructureOnObjects" ], f -> CanCompute( underlying_category, f ) ) + then + + ## + AddHomomorphismStructureOnObjects( AC_objfin, + function( cat, object_1, object_2 ) + + return DirectSum( range_category, + List( [ 1 .. Length( UnderlyingObjectList( AC_objfin, object_1 ) ) ], j -> + DirectSum( range_category, + List( [ 1 .. Length( UnderlyingObjectList( AC_objfin, object_2 ) ) ], s -> + HomomorphismStructureOnObjectsExtendedByFullEmbedding( + UnderlyingCategory( cat ), + range_category, + UnderlyingObjectList( AC_objfin, object_1 )[j], + UnderlyingObjectList( AC_objfin, object_2 )[s] ) ) ) ) ); + + end ); + + fi; + + # legacy + if (ForAll( [ "MorphismBetweenDirectSumsWithGivenDirectSums" ], f -> CanCompute( range_category, f ) ) or IsIdenticalObj( range_category, AC_objfin )) and + ForAll( [ "HomomorphismStructureOnMorphismsWithGivenObjects" ], f -> CanCompute( underlying_category, f ) ) and + not (IsBound( range_category!.supports_empty_limits ) and range_category!.supports_empty_limits = true) then + + ## + AddHomomorphismStructureOnMorphismsWithGivenObjects( AC_objfin, + function( cat, source, alpha, beta, range ) + local size_i, size_j, size_s, size_t; + + size_i := NumberRows( alpha ); + + size_j := NumberColumns( alpha ); + + size_s := NumberRows( beta ); + + size_t := NumberColumns( beta ); + + if size_i <= 0 or size_j <= 0 or size_s <= 0 or size_t <= 0 then + + return ZeroMorphism( range_category, source, range ); + + fi; + + return MorphismBetweenDirectSums( + List( [ 1 .. size_j ], j -> + List( [ 1 .. size_i ], i -> + MorphismBetweenDirectSums( + List( [ 1 .. size_s ], s -> + List( [ 1 .. size_t ], t -> + HomomorphismStructureOnMorphismsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, alpha[i, j], beta[s, t] ) + ) + ) + ) + ) + ) ); + + end ); + + fi; + + if (ForAll( [ "MorphismBetweenDirectSumsWithGivenDirectSums" ], f -> CanCompute( range_category, f ) ) or IsIdenticalObj( range_category, AC_objfin )) + and ForAll( [ "HomomorphismStructureOnMorphismsWithGivenObjects" ], f -> CanCompute( underlying_category, f ) ) + and IsBound( range_category!.supports_empty_limits ) and range_category!.supports_empty_limits = true then + + ## + AddHomomorphismStructureOnMorphismsWithGivenObjects( AC_objfin, + function( cat, source, alpha, beta, range ) + local size_i, size_j, size_s, size_t, A, B, C, D, H_B_C, H_A_D, source_direct_sums, range_direct_sums; + + size_i := NumberRows( alpha ); + + size_j := NumberColumns( alpha ); + + size_s := NumberRows( beta ); + + size_t := NumberColumns( beta ); + + A := Source( alpha ); + B := Target( alpha ); + C := Source( beta ); + D := Target( beta ); + + H_B_C := + List( [ 1 .. size_j ], j -> + List( [ 1 .. size_s ], s -> + HomomorphismStructureOnObjectsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, B[j], C[s] ) + ) + ); + + H_A_D := + List( [ 1 .. size_i ], i -> + List( [ 1 .. size_t ], t -> + HomomorphismStructureOnObjectsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, A[i], D[t] ) + ) + ); + + source_direct_sums := List( [ 1 .. size_j ], j -> DirectSum( range_category, List( [ 1 .. size_s ], s -> H_B_C[j][s] ) ) ); + range_direct_sums := List( [ 1 .. size_i ], i -> DirectSum( range_category, List( [ 1 .. size_t ], t -> H_A_D[i][t] ) ) ); + + return MorphismBetweenDirectSumsWithGivenDirectSums( + range_category, + source, + source_direct_sums, + List( [ 1 .. size_j ], j -> + List( [ 1 .. size_i ], i -> + MorphismBetweenDirectSumsWithGivenDirectSums( + range_category, + source_direct_sums[j], + List( [ 1 .. size_s ], s -> H_B_C[j][s] ), + List( [ 1 .. size_s ], s -> + List( [ 1 .. size_t ], t -> + HomomorphismStructureOnMorphismsWithGivenObjectsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, H_B_C[j][s], alpha[i, j], beta[s, t], H_A_D[i][t] ) + ) + ), + List( [ 1 .. size_t ], t -> H_A_D[i][t] ), + range_direct_sums[i] + ) + ) + ), + range_direct_sums, + range + ); + + end ); + + fi; + + if ForAll( [ "DistinguishedObjectOfHomomorphismStructure" ], f -> CanCompute( underlying_category, f ) ) then + ## + AddDistinguishedObjectOfHomomorphismStructure( AC_objfin, + function( cat ) + + return DistinguishedObjectOfHomomorphismStructureExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category ); + + end ); + + fi; + + if (ForAll( [ "UniversalMorphismIntoZeroObject", + "UniversalMorphismIntoDirectSum" ], + f -> CanCompute( range_category, f ) ) or IsIdenticalObj( range_category, AC_objfin )) and + ForAll( [ "DistinguishedObjectOfHomomorphismStructure", + "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructure" ], + f -> CanCompute( underlying_category, f ) ) and + not (IsBound( range_category!.supports_empty_limits ) and range_category!.supports_empty_limits = true) then + + ## + AddInterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructure( AC_objfin, + function( cat, alpha ) + local size_i, size_j; + + size_i := NumberRows( alpha ); + + size_j := NumberColumns( alpha ); + + if size_i = 0 or size_j = 0 then + + return UniversalMorphismIntoZeroObject( range_category, DistinguishedObjectOfHomomorphismStructure( UnderlyingCategory( cat ) ) ); + + fi; + + return UniversalMorphismIntoDirectSum( range_category, + List( [ 1 .. size_i ], i -> + UniversalMorphismIntoDirectSum( range_category, + List( [ 1 .. size_j ], j -> + InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, alpha[i, j] ) + ) + ) + ) + ); + + end ); + + fi; + + if (ForAll( [ "UniversalMorphismIntoDirectSum" ], + f -> CanCompute( range_category, f ) ) or IsIdenticalObj( range_category, AC_objfin )) and + ForAll( [ "DistinguishedObjectOfHomomorphismStructure", + "InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructure" ], + f -> CanCompute( underlying_category, f ) ) and + IsBound( range_category!.supports_empty_limits ) and range_category!.supports_empty_limits = true then + + ## + AddInterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureWithGivenObjects( AC_objfin, + function( cat, distinguished_object, alpha, range ) + local size_j, size_s, B, C, H_B_C, direct_sums; + + size_j := NumberRows( alpha ); + + size_s := NumberColumns( alpha ); + + B := Source( alpha ); + C := Target( alpha ); + + H_B_C := + List( [ 1 .. size_j ], j -> + List( [ 1 .. size_s ], s -> + HomomorphismStructureOnObjectsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, B[j], C[s] ) + ) + ); + + direct_sums := List( [ 1 .. size_j ], j -> DirectSum( range_category, List( [ 1 .. size_s ], s -> H_B_C[j][s] ) ) ); + + return UniversalMorphismIntoDirectSumWithGivenDirectSum( + range_category, + direct_sums, + distinguished_object, + List( [ 1 .. size_j ], j -> + UniversalMorphismIntoDirectSumWithGivenDirectSum( range_category, + List( [ 1 .. size_s ], s -> H_B_C[j][s] ), + distinguished_object, + List( [ 1 .. size_s ], s -> + InterpretMorphismAsMorphismFromDistinguishedObjectToHomomorphismStructureWithGivenObjectsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, distinguished_object, alpha[j, s], H_B_C[j][s] ) + ), + direct_sums[j] + ) + ), + range + ); + + end ); + + fi; + + if ForAll( [ "HomomorphismStructureOnObjects", + "InterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphism" ], + f -> CanCompute( underlying_category, f ) ) and + (ForAll( [ "PreCompose", + "ProjectionInFactorOfDirectSum" ], + f -> CanCompute( range_category, f ) ) or IsIdenticalObj( range_category, AC_objfin )) then + + ## + AddInterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphism( AC_objfin, + function( cat, B, C, morphism ) + local size_j, size_s, H_B_C, direct_sums, blocks, listlist; + + size_j := Length( UnderlyingObjectList( AC_objfin, B ) ); + + size_s := Length( UnderlyingObjectList( AC_objfin, C ) ); + + H_B_C := + List( [ 1 .. size_j ], j -> + List( [ 1 .. size_s ], s -> + HomomorphismStructureOnObjectsExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, B[j], C[s] ) + ) + ); + + direct_sums := List( [ 1 .. size_j ], j -> DirectSum( range_category, List( [ 1 .. size_s ], s -> H_B_C[j][s] ) ) ); + + blocks := List( [ 1 .. size_j ], j -> + ComponentOfMorphismIntoDirectSum( range_category, + morphism, + direct_sums, + j + ) + ); + + listlist := List( [ 1 .. size_j ], j -> + List( [ 1 .. size_s ], s -> + ComponentOfMorphismIntoDirectSum( range_category, + blocks[j], + H_B_C[j], + s + ) + ) + ); + + return AdditiveClosureMorphism( cat, + B, + List( [ 1 .. size_j ], j -> + List( [ 1 .. size_s ], s -> + InterpretMorphismFromDistinguishedObjectToHomomorphismStructureAsMorphismExtendedByFullEmbedding( UnderlyingCategory( cat ), range_category, + B[j], + C[s], + listlist[j][s] + ) + ) + ), + C + ); + + end ); + fi; + + fi; + + if HasIsMonoidalCategory( underlying_category ) and IsMonoidalCategory( underlying_category ) then + + ## + AddTensorUnit( AC_objfin, + function( AC_objfin ) + local multiplicities; + + multiplicities := ObjectToMultiplicityList( underlying_category, TensorUnit( underlying_category ) ); + + return AdditiveClosureObject( AC_objfin, [ 1, multiplicities ] ); + + end ); + + ## + AddTensorProductOnObjects( AC_objfin, + function( AC_objfin, obj_1, obj_2 ) + local len_1, len_2, summands, multiplicities; + + len_1 := NrOfSummands( obj_1 ); + len_2 := NrOfSummands( obj_2 ); + + summands := + List( [ 0 .. len_1 * len_2 - 1 ], i -> + TensorProductOnObjects( underlying_category, + obj_1[ 1 + QuoInt( i, len_2 ) ], + obj_2[ 1 + RemInt( i, len_2 ) ] ) ); + + multiplicities := ObjectsToMultiplicityList( underlying_category, summands ); + + return AdditiveClosureObject( AC_objfin, [ Length( summands ), multiplicities ] ); + + end ); + + ## + AddTensorProductOnMorphismsWithGivenTensorProducts( AC_objfin, + function( AC_objfin, source, morph_1, morph_2, target ) + local source_1, source_2, target_1, target_2, + len_s1, len_s2, len_t1, len_t2; + + source_1 := Source( morph_1 ); + source_2 := Source( morph_2 ); + target_1 := Target( morph_1 ); + target_2 := Target( morph_2 ); + len_s1 := NrOfSummands( source_1 ); + len_s2 := NrOfSummands( source_2 ); + len_t1 := NrOfSummands( target_1 ); + len_t2 := NrOfSummands( target_2 ); + + return AdditiveClosureMorphism( AC_objfin, + source, + List( [ 0 .. len_s1 * len_s2 - 1 ], i -> + List( [ 0 .. len_t1 * len_t2 - 1 ], j -> + TensorProductOnMorphismsWithGivenTensorProducts( underlying_category, + source[ 1 + len_s2 * QuoInt( i, len_s2 ) + RemInt( i, len_s2 ) ], + morph_1[ 1 + QuoInt( i, len_s2 ), 1 + QuoInt( j, len_t2 ) ], + morph_2[ 1 + RemInt( i, len_s2 ), 1 + RemInt( j, len_t2 ) ], + target[ 1 + len_t2 * QuoInt( j, len_t2 ) + RemInt( j, len_t2 ) ] ) ) ), + target ); + + end ); + + if not ( HasIsStrictMonoidalCategory( underlying_category ) and IsStrictMonoidalCategory( underlying_category ) ) then + + ## + AddLeftUnitorWithGivenTensorProduct( AC_objfin, + function( AC_objfin, obj, unit_tensor_obj ) + local length, source_diagram, target_diagram; + + length := NrOfSummands( obj ); + source_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ unit_tensor_obj[ o ] ] ) ); + target_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ obj[ o ] ] ) ); + + return DirectSumFunctorialWithGivenDirectSums( AC_objfin, + unit_tensor_obj, + source_diagram, + List( [ 1 .. length ], o -> + AdditiveClosureMorphism( AC_objfin, + source_diagram[ o ], + [ [ LeftUnitorWithGivenTensorProduct( underlying_category, + obj[ o ], + unit_tensor_obj[ o ] ) ] ], + target_diagram[ o ] ) ), + target_diagram, + obj ); + + end ); + + ## + AddLeftUnitorInverseWithGivenTensorProduct( AC_objfin, + function( AC_objfin, obj, unit_tensor_obj ) + local length, source_diagram, target_diagram; + + length := NrOfSummands( obj ); + source_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ obj[ o ] ] ) ); + target_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ unit_tensor_obj[ o ] ] ) ); + + return DirectSumFunctorialWithGivenDirectSums( AC_objfin, + obj, + source_diagram, + List( [ 1 .. length ], o -> + AdditiveClosureMorphism( AC_objfin, + source_diagram[ o ], + [ [ LeftUnitorInverseWithGivenTensorProduct( underlying_category, + obj[ o ], + unit_tensor_obj[ o ] ) ] ], + target_diagram[ o ] ) ), + target_diagram, + unit_tensor_obj ); + + end ); + + ## + AddRightUnitorWithGivenTensorProduct( AC_objfin, + function( AC_objfin, obj, obj_tensor_unit ) + local length, source_diagram, target_diagram; + + length := Length( UnderlyingObjectList( AC_objfin, obj ) ); + source_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ obj_tensor_unit[ o ] ] ) ); + target_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ obj[ o ] ] ) ); + + return DirectSumFunctorialWithGivenDirectSums( AC_objfin, + obj_tensor_unit, + source_diagram, + List( [ 1 .. length ], o -> + AdditiveClosureMorphism( AC_objfin, + source_diagram[ o ], + [ [ RightUnitorWithGivenTensorProduct( underlying_category, + obj[ o ], + obj_tensor_unit[ o ] ) ] ], + target_diagram[ o ] ) ), + target_diagram, + obj ); + + end ); + + ## + AddRightUnitorInverseWithGivenTensorProduct( AC_objfin, + function( AC_objfin, obj, obj_tensor_unit ) + local length, source_diagram, target_diagram; + + length := Length( UnderlyingObjectList( AC_objfin, obj ) ); + source_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ obj[ o ] ] ) ); + target_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ obj_tensor_unit[ o ] ] ) ); + + return DirectSumFunctorialWithGivenDirectSums( AC_objfin, + obj, + source_diagram, + List( [ 1 .. length ], o -> + AdditiveClosureMorphism( AC_objfin, + source_diagram[ o ], + [ [ RightUnitorInverseWithGivenTensorProduct( underlying_category, + obj[ o ], + obj_tensor_unit[ o ] ) ] ], + target_diagram[ o ] ) ), + target_diagram, + obj_tensor_unit ); + + end ); + + ## + AddAssociatorLeftToRightWithGivenTensorProducts( AC_objfin, + function( AC_objfin, source, obj_1, obj_2, obj_3, target ) + local len_1, len_2, len_3, length, source_diagram, target_diagram; + + len_1 := Length( UnderlyingObjectList( AC_objfin, obj_1 ) ); + len_2 := Length( UnderlyingObjectList( AC_objfin, obj_2 ) ); + len_3 := Length( UnderlyingObjectList( AC_objfin, obj_3 ) ); + length := len_1 * len_2 * len_3; + source_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ source[ o ] ] ) ); + target_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ target[ o ] ] ) ); + + return DirectSumFunctorialWithGivenDirectSums( AC_objfin, + source, + source_diagram, + List( [ 0 .. length - 1 ], o -> + AdditiveClosureMorphism( AC_objfin, + source_diagram[1 + o], + [ [ AssociatorLeftToRightWithGivenTensorProducts( underlying_category, + source[1 + o], + obj_1[1 + QuoInt( o, len_2 * len_3 )], + obj_2[1 + RemInt( QuoInt( o, len_3 ), len_2 )], + obj_3[1 + RemInt( o, len_3 )], + target[1 + o] ) ] ], + target_diagram[1 + o] ) ), + target_diagram, + target ); + + end ); + + ## + AddAssociatorRightToLeftWithGivenTensorProducts( AC_objfin, + function( AC_objfin, source, obj_1, obj_2, obj_3, target ) + local len_1, len_2, len_3, length, source_diagram, target_diagram; + + len_1 := Length( UnderlyingObjectList( AC_objfin, obj_1 ) ); + len_2 := Length( UnderlyingObjectList( AC_objfin, obj_2 ) ); + len_3 := Length( UnderlyingObjectList( AC_objfin, obj_3 ) ); + length := len_1 * len_2 * len_3; + source_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ source[ o ] ] ) ); + target_diagram := List( [ 1 .. length ], o -> AdditiveClosureObject( AC_objfin, [ target[ o ] ] ) ); + + return DirectSumFunctorialWithGivenDirectSums( AC_objfin, + source, + source_diagram, + List( [ 0 .. length - 1 ], o -> + AdditiveClosureMorphism( AC_objfin, + source_diagram[1 + o], + [ [ AssociatorRightToLeftWithGivenTensorProducts( underlying_category, + source[1 + o], + obj_1[1 + QuoInt( o, len_2 * len_3 )], + obj_2[1 + RemInt( QuoInt( o, len_3 ), len_2 )], + obj_3[1 + RemInt( o, len_3 )], + target[1 + o] ) ] ], + target_diagram[1 + o] ) ), + target_diagram, + target ); + + end ); + + fi; + fi; + +end ); + +#################################### +## +## Attributes +## +#################################### + +InstallMethod( ListOfObjectsOfUnderlyingCategory, + [ IsAdditiveClosureOfObjectFiniteCategory ], + + function( cat ) + + return SetOfObjectsOfCategory( UnderlyingCategory( cat ) ); + +end ); + +InstallMethodForCompilerForCAP( NrOfSummands, + [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( obj ) + + return NrSummandsAndMultiplicities( obj )[1]; + +end ); + +InstallMethodForCompilerForCAP( Multiplicities, + [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( obj ) + + return NrSummandsAndMultiplicities( obj )[2]; + +end ); + +InstallMethodForCompilerForCAP( UnderlyingObjectList, + [ IsAdditiveClosureOfObjectFiniteCategory, IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( cat, obj ) + local underlying_objects, l, multiplicities; + + underlying_objects := ListOfObjectsOfUnderlyingCategory( cat ); + + l := NumberOfObjectsOfUnderlyingCategory( cat ); + + multiplicities := Multiplicities( obj ); + + return Concatenation( List( [ 1 .. l ], i -> ListWithIdenticalEntries( multiplicities[i], underlying_objects[i] ) ) ); + +end ); + +## +InstallMethodForCompilerForCAP( NumberRows, + [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], + + function( morphism ) + + return NrOfSummands( Source( morphism ) ); + +end ); + +## +InstallMethodForCompilerForCAP( NumberColumns, + [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], + + function( morphism ) + + return NrOfSummands( Target( morphism ) ); + +end ); + +#################################### +## +## Operators +## +#################################### + +## +InstallMethod( \[\], + [ IsObjectInAdditiveClosureOfObjectFiniteCategory, IsInt ], + + function( object, i ) + local obj_list; + + obj_list := UnderlyingObjectList( CapCategory( object ), object ); + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, 1 <= i and i <= Length( obj_list ), "out of bounds.\n" ); + + return obj_list[ i ]; + +end ); + +## +InstallMethodForCompilerForCAP( \[\,\], + [ IsMorphismInAdditiveClosureOfObjectFiniteCategory, IsInt, IsInt ], + + function( morphism, i, j ) + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, 1 <= i and i <= NumberRows( morphism ) and + 1 <= j and j <= NumberColumns( morphism ), "out of bounds.\n" ); + + return MorphismMatrix( morphism )[i][j]; + +end ); + +## +InstallMethodForCompilerForCAP( ObjectToMultiplicityList, + [ IsCapCategory and IsObjectFiniteCategory, IsCapCategoryObject ], + function( category, obj ) + local set_of_objects, pos, positions; + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, category = CapCategory( obj ) ); + + set_of_objects := SetOfObjectsOfCategory( category ); + + pos := Position( set_of_objects, obj ); + + positions := ListWithIdenticalEntries( Length( set_of_objects ), 0 ); + + positions[pos] := 1; + + return positions; + +end ); + +## +InstallMethodForCompilerForCAP( ObjectsToMultiplicityList, + [ IsCapCategory and IsObjectFiniteCategory, IsList ], + function( category, objects ) + local set_of_objects; + + #% CAP_JIT_DROP_NEXT_STATEMENT + Assert( 0, ForAll( objects, obj -> category = CapCategory( obj ) ) ); + + set_of_objects := SetOfObjectsOfCategory( category ); + + return List( [ 1 .. Length( set_of_objects ) ], i -> + Length( PositionsProperty( objects, obj -> + IsEqualForObjects( category, obj, set_of_objects[i] ) ) ) ); + +end ); + +## +InstallOtherMethod( \/, + [ IsList, IsAdditiveClosureOfObjectFiniteCategory ], + + function( listlist, AC_objfin ) + local underlying_category, multiplicities, nr_summands_and_multiplicities, + sources_list, targets_list, source, target, mor; + + underlying_category := UnderlyingCategory( AC_objfin ); + + if ForAll( listlist, obj -> IsCapCategoryObject( obj ) and + IsIdenticalObj( CapCategory( obj ), underlying_category ) ) + then + + # It's a list of objects in the underlying category. + + multiplicities := ObjectsToMultiplicityList( underlying_category, listlist ); + + nr_summands_and_multiplicities := [ Length( listlist ), multiplicities ]; + + return AdditiveClosureObject( AC_objfin, nr_summands_and_multiplicities ); + + else + + # Assume it's a matrix of morphisms in the underlying category. + + sources_list := List( listlist, row -> Source( row[1] ) ); + targets_list := List( listlist[1], col -> Target( col ) ); + + source := AdditiveClosureObject( AC_objfin, + [ Length( sources_list ), ObjectsToMultiplicityList( underlying_category, sources_list ) ] ); + + target := AdditiveClosureObject( AC_objfin, + [ Length( targets_list ), ObjectsToMultiplicityList( underlying_category, targets_list ) ] ); + + return AdditiveClosureMorphism( AC_objfin, source, listlist, target ); + + fi; + +end ); + +## +InstallOtherMethod( \/, + [ IsCapCategoryObject, IsAdditiveClosureOfObjectFiniteCategory ], + + function( obj, AC_objfin ) + local pos, multiplicity_list; + + Assert( 0, IsIdenticalObj( UnderlyingCategory( AC_objfin ), CapCategory( obj ) ) ); + + multiplicity_list := ObjectToMultiplicityList( UnderlyingCategory( AC_objfin ), obj ); + + return ObjectConstructor( AC_objfin, [ 1, multiplicity_list ] ); + +end ); + +## +InstallOtherMethod( \/, + [ IsCapCategoryMorphism, IsAdditiveClosureOfObjectFiniteCategory ], + + function( alpha, AC_objfin ) + local underlying_category, source, target; + + underlying_category := UnderlyingCategory( AC_objfin ); + + Assert( 0, IsIdenticalObj( underlying_category, CapCategory( alpha ) ) ); + + source := ObjectConstructor( AC_objfin, [ 1, ObjectToMultiplicityList( underlying_category, Source( alpha ) ) ] ); + target := ObjectConstructor( AC_objfin, [ 1, ObjectToMultiplicityList( underlying_category, Target( alpha ) ) ] ); + + return MorphismConstructor( AC_objfin, source, [ [ alpha ] ], target ); + +end ); + +#################################### +## +## View +## +#################################### + +## +InstallMethod( ViewString, + [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( object ) + return Concatenation( + "" ); +end ); + +## +InstallMethod( ViewString, + [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], + + function( morphism ) + return Concatenation( + "" ); +end ); + +## +InstallMethod( DisplayString, + [ IsObjectInAdditiveClosureOfObjectFiniteCategory ], + + function( object ) + local AC_objfin, A, objects_of_underlying_category, nr_objects_of_underlying_category, + nr_objects, multiplicities, string, obj; + + AC_objfin := CapCategory( object ); + A := UnderlyingCategory( AC_objfin ); + + objects_of_underlying_category := SetOfObjectsOfCategory( A ); + nr_objects_of_underlying_category := NumberOfObjectsOfUnderlyingCategory( AC_objfin ); + nr_objects := NrOfSummands( object ); + multiplicities := Multiplicities( object ); + + if nr_objects = 1 then + + string := Concatenation( "A formal direct sum consisting of ", String( nr_objects ), " object:\n\n" ); + + else + + string := Concatenation( "A formal direct sum consisting of ", String( nr_objects ), " objects:\n\n" ); + + fi; + + for obj in [ 1 .. nr_objects_of_underlying_category ] do + + string := Concatenation( string, String( multiplicities[ obj ] ), " times: " ); + + string := Concatenation( string, ViewString( objects_of_underlying_category[ obj ] ), "\n" ); + + od; + + return string; + +end ); + +## +InstallMethod( DisplayString, + [ IsMorphismInAdditiveClosureOfObjectFiniteCategory ], + + function( morphism ) + local nr_rows, nr_cols, string, i, j; + + nr_rows := NumberRows( morphism ); + nr_cols := NumberColumns( morphism ); + + string := Concatenation( "A ", String( nr_rows ), " x ", String( nr_cols ), + " matrix with entries in ", + Name( UnderlyingCategory( CapCategory( morphism ) ) ), "\n" ); + + for i in [ 1 .. nr_rows ] do + + for j in [ 1 .. nr_cols ] do + + string := Concatenation( string, Concatenation( "\n[", String(i), ",", String(j), "]: " ) ); + + string := Concatenation( string, ViewString( morphism[i,j] ) ); + + od; + + od; + + string := Concatenation( string, "\n" ); + + return string; + +end ); + diff --git a/AdditiveClosuresForCAP/init.g b/AdditiveClosuresForCAP/init.g index 5f388cbba8..2a1009b9d3 100644 --- a/AdditiveClosuresForCAP/init.g +++ b/AdditiveClosuresForCAP/init.g @@ -23,7 +23,6 @@ ReadPackage( "AdditiveClosuresForCAP", "gap/CategoryOfGradedRowsAndColumns/Tools # =# ReadPackage( "AdditiveClosuresForCAP", "gap/AdditiveClosure.gd" ); +ReadPackage( "AdditiveClosuresForCAP", "gap/AdditiveClosureOfObjectFiniteCategory.gd" ); ReadPackage( "AdditiveClosuresForCAP", "gap/RingsAsAbCats.gd" ); - -ReadPackage( "AdditiveClosuresForCAP", "gap/LinearCategoryWithMorphismsByCoefficients.gd" ); diff --git a/AdditiveClosuresForCAP/makedoc.g b/AdditiveClosuresForCAP/makedoc.g index 4df26399db..2a74606a66 100644 --- a/AdditiveClosuresForCAP/makedoc.g +++ b/AdditiveClosuresForCAP/makedoc.g @@ -20,9 +20,12 @@ AutoDoc( rec( gapdoc := rec( LaTeXOptions := rec( LateExtraPreamble := """ + \usepackage{mathtools} + \usepackage[table]{xcolor} \usepackage{tikz} \usetikzlibrary{arrows} \usetikzlibrary{calc} + \DeclareUnicodeCharacter{2295}{\ensuremath{\oplus}} """, ), ), diff --git a/AdditiveClosuresForCAP/read.g b/AdditiveClosuresForCAP/read.g index 9a4ea2eb65..1809abe955 100644 --- a/AdditiveClosuresForCAP/read.g +++ b/AdditiveClosuresForCAP/read.g @@ -24,7 +24,6 @@ ReadPackage( "AdditiveClosuresForCAP", "gap/CategoryOfGradedRowsAndColumns/Tools ReadPackage( "AdditiveClosuresForCAP", "gap/AdditiveClosure.gi" ); ReadPackage( "AdditiveClosuresForCAP", "gap/AdditiveClosureDerivedMethods.gi" ); +ReadPackage( "AdditiveClosuresForCAP", "gap/AdditiveClosureOfObjectFiniteCategory.gi" ); ReadPackage( "AdditiveClosuresForCAP", "gap/RingsAsAbCats.gi" ); - -ReadPackage( "AdditiveClosuresForCAP", "gap/LinearCategoryWithMorphismsByCoefficients.gi" ); diff --git a/AdditiveClosuresForCAP/tst/AdditiveClosureOfObjectFiniteCategoryTest.tst b/AdditiveClosuresForCAP/tst/AdditiveClosureOfObjectFiniteCategoryTest.tst new file mode 100644 index 0000000000..b6156942a4 --- /dev/null +++ b/AdditiveClosuresForCAP/tst/AdditiveClosureOfObjectFiniteCategoryTest.tst @@ -0,0 +1,135 @@ +gap> START_TEST("AddClosureObjFinTest.tst"); + +gap> LoadPackage( "LinearClosuresForCAP", false ); +true +gap> D := FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] );; +gap> Q := HomalgFieldOfRationals( );; +gap> L := LinearClosure( Q, D );; +gap> A := AdditiveClosureOfObjectFiniteCategory( L );; +gap> a := ObjectConstructor( A, [1,[1,0]] );; +gap> b := ObjectConstructor( A, [1,[0,1]] );; +gap> ObjectDatum( a ); +[ 1, [ 1, 0 ] ] +gap> Display( b ); +A formal direct sum consisting of 1 object: + +0 times: LinearClosureObject() +1 times: LinearClosureObject() +gap> Display( ZeroObject( A ) ); +A formal direct sum consisting of 0 objects: + +0 times: LinearClosureObject() +0 times: LinearClosureObject() +gap> aab := ObjectConstructor( A, [3,[2,1]] );; +gap> aab = DirectSum( [ a, b, a ] ); +true +gap> aab[1] = D[1] / L; +true +gap> aab[2] = D[1] / L; +true +gap> aab[3] = D[2] / L; +true +gap> id_aab := IdentityMorphism( aab );; +gap> z := ZeroMorphism( aab, b );; +gap> MorphismDatum( z ); +[ [ 0 ], [ 0 ], [ 0 ] ] +gap> Display( z ); +A 3 x 1 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: 0 +[2,1]: 0 +[3,1]: 0 +gap> IsZeroForMorphisms( z ); +true +gap> z_aab := ZeroMorphism( aab, aab );; +gap> IsEqualForMorphisms( id_aab, z_aab ); +false +gap> IsEqualForMorphisms( id_aab, id_aab ); +true +gap> IsCongruentForMorphisms( id_aab, z_aab ); +false +gap> IsCongruentForMorphisms( id_aab, id_aab ); +true +gap> PreCompose( id_aab, z_aab ); + +gap> Display( AdditionForMorphisms( id_aab, id_aab ) ); +A 3 x 3 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: (1*) + (1*) +[1,2]: 0 +[1,3]: 0 +[2,1]: 0 +[2,2]: (1*) + (1*) +[2,3]: 0 +[3,1]: 0 +[3,2]: 0 +[3,3]: (1*) + (1*) +gap> Display( SumOfMorphisms( Source( id_aab ), [ id_aab, z_aab, id_aab ], Target( id_aab ) ) ); +A 3 x 3 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: (1*) + (1*) +[1,2]: 0 +[1,3]: 0 +[2,1]: 0 +[2,2]: (1*) + (1*) +[2,3]: 0 +[3,1]: 0 +[3,2]: 0 +[3,3]: (1*) + (1*) +gap> Display( AdditiveInverseForMorphisms( id_aab ) ); +A 3 x 3 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: (-1*) +[1,2]: 0 +[1,3]: 0 +[2,1]: 0 +[2,2]: (-1*) +[2,3]: 0 +[3,1]: 0 +[3,2]: 0 +[3,3]: (-1*) +gap> diag := [ a, a, b ];; +gap> pr1 := ProjectionInFactorOfDirectSum( diag, 1 );; +gap> pr2 := ProjectionInFactorOfDirectSum( diag, 2 );; +gap> pr3 := ProjectionInFactorOfDirectSum( diag, 3 );; +gap> u := UniversalMorphismIntoDirectSumWithGivenDirectSum( diag, [ pr1, pr2, pr3 ], aab );; +gap> IsWellDefinedForMorphisms( u ); +true +gap> inj1 := InjectionOfCofactorOfDirectSum( diag, 1 );; +gap> inj2 := InjectionOfCofactorOfDirectSum( diag, 2 );; +gap> inj3 := InjectionOfCofactorOfDirectSum( diag, 3 );; +gap> u := UniversalMorphismFromDirectSumWithGivenDirectSum( diag, [ inj1, inj2, inj3 ], aab );; +gap> IsWellDefinedForMorphisms( u ); +true +gap> comp := ComponentOfMorphismIntoDirectSum( inj1, [ a, a, b ], 3 );; +gap> IsWellDefined( comp ); +true +gap> Display( comp ); +A 1 x 1 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: 0 +gap> comp := ComponentOfMorphismFromDirectSum( pr3, [ a, a, b ], 1 );; +gap> IsWellDefined( comp ); +true +gap> Display( comp ); +A 1 x 1 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: 0 +gap> Display( MultiplyWithElementOfCommutativeSemiringForMorphisms( 10 / Q, id_aab ) );; +A 3 x 3 matrix with entries in LinearClosure( FiniteSkeletalDiscreteCategory( [ 1 .. 2 ] ) ) + +[1,1]: (10*) +[1,2]: 0 +[1,3]: 0 +[2,1]: 0 +[2,2]: (10*) +[2,3]: 0 +[3,1]: 0 +[3,2]: 0 +[3,3]: (10*) +gap> D[1] / L / A;; +gap> IdentityMorphism( D[1] / L ) / A;; +gap> [ D[1] / L, D[2] / L, D[1] / L ] / A;; + +# +gap> STOP_TEST("AddClosureObjFinTest.tst", 1);