Raw File
LIMOR.gi
# SPDX-License-Identifier: GPL-2.0-or-later
# homalg: A homological algebra meta-package for computable Abelian categories
#
# Implementations
#

##         LIMOR = Logical Implications for homalg MORphisms

####################################
#
# global variables:
#
####################################

# a central place for configuration variables:

InstallValue( LIMOR,
        rec(
            color := "\033[4;30;46m",
            intrinsic_properties :=
            [ "IsZero",
              "IsMorphism",
              "IsGeneralizedMorphismWithFullDomain",
              "IsGeneralizedEpimorphism",
              "IsGeneralizedMonomorphism",
              "IsGeneralizedIsomorphism",
              "IsOne",
              "IsIdempotent",
              "IsMonomorphism",
              "IsEpimorphism",
              "IsSplitMonomorphism",
              "IsSplitEpimorphism",
              "IsIsomorphism",
              "IsAutomorphism" ],
            intrinsic_attributes :=
            [ "DegreeOfMorphism" ],
          )
        );

##
InstallValue( LogicalImplicationsForHomalgMorphisms,
        [ 
          ## IsZero does not imply IsMorphism!!!
          [ IsZero,
            "implies", IsGeneralizedMorphismWithFullDomain ],
          
          [ IsMorphism,
            "implies", IsGeneralizedMorphismWithFullDomain ],
          
# Comply with CAP: no mathematical properties should imply IsMorphism
#          [ IsMonomorphism,
#            "implies", IsMorphism ],
          
          [ IsMonomorphism,
            "implies", IsGeneralizedMonomorphism ],
          
          [ IsGeneralizedMonomorphism,
            "implies", IsGeneralizedMorphismWithFullDomain ],
          
# Comply with CAP: no mathematical properties should imply IsMorphism
#          [ IsEpimorphism,
#            "implies", IsMorphism ],
          
          [ IsEpimorphism,
            "implies", IsGeneralizedEpimorphism ],
          
          [ IsGeneralizedEpimorphism,
            "implies", IsGeneralizedMorphismWithFullDomain ],
          
          [ IsAutomorphism,
            "implies", IsIsomorphism ],
          
          [ IsIsomorphism,
            "implies", IsGeneralizedIsomorphism ],
          
          [ IsIsomorphism,
            "implies", IsSplitMonomorphism ],
          
          [ IsIsomorphism,
            "implies", IsSplitEpimorphism ],
          
          [ IsSplitEpimorphism,
            "implies", IsEpimorphism ],
          
          [ IsSplitMonomorphism,
            "implies", IsMonomorphism ],
          
          [ IsEpimorphism, "and", IsMonomorphism,
            "imply", IsIsomorphism ],
          
          [ IsGeneralizedIsomorphism,
            "implies", IsGeneralizedMonomorphism ],
          
          [ IsGeneralizedIsomorphism,
            "implies", IsGeneralizedEpimorphism ],
          
          [ IsGeneralizedEpimorphism, "and", IsGeneralizedMonomorphism,
            "imply", IsGeneralizedIsomorphism ],
          
          ## this is wrong:
          ## [ IsGeneralizedEpimorphism, "and", IsMorphism,
          ##  "imply", IsEpimorphism ],
          
          [ IsGeneralizedMonomorphism, "and", IsMorphism,
            "imply", IsMonomorphism ],
          
          [ IsOne,
            "implies", IsAutomorphism ],
          
          ] );

##
InstallValue( LogicalImplicationsForHomalgEndomorphisms,
        [ 
          
          [ IsZero, "and", IsMorphism,
            "imply", IsIdempotent ],
          
          [ IsOne, "and", IsMorphism,
            "imply", IsIdempotent ],
          
          [ IsIsomorphism,
            "implies", IsAutomorphism ],
          
          ] );

####################################
#
# logical implications methods:
#
####################################

InstallLogicalImplicationsForHomalgObjects( LogicalImplicationsForHomalgMorphisms, IsHomalgMorphism );

InstallLogicalImplicationsForHomalgObjects( LogicalImplicationsForHomalgEndomorphisms, IsHomalgEndomorphism );

####################################
#
# immediate methods for properties:
#
####################################

