# additional components which are deprecated or undocumented
BindGlobal( "CAP_INTERNAL_LEGACY_METHOD_NAME_RECORD_COMPONENTS",
[ "is_merely_set_theoretic", "is_reflected_by_faithful_functor",
]
);
for limit in limits do
object_specification := limit.object_specification;
morphism_specification := limit.morphism_specification;
#### check that given diagram is well-defined if not (IsDenseList( object_specification ) and IsDenseList( morphism_specification )) then
Error( "the given diagram is not well-defined" ); fi;
if Length( object_specification ) = 0 and Length( morphism_specification ) > 0then
Error( "the given diagram is not well-defined" ); fi;
if not (ForAll( object_specification, object -> object in [ "fixedobject", "varobject" ] )) then
Error( "the given diagram is not well-defined" ); fi;
for morphism in morphism_specification do if not (IsList( morphism ) and Length( morphism ) = 3) then
Error( "the given diagram is not well-defined" ); fi;
source_position := morphism[1];
type := morphism[2];
range_position := morphism[3];
if not (IsInt( source_position ) and source_position >= 1 and source_position <= Length( object_specification )) then
Error( "the given diagram is not well-defined" ); fi;
if not (IsInt( range_position ) and range_position >= 1 and range_position <= Length( object_specification )) then
Error( "the given diagram is not well-defined" ); fi;
if not type in [ "fixedmorphism", "varmorphism", "zeromorphism" ] then
Error( "the given diagram is not well-defined" ); fi;
if type = "fixedmorphism" and (object_specification[source_position] = "varobject" or object_specification[range_position] = "varobject") then
Error( "the given diagram is not well-defined" ); fi;
od;
#### get number of variables # morphisms
unbound_morphism_positions := PositionsProperty( morphism_specification, x -> x[2] = "varmorphism" or x[2] = "fixedmorphism" ); if Length( unbound_morphism_positions ) = 0then
number_of_unbound_morphisms := 0; elif Length( unbound_morphism_positions ) = 1 and morphism_specification[unbound_morphism_positions[1]][2] = "fixedmorphism"then
number_of_unbound_morphisms := 1; else
number_of_unbound_morphisms := 2; fi;
if not ForAll( unbound_morphism_positions, i -> morphism_specification[i][2] = "fixedmorphism" or i = Length( unbound_morphism_positions ) ) then
Error( "diagrams of the given type are not supported" ); fi;
# objects
unbound_objects := StructuralCopy( object_specification ); for position in unbound_morphism_positions do
morphism := morphism_specification[position];
source_position := morphism[1];
range_position := morphism[3];
if not ForAll( unbound_object_positions, i -> object_specification[i] = "fixedobject" or i = Length( unbound_object_positions ) ) then
Error( "diagrams of the given type are not supported" ); fi;
# (non-)targets
targets := StructuralCopy( object_specification ); for morphism in morphism_specification do
range_position := morphism[3];
targets[range_position] := "";
od;
target_positions := PositionsProperty( targets, x -> x <> "" );
nontarget_positions := PositionsProperty( targets, x -> x = "" ); if Length( target_positions ) = 0then
number_of_targets := 0; elif Length( target_positions ) = 1 and object_specification[target_positions[1]] = "fixedobject"then
number_of_targets := 1; else
number_of_targets := 2; fi; if Length( nontarget_positions ) = 0then
number_of_nontargets := 0; elif Length( nontarget_positions ) = 1 and object_specification[nontarget_positions[1]] = "fixedobject"then
number_of_nontargets := 1; else
number_of_nontargets := 2; fi;
#### set default projection/injection/universal morphism names if number_of_targets > 0 and not IsBound( limit.limit_projection_name ) then
limit.limit_projection_name := Concatenation( "ProjectionInFactorOf", limit.limit_object_name ); fi; if not IsBound( limit.limit_universal_morphism_name ) then
limit.limit_universal_morphism_name := Concatenation( "UniversalMorphismInto", limit.limit_object_name ); fi;
if number_of_targets > 0 and not IsBound( limit.colimit_injection_name ) then
limit.colimit_injection_name := Concatenation( "InjectionOfCofactorOf", limit.colimit_object_name ); fi; if not IsBound( limit.colimit_universal_morphism_name ) then
limit.colimit_universal_morphism_name := Concatenation( "UniversalMorphismFrom", limit.colimit_object_name ); fi;
if not IsBound( method_record.(entry_name) ) then
Display( Concatenation( "WARNING: The method record is missing a component named \"", entry_name, "\" which is expected by the validator.\n" ) );
return; fi;
for name in RecNames( method_record_entry ) do if name in excluded_names then
continue; fi; if not IsBound( generated_entry.(name) ) then if CAP_NAMED_ARGUMENTS.subset_only then
continue; else
Display( Concatenation( "WARNING: The entry \"", entry_name, "\" in the method record has a component named \"", name, "\" which is not expected by the validator.\n" ) ); fi; elif method_record_entry.(name) <> generated_entry.(name) then
Display( Concatenation( "WARNING: The entry \"", entry_name, "\" in the method record has a component named \"", name, "\" with value \"", String( method_record_entry.(name) ), "\". The value expected by the validator is \"", String( generated_entry.(name) ), "\".\n" ) ); fi;
od; for name in RecNames( generated_entry ) do if name in excluded_names then
continue; fi; if not IsBound( method_record_entry.(name) ) then
Display( Concatenation( "WARNING: The entry \"", entry_name, "\" in the method record is missing a component named \"", name, "\" which is expected by the validator.\n" ) ); fi;
od; end ) );
# The diagram has only objects as input -> all operations are compatible with the congruence of morphisms: # For the universal morphisms and functorials, this follows from the universal property. # All other operations are automatically compatible because they do not have morphisms as input.
# if limit.number_of_targets = 0, the universal morphism has no test morphism as input anyway if limit.number_of_targets > 0then
# GAP has a limit of 6 arguments per operation -> operations which would have more than 6 arguments have to work around this if Length( functorial_with_given_record.filter_list ) <= 6then
# GAP has a limit of 6 arguments per operation -> operations which would have more than 6 arguments have to work around this if Length( functorial_with_given_record.filter_list ) <= 6then
InstallGlobalFunction( CAP_INTERNAL_ADD_REPLACEMENTS_FOR_METHOD_RECORD, function( replacement_data )
local current_name;
for current_name in RecNames( replacement_data ) do if IsBound( CAP_INTERNAL_METHOD_RECORD_REPLACEMENTS.(current_name) ) then
Error( Concatenation( current_name, " already has a replacement" ) ); fi;
CAP_INTERNAL_METHOD_RECORD_REPLACEMENTS.(current_name) := replacement_data.(current_name);
od;
# Check if `object_function` is declared as an attribute and can actually be used as one in our context.
is_attribute := IsAttribute( object_function ) and Length( object_filter_list ) <= 2 and IsSpecializationOfFilter( IsAttributeStoringRep, CAP_INTERNAL_REPLACED_STRING_WITH_FILTER( Last( object_filter_list ) ) );
# If the WithGiven version is more expensive than the WithoutGiven version, redirection makes no sense and # might even lead to inifite loops if the WithGiven version is derived from the WithoutGiven version. if with_given_weight > without_given_weight then
# If the WithGiven version is more expensive than the WithoutGiven version, redirection makes no sense and # might even lead to inifite loops if the WithGiven version is derived from the WithoutGiven version. if with_given_weight > without_given_weight then
return [ false ];
fi;
object_args := arg{ object_arguments_positions };
if attribute_tester( object_args[ Length( object_args ) ] ) then
if source_range_object = "Source"then
object_getter := Source; elif source_range_object = "Range"then
object_getter := Range; else
Error( "the first argument of CAP_INTERNAL_CREATE_POST_FUNCTION must be 'Source' or 'Range'" ); fi;
# Check if `object_function` is declared as an attribute and can actually be used as one in our context.
is_attribute := IsAttribute( object_function ) and Length( object_filter_list ) <= 2 and IsSpecializationOfFilter( IsAttributeStoringRep, CAP_INTERNAL_REPLACED_STRING_WITH_FILTER( Last( object_filter_list ) ) );
if not is_attribute then
return function( arg )
local category, object_args, result, object;
category := arg[ 1 ];
object_args := arg{ object_arguments_positions };
result := arg[ Length( arg ) ];
object := object_getter( result );
Print( "WARNING: The following method name record components are not known: " );
Display( diff );
fi;
# validity checks if not IsBound( current_rec.return_type ) then
Error( "<current_rec> has no return_type" ); fi;
if current_rec.return_type in [ "other_object", "other_morphism" ] then
Error( "The return types \"other_object\" and \"other_morphism\" are not supported anymore. If you need those, please report this using the CAP_projects's issue tracker." ); fi;
if not current_rec.return_type in CAP_INTERNAL_VALID_RETURN_TYPES then
Error( "The return_type of <current_rec> does not appear in CAP_INTERNAL_VALID_RETURN_TYPES. Note that proper filters are not supported anymore." ); fi;
if current_rec.filter_list[1] <> "category"then
Error( "The first entry of `filter_list` must be the string \"category\"." );
fi;
if ForAny( current_rec.filter_list, x -> x in [ "other_category", "other_object", "other_morphism", "other_twocell" ] ) then
Error( "The filters \"other_category\", \"other_object\", \"other_morphism\", and \"other_twocell\" are not supported anymore. If you need those, please report this using the CAP_projects's issue tracker." ); fi;
if IsBound( current_rec.output_source_getter_preconditions ) and not IsBound( current_rec.output_source_getter_string ) then
Error( "output_source_getter_preconditions may only be set if output_source_getter_string is set" );
fi;
if IsBound( current_rec.output_range_getter_preconditions ) and not IsBound( current_rec.output_range_getter_string ) then
Error( "output_range_getter_preconditions may only be set if output_range_getter_string is set" );
fi;
current_rec.function_name := current_recname;
if IsBound( current_rec.pre_function ) and IsString( current_rec.pre_function ) then
if IsBound( record.(current_rec.pre_function) ) and IsBound( record.(current_rec.pre_function).pre_function ) and IsFunction( record.(current_rec.pre_function).pre_function ) then
Error( "Could not find pre function for ", current_recname, ". ", current_rec.pre_function, " is not the name of an operation in the record, has no pre function, or has itself a string as pre function." );
fi;
fi;
if IsBound( current_rec.pre_function_full ) and IsString( current_rec.pre_function_full ) then
if IsBound( record.(current_rec.pre_function_full) ) and IsBound( record.(current_rec.pre_function_full).pre_function_full ) and IsFunction( record.(current_rec.pre_function_full).pre_function_full ) then
Error( "Could not find full pre function for ", current_recname, ". ", current_rec.pre_function_full, " is not the name of an operation in the record, has no full pre function, or has itself a string as full pre function." );
fi;
fi;
if IsBound( current_rec.redirect_function ) and IsString( current_rec.redirect_function ) then
if IsBound( record.(current_rec.redirect_function) ) and IsBound( record.(current_rec.redirect_function).redirect_function ) and IsFunction( record.(current_rec.redirect_function).redirect_function ) then
Error( "Could not find redirect function for ", current_recname, ". ", current_rec.redirect_function, " is not the name of an operation in the record, has no redirect function, or has itself a string as redirect function." );
if IsBound( current_rec.pre_function ) and NumberArgumentsFunction( current_rec.pre_function ) >= 0 and NumberArgumentsFunction( current_rec.pre_function ) <> number_of_arguments then
Error( "the pre function of <current_rec> has the wrong number of arguments" ); fi;
if IsBound( current_rec.pre_function_full ) and NumberArgumentsFunction( current_rec.pre_function_full ) >= 0 and NumberArgumentsFunction( current_rec.pre_function_full ) <> number_of_arguments then
Error( "the full pre function of <current_rec> has the wrong number of arguments" ); fi;
if IsBound( current_rec.redirect_function ) and NumberArgumentsFunction( current_rec.redirect_function ) >= 0 and NumberArgumentsFunction( current_rec.redirect_function ) <> number_of_arguments then
Error( "the redirect function of <current_rec> has the wrong number of arguments" ); fi;
if IsBound( current_rec.post_function ) and NumberArgumentsFunction( current_rec.post_function ) >= 0 and NumberArgumentsFunction( current_rec.post_function ) <> number_of_arguments + 1then
Error( "the post function of <current_rec> has the wrong number of arguments" ); fi;
if IsBound( current_rec.dual_preprocessor_func ) and NumberArgumentsFunction( current_rec.dual_preprocessor_func ) >= 0 and NumberArgumentsFunction( current_rec.dual_preprocessor_func ) <> number_of_arguments then
Error( "the dual preprocessor function of ", current_recname, " has the wrong number of arguments" ); fi;
if not ForAll( current_rec.filter_list, IsString ) then
Error( "Not all entries of filter_list of ", current_recname, " are strings. This is not supported anymore." ); fi;
if not IsBound( current_rec.install_convenience_without_category ) then
if ForAny( [ "object", "morphism", "twocell", "list_of_objects", "list_of_morphisms", "list_of_twocells" ], filter -> filter in current_rec.filter_list ) then
# check that dual of the dual is the original operation
if not IsBound( record.( current_rec.dual_operation ) ) then
Error( "the dual operation must be added in the same call to `CAP_INTERNAL_ENHANCE_NAME_RECORD`" );
fi;
if not IsBound( record.( current_rec.dual_operation ).dual_operation ) then
Error( "the dual operation of ", current_recname, ", i.e. ", current_rec.dual_operation, ", has no dual operation" );
fi;
if record.( current_rec.dual_operation ).dual_operation <> current_recname then
Error( "the dual operation of ", current_recname, ", i.e. ", current_rec.dual_operation, ", has the unexpected dual operation ", record.( current_rec.dual_operation ).dual_operation );
fi;
fi;
if not IsBound( current_rec.dual_arguments_reversed ) then
current_rec.dual_arguments_reversed := false;
fi;
if Length( Filtered( [ "dual_preprocessor_func", "dual_arguments_reversed", "dual_with_given_objects_reversed" ],
name -> IsBound( current_rec.(name) ) and ( IsFunction( current_rec.(name) ) or current_rec.(name) = true )
) ) >= 2then
Error( "dual_preprocessor_func, dual_arguments_reversed = true and dual_with_given_objects_reversed = true are mutually exclusive" );
fi;
if IsBound( current_rec.dual_preprocessor_func ) then
if IsBound( current_rec.dual_preprocessor_func_string ) then
Error( "dual_preprocessor_func and dual_preprocessor_func_string are mutually exclusive" );
fi;
if IsOperation( current_rec.dual_preprocessor_func ) or IsKernelFunction( current_rec.dual_preprocessor_func ) then
if current_rec.input_arguments_names[1] <> "cat"then
Error( "the category argument must always be called \"cat\", please adjust the method record entry of ", current_recname );
fi;
if not ForAll( current_rec.input_arguments_names, x -> IsString( x ) ) then
Error( "the entries of input_arguments_names must be strings, please adjust the method record entry of ", current_recname );
fi;
if not IsDuplicateFreeList( current_rec.input_arguments_names ) then
Error( "input_arguments_names must be duplicate free, please adjust the method record entry of ", current_recname );
fi;
if ForAll( current_rec.filter_list, x -> x in [ "element_of_commutative_ring_of_linear_structure", "integer", "nonneg_integer_or_infinity", "category", "object", "object_in_range_category_of_homomorphism_structure", "list_of_objects" ] ) then
if not IsBound( current_rec.compatible_with_congruence_of_morphisms ) then
if current_rec.compatible_with_congruence_of_morphisms <> true then
Error( current_recname, " does not depend on morphisms but is still marked as not compatible with the congruence of morphisms" );
fi;
fi;
od;
# detect With(out)Given pairs for current_recname in recnames do
current_rec := record.(current_recname);
if IsBound( current_rec.with_given_object_position ) then
if PositionSublist( current_recname, "WithGiven" ) <> fail then
Error( "WithGiven operations must NOT have the component with_given_object_position set, please adjust the method record entry of ", current_recname );
# plausibility checks for without_given_rec if with_given_object_position in [ "Source", "both" ] then
if not IsBound( without_given_rec.output_source_getter_string ) then
Error( "This is a WithoutGiven record, but output_source_getter_string is not set. This is not supported." );
fi;
fi;
if with_given_object_position in [ "Range", "both" ] then
if not IsBound( without_given_rec.output_range_getter_string ) then
Error( "This is a WithoutGiven record, but output_range_getter_string is not set. This is not supported." );
fi;
fi;
if not without_given_rec.return_type in [ "morphism", "morphism_in_range_category_of_homomorphism_structure" ] then
Error( "This is a WithoutGiven record, but return_type is neither \"morphism\" nor \"morphism_in_range_category_of_homomorphism_structure\". This is not supported." );
fi;
# generate with_given_rec if without_given_rec.return_type = "morphism"then
# now enhance the actual with_given_rec
with_given_rec := record.(with_given_name);
if IsBound( without_given_rec.pre_function ) and not IsBound( with_given_rec.pre_function ) then
with_given_rec.pre_function := CAP_INTERNAL_PREPARE_INHERITED_PRE_FUNCTION( record.(without_given_name).pre_function, with_given_object_position = "both" ); fi;
if IsBound( without_given_rec.pre_function_full ) and not IsBound( with_given_rec.pre_function_full ) then
with_given_rec.pre_function_full := CAP_INTERNAL_PREPARE_INHERITED_PRE_FUNCTION( record.(without_given_name).pre_function_full, with_given_object_position = "both" ); fi;
Error( "with_given_object_position is \"both\", but the WithGiven name suggests that only a single object of name ", object_name, " is given. This is not supported." );
if not StartsWith( without_given_rec.output_source_getter_string, object_name ) then
Error( "the output_source_getter_string of the WithoutGiven record does not call the detected object ", object_name );
fi;
fi;
if with_given_object_position = "Range"then
if not StartsWith( without_given_rec.output_range_getter_string, object_name ) then
Error( "the output_range_getter_string of the WithoutGiven record does not call the detected object ", object_name );
fi;
fi;
if not StartsWith( without_given_rec.filter_list, object_filter_list ) then
Error( "the object arguments must be the first arguments of the without given method, but the corresponding filters do not match" );
fi;
if not IsBound( without_given_rec.redirect_function ) then
if Length( record.( without_given_name ).filter_list ) + 1 <> Length( record.( with_given_name ).filter_list ) then
Display( Concatenation( "WARNING: You seem to be relying on automatically installed redirect functions. ", "For this, the with given method must have exactly one additional argument compared to the without given method. ", "This is not the case, so no automatic redirect function will be installed. ", "Install a custom redirect function to prevent this warning."
) );
if not IsEmpty( current_rec.output_source_getter_preconditions ) then
Error( "<current_rec.output_source_getter_preconditions> does not match the automatically detected value" );
fi;
fi;
#= comment for Julia if IsBound( current_rec.output_source_getter_preconditions ) then
if ForAny( current_rec.output_source_getter_preconditions, x -> IsList( x ) and Length( x ) = 3 ) then
Print( "WARNING: preconditions in other categories are not yet supported, please report this using the CAP_projects's issue tracker.\n" );
fi;
if ForAny( current_rec.output_source_getter_preconditions, x -> not IsList( x ) or Length( x ) <> 2 or not IsString( x[1] ) or not IsInt( x[2] ) ) then
Error( "Preconditions must be pairs of names of CAP operations and integers." );
if Set( current_rec.output_source_getter_preconditions ) <> preconditions then
Error( "output_source_getter_preconditions of ", current_recname, " is ", current_rec.output_source_getter_preconditions, " but expected ", preconditions );
fi;
fi; # =#
if IsBound( current_rec.output_source_getter_preconditions ) then
if Set( current_rec.output_range_getter_preconditions ) <> preconditions then
Error( "output_range_getter_preconditions of ", current_recname, " is ", current_rec.output_range_getter_preconditions, " but expected ", preconditions );
fi;
fi; # =#
if IsBound( current_rec.output_range_getter_preconditions ) then
# the space between # and ! prevents AutoDoc from parsing these strings and is removed below
current_string := ReplacedStringViaRecord( """# SPDX-License-Identifier: GPL-2.0-or-later # package_name: package_subtitle # # Declarations # # THIS FILE IS AUTOMATICALLY GENERATED, SEE CAP_project/CAP/gap/MethodRecordTools.gi
# the space between # and ! prevents AutoDoc from parsing these strings and is removed below
current_string := ReplacedStringViaRecord( """ # ! @BeginGroup # ! @Description # ! The arguments are a category $C$ and a function $F$. # ! This operation adds the given function $F$ # ! to the category for the basic operation `function_name`. # ! Optionally, a weight (default: 100) can be specified which should roughly correspond # ! to the computational complexity of the function (lower weight = less complex = faster execution). # ! $F: ( input_arguments... ) \mapsto \mathtt{function_name}(input_arguments...)$. # ! @Returns nothing # ! @Arguments C, F
DeclareOperation( "Addfunction_name",
[ IsCapCategory, IsFunction ] );
if not IsBound( without_given_rec.output_source_getter_preconditions ) then
Print( "WARNING: Cannot install with given derivation pair for ", without_given_name, " because <without_given_rec.output_source_getter_preconditions> is not set.\n" );
return;
if not IsBound( without_given_rec.output_range_getter_preconditions ) then
Print( "WARNING: Cannot install with given derivation pair for ", without_given_name, " because <without_given_rec.output_range_getter_preconditions> is not set.\n" );
return;
if not IsBound( without_given_rec.output_source_getter_preconditions ) then
Print( "WARNING: Cannot install with given derivation pair for ", without_given_name, " because <without_given_rec.output_source_getter_preconditions> is not set.\n" );
return;
fi;
if not IsBound( without_given_rec.output_range_getter_preconditions ) then
Print( "WARNING: Cannot install with given derivation pair for ", without_given_name, " because <without_given_rec.output_range_getter_preconditions> is not set.\n" );
return;
fi;
# merge output_source_getter_preconditions and output_range_getter_preconditions
additional_preconditions := without_given_rec.output_source_getter_preconditions;
for x in without_given_rec.output_range_getter_preconditions do
pos := PositionProperty( additional_preconditions, y -> y[1] = x[1] );
if not IsExistingFileInPackageForHomalg( package_name, gd_filename ) or gd_output_string <> ReadFileFromPackageForHomalg( package_name, gd_filename ) then
Display( Concatenation( "WARNING: The file ", gd_filename, " in package ", package_name, " differs from the automatically generated one. ", "You can view the automatically generated file at the following path: ",
output_path
) );
if not IsExistingFileInPackageForHomalg( package_name, gi_filename ) or gi_output_string <> ReadFileFromPackageForHomalg( package_name, gi_filename ) then
Display( Concatenation( "WARNING: The file ", gi_filename, " in package ", package_name, " differs from the automatically generated one. ", "You can view the automatically generated file at the following path: ",
output_path
) );
# the space between # and ! prevents AutoDoc from parsing these strings and is removed below
current_string := ReplacedStringViaRecord( """# SPDX-License-Identifier: GPL-2.0-or-later # package_name: package_subtitle # # Declarations # # THIS FILE IS AUTOMATICALLY GENERATED, SEE CAP_project/CAP/gap/MethodRecord.gi
# We do not want to include operations from optional dependencies because those might not be available.
transitively_needed_other_packages := TransitivelyNeededOtherPackages( package_name );
for i in [ 1 .. Length( subsections ) ] do
subsection := subsections[i];
Assert( 0, IsList( subsection ) and Length( subsection ) in [ 2, 3 ] );
if not IsSubset( operations, subsections[parent_index][4] ) then
Error( "the operations of the category", Name( subsections[i - 1][1] ), " are not a subset of the operations of the category ", Name( subsections[i][1] ) );
current_string := Concatenation( "\n\n# ! Additional to the operations listed in “", subsections[parent_index][2], "” the following operations are supported:" );
fi;
if IsEmpty( operations ) then
Display( "WARNING: No operations found, skipping subection" );
Display( Concatenation( "WARNING: The file ", filename, " in package ", package_name, " differs from the automatically generated one. ", "You can view the automatically generated file at the following path: ",
output_path
) );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.