<jupyter_start><jupyter_text>Category theory in computer algebra: first steps in CAP  Introduction**Categorical abstraction** is a powerful **computational tool**.Category theory gains its computational power from three key observations:1. equivalences of categories can transform otherwise inaccessible mathematical objects into computationally easily graspable entities,2. category theory defines a *language* that respects the isomorphism-invariant structures and properties of mathematical objects, an idea that justifies the treatment of equivalent categories as "being equal from a categorical point of view",3. lots of mathematicians nowadays use category theory as a widely accepted language to express their ideas, and thus, constructive category theory has a great range of applications.In this worksheet, we will explore - the category of finite dimensional vector spaces $\mathrm{vec}_k$ over a computable field $k$,- the category of finitely presented (left) modules $\mathrm{mod}_R$ over a computable ring $R$.We will do this by giving **computational models** for these categories,i.e., we will construct categories $\mathrm{mat}_k$ and $\mathrm{fpres}_R$for which we have$$\mathrm{vec}_k \simeq \mathrm{mat}_k$$and$$\mathrm{mod}_R \simeq \mathrm{fpres}_R\text{,}$$but with the advantage that these categories will be much easier to work with from a computational point of view.  Computing in abelian categories The categories $\mathrm{vec}_k$ and $\mathrm{mod}_R$ are bothexamples of **abelian categories**.*Remark for those who already know what an abelian category is:the fact that $\mathrm{mod}_R$ is an abelian category relieson the ring $R$ being coherent, a property that will be impliedby our notion of a computable ring.*The computational aspects of the *language of abelian categories*will be our guide in this section.  Finite dimensional vector spaces Our computational model $\mathrm{mat}_k$ for finite dimensional vector spaces,which we call the **matrix category** of $k$, is part of the following $\textsf{GAP}$-package:<jupyter_code>LoadPackage( "LinearAlgebraForCAP" );<jupyter_output><empty_output><jupyter_text>First, we need to create a field. For example, we can create the rationals $\mathbb{Q}$:<jupyter_code>QQ := HomalgFieldOfRationals();<jupyter_output><empty_output><jupyter_text>We could also create a finite field $\mathbb{F}_3$ with $3$ elements:<jupyter_code>F3 := HomalgRingOfIntegers( 3 );<jupyter_output><empty_output><jupyter_text>The following constructor takes such a field as an input an returnsour computational model of the category of finite dimensional vector spaces as an output:<jupyter_code>matQQ := MatrixCategory( QQ );<jupyter_output><empty_output><jupyter_text>The $\mathsf{GAP}$-object $\mathrm{mat}_{\mathbb{Q}}$ comes with some preset knowledge:<jupyter_code>IsAbelianCategory( matQQ );<jupyter_output><empty_output><jupyter_text>We claimed in the introduction that we have an equivalence$$\mathrm{vec}_{\mathbb{Q}} \simeq \mathrm{mat}_{\mathbb{Q}}\text{,}$$so, let us learn more about $\mathrm{mat}_{\mathbb{Q}}$.We start with the **objects**. To construct an object in $\mathrm{mat}_{\mathbb{Q}}$, we use the following constructor:<jupyter_code>V1 := VectorSpaceObject( 1, QQ );<jupyter_output><empty_output><jupyter_text>Since we expect this object to represent a vector space, we ask for its dimension:<jupyter_code>Dimension( V1 );<jupyter_output><empty_output><jupyter_text>Thus, $V_1$ shall represent a $\mathbb{Q}$-vector space of dimension $1$.Likewise, we can use the command `VectorSpaceObject` to create vector spaceobjects of any finite dimension. What happens if we create another vectorspace object of the same dimension?<jupyter_code>W1 := VectorSpaceObject( 1, QQ );;

