##############################################################################
##
#W  actor2.gi                      XMOD Package                  Chris Wensley
#W                                                                 & Murat Alp
##
##  Declaration file for functions of the XMOD package.
##
#H  @(#)$Id: actor2.gi,v 2.007 2006/07/04 gap Exp $
##
#Y  Copyright (C) 1999,2001 University of St. Andrews, North Haugh,
#Y                          St. Andrews, Fife KY16 9SS, Scotland
##
Revision.("xmod/gap/actor2_gd") := 
   "@(#)$Id: actor2.gi,v 2.007 2006/07/04 gap Exp $";

#############################################################################
##
#M  AutomorphismPermGroup( <XM> )  subgroup of Aut(Source(XM))xAut(Range(XM))
##
##  revised version 21/06/06
##
InstallMethod( AutomorphismPermGroup, "automorphism perm group of xmod", 
    true, [ IsXMod ], 0, 
function( XM )

    local  S, genS, ngS, R, genR, ngR, bdy, act, 
           AS, genAS, a2pS, PAS, genPAS, p2aS,
           AR, genAR, a2pR, PAR, genPAR, p2aR, 
           D, genD, emS, emR, emgenPAS, emgenPAR, emAS, emAR, infoD, 
           P, num, autogens, as, eas, ar, ear, mor, ispre, ismor, 
           genP, p2, p2i, newS, oldS, newR, oldR, imsrc, imrng, 
           projS, projR, ePAS, egenR, ePAR;

    S := Source( XM );
    genS := GeneratorsOfGroup( S );
    ngS := Length( genS );
    R := Range( XM );
    genR := GeneratorsOfGroup( R );
    ngR := Length( genR );
    bdy := Boundary( XM );
    act := XModAction( XM );

    AS := AutomorphismGroup( S );
    genAS := GeneratorsOfGroup( AS );
    a2pS := IsomorphismSmallPermGroup( AS );
    PAS := Image( a2pS );
    genPAS := List( genAS, a -> Image( a2pS, a ) );
    p2aS := GroupHomomorphismByImagesNC( PAS, AS, genPAS, genAS );
    SetIsomorphismAutoGroup( PAS, p2aS );

    AR := AutomorphismGroup( R );
    genAR := GeneratorsOfGroup( AR );
    a2pR := IsomorphismSmallPermGroup( AR );
    PAR := Image( a2pR );
    genPAR := List( genAR, a -> Image( a2pR, a ) );
    p2aR := GroupHomomorphismByImagesNC( PAR, AR, genPAR, genAR );
    SetIsomorphismAutoGroup( PAR, p2aR );

    D := DirectProduct( PAS, PAR );
    genD := GeneratorsOfGroup( D );
    if ( HasName( PAS ) and HasName( PAR ) ) then
        SetName( D, Concatenation( Name(PAS), "x", Name(PAR) ) );
    fi;
    emS := Embedding( D, 1 );
    emR := Embedding( D, 2 );
    emgenPAS := List( genPAS, a -> Image( emS, a ) );
    emgenPAR := List( genPAR, a -> Image( emR, a ) );
    emAS := GroupHomomorphismByImages( AS, D, genAS, emgenPAS );
    emAR := GroupHomomorphismByImages( AR, D, genAR, emgenPAR );
    infoD := DirectProductInfo( D );
    P := Subgroup( D, [ ] );
    num := 0;
    autogens := [ ];
    for as in AS do 
        eas := Image( emAS, as );
        for ar in AR do 
            ear := Image( emAR, ar );
            if not ( eas*ear in P ) then
                mor := Make2dMapping( XM, XM, as, ar );
                ispre := IsPreXModMorphism( mor );
                if ispre then 
                    ismor := IsXModMorphism( mor );
                    if ismor then
                        num := num + 1;
                        Add( autogens, mor );
                        P := ClosureGroup( P, eas*ear );
                        Info( InfoXMod, 2, "size of P now ", Size(P) );
                    fi;
                fi;
            fi;
        od;
    od;
    genP := GeneratorsOfGroup( P );
    p2 := infoD.perms[2];
    p2i := p2^(-1);
    newS := infoD.news[1];  oldS := infoD.olds[1];
    newR := infoD.news[2];  oldR := infoD.olds[2];
    imsrc := List( genP, g -> 
                   MappingPermListList( oldS, List( newS, x->(x^g) ) ) );
    imrng := List( genP, g -> 
                   MappingPermListList( oldR, List( newR, x->(x^g)^p2i ) ) );
    projS := GroupHomomorphismByImages( P, PAS, genP, imsrc );
    projR := GroupHomomorphismByImages( P, PAR, genP, imrng );
    ### 21/06/06 ### genPAS := GeneratorsOfGroup( PAS );
    ePAS := GroupHomomorphismByImages( PAS, D, genPAS, genPAS );
    ### 21/06/06 ### genPAR := GeneratorsOfGroup( PAR );
    egenR := List( genPAR, p -> p^p2 );
    ePAR := GroupHomomorphismByImages( PAR, D, genPAR, egenR );
    SetGeneratingAutomorphisms( XM, autogens );
    SetIsAutomorphismPermGroupOfXMod( P, true );
    ### 22/06/06 ###
    ### these two functions would better be  AS -> P
    SetEmbedSourceAutos( P, ePAS );
    SetEmbedRangeAutos( P, ePAR );
    SetSourceProjection( P, projS );
    SetRangeProjection( P, projR );
    SetXModActedUpon( P, XM );
    return P;
end );