##
InstallImmediateMethod( IsZero,
        IsHomalgMorphism, 0,
        
  function( phi )
    
    if ( HasIsZero( Source( phi ) ) and IsZero( Source( phi ) ) ) and ## to place "or" here we need to know that phi is a morphism;
       ( HasIsZero( Range( phi ) ) and IsZero( Range( phi ) ) ) then  ## see the method below
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMorphism and IsMorphism, 0,
        
  function( phi )
    
    if ( HasIsZero( Source( phi ) ) and IsZero( Source( phi ) ) ) or
       ( HasIsZero( Range( phi ) ) and IsZero( Range( phi ) ) ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMorphism and IsMonomorphism, 0,
        
  function( phi )
    local S;
    
    S := Source( phi );
    
    if HasIsZero( S ) then
        return IsZero( S );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsZero,
        IsHomalgMorphism and IsEpimorphism, 0,
        
  function( phi )
    local T;
    
    T := Range( phi );
    
    if HasIsZero( T ) then
        return IsZero( T );
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsMorphism,
        IsHomalgMorphism and IsZero, 0,
        
  function( phi )
    
    if HasMorphismAid( phi ) then
        TryNextMethod( );
    fi;
    
    return true;
    
end );

##
InstallImmediateMethod( IsSplitEpimorphism,
        IsHomalgStaticMorphism and IsEpimorphism, 0,
        
  function( phi )
    local T;
    
    T := Range( phi );
    
    if HasIsProjective( T ) and IsProjective( T ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
## this immediate method together with the above ture-method
## IsZero => IsMorphism
## are essential to avoid infinite loops that
## Assert( 5, IsMonomorphism( emb ) );
## in _Functor_ImageObject_OnObjects may cause
##
InstallImmediateMethod( IsSplitMonomorphism,
        IsHomalgMorphism and IsMorphism, 0,
        
  function( phi )
    local S;
    
    S := Source( phi );
    
    if HasIsZero( S ) and IsZero( S ) then
        return true;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsAutomorphism,
        IsHomalgMorphism, 0,
        
  function( phi )
    
    if not IsIdenticalObj( Source( phi ), Range( phi ) ) then
        return false;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallImmediateMethod( IsIdempotent,
        IsHomalgMorphism, 0,
        
  function( phi )
    
    if not IsIdenticalObj( Source( phi ), Range( phi ) ) then
        return false;
    fi;
    
    TryNextMethod( );
    
end );

####################################
#
# methods for properties:
#
####################################

##
InstallMethod( IsMorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism and HasMorphismAid ], 10001,
        
  function( phi )
    
    if not IsZero( MorphismAid( phi ) ) then
        return false;
    fi;
    
    TryNextMethod( );
    
end );

##
InstallMethod( IsGeneralizedMorphismWithFullDomain,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    
    if HasMorphismAid( phi ) then
        TryNextMethod( );
    fi;
    
    return IsMorphism( phi );
    
end );

##
InstallMethod( IsGeneralizedMorphismWithFullDomain,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism and HasMorphismAid ],
        
  function( phi )
    
    return IsMorphism( AssociatedMorphismOfGeneralizedMorphismWithFullDomain( phi ) );
    
end );

##
InstallMethod( IsEpimorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    local b, S, T;
    
    b := IsMorphism( phi ) and IsZero( Cokernel( phi ) );
    
    if b then
        S := Source( phi );
        T := Range( phi );
        
        if HasIsTorsion( T ) and not IsTorsion( T ) then
            SetIsTorsion( S, false );
        elif HasIsTorsion( S ) and IsTorsion( S ) then
            SetIsTorsion( T, true );
        fi;
    fi;
    
    return b;
    
end );

##
InstallMethod( IsGeneralizedEpimorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    
    ## this is just the fall back method
    return IsEpimorphism( phi );
    
end );

##
InstallMethod( IsGeneralizedEpimorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism and HasMorphismAid ],
        
  function( phi )
    local mu;
    
    mu := AssociatedMorphismOfGeneralizedMorphismWithFullDomain( phi );
    
    SetIsGeneralizedMorphismWithFullDomain( phi, IsMorphism( mu ) );
    
    return IsEpimorphism( mu );
    
end );

##
InstallMethod( IsSplitEpimorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    local split;
    
    if not IsEpimorphism( phi ) then
        return false;
    fi;
    
    split := PreInverse( phi );
    
    if split = fail then
        TryNextMethod( );
    fi;
    
    return split <> false;
    
end );

##
InstallMethod( IsMonomorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    local b, S, T;
    
    b := IsMorphism( phi ) and IsZero( Kernel( phi ) );
    
    if b then
        S := Source( phi );
        T := Range( phi );
        
        if HasIsTorsionFree( T ) and IsTorsionFree( T ) then
            SetIsTorsionFree( S, true );
        elif HasIsTorsionFree( S ) and not IsTorsionFree( S ) then
            SetIsTorsionFree( T, false );
        fi;
        
        if HasIsTorsion( T ) and IsTorsion( T ) then
            SetIsTorsion( S, true );
        elif HasIsTorsion( S ) and not IsTorsion( S ) then
            SetIsTorsion( T, false );
        fi;
    fi;
    
    return b;
    
end );

##
InstallMethod( IsGeneralizedMonomorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    
    ## this is just the fall back method
    return IsMonomorphism( phi );
    
end );

##
InstallMethod( IsGeneralizedMonomorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism and HasMorphismAid ],
        
  function( phi )
    local mu;
    
    mu := AssociatedMorphismOfGeneralizedMorphismWithFullDomain( phi );
    
    SetIsGeneralizedMorphismWithFullDomain( phi, IsMorphism( mu ) );
    
    return IsMonomorphism( mu );
    
end );