IsEqualForObjects( V1, W1 );<jupyter_output><empty_output><jupyter_text>Two objects with the same dimension are considered to be equal in$\mathrm{mat}_{\mathbb{Q}}$. Since the only datum needed for thecreation of an object was a natural number (including zero),we can summarize:$$\mathrm{Obj}\big( \mathrm{mat}_{\mathbb{Q}} \big) = \mathbb{N}_0$$Next, we turn to **morphisms**.Given two objects$$m,n \in \mathrm{Obj}\big( \mathrm{mat}_{\mathbb{Q}} \big) = \mathbb{N}_0$$the set of homomorphisms is simply given by$$\mathrm{Hom}_{\mathrm{mat}_{\mathbb{Q}}}( m, n ) := \mathbb{Q}^{m \times n},$$i.e., $m$ by $n$ matrices with entries in $\mathbb{Q}$.The corresponding constructor is called `VectorSpaceMorphism`.<jupyter_code>V2 := VectorSpaceObject( 2, QQ );;
mat := HomalgMatrix( "[1, 1, 1, 1]", 2, 2, QQ );;
alpha := VectorSpaceMorphism( V2, mat, V2 );;
Display( alpha );<jupyter_output>[ [  1,  1 ],
  [  1,  1 ] ]

A morphism in Category of matrices over Q<jupyter_text>Composition in $\mathrm{mat}_{\mathbb{Q}}$ is given by matrix multiplication.There are two commands for composition:`PreCompose` and `PostCompose`You can type `?PreCompose` and `?PostCompose` to learnabout the different conventions in the odering of composition.In this worksheet, we will always write$$\alpha \cdot \beta$$to refer to the **precomposition** of morphisms $\alpha$ and $\beta$, and$$\alpha \circ \beta$$to refer to the **postcomposition** of morphisms $\alpha$ and $\beta$.<jupyter_code>?PreCompose<jupyter_output><empty_output><jupyter_text>**Exercise 1**> Create a *non-zero* morphism $\beta: V_2 \rightarrow V_2$ in $\mathrm{mat}_{\mathbb{Q}}$such that both$$\alpha \cdot \beta = 0$$and$$\alpha \circ \beta = 0\text{,}$$where $\alpha = \begin{pmatrix} 1 & 1 \\ 1 & 1\end{pmatrix}: V_2 \rightarrow V_2$.<jupyter_code># Solution of Exercise 1:

# beta :=<jupyter_output><empty_output><jupyter_text>**Identities** in $\mathrm{mat}_{\mathbb{Q}}$ are given byidentity matrices.<jupyter_code>Display( IdentityMorphism( V2 ) );<jupyter_output>[ [  1,  0 ],
  [  0,  1 ] ]

An identity morphism in Category of matrices over Q<jupyter_text>Classically, the category of finite dimensional vector spacesis given by the class of objects$$\mathrm{Obj}\big( \mathrm{vec}_{\mathbb{Q}} \big) = \{ V \mid V ~\text{is a finite dimensional $\mathbb{Q}$-vector space}\}\text{,}$$and homomorphism sets$$\mathrm{Hom}_{ \mathrm{vec}_{\mathbb{Q}} }( V, W ) =\{ \alpha: V \rightarrow W \mid \text{$\alpha$ is $\mathbb{Q}$-linear } \}$$for vector spaces $V,W$.For us, the crucial point is that the mappings$$m \mapsto \mathbb{Q}^m$$and$$(a_{ij})_{\substack{i = 1, \dots m \\ j = 1, \dots n}} \mapsto\big( \mathbb{Q}^m \stackrel{(a_{ij})_{ij}}{\longrightarrow} \mathbb{Q}^n \big)$$define a functor$$\mathrm{mat}_{\mathbb{Q}} \longrightarrow \mathrm{vec}_{\mathbb{Q}}$$that is an equivalence of categories.Thus, simply regarded as categories,$\mathrm{mat}_{\mathbb{Q}}$ and $\mathrm{vec}_{\mathbb{Q}}$are indistinguishable.Of course, this statement can only be computationally useful if there are interesting computations to do that only concern thecategorical structure of $\mathrm{vec}_{\mathbb{Q}}$.Luckily, there is a lot that we can compute, and this isdue to the various constructions provided by theconcept of an *abelian category*.  Ab-categories An Ab-category (which is much weaker than an abelian category)is a category in which all homomorphism sets are abelian groups,and composition distributes over addition.<jupyter_code>Display( alpha + alpha );
Display( -alpha );
Display( ZeroMorphism( V1, V2 ) );
gamma := VectorSpaceMorphism( V1, HomalgMatrix( "[3,5]", 1, 2, QQ ), V2 );;