#######  special version for XModByNormalSubgroup xmods, 23/06/06  #######

InstallMethod( AutomorphismPermGroup, "automorphism perm group of xmod", 
    true, [ IsXMod and IsNormalSub2dObject ], 0, 
function( XM )

    local  S, genS, R, genR, autR, autS, AR, genAR, ngAR, AS, genAS, ar, as, 
           a2pR, PAR, genPAR, p2aR, a2pS, PAS, genPAS, p2aS, restrict, 
           D, genD, emS, emR, emgenPAS, emgenPAR, emAS, emAR, infoD, 
           P, genP, autogens, j, p2, p2i, newS, newR, oldS, oldR, 
           imsrc, imrng, projS, projR, filtS, ePAS, egenR, ePAR;

    Info( InfoXMod, 1, "using special AutomorphismPermGroup method" );

    S := Source( XM );
    genS := GeneratorsOfGroup( S );
    R := Range( XM );
    genR := GeneratorsOfGroup( R );

    autR := AutomorphismGroup( R );
    autS := AutomorphismGroup( S );
    genAR := [ ];
    genAS := [ ]; 
    AR := Subgroup( autR, [ IdentityMapping( R ) ] );
    AS := Subgroup( autS, [ IdentityMapping( S ) ] );
    for ar in autR do
        as := RestrictionMappingGroups( ar, S, S ); 
        if not ( as = fail ) then 
            if not ( ar in AR ) then 
                Add( genAR, ar );
                Add( genAS, as );
                AR := ClosureGroup( AR, ar );
                AS := ClosureGroup( AS, as );
            fi;
        fi;
    od;
    Info( InfoXMod, 2, " genAR = ", genAR );
    Info( InfoXMod, 2, " genAS = ", genAS );
    ngAR := Length( genAR );
    a2pR := IsomorphismSmallPermGroup( AR );
    PAR := Image( a2pR, AR );
    genPAR := List( genAR, a -> Image( a2pR, a ) );
    p2aR := GroupHomomorphismByImagesNC( PAR, AR, genPAR, genAR );
    SetIsomorphismAutoGroup( PAR, p2aR );
    a2pS := IsomorphismSmallPermGroup( AS );
    PAS := Image( a2pS, AS );
    genPAS := List( genAS, a -> Image( a2pS, a ) );
    Info( InfoXMod, 2, "genPAS = ", genPAS );
    p2aS := GroupHomomorphismByImagesNC( PAS, AS, genPAS, genAS );
    SetIsomorphismAutoGroup( PAS, p2aS );
    restrict := GroupHomomorphismByImages( PAR, PAS, genPAR, genPAS );

    D := DirectProduct( PAS, PAR );
    genD := GeneratorsOfGroup( D );
    if ( HasName( PAS ) and HasName( PAR ) ) then
        SetName( D, Concatenation( Name(PAS), "x", Name(PAR) ) );
    fi;
    emS := Embedding( D, 1 );
    emR := Embedding( D, 2 );
    filtS := Filtered( [1..ngAR], i -> not IsOne( genPAS[i] ) );
    emgenPAS := List( genPAS, a -> Image( emS, a ) );
    emgenPAR := List( genPAR, a -> Image( emR, a ) );
    emAS := GroupHomomorphismByImages( AS, D, genAS{filtS}, emgenPAS{filtS} );
    emAR := GroupHomomorphismByImages( AR, D, genAR, emgenPAR );
    infoD := DirectProductInfo( D );

    genP := ListWithIdenticalEntries( ngAR, 0 );
    autogens := ListWithIdenticalEntries( ngAR, 0 );
    for j in [1..ngAR] do
        genP[j] := Image( emAS, genAS[j] ) * Image( emAR, genAR[j] );
        autogens[j] := XModMorphism( XM, XM, genAS[j], genAR[j] );
    od;
    P := Subgroup( D, genP );

    p2 := infoD.perms[2];
    p2i := p2^(-1);
    newS := infoD.news[1];  oldS := infoD.olds[1];
    newR := infoD.news[2];  oldR := infoD.olds[2];
    imsrc := List( genP, g -> 
                   MappingPermListList( oldS, List( newS, x->(x^g) ) ) );
    imrng := List( genP, g -> 
                   MappingPermListList( oldR, List( newR, x->(x^g)^p2i ) ) );
    projS := GroupHomomorphismByImages( P, PAS, genP, imsrc );
    projR := GroupHomomorphismByImages( P, PAR, genP, imrng );
    ePAS := GroupHomomorphismByImages( PAS, D, genPAS{filtS}, genPAS{filtS} );
    egenR := List( genPAR, p -> p^p2 );
    ePAR := GroupHomomorphismByImages( PAR, D, genPAR, egenR );

    SetGeneratingAutomorphisms( XM, autogens );
    SetIsAutomorphismPermGroupOfXMod( P, true );
    SetEmbedSourceAutos( P, ePAS );
    SetEmbedRangeAutos( P, ePAR );
    SetSourceProjection( P, projS );
    SetRangeProjection( P, projR );
    SetXModActedUpon( P, XM );
    return P;
end );

