diff --git a/.gitignore b/.gitignore
index 7944d14..0fa6292 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@
/doc/*.toc
/doc/title.xml
+/doc/xmodalg.xml
/doc/XModAlg.xml
/doc/manual.pdf
/doc/bib.xml.bib
@@ -28,8 +29,11 @@
/tmp
+/tst/algebra.g
/tst/cat1.g
-/tst/xmod.g
+/tst/dsum-xmod.g
/tst/convert.g
+/tst/module.g
+/tst/xmod.g
/gh-pages/
diff --git a/CHANGES.md b/CHANGES.md
index 038fdc7..0c06510 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,7 @@
# CHANGES to the 'XModAlg' package
-## 1.32 -> 1.33 (27/08/25)
+## 1.32 -> 1.33 (16/03/26)
+ * (18/12/25) added new material on direct sums
* (27/08/25) added installation instructions to the manual introduction
replaced \mathcal by \mathbb which suits MathJax better
diff --git a/PackageInfo.g b/PackageInfo.g
index 4104c17..a3dbe3a 100644
--- a/PackageInfo.g
+++ b/PackageInfo.g
@@ -8,8 +8,8 @@ SetPackageInfo( rec(
PackageName := "XModAlg",
Subtitle := "Crossed Modules and Cat1-Algebras",
-Version := "1.32",
-Date := "11/04/2025", # dd/mm/yyyy format
+Version := "1.32-dev",
+Date := "17/03/2026", # dd/mm/yyyy format
License := "GPL-2.0-or-later",
Persons := [
diff --git a/doc/xmod.xml b/doc/xmod.xml
index 75d8fd9..04a992d 100644
--- a/doc/xmod.xml
+++ b/doc/xmod.xml
@@ -166,6 +166,11 @@ endomorphisms of Source(X).
+The action in XIAk4 is straightforward multiplication,
+so f1 and f2 map the generating set [1-f1,f1-f2,f2-f1*f2]
+to [f1-1,1-f1*f2,f1*f2-f2] and [f2-f1*f2,f1*f2-1,1-f1]
+respectively.
+
The following standard ⪆ operations have special &XModAlg; implementations:
-
diff --git a/init.g b/init.g
index 7210d8c..937c35b 100644
--- a/init.g
+++ b/init.g
@@ -2,7 +2,7 @@
##
#W init.g The XMODALG package Zekeriya Arvasi
#W & Alper Odabas
-#Y Copyright (C) 2014-2024, Zekeriya Arvasi & Alper Odabas,
+#Y Copyright (C) 2014-2025, Zekeriya Arvasi & Alper Odabas,
##
if not IsBound( PreImagesRepresentativeNC ) then
@@ -14,3 +14,4 @@ ReadPackage( "xmodalg", "lib/algebra.gd" );
ReadPackage( "xmodalg", "lib/alg2obj.gd" );
ReadPackage( "xmodalg", "lib/module.gd" );
ReadPackage( "xmodalg", "lib/alg2map.gd" );
+ReadPackage( "xmodalg", "lib/dsum-xmod.gd" );
diff --git a/lib/alg2obj.gd b/lib/alg2obj.gd
index f8e7e68..ffefa88 100644
--- a/lib/alg2obj.gd
+++ b/lib/alg2obj.gd
@@ -80,7 +80,7 @@ DeclareOperation( "PreXModAlgebraByBoundaryAndAction",
[ IsAlgebraHomomorphism, IsAlgebraAction ] );
DeclareOperation( "PreXModAlgebraByBoundaryAndActionNC",
[ IsAlgebraHomomorphism, IsAlgebraAction ] );
- DeclareOperation( "XModAlgebraByBoundaryAndAction",
+DeclareOperation( "XModAlgebraByBoundaryAndAction",
[ IsAlgebraHomomorphism, IsAlgebraAction ] );
DeclareOperation( "XModAlgebraByBoundaryAndActionNC",
[ IsAlgebraHomomorphism, IsAlgebraAction ] );
diff --git a/lib/algebra.gi b/lib/algebra.gi
index 88fa408..28365ad 100644
--- a/lib/algebra.gi
+++ b/lib/algebra.gi
@@ -582,7 +582,9 @@ function ( hom )
for k in vecK do
for a in vecA do
if not ( k*a = zA ) then
- Print( "kernel of hom is not in the annihilator of A\n" );
+ Print( "!!!\n" );
+ Print( "kernel of hom is not in the annihilator of A\n" );
+ Print( "!!!\n" );
return fail;
fi;
od;
diff --git a/lib/dsum-xmod.gd b/lib/dsum-xmod.gd
new file mode 100644
index 0000000..43719d9
--- /dev/null
+++ b/lib/dsum-xmod.gd
@@ -0,0 +1,203 @@
+ #############################################################################
+##
+#W dsum-xmod.gd The XMODALG package Zekeriya Arvasi
+#W & Alper Odabas
+#Y Copyright (C) 2014-2025, Zekeriya Arvasi & Alper Odabas,
+##
+
+############################################################################
+##
+## AlgebraActionByDirectSum( )
+##
+## <#GAPDoc Label="AlgebraActionByDirectSum">
+##
+##
+##
+##
+## If \alpha_1 : A_1 \to C_1 and \alpha_2: A_2 \to C_2
+## are two actions on algebra B
+## then the direct sum A_1 \oplus A_2 acts on B by
+## (a_1,a_2)\cdot b = a_1\cdot(a_2\cdot b) = a_2\cdot(a_1 \cdot b)
+## provided the two actions commute.
+##
+##
+##
+##
+##
+## ]]>
+##
+## <#/GAPDoc>
+##
+DeclareOperation( "AlgebraActionByDirectSum",
+ [ IsAlgebraAction, IsAlgebraAction ] );
+
+## section 2.4.3
+############################################################################
+##
+#O DirectSumOfAlgebraHomomorphisms( )
+#O AlgebraHomomorphismFromDirectSum( )
+##
+## <#GAPDoc Label="DirectSumOfAlgebraHomomorphisms">
+##
+##
+##
+##
+##
+## Let \theta_1 : B_1 \to A_1 and \theta_2 : B_2 \to A_2
+## be algebra homomorphisms.
+## The first operation uses embeddings into A = A_1 \oplus A_2
+## and B = B_1 \oplus B_2 to construct
+## \theta = \theta_1 \oplus \theta_2 : B \to A
+## where \theta(b_1,b_2) = (\theta_1b_1,\theta_2b_2).
+##
+## When A_1=A_2 the second operation constructs
+## \theta = \theta_1 \oplus \theta_2 : B \to A_1
+## where \theta(b_1,b_2) = \theta_1b_1 + \theta_2b_2.
+##
+## The example uses the homomorphism homg3 used in
+## Section
+##
+##
+##
+##
+## hom33a := DirectSumOfAlgebraHomomorphisms( homg3, homg3 );;
+## gap> Print( hom33a, "\n" );
+## AlgebraHomomorphismByImages( A3(+)A3, Algebra( Rationals,
+## [ v.1, v.2, v.3, v.4, v.5, v.6 ] ),
+## [ [ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ],
+## [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ],
+## [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ],
+## [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 1, 0, 0 ] ] ],
+## [ v.1, v.4 ] )
+## ]]>
+##
+## <#/GAPDoc>
+##
+DeclareOperation( "DirectSumOfAlgebraHomomorphisms",
+ [ IsAlgebraHomomorphism, IsAlgebraHomomorphism ] );
+DeclareOperation( "AlgebraHomomorphismFromDirectSum",
+ [ IsAlgebraHomomorphism, IsAlgebraHomomorphism ] );
+
+## section 2.4.4
+############################################################################
+##
+## AlgebraActionOnDirectSum( )
+##
+## <#GAPDoc Label="AlgebraActionOnDirectSum">
+##
+##
+##
+##
+## If \alpha_1 : A \to C_1 is an action on algebra B_1
+## and \alpha_2 : A \to C_2 is an action on algebra B_2
+## by the same algebra A,
+## then A acts on the direct sum B_1 \oplus B_2
+## by a \cdot (b_1,b_2) = (a \cdot b_1, a \cdot b_2).
+##
+## In Section there is created
+## an action actB3 of A3 on an isomorphic B3.
+## In the example here we construct actA3, with A3 acting
+## on itself, formed using AlgebraActionByMultipliers.
+## Then we construct the direcct sum of these actions.
+##
+##
+##
+## actMA3 := AlgebraActionByMultipliers( A3, A3, A3 );;
+## gap> act4 := AlgebraActionOnDirectSum( actMA3, actg3 );
+## [ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ],
+## [ [ 0, 0, 1 ], [ 1, 0, 0 ], [ 0, 1, 0 ] ],
+## [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] ] ->
+## [ [ v.1, v.2, v.3, v.4, v.5, v.6 ] -> [ v.2, v.3, v.1, v.5, v.6, v.4 ],
+## [ v.1, v.2, v.3, v.4, v.5, v.6 ] -> [ v.3, v.1, v.2, v.6, v.4, v.5 ],
+## [ v.1, v.2, v.3, v.4, v.5, v.6 ] -> [ v.1, v.2, v.3, v.4, v.5, v.6 ] ]
+## ]]>
+##
+## <#/GAPDoc>
+##
+DeclareOperation( "AlgebraActionOnDirectSum",
+ [ IsAlgebraAction, IsAlgebraAction ] );
+
+## section 2.4.5
+############################################################################
+##
+## DirectSumOfAlgebraActions( )
+##
+## <#GAPDoc Label="DirectSumOfAlgebraActions">
+##
+##
+##
+##
+## Let
+## If \alpha_1 : A_1 \to C_1 is an action on algebra B_1,
+## and \alpha_2 : A_2 \to C_2 is an action on algebra B_2,
+## then A_1 \oplus A_2 acts on the direct sum B_1 \oplus B_2
+## by (a_1,a_2) \cdot (b_1,b_2) = (a_1 \cdot b_1, a_2 \cdot b_2).
+## The example forms the direct sum of the actions constructed in
+## sections
+## and
+##
+##
+##
+##
+## act5 := DirectSumOfAlgebraActions( actg3, act3 );;
+## gap> A5 := Source( act5 );
+## A3(+)A3
+## gap> B5 := AlgebraActedOn( act5 );
+## GR(c3)(+)A(M3)
+## gap> em3 := ImageElm( Embedding( A5, 1 ), m3 );
+## [ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ],
+## [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]
+## gap> ImageElm( act5, em3 );
+## Basis( GR(c3)(+)A(M3), [ v.1, v.2, v.3, v.4, v.5, v.6 ] ) ->
+## [ v.2, v.3, v.1, 0*v.1, 0*v.1, 0*v.1 ]
+## gap> ea3 := ImageElm( Embedding( A5, 2 ), a3 );
+## [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ],
+## [ 0, 0, 0, 0, 2, 3 ], [ 0, 0, 0, 3, 0, 2 ], [ 0, 0, 0, 2, 3, 0 ] ]
+### gap> ImageElm( act5, ea3 );
+## Basis( GR(c3)(+)A(M3), [ v.1, v.2, v.3, v.4, v.5, v.6 ] ) ->
+## [ 0*v.1, 0*v.1, 0*v.1, (3)*v.5+(2)*v.6, (2)*v.4+(3)*v.6, (3)*v.4+(2)*v.5 ]
+## ]]>
+##
+## <#/GAPDoc>
+##
+DeclareOperation( "DirectSumOfAlgebraActions",
+ [ IsAlgebraAction, IsAlgebraAction ] );
+
+## section 4.1.9
+############################################################################
+##
+## DirectSumOfXModAlgebras( )
+##
+## <#GAPDoc Label="DirectSumOfXModAlgebras">
+##
+##
+##
+##
+## In Sections
+## and
+## we constructed direct sums of algebra homomorphisms and algebra actions.
+## So, given two crossed modules of algebras X_1, X_2,
+## we can form the direct sums of their boundaries and actions
+## to form a direct sum X_1 \oplus X_2 of crossed modules.
+##
+## In the example we combine crossed modules X3 from section
+## and X4
+## from section .
+##
+##
+##
+##
+## XY3 := DirectSumOfXModAlgebras( X3, Y3 );
+## [ GR(c3)(+)A(M3) -> A3(+)A3 ]
+## ]]>
+##
+## <#/GAPDoc>
+##
+DeclareOperation( "DirectSumOfXModAlgebras",
+ [ IsXModAlgebra, IsXModAlgebra ] );
+
diff --git a/lib/dsum-xmod.gi b/lib/dsum-xmod.gi
new file mode 100644
index 0000000..2c3a357
--- /dev/null
+++ b/lib/dsum-xmod.gi
@@ -0,0 +1,443 @@
+############################################################################
+##
+#W dsum-xmod.gi The XMODALG package Zekeriya Arvasi
+#W & Alper Odabas
+#Y Copyright (C) 2014-2025, Zekeriya Arvasi & Alper Odabas,
+##
+
+#############################################################################
+##
+#M AlgebraActionByDirectSum
+##
+InstallMethod( AlgebraActionByDirectSum, "for two algebra actions", true,
+ [ IsAlgebraAction, IsAlgebraAction ], 0,
+function( act1, act2 )
+ local A1, domA, basA1, n1, A2, basA2, n2, B, basB, C1, basC1, C2, basC2,
+ A, firstA, basA, eA1, im1, eA2, im2, i, c1, j, c2, b, basC, C,
+ act, b1,b2,b3,b4,b5,b6, v1,v2,v3,v4,v5,v6,v ;
+ A1 := Source( act1 );
+ domA := LeftActingDomain( A1 );
+ basA1 := BasisVectors( Basis( A1 ) );
+ n1 := Length( basA1 );
+ C1 := Range( act1 );
+ basC1 := BasisVectors( Basis( C1 ) );
+ B := AlgebraActedOn( act1 );
+ if not ( AlgebraActedOn( act2 ) = B ) then
+ Error( "act1, act2 must act on the same algebra" );
+ fi;
+ basB := BasisVectors( Basis( B ) );
+ A2 := Source( act2 );
+ basA2 := BasisVectors( Basis( A2 ) );
+ n2 := Length( basA2 );
+ C2 := Range( act2 );
+ basC2 := BasisVectors( Basis( C2 ) );
+ A := DirectSumOfAlgebras( A1, A2 );
+ firstA := [ 1, 1 + Dimension( A1 ) ];
+ SetDirectSumOfAlgebrasInfo( A,
+ rec( algebras := [ A1, A2 ],
+ first := firstA,
+ embeddings := [ ],
+ projections := [ ] ) );
+ eA1 := Embedding( A, 1 );
+ im1 := List( [1..n1], i -> ImageElm( eA1, basA1[i] ) );
+ eA2 := Embedding( A, 2 );
+ im2 := List( [1..n2], j -> ImageElm( eA2, basA2[j] ) );
+ basA := Concatenation( im1, im2 );
+ for i in [1..n1] do
+ c1 := Image( act1, basA1[i] );
+ for j in [1..n2] do
+ c2 := ImageElm( act2, basA2[j] );
+ for b in basB do
+ if Image(c2,Image(c1,b)) <> Image(c1,Image(c2,b)) then
+ Error( "the actions on B do not commute" );
+ fi;
+ od;
+ od;
+ od;
+ for i in [1..n1] do
+ if Image( eA1, basA1[i] ) <> basA[i] then
+ Error( "unexpected image of eA1" );
+ fi;
+ od;
+ for j in [1..n2] do
+ if Image( eA2, basA2[j] ) <> basA[n1+j] then
+ Error( "unexpected image of eA2" );
+ fi;
+ od;
+ basC1 := List( [1..n1], i -> ImageElm( act1, basA1[i] ) );
+Print( "basC1 = ", basC1, "\n" );
+ basC2 := List( [1..n2], j -> ImageElm( act2, basA2[j] ) );
+Print( "basC2 = ", basC2, "\n" );
+ basC := Concatenation( basC1, basC2 );
+ C := AlgebraByGenerators( domA, basC );
+
+ v1:=basC[1]; v2:=basC[2]; v3:=basC[3];
+ v4:=basC[4]; v5:=basC[5]; v6:=basC[6];
+ v := [v1,v2,v3,v4,v5,v6];
+ b1:=basA[1]; b2:=basA[2]; b3:=basA[3];
+ b4:=basA[4]; b5:=basA[5]; b6:=basA[6];
+ b := [b1,b2,b3,b4,b5,b6];
+ Print( "\nmultiplication table for v\n" );
+ Print( List( v, g -> v1*g ), "\n" );
+ Print( List( v, g -> v2*g ), "\n" );
+ Print( List( v, g -> v3*g ), "\n" );
+ Print( List( v, g -> v4*g ), "\n" );
+ Print( List( v, g -> v5*g ), "\n" );
+ Print( List( v, g -> v6*g ), "\n" );
+ Print( "multiplication table for b\n" );
+ Print( List( b, g -> b1*g ), "\n" );
+ Print( List( b, g -> b2*g ), "\n" );
+ Print( List( b, g -> b3*g ), "\n" );
+ Print( List( b, g -> b4*g ), "\n" );
+ Print( List( b, g -> b5*g ), "\n" );
+ Print( List( b, g -> b6*g ), "\n" );
+
+
+ act := AlgebraHomomorphismByImages( A, C, basA, basC );
+ SetIsAlgebraAction( act, true );
+ SetAlgebraActionType( act, "direct sum 2" );
+ return act;
+end );
+
+#############################################################################
+##
+#M DirectSumOfXModAlgebras
+##
+InstallMethod( DirectSumOfXModAlgebras, "for two crossed modules", true,
+ [ IsXModAlgebra, IsXModAlgebra ], 0,
+function( X1, X2 )
+ local S1, basS1, nS1, R1, basR1, nR1, bdy1, act1, dom,
+ S2, basS2, nS2, R2, basR2, nR2, bdy2, act2,
+ bdy12, S12, eS1, imS1, pS1, eS2, imS2, pS2, basS12,
+ R12, eR1, imR1, pR1, eR2, imR2, pR2, basR12,
+ basQ12, i, r, pr, hpr, imh, j, s, ps, hps, h,
+ Q12, act12, X12;
+ S1 := Source( X1 );
+ basS1 := CanonicalBasis( S1 );
+ nS1 := Length( basS1 );
+ R1 := Range( X1 );
+ basR1 := CanonicalBasis( R1 );
+ nR1 := Length( basR1 );
+ bdy1 := Boundary( X1 );
+ act1 := XModAlgebraAction( X1 );
+ dom := LeftActingDomain( S1 );
+ S2 := Source( X2 );
+ if not ( LeftActingDomain( S1 ) = dom ) then
+ Error( "conflicting domains" );
+ fi;
+ basS2 := CanonicalBasis( S2 );
+ nS2 := Length( basS2 );
+ R2 := Range( X2 );
+ basR2 := CanonicalBasis( R2 );
+ nR2 := Length( basR2 );
+ bdy2 := Boundary( X2 );
+ act2 := XModAlgebraAction( X2 );
+ ## now construct the combined boundary
+ bdy12 := DirectSumOfAlgebraHomomorphisms( bdy1, bdy2 );
+ S12 := Source( bdy12 );
+ eS1 := Embedding( S12, 1 );
+ imS1 := List( [1..nS1], i -> ImageElm( eS1, basS1[i] ) );
+ pS1 := Projection( S12, 1 );
+ eS2 := Embedding( S12, 2 );
+ imS2 := List( [1..nS2], i -> ImageElm( eS2, basS2[i] ) );
+ pS2 := Projection( S12, 2 );
+ basS12 := Concatenation( imS1, imS2 );
+ R12 := Range( bdy12 );
+ eR1 := Embedding( R12, 1 );
+ imR1 := List( [1..nR1], i -> ImageElm( eR1, basR1[i] ) );
+ pR1 := Projection( R12, 1 );
+ eR2 := Embedding( R12, 2 );
+ imR2 := List( [1..nR2], i -> ImageElm( eR2, basR2[i] ) );
+ pR2 := Projection( R12, 2 );
+ basR12 := Concatenation( imR1, imR2 );
+ ## now construct the combined action
+ basQ12 := ListWithIdenticalEntries( nR1+nR2, 0 );
+ for i in [1..nR1] do
+ r := imR1[i];
+ pr := ImageElm( pR1, r );
+ hpr := ImageElm( act1, pr );
+ imh := ListWithIdenticalEntries( nS1, 0 );
+ for j in [1..nS1] do
+ s := imS1[j];
+ ps := ImageElm( pS1, s );
+ hps := ImageElm( hpr, ps );
+ imh[j] := ImageElm( eS1, hps );
+ od;
+ imh := Concatenation( imh, imS2 );
+ h := AlgebraGeneralMappingByImages( S12, S12, basS12, imh );
+Error("here");
+ basQ12[i] := h;
+ od;
+Error("here");
+ Q12 := AlgebraByGenerators( dom, basQ12 );
+ act12 := AlgebraGeneralMappingByImages( R12, Q12, basR12, basQ12 );
+ X12 := PreXModAlgebraByBoundaryAndAction( bdy12, act12 );
+## SetIsXModAlgebra( X12, true );
+ return X12;
+end );
+
+#############################################################################
+##
+#M DirectSumOfAlgebraHomomorphisms
+##
+InstallMethod( DirectSumOfAlgebraHomomorphisms,
+ "for two algebra homomorphisms",
+ [ IsAlgebraHomomorphism, IsAlgebraHomomorphism ],
+ function( hom1, hom2 )
+ local B1, A1, gen1, im1, B2, A2, gen2, im2,
+ dom, B, eB1, eB2, genB, A, eA1, eA2, imhom, hom;
+ B1 := Source( hom1 );
+ A1 := Range( hom1 );
+ gen1 := GeneratorsOfAlgebra( B1 );
+ im1 := List( gen1, g -> ImageElm( hom1, g ) );
+ B2 := Source( hom2 );
+ A2 := Range( hom2 );
+ gen2 := GeneratorsOfAlgebra( B2 );
+ im2 := List( gen2, g -> ImageElm( hom2, g ) );
+ dom := LeftActingDomain( B1 );
+ if not ( dom = LeftActingDomain( B2 ) ) then
+ Error( "homomorphisms are over different domains" );
+ fi;
+ B := DirectSumOfAlgebrasWithInfo( B1, B2 );
+ eB1 := Embedding( B, 1 );
+ eB2 := Embedding( B, 2 );
+ A := DirectSumOfAlgebrasWithInfo( A1, A2 );
+ eA1 := Embedding( A, 1 );
+ eA2 := Embedding( A, 2 );
+ genB := Concatenation( List( gen1, b -> ImageElm( eB1, b ) ),
+ List( gen2, b -> ImageElm( eB2, b ) ) );
+ imhom := Concatenation( List( im1, a -> ImageElm( eA1, a ) ),
+ List( im2, a -> ImageElm( eA2, a ) ) );
+ hom := AlgebraHomomorphismByImages( B, A, genB, imhom );
+ return hom;
+end);
+
+#############################################################################
+##
+#M AlgebraHomomorphismFromDirectSum
+##
+InstallMethod( AlgebraHomomorphismFromDirectSum,
+ "for two algebra homomorphisms",
+ [ IsAlgebraHomomorphism, IsAlgebraHomomorphism ],
+ function( hom1, hom2 )
+ local B1, A, gen1, im1, B2, gen2, im2,
+ dom, B, eB1, eB2, genB, imhom, hom;
+ B1 := Source( hom1 );
+ A := Range( hom1 );
+ gen1 := GeneratorsOfAlgebra( B1 );
+ im1 := List( gen1, g -> ImageElm( hom1, g ) );
+ B2 := Source( hom2 );
+ if not ( A = Range( hom2 ) ) then
+ Error( "hom1 and hom2 should have the same range" );
+ fi;
+ gen2 := GeneratorsOfAlgebra( B2 );
+ im2 := List( gen2, g -> ImageElm( hom2, g ) );
+ dom := LeftActingDomain( B1 );
+ if not ( dom = LeftActingDomain( B2 ) ) then
+ Error( "homomorphisms are over different domains" );
+ fi;
+ B := DirectSumOfAlgebrasWithInfo( B1, B2 );
+ eB1 := Embedding( B, 1 );
+ eB2 := Embedding( B, 2 );
+ genB := Concatenation( List( gen1, b -> ImageElm( eB1, b ) ),
+ List( gen2, b -> ImageElm( eB2, b ) ) );
+Print( "genB = ", genB, "\n" );
+ imhom := Concatenation( im1, im2 );
+Print( "imhom = ", imhom, "\n" );
+Error("here");
+ hom := AlgebraHomomorphismByImages( B, A, genB, imhom );
+ return hom;
+end);
+
+#############################################################################
+##
+#M AlgebraActionOnDirectSum
+##
+InstallMethod( AlgebraActionOnDirectSum, "for two algebra actions", true,
+ [ IsAlgebraAction, IsAlgebraAction ], 0,
+function( act1, act2 )
+ local A, domA, genA, B1, basB1, B2, basB2, B, firstB, basB,
+ eB1, eB2, genC, a, c1, c2, imc1, imc2, imB, C, act;
+ A := Source( act1 );
+ domA := LeftActingDomain( A );
+ genA := BasisVectors( Basis( A ) );
+ if not ( Source( act2 ) = A ) then
+ Error( "act1, act2 must have the same source" );
+ fi;
+ B1 := AlgebraActedOn( act1 );
+ basB1 := BasisVectors( Basis( B1 ) );
+ B2 := AlgebraActedOn( act2 );
+ basB2 := BasisVectors( Basis( B2 ) );
+ B := DirectSumOfAlgebras( B1, B2 );
+ firstB := [ 1, 1 + Dimension( B1 ) ];
+ basB := BasisVectors( Basis( B ) );
+ SetDirectSumOfAlgebrasInfo( B,
+ rec( algebras := [ B1, B2 ],
+ first := firstB,
+ embeddings := [ ],
+ projections := [ ] ) );
+ eB1 := Embedding( B, 1 );
+ eB2 := Embedding( B, 2 );
+ genC := [ ];
+ for a in genA do
+ c1 := ImageElm( act1, a );
+ c2 := ImageElm( act2, a );
+ imc2 := List( basB2, b -> ImageElm( eB2, ImageElm( c2, b ) ) );
+ imc1 := List( basB1, b -> ImageElm( eB1, ImageElm( c1, b ) ) );
+ imB := Concatenation( imc1, imc2 );
+ Add( genC, LeftModuleHomomorphismByImages( B, B, basB, imB ) );
+ od;
+ C := AlgebraByGenerators( domA, genC );
+ act := AlgebraHomomorphismByImages( A, C, genA, genC );
+ SetIsAlgebraAction( act, true );
+ SetAlgebraActedOn( act, B );
+ SetAlgebraActionType( act, "on direct sum 1" );
+ return act;
+end );
+
+#############################################################################
+##
+#M DirectSumOfAlgebraActions
+##
+InstallMethod( DirectSumOfAlgebraActions, "for two algebra actions", true,
+ [ IsAlgebraAction, IsAlgebraAction ], 0,
+function( act1, act2 )
+ local domA, A1, basA1, nA1, A2, basA2, nA2, A, basA, firstA,
+ B1, basB1, nB1, B2, basB2, nB2, B, basB, firstB, zB, zB1, zB2,
+ C1, basC1, nC1, C2, basC2, nC2, C, basC, c, imc, hom,
+ eA1, imA1, eA2, imA2, eB1, imB1, eB2, imB2, i, act;
+ A1 := Source( act1 );
+ domA := LeftActingDomain( A1 );
+ basA1 := BasisVectors( Basis( A1 ) );
+ nA1 := Length( basA1 );
+ B1 := AlgebraActedOn( act1 );
+ basB1 := BasisVectors( Basis( B1 ) );
+ nB1 := Length( basB1 );
+ C1 := Range( act1 );
+ basC1 := BasisVectors( Basis( C1 ) );
+ nC1 := Length( basC1 );
+ A2 := Source( act2 );
+ if not ( domA = LeftActingDomain( A2 ) ) then
+ Error( "act1 and act2 have different left acting domains" );
+ fi;
+ basA2 := BasisVectors( Basis( A2 ) );
+ nA2 := Length( basA2 );
+ B2 := AlgebraActedOn( act2 );
+ basB2 := BasisVectors( Basis( B2 ) );
+ nB2 := Length( basB2 );
+ C2 := Range( act2 );
+ basC2 := BasisVectors( Basis( C2 ) );
+ nC2 := Length( basC2 );
+ A := DirectSumOfAlgebras( A1, A2 );
+ if HasName( A1 ) and HasName( A2 ) then
+ SetName( A, Concatenation( Name(A1), "(+)", Name(A2) ) );
+ fi;
+ firstA := [ 1, 1 + Dimension( A1 ) ];
+ SetDirectSumOfAlgebrasInfo( A,
+ rec( algebras := [ A1, A2 ],
+ first := firstA,
+ embeddings := [ ],
+ projections := [ ] ) );
+ eA1 := Embedding( A, 1 );
+ imA1 := List( [1..nA1], i -> ImageElm( eA1, basA1[i] ) );
+ eA2 := Embedding( A, 2 );
+ imA2 := List( [1..nA2], j -> ImageElm( eA2, basA2[j] ) );
+ basA := Concatenation( imA1, imA2 );
+ B := DirectSumOfAlgebras( B1, B2 );
+## Print( "B = ", B, "\n", "has zero ", Zero(B), "\n" );
+ if HasName( B1 ) and HasName( B2 ) then
+ SetName( B, Concatenation( Name(B1), "(+)", Name(B2) ) );
+ fi;
+ firstB := [ 1, 1 + Dimension( B1 ) ];
+ SetDirectSumOfAlgebrasInfo( B,
+ rec( algebras := [ B1, B2 ],
+ first := firstB,
+ embeddings := [ ],
+ projections := [ ] ) );
+ eB1 := Embedding( B, 1 );
+ imB1 := List( [1..nB1], i -> ImageElm( eB1, basB1[i] ) );
+ eB2 := Embedding( B, 2 );
+ imB2 := List( [1..nB2], j -> ImageElm( eB2, basB2[j] ) );
+ basB := Concatenation( imB1, imB2 );
+ basC := ListWithIdenticalEntries( nC1+nC2, 0 );
+ zB := Zero( B );
+ zB1 := List( [1..nB1], i -> zB );
+ zB2 := List( [1..nB2], i -> zB );
+## zB1 := imB1;
+## zB2 := imB2;
+## Print( "zB1 = ", zB1, "\n" );
+## Print( "zB2 = ", zB2, "\n" );
+ for i in [1..nC1] do
+ ## c := ImageElm( act1, basA1[i] );
+ c := basC1[i];
+ imc := List( basB1, b -> ImageElm( eB1, ImageElm( c, b ) ) );
+ imc := Concatenation( imc, zB2 );
+## Print( "\nimc1 = ", imc, "\n\n" );
+ hom := LeftModuleHomomorphismByImages( B, B, basB, imc );
+## Error("here");
+ if ( hom = fail ) then
+ Print( "!!! hom = fail !!!\n" );
+ fi;
+ basC[i] := hom;
+ od;
+ for i in [1..nC2] do
+ ## c := ImageElm( act2, basA2[i] );
+ c := basC2[i];
+ imc := List( basB2, b -> ImageElm( eB2, ImageElm( c, b ) ) );
+ imc := Concatenation( zB1, imc );
+## Print( "\nimc2 = ", imc, "\n\n" );
+ hom := LeftModuleHomomorphismByImages( B, B, basB, imc );
+ basC[nC1+i] := hom;
+ od;
+
+## Print( "\nbasC = ", basC, "\n\n" );
+
+ C := AlgebraByGenerators( domA, basC );
+ act := AlgebraGeneralMappingByImages( A, C, basA, basC );
+ SetIsAlgebraAction( act, true );
+ SetAlgebraActedOn( act, B );
+ SetAlgebraActionType( act, "direct sum" );
+## Error("here");
+ return act;
+end );
+
+#############################################################################
+##
+#M DirectSumOfXModAlgebras
+##
+InstallMethod( DirectSumOfXModAlgebras, "for two crossed modules", true,
+ [ IsXModAlgebra, IsXModAlgebra ], 0,
+function( X1, X2 )
+ local S1, basS1, nS1, R, basR, nR, bdy1, act1, dom,
+ S2, basS2, nS2, bdy2, act2, bdy12, act12, X12, ok;
+ S1 := Source( X1 );
+ basS1 := CanonicalBasis( S1 );
+ nS1 := Length( basS1 );
+ R := Range( X1 );
+ basR := CanonicalBasis( R );
+ nR := Length( basR );
+ bdy1 := Boundary( X1 );
+ act1 := XModAlgebraAction( X1 );
+ dom := LeftActingDomain( S1 );
+ S2 := Source( X2 );
+ if not ( LeftActingDomain( S1 ) = dom ) then
+ Error( "conflicting domains" );
+
+ fi;
+ basS2 := CanonicalBasis( S2 );
+ nS2 := Length( basS2 );
+ if not ( R = Range( X2 ) ) then
+ Error( "X1, X2 do not have a common range" );
+ fi;
+ bdy2 := Boundary( X2 );
+ act2 := XModAlgebraAction( X2 );
+ ## now construct the combined boundary
+ bdy12 := DirectSumOfAlgebraHomomorphisms( bdy1, bdy2 );
+ act12 := AlgebraActionOnDirectSum( act1, act2 );
+ X12 := PreXModAlgebraByBoundaryAndAction( bdy12, act12 );
+ ok := IsPreXModAlgebra( X12 );
+ Print( "X12 is a pre-crossed module of algebras? ", ok, "\n" );
+ ok := IsXModAlgebra( X12 );
+ Print( "X12 is a crossed module of algebras? ", ok, "\n" );
+ return X12;
+end );
diff --git a/read.g b/read.g
index 0591bf3..da4eb81 100644
--- a/read.g
+++ b/read.g
@@ -2,14 +2,15 @@
##
#W read.g The XMODALG package Zekeriya Arvasi
#W & Alper Odabas
-#Y Copyright (C) 2014-2024, Zekeriya Arvasi & Alper Odabas,
+#Y Copyright (C) 2014-2025, Zekeriya Arvasi & Alper Odabas,
##
-## read the actual code
+## read the actual code
ReadPackage( "xmodalg", "lib/algebra.gi" );
-ReadPackage( "xmodalg", "lib/alg2obj.gi" );
+ReadPackage( "xmodalg", "lib/alg2obj.gi" );
ReadPackage( "xmodalg", "lib/module.gi" );
-ReadPackage( "xmodalg", "lib/alg2map.gi" );
+ReadPackage( "xmodalg", "lib/alg2map.gi" );
+ReadPackage( "xmodalg", "lib/dsum-xmod.gi" );
## temporary fix
RereadPackage( "xmodalg", "lib/vspchom.gi" );
diff --git a/tst/dsum-xmod.tst b/tst/dsum-xmod.tst
new file mode 100644
index 0000000..1de42ce
--- /dev/null
+++ b/tst/dsum-xmod.tst
@@ -0,0 +1,139 @@
+#############################################################################
+##
+#W dsum-xmod.tst XModAlg test files Z. Arvasi - A. Odabas
+##
+#@local level,m,A1,m3,A3,c3, Rc3,g3,mg3,Amg3,homg3,m2,A2,S2,nat2,Q2,bdy3,X3,X4,hom2,hom22a,hom33a,hom33b,actMA3,act4,act5,A5,B5,em3,ea3,XY3,C4
+
+gap> START_TEST( "XModAlg package: dsum-xmod.tst" );
+gap> level := InfoLevel( InfoXModAlg );;
+gap> SetInfoLevel( InfoXModAlg, 0 );
+
+## make this test independent of algebra.tst and module.tst
+gap> m := [ [0,1,2,3], [0,0,1,2], [0,0,0,1], [0,0,0,0] ];;
+gap> A1 := Algebra( Rationals, [m] );;
+gap> m3 := [ [0,1,0], [0,0,1], [1,0,0,] ];;
+gap> A3 := Algebra( Rationals, [m3] );;
+gap> SetName( A3, "A3" );;
+gap> c3 := Group( (1,2,3) );;
+gap> Rc3 := GroupRing( Rationals, c3 );;
+gap> SetName( Rc3, "GR(c3)" );
+gap> g3 := GeneratorsOfAlgebra( Rc3 )[2];;
+gap> mg3 := RegularAlgebraMultiplier( Rc3, Rc3, g3 );;
+gap> Amg3 := AlgebraByGenerators( Rationals, [ mg3 ] );;
+gap> homg3 := AlgebraHomomorphismByImages( A3, Amg3, [ m3 ], [ mg3 ] );;
+gap> m2 := [ [0,1,2,3], [0,0,1,2], [0,0,0,1], [0,0,0,0] ];;
+gap> A2 := Algebra( Rationals, [m2] );;
+gap> SetName( A2, "A2" );
+gap> S2 := Subalgebra( A2, [m2^3] );;
+gap> nat2 := NaturalHomomorphismByIdeal( A2, S2 );;
+gap> Q2 := Image( nat2 );;
+gap> SetName( Q2, "Q2" );
+
+## Section 4.1.7
+gap> bdy3 := AlgebraHomomorphismByImages( Rc3, A3, [ g3 ], [ m3 ] );
+[ (1)*(1,2,3) ] -> [ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] ]
+gap> X3 := XModAlgebraByBoundaryAndAction( bdy3, actg3 );
+[ GR(c3) -> A3 ]
+gap> Display( X3 );
+Crossed module [GR(c3) -> A3] :-
+: Source algebra GR(c3) has generators:
+ [ (1)*(), (1)*(1,2,3) ]
+: Range algebra A3 has generators:
+ [ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] ]
+: Boundary homomorphism maps source generators to:
+ [ [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
+ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] ]
+
+## Section 4.1.8
+gap> X4 := XModAlgebraByModule( A3, M3 );
+[A(M3)->A3]
+gap> XModAlgebraAction( X4 ) = act3;
+true
+gap> Display( X4 );
+Crossed module [A(M3)->A3] :-
+: Source algebra A(M3) has generators:
+ [ [[ 1, 0, 0 ]], [[ 0, 1, 0 ]], [[ 0, 0, 1 ]] ]
+: Range algebra A3 has generators:
+ [ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] ]
+: Boundary homomorphism maps source generators to:
+ [ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
+ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
+ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]
+
+## Section 2.4.3
+gap> hom2 := AlgebraHomomorphismByImages( A1, A1, [BA1[2]], [BA1[3]] );
+[ (Z(5)^0)*(1,2,3,4,5,6) ] -> [ (Z(5)^0)*(1,3,5)(2,4,6) ]
+gap> hom22a := DirectSumOfAlgebraHomomorphisms( hom2, hom2 );;
+gap> Print( hom33a, "\n" );
+AlgebraHomomorphismByImages( A3(+)A3, Algebra( Rationals,
+[ v.1, v.2, v.3, v.4, v.5, v.6 ] ),
+[ [ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ],
+ [ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 0, 1 ], [ 0, 0, 0, 1, 0, 0 ] ] ],
+[ v.1, v.4 ] )
+gap> hom33a := DirectSumOfAlgebraHomomorphisms( homg3, homg3 );
+gap> Print( "\nfirst direct sum of homg3 with itself is:\n", hom33a, "\n" );
+gap> hom33b := AlgebraHomomorphismFromDirectSum( homg3, homg3 );;
+gap> Print( hom33b, "\n" );
+
+## Section 2.4.4
+gap> actMA3 := AlgebraActionByMultipliers( A3, A3, A3 );;
+gap> act4 := AlgebraActionOnDirectSum( actMA3, actg3 );
+[ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ],
+ [ [ 0, 0, 1 ], [ 1, 0, 0 ], [ 0, 1, 0 ] ],
+ [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ] ] ->
+[ [ v.1, v.2, v.3, v.4, v.5, v.6 ] -> [ v.2, v.3, v.1, v.5, v.6, v.4 ],
+ [ v.1, v.2, v.3, v.4, v.5, v.6 ] -> [ v.3, v.1, v.2, v.6, v.4, v.5 ],
+ [ v.1, v.2, v.3, v.4, v.5, v.6 ] -> [ v.1, v.2, v.3, v.4, v.5, v.6 ] ]
+
+## Section 2.4.5
+gap> act5 := DirectSumOfAlgebraActions( actg3, act3 );;
+gap> A5 := Source( act5 );
+A3(+)A3
+gap> B5 := AlgebraActedOn( act5 );CanonicalBasis(A1);
+gap> em3 := ImageElm( Embedding( A5, 1 ), m3 );
+[ [ 0, 1, 0, 0, 0, 0 ], [ 0, 0, 1, 0, 0, 0 ], [ 1, 0, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]
+gap> ImageElm( act5, em3 );
+Basis( GR(c3)(+)A(M3), [ v.1, v.2, v.3, v.4, v.5, v.6 ] ) ->
+[ v.2, v.3, v.1, 0*v.1, 0*v.1, 0*v.1 ]
+gap> ea3 := ImageElm( Embedding( A5, 2 ), a3 );
+[ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ],
+ [ 0, 0, 0, 0, 2, 3 ], [ 0, 0, 0, 3, 0, 2 ], [ 0, 0, 0, 2, 3, 0 ] ]
+gap> ImageElm( act5, ea3 );
+Basis( GR(c3)(+)A(M3), [ v.1, v.2, v.3, v.4, v.5, v.6 ] ) ->
+[ 0*v.1, 0*v.1, 0*v.1, (3)*v.5+(2)*v.6, (2)*v.4+(3)*v.6, (3)*v.4+(2)*v.5 ]
+
+############################
+## Section 4.1.9
+gap> XY3 := DirectSumOfXModAlgebras( X3, Y3 );
+[ GR(c3)(+)A(M3) -> A3(+)A3 ]
+
+############################
+## Section 5.1.1
+gap> C4 := Cat1AlgebraOfXModAlgebra( X4 );
+[A3 |X A(M3) -> A3]
+gap> Display( C4 );
+Cat1-algebra [A3 |X A(M3)=>A3] :-
+: range algebra has generators:
+ [ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ] ]
+: tail homomorphism = head homomorphism
+ they map the source generators to:
+ [ [ [ 0, 1, 0 ], [ 0, 0, 1 ], [ 1, 0, 0 ] ],
+ [ [ 0, 0, 1 ], [ 1, 0, 0 ], [ 0, 1, 0 ] ],
+ [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ],
+ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
+ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
+ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]
+: range embedding maps range generators to:
+ [ v.1 ]
+: kernel has generators:
+ [ v.4, v.5, v.6 ]
+
+
+gap> STOP_TEST( "dsum-xmod.tst", 10000 );
+
+############################################################################
+##
+#E xmod.tst . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here