delta := VectorSpaceMorphism( V1, HomalgMatrix( "[-9, 0]", 1, 2, QQ ), V2 );;

IsCongruentForMorphisms(
PreCompose( gamma + delta, alpha ),
PreCompose( gamma, alpha ) + PreCompose( delta, alpha )
);<jupyter_output><empty_output><jupyter_text>The command for comparing morphisms on a mathematical level is `IsCongruentForMorphisms`.*Remark: there is also a command called `IsEqualForMorphisms` that comparesmorphisms on a technical level. We will see the difference betweenthese two notions in our discussionof the category $\mathrm{fpres}_R$.*Given two morphisms $\alpha, \beta: A \rightarrow B$, we will write$$\alpha \sim_{A,B} \beta$$or simply$$\alpha \sim \beta$$when we mean that they are congruent, i.e., equal on a mathematical level.  Direct sums The following description is taken from the CAP manual:> For a given list $D = (S_1, \dots, S_n)$ in an Ab-category, a direct sum consists of five parts:- an object $S$,- a list of morphisms $\pi = (\pi_i: S \rightarrow S_i)_{i = 1 \dots n}$,- a list of morphisms $\iota = (\iota_i: S_i \rightarrow S)_{i = 1 \dots n}$- a  dependent  function  $u_{\mathrm{in}}$  mapping  every  list  $\tau  =  (  \tau_i:  T  \rightarrow  S_i  )_{i  =  1 \dots n}$ to a morphism $u_{\mathrm{in}}(\tau): T \rightarrow S$ such that $\pi_i \circ u_{\mathrm{in}}(\tau) \sim_{T,S_i} \tau_i$ for all $i = 1, \dots, n$.- a  dependent  function  $u_{\mathrm{out}}$  mapping  every  list  $\tau  =  (  \tau_i:  S_i  \rightarrow  T  )_{i  = 1 \dots n}$ to a morphism $u_{\mathrm{out}}(\tau): S \rightarrow T$ such that $u_{\mathrm{out}}(\tau) \circ \iota_i \sim_{S_i, T} \tau_i$ for all $i = 1, \dots, n$,>>such that>> - $\sum_{i=1}^{n} \iota_i \circ \pi_i \sim_{S,S} \mathrm{id}_S$,- $\pi_j \circ \iota_i \sim_{S_i,S_j} \delta_{i,j}$,>> where  $\delta_{i,j}  \in  \mathrm{Hom}(  S_i,  S_j  )$ is the identity if $i=j$, and $0$ otherwise. The $5$-tuple $(S, \pi, \iota, u_{\mathrm{in}},  u_{\mathrm{out}})$ is called a direct sum of $D$. We denote the object $S$ of such a $5$-tuple by $\bigoplus_{i=1}^n S_i$. We say that the morphisms  $u_{\mathrm{in}}(\tau),  u_{\mathrm{out}}(\tau)$ are induced by the universal property of the direct sum.We show how the described functionalities of direct sumscan be addressed in CAP:<jupyter_code>L := [ V1, V2, V2, V1 ];;
S := DirectSum( L );;
Display( S );
pi1 := ProjectionInFactorOfDirectSum( L, 2 );;
Display( pi1 );<jupyter_output>[ [  0,  0 ],
  [  1,  0 ],
  [  0,  1 ],
  [  0,  0 ],
  [  0,  0 ],
  [  0,  0 ] ]