##
InstallMethod( IsIsomorphism,
        "LIMOR: for homalg morphisms",
        [ IsHomalgMorphism ],
        
  function( phi )
    local iso;
    
    iso := IsEpimorphism( phi ) and IsMonomorphism( phi );
    
    if iso then
        SetIsIsomorphism( phi, true ); ## needed for UpdateObjectsByMorphism
        UpdateObjectsByMorphism( phi );
    fi;
    
    return iso;
    
end );

##
InstallMethod( IsGeneralizedIsomorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    
    ## this is just the fall back method
    return IsIsomorphism( phi );
    
end );

##
InstallMethod( IsGeneralizedIsomorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism and HasMorphismAid ],
        
  function( phi )
    local mu;
    
    mu := AssociatedMorphismOfGeneralizedMorphismWithFullDomain( phi );
    
    SetIsGeneralizedMorphismWithFullDomain( phi, IsMorphism( mu ) );
    
    SetIsGeneralizedMonomorphism( phi, IsMonomorphism( mu ) );
    
    return IsIsomorphism( mu );
    
end );

##
InstallMethod( IsAutomorphism,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism ],
        
  function( phi )
    
    return IsHomalgEndomorphism( phi ) and IsIsomorphism( phi );
    
end );

##
InstallMethod( IsIdempotent,
        "LIMOR: for homalg morphisms",
        [ IsHomalgMorphism ],
        
  function( phi )
    
    return IsHomalgEndomorphism( phi ) and IsZero( phi^2 - phi );
    
end );

####################################
#
# methods for attributes:
#
####################################

## Cf. [Bar, Cor. 4.8]
InstallMethod( InverseOfGeneralizedMorphismWithFullDomain,
        "LIMOR: for morphisms of homalg static objects",
        [ IsHomalgStaticMorphism and IsEpimorphism ],
        
  function( epsilon )
    local gen_iso, aid;
    
    ## the generalized inverse of the epimorphism
    gen_iso := epsilon^-1;
    
    ## the morphism aid map of the generalized inverse
    aid := MorphismHavingSubobjectAsItsImage( KernelSubobject( epsilon ) );
    
    ## set the morphism aid map
    gen_iso := AddToMorphismAid( gen_iso, aid );
    
    ## check assertion
    Assert( 5, IsGeneralizedIsomorphism( gen_iso ) );
    
    SetIsGeneralizedIsomorphism( gen_iso, true );
    
    return gen_iso;
    
end );

##
InstallMethod( Cokernel,
        "for homalg static morphisms",
        [ IsStaticMorphismOfFinitelyGeneratedObjectsRep and HasDirectSummands ], 1001,
        
  function( phi )
    local phis, coker, epi;
    
    phis := DirectSummands( phi );
    
    coker := List( phis, Cokernel );
    
    coker := DirectSum( coker );
    
    epi := List( phis, CokernelEpi );
    
    epi := DiagonalMorphism( epi );
    
    SetCokernelEpi( phi, epi );
    
    return coker;
    
end );

####################################
#
# methods for operations:
#
####################################

##
InstallMethod( SetPropertiesOfGeneralizedMorphism,
        "for two homalg morphisms",
        [ IsHomalgMorphism,
          IsHomalgMorphism ],
        
  function( psi, phi )
    
    homalgResetFilters( psi );
    
    if HasIsZero( phi ) and IsZero( phi ) then
        SetIsZero( psi, true );
    fi;
    
    ## this is wrong:
    ## if HasIsIsomorphism( phi ) and IsIsomorphism( phi ) then
    ##     SetIsGeneralizedIsomorphism( psi, true );
    ## fi;
    
    if HasIsGeneralizedEpimorphism( phi ) and IsGeneralizedEpimorphism( phi ) then
        SetIsGeneralizedEpimorphism( psi, true );
    elif HasIsGeneralizedMorphismWithFullDomain( phi ) and IsGeneralizedMorphismWithFullDomain( phi ) then
        SetIsGeneralizedMorphismWithFullDomain( psi, true );
    fi;
    
    return psi;
    
end );

##
InstallMethod( SetPropertiesOfAdditiveInverse,
        "for two homalg morphisms",
        [ IsHomalgMorphism,
          IsHomalgMorphism ],
        
  function( psi, phi )
    
    if HasIsMorphism( phi ) then
        SetIsMorphism( psi, IsMorphism( phi ) );
    fi;
    if HasMorphismAid( phi ) then
        psi := AddToMorphismAid( psi, MorphismAid( phi ) );
    fi;
    if HasIsGeneralizedMorphismWithFullDomain( phi ) then
        SetIsGeneralizedMorphismWithFullDomain( psi, IsGeneralizedMorphismWithFullDomain( phi ) );
    fi;
    if HasIsEpimorphism( phi )  then
        SetIsEpimorphism( psi, IsEpimorphism( phi ) );
    fi;
    if HasIsMonomorphism( phi )  then
        SetIsMonomorphism( psi, IsMonomorphism( phi ) );
    fi;
    
    return psi;
    
end );
back to top