diff --git a/FiniteCocompletions/gap/CategoryOfColimitQuivers.gd b/FiniteCocompletions/gap/CategoryOfColimitQuivers.gd
index 7ca7c8596..6826a2db0 100644
--- a/FiniteCocompletions/gap/CategoryOfColimitQuivers.gd
+++ b/FiniteCocompletions/gap/CategoryOfColimitQuivers.gd
@@ -118,6 +118,15 @@ CapJitAddTypeSignature( "FiniteColimitCompletionWithStrictCoproductsOfUnderlying
end );
+#! @Description
+#! The inputs are a colimit quiver colim_quiver in the category $C$
+#! and a list vertices of objects in $C$.
+#! The output is the full colimit subquiver on these objects.
+#! @Returns a monomorphism of colimit quivers
+#! @Arguments colim_quiver, vertices
+DeclareOperation( "EmbeddingOfFullColimitSubquiver",
+ [ IsObjectInCategoryOfColimitQuivers, IsList ] );
+
####################################
#
#! @Section Constructors
diff --git a/FiniteCocompletions/gap/CategoryOfColimitQuivers.gi b/FiniteCocompletions/gap/CategoryOfColimitQuivers.gi
index d52bae014..b20b72889 100644
--- a/FiniteCocompletions/gap/CategoryOfColimitQuivers.gi
+++ b/FiniteCocompletions/gap/CategoryOfColimitQuivers.gi
@@ -349,6 +349,65 @@ InstallMethod( CategoryOfPreSheavesOfUnderlyingCategory,
end );
+##
+InstallMethod( CategoryOfPreSheavesOfUnderlyingCategory,
+ [ IsCategoryOfColimitQuivers ],
+
+ function( ColimitQuiversC )
+
+ return PreSheaves( UnderlyingCategory( ColimitQuiversC ) );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( EmbeddingOfFullColimitSubquiver,
+ [ IsCategoryOfColimitQuivers, IsObjectInCategoryOfColimitQuivers, IsList ],
+
+ function( ColimitQuiversC, colim_quiver, list_of_objects )
+ local C, vertices_arrows, vertices, arrows, positions, V, id, A, colim_subquiver, embedding;
+
+ C := UnderlyingCategory( ColimitQuiversC );
+
+ vertices_arrows := ObjectDatum( ColimitQuiversC, colim_quiver );
+
+ vertices := vertices_arrows[1];
+ arrows := vertices_arrows[2];
+
+ positions := List( vertices, vertex ->
+ PositionProperty( list_of_objects, obj -> IsEqualForObjects( C, obj, vertex ) ) );
+
+ V := Filtered( [ 0 .. Length( vertices ) - 1 ], i -> IsInt( positions[1 + i] ) );
+
+ id := List( list_of_objects, obj -> IdentityMorphism( C, obj ) );
+
+ A := Filtered( [ 0 .. Length( arrows ) - 1 ], j ->
+ ( arrows[1 + j][1] in V ) and ( arrows[1 + j][3] in V ) );
+
+ colim_subquiver := CreateColimitQuiver( ColimitQuiversC,
+ Pair( vertices{1 + V}, arrows{1 + A} ) );
+
+ embedding := CreateMorphismOfColimitQuivers( ColimitQuiversC,
+ colim_subquiver,
+ Pair( Pair( V, id{positions{1 + V}} ),
+ A ),
+ colim_quiver );
+ #% CAP_JIT_DROP_NEXT_STATEMENT
+ SetIsMonomorphism( embedding, true );
+
+ return embedding;
+
+end );
+
+##
+InstallMethod( EmbeddingOfFullColimitSubquiver,
+ [ IsObjectInCategoryOfColimitQuivers, IsList ],
+
+ function( colim_quiver, list_of_objects )
+
+ return EmbeddingOfFullColimitSubquiver( CapCategory( colim_quiver ), colim_quiver, list_of_objects );
+
+end );
+
####################################
#
# View, Print, Display and LaTeX methods:
diff --git a/FpCategories/gap/PathCategories.gd b/FpCategories/gap/PathCategories.gd
index cbddd65c3..b666b68fe 100644
--- a/FpCategories/gap/PathCategories.gd
+++ b/FpCategories/gap/PathCategories.gd
@@ -173,5 +173,11 @@ DeclareAttribute( "ExternalHoms", IsPathCategory );
#
####################################
+DeclareAttribute( "DecompositionIndicesOfMorphism",
+ IsPathCategoryMorphism );
+
+DeclareAttribute( "DecompositionOfMorphismInCategory",
+ IsPathCategoryMorphism );
+
DeclareOperation( "ExtendFunctorToFpCategoryData",
[ IsPathCategory, IsList, IsCapCategory ] );
diff --git a/FpCategories/gap/PathCategories.gi b/FpCategories/gap/PathCategories.gi
index 8c25ed9c0..6281e7098 100644
--- a/FpCategories/gap/PathCategories.gi
+++ b/FpCategories/gap/PathCategories.gi
@@ -1066,6 +1066,42 @@ InstallOtherMethod( ExternalHoms,
end );
+##
+InstallOtherMethodForCompilerForCAP( DecompositionIndicesOfMorphism,
+ "for a path category and a morphism therein",
+ [ IsPathCategory, IsPathCategoryMorphism ],
+
+ function( C, mor )
+
+ return List( MorphismIndices( mor ), i -> -1 + i );
+
+end );
+
+##
+InstallMethod( DecompositionIndicesOfMorphism,
+ "for a morphism in a path category",
+ [ IsPathCategoryMorphism ],
+
+ function( mor )
+
+ return DecompositionIndicesOfMorphism( CapCategory( mor ), mor );
+
+end );
+
+##
+InstallMethod( DecompositionOfMorphismInCategory,
+ "for a morphism in a path category",
+ [ IsPathCategoryMorphism ],
+
+ function( mor )
+ local C;
+
+ C := CapCategory( mor );
+
+ return SetOfGeneratingMorphisms( C ){1 + DecompositionIndicesOfMorphism( mor )};
+
+end );
+
##
InstallMethod( DatumOfCellAsEvaluatableString,
[ IsPathCategoryMorphism, IsList ],
diff --git a/FunctorCategories/PackageInfo.g b/FunctorCategories/PackageInfo.g
index fec80c8c0..cf3a9d7b0 100644
--- a/FunctorCategories/PackageInfo.g
+++ b/FunctorCategories/PackageInfo.g
@@ -89,7 +89,7 @@ Dependencies := rec(
NeededOtherPackages := [
[ "GAPDoc", ">= 1.5" ],
[ "ToolsForHomalg", ">= 2022.12-01" ],
- [ "CAP", ">= 2024.02-01" ],
+ [ "CAP", ">= 2024.04-02" ],
[ "MonoidalCategories", ">= 2024.02-01" ],
[ "CartesianCategories", ">= 2024.02-05" ],
[ "ToolsForCategoricalTowers", ">= 2024.03-02" ],
diff --git a/FunctorCategories/examples/ColimitingCocone.g b/FunctorCategories/examples/ColimitingCocone.g
new file mode 100644
index 000000000..66efa0602
--- /dev/null
+++ b/FunctorCategories/examples/ColimitingCocone.g
@@ -0,0 +1,35 @@
+#! @Chunk ColimitingCocone
+
+#! @Example
+LoadPackage( "FunctorCategories", false );
+#! true
+q := "q(a,l,m,r,i,i1,i2,c,b)[ac:a->c,lc:l->c,mi:m->i,ic:i->c,ri1:r->i1,i1i2:i1->i2,i2c:i2->c,cb:c->b]";;
+q := RightQuiver( q );
+#! RightQuiver( "" );
+F := FreeCategory( q );
+#F := PathCategory( q );
+#! FreeCategory(
+#! RightQuiver( "" ) );
+Size( F );
+#! 7
+PSh := PreSheaves( F );
+#! PreSheaves( FreeCategory(
+#! RightQuiver( "" ) ) );
+#! SkeletalFinSets )
+Y := YonedaEmbeddingOfSourceCategory( PSh );
+#! Yoneda embedding functor
+coprd_cocone := [ F.c, [ F.lc, F.mi * F.ic, F.ri1 * F.i1i2 * F.i2c ] ];
+#coprd_cocone := [ F.c, [ F.ac, F.lc ] ];
+is_closed := G -> IsClosedPreSheafWRTCoproductCocones( PSh, G, [ coprd_cocone ] );
+#! function( G ) ... end
+G := Coproduct( [ PSh.a, PSh.a, PSh.l, PSh.m, PSh.r, PSh.r, PSh.c, PSh.b ] );
+#G := Coproduct( [ PSh.a, PSh.l, PSh.l ] );
+#!
+emb := EmbeddingIntoClosureOfPreSheafWRTCoproductCocones( G, [ coprd_cocone ] );
+Assert( 0, IsWellDefined( emb ) );
+Assert( 0, IsMonomorphism( emb ) );
+Assert( 0, Source( emb ) = G );
+Assert( 0, is_closed( Target( emb ) ) );
+#! @EndExample
diff --git a/FunctorCategories/examples/JoinCocone.g b/FunctorCategories/examples/JoinCocone.g
new file mode 100644
index 000000000..f2aa5bb3b
--- /dev/null
+++ b/FunctorCategories/examples/JoinCocone.g
@@ -0,0 +1,40 @@
+#! @Chunk JoinCocone
+
+#! @Example
+LoadPackage( "FunctorCategories", false );
+#! true
+q := FinQuiver( "q(a,l,r,i,c,b)[ac:a->c,lc:l->c,ri:r->i,ic:i->c,cb:c->b]" );
+#! FinQuiver( "q(a,l,r,i,c,b)[ac:a-≻c,lc:l-≻c,ri:r-≻i,ic:i-≻c,cb:c-≻b]" )
+F := PathCategory( q );
+#! PathCategory(
+#! FinQuiver( "q(a,l,r,i,c,b)[ac:a-≻c,lc:l-≻c,ri:r-≻i,ic:i-≻c,cb:c-≻b]" ) )
+Size( F );
+#! 16
+P := PosetOfCategory( F );
+#! PosetOfCategory( PathCategory(
+#! FinQuiver( "q(a,l,r,i,c,b)[ac:a-≻c,lc:l-≻c,ri:r-≻i,ic:i-≻c,cb:c-≻b]" ) ) )
+Size( P );
+#! 16
+digraphF := DigraphOfPoset( P );;
+digraphF!.vertexlabels := List( SetOfObjects( F ), String );
+#Splash( DotVertexLabelledDigraph( digraphF ) );
+#Splash( DotVertexLabelledDigraph( DigraphOfPoset( P ) ) );
+PSh := PreSheaves( P );
+#! PreSheaves( PosetOfCategory( PathCategory(
+#! FinQuiver( "q(a,l,r,i,c,b)[ac:a-≻c,lc:l-≻c,ri:r-≻i,ic:i-≻c,cb:c-≻b]" ) ) ),
+#! IntervalCategory )
+Y := YonedaEmbeddingOfSourceCategory( PSh );
+#! Yoneda embedding functor
+coproducts := [ [ P.c, [ P.l, P.r ] ] ];;
+#! [ [ An object in the poset given by: (c),
+#! [ An object in the poset given by: (l),
+#! An object in the poset given by: (r) ] ] ]
+PSh_J := ClosedPreSheavesWRTCoproducts( P, coproducts );;
+closed := SetOfObjects( PSh_J );;
+Assert( 0, Length( closed ) = 10 );
+psh_J := ModelingCategory( ModelingCategory( PSh_J ) );;
+Assert( 0, Length( SetOfObjects( psh_J ) ) = Length( SetOfObjects( PSh_J ) ) );
+is_closed := psh_J!.ObjectMembershipFunction;
+Assert( 0, ForAll( closed, obj -> is_closed( ObjectDatum( ModelingObject( PSh_J, obj ) ) ) ) );
+#Splash( DotVertexLabelledDigraph( PSh, [ Y, psh_J ], [ "grey", "blue", "red" ] : offset := 0 ) );
+#! @EndExample
diff --git a/FunctorCategories/gap/ClosedCoPreSheavesWRTLimitingCones.gd b/FunctorCategories/gap/ClosedCoPreSheavesWRTLimitingCones.gd
new file mode 100644
index 000000000..651f96afc
--- /dev/null
+++ b/FunctorCategories/gap/ClosedCoPreSheavesWRTLimitingCones.gd
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# FunctorCategories: Categories of functors
+#
+# Declarations
+#
+
+#! @Chapter Category of closed copresheaves with respect to limiting cones
+
+####################################
+#
+#! @Section GAP categories
+#
+####################################
+
+#! @Description
+#! The ⪆ category of closed copresheaves with respect to limiting cones.
+DeclareCategory( "IsClosedCoPreSheavesWRTLimitingCones",
+ IsCapCategory );
+
+#! @Description
+#! The ⪆ category of cells in the category of closed copresheaves with respect to limiting cones.
+DeclareCategory( "IsCellInClosedCoPreSheavesWRTLimitingCones",
+ IsCapCategoryCell );
+
+#! @Description
+#! The ⪆ category of objects in the category of closed copresheaves with respect to limiting cones.
+DeclareCategory( "IsObjectInClosedCoPreSheavesWRTLimitingCones",
+ IsCellInClosedCoPreSheavesWRTLimitingCones and IsCapCategoryObject );
+
+#! @Description
+#! The ⪆ category of morphisms in the category of closed copresheaves with respect to limiting cones.
+DeclareCategory( "IsMorphismInClosedCoPreSheavesWRTLimitingCones",
+ IsCellInClosedCoPreSheavesWRTLimitingCones and IsCapCategoryMorphism );
+
+####################################
+#
+#! @Section Constructors
+#
+####################################
+
+#! @Description
+#! The input is category C and a list product_cones of product cones in C.
+#! The output is the category of of closed copresheaves with respect to product_cones.
+#! @Arguments C, product_cones
+DeclareOperation( "ClosedCoPreSheavesWRTProductCones",
+ [ IsCapCategory, IsList ] );
+
+#CapJitAddTypeSignature( "ClosedCoPreSheavesWRTProductCones", [ IsCapCategory, IsList ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( ClosedCoPreSheavesWRTProductCones( input_types[1].category ) );
+#
+#end );
+
+#! @Description
+#! The input is category C and a list lists_of_product_cofactors of lists of product cofactors in C.
+#! The output is the category of of closed copresheaves with respect to lists_of_product_cofactors.
+#! @Arguments C, lists_of_product_cofactors
+DeclareOperation( "ClosedCoPreSheavesWRTProducts",
+ [ IsCapCategory, IsList ] );
+
+#CapJitAddTypeSignature( "ClosedCoPreSheavesWRTProducts", [ IsCapCategory, IsList ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( ClosedCoPreSheavesWRTProducts( input_types[1].category ) );
+#
+#end );
+
+#! @Description
+#! The input is category C and a list lists_of_product_cofactors of lists of product cofactors in C.
+#! The output is the category of of closed copresheaves with respect to lists_of_product_cofactors.
+#! @Arguments C, lists_of_product_cofactors
+DeclareOperation( "ClosedCoPreSheavesWRTProductsByIndices",
+ [ IsCapCategory, IsList ] );
+
+#CapJitAddTypeSignature( "ClosedCoPreSheavesWRTProductsByIndices", [ IsCapCategory, IsList ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( ClosedCoPreSheavesWRTProductsByIndices( input_types[1].category ) );
+#
+#end );
+
+####################################
+#
+#! @Section Attributes
+#
+####################################
+
+#! @Description
+#! The input is the category of closed copresheaves on a category $C$ with respect to a list $L$ of limiting cones in $C$.
+#! The output is the list $L$.
+#! @Arguments coPSh_J
+DeclareAttribute( "UnderlyingLimitingCones",
+ IsClosedCoPreSheavesWRTLimitingCones );
+
+#! @Description
+#! The input is the category of closed copresheaves on a category $C$ with respect to limiting cones in $C$.
+#! The output is the category $C$.
+#! @Arguments coPSh_J
+DeclareAttribute( "Source",
+ IsClosedCoPreSheavesWRTLimitingCones );
+
+CapJitAddTypeSignature( "Source", [ IsClosedCoPreSheavesWRTLimitingCones ],
+ function ( input_types )
+
+ return CapJitDataTypeOfCategory( Source( input_types[1].category ) );
+
+end );
+
+#! @Description
+#! The input is the category of closed copresheaves on a category $C$ with respect to limiting cones in $C$.
+#! The output is the target category.
+#! @Arguments coPSh_J
+DeclareAttribute( "Target",
+ IsClosedCoPreSheavesWRTLimitingCones );
+
+CapJitAddTypeSignature( "Target", [ IsClosedCoPreSheavesWRTLimitingCones ],
+ function ( input_types )
+
+ return CapJitDataTypeOfCategory( Target( input_types[1].category ) );
+
+end );
+
+DeclareAttribute( "CoYonedaEmbeddingDataOfSourceCategory",
+ IsClosedCoPreSheavesWRTLimitingCones );
+
+#! @Arguments coPSh_J
+#! @Returns a ∩ functor
+DeclareAttribute( "CoYonedaEmbeddingOfSourceCategory",
+ IsClosedCoPreSheavesWRTLimitingCones );
diff --git a/FunctorCategories/gap/ClosedCoPreSheavesWRTLimitingCones.gi b/FunctorCategories/gap/ClosedCoPreSheavesWRTLimitingCones.gi
new file mode 100644
index 000000000..64d096627
--- /dev/null
+++ b/FunctorCategories/gap/ClosedCoPreSheavesWRTLimitingCones.gi
@@ -0,0 +1,377 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# FunctorCategories: Categories of functors
+#
+# Implementations
+#
+
+##
+InstallMethod( ClosedCoPreSheavesWRTProductCones,
+ "for a category and a list of product cones",
+ [ IsCapCategory, IsList ],
+
+ function ( C, product_cones )
+ local H,
+ object_datum_type, object_constructor, object_datum,
+ morphism_datum_type, morphism_constructor, morphism_datum,
+ C_op, coproduct_cocones, PSh_C_op_J, op_PSh_C_op_J,
+ modeling_tower_object_constructor, modeling_tower_object_datum,
+ modeling_tower_morphism_constructor, modeling_tower_morphism_datum,
+ coPSh_J;
+
+ if not ( ForAll( product_cones, IsList ) and
+ ForAll( product_cones, pair -> IsCapCategoryObject( pair[1] ) and IsIdenticalObj( C, CapCategory( pair[1] ) ) ) and
+ ForAll( product_cones, pair -> ForAll( pair[2], mor -> IsCapCategoryMorphism( mor ) and IsIdenticalObj( C, CapCategory( mor ) ) ) ) ) then
+
+ Error( "the second argument `product_cones` must be a list of pairs, ",
+ "where the first entry of the pair is an object in the category `C` and ",
+ "the second entry a list of morphisms in `C`" );
+
+ fi;
+
+ H := RangeCategoryOfHomomorphismStructure( C );
+
+ ##
+ object_datum_type :=
+ CapJitDataTypeOfNTupleOf( 2,
+ CapJitDataTypeOfListOf( CapJitDataTypeOfObjectOfCategory( H ) ),
+ CapJitDataTypeOfListOf( CapJitDataTypeOfMorphismOfCategory( H ) ) );
+
+ ##
+ object_constructor :=
+ function( coPSh_J, pair )
+
+ return CreateCapCategoryObjectWithAttributes( coPSh_J,
+ Source, Source( coPSh_J ),
+ Target, Target( coPSh_J ),
+ AsPrimitiveValue, pair );
+
+ end;
+
+ ##
+ object_datum := { coPSh_J, o } -> AsPrimitiveValue( o );
+
+ ##
+ morphism_datum_type :=
+ CapJitDataTypeOfListOf( CapJitDataTypeOfMorphismOfCategory( H ) );
+
+ ##
+ morphism_constructor :=
+ function( coPSh_J, source, components, target )
+
+ return CreateCapCategoryMorphismWithAttributes( coPSh_J,
+ source,
+ target,
+ AsPrimitiveValue, components );
+
+ end;
+
+ ##
+ morphism_datum := { coPSh_J, m } -> AsPrimitiveValue( m );
+
+ ## building the categorical tower:
+
+ C_op := Opposite( C : FinalizeCategory := true, only_primitive_operations := true );
+
+ coproduct_cocones := List( product_cones, pair ->
+ Pair( ObjectConstructor( C_op, pair[1] ),
+ List( pair[2], mor ->
+ MorphismConstructor( C_op,
+ ObjectConstructor( C_op, Target( mor ) ),
+ mor,
+ ObjectConstructor( C_op, Source( mor ) ) ) ) ) );
+
+ PSh_C_op_J := ClosedPreSheavesWRTCoproductCocones( C_op, coproduct_cocones : FinalizeCategory := true );
+
+ op_PSh_C_op_J := Opposite( PSh_C_op_J : FinalizeCategory := true, only_primitive_operations := true );
+
+ ## from the raw object data to the object in the modeling category
+ modeling_tower_object_constructor :=
+ function( coPSh_J, pair )
+ local op_PSh_C_op_J, PSh_C_op_J;
+
+ op_PSh_C_op_J := ModelingCategory( coPSh_J );
+
+ PSh_C_op_J := OppositeCategory( op_PSh_C_op_J );
+
+ return ObjectConstructor( op_PSh_C_op_J,
+ ObjectConstructor( PSh_C_op_J,
+ pair ) );
+
+ end;
+
+ ## from the object in the modeling category to the raw object data
+ modeling_tower_object_datum :=
+ function( coPSh_J, obj )
+ local op_PSh_C_op_J, PSh_C_op_J;
+
+ op_PSh_C_op_J := ModelingCategory( coPSh_J );
+
+ PSh_C_op_J := OppositeCategory( op_PSh_C_op_J );
+
+ return ObjectDatum( PSh_C_op_J,
+ ObjectDatum( op_PSh_C_op_J,
+ obj ) );
+
+ end;
+
+ ## from the raw morphism data to the morphism in the modeling category
+ modeling_tower_morphism_constructor :=
+ function( coPSh_J, source, images, target )
+ local op_PSh_C_op_J, PSh_C_op_J;
+
+ op_PSh_C_op_J := ModelingCategory( coPSh_J );
+
+ PSh_C_op_J := OppositeCategory( op_PSh_C_op_J );
+
+ return MorphismConstructor( op_PSh_C_op_J,
+ source,
+ MorphismConstructor( PSh_C_op_J,
+ ObjectDatum( op_PSh_C_op_J, target ),
+ images,
+ ObjectDatum( op_PSh_C_op_J, source ) ),
+ target );
+
+ end;
+
+ ## from the morphism in the modeling category to the raw morphism data
+ modeling_tower_morphism_datum :=
+ function( coPSh_J, mor )
+ local op_PSh_C_op_J, PSh_C_op_J;
+
+ op_PSh_C_op_J := ModelingCategory( coPSh_J );
+
+ PSh_C_op_J := OppositeCategory( op_PSh_C_op_J );
+
+ return MorphismDatum( PSh_C_op_J,
+ MorphismDatum( op_PSh_C_op_J,
+ mor ) );
+
+ end;
+
+ ##
+ coPSh_J :=
+ ReinterpretationOfCategory( op_PSh_C_op_J,
+ rec( name := Concatenation( "ClosedCoPreSheavesWRTProductCones( ", Name( C ), ", product_cones )" ),
+ category_filter := IsClosedCoPreSheavesWRTLimitingCones,
+ category_object_filter := IsObjectInClosedCoPreSheavesWRTLimitingCones,
+ category_morphism_filter := IsMorphismInClosedCoPreSheavesWRTLimitingCones,
+ object_datum_type := object_datum_type,
+ morphism_datum_type := morphism_datum_type,
+ object_constructor := object_constructor,
+ object_datum := object_datum,
+ morphism_constructor := morphism_constructor,
+ morphism_datum := morphism_datum,
+ modeling_tower_object_constructor := modeling_tower_object_constructor,
+ modeling_tower_object_datum := modeling_tower_object_datum,
+ modeling_tower_morphism_constructor := modeling_tower_morphism_constructor,
+ modeling_tower_morphism_datum := modeling_tower_morphism_datum,
+ only_primitive_operations := true )
+ : FinalizeCategory := false );
+
+ SetSource( coPSh_J, C );
+ SetTarget( coPSh_J, Target( PSh_C_op_J ) );
+ SetUnderlyingLimitingCones( coPSh_J, product_cones );
+
+ Append( coPSh_J!.compiler_hints.category_attribute_names,
+ [ "Source",
+ "Target",
+ "UnderlyingLimitingCones" ] );
+
+ Finalize( coPSh_J );
+
+ return coPSh_J;
+
+end );
+
+##
+InstallMethod( ClosedCoPreSheavesWRTProducts,
+ "for a category and a list of product cones",
+ [ IsCapCategory, IsList ],
+
+ function ( C, lists_of_product_factors )
+
+ return ClosedCoPreSheavesWRTProductCones( C, ConesOfProducts( C, lists_of_product_factors ) );
+
+end );
+
+##
+InstallMethod( ClosedCoPreSheavesWRTProductsByIndices,
+ "for a category and a list of product cones",
+ [ IsCapCategory, IsList ],
+
+ function ( C, lists_of_product_factors_by_indices )
+
+ return ClosedCoPreSheavesWRTProductCones( C, ConesOfProductsByIndices( C, lists_of_product_factors_by_indices ) );
+
+end );
+
+##
+InstallMethod( \.,
+ "for the category of closed copresheaves with respect to colimiting cocones and a positive integer",
+ [ IsClosedCoPreSheavesWRTLimitingCones, IsPosInt ],
+
+ function( coPSh_J, string_as_int )
+ local name, op_PSh_C_op_J, c;
+
+ name := NameRNam( string_as_int );
+
+ op_PSh_C_op_J := ModelingCategory( coPSh_J );
+
+ c := op_PSh_C_op_J.(name);
+
+ if IsCapCategoryObject( c ) and IsIdenticalObj( CapCategory( c ), op_PSh_C_op_J ) then
+
+ return ReinterpretationOfObject( coPSh_J, c );
+
+ elif IsCapCategoryMorphism( c ) and IsIdenticalObj( CapCategory( c ), op_PSh_C_op_J ) then
+
+ return ReinterpretationOfMorphism( coPSh_J,
+ ReinterpretationOfObject( coPSh_J, Source( c ) ),
+ c,
+ ReinterpretationOfObject( coPSh_J, Target( c ) ) );
+
+ else
+
+ Error( "`c` is neither an object nor a morphism in the modeling category `op_PSh_C_op_J := ModelingCategory( coPSh_J )`\n" );
+
+ fi;
+
+end );
+
+##
+InstallMethodForCompilerForCAP( SetOfObjects,
+ "for the category of closed copresheaves with respect to limiting cones",
+ [ IsClosedCoPreSheavesWRTLimitingCones ],
+
+ function( cat )
+
+ return SetOfObjectsOfCategory( cat );
+
+end );
+
+##
+InstallMethodForCompilerForCAP( SetOfGeneratingMorphisms,
+ "for the category of closed copresheaves with respect to limiting cones",
+ [ IsClosedCoPreSheavesWRTLimitingCones ],
+
+ function( cat )
+
+ return SetOfGeneratingMorphismsOfCategory( cat );
+
+end );
+
+##
+InstallMethodForCompilerForCAP( CoYonedaEmbeddingDataOfSourceCategory,
+ "for a category of closed copresheaves w.r.t. limiting cones",
+ [ IsClosedCoPreSheavesWRTLimitingCones ],
+
+ function ( coPSh_J )
+ local C, coyoneda_data, coYoneda_on_objs, coYoneda_on_mors;
+
+ C := Source( coPSh_J );
+
+ coyoneda_data := CoYonedaEmbeddingData( C );
+
+ coYoneda_on_objs :=
+ function ( obj )
+
+ return ObjectConstructor( coPSh_J,
+ coyoneda_data[1]( obj ) );
+
+ end;
+
+ coYoneda_on_mors :=
+ function ( source, mor, target )
+ local source_on_objs, target_on_objs;
+
+ Error( "not implemented yet" );
+
+ source_on_objs := ObjectDatum( coPSh_J, source )[1];
+ target_on_objs := ObjectDatum( coPSh_J, target )[1];
+
+ return MorphismConstructor( coPSh_J,
+ source,
+ coyoneda_data[2]( source_on_objs, mor, target_on_objs ),
+ target );
+
+ end;
+
+ return Pair( coYoneda_on_objs, coYoneda_on_mors );
+
+end );
+
+##
+InstallMethod( CoYonedaEmbeddingOfSourceCategory,
+ "for a category of closed copresheaves w.r.t. limiting cones",
+ [ IsClosedCoPreSheavesWRTLimitingCones ],
+
+ function ( coPSh_J )
+ local C, coYoneda, coYoneda_data;
+
+ C := Source( coPSh_J );
+
+ coYoneda := CapFunctor( "co-Yoneda embedding functor", C, coPSh_J );
+
+ coYoneda_data := CoYonedaEmbeddingDataOfSourceCategory( coPSh_J );
+
+ AddObjectFunction( coYoneda, coYoneda_data[1] );
+
+ AddMorphismFunction( coYoneda, coYoneda_data[2] );
+
+ return coYoneda;
+
+end );
+
+##################################
+##
+## View & Display
+##
+##################################
+
+##
+InstallMethod( ViewObj,
+ [ IsObjectInClosedCoPreSheavesWRTLimitingCones ],
+
+ function( a )
+
+ Print( "An object in category of closed copresheaves given by: " );
+
+ ViewObj( ObjectDatum( CapCategory( a ), a ) );
+
+end );
+
+##
+InstallMethod( ViewObj,
+ [ IsMorphismInClosedCoPreSheavesWRTLimitingCones ],
+
+ function( phi )
+
+ Print( "A morphism in category of closed copresheaves given by: " );
+
+ ViewObj( MorphismDatum( CapCategory( phi ), phi ) );
+
+end );
+
+##
+InstallMethod( Display,
+ [ IsObjectInClosedCoPreSheavesWRTLimitingCones ],
+
+ function( a )
+
+ Display( ObjectDatum( CapCategory( a ), a ) );
+
+ Display( "\nAn object in category of closed copresheaves given by the above data" );
+
+end );
+
+##
+InstallMethod( Display,
+ [ IsMorphismInClosedCoPreSheavesWRTLimitingCones ],
+
+ function( phi )
+
+ Display( MorphismDatum( CapCategory( phi ), phi ) );
+
+ Display( "A morphism in category of closed copresheaves given by the above data" );
+
+end );
diff --git a/FunctorCategories/gap/ClosedPreSheavesWRTColimitingCocones.gd b/FunctorCategories/gap/ClosedPreSheavesWRTColimitingCocones.gd
new file mode 100644
index 000000000..7ebd7e3a1
--- /dev/null
+++ b/FunctorCategories/gap/ClosedPreSheavesWRTColimitingCocones.gd
@@ -0,0 +1,165 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# FunctorCategories: Categories of functors
+#
+# Declarations
+#
+
+#! @Chapter Category of closed presheaves with respect to colimiting cocones
+
+####################################
+#
+#! @Section GAP categories
+#
+####################################
+
+#! @Description
+#! The ⪆ category of closed presheaves with respect to colimiting cocones.
+DeclareCategory( "IsClosedPreSheavesWRTColimitingCocones",
+ IsCapCategory );
+
+#! @Description
+#! The ⪆ category of cells in the category of closed presheaves with respect to colimiting cocones.
+DeclareCategory( "IsCellInClosedPreSheavesWRTColimitingCocones",
+ IsCapCategoryCell );
+
+#! @Description
+#! The ⪆ category of objects in the category of closed presheaves with respect to colimiting cocones.
+DeclareCategory( "IsObjectInClosedPreSheavesWRTColimitingCocones",
+ IsCellInClosedPreSheavesWRTColimitingCocones and IsCapCategoryObject );
+
+#! @Description
+#! The ⪆ category of morphisms in the category of closed presheaves with respect to colimiting cocones.
+DeclareCategory( "IsMorphismInClosedPreSheavesWRTColimitingCocones",
+ IsCellInClosedPreSheavesWRTColimitingCocones and IsCapCategoryMorphism );
+
+####################################
+#
+#! @Section Constructors
+#
+####################################
+
+#! @Description
+#! The input is category C and a list coproduct_cocones of coproduct cocones in C.
+#! The output is the category of of closed presheaves with respect to coproduct_cocones.
+#! @Arguments C, coproduct_cocones
+DeclareOperation( "ClosedPreSheavesWRTCoproductCocones",
+ [ IsCapCategory, IsList ] );
+
+#CapJitAddTypeSignature( "ClosedPreSheavesWRTCoproductCocones", [ IsCapCategory, IsList ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( ClosedPreSheavesWRTCoproductCocones( input_types[1].category ) );
+#
+#end );
+
+#! @Description
+#! The input is category C and a list lists_of_coproduct_cofactors of lists of coproduct cofactors in C.
+#! The output is the category of of closed presheaves with respect to lists_of_coproduct_cofactors.
+#! @Arguments C, lists_of_coproduct_cofactors
+DeclareOperation( "ClosedPreSheavesWRTCoproducts",
+ [ IsCapCategory, IsList ] );
+
+#CapJitAddTypeSignature( "ClosedPreSheavesWRTCoproducts", [ IsCapCategory, IsList ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( ClosedPreSheavesWRTCoproducts( input_types[1].category ) );
+#
+#end );
+
+#! @Description
+#! The input is category C and a list lists_of_coproduct_cofactors of lists of coproduct cofactors in C.
+#! The output is the category of of closed presheaves with respect to lists_of_coproduct_cofactors.
+#! @Arguments C, lists_of_coproduct_cofactors
+DeclareOperation( "ClosedPreSheavesWRTCoproductsByIndices",
+ [ IsCapCategory, IsList ] );
+
+#CapJitAddTypeSignature( "ClosedPreSheavesWRTCoproductsByIndices", [ IsCapCategory, IsList ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( ClosedPreSheavesWRTCoproductsByIndices( input_types[1].category ) );
+#
+#end );
+
+####################################
+#
+#! @Section Attributes
+#
+####################################
+
+#! @Description
+#! The input is the category of closed presheaves on a category $C$ with respect to a list $L$ of colimiting cocones in $C$.
+#! The output is the list $L$.
+#! @Arguments PSh_J
+DeclareAttribute( "UnderlyingColimitingCocones",
+ IsClosedPreSheavesWRTColimitingCocones );
+
+#! @Description
+#! The input is the category of closed presheaves on a category $C$ with respect to colimiting cocones in $C$.
+#! The output is the category $C$.
+#! @Arguments PSh_J
+DeclareAttribute( "Source",
+ IsClosedPreSheavesWRTColimitingCocones );
+
+CapJitAddTypeSignature( "Source", [ IsClosedPreSheavesWRTColimitingCocones ],
+ function ( input_types )
+
+ return CapJitDataTypeOfCategory( Source( input_types[1].category ) );
+
+end );
+
+#! @Description
+#! The input is the category of closed presheaves on a category $C$ with respect to colimiting cocones in $C$.
+#! The output is the target category.
+#! @Arguments PSh_J
+DeclareAttribute( "Target",
+ IsClosedPreSheavesWRTColimitingCocones );
+
+CapJitAddTypeSignature( "Target", [ IsClosedPreSheavesWRTColimitingCocones ],
+ function ( input_types )
+
+ return CapJitDataTypeOfCategory( Target( input_types[1].category ) );
+
+end );
+
+DeclareAttribute( "YonedaEmbeddingDataOfSourceCategory",
+ IsClosedPreSheavesWRTColimitingCocones );
+
+#! @Arguments PSh_J
+#! @Returns a ∩ functor
+DeclareAttribute( "YonedaEmbeddingOfSourceCategory",
+ IsClosedPreSheavesWRTColimitingCocones );
+
+####################################
+#
+#! @Section Operations
+#
+####################################
+
+#! @Arguments PSh, presheaf, coproducts_cocones
+DeclareOperation( "IsClosedPreSheafWRTCoproductCocones",
+ [ IsObjectInPreSheafCategory, IsList ] );
+
+#! @Arguments PSh, presheaf, lists_of_coproduct_cofactors
+DeclareOperation( "IsClosedPreSheafWRTCoproducts",
+ [ IsObjectInPreSheafCategory, IsList ] );
+
+#! @Arguments presheaf, lists_of_indices
+DeclareOperation( "IsClosedPreSheafWRTCoproductsByIndices",
+ [ IsObjectInPreSheafCategory, IsList ] );
+
+#! @Arguments presheaf, coproduct_cocone
+DeclareOperation( "EmbeddingIntoClosureOfPreSheafWRTCoproductCocone",
+ [ IsObjectInPreSheafCategory, IsList ] );
+
+#! @Arguments presheaf, coproducts_cocones
+DeclareOperation( "EmbeddingIntoClosureOfPreSheafWRTCoproductCocones",
+ [ IsObjectInPreSheafCategory, IsList ] );
+
+#! @Arguments presheaf, lists_of_coproduct_cofactors
+DeclareOperation( "EmbeddingIntoClosureOfPreSheafWRTCoproducts",
+ [ IsObjectInPreSheafCategory, IsList ] );
+
+#! @Arguments PSh, coproducts_cocones
+DeclareOperation( "ClosureOfPreSheavesWRTCoproductCocones",
+ [ IsPreSheafCategoryOfFpEnrichedCategory, IsList ] );
+
+#! @Arguments PSh, lists_of_coproduct_cofactors
+DeclareOperation( "ClosureOfPreSheavesWRTCoproducts",
+ [ IsPreSheafCategoryOfFpEnrichedCategory, IsList ] );
diff --git a/FunctorCategories/gap/ClosedPreSheavesWRTColimitingCocones.gi b/FunctorCategories/gap/ClosedPreSheavesWRTColimitingCocones.gi
new file mode 100644
index 000000000..ea408337d
--- /dev/null
+++ b/FunctorCategories/gap/ClosedPreSheavesWRTColimitingCocones.gi
@@ -0,0 +1,702 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# FunctorCategories: Categories of functors
+#
+# Implementations
+#
+
+##
+InstallMethod( ClosedPreSheavesWRTCoproductCocones,
+ "for a category and a list of coproduct cocones",
+ [ IsCapCategory, IsList ],
+
+ function ( C, coproduct_cocones )
+ local H,
+ object_datum_type, object_constructor, object_datum,
+ morphism_datum_type, morphism_constructor, morphism_datum,
+ PSh, eta, Kleisli,
+ modeling_tower_object_constructor, modeling_tower_object_datum,
+ modeling_tower_morphism_constructor, modeling_tower_morphism_datum,
+ PSh_J;
+
+ if not ( ForAll( coproduct_cocones, IsList ) and
+ ForAll( coproduct_cocones, pair -> IsCapCategoryObject( pair[1] ) and IsIdenticalObj( C, CapCategory( pair[1] ) ) ) and
+ ForAll( coproduct_cocones, pair -> ForAll( pair[2], mor -> IsCapCategoryMorphism( mor ) and IsIdenticalObj( C, CapCategory( mor ) ) ) ) ) then
+
+ Error( "the second argument `coproduct_cocones` must be a list of pairs, ",
+ "where the first entry of the pair is an object in the category `C` and ",
+ "the second entry a list of morphisms in `C`" );
+
+ fi;
+
+ H := RangeCategoryOfHomomorphismStructure( C );
+
+ ##
+ object_datum_type :=
+ CapJitDataTypeOfNTupleOf( 2,
+ CapJitDataTypeOfListOf( CapJitDataTypeOfObjectOfCategory( H ) ),
+ CapJitDataTypeOfListOf( CapJitDataTypeOfMorphismOfCategory( H ) ) );
+
+ ##
+ object_constructor :=
+ function( PSh_J, pair )
+
+ return CreateCapCategoryObjectWithAttributes( PSh_J,
+ Source, Source( PSh_J ),
+ Target, Target( PSh_J ),
+ AsPrimitiveValue, pair );
+
+ end;
+
+ ##
+ object_datum := { PSh_J, o } -> AsPrimitiveValue( o );
+
+ ##
+ morphism_datum_type :=
+ CapJitDataTypeOfListOf( CapJitDataTypeOfMorphismOfCategory( H ) );
+
+ ##
+ morphism_constructor :=
+ function( PSh_J, source, components, target )
+
+ return CreateCapCategoryMorphismWithAttributes( PSh_J,
+ source,
+ target,
+ AsPrimitiveValue, components );
+
+ end;
+
+ ##
+ morphism_datum := { PSh_J, m } -> AsPrimitiveValue( m );
+
+ ## building the categorical tower:
+
+ PSh := PreSheaves( C : FinalizeCategory := true );
+
+ eta := ClosureOfPreSheavesWRTCoproductCocones( PSh, coproduct_cocones );
+
+ Kleisli := KleisliReflectiveSubcategoryOfIdempotentMonad( eta :
+ properties := [ "IsFiniteBicompleteCategory" ],
+ additional_operations_to_install := CAP_INTERNAL_CONSTRUCTIVE_CATEGORIES_RECORD.IsCartesianCategory,
+ supports_empty_limits := true,
+ FinalizeCategory := false );
+
+ AddCoproduct( Kleisli,
+ function( Kleisli, list_of_cofactors )
+ local PSh, coproduct, closure;
+
+ PSh := AmbientCategory( Kleisli );
+
+ coproduct := Coproduct( PSh,
+ List( list_of_cofactors, cofactor ->
+ ObjectDatum( Kleisli, cofactor ) ) );
+
+ closure := Target( EmbeddingIntoClosureOfPreSheafWRTCoproductCocones( PSh, coproduct, coproduct_cocones ) );
+
+ return ObjectConstructor( Kleisli,
+ closure );
+
+ end );
+
+ ## TODO:
+ ## AddInjectionOfCofactorOfCoproductWithGivenCoproduct
+ ## AddUniversalMorphismFromCoproductWithGivenCoproduct
+
+ Finalize( Kleisli : FinalizeCategory := true );
+
+ ## from the raw object data to the object in the modeling category
+ modeling_tower_object_constructor :=
+ function( PSh_J, pair )
+ local Kleisli, PSh;
+
+ Kleisli := ModelingCategory( PSh_J );
+
+ PSh := AmbientCategory( Kleisli );
+
+ return ObjectConstructor( Kleisli,
+ ObjectConstructor( PSh,
+ pair ) );
+
+ end;
+
+ ## from the object in the modeling category to the raw object data
+ modeling_tower_object_datum :=
+ function( PSh_J, obj )
+ local Kleisli, PSh;
+
+ Kleisli := ModelingCategory( PSh_J );
+
+ PSh := AmbientCategory( Kleisli );
+
+ return ObjectDatum( PSh,
+ ObjectDatum( Kleisli,
+ obj ) );
+
+ end;
+
+ ## from the raw morphism data to the morphism in the modeling category
+ modeling_tower_morphism_constructor :=
+ function( PSh_J, source, images, target )
+ local Kleisli, PSh;
+
+ Kleisli := ModelingCategory( PSh_J );
+
+ PSh := AmbientCategory( Kleisli );
+
+ return MorphismConstructor( Kleisli,
+ source,
+ MorphismConstructor( PSh,
+ ObjectDatum( Kleisli, source ),
+ images,
+ ObjectDatum( Kleisli, target ) ),
+ target );
+
+ end;
+
+ ## from the morphism in the modeling category to the raw morphism data
+ modeling_tower_morphism_datum :=
+ function( PSh_J, mor )
+ local Kleisli, PSh;
+
+ Kleisli := ModelingCategory( PSh_J );
+
+ PSh := AmbientCategory( Kleisli );
+
+ return MorphismDatum( PSh,
+ MorphismDatum( Kleisli,
+ mor ) );
+
+ end;
+
+ ##
+ PSh_J :=
+ ReinterpretationOfCategory( Kleisli,
+ rec( name := Concatenation( "ClosedPreSheavesWRTCoproductCocones( ", Name( C ), ", coproduct_cocones )" ),
+ category_filter := IsClosedPreSheavesWRTColimitingCocones,
+ category_object_filter := IsObjectInClosedPreSheavesWRTColimitingCocones,
+ category_morphism_filter := IsMorphismInClosedPreSheavesWRTColimitingCocones,
+ object_datum_type := object_datum_type,
+ morphism_datum_type := morphism_datum_type,
+ object_constructor := object_constructor,
+ object_datum := object_datum,
+ morphism_constructor := morphism_constructor,
+ morphism_datum := morphism_datum,
+ modeling_tower_object_constructor := modeling_tower_object_constructor,
+ modeling_tower_object_datum := modeling_tower_object_datum,
+ modeling_tower_morphism_constructor := modeling_tower_morphism_constructor,
+ modeling_tower_morphism_datum := modeling_tower_morphism_datum,
+ only_primitive_operations := true )
+ : FinalizeCategory := false );
+
+ SetSource( PSh_J, C );
+ SetTarget( PSh_J, Target( PSh ) );
+ SetUnderlyingColimitingCocones( PSh_J, coproduct_cocones );
+
+ #if CanCompute( Kleisli, "SetOfObjectsOfCategory" ) then
+ #
+ # ## add a potentially slower method, but that does not need to generate all objects in PSh
+ # AddSetOfObjectsOfCategory( PSh_J,
+ # function( PSh_J )
+ # local C, Yoneda, representables, joins;
+ #
+ # C := Source( PSh_J );
+ #
+ # ## the Yoneda embedding: C ↪ PSh_J( C )
+ # Yoneda := YonedaEmbeddingDataOfSourceCategory( PSh_J );
+ #
+ # representables := List( SetOfObjects( C ), Yoneda[1] );
+ #
+ # representables := Filtered( representables, representable -> not IsInitial( PSh_J, representable ) );
+ #
+ # joins := AllCoproducts( PSh_J, representables );
+ #
+ # return List( Concatenation( joins ), entry -> entry[2] );
+ #
+ # end );
+ #
+ #fi;
+
+ Append( PSh_J!.compiler_hints.category_attribute_names,
+ [ "Source",
+ "Target",
+ "UnderlyingColimitingCocones" ] );
+
+ Finalize( PSh_J );
+
+ return PSh_J;
+
+end );
+
+##
+InstallMethod( ClosedPreSheavesWRTCoproducts,
+ "for a category and a list of coproduct cocones",
+ [ IsCapCategory, IsList ],
+
+ function ( C, lists_of_coproduct_cofactors )
+
+ return ClosedPreSheavesWRTCoproductCocones( C, CoconesOfCoproducts( C, lists_of_coproduct_cofactors ) );
+
+end );
+
+##
+InstallMethod( ClosedPreSheavesWRTCoproductsByIndices,
+ "for a category and a list of coproduct cocones",
+ [ IsCapCategory, IsList ],
+
+ function ( C, lists_of_coproduct_cofactors_by_indices )
+
+ return ClosedPreSheavesWRTCoproductCocones( C, CoconesOfCoproductsByIndices( C, lists_of_coproduct_cofactors_by_indices ) );
+
+end );
+
+##
+InstallMethod( \.,
+ "for the category of closed presheaves with respect to colimiting cocones and a positive integer",
+ [ IsClosedPreSheavesWRTColimitingCocones, IsPosInt ],
+
+ function( PSh_J, string_as_int )
+ local name, Kleisli, c;
+
+ name := NameRNam( string_as_int );
+
+ Kleisli := ModelingCategory( PSh_J );
+
+ c := Kleisli.(name);
+
+ if IsCapCategoryObject( c ) and IsIdenticalObj( CapCategory( c ), Kleisli ) then
+
+ return ReinterpretationOfObject( PSh_J, c );
+
+ elif IsCapCategoryMorphism( c ) and IsIdenticalObj( CapCategory( c ), Kleisli ) then
+
+ return ReinterpretationOfMorphism( PSh_J,
+ ReinterpretationOfObject( PSh_J, Source( c ) ),
+ c,
+ ReinterpretationOfObject( PSh_J, Target( c ) ) );
+
+ else
+
+ Error( "`c` is neither an object nor a morphism in the Kleisli category `Kleisli`\n" );
+
+ fi;
+
+end );
+
+##
+InstallMethodForCompilerForCAP( SetOfObjects,
+ "for the category of closed presheaves with respect to colimiting cocones",
+ [ IsClosedPreSheavesWRTColimitingCocones ],
+
+ function( cat )
+
+ return SetOfObjectsOfCategory( cat );
+
+end );
+
+##
+InstallMethodForCompilerForCAP( SetOfGeneratingMorphisms,
+ "for the category of closed presheaves with respect to colimiting cocones",
+ [ IsClosedPreSheavesWRTColimitingCocones ],
+
+ function( cat )
+
+ return SetOfGeneratingMorphismsOfCategory( cat );
+
+end );
+
+##
+InstallMethodForCompilerForCAP( YonedaEmbeddingDataOfSourceCategory,
+ "for a category of closed presheaves w.r.t. colimiting cocones",
+ [ IsClosedPreSheavesWRTColimitingCocones ],
+
+ function ( PSh_J )
+ local C, yoneda_data, Yoneda_on_objs, Yoneda_on_mors;
+
+ C := Source( PSh_J );
+
+ yoneda_data := YonedaEmbeddingData( C );
+
+ Yoneda_on_objs :=
+ function ( obj )
+
+ return ObjectConstructor( PSh_J,
+ yoneda_data[1]( obj ) );
+
+ end;
+
+ Yoneda_on_mors :=
+ function ( source, mor, target )
+ local source_on_objs, target_on_objs;
+
+ Error( "not implemented yet" );
+
+ source_on_objs := ObjectDatum( PSh_J, source )[1];
+ target_on_objs := ObjectDatum( PSh_J, target )[1];
+
+ return MorphismConstructor( PSh_J,
+ source,
+ yoneda_data[2]( source_on_objs, mor, target_on_objs ),
+ target );
+
+ end;
+
+ return Pair( Yoneda_on_objs, Yoneda_on_mors );
+
+end );
+
+##
+InstallMethod( YonedaEmbeddingOfSourceCategory,
+ "for a category of closed presheaves w.r.t. colimiting cocones",
+ [ IsClosedPreSheavesWRTColimitingCocones ],
+
+ function ( PSh_J )
+ local C, Yoneda, Yoneda_data;
+
+ C := Source( PSh_J );
+
+ Yoneda := CapFunctor( "Yoneda embedding functor", C, PSh_J );
+
+ Yoneda_data := YonedaEmbeddingDataOfSourceCategory( PSh_J );
+
+ AddObjectFunction( Yoneda, Yoneda_data[1] );
+
+ AddMorphismFunction( Yoneda, Yoneda_data[2] );
+
+ return Yoneda;
+
+end );
+
+####################################
+#
+# Methods for operations
+#
+####################################
+
+##
+InstallOtherMethodForCompilerForCAP( IsClosedPreSheafWRTCoproductCocones,
+ [ IsPreSheafCategory, IsObjectInPreSheafCategory, IsList ],
+
+ function( PSh, presheaf, list_of_coproduct_cones )
+ local H, coproducts, cocones;
+
+ H := Target( PSh );
+
+ coproducts := List( list_of_coproduct_cones, cocone -> cocone[1] );
+ cocones := List( list_of_coproduct_cones, cocone -> cocone[2] );
+
+ return ForAll( [ 1 .. Length( coproducts ) ], i ->
+ IsIsomorphism( H,
+ UniversalMorphismIntoDirectProduct( H,
+ List( cocones[i], morphism ->
+ ApplyObjectInPreSheafCategoryOfFpEnrichedCategoryToObject( PSh, presheaf, Source( morphism ) ) ),
+ ApplyObjectInPreSheafCategoryOfFpEnrichedCategoryToObject( PSh, presheaf, coproducts[i] ),
+ List( cocones[i], morphism ->
+ ApplyObjectInPreSheafCategoryOfFpEnrichedCategoryToMorphism( PSh, presheaf, morphism ) ) ) ) );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( IsClosedPreSheafWRTCoproducts,
+ [ IsPreSheafCategory and IsThinCategory, IsObjectInPreSheafCategory, IsList ],
+
+ function( PSh, presheaf, lists_of_coproduct_cofactors )
+ local list_of_coproduct_cones;
+
+ list_of_coproduct_cones := CoconesOfCoproducts( Source( PSh ), lists_of_coproduct_cofactors );
+
+ return IsClosedPreSheafWRTCoproductCocones( PSh, presheaf, list_of_coproduct_cones );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( IsClosedPreSheafWRTCoproductsByIndices,
+ [ IsPreSheafCategory and IsThinCategory, IsObjectInPreSheafCategory, IsList ],
+
+ function( PSh, presheaf, lists_of_coproduct_cofactors_by_indices )
+ local lists_of_coproduct_cofactors;
+
+ lists_of_coproduct_cofactors := CoconesOfCoproductsByIndices( Source( PSh ), lists_of_coproduct_cofactors_by_indices );
+
+ return IsClosedPreSheafWRTCoproducts( PSh, presheaf, lists_of_coproduct_cofactors );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( EmbeddingIntoClosureOfPreSheafWRTCoproductCocone,
+ [ IsPreSheafCategory, IsObjectInPreSheafCategory, IsList ],
+
+ function( PSh, presheaf, coproduct_cocone )
+ local C, H, C_hat, ColimitQuiversC, objects, id_objects,
+ colim_quiver_of_presheaf, vertices_arrows, vertices, arrows, v, vertices_indices,
+ coproduct, id_coproduct, c, coproduct_index, coproduct_indices_in_vertices,
+ cocone, l, diagram, diagram_indices, diagram_indices_in_vertices,
+ direct_product_diagram, direct_product, universal_morphism, universal_map, projection_morphisms, projection_maps,
+ d, additional_vertices, additional_arrows_in, additional_arrows_out, closure_of_colim_quiver_of_presheaf, embedding;
+
+ ## categories
+ C := Source( PSh );
+ H := Target( PSh );
+
+ C_hat := FiniteColimitCompletionWithStrictCoproductsOfSourceCategory( PSh );
+
+ ColimitQuiversC := CategoryOfColimitQuiversOfSourceCategory( PSh );
+
+ objects := SetOfObjects( C );
+
+ id_objects := List( objects, o -> IdentityMorphism( C, o ) );
+
+ ## presheaf
+ colim_quiver_of_presheaf := AssociatedColimitQuiver( C_hat, CoYonedaLemmaOnObjects( presheaf ) );
+
+ vertices_arrows := ObjectDatum( ColimitQuiversC, colim_quiver_of_presheaf );
+
+ vertices := vertices_arrows[1];
+ arrows := vertices_arrows[2];
+
+ v := Length( vertices );
+
+ vertices_indices := List( vertices, vertex -> -1 + SafeUniquePositionProperty( objects, o -> IsEqualForObjects( C, vertex, o ) ) );
+
+ ## coproduct
+ coproduct := coproduct_cocone[1];
+
+ id_coproduct := IdentityMorphism( C, coproduct );
+
+ c := presheaf( coproduct );
+
+ coproduct_index := -1 + SafeUniquePositionProperty( objects, o -> IsEqualForObjects( C, coproduct_cocone[1], o ) );
+
+ coproduct_indices_in_vertices := Positions( vertices_indices, coproduct_index );
+
+ ## cocone
+ cocone := coproduct_cocone[2];
+
+ l := Length( cocone );
+
+ ## diagram
+ diagram := List( cocone, Source );
+
+ diagram_indices := List( diagram, obj ->
+ -1 + SafeUniquePositionProperty( objects, o -> IsEqualForObjects( C, obj, o ) ) );
+
+ diagram_indices_in_vertices := List( diagram_indices, i -> Positions( vertices_indices, i ) );
+
+ ## direct product
+ direct_product_diagram := List( diagram, presheaf );
+
+ direct_product := DirectProduct( H, direct_product_diagram );
+
+ universal_morphism := UniversalMorphismIntoDirectProductWithGivenDirectProduct( H,
+ direct_product_diagram,
+ c,
+ List( cocone, presheaf ),
+ direct_product );
+
+ universal_map := MorphismDatum( H, universal_morphism );
+
+ projection_morphisms := List( [ 1 .. l ], p ->
+ ProjectionInFactorOfDirectProductWithGivenDirectProduct( H,
+ direct_product_diagram,
+ p,
+ direct_product ) );
+
+ projection_maps := List( [ 1 .. l ], p -> AsList( projection_morphisms[p] ) );
+
+ d := Length( direct_product );
+
+ ## closure of colimit quiver of presheaf
+ additional_vertices := ListWithIdenticalEntries( d, coproduct );
+
+ additional_arrows_in := List( [ 0 .. Length( c ) - 1 ], i ->
+ Triple( v + universal_map[1 + i], id_coproduct, -1 + coproduct_indices_in_vertices[1 + i] ) );
+
+ additional_arrows_out := List( [ 1 .. l ], p ->
+ List( [ 0 .. d - 1 ], i ->
+ Triple( -1 + diagram_indices_in_vertices[p][1 + projection_maps[p][1 + i]], cocone[p], v + i ) ) );
+
+ closure_of_colim_quiver_of_presheaf := CreateColimitQuiver( ColimitQuiversC,
+ Pair( Concatenation( vertices, additional_vertices ),
+ Concatenation( arrows, additional_arrows_in, Concatenation( additional_arrows_out ) ) ) );
+
+ embedding := CreateMorphismOfColimitQuivers( ColimitQuiversC,
+ colim_quiver_of_presheaf,
+ Pair( Pair( [ 0 .. v - 1 ], id_objects{1 + vertices_indices} ),
+ [ 0 .. Length( arrows ) - 1 ] ),
+ closure_of_colim_quiver_of_presheaf );
+
+ return AssociatedCellInPreSheaves( ColimitQuiversC, embedding );
+
+end );
+
+##
+InstallMethod( EmbeddingIntoClosureOfPreSheafWRTCoproductCocone,
+ [ IsObjectInPreSheafCategory, IsList ],
+
+ function( presheaf, coproduct_cocone )
+
+ return EmbeddingIntoClosureOfPreSheafWRTCoproductCocone( CapCategory( presheaf ), presheaf, coproduct_cocone );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( EmbeddingIntoClosureOfPreSheafWRTCoproductCocones,
+ [ IsPreSheafCategory, IsObjectInPreSheafCategory, IsList ],
+
+ function( PSh, presheaf, coproduct_cocones )
+ local func, emb;
+
+ func :=
+ function( embedding, cocone )
+ return PreCompose( PSh,
+ embedding,
+ EmbeddingIntoClosureOfPreSheafWRTCoproductCocone( PSh,
+ Target( embedding ),
+ cocone ) );
+ end;
+
+ emb := Iterated( coproduct_cocones,
+ func,
+ IdentityMorphism( PSh, presheaf ) );
+
+ #% CAP_JIT_DROP_NEXT_STATEMENT
+ Assert( 0, IsClosedPreSheafWRTCoproductCocones( PSh, Target( emb ), coproduct_cocones ) );
+
+ return emb;
+
+end );
+
+##
+InstallMethod( EmbeddingIntoClosureOfPreSheafWRTCoproductCocones,
+ [ IsObjectInPreSheafCategory, IsList ],
+
+ function( presheaf, coproduct_cocones )
+
+ return EmbeddingIntoClosureOfPreSheafWRTCoproductCocones( CapCategory( presheaf ), presheaf, coproduct_cocones );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( EmbeddingIntoClosureOfPreSheafWRTCoproducts,
+ [ IsPreSheafCategory and IsThinCategory, IsObjectInPreSheafCategory, IsList ],
+
+ function( PSh, presheaf, lists_of_coproduct_cofactors )
+ local list_of_coproduct_cones;
+
+ list_of_coproduct_cones := CoconesOfCoproducts( Source( PSh ), lists_of_coproduct_cofactors );
+
+ return EmbeddingIntoClosureOfPreSheafWRTCoproductCocones( PSh, presheaf, list_of_coproduct_cones );
+
+end );
+
+##
+InstallMethod( EmbeddingIntoClosureOfPreSheafWRTCoproducts,
+ [ IsObjectInPreSheafCategory, IsList ],
+
+ function( presheaf, lists_of_coproduct_cofactors )
+
+ return EmbeddingIntoClosureOfPreSheafWRTCoproducts( CapCategory( presheaf ), presheaf, lists_of_coproduct_cofactors );
+
+end );
+
+##
+InstallMethod( ClosureOfPreSheavesWRTCoproductCocones,
+ [ IsPreSheafCategoryOfFpEnrichedCategory, IsList ],
+
+ function( PSh, coproducts_cocones )
+ local Id_PSh, ClosureMonad, UnitOfClosureMonad;
+
+ Id_PSh := IdentityFunctor( PSh );
+
+ ClosureMonad := CapFunctor( "Closure idempotent monad with respect to coproduct cocones", PSh, PSh );
+
+ AddObjectFunction( ClosureMonad,
+ function( object )
+
+ return Target( EmbeddingIntoClosureOfPreSheafWRTCoproductCocones( PSh, object, coproducts_cocones ) );
+
+ end );
+
+ AddMorphismFunction( ClosureMonad,
+ function( source, morphism, target )
+
+ Error( "not implemented yet\n" );
+
+ end );
+
+ ClosureMonad!.ObjectMembershipFunction := presheaf -> IsClosedPreSheafWRTCoproductCocones( PSh, presheaf, coproducts_cocones );
+
+ UnitOfClosureMonad := NaturalTransformation( Id_PSh, ClosureMonad );
+
+ AddNaturalTransformationFunction( UnitOfClosureMonad,
+ function( source, object, target )
+
+ return EmbeddingIntoClosureOfPreSheafWRTCoproductCocones( PSh, object, coproducts_cocones );
+
+ end );
+
+ return UnitOfClosureMonad;
+
+end );
+
+##
+InstallMethod( ClosureOfPreSheavesWRTCoproducts,
+ [ IsPreSheafCategoryOfFpEnrichedCategory, IsList ],
+
+ function( PSh, lists_of_coproduct_cofactors )
+
+ return ClosureOfPreSheavesWRTCoproductCocones( PSh, CoconesOfCoproducts( Source( PSh ), lists_of_coproduct_cofactors ) );
+
+end );
+
+##################################
+##
+## View & Display
+##
+##################################
+
+##
+InstallMethod( ViewObj,
+ [ IsObjectInClosedPreSheavesWRTColimitingCocones ],
+
+ function( a )
+
+ Print( "An object in category of closed presheaves given by: " );
+
+ ViewObj( ObjectDatum( CapCategory( a ), a ) );
+
+end );
+
+##
+InstallMethod( ViewObj,
+ [ IsMorphismInClosedPreSheavesWRTColimitingCocones ],
+
+ function( phi )
+
+ Print( "A morphism in category of closed presheaves given by: " );
+
+ ViewObj( MorphismDatum( CapCategory( phi ), phi ) );
+
+end );
+
+##
+InstallMethod( Display,
+ [ IsObjectInClosedPreSheavesWRTColimitingCocones ],
+
+ function( a )
+
+ Display( ObjectDatum( CapCategory( a ), a ) );
+
+ Display( "\nAn object in category of closed presheaves given by the above data" );
+
+end );
+
+##
+InstallMethod( Display,
+ [ IsMorphismInClosedPreSheavesWRTColimitingCocones ],
+
+ function( phi )
+
+ Display( MorphismDatum( CapCategory( phi ), phi ) );
+
+ Display( "A morphism in category of closed presheaves given by the above data" );
+
+end );
diff --git a/FunctorCategories/gap/FreeDistributiveCompletion.gd b/FunctorCategories/gap/FreeDistributiveCompletion.gd
index 873c68b28..bf66a3dcb 100644
--- a/FunctorCategories/gap/FreeDistributiveCompletion.gd
+++ b/FunctorCategories/gap/FreeDistributiveCompletion.gd
@@ -4,7 +4,7 @@
# Declarations
#
-#! @Chapter Free distributive completion of a finitely presented (linear) category
+#! @Chapter Free distributive completion of a finitely presented category
####################################
#
diff --git a/FunctorCategories/gap/PreSheaves.gd b/FunctorCategories/gap/PreSheaves.gd
index 7791785ab..a627e42a8 100644
--- a/FunctorCategories/gap/PreSheaves.gd
+++ b/FunctorCategories/gap/PreSheaves.gd
@@ -393,6 +393,10 @@ DeclareAttribute( "CoequalizerDataOfPreSheafUsingOptimizedCoYonedaLemma",
DeclareAttribute( "AssociatedCoequalizerPairInPreSheaves",
IsObjectInCategoryOfColimitQuivers );
+#! @Arguments F
+DeclareAttribute( "AssociatedCellInPreSheaves",
+ IsCellInCategoryOfColimitQuivers );
+
#! @Arguments F
DeclareAttribute( "AssociatedCoequalizerPairInPreSheaves",
IsObjectInFiniteColimitCompletionWithStrictCoproducts );
diff --git a/FunctorCategories/gap/PreSheaves.gi b/FunctorCategories/gap/PreSheaves.gi
index fb676bd42..a7e6bc663 100644
--- a/FunctorCategories/gap/PreSheaves.gi
+++ b/FunctorCategories/gap/PreSheaves.gi
@@ -306,13 +306,24 @@ InstallMethodWithCache( PreSheavesOfFpEnrichedCategory,
[ IsCapCategory, IsCapCategory ],
function ( B, D )
- local B_op, kq, A, relations, name, list_of_operations,
+ local object_datum_type, morphism_datum_type, is_computable,
+ B_op, kq, A, relations, name, list_of_operations,
object_constructor, object_datum, morphism_constructor, morphism_datum,
create_func_bool, create_func_object, create_func_morphism,
list_of_operations_to_install, skip, commutative_ring,
properties, supports_empty_limits, prop, option_record,
PSh, H, auxiliary_indices;
+ object_datum_type :=
+ CapJitDataTypeOfNTupleOf( 2,
+ CapJitDataTypeOfListOf( CapJitDataTypeOfObjectOfCategory( D ) ),
+ CapJitDataTypeOfListOf( CapJitDataTypeOfMorphismOfCategory( D ) ) );
+
+ morphism_datum_type :=
+ CapJitDataTypeOfListOf( CapJitDataTypeOfMorphismOfCategory( D ) );
+
+ is_computable := IsBound( D!.is_computable ) and D!.is_computable;
+
if IsFpCategory( B ) then
B_op := OppositeFpCategory( B : FinalizeCategory := true );
kq := UnderlyingQuiverAlgebra( B_op );
@@ -326,6 +337,8 @@ InstallMethodWithCache( PreSheavesOfFpEnrichedCategory,
B_op := OppositeCategoryFromNerveData( B : FinalizeCategory := true );
elif IsCategoryFromDataTables( B ) then
B_op := OppositeCategoryFromDataTables( B : FinalizeCategory := true );
+ elif WasCreatedAsOppositeCategory( B ) then
+ B_op := OppositeCategory( B );
elif HasIsFiniteCategory( B ) and IsFiniteCategory( B ) then
B_op := OppositeFiniteCategory( B : FinalizeCategory := true );
elif IsAlgebroid( B ) then
@@ -776,17 +789,20 @@ InstallMethodWithCache( PreSheavesOfFpEnrichedCategory,
category_filter := IsPreSheafCategoryOfFpEnrichedCategory,
category_object_filter := IsObjectInPreSheafCategoryOfFpEnrichedCategory,
category_morphism_filter := IsMorphismInPreSheafCategoryOfFpEnrichedCategory,
- supports_empty_limits := supports_empty_limits,
- list_of_operations_to_install := list_of_operations_to_install,
+ object_datum_type := object_datum_type,
+ morphism_datum_type := morphism_datum_type,
properties := properties,
object_constructor := object_constructor,
object_datum := object_datum,
morphism_constructor := morphism_constructor,
morphism_datum := morphism_datum,
+ list_of_operations_to_install := list_of_operations_to_install,
+ is_computable := is_computable,
+ supports_empty_limits := supports_empty_limits,
+ underlying_category_getter_string := "Target",
create_func_bool := create_func_bool,
create_func_object := create_func_object,
create_func_morphism := create_func_morphism,
- underlying_category_getter_string := "Target"
);
if not commutative_ring = fail then
@@ -2741,6 +2757,13 @@ InstallMethodForCompilerForCAP( ApplyObjectInPreSheafCategoryOfFpEnrichedCategor
OppositeAlgebraElement( UnderlyingQuiverAlgebraElement( morB ) ),
SetOfObjects( B_op )[VertexIndex( UnderlyingVertex( Source( morB ) ) )] );
+ elif WasCreatedAsOppositeCategory( B ) then
+
+ morB_op := MorphismConstructor( B_op,
+ SetOfObjects( B_op )[SafeUniquePositionProperty( SetOfObjects( B ), obj -> IsEqualForObjects( B, obj, Target( morB ) ) )],
+ MorphismDatum( B_op, MorphismDatum( B, morB ) ),
+ SetOfObjects( B_op )[SafeUniquePositionProperty( SetOfObjects( B ), obj -> IsEqualForObjects( B, obj, Source( morB ) ) )] );
+
else
morB_op := MorphismConstructor( B_op,
@@ -3239,6 +3262,80 @@ InstallMethod( AssociatedCoequalizerPairInPreSheaves,
end );
+##
+InstallOtherMethodForCompilerForCAP( AssociatedCellInPreSheaves,
+ "for a category of colimit quivers and an object therein",
+ [ IsCategoryOfColimitQuivers, IsObjectInCategoryOfColimitQuivers ],
+
+ function( ColimitQuiversC, colimit_quiver )
+ local PSh, coequalizer_pair;
+
+ PSh := CategoryOfPreSheavesOfUnderlyingCategory( ColimitQuiversC );
+
+ coequalizer_pair := AssociatedCoequalizerPairInPreSheaves( ColimitQuiversC, colimit_quiver );
+
+ return Coequalizer( PSh, coequalizer_pair[1], coequalizer_pair[2] );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( AssociatedCellInPreSheaves,
+ "for a category of colimit quivers, two objects and a morphism therein",
+ [ IsCategoryOfColimitQuivers, IsObjectInPreSheafCategoryOfFpEnrichedCategory, IsMorphismInCategoryOfColimitQuivers, IsObjectInPreSheafCategoryOfFpEnrichedCategory ],
+
+ function( ColimitQuiversC, source, colimit_quiver_morphism, target )
+ local ParallelPairs, PSh_VA, mor_VA, S, T, V, A, PSh, Yoneda, Y_V, Y_A;
+
+ ParallelPairs := ModelingCategory( ColimitQuiversC );
+
+ PSh_VA := ModelingCategory( ParallelPairs );
+
+ mor_VA := MorphismDatum( PSh_VA,
+ ModelingMorphism( ParallelPairs,
+ ModelingMorphism( ColimitQuiversC, colimit_quiver_morphism ) ) );
+
+ V := mor_VA[1];
+
+ PSh := CategoryOfPreSheavesOfUnderlyingCategory( ColimitQuiversC );
+
+ Yoneda := EmbeddingFunctorOfFiniteStrictCoproductCompletionIntoPreSheavesData( PSh )[2];
+
+ Y_V := Yoneda[2]( Yoneda[1]( Source( V ) ), V, Yoneda[1]( Target( V ) ) );
+
+ return CoequalizerFunctorialWithGivenCoequalizers( PSh,
+ source,
+ AssociatedCoequalizerPairInPreSheaves( ColimitQuiversC, Source( colimit_quiver_morphism ) )[2],
+ Y_V,
+ AssociatedCoequalizerPairInPreSheaves( ColimitQuiversC, Target( colimit_quiver_morphism ) )[2],
+ target );
+
+end );
+
+##
+InstallOtherMethod( AssociatedCellInPreSheaves,
+ "for a category of colimit quivers and an morphism therein",
+ [ IsCategoryOfColimitQuivers, IsMorphismInCategoryOfColimitQuivers ],
+
+ function( ColimitQuiversC, colimit_quiver_morphism )
+
+ return AssociatedCellInPreSheaves( ColimitQuiversC,
+ AssociatedCellInPreSheaves( Source( colimit_quiver_morphism ) ),
+ colimit_quiver_morphism,
+ AssociatedCellInPreSheaves( Target( colimit_quiver_morphism ) ) );
+
+end );
+
+##
+InstallOtherMethod( AssociatedCellInPreSheaves,
+ "for a category of colimit quivers and a cell therein",
+ [ IsCellInCategoryOfColimitQuivers ],
+
+ function( colimit_quiver_cell )
+
+ return AssociatedCellInPreSheaves( CapCategory( colimit_quiver_cell ), colimit_quiver_cell );
+
+end );
+
##
InstallOtherMethodForCompilerForCAP( AssociatedCoequalizerPairInPreSheaves,
"for the finite colimit completion of a category and an object therein",
diff --git a/FunctorCategories/gap/Tools.gd b/FunctorCategories/gap/Tools.gd
index 510b1c0ce..479573fc5 100644
--- a/FunctorCategories/gap/Tools.gd
+++ b/FunctorCategories/gap/Tools.gd
@@ -72,3 +72,25 @@ end );
#! @Arguments F
DeclareProperty( "IsReflexive",
IsCapCategoryObject );
+
+###################################
+##
+#! @Section Operations
+##
+###################################
+
+#! @Arguments PSh, lists_of_cofactors
+DeclareOperation( "CoconesOfCoproducts",
+ [ IsCapCategory, IsList ] );
+
+#! @Arguments PSh, lists_of_cofactors_by_indices
+DeclareOperation( "CoconesOfCoproductsByIndices",
+ [ IsCapCategory, IsList ] );
+
+#! @Arguments PSh, lists_of_factors
+DeclareOperation( "ConesOfProducts",
+ [ IsCapCategory, IsList ] );
+
+#! @Arguments PSh, lists_of_factors_by_indices
+DeclareOperation( "ConesOfProductsByIndices",
+ [ IsCapCategory, IsList ] );
diff --git a/FunctorCategories/gap/Tools.gi b/FunctorCategories/gap/Tools.gi
index f6afe3f24..13d4e616d 100644
--- a/FunctorCategories/gap/Tools.gi
+++ b/FunctorCategories/gap/Tools.gi
@@ -13,3 +13,79 @@ InstallOtherMethod( QUO,
return HomalgMatrix( mat, CommutativeRingOfLinearCategory( A ) ) / A;
end );
+
+##
+InstallOtherMethodForCompilerForCAP( CoconesOfCoproducts,
+ [ IsCapCategory and IsThinCategory, IsList ],
+
+ function( P, list_of_coproducts )
+ local coproducts, cocones;
+
+ if not CanCompute( P, "UniqueMorphism" ) then
+ Error( "the poset `P` cannot compute the categorical operation `UniqueMorphism`\n" );
+ fi;
+
+ coproducts := List( list_of_coproducts, cocone -> cocone[1] );
+ cocones := List( list_of_coproducts, cocone -> List( cocone[2], cofactor -> UniqueMorphism( P, cofactor, cocone[1] ) ) );
+
+ return ListN( coproducts, cocones, { coproduct, cocone } -> [ coproduct, cocone ] );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( CoconesOfCoproductsByIndices,
+ [ IsCapCategory and IsThinCategory, IsList ],
+
+ function( P, list_of_coproducts_by_indices )
+ local offset, objects, coproducts, cofactors, list_of_coproducts;
+
+ offset := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "offset", 0 );
+
+ objects := SetOfObjects( P );
+
+ coproducts := List( list_of_coproducts_by_indices, cocone -> objects[offset + cocone[1]] );
+ cofactors := List( list_of_coproducts_by_indices, cocone -> List( cocone[2], i -> objects[offset + i] ) );
+
+ list_of_coproducts := ListN( coproducts, cofactors, { coproduct, cofactor } -> [ coproduct, cofactor ] );
+
+ return CoconesOfCoproducts( P, list_of_coproducts );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( ConesOfProducts,
+ [ IsCapCategory and IsThinCategory, IsList ],
+
+ function( P, list_of_products )
+ local products, cones;
+
+ if not CanCompute( P, "UniqueMorphism" ) then
+ Error( "the poset `P` cannot compute the categorical operation `UniqueMorphism`\n" );
+ fi;
+
+ products := List( list_of_products, cone -> cone[1] );
+ cones := List( list_of_products, cone -> List( cone[2], factor -> UniqueMorphism( P, cone[1], factor ) ) );
+
+ return ListN( products, cones, { product, cone } -> [ product, cone ] );
+
+end );
+
+##
+InstallOtherMethodForCompilerForCAP( ConesOfProductsByIndices,
+ [ IsCapCategory and IsThinCategory, IsList ],
+
+ function( P, list_of_products_by_indices )
+ local offset, objects, products, factors, list_of_products;
+
+ offset := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "offset", 0 );
+
+ objects := SetOfObjects( P );
+
+ products := List( list_of_products_by_indices, cone -> objects[offset + cone[1]] );
+ factors := List( list_of_products_by_indices, cone -> List( cone[2], i -> objects[offset + i] ) );
+
+ list_of_products := ListN( products, factors, { product, factor } -> [ product, factor ] );
+
+ return ConesOfProducts( P, list_of_products );
+
+end );
diff --git a/FunctorCategories/init.g b/FunctorCategories/init.g
index cf162c1c5..ab7f92c13 100644
--- a/FunctorCategories/init.g
+++ b/FunctorCategories/init.g
@@ -16,6 +16,8 @@ ReadPackage( "FunctorCategories", "gap/CategoryOfReflexiveQuivers.gd");
ReadPackage( "FunctorCategories", "gap/FiniteCompletion.gd");
ReadPackage( "FunctorCategories", "gap/FreeDistributiveCompletion.gd");
ReadPackage( "FunctorCategories", "gap/AbelianClosure.gd");
+ReadPackage( "FunctorCategories", "gap/ClosedPreSheavesWRTColimitingCocones.gd");
+ReadPackage( "FunctorCategories", "gap/ClosedCoPreSheavesWRTLimitingCones.gd");
ReadPackage( "FunctorCategories", "gap/Functors.gd");
ReadPackage( "FunctorCategories", "gap/DirectSumDecomposition.gd");
ReadPackage( "FunctorCategories", "gap/HomologicalMethods.gd");
diff --git a/FunctorCategories/read.g b/FunctorCategories/read.g
index 38c2ad3cd..7d7622d18 100644
--- a/FunctorCategories/read.g
+++ b/FunctorCategories/read.g
@@ -34,6 +34,8 @@ ReadPackage( "FunctorCategories", "gap/CategoryOfReflexiveQuivers.gi");
ReadPackage( "FunctorCategories", "gap/FiniteCompletion.gi");
ReadPackage( "FunctorCategories", "gap/FreeDistributiveCompletion.gi");
ReadPackage( "FunctorCategories", "gap/AbelianClosure.gi");
+ReadPackage( "FunctorCategories", "gap/ClosedPreSheavesWRTColimitingCocones.gi");
+ReadPackage( "FunctorCategories", "gap/ClosedCoPreSheavesWRTLimitingCones.gi");
ReadPackage( "FunctorCategories", "gap/Functors.gi");
ReadPackage( "FunctorCategories", "gap/DirectSumDecomposition.gi");
ReadPackage( "FunctorCategories", "gap/HomologicalMethods.gi");
diff --git a/Locales/examples/DifferenceCSL.g b/Locales/examples/DifferenceCSL.g
new file mode 100644
index 000000000..ace3b94ee
--- /dev/null
+++ b/Locales/examples/DifferenceCSL.g
@@ -0,0 +1,93 @@
+#! @Chunk DifferenceCSL
+
+# the assumption si <= mi leads to fewer meets and joins:
+
+#! @Example
+LoadPackage( "FunctorCategories", false );
+#! true
+q := "q(m0,s0,m1,s1,m2,s2,m0_x_s1,s0_u_m1,m1_x_s2,s1_u_m2)\
+[sm0:s0->m0,sm1:s1->m1,sm2:s2->m2,\
+p011:m0_x_s1->s1,\
+i101:m1->s0_u_m1,\
+p122:m1_x_s2->s2,\
+i212:m2->s1_u_m2,\
+mc0:m0_x_s1->s0,jc0:m0->s0_u_m1,\
+mc1:m1_x_s2->s1,jc1:m1->s1_u_m2]";;
+q := FinQuiver( q );
+#! FinQuiver( "q(m0,s0,m1,s1,m2,s2,m0_x_s1,s0_u_m1,m1_x_s2,s1_u_m2)
+#! [sm0:s0-≻m0,sm1:s1-≻m1,sm2:s2-≻m2,
+#! p011:m0_x_s1-≻s1,
+#! i101:m1-≻s0_u_m1,
+#! p122:m1_x_s2-≻s2,
+#! i212:m2-≻s1_u_m2,
+#! mc0:m0_x_s1-≻s0,jc0:m0-≻s0_u_m1,
+#! mc1:m1_x_s2-≻s1,jc1:m1-≻s1_u_m2]" )
+F := PathCategory( q );
+#! PathCategory( FinQuiver( "q(m0,s0,m1,s1,m2,s2,m0_x_s1,s0_u_m1,m1_x_s2,s1_u_m2)
+#! [sm0:s0-≻m0,sm1:s1-≻m1,sm2:s2-≻m2,
+#! p011:m0_x_s1-≻s1,
+#! i101:m1-≻s0_u_m1,
+#! p122:m1_x_s2-≻s2,
+#! i212:m2-≻s1_u_m2,
+#! mc0:m0_x_s1-≻s0,jc0:m0-≻s0_u_m1,
+#! mc1:m1_x_s2-≻s1,jc1:m1-≻s1_u_m2]" ) )
+Size( F );
+#! 35
+HomStructure( F.s0, F.s0_u_m1 );
+#! |1|
+HomStructure( F.s1, F.s1_u_m2 );
+#! |1|
+HomStructure( F.m0_x_s1, F.m0 );
+#! |1|
+HomStructure( F.m1_x_s2, F.m1 );
+#! |1|
+C := F /
+ [ [ F.p011 * F.sm1 * F.i101, F.mc0 * F.sm0 * F.jc0 ],
+ [ F.p122 * F.sm2 * F.i212, F.mc1 * F.sm1 * F.jc1 ] ];
+#! PathCategory( FinQuiver( "q(m0,s0,m1,s1,m2,s2,m0_x_s1,s0_u_m1,m1_x_s2,s1_u_m2)
+#! [sm0:s0-≻m0,sm1:s1-≻m1,sm2:s2-≻m2,
+#! p011:m0_x_s1-≻s1,
+#! i101:m1-≻s0_u_m1,
+#! p122:m1_x_s2-≻s2,
+#! i212:m2-≻s1_u_m2,
+#! mc0:m0_x_s1-≻s0,jc0:m0-≻s0_u_m1,
+#! mc1:m1_x_s2-≻s1,jc1:m1-≻s1_u_m2]" ) )
+#! / [ p011⋅sm1⋅i101 = mc0⋅sm0⋅jc0, p122⋅sm2⋅i212 = mc1⋅sm1⋅jc1 ]
+Size( C );
+#! 33
+P := PosetOfCategory( F );;
+Size( P );
+#! 33
+digraphF := DigraphOfPoset( P );;
+digraphF!.vertexlabels := List( SetOfObjects( F ), String );
+#Splash( DotVertexLabelledDigraph( digraphF ) );
+coPSh := CoPreSheaves( P );;
+Length( SetOfObjects( coPSh ) );
+#! 41
+products := [ [ P.m1_x_s2, [ P.m1, P.s2 ] ],
+ [ P.m0_x_s1, [ P.m0, P.s1 ] ] ];; ## the order is important
+coPSh_J := ClosedCoPreSheavesWRTProducts( P, products );;
+coY := CoYonedaEmbeddingOfSourceCategory( coPSh_J );
+#! co-Yoneda embedding functor
+objs_coPSh_J := SetOfObjects( coPSh_J );
+Assert( 0, Length( objs_coPSh_J ) = 28 );
+#Splash( DotVertexLabelledDigraph( coPSh_J, [ coY ], [ "darkgreen", "blue" ] : offset := 0 ) );
+coproducts := [ [ coPSh_J.s1_u_m2, [ coPSh_J.s1, coPSh_J.m2 ] ],
+ [ coPSh_J.s0_u_m1, [ coPSh_J.s0, coPSh_J.m1 ] ] ];; ## the order is important
+PSh_J := ClosedPreSheavesWRTCoproducts( coPSh_J, coproducts );;
+Y := YonedaEmbeddingOfSourceCategory( PSh_J );
+Assert( 0, IsHomSetInhabited( PSh_J.m0, PSh_J.s0_u_m1 ) );
+Assert( 0, IsHomSetInhabited( PSh_J.m1, PSh_J.s1_u_m2 ) );
+Assert( 0, IsHomSetInhabited( PSh_J.m0_x_s1, PSh_J.s0 ) );
+Assert( 0, IsHomSetInhabited( PSh_J.m1_x_s2, PSh_J.s1 ) );
+Assert( 0, DirectProduct( PSh_J.m0, PSh_J.s1 ) = PSh_J.m0_x_s1 );
+Assert( 0, DirectProduct( PSh_J.m1, PSh_J.s2 ) = PSh_J.m1_x_s2 );
+Assert( 0, Coproduct( PSh_J.s0, PSh_J.m1 ) = PSh_J.s0_u_m1 );
+Assert( 0, Coproduct( PSh_J.s1, PSh_J.m2 ) = PSh_J.s1_u_m2 );
+#objs := SetOfObjects( PSh_J );
+
+#PSh := PreSheaves( coPSh_J );
+#objs := SetOfObjects( PSh ); ## took 122h 15m to compute
+#Length( objs ); ## 728
+#Splash( DotVertexLabelledDigraph( PSh_J, [ PreCompose( coY, Y ), Y ], [ "red", "blue", "darkgreen" ] ) );
+#! @EndExample
diff --git a/Locales/examples/FreeBooleanAlgebra.g b/Locales/examples/FreeBooleanAlgebra.g
new file mode 100644
index 000000000..9e38251d7
--- /dev/null
+++ b/Locales/examples/FreeBooleanAlgebra.g
@@ -0,0 +1,65 @@
+#! @Chunk FreeBooleanAlgebra
+
+#! Construct the free boolean algebra on two generators with its $2^(2^2)$ elements
+#! in two steps.
+
+#! @Example
+LoadPackage( "FunctorCategories", false );
+#! true
+pq := FinQuiver( "quiver(p,q)" );
+#! FinQuiver( "quiver(p,q)[]" )
+F := PathCategory( pq );
+#! PathCategory( FinQuiver( "quiver(p,q)[]" ) )
+P := PosetOfCategory( F );
+#! PosetOfCategory( PathCategory( FinQuiver( "quiver(p,q)[]" ) ) )
+Length( SetOfObjects( P ) );
+#! 2
+Dist := FreeDistributiveCompletion( P );
+#! FreeDistributiveCompletion(
+#! PosetOfCategory( PathCategory( FinQuiver( "quiver(p,q)[]" ) ) ) )
+Display( Dist );
+#! A CAP category with name FreeDistributiveCompletion(
+#! PosetOfCategory( PathCategory( FinQuiver( "quiver(p,q)[]" ) ) ) ):
+#!
+#! 54 primitive operations were used to derive 250 operations for this category
+#! which algorithmically
+#! * IsFiniteCategory
+#! * IsEquippedWithHomomorphismStructure
+#! * IsHeytingAlgebra
+#! and not yet algorithmically
+#! * IsBiHeytingAlgebra
+Length( SetOfObjects( Dist ) );
+#! 6
+#Splash( DotVertexLabelledDigraph( Dist, [ [ Dist.p, Dist.q ] ], [ "magenta", "blue" ] ) );
+DiffbCSL := MeetSemilatticeOfSingleDifferences( Dist );
+#! MeetSemilatticeOfSingleDifferences( FreeDistributiveCompletion(
+#! PosetOfCategory( PathCategory( FinQuiver( "quiver(p,q)[]" ) ) ) ) )
+Length( SetOfObjects( DiffbCSL ) );
+#! 13
+#Splash( DotVertexLabelledDigraph( DiffbCSL, [ [ DiffbCSL.p, DiffbCSL.q ], SetOfGeneratingObjects( DiffbCSL ) ], [ "orange", "blue", "magenta" ] ) );
+PSh := PreSheaves( DiffbCSL );
+#! PreSheaves( MeetSemilatticeOfSingleDifferences( FreeDistributiveCompletion(
+#! PosetOfCategory( PathCategory( FinQuiver( "quiver(p,q)[]" ) ) ) ) ),
+#! IntervalCategory )
+Y := YonedaEmbeddingOfSourceCategory( PSh );;
+Length( SetOfObjects( PSh ) );
+#! 85
+coproducts := [ [ 1, [ ] ],
+ [ 3, [ 5, 11 ] ],
+ [ 4, [ 5, 12 ] ],
+ [ 7, [ 10, 12 ] ],
+ [ 8, [ 10, 11 ] ],
+ [ 13, [ 11, 12 ] ],
+ [ 6, [ 3, 4, 13 ] ],
+ [ 9, [ 7, 8, 13 ] ],
+ [ 2, [ 6, 9 ] ] ];;
+PSh_J := ClosedPreSheavesWRTCoproductsByIndices( DiffbCSL, coproducts );;
+psh_J := ModelingCategory( ModelingCategory( PSh_J ) );;
+Assert( 0, Length( SetOfObjects( psh_J ) ) = 16 );
+is_closed := psh_J!.ObjectMembershipFunction;
+closed := SetOfObjects( PSh_J );;
+Assert( 0, Length( closed ) = 16 );
+Assert( 0, ForAll( closed, obj -> is_closed( ObjectDatum( ModelingObject( PSh_J, obj ) ) ) ) );
+#Splash( DotVertexLabelledDigraph( PSh, [ [ PSh.p, PSh.q ], List( SetOfGeneratingObjects( DiffbCSL ), Y ), Y, psh_J ], [ "gray", "blue", "magenta", "orange", "red" ] ) );
+#Splash( DotVertexLabelledDigraph( psh_J, [ [ PSh.p, PSh.q ], List( SetOfGeneratingObjects( DiffbCSL ), Y ), Y ], [ "red", "blue", "magenta", "orange" ] : offset := 0 ) );
+#! @EndExample
diff --git a/Locales/examples/PSh_J_coPSh_J.g b/Locales/examples/PSh_J_coPSh_J.g
new file mode 100644
index 000000000..4fd316ee8
--- /dev/null
+++ b/Locales/examples/PSh_J_coPSh_J.g
@@ -0,0 +1,73 @@
+#! @Chunk DifferenceCSL
+
+# the assumption si <= mi leads to fewer meets and joins:
+
+#! @Example
+LoadPackage( "FunctorCategories", false );
+#! true
+q := "q(m0,s0,m1,s1,m0_x_s1,s0_u_m1)\
+[sm0:s0->m0,sm1:s1->m1,\
+p011:m0_x_s1->s1,\
+i101:m1->s0_u_m1,\
+mc0:m0_x_s1->s0,jc0:m0->s0_u_m1]";;
+q := FinQuiver( q );
+#! FinQuiver( "q(m0,s0,m1,s1,m0_x_s1,s0_u_m1)
+#! [sm0:s0-≻m0,sm1:s1-≻m1,p011:m0_x_s1-≻s1,
+#! i101:m1-≻s0_u_m1,mc0:m0_x_s1-≻s0,jc0:m0-≻s0_u_m1]" )
+F := PathCategory( q );
+#! PathCategory( FinQuiver( "q(m0,s0,m1,s1,m0_x_s1,s0_u_m1)
+#! [sm0:s0-≻m0,sm1:s1-≻m1,p011:m0_x_s1-≻s1,
+#! i101:m1-≻s0_u_m1,mc0:m0_x_s1-≻s0,jc0:m0-≻s0_u_m1]" ) )
+Size( F );
+#! 18
+HomStructure( F.s0, F.s0_u_m1 );
+#! |1|
+HomStructure( F.m0_x_s1, F.m0 );
+#! |1|
+C := F /
+ [ [ F.p011 * F.sm1 * F.i101, F.mc0 * F.sm0 * F.jc0 ] ];
+#! PathCategory( FinQuiver( "q(m0,s0,m1,s1,m2,s2,m0_x_s1,s0_u_m1,m1_x_s2,s1_u_m2)
+#! [sm0:s0-≻m0,sm1:s1-≻m1,sm2:s2-≻m2,
+#! p011:m0_x_s1-≻s1,
+#! i101:m1-≻s0_u_m1,
+#! p122:m1_x_s2-≻s2,
+#! i212:m2-≻s1_u_m2,
+#! mc0:m0_x_s1-≻s0,jc0:m0-≻s0_u_m1,
+#! mc1:m1_x_s2-≻s1,jc1:m1-≻s1_u_m2]" ) )
+#! / [ p011⋅sm1⋅i101 = mc0⋅sm0⋅jc0, p122⋅sm2⋅i212 = mc1⋅sm1⋅jc1 ]
+Size( C );
+#! 17
+P := PosetOfCategory( F );;
+Size( P );
+#! 17
+digraphF := DigraphOfPoset( P );;
+digraphF!.vertexlabels := List( SetOfObjects( F ), String );
+#Splash( DotVertexLabelledDigraph( digraphF ) );
+#Splash( DotVertexLabelledDigraph( DigraphOfPoset( P ) ) );
+coPSh := CoPreSheaves( P );;
+Length( SetOfObjects( coPSh ) );
+#! 11
+products := [ [ P.m0_x_s1, [ P.m0, P.s1 ] ] ];;
+coPSh_J := ClosedCoPreSheavesWRTProducts( P, products );;
+coY := CoYonedaEmbeddingOfSourceCategory( coPSh_J );
+#! co-Yoneda embedding functor
+objs_coPSh_J := SetOfObjects( coPSh_J );
+Assert( 0, Length( objs_coPSh_J ) = 9 );
+#Splash( DotVertexLabelledDigraph( coPSh_J, [ coY ], [ "darkgreen", "blue" ] ) );
+#coproducts := [ [ coPSh_J.s0_u_m1, [ coPSh_J.s0, coPSh_J.m1 ] ] ];;
+coproducts := [ [ coPSh_J.s0_u_m1, [ coPSh_J.s0, coPSh_J.m1 ] ],
+ [ objs_coPSh_J[1 + 1], [ objs_coPSh_J[1 + 2], objs_coPSh_J[1 + 7] ] ] ];;
+PSh_J := ClosedPreSheavesWRTCoproducts( coPSh_J, coproducts );;
+Y := YonedaEmbeddingOfSourceCategory( PSh_J );
+#! Yoneda embedding functor
+Assert( 0, IsHomSetInhabited( PSh_J.m0, PSh_J.s0_u_m1 ) );
+Assert( 0, IsHomSetInhabited( PSh_J.m0_x_s1, PSh_J.s0 ) );
+Assert( 0, DirectProduct( PSh_J.m0, PSh_J.s1 ) = PSh_J.m0_x_s1 );
+Assert( 0, Coproduct( PSh_J.s0, PSh_J.m1 ) = PSh_J.s0_u_m1 );
+objs := SetOfObjects( PSh_J );
+Assert( 0, Length( objs ) = 14 );
+#Splash( DotVertexLabelledDigraph( PSh_J, [ PreCompose( coY, Y ), Y ], [ "red", "blue", "darkgreen" ] : offset := 0 ) );
+#PSh := PreSheaves( coPSh_J );
+#objs := SetOfObjects( PSh ); ## took 122h 15m to compute
+#Length( objs ); ## 728
+#! @EndExample
diff --git a/Locales/gap/ProsetDerivedMethods.gi b/Locales/gap/ProsetDerivedMethods.gi
index febe99fca..152803cf4 100644
--- a/Locales/gap/ProsetDerivedMethods.gi
+++ b/Locales/gap/ProsetDerivedMethods.gi
@@ -99,9 +99,9 @@ AddDerivationToCAP( UniversalMorphismIntoTerminalObject,
[ [ TerminalObject, 1 ],
[ UniqueMorphism, 1 ] ],
- function( cat, A )
+ function( cat, source )
- return UniqueMorphism( cat, A, TerminalObject( cat ) );
+ return UniqueMorphism( cat, source, TerminalObject( cat ) );
end : CategoryFilter := IsThinCategory );
@@ -123,9 +123,9 @@ AddDerivationToCAP( UniversalMorphismFromInitialObject,
[ [ InitialObject, 1 ],
[ UniqueMorphism, 1 ] ],
- function( cat, A )
+ function( cat, target )
- return UniqueMorphism( cat, InitialObject( cat ), A );
+ return UniqueMorphism( cat, InitialObject( cat ), target );
end : CategoryFilter := IsThinCategory );
diff --git a/Locales/gap/SingleDifferences.gd b/Locales/gap/SingleDifferences.gd
index 85e536f35..175750909 100644
--- a/Locales/gap/SingleDifferences.gd
+++ b/Locales/gap/SingleDifferences.gd
@@ -94,6 +94,9 @@ DeclareAttribute( "MeetSemilatticeOfSingleDifferences",
DeclareOperation( "SingleDifference",
[ IsList ] );
+DeclareAttribute( "SetOfGeneratingObjects",
+ IsMeetSemilatticeOfSingleDifferences );
+
#! @Description
#! Form the formal single difference object A - B.
#! The expression A - 0 := A - InitialObject( CapCategory( A ) ).
diff --git a/Locales/gap/SingleDifferences.gi b/Locales/gap/SingleDifferences.gi
index fffdc4a38..38e260358 100644
--- a/Locales/gap/SingleDifferences.gi
+++ b/Locales/gap/SingleDifferences.gi
@@ -227,6 +227,21 @@ InstallMethodForCompilerForCAP( SetOfGeneratingMorphisms,
end );
+##
+InstallMethod( SetOfGeneratingObjects,
+ "for a meet-semilattice of single differences",
+ [ IsMeetSemilatticeOfSingleDifferences ],
+
+ function( D )
+ local Dist;
+
+ Dist := UnderlyingCategory( D );
+
+ return List( SetOfObjects( Dist ), minued ->
+ SingleDifference( D, Pair( minued, InitialObject( Dist ) ) ) );
+
+end );
+
##
InstallMethod( \-,
"for two objects in a thin category",
@@ -316,7 +331,7 @@ end );
##
InstallOtherMethodForCompilerForCAP( NormalizedMinuendAndSubtrahendInUnderlyingHeytingOrCoHeytingAlgebroid,
"for a Heyting algebroid and two objects in it",
- [ IsCapCategory and IsHeytingAlgebroid, IsObjectInThinCategory, IsObjectInThinCategory ],
+ [ IsCapCategory and IsHeytingAlgebroid, IsCapCategoryObject, IsCapCategoryObject ],
function( L, minuend, subtrahend )
local H;
@@ -332,7 +347,7 @@ end );
##
InstallOtherMethodForCompilerForCAP( NormalizedMinuendAndSubtrahendInUnderlyingHeytingOrCoHeytingAlgebroid,
"for a co-Heyting algebroid and two objects in it",
- [ IsCapCategory and IsCoHeytingAlgebroid, IsObjectInThinCategory, IsObjectInThinCategory ],
+ [ IsCapCategory and IsCoHeytingAlgebroid, IsCapCategoryObject, IsCapCategoryObject ],
function( L, minuend, subtrahend )
local H;
@@ -582,6 +597,22 @@ InstallMethod( \.,
end );
+##
+InstallMethod( \.,
+ "for a meet-semilattice of formal single differences and a positive integer",
+ [ IsMeetSemilatticeOfSingleDifferences, IsPosInt ],
+
+ function( D, string_as_int )
+ local Dist, name;
+
+ Dist := UnderlyingCategory( D );
+
+ name := NameRNam( string_as_int );
+
+ return SingleDifference( D, Pair( Dist.(name), InitialObject( Dist ) ) );
+
+end );
+
##
InstallMethod( ViewString,
"for an object in a meet-semilattice of formal single differences",
diff --git a/Locales/gap/ToolsUsingDigraphs.gi b/Locales/gap/ToolsUsingDigraphs.gi
index 47808be31..6efb74e14 100644
--- a/Locales/gap/ToolsUsingDigraphs.gi
+++ b/Locales/gap/ToolsUsingDigraphs.gi
@@ -208,14 +208,16 @@ InstallMethod( DigraphOfPoset,
[ IsThinCategory and IsFiniteCategory ],
function( P )
- local objects, D;
+ local objects, offset, D;
objects := SetOfObjectsOfCategory( P );
+ offset := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "offset", 1 );
+
if ValueOption( "use_vertex_labels" ) = true then
D := Digraph( objects, IsHomSetInhabited );
else
- D := Digraph( [ 0 .. Length( objects ) - 1 ], { i, j } -> IsHomSetInhabited( objects[1+i], objects[1+j] ) );
+ D := Digraph( [ offset .. offset + Length( objects ) - 1 ], { i, j } -> IsHomSetInhabited( objects[1-offset+i], objects[1-offset+j] ) );
fi;
D := DigraphReflexiveTransitiveReduction( D );
@@ -226,6 +228,87 @@ InstallMethod( DigraphOfPoset,
end );
+##
+InstallOtherMethod( DotVertexLabelledDigraph,
+ [ IsDigraphByOutNeighboursRep and IsDigraphOfSubobjects, IsList ],
+
+ function( D, list_of_colorings )
+ local out, str, i, pos, j;
+
+ # Copied from DotVertexLabeledDigraph() at Digraphs/gap/display.gi
+ out := OutNeighbours( D );
+ str := "//dot\n";
+
+ Append( str, "digraph subobject_lattice{\n" );
+ Append( str, "rankdir=\"BT\"\n" );
+ Append( str, "minlen=0\n" );
+ Append( str, "node [shape=circle width=0 height=0]\n" );
+
+ for i in DigraphVertices( D ) do
+ Append( str, String( i ) );
+ Append( str, " [label=\"" );
+ Append( str, String( DigraphVertexLabel( D, i ) ) );
+ pos := PositionProperty( list_of_colorings, pair -> pair[1] = i );
+ Append( str, "\"" );
+ if IsInt( pos ) then
+ Append( str, Concatenation( " color=", list_of_colorings[pos][2], " fontcolor=", list_of_colorings[pos][2] ) );
+ fi;
+ Append( str, " fontsize=12 margin=0.01 fontname=\"DejaVu Serif,serif\"]\n" );
+ od;
+
+ for i in DigraphVertices( D ) do
+ for j in out[i] do
+ Append( str, Concatenation( String( i ), " -> ", String( j ), " [arrowsize=0.5]\n" ) );
+ od;
+ od;
+
+ Append( str, "}\n" );
+
+ return str;
+
+end );
+
+##
+InstallOtherMethod( DotVertexLabelledDigraph,
+ [ IsPosetCategory and IsFiniteCategory, IsList, IsList ],
+
+ function( P, lists_of_subobjects, list_of_colors )
+ local c, objects, l, func, list_of_colorings;
+
+ c := Length( list_of_colors );
+
+ Assert( 0, Length( lists_of_subobjects ) + 1 = c );
+
+ objects := SetOfObjects( P );
+
+ l := Length( objects );
+
+ func :=
+ function( emb )
+ if IsCapFunctor( emb ) then
+ return List( SetOfObjects( SourceOfFunctor( emb ) ), emb );
+ elif IsBoundGlobal( "IsCapSubcategory" ) and ValueGlobal( "IsCapSubcategory" )( emb ) then
+ return List( SetOfObjects( emb ), UnderlyingCell );
+ else
+ return emb;
+ fi;
+
+ end;
+
+ lists_of_subobjects := List( lists_of_subobjects, func );
+
+ list_of_colorings := List( lists_of_subobjects, list_of_subobjects ->
+ List( list_of_subobjects, object ->
+ SafeUniquePositionProperty( objects, obj -> IsEqualForObjects( P, obj, object ) ) ) );
+
+ list_of_colorings := Concatenation( [ Difference( [ 1 .. l ], Concatenation( list_of_colorings ) ) ], list_of_colorings );
+
+ list_of_colorings := List( [ 1 .. c ], i -> List( list_of_colorings[i], o -> [ o, list_of_colors[i] ] ) );
+
+ return DotVertexLabelledDigraph( DigraphOfPoset( P ), Concatenation( list_of_colorings ) );
+
+end );
+
##
InstallMethod( Visualize,
"for a datastructure of a constructible object",
diff --git a/SubcategoriesForCAP/PackageInfo.g b/SubcategoriesForCAP/PackageInfo.g
index bea524bab..58b558820 100644
--- a/SubcategoriesForCAP/PackageInfo.g
+++ b/SubcategoriesForCAP/PackageInfo.g
@@ -10,7 +10,7 @@ SetPackageInfo( rec(
PackageName := "SubcategoriesForCAP",
Subtitle := "Subcategory and other related constructors for CAP categories",
-Version := "2024.03-03",
+Version := "2024.03-04",
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/SubcategoriesForCAP/gap/FullSubcategory.gi b/SubcategoriesForCAP/gap/FullSubcategory.gi
index 75da0cadb..539de3a89 100644
--- a/SubcategoriesForCAP/gap/FullSubcategory.gi
+++ b/SubcategoriesForCAP/gap/FullSubcategory.gi
@@ -362,10 +362,10 @@ InstallMethod( Display,
[ IsObjectInAFullSubcategory ],
function( a )
- Print( "An object in full subcategory given by: " );
-
Display( UnderlyingCell( a ) );
+ Display( "\nAn object in full subcategory given by the above data" );
+
end );
##
@@ -373,8 +373,8 @@ InstallMethod( Display,
[ IsMorphismInAFullSubcategory ],
function( phi )
- Print( "A morphism in full subcategory given by: " );
-
Display( UnderlyingCell( phi ) );
+ Display( "\nA morphism in full subcategory given by the above data" );
+
end );
diff --git a/SubcategoriesForCAP/gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gd b/SubcategoriesForCAP/gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gd
new file mode 100644
index 000000000..7c34551d0
--- /dev/null
+++ b/SubcategoriesForCAP/gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gd
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SubcategoriesForCAP: Subcategory and other related constructors for CAP categories
+#
+# Declarations
+#
+
+#! @Chapter Kleisli reflective subcategory of an idempotent monad
+
+####################################
+#
+#! @Section GAP categories
+#
+####################################
+
+#! @Description
+#! The &GAP; category of Kleisli reflective subcategories of idempotent monads.
+DeclareCategory( "IsKleisliReflectiveSubcategoryOfIdempotentMonad",
+ IsCapCategory );
+
+#! @Description
+#! The &GAP; category of cells in the Kleisli reflective subcategory of an idempotent monad.
+DeclareCategory( "IsCellInKleisliReflectiveSubcategoryOfIdempotentMonad",
+ IsCapCategoryCell );
+
+#! @Description
+#! The &GAP; category of objects in the Kleisli reflective subcategory of an idempotent monad.
+DeclareCategory( "IsObjectInKleisliReflectiveSubcategoryOfIdempotentMonad",
+ IsCellInKleisliReflectiveSubcategoryOfIdempotentMonad and IsCapCategoryObject );
+
+#! @Description
+#! The &GAP; category of morphisms in the Kleisli reflective subcategory of an idempotent monad.
+DeclareCategory( "IsMorphismInKleisliReflectiveSubcategoryOfIdempotentMonad",
+ IsCellInKleisliReflectiveSubcategoryOfIdempotentMonad and IsCapCategoryMorphism );
+
+####################################
+#
+#! @Section Constructors
+#
+####################################
+
+#! @Description
+#! Return the Kleisli reflective subcategory of the idempotent monad $T:C \to C$
+#! with unit eta:$\mathrm{Id}_C \to T$.
+#! @Arguments T
+DeclareAttribute( "KleisliReflectiveSubcategoryOfIdempotentMonad",
+ IsCapNaturalTransformation );
+
+#CapJitAddTypeSignature( "KleisliReflectiveSubcategoryOfIdempotentMonad", [ IsCapFunctor ], function ( input_types )
+#
+# return CapJitDataTypeOfCategory( KleisliReflectiveSubcategoryOfIdempotentMonad( input_types[1].category ) );
+#
+#end );
+
+####################################
+#
+#! @Section Attributes
+#
+####################################
+
+#! @Description
+#! The input is the Kleisli reflective subcategory C_T of an idempotent monad $T:C \to C$.
+#! The output is the monad $T$.
+#! @Arguments C_T
+DeclareAttribute( "UnderlyingMonadUnit",
+ IsKleisliReflectiveSubcategoryOfIdempotentMonad );
+
+#! @Description
+#! The input is the Kleisli reflective subcategory of an idempotent monad $T:C \to C$.
+#! The output is the monad $T$.
+#! @Arguments C_T
+DeclareAttribute( "UnderlyingMonad",
+ IsKleisliReflectiveSubcategoryOfIdempotentMonad );
+
+#! @Description
+#! The input is the Kleisli reflective subcategory of an idempotent monad $T:C \to C$.
+#! The output is the underlying category $C$.
+#! @Arguments C_T
+DeclareAttribute( "AmbientCategory",
+ IsKleisliReflectiveSubcategoryOfIdempotentMonad );
+
+CapJitAddTypeSignature( "AmbientCategory", [ IsKleisliReflectiveSubcategoryOfIdempotentMonad ],
+ function ( input_types )
+
+ return CapJitDataTypeOfCategory( AmbientCategory( input_types[1].category ) );
+
+end );
diff --git a/SubcategoriesForCAP/gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gi b/SubcategoriesForCAP/gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gi
new file mode 100644
index 000000000..f8b3f654f
--- /dev/null
+++ b/SubcategoriesForCAP/gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gi
@@ -0,0 +1,266 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SubcategoriesForCAP: Subcategory and other related constructors for CAP categories
+#
+# Implementations
+#
+
+##
+InstallMethod( KleisliReflectiveSubcategoryOfIdempotentMonad,
+ "for a CAP natural transformation",
+ [ IsCapNaturalTransformation ],
+
+ function ( eta )
+ local T, C,
+ object_datum_type, object_constructor, object_datum,
+ morphism_datum_type, morphism_constructor, morphism_datum,
+ object_membership_func, reflective_subcategory,
+ modeling_tower_object_constructor, modeling_tower_object_datum,
+ modeling_tower_morphism_constructor, modeling_tower_morphism_datum,
+ Kleisli;
+
+ T := Target( eta );
+ C := SourceOfFunctor( T );
+
+ #% CAP_JIT_DROP_NEXT_STATEMENT
+ Assert( 0, IsIdenticalObj( C, RangeOfFunctor( T ) ) );
+
+ ##
+ object_datum_type :=
+ CapJitDataTypeOfObjectOfCategory( C );
+
+ ##
+ object_constructor :=
+ function( Kleisli, obj )
+
+ return CreateCapCategoryObjectWithAttributes( Kleisli,
+ AsPrimitiveValue, obj );
+
+ end;
+
+ ##
+ object_datum := { Kleisli, o } -> AsPrimitiveValue( o );
+
+ ##
+ morphism_datum_type :=
+ CapJitDataTypeOfMorphismOfCategory( C );
+
+ ##
+ morphism_constructor :=
+ function( Kleisli, source, mor, target )
+
+ return CreateCapCategoryMorphismWithAttributes( Kleisli,
+ source,
+ target,
+ AsPrimitiveValue, mor );
+
+ end;
+
+ ##
+ morphism_datum := { Kleisli, m } -> AsPrimitiveValue( m );
+
+ ## building the categorical tower:
+
+ if IsBound( T!.ObjectMembershipFunction ) then
+ object_membership_func := T!.ObjectMembershipFunction;
+ else
+ object_membership_func :=
+ function( object )
+
+ return IsIsomorphism( C, eta( object ) );
+
+ end;
+ fi;
+
+ reflective_subcategory := FullSubcategoryByObjectMembershipFunction( C, object_membership_func : FinalizeCategory := true );
+
+ ## from the raw object data to the object in the modeling category
+ modeling_tower_object_constructor :=
+ function( Kleisli, obj )
+ local reflective_subcategory;
+
+ reflective_subcategory := ModelingCategory( Kleisli );
+
+ return ObjectConstructor( reflective_subcategory,
+ obj );
+
+ end;
+
+ ## from the object in the modeling category to the raw object data
+ modeling_tower_object_datum :=
+ function( Kleisli, obj )
+ local reflective_subcategory;
+
+ reflective_subcategory := ModelingCategory( Kleisli );
+
+ return ObjectDatum( reflective_subcategory,
+ obj );
+
+ end;
+
+ ## from the raw morphism data to the morphism in the modeling category
+ modeling_tower_morphism_constructor :=
+ function( Kleisli, source, mor, target )
+ local reflective_subcategory;
+
+ reflective_subcategory := ModelingCategory( Kleisli );
+
+ return MorphismConstructor( reflective_subcategory,
+ source,
+ mor,
+ target );
+
+ end;
+
+ ## from the morphism in the modeling category to the raw morphism data
+ modeling_tower_morphism_datum :=
+ function( Kleisli, mor )
+ local reflective_subcategory;
+
+ reflective_subcategory := ModelingCategory( Kleisli );
+
+ return MorphismDatum( reflective_subcategory,
+ mor );
+
+ end;
+
+ ##
+ Kleisli :=
+ ReinterpretationOfCategory( reflective_subcategory,
+ rec( name := Concatenation( "KleisliReflectiveSubcategoryOfIdempotentMonad( ", Name( eta ), " )" ),
+ category_filter := IsKleisliReflectiveSubcategoryOfIdempotentMonad,
+ category_object_filter := IsObjectInKleisliReflectiveSubcategoryOfIdempotentMonad,
+ category_morphism_filter := IsMorphismInKleisliReflectiveSubcategoryOfIdempotentMonad,
+ object_datum_type := object_datum_type,
+ morphism_datum_type := morphism_datum_type,
+ object_constructor := object_constructor,
+ object_datum := object_datum,
+ morphism_constructor := morphism_constructor,
+ morphism_datum := morphism_datum,
+ modeling_tower_object_constructor := modeling_tower_object_constructor,
+ modeling_tower_object_datum := modeling_tower_object_datum,
+ modeling_tower_morphism_constructor := modeling_tower_morphism_constructor,
+ modeling_tower_morphism_datum := modeling_tower_morphism_datum,
+ only_primitive_operations := true )
+ : FinalizeCategory := false );
+
+ SetUnderlyingMonad( Kleisli, T );
+ SetAmbientCategory( Kleisli, C );
+
+ Append( Kleisli!.compiler_hints.category_attribute_names,
+ [ "UnderlyingMonad",
+ "AmbientCategory" ] );
+
+ Finalize( Kleisli );
+
+ return Kleisli;
+
+end );
+
+##
+InstallMethod( \.,
+ "for the Kleisli reflective subcategory of an idempotent monad and a positive integer",
+ [ IsKleisliReflectiveSubcategoryOfIdempotentMonad, IsPosInt ],
+
+ function( Kleisli, string_as_int )
+ local name, reflective_subcategory, c;
+
+ name := NameRNam( string_as_int );
+
+ reflective_subcategory := ModelingCategory( Kleisli );
+
+ c := reflective_subcategory.(name);
+
+ if IsCapCategoryObject( c ) and IsIdenticalObj( CapCategory( c ), reflective_subcategory ) then
+
+ return ReinterpretationOfObject( Kleisli, c );
+
+ elif IsCapCategoryMorphism( c ) and IsIdenticalObj( CapCategory( c ), reflective_subcategory ) then
+
+ return ReinterpretationOfMorphism( Kleisli,
+ ReinterpretationOfObject( Kleisli, Source( c ) ),
+ c,
+ ReinterpretationOfObject( Kleisli, Target( c ) ) );
+
+ else
+
+ Error( "`c` is neither an object nor a morphism in the ambient category `C`\n" );
+
+ fi;
+
+end );
+
+##
+InstallMethodForCompilerForCAP( SetOfObjects,
+ "for the Kleisli reflective subcategory of an idempotent monad",
+ [ IsKleisliReflectiveSubcategoryOfIdempotentMonad ],
+
+ function( cat )
+
+ return SetOfObjectsOfCategory( cat );
+
+end );
+
+##
+InstallMethodForCompilerForCAP( SetOfGeneratingMorphisms,
+ "for the Kleisli reflective subcategory of an idempotent monad",
+ [ IsKleisliReflectiveSubcategoryOfIdempotentMonad ],
+
+ function( cat )
+
+ return SetOfGeneratingMorphismsOfCategory( cat );
+
+end );
+
+##################################
+##
+## View & Display
+##
+##################################
+
+##
+InstallMethod( ViewObj,
+ [ IsObjectInKleisliReflectiveSubcategoryOfIdempotentMonad ],
+
+ function( a )
+
+ Print( "An object in the Kleisli category of an idempotent monad given by: " );
+
+ ViewObj( ObjectDatum( a ) );
+
+end );
+
+##
+InstallMethod( ViewObj,
+ [ IsMorphismInASubcategory ],
+
+ function( phi )
+
+ Print( "A morphism in the Kleisli category of an idempotent monad given by: " );
+
+ ViewObj( MorphismDatum( phi ) );
+
+end );
+
+##
+InstallMethod( Display,
+ [ IsObjectInKleisliReflectiveSubcategoryOfIdempotentMonad ],
+
+ function( a )
+
+ Display( ObjectDatum( a ) );
+
+ Display( "\nAn object in the Kleisli category of an idempotent monad given by the above data" );
+
+end );
+
+##
+InstallMethod( Display,
+ [ IsMorphismInASubcategory ],
+
+ function( phi )
+
+ Display( MorphismDatum( phi ) );
+
+ Display( "\nA morphism in the Kleisli category of an idempotent monad given by the above data" );
+
+end );
diff --git a/SubcategoriesForCAP/gap/Subcategory.gi b/SubcategoriesForCAP/gap/Subcategory.gi
index bea7d87fd..fcf97b427 100644
--- a/SubcategoriesForCAP/gap/Subcategory.gi
+++ b/SubcategoriesForCAP/gap/Subcategory.gi
@@ -90,7 +90,8 @@ InstallMethod( Subcategory,
[ IsCapCategory, IsString ],
function( C, name )
- local category_constructor_options, list_of_operations_to_install, is_full, is_additive, skip, func, pos, properties, D;
+ local category_constructor_options, list_of_operations_to_install, is_full, is_additive, additional_operations_to_install,
+ skip, func, pos, properties, additional_properties, D;
category_constructor_options := rec(
name := name,
@@ -116,6 +117,10 @@ InstallMethod( Subcategory,
is_additive := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "is_additive", false );
+ additional_operations_to_install := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "additional_operations_to_install", [ ] );
+
+ list_of_operations_to_install := DuplicateFreeList( Concatenation( list_of_operations_to_install, additional_operations_to_install ) );
+
if IsIdenticalObj( is_full, true ) then
Append( list_of_operations_to_install, CAP_INTERNAL_METHOD_NAME_LIST_FOR_FULL_SUBCATEGORY );
fi;
@@ -180,7 +185,11 @@ InstallMethod( Subcategory,
Add( properties, "IsAdditiveCategory" );
fi;
- category_constructor_options.properties := properties;
+ additional_properties := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "properties", [ ] );
+
+ category_constructor_options.properties := Concatenation( properties, additional_properties );
+
+ category_constructor_options.supports_empty_limits := CAP_INTERNAL_RETURN_OPTION_OR_DEFAULT( "supports_empty_limits", false );
D := CategoryConstructor( category_constructor_options );
@@ -288,6 +297,33 @@ InstallGlobalFunction( SubcategoryGeneratedByListOfMorphisms,
end );
+##
+InstallMethod( \.,
+ "for a subcategory and a positive integer",
+ [ IsCapSubcategory, IsPosInt ],
+
+ function( subcategory, string_as_int )
+ local name, C, c;
+
+ name := NameRNam( string_as_int );
+
+ C := AmbientCategory( subcategory );
+
+ c := C.(name);
+
+ if ( IsCapCategoryObject( c ) or IsCapCategoryMorphism( c ) ) and
+ IsIdenticalObj( CapCategory( c ), C ) then
+
+ return c / subcategory;
+
+ else
+
+ Error( "`c` is neither an object nor a morphism in the ambient category `C`\n" );
+
+ fi;
+
+end );
+
##
InstallMethodForCompilerForCAP( SetOfObjects,
"for a subcategory",
@@ -318,7 +354,8 @@ end );
##
InstallMethod( ViewObj,
- [ IsObjectInASubcategory ],
+ [ IsObjectInASubcategory ],
+
function( a )
Print( "An object in subcategory given by: " );
@@ -329,7 +366,8 @@ end );
##
InstallMethod( ViewObj,
- [ IsMorphismInASubcategory ],
+ [ IsMorphismInASubcategory ],
+
function( phi )
Print( "A morphism in subcategory given by: " );
@@ -340,7 +378,8 @@ end );
##
InstallMethod( Display,
- [ IsObjectInASubcategory ],
+ [ IsObjectInASubcategory ],
+
function( a )
Print( "An object in subcategory given by: " );
@@ -351,7 +390,8 @@ end );
##
InstallMethod( Display,
- [ IsMorphismInASubcategory ],
+ [ IsMorphismInASubcategory ],
+
function( phi )
Print( "A morphism in subcategory given by: " );
@@ -359,4 +399,3 @@ InstallMethod( Display,
Display( UnderlyingCell( phi ) );
end );
-
diff --git a/SubcategoriesForCAP/gap/ToolsUsingDigraphs.gi b/SubcategoriesForCAP/gap/ToolsUsingDigraphs.gi
new file mode 100644
index 000000000..865b8cd13
--- /dev/null
+++ b/SubcategoriesForCAP/gap/ToolsUsingDigraphs.gi
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SubcategoriesForCAP: Subcategory and other related constructors for CAP categories
+#
+# Implementations
+#
+
+##
+InstallOtherMethod( DotVertexLabelledDigraph,
+ [ IsCapSubcategory and IsPosetCategory and IsFiniteCategory, IsList, IsList ],
+
+ function( subposet, lists_of_subobjects, list_of_colors )
+ local P, c, objects, l, func, list_of_colorings, digraph, ambient_objects;
+
+ P := AmbientCategory( subposet );
+
+ c := Length( list_of_colors );
+
+ Assert( 0, Length( lists_of_subobjects ) + 1 = c );
+
+ objects := List( SetOfObjects( subposet ), UnderlyingCell );
+
+ l := Length( objects );
+
+ func :=
+ function( emb )
+ if IsCapFunctor( emb ) then
+ return List( SetOfObjects( SourceOfFunctor( emb ) ), emb );
+ elif IsCapSubcategory( emb ) then
+ return List( SetOfObjects( emb ), UnderlyingCell );
+ else
+ return emb;
+ fi;
+
+ end;
+
+ lists_of_subobjects := List( lists_of_subobjects, func );
+
+ list_of_colorings := List( lists_of_subobjects, list_of_subobjects ->
+ List( list_of_subobjects, object ->
+ SafeUniquePositionProperty( objects, obj -> IsEqualForObjects( P, obj, object ) ) ) );
+
+ list_of_colorings := Concatenation( [ Difference( [ 1 .. l ], Concatenation( list_of_colorings ) ) ], list_of_colorings );
+
+ list_of_colorings := List( [ 1 .. c ], i -> List( list_of_colorings[i], o -> [ o, list_of_colors[i] ] ) );
+
+ digraph := DigraphOfPoset( subposet );
+
+ ambient_objects := SetOfObjects( P );
+
+ digraph!.vertexlabels := List( objects, object -> String( -1 + SafeUniquePositionProperty( ambient_objects, obj -> IsEqualForObjects( P, obj, object ) ) ) );
+
+ return DotVertexLabelledDigraph( digraph, Concatenation( list_of_colorings ) );
+
+end );
diff --git a/SubcategoriesForCAP/init.g b/SubcategoriesForCAP/init.g
index f2be236d6..d0ac90610 100644
--- a/SubcategoriesForCAP/init.g
+++ b/SubcategoriesForCAP/init.g
@@ -7,6 +7,7 @@
ReadPackage( "SubcategoriesForCAP", "gap/Subcategory.gd");
ReadPackage( "SubcategoriesForCAP", "gap/FullSubcategory.gd");
ReadPackage( "SubcategoriesForCAP", "gap/FunctorsForFullSubcategories.gd");
+ReadPackage( "SubcategoriesForCAP", "gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gd");
if IsPackageMarkedForLoading( "Toposes", ">= 2020.02.19" ) and
IsPackageMarkedForLoading( "FreydCategoriesForCAP", ">= 2019.11.02" ) then
diff --git a/SubcategoriesForCAP/read.g b/SubcategoriesForCAP/read.g
index 5389bf890..043519945 100644
--- a/SubcategoriesForCAP/read.g
+++ b/SubcategoriesForCAP/read.g
@@ -7,6 +7,7 @@
ReadPackage( "SubcategoriesForCAP", "gap/Subcategory.gi");
ReadPackage( "SubcategoriesForCAP", "gap/FullSubcategory.gi");
ReadPackage( "SubcategoriesForCAP", "gap/FunctorsForFullSubcategories.gi");
+ReadPackage( "SubcategoriesForCAP", "gap/KleisliReflectiveSubcategoryOfIdempotentMonad.gi");
if IsPackageMarkedForLoading( "Toposes", ">= 2020.02.19" ) and
IsPackageMarkedForLoading( "FreydCategoriesForCAP", ">= 2019.11.02" ) then
@@ -16,3 +17,7 @@ if IsPackageMarkedForLoading( "Toposes", ">= 2020.02.19" ) and
ReadPackage( "SubcategoriesForCAP", "gap/LazySliceCategory.gi");
fi;
+
+if IsPackageMarkedForLoading( "Digraphs", ">= 1.3.1" ) then
+ ReadPackage( "SubcategoriesForCAP", "gap/ToolsUsingDigraphs.gi");
+fi;
diff --git a/ToolsForCategoricalTowers/gap/Tools.gi b/ToolsForCategoricalTowers/gap/Tools.gi
index f3193c34c..18ea5f5c1 100644
--- a/ToolsForCategoricalTowers/gap/Tools.gi
+++ b/ToolsForCategoricalTowers/gap/Tools.gi
@@ -961,6 +961,39 @@ InstallGlobalFunction( PositionsOfSublist,
end );
+##
+InstallMethod( \.,
+ "for an opposite category and a positive integer",
+ [ IsCapCategory and WasCreatedAsOppositeCategory, IsPosInt ],
+
+ function( C_op, string_as_int )
+ local name, C, c;
+
+ name := NameRNam( string_as_int );
+
+ C := OppositeCategory( C_op );
+
+ c := C.(name);
+
+ if IsCapCategoryObject( c ) and IsIdenticalObj( CapCategory( c ), C ) then
+
+ return ObjectConstructor( C_op, c );
+
+ elif IsCapCategoryMorphism( c ) and IsIdenticalObj( CapCategory( c ), C ) then
+
+ return MorphismConstructor( C_op,
+ ObjectConstructor( C_op, Target( c ) ),
+ c,
+ ObjectConstructor( C_op, Source( c ) ) );
+
+ else
+
+ Error( "`c` is neither an object nor a morphism in the category `C := OppositeCategory( C_op )`\n" );
+
+ fi;
+
+end );
+
##
InstallMethod( AllCoproducts,
"for a CAP category and list of objects",