A morphism in Category of matrices over Q<jupyter_text>Note that the argument in`ProjectionInFactorOfDirectSum`is the list $L$, not the already constructed object $S$.The object $S$ is simply given by the number $6$ anddoes not know anything about the way it was created.<jupyter_code>iota1 := InjectionOfCofactorOfDirectSum( L, 2 );;
Display( iota1 );
IsCongruentForMorphisms(
IdentityMorphism( V2 ),
PreCompose( iota1, pi1 )
);
Display( 
UniversalMorphismIntoDirectSum( [
ZeroMorphism( V2, V1 ),
alpha,
-3 * IdentityMorphism( V2 ),
ZeroMorphism( V2, V1 )
] )
);
Display( 
UniversalMorphismFromDirectSum( [
ZeroMorphism( V1, V2 ),
alpha,
-3 * IdentityMorphism( V2 ),
ZeroMorphism( V1, V2 )
] )
);<jupyter_output>[ [   0,   0 ],
  [   1,   1 ],
  [   1,   1 ],
  [  -3,   0 ],
  [   0,  -3 ],
  [   0,   0 ] ]

A morphism in Category of matrices over Q<jupyter_text>**Exercise 2**> Create the morphism> $$\alpha = \begin{pmatrix} 1 & 1 \\ 1 & 1\end{pmatrix}: V_2 \rightarrow V_2$$ > > only using the object $V_1$ and the following commands:> - `IdentityMorphism`> - `UniversalMorphismFromDirectSum`> - `UniversalMorphismIntoDirectSum`<jupyter_code># Solution of Exercise 2:<jupyter_output><empty_output><jupyter_text>Kernels Given a morphism $$\mu: V \rightarrow W$$between vector spaces $V,W$, the commonway to describe its kernel set-theoreticallyis given by$$\mathrm{kernel}(\mu) := \{ v \in V \mid \mu(v) = 0 \}.$$Clearly, this definition makes no sense in our computationalmodel $\mathrm{mat}_{\mathbb{Q}}$, where we do not haveaccess to "elements of vector spaces", since objects in$\mathrm{mat}_{\mathbb{Q}}$ aresimply represented by natural numbers.**Nevertheless, category theory provides enough languagethat lets us work with kernels anyway.**The following description is taken from the CAP manual:>For a given morphism $\alpha: A \rightarrow B$, a kernel of $\alpha$ consists of three parts:- an object $K$,- a morphism $\iota: K \rightarrow A$ such that $\alpha \circ \iota \sim_{K,B} 0$,- a  dependent  function $u$ mapping each morphism $\tau: T \rightarrow A$ satisfying $\alpha \circ \tau \sim_{T,B} 0$ to a morphism $u(\tau): T \rightarrow K$ such that $\iota        \circ u( \tau ) \sim_{T,A} \tau$.  >>  The  triple  $( K, \iota, u )$ is called a kernel of $\alpha$ if the morphisms $u( \tau )$ are uniquely determined up to congruence of morphisms. We denote the object $K$ of such a  triple  by  $\mathrm{KernelObject}(\alpha)$. We  say  that the morphism $u(\tau)$ is induced by the universal property of the kernel.    We show how the described functionalities of kernelscan be addressed in CAP: Recall that $\alpha$ was given by<jupyter_code>Display( alpha );
K := KernelObject( alpha );;
Display( K );
emb := KernelEmbedding( alpha );;
Display( emb );<jupyter_output>[ [  -1,   1 ] ]

A split monomorphism in Category of matrices over Q<jupyter_text>So, instead of "seeing" the linear dependencies of the rowsof the underlying matrix of $\alpha$ within the kernel object,we can "see" them in the kernel embedding of $\alpha$ instead. Next, we create a test morphism.<jupyter_code>tau := UniversalMorphismFromDirectSum( [ 2*emb, emb ] );;
Display( tau );<jupyter_output>[ [  -2,   2 ],
  [  -1,   1 ] ]

