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

Quelle  LimitConvenience.gi   Sprache: unbekannt

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

InstallGlobalFunction( "CAP_INTERNAL_GENERATE_CONVENIENCE_METHODS_FOR_LIMITS",
  function ( package_name, method_name_record, limits )
    local output_string, generate_universal_morphism_convenience, generate_functorial_convenience_method, number_of_diagram_arguments, limit, output_path;
    
    output_string :=
"""# SPDX-License-Identifier: GPL-2.0-or-later
# CAP: Categories, Algorithms, Programming
#
# Implementations
#
# THIS FILE IS AUTOMATICALLY GENERATED, SEE LimitConvenience.gi
""";
    
    #### helper functions
    generate_universal_morphism_convenience := function( limit, universal_morphism_name, object_name, diagram_position )
      local current_string, test_object_position, diagram_filter_list_string, tau_filter, list_selector;
        
        if not diagram_position in [ "Source", "Range" ] then
            
            Error( "diagram_position must be \"Source\" or \"Range\"" );
            
        fi;
        
        if limit.number_of_unbound_morphisms = 0 then
            
            # diagram can be derived from morphism(s) via diagram_position
            
            if limit.number_of_targets = 1 then
                
                Error( "this case is currently not supported" );
                
            elif limit.number_of_targets > 1 then
                
                # derive diagram from morphisms via diagram_position
                current_string := Concatenation(
                    "\n",
                    "##\n",
                    "InstallMethod( ", universal_morphism_name, ",\n",
                    "               [ IsList ],\n",
                    "               \n",
                    "  function( list )\n",
                    "    #% CAP_JIT_RESOLVE_FUNCTION\n",
                    "    \n",
                    "    return ", universal_morphism_name, "( CapCategory( list[1] ), list );\n",
                    "    \n",
                    "end );\n",
                    "\n",
                    "##\n",
                    "InstallOtherMethod( ", universal_morphism_name, ",\n",
                    "               [ IsCapCategory, IsList ],\n",
                    "               \n",
                    "  function( cat, list )\n",
                    "    #% CAP_JIT_RESOLVE_FUNCTION\n",
                    "    \n",
                    "    return ", universal_morphism_name, "( cat, List( list, ", diagram_position, " ), list );\n",
                    "    \n",
                    "end );\n",
                    "\n",
                    "##\n",
                    "InstallOtherMethod( ", universal_morphism_name, ",\n",
                    "               [ IsCapCategoryObject, IsList ],\n",
                    "               \n",
                    "  function( test_object, list )\n",
                    "    #% CAP_JIT_RESOLVE_FUNCTION\n",
                    "    \n",
                    "    return ", universal_morphism_name, "( CapCategory( test_object ), test_object, list );\n",
                    "    \n",
                    "end );\n",
                    "\n",
                    "##\n",
                    "InstallOtherMethod( ", universal_morphism_name, ",\n",
                    "               [ IsCapCategory, IsCapCategoryObject, IsList ],\n",
                    "               \n",
                    "  function( cat, test_object, list )\n",
                    "    #% CAP_JIT_RESOLVE_FUNCTION\n",
                    "    \n",
                    "    return ", universal_morphism_name, "( cat, List( list, ", diagram_position, " ), test_object, list );\n",
                    "    \n",
                    "end );\n"
                );
                
                output_string := Concatenation( output_string, current_string );
                
            fi;
            
        fi;
        
        # derive test object
        if IsOperation( ValueGlobal( universal_morphism_name ) ) then
            
            if diagram_position = "Source" then
                
                test_object_position := "Range";
                
            elif diagram_position = "Range" then
                
                test_object_position := "Source";
                
            else
                
                Error( "this should never happen" );
                
            fi;
            
            if limit.number_of_targets = 1 then
                
                tau_filter := "IsCapCategoryMorphism";
                list_selector := "";
                
            else
                
                tau_filter := "IsList";
                list_selector := "[1]";
                
            fi;
            
            current_string := ReplacedStringViaRecord( """
InstallOtherMethod( without_given_universal_morphism,
                    [ diagram_filter_list..., tau_filter ],
                    
    function( diagram_arguments..., tau )
        #% CAP_JIT_RESOLVE_FUNCTION
        
        return without_given_universal_morphism( diagram_arguments..., test_object_position( selected_tau ), tau );
        
end );

InstallOtherMethod( without_given_universal_morphism,
                    [ IsCapCategory, diagram_filter_list..., tau_filter ],
                    
    function( cat, diagram_arguments..., tau )
        #% CAP_JIT_RESOLVE_FUNCTION
        
        return without_given_universal_morphism( cat, diagram_arguments..., test_object_position( selected_tau ), tau );
        
end );

InstallOtherMethod( with_given_universal_morphism,
                    [ diagram_filter_list..., tau_filter, IsCapCategoryObject ],
                    
    function( diagram_arguments..., tau, P )
        #% CAP_JIT_RESOLVE_FUNCTION
        
        return with_given_universal_morphism( diagram_arguments..., test_object_position( selected_tau ), tau, P );
        
end );

InstallOtherMethod( with_given_universal_morphism,
                    [ IsCapCategory, diagram_filter_list..., tau_filter, IsCapCategoryObject ],
                    
    function( cat, diagram_arguments..., tau, P )
        #% CAP_JIT_RESOLVE_FUNCTION
        
        return with_given_universal_morphism( cat, diagram_arguments..., test_object_position( selected_tau ), tau, P );
        
end );
""",
                rec(
                    without_given_universal_morphism := universal_morphism_name,
                    with_given_universal_morphism := Concatenation( universal_morphism_name, "WithGiven", object_name ),
                    diagram_filter_list := List( CAP_INTERNAL_REPLACED_STRINGS_WITH_FILTERS( limit.diagram_filter_list ), NameFunction ),
                    tau_filter := tau_filter,
                    diagram_arguments := limit.diagram_arguments_names,
                    test_object_position := test_object_position,
                    selected_tau := Concatenation( "tau", list_selector ),
                )
            );
            
            output_string := Concatenation( output_string, current_string );

        fi;
        
    end;
    
    generate_functorial_convenience_method := function( limit, limit_colimit, object_name, functorial_name, functorial_with_given_name )
      local functorial_with_given_record, filter_list, arguments_names, arguments_string, source_diagram_arguments_string, range_diagram_arguments_string, replaced_filter_list, current_string, input_arguments_names, source_argument_name, range_argument_name, source_diagram_arguments_names, range_diagram_arguments_names, equalizer_preprocessing, test_string, additional_preconditions, test_arguments, universal_morphism_with_given_name, call_arguments;
        
        Assert( 0, limit_colimit in [ "limit", "colimit" ] );
        
        functorial_with_given_record := method_name_record.( limit.limit_functorial_with_given_name );
        
        if Length( limit.diagram_filter_list ) > 0 and limit.number_of_unbound_morphisms = 0 and (limit.limit_object_name <> limit.colimit_object_name or limit_colimit = "limit") then
            
            # convenience: derive diagrams from arguments
            filter_list := limit.diagram_morphism_filter_list;
            arguments_names := limit.diagram_morphism_arguments_names;
            
            Assert( 0, Length( filter_list ) = 1 );
            Assert( 0, Length( arguments_names ) = 1 );
            
            arguments_string := JoinStringsWithSeparator( arguments_names, ", " );
            
            if limit.number_of_targets = 1 then
                source_diagram_arguments_string := Concatenation( "Source( ", arguments_string, " )" );
                range_diagram_arguments_string := Concatenation( "Range( ", arguments_string, " )" );
            else
                source_diagram_arguments_string := Concatenation( "List( ", arguments_string, ", Source )" );
                range_diagram_arguments_string := Concatenation( "List( ", arguments_string, ", Range )" );
            fi;
            
            replaced_filter_list := List( CAP_INTERNAL_REPLACED_STRINGS_WITH_FILTERS( filter_list ), NameFunction );
            
            current_string := ReplacedStringViaRecord( """
##
InstallOtherMethod( functorial_name,
                    [ filter_list... ],
               
  function( input_arguments... )
    
    return functorial_name( source_diagram_arguments, input_arguments..., range_diagram_arguments );
    
end );
""",
                rec(
                    functorial_name := functorial_name,
                    filter_list := replaced_filter_list,
                    input_arguments := arguments_names,
                    source_diagram_arguments := source_diagram_arguments_string,
                    range_diagram_arguments := range_diagram_arguments_string,
                )
            );
            
            output_string := Concatenation( output_string, current_string );
            
            # it is safe to use InstallOtherMethodForCompilerForCAP because there is no other two-argument convenience method for functorials
            current_string := ReplacedStringViaRecord( """
##
InstallOtherMethodForCompilerForCAP( functorial_name,
                                     [ IsCapCategory, filter_list... ],
                    
  function( cat, input_arguments... )
    
    return functorial_name( cat, source_diagram_arguments, input_arguments..., range_diagram_arguments );
    
end );
""",
                rec(
                    functorial_name := functorial_name,
                    filter_list := replaced_filter_list,
                    input_arguments := arguments_names,
                    source_diagram_arguments := source_diagram_arguments_string,
                    range_diagram_arguments := range_diagram_arguments_string,
                )
            );
            
            output_string := Concatenation( output_string, current_string );
            
            current_string := ReplacedStringViaRecord( """
##
InstallOtherMethod( functorial_with_given_name,
               [ IsCapCategoryObject, filter_list..., IsCapCategoryObject ],
               
  function( source, input_arguments..., range )
    
    return functorial_with_given_name( source, source_diagram_arguments, input_arguments..., range_diagram_arguments, range );
    
end );
""",
                rec(
                    functorial_with_given_name := functorial_with_given_name,
                    filter_list := replaced_filter_list,
                    input_arguments := arguments_names,
                    source_diagram_arguments := source_diagram_arguments_string,
                    range_diagram_arguments := range_diagram_arguments_string,
                )
            );
            
            output_string := Concatenation( output_string, current_string );
            
            # it is safe to use InstallOtherMethodForCompilerForCAP because there is no other four-argument convenience method for with given functorials
            current_string := ReplacedStringViaRecord( """
##
InstallOtherMethodForCompilerForCAP( functorial_with_given_name,
                                     [ IsCapCategory, IsCapCategoryObject, filter_list..., IsCapCategoryObject ],
               
  function( cat, source, input_arguments..., range )
    
    return functorial_with_given_name( cat, source, source_diagram_arguments, input_arguments..., range_diagram_arguments, range );
    
end );
""",
                rec(
                    functorial_with_given_name := functorial_with_given_name,
                    filter_list := replaced_filter_list,
                    input_arguments := arguments_names,
                    source_diagram_arguments := source_diagram_arguments_string,
                    range_diagram_arguments := range_diagram_arguments_string,
                )
            );
            
            output_string := Concatenation( output_string, current_string );
            
        fi;
        
        # derive functorials from the universality of the limit
        # only do this for limits, colimits will be handled by the automatic dualization of derivations
        if limit_colimit = "limit" then
            
            Assert( 0, Length( limit.diagram_morphism_filter_list ) <= 1 );
            Assert( 0, Length( limit.diagram_morphism_arguments_names ) <= 1 );
            
            input_arguments_names := functorial_with_given_record.input_arguments_names;
            
            source_argument_name := input_arguments_names[2];
            range_argument_name := Last( input_arguments_names );
            
            source_diagram_arguments_names := limit.functorial_source_diagram_arguments_names;
            range_diagram_arguments_names := limit.functorial_range_diagram_arguments_names;
            
            # EqualizerFunctorialWithGivenEqualizers would have 8 arguments if the source objects would be given
            # -> we have to work around this and derive the source objects from the morphism between the diagrams.
            equalizer_preprocessing := "";
            
            if Length( limit.diagram_filter_list ) > 0 then
                
                if limit.number_of_targets = 1 then
                    
                    Assert( 0, limit.diagram_morphism_arguments_names = [ "mu" ] );
                    
                    test_string := ReplacedStringViaRecord(
                        "PreCompose( cat, projection_with_given( cat, source_diagram..., source_object ), mu )",
                        rec(
                            projection_with_given := limit.limit_projection_with_given_name,
                            source_diagram := source_diagram_arguments_names,
                            source_object := source_argument_name,
                        )
                    );
                    
                    additional_preconditions := [ "[ PreCompose, 1 ]", Concatenation( "[ ", limit.limit_projection_with_given_name, ", 1 ]" ) ];
                        
                    if limit.number_of_unbound_morphisms > 1 then
                        
                        if limit.limit_object_name <> "Equalizer" then
                            
                            Error( "This is a hack which might not be valid in general." );
                            
                        fi;
                        
                        # we are in the Equalizer case, which needs special handling (see above)
                        equalizer_preprocessing := "local Y, Yp;\n    \n    Y := Source( mu );\n    Yp := Range( mu );\n    ";
                        
                    fi;
                    
                else
                    
                    Assert( 0, limit.diagram_morphism_arguments_names = [ "L" ] );
                    
                    test_string := ReplacedStringViaRecord(
                        "List( [ 1 .. Length( L ) ], i -> PreCompose( cat, projection_with_given( cat, source_diagram..., i, source_object ), L[i] ) )",
                        rec(
                            projection_with_given := limit.limit_projection_with_given_name,
                            source_diagram := source_diagram_arguments_names,
                            source_object := source_argument_name,
                        )
                    );
                    
                    additional_preconditions := [ "[ PreCompose, 2 ]", Concatenation( "[ ", limit.limit_projection_with_given_name, ", 2 ]" ) ];
                    
                fi;
                
                test_arguments := [ test_string ];
                
            else
                
                Assert( 0, limit.diagram_morphism_arguments_names = [ ] );
                
                test_arguments := [ ];
                
                additional_preconditions := [ ];
                
            fi;
            
            universal_morphism_with_given_name := limit.limit_universal_morphism_with_given_name;
            call_arguments := Concatenation( [ "cat" ], range_diagram_arguments_names, [ source_argument_name ], test_arguments, [ range_argument_name ] );
            
            current_string := ReplacedStringViaRecord( """
##
AddDerivationToCAP( functorial_with_given_name,
                    "functorial_with_given_name using the universality of the limit_colimit",
                    [ preconditions... ],
                    
  function( input_arguments... )
    equalizer_preprocessing
    return universal_morphism_with_given( call_arguments... );
    
end );
""",
                rec(
                    functorial_with_given_name := functorial_with_given_name,
                    input_arguments := input_arguments_names,
                    preconditions := Concatenation( [ Concatenation( "[", universal_morphism_with_given_name, ", 1 ]" ) ], additional_preconditions ),
                    equalizer_preprocessing := equalizer_preprocessing,
                    universal_morphism_with_given := universal_morphism_with_given_name,
                    call_arguments := call_arguments,
                    limit_colimit := limit_colimit,
                )
            );
            
            output_string := Concatenation( output_string, current_string );
            
            # derive functorial of empty limits from IdentityMorphism
            if Length( limit.diagram_filter_list ) = 0 then
                
                current_string := ReplacedStringViaRecord( """
##
AddDerivationToCAP( functorial_name,
                    "functorial_name by taking the identity morphism of object_name",
                    [ [ object_name, 1 ],
                      [ IdentityMorphism, 1 ] ],
                    
  function( cat )
    
    return IdentityMorphism( cat, object_name( cat ) );
    
end );
""",
                    rec(
                        functorial_name := functorial_name,
                        object_name := object_name,
                    )
                );
                
                output_string := Concatenation( output_string, current_string );
                
            fi;
            
        fi;
        
    end;
    
    for limit in limits do
        
        number_of_diagram_arguments := Length( limit.diagram_filter_list );
        
        if number_of_diagram_arguments > 0 then
            
            #### universal morphism convenience
            generate_universal_morphism_convenience( limit, limit.limit_universal_morphism_name, limit.limit_object_name, "Range" );
            generate_universal_morphism_convenience( limit, limit.colimit_universal_morphism_name, limit.colimit_object_name, "Source" );
            
        fi;
        
        #### functorial convenience method
        generate_functorial_convenience_method( limit, "limit", limit.limit_object_name, limit.limit_functorial_name, limit.limit_functorial_with_given_name );
        generate_functorial_convenience_method( limit, "colimit", limit.colimit_object_name, limit.colimit_functorial_name, limit.colimit_functorial_with_given_name );
        
    od;
    
    if not IsExistingFileInPackageForHomalg( package_name, "LimitConvenienceOutput.gi" ) or output_string <> ReadFileFromPackageForHomalg( package_name, "LimitConvenienceOutput.gi" ) then
        
        output_path := Filename( DirectoryTemporary( ), "LimitConvenienceOutput.gi" );
        
        WriteFileForHomalg( output_path, output_string );
        
        Display( Concatenation(
            "WARNING: The file LimitConvenienceOutput.gi differs from the automatically generated one. ",
            "You can view the automatically generated file at the following path: ",
            output_path
        ) );
        
    fi;
    
end );

[ Dauer der Verarbeitung: 0.37 Sekunden  (vorverarbeitet)  ]