#############################################################################
##
#M  PermAutomorphismAsXModMorphism( <xmod>, <permaut> )
##
InstallMethod( PermAutomorphismAsXModMorphism, 
    "xmod morphism coresponding to an element of the AutomorphismPermGroup",
    true, [ IsXMod, IsPerm ], 0, 
function( XM, a )

    local APXM, sp, rp, sa, ra, si, ri, smor, rmor, mor;

    APXM := AutomorphismPermGroup( XM );
    sp := SourceProjection( APXM );
    sa := Image( sp, a );
    si := IsomorphismAutoGroup( Range( sp ) );
    smor := Image( si, sa );
    rp := RangeProjection( APXM );
    ra := Image( rp, a );
    ri := IsomorphismAutoGroup( Range( rp ) );
    rmor := Image( ri, ra );
    mor := XModMorphism( XM, XM, smor, rmor ); 
    return mor;
end );

#############################################################################
##
#M  ImageAutomorphismDerivation( <mor>, <chi> )
##
InstallMethod( ImageAutomorphismDerivation, "image of derivation under action",
    true, [ IsXModMorphism, IsDerivation ], 0, 
function( mor, chi )

    local  XM, R, stgR, imj, rho, imrho, sigma, invrho,
           rngR, k, r, rr, crr, chj;

    XM := Source( mor );
    sigma := SourceHom( mor );
    rho := RangeHom( mor );
    R := Range( XM );
    stgR := StrongGeneratorsStabChain( StabChain( R ) );
    rngR := [ 1..Length( stgR ) ];
    imrho := List( stgR, r -> Image( rho, r ) );
    invrho := GroupHomomorphismByImages( R, R, imrho, stgR );
    imj := 0 * rngR;
    for k in rngR do
        r := stgR[k];
        rr := Image( invrho, r );
        crr := DerivationImage( chi, rr );
        imj[k] := Image( sigma, crr );
    od;
    chj := DerivationByImages( XM, imj );
    return chj;
end );

#############################################################################
##
#M  WhiteheadXMod( <XM> )     (InnerSourceHom : Range(XM) -> Whitehead Group)
##
InstallMethod( WhiteheadXMod, "Whitehead crossed module", true, 
    [ IsXMod ], 0, 
function( XM )
    local  S, genS, reg, imreg, W, WT, posW, nposW, genW, imiota,
           s, chi, poschi, iota, autS, genchi, j, sigma, ima, a, 
           imact, act, WX, name;

    S := Source( XM );
    genS := GeneratorsOfGroup( S );
    reg := RegularDerivations( XM );
    imreg := ImagesList( reg );
    W := WhiteheadPermGroup( XM );
    WT := WhiteheadGroupTable( XM );
    posW := WhiteheadGroupGeneratorPositions( XM );
    nposW := Length( posW );
    genW := GeneratorsOfGroup( W );
    # determine the boundary map iota = PrincipalSourceHom
    imiota := [ ];
    for s in genS do
        chi := PrincipalDerivation( XM, s );
        poschi := Position( imreg, GeneratorImages( chi ) );
        Add( imiota, PermList( WT[poschi] ) );
    od;
    iota := GroupHomomorphismByImages( S, W, genS, imiota );
    ##  ????? should this be a general mapping ????????????????????
    if not IsGroupHomomorphism( iota ) then
        Error( "Whitehead boundary fails to be a homomorphism" );
    fi;
    # now calculate the action homomorphism
    autS := AutomorphismGroup( S );
    genchi := WhiteheadGroupGeneratingDerivations( XM );
    imact := [ 1..nposW ];
    for j in [1..nposW] do
        chi := genchi[j];
        sigma := SourceEndomorphism( chi );
        ima := List( genS, s -> Image( sigma, s ) );
        a := GroupHomomorphismByImages( S, S, genS, ima );
        imact[j] := a;
    od;
    act := GroupHomomorphismByImages( W, autS, genW, imact );
    WX := XMod( iota, act );
    name := Name( XM );
    SetName( WX, Concatenation( "Whitehead", name ) );
    ## SetIsWhiteheadXMod( WX, true );
    return WX;
end );

#############################################################################
##
#M  NorrieXMod( <XM> )
##
##  revised  23/06/06
##
InstallMethod( NorrieXMod, "Norrie crossed module", true,
    [ IsXMod ], 0, 
function( XM )

    local  S, R, genR, P, DX, genP, Prng, 
           AS, AR, a2pS, PAS, p2aS, a2pR, PAR, p2aR, 
           im, r, autr, psrc, emsrc, conjr, prng, emrng, bdy, ok,
           imact, p, projp, proja, ima, a, act, i, f, NX, name;

    S := Source( XM );
    R := Range( XM );
    genR := GeneratorsOfGroup( R );
    P := AutomorphismPermGroup( XM );
    DX := Parent( P );
    genP := GeneratorsOfGroup( P );
    Prng := [ 1..Length( genP ) ];
    ########## 23/06/06 revision ########
    PAR := Image( RangeProjection( P ) ); 
    if HasIsomorphismAutoGroup( PAR ) then 
        p2aR := IsomorphismAutoGroup( PAR ); 
    elif ( HasParent( PAR ) and HasIsomorphismAutoGroup( Parent(PAR) ) ) then 
        p2aR := IsomorphismAutoGroup( Parent( PAR ) );
    else
        Error( "IsomorphismAutoGroup unavailable for PAR" );
    fi; 
    AR := Image( p2aR );
    a2pR := InverseGeneralMapping( p2aR );
    PAS := Image( SourceProjection( P ) ); 
    if HasIsomorphismAutoGroup( PAS ) then 
        p2aS := IsomorphismAutoGroup( PAS ); 
    elif ( HasParent( PAS ) and HasIsomorphismAutoGroup( Parent(PAS) ) ) then 
        p2aS := IsomorphismAutoGroup( Parent( PAS ) );
    else
        Error( "IsomorphismAutoGroup unavailable for PAS" );
    fi; 
    AS := Image( p2aS );
    a2pS := InverseGeneralMapping( p2aS );
    ######################################
    # determine the boundary map
    im := [ ]; 
    for r in genR do
        autr := Image( XModAction( XM ), r );
        psrc := Image( a2pS, autr );
        emsrc := Image( EmbedSourceAutos( P ), psrc );
        conjr := InnerAutomorphism( R, r );
        prng := Image( a2pR, conjr );
        emrng := Image( EmbedRangeAutos( P ), prng );
        Add( im, emrng * emsrc );  ### assumes direct product ###
    od;
    bdy := GroupHomomorphismByImages( R, P, genR, im );
    # determine the action
    imact := 0 * Prng;
    for i in Prng do
        p := genP[i];
        projp := Image( RangeProjection( P ), p );
        proja := Image( p2aR, projp );
        ima := List( genR, r -> Image( proja, r ) );
        a := GroupHomomorphismByImages( R, R, genR, ima );
        imact[i] := a;
    od;
    act := GroupHomomorphismByImages( P, AR, genP, imact );
    for f in MappingGeneratorsImages( act )[2] do
        if ( f = IdentityMapping( R ) ) then
            f := InclusionMappingGroups( R, R );
        fi;
    od;
    ## create the crossed module
    NX := XMod( bdy, act );
    name := Name( XM );
    SetName( NX, Concatenation( "Norrie", name ) );
    return NX;
end );

#############################################################################
##
#M  LueXMod( <XM> )
##
##  revised  23/06/06
##
InstallMethod( LueXMod, "Lue crossed module", true,
    [ IsXMod ], 0, 
function( XM )

    local  NX, Nbdy, Xbdy, Lbdy, P, genP, Prng, S, genS, AS, a2pS, PAS, 
           p2aS, imact, i, p, projp, proja, ima, a, act, f, LX, name;

    NX := NorrieXMod( XM );
    Nbdy := Boundary( NX );
    Xbdy := Boundary( XM );
    Lbdy := Xbdy * Nbdy;
    P := AutomorphismPermGroup( XM );
    genP := GeneratorsOfGroup( P );
    Prng := [ 1..Length( genP ) ];
    S := Source( XM );
    genS := GeneratorsOfGroup( S );
    ########## 23/06/06 revision ##########
    PAS := Image( SourceProjection( P ) ); 
    if HasIsomorphismAutoGroup( PAS ) then 
        p2aS := IsomorphismAutoGroup( PAS ); 
    elif ( HasParent( PAS ) and HasIsomorphismAutoGroup( Parent(PAS) ) ) then 
        p2aS := IsomorphismAutoGroup( Parent( PAS ) );
    else
        Error( "IsomorphismAutoGroup unavailable for PAS" );
    fi; 
    AS := Image( p2aS );
    a2pS := InverseGeneralMapping( p2aS );
    ######################################
    imact := 0 * Prng;
    for i in Prng  do
        p := genP[i];
        projp := Image( SourceProjection( P ), p );
        proja := Image( p2aS, projp );
        ima := List( genS, s -> Image( proja, s ) );
        a := GroupHomomorphismByImages( S, S, genS, ima );
        imact[i] := a;
    od;
    act := GroupHomomorphismByImages( P, AS, genP, imact );
    for f in MappingGeneratorsImages( act )[2] do
        if ( f = IdentityMapping( S ) ) then
            f := InclusionMappingGroups( S, S );
        fi;
    od;
    LX := XMod( Lbdy, act );
    name := Name( XM );
    SetName( LX, Concatenation( "Lue", name ) );
    return LX;
end );