A morphism in Category of matrices over Q<jupyter_text>From the induced map of the universal property of the kernel,we can read off how the rows of $\tau$ are given as linearcombinations of the rows in the kernel embedding.<jupyter_code>lift := KernelLift( alpha, tau );;
Display( lift );
IsCongruentForMorphisms(
PreCompose( lift, emb ),
tau
);<jupyter_output><empty_output><jupyter_text>*Remark: on a technical level, Gaussian elemination is triggered in order to compute the outputs of the commands given above. However, as long as you can phraseand interpret the entities that you wish to compute categorically, you do not need to knowthe technicalities behind the commands.* **Exercise 3**> Write a function for the functoriality of the kernel, i.e., a function that takes as an input> $$\mu_1: A \rightarrow B$$> $$\mu_2: A' \rightarrow B'$$> $$\nu_1: A \rightarrow A'$$> $$\nu_2: B \rightarrow B'$$> such that> $$\mu_1 \cdot \nu_2 \sim \nu_1 \cdot \mu_2\text{,}$$> and gives as an output a morphism> $$\iota: \mathrm{KernelObject}( \mu_1 ) \longrightarrow \mathrm{KernelObject}( \mu_2 )$$> such that> $$\iota \cdot \mathrm{KernelEmbedding}( \mu_2 ) \sim \mathrm{KernelEmbedding}( \mu_1 ) \cdot \nu_1\text{.}$$> > Only use those CAP commands that you have already seen in this worksheet.<jupyter_code># Solution of Exercise 3<jupyter_output><empty_output><jupyter_text>Cokernels In order to properly introduce the cokernel of a morphism$$\mu: V \rightarrow W$$between vector spaces $V,W$ in a set-theoretical way,we would need to introduce the concept of images and quotientspaces first.In the language of category theory, we can simply statethat the definition of a cokernel is dual to the definitionof a kernel, i.e., simply reverse all the arrows in the categorical definition of the kernel.The following description is taken from the CAP manual:> For a given morphism $\alpha: A \rightarrow B$, a cokernel of $\alpha$ consists of three parts:  - an object $K$,  - a morphism $\epsilon: B \rightarrow K$ such that $\epsilon \circ \alpha \sim_{A,K} 0$,  - a  dependent  function  $u$ mapping each $\tau: B \rightarrow T$ satisfying $\tau \circ \alpha \sim_{A, T} 0$ to a morphism $u(\tau):K \rightarrow T$ such that $u(\tau) \circ        \epsilon \sim_{B,T} \tau$.>> The  triple  $(  K,  \epsilon, u )$ is called a cokernel of $\alpha$ if the morphisms $u( \tau )$ are uniquely determined up to congruence of morphisms. We denote the object $K$ of  such  a  triple  by $\mathrm{CokernelObject}(\alpha)$. We say that the morphism $u(\tau)$ is induced by the universal property of the cokernel.  We show how the described functionalities of cokernelscan be addressed in CAP: Recall that $\alpha$ was given by<jupyter_code>Display( alpha );
C := CokernelObject( alpha );;
Display( C );
proj := CokernelProjection( alpha );;
Display( proj );
tau := proj;;
colift := CokernelColift( alpha, proj );;
Display( colift );
IsCongruentForMorphisms(
PreCompose( proj, colift ),
tau
);<jupyter_output><empty_output><jupyter_text>**Exercise 4**> Construct an example of morphisms>> $$\alpha, \tau$$>> such that> `CokernelColift( alpha, tau )` is neither the identity nor zero.<jupyter_code># Solution of Exercise 4<jupyter_output><empty_output><jupyter_text>Lift along monos, colift along epis The definition of an abelian category involves the following two statements:> every mono is the kernel of its cokerneland> every epi is the cokernel of its kernel.Unwrapping these shortcut statements, we see thatwe have to able to compute> lifts along monomorphismsand> colifts along epimorphisms.We start with lifts along monomorphisms.<jupyter_code>mono :=
VectorSpaceMorphism( V1, HomalgMatrix( "[1,-1]", 1, 2, QQ ), V2 );;
Display( mono );
IsMonomorphism( mono );
tau :=
VectorSpaceMorphism( V2, HomalgMatrix( "[2,-2, 3,-3]", 2, 2, QQ ), V2 );;
Display( tau );
IsZeroForMorphisms( 
PreCompose( tau, CokernelProjection( mono ) )
);<jupyter_output><empty_output><jupyter_text>Since we expect `mono` to be the kernel embedding of its cokernel projection,and since `tau` is a proper test morphism, we should be ableto compute the lift:<jupyter_code>lift := LiftAlongMonomorphism( mono, tau );;
Display( lift );<jupyter_output>[ [  2 ],
  [  3 ] ]

A morphism in Category of matrices over Q<jupyter_text>**Exercise 5**> The command for colifts along epimorphism is given by> `ColiftAlongEpimorphism`. Create an example for its usage.  Category of finitely presented left modules As promised, we introduce a computablemodel of the category $\mathrm{mod}_R$ of finitely presented (left)modules over a computable ring $R$.A **(left) computable ring** is a ring $R$ equipped with- an algorithm to compute a finite generating set of the row syzygies of a given matrix,- an algorithm to decide the existence and to find a particular solution of a left-sided inhomogeneous linear system, i.e., a linear system of the form $X \cdot A = B$ for given matrices $A,B$ over $R$.*Remark: the existence of finite generating sets of row syzygies is actuallyequivalent to the category $\mathrm{mod}_R$being abelian.*In order to get access to some instances of computable rings,we load another $\mathsf{GAP}$ package.<jupyter_code>LoadPackage( "RingsForHomalg" );<jupyter_output><empty_output><jupyter_text>We are going to create the polynomial ring$$R := \mathbb{Q}[x,y,z].$$<jupyter_code>R := HomalgFieldOfRationalsInSingular() * "x,y,z";;<jupyter_output>================================================================
                     SINGULAR                                 /  Development
 A Computer Algebra System for Polynomial Computations       /   version 4.1.1
                                                           0<
 by: <NAME>, <NAME>, <NAME>, <NAME>     \   Feb 2018