#############################################################################
##
#M  ActorXMod( <XM> )
##
##  revised  23/06/06
##
InstallMethod( ActorXMod, "actor crossed module", true,
    [ IsXMod ], 0, 
function( XM )

    local  D, L, W, eW, P, genP, genpos, ngW, genW, invW, imdelta, 
           S, R, AS, AR, PAS, p2aS, a2pS, PAR, p2aR, a2pR, emsrc, emrng, 
           i, j, k, mor, imsrc, imrng, delta, GA, nGA, imact, rho, invrho, 
           impos, chi, chj, imgen, phi, id, aut, act, ActX, name;

    D := RegularDerivations( XM );
    L := ImagesList( D );
    W := WhiteheadPermGroup( XM );
    eW := Elements( W );
    P := AutomorphismPermGroup( XM );
    genP := GeneratorsOfGroup( P );
    genpos := WhiteheadGroupGeneratorPositions( XM );
    ngW := Length( genpos );
    # determine the boundary map
    genW := List( genpos, i -> eW[i] );
    invW := List( genW, g -> g^-1 );
    imdelta := ListWithIdenticalEntries( ngW, 0 );
    S := Source( XM );
    R := Range( XM );
    ########## 23/06/06 revision ##########
    PAR := Image( RangeProjection( P ) ); 
    if HasIsomorphismAutoGroup( PAR ) then 
        p2aR := IsomorphismAutoGroup( PAR ); 
    elif ( HasParent( PAR ) and HasIsomorphismAutoGroup( Parent(PAR) ) ) then 
        p2aR := IsomorphismAutoGroup( Parent( PAR ) );
    else
        Error( "IsomorphismAutoGroup unavailable for PAR" );
    fi; 
    AR := Image( p2aR );
    a2pR := InverseGeneralMapping( p2aR );
    PAS := Image( SourceProjection( P ) ); 
    if HasIsomorphismAutoGroup( PAS ) then 
        p2aS := IsomorphismAutoGroup( PAS ); 
    elif ( HasParent( PAS ) and HasIsomorphismAutoGroup( Parent(PAS) ) ) then 
        p2aS := IsomorphismAutoGroup( Parent( PAS ) );
    else
        Error( "IsomorphismAutoGroup unavailable for PAS" );
    fi; 
    AS := Image( p2aS );
    a2pS := InverseGeneralMapping( p2aS );
    ######################################
    emsrc := EmbedSourceAutos( P );
    emrng := EmbedRangeAutos( P );
    for i in [1..ngW] do
        j := genpos[i];
        chj := DerivationByImages( XM, L[j] );
        mor := Object2dEndomorphism( chj );
        imsrc := Image( emsrc, Image( a2pS, SourceHom( mor ) ) );
        imrng := Image( emrng, Image( a2pR, RangeHom( mor ) ) );
        imdelta[i] := imsrc * imrng;
    od;
    delta := GroupHomomorphismByImages( W, P, genW, imdelta );
    Info( InfoXMod, 3, "delta: ", MappingGeneratorsImages( delta ) );

    # determine the action
    GA := GeneratingAutomorphisms( XM );
    nGA := Length( GA );
    imact := ListWithIdenticalEntries( nGA, 0 );
    for k in [1..nGA] do
        mor := GA[k];
        rho := RangeHom( mor );
        invrho := rho^(-1);
        impos := ListWithIdenticalEntries( ngW, 0);
        for i in [1..ngW] do
            j := genpos[i];
            chi := DerivationByImages( XM, L[j] );
            chj := ImageAutomorphismDerivation( mor, chi );
            impos[i] := Position( L, GeneratorImages( chj ) );
        od;
        imgen := List( impos, i -> eW[i] );
        phi := GroupHomomorphismByImages( W, W, genW, imgen );
        imact[k] := phi;
    od;
    id := InclusionMappingGroups( W, W );
    aut := Group( imact, id );
    SetName( aut, "Aut(W)" );
    act := GroupHomomorphismByImages( P, aut, genP, imact );
    ActX := XMod( delta, act );
    name := Name( XM );
    SetName( ActX, Concatenation( "Actor", name ) );
    return ActX;
end );

#############################################################################
##
#M  ActorCat1( <C> )
##
InstallMethod( ActorCat1, "actor cat1-group", true, [ IsCat1 ], 0, 
function( C )
    return 0;
end );

#############################################################################
##
#M  InnerMorphism( <XM> )
##
InstallMethod( InnerMorphism, "inner morphism of xmod", true,
    [ IsXMod ], 0, 
function( XM )

    local  WX, NX, ActX, mor;

    WX := WhiteheadXMod( XM );
    NX := NorrieXMod( XM );
    ActX := ActorXMod( XM );
    mor := XModMorphismByHoms( XM, ActX, Boundary(WX), Boundary(NX) );
    return mor;
end );

#############################################################################
##
#M  Centre( <XM> )
##
InstallOtherMethod( Centre, "centre of an xmod", true, [ IsXMod ], 0, 
function( XM )
    return Kernel( InnerMorphism( XM ) );
end );

#############################################################################
##
#M  ImagesSource( <mor> )
##
InstallOtherMethod( ImagesSource, "xmod image for an xmod morphism", true, 
    [ IsPreXModMorphism ], 0, 
function( mor )
    
    local  S, R, Shom, Rhom, imS, imR, SX;

    Shom := SourceHom( mor );
    Rhom := RangeHom( mor );
    imS := ImagesSource( Shom );
    imR := ImagesSource( Rhom );
    SX := SubPreXMod( Range(mor), imS, imR );
    return SX;
end );

#############################################################################
##
#M  InnerActorXMod( <XM> )
##
InstallMethod( InnerActorXMod, "inner actor crossed module", true,
    [ IsXMod ], 0, 
function( XM )

    local  InnX, mor, name, ActX;
    
    ActX := ActorXMod( XM );
    mor := InnerMorphism( XM );
    InnX := ImagesSource( mor );
    if ( InnX = ActX ) then
        InnX := ActX;
    else
        name := Name( XM );
        SetName( InnX, Concatenation( "InnerActor", name ) );
    fi;
    return InnX;
end );


#############################################################################
##
#E  actor2.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