FB Mathematik der Universitaet, D-67653 Kaiserslautern        \[0m
================================================================<jupyter_text>*Remark: on a technical level, we have just started a $\mathsf{Singular}$ sessionin the background. All computations that concern the ring $R$ will be delegatedto this external $\mathsf{Singular}$ session.* *Convention: when we say module, we will always mean a left module.*An $R$-module $M$ is finitely presented if$$\exists m,n \in \mathbb{N}_0 ~\exists (a_{ij})_{ij} \in R^{a \times b}:~M \simeq \mathrm{CokernelObject}( R^a \stackrel{(a_{ij})_{ij}}{\longrightarrow} R^b )$$Thus, matrices with entries in $R$ are great candidates for a data structureof the objects in our computational model $\mathrm{fpres}_R$.Our computational model $\mathrm{fpres}_R$ for finitely presented (left) modules,which we call the **category of left presentations** of $R$, is part of the following $\textsf{GAP}$-package:<jupyter_code>LoadPackage( "ModulePresentationsForCAP" );
fpresR := LeftPresentations( R );<jupyter_output><empty_output><jupyter_text>To construct an object in $\mathrm{fpres}_R$, we use the following constructor:<jupyter_code>M1 := AsLeftPresentation( HomalgMatrix( "[x,1,1,0]", 2, 2, R ) );;
Display( M1 );
M2 := AsLeftPresentation( HomalgIdentityMatrix( 2, R ) );;
Display( M2 );<jupyter_output>1,0,
0,1 

An object in Category of left presentations of Q[x,y,z]<jupyter_text>The two objects $M_1, M_2$ that we have just createdare considered to be unequal, since their underlyingmatrices are unequal:<jupyter_code>IsEqualForObjects( M1, M2 );<jupyter_output><empty_output><jupyter_text>However, both objects are isomorphic to the zero object:<jupyter_code>IsZeroForObjects( M1 );
IsZeroForObjects( M2 );<jupyter_output><empty_output><jupyter_text>This computation reflects the fact that the matrix over $R$presenting a module $M$ is not uniquely determined.Nevertheless, this does not prevent us from taking such matricesas a data structure for the objects in $\mathrm{fpres}_R$,as long as our choice for the morphisms will grantuee that wewill end up with an equivalence$$\mathrm{mod}_R \simeq \mathrm{fpres}_R.$$A morphism between two objects$$(a_{ij})_{ij}, (b_{kl})_{kl} \in \mathrm{Obj}\big( \mathrm{fpres}_R \big)$$is given by a matrix$$(c_{jl})_{jl}$$over $R$ such that there exists another matrix $( d_{ik} )_{ik}$ over $R$such that$$(a_{ij})_{ij} \cdot (c_{jl})_{jl}=(d_{ik})_{ik} \cdot (b_{kl})_{kl}\text{.}$$As an example, let us create the natural epimorphism$$\epsilon: R \twoheadrightarrow R/\langle x,y,z \rangle$$<jupyter_code>F := FreeLeftPresentation( 1, R );;
Display( F );
M := AsLeftPresentation( HomalgMatrix( "[ x, y, z ]", 3, 1, R ) );;
Display( M );
epsilon :=
PresentationMorphism(
F,
HomalgIdentityMatrix( 1, R ),
M );;
Display( epsilon );<jupyter_output>1

A morphism in Category of left presentations of Q[x,y,z]<jupyter_text>To check that the existence statement in the definition of a morphism in $\mathrm{fpres}_R$ is satisfied, we can call the following command:<jupyter_code>IsWellDefined( epsilon );<jupyter_output><empty_output><jupyter_text>A quicker way to create $\epsilon$ is the following:<jupyter_code>Display( CoverByFreeModule( M ) );<jupyter_output>1

A morphism in Category of left presentations of Q[x,y,z]<jupyter_text>Mathematically, the following matrix gives also rise to the morphism $\epsilon$:<jupyter_code>epsilon2 :=
PresentationMorphism(
F,
HomalgMatrix( "[1+x]", 1, 1, R ),
M
);;
Display( epsilon2 );
IsCongruentForMorphisms( epsilon, epsilon2 );<jupyter_output><empty_output><jupyter_text>However, the underlying matrices defining $\epsilon$and $\epsilon_2$ differ, which is what is asked forwhen we use the following command:<jupyter_code>IsEqualForMorphisms( epsilon, epsilon2 );<jupyter_output><empty_output><jupyter_text>So remember:`IsCongruentForMorphisms` is the mathematical notion of equality,`IsEqualForMorphisms` is the technical notion of equality.The latter is used for the technical specifications of CAP-operations:> "equal" input yields "equal" output,where the equality notion is always meant to be the technical one. It is mainly due to the comparision theorem of projective resolutionsand the functoriality of cokernelsthat the map$$(a_{ij})_{\substack{i = 1, \dots m \\ j = 1, \dots n}} \mapsto\mathrm{CokernelObject}\big( {R}^m \stackrel{(a_{ij})_{ij}}{\longrightarrow} {R}^n \big)$$extends to the level of morphisms and defines a functor$$\mathrm{fpres}_{R} \longrightarrow \mathrm{mod}_{R}$$that is an equivalence of categories.Moreover, $\mathrm{mod}_{R}$is an abelian category and consequently so is $\mathrm{fpres}_{R}$.We can use **exactly the same commands** as in the case of $\mathrm{mat}_k$in order to operate in $\mathrm{fpres}_{R}$.Here are examples:<jupyter_code>Display( KernelEmbedding( epsilon ) );
IsZeroForObjects( CokernelObject( epsilon ) );
Display( DirectSum( F, M, M, F ) );<jupyter_output>0,x,0,0,
0,y,0,0,
0,z,0,0,
0,0,x,0,
0,0,y,0,
0,0,z,0 

An object in Category of left presentations of Q[x,y,z]<jupyter_text>**Exercise 6**> Create a free resolution of $R/\langle x,y,z \rangle$ in CAP.  Generic algorithms for abelian categories Our computational models$\mathrm{mat}_k$ and $\mathrm{fpres}_R$are both examples of abelian categories.Let us refer to a CAP operationthat can be interpretedin any abelian categoryas an **abelian operation**.It then follows that any $\mathsf{GAP}$ functionthat we build up only using abelian operationscan be executed both in $\mathrm{mat}_k$ and $\mathrm{fpres}_R$.As an example, try out the code you wroteto solve Exercise 3 on the following input:<jupyter_code>M := AsLeftPresentation( HomalgMatrix( "[ x, y, z ]", 3, 1, R ) );;
N := AsLeftPresentation( HomalgMatrix( "[ x, y ]", 2, 1, R ) );;
mu1 := CoverByFreeModule( N );;
mu2 := CoverByFreeModule( M );;
nu1 := PresentationMorphism( Source( mu1 ), HomalgIdentityMatrix( 1, R ), Source( mu2 ) );;
nu2 := PresentationMorphism( N, HomalgIdentityMatrix( 1, R ), M );;<jupyter_output><empty_output><jupyter_text>Did you write your code generically enough that it was not only applicable in the contextof $\mathrm{mat}_k$, but also in $\mathrm{fpres}_R$? **Exercise 7**> Write generic algorithms for> 1. the intersection $A \cap B$ of two subobjects $A,B \hookrightarrow C$> 2. the sum $A + B$ of two subobjects $A,B \hookrightarrow C$ >> that work in any abelian category. > Note that subobjects of an object $C$ are simply modeled by monomorphisms into $C$.> Test your code on> the following examples: **Test case 1**Category: $\mathrm{mat}_{\mathbb{Q}}$<jupyter_code>C := VectorSpaceObject( 3, QQ );;

A := 
VectorSpaceMorphism(
VectorSpaceObject( 2, QQ ),
HomalgMatrix( "[1,1,0, 0,1,1]", 2, 3, QQ ), 
C );;

B := 
VectorSpaceMorphism(
VectorSpaceObject( 2, QQ ),
HomalgMatrix( "[1,0,1, 1,1,0]", 2, 3, QQ ), 
C );;

Display( A );
Display( B );<jupyter_output>[ [  1,  1,  0 ],
  [  0,  1,  1 ] ]

A morphism in Category of matrices over Q
[ [  1,  0,  1 ],
  [  1,  1,  0 ] ]

A morphism in Category of matrices over Q<jupyter_text>**Test case 2**Category: $\mathrm{fpres}_{\mathbb{Q}[x,y,z]}$<jupyter_code>A := AsMorphismBetweenFreeLeftPresentations(
HomalgMatrix( "[x]", 1, 1, R )
);;

B := AsMorphismBetweenFreeLeftPresentations(
HomalgMatrix( "[y]", 1, 1, R )
);;

Display( A );
Display( B );
# Solution of Exercise 7<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13301129664143624, 'fraction_numerical': 0.011638963903997566, 'mean_word_length': 5.1501754385964915, 'pattern_counts': {'":': 0, '<': 149, '<?xml version=': 0, '>': 204, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '39', 'dir': 'jupyter-structured-clean-dedup', 'id': '577797', 'license': 'MIT', 'n_tokens_mistral': 8552, 'n_tokens_neox': 8063, 'n_words': 3053, 'path': 'public/Abelian Categories.ipynb', 'repo_name': 'homalg-project/capdays-2018', 'size': '26312'}