A double groupoid is a double category in which all the category structures are groupoids. There is also a pre-crossed module associated to the double groupoid. In a double groupoid, as well as objects and arrows we need a set of squares. A square is bounded by four arrows, two horizontal and two vertical, and there is a horizontal groupoid structure and a vertical groupoid structure on these squares. A square also contains an element of the source group of the pre-crossed module, and its image under the boundary map is equal to the boundary of the square. When printing a square, this element is located at the centre,
The double groupoids constructed here are special in that all four arrows come from the same groupoid. We call these edge-symmetric double groupoids.
This material in this chapter is experimental. It was started in 2023, in version 2.91, and extensively revised in 2025, for version 2.95. Further extensions are likely in due course.
It is assumed in this chapter that the reader is familiar with constructions for groupoids given in the Groupoids package, such as SinglePieceBasicDoubleGroupoid
. Such groupoids are basic, in that there is no pre-crossed module involvement. In XMod the operation SinglePieceDoubleGroupoid
requires a groupoid and a crossed module as input parameters.
‣ SinglePieceDoubleGroupoid ( gpd, pxmod ) | ( operation ) |
For an example we take for our groupoid the product of the group \(S_3 = \langle (7,8,9), (8,9) \rangle\) with the complete graph on \([-6 \ldots -1]\) and, for our pre-crossed module, the X12
, isomorphic to \((D_{12} \to S_3)\), constructed using XModByCentralExtension
(2.1-5). The source of X12
has generating set \(\left\{ g = (11,12,13,14,15,16),~ h = (12,16)(13,15) \right\}\).
gap> gens3 := [ (7,8,9), (8,9) ];; gap> s3 := Group( gens3 );; gap> SetName( s3, "s3" ); gap> Gs3 := Groupoid( s3, [-6..-1] );; gap> SetName( Gs3, "Gs3" ); gap> g := (11,12,13,14,15,16);; h := (12,16)(13,15);; gap> gend12 := [ g, h ];; gap> d12 := Group( gend12 );; gap> SetName( d12, "d12" ); gap> pr12 := GroupHomomorphismByImages( d12, s3, gend12, gens3 );; gap> X12 := XModByCentralExtension( pr12 );; gap> SetName( X12, "X12" ); gap> Display( X12 ); Crossed module X12 :- : Source group d12 has generators: [ (11,12,13,14,15,16), (12,16)(13,15) ] : Range group s3 has generators: [ (7,8,9), (8,9) ] : Boundary homomorphism maps source generators to: [ (7,8,9), (8,9) ] : Action homomorphism maps range generators to automorphisms: (7,8,9) --> { source gens --> [ (11,12,13,14,15,16), (11,13)(14,16) ] } (8,9) --> { source gens --> [ (11,16,15,14,13,12), (12,16)(13,15) ] } These 2 automorphisms generate the group of automorphisms. gap> D1 := SinglePieceDoubleGroupoid( Gs3, X12 );; gap> D1!.groupoid; Gs3 gap> D1!.prexmod; X12
‣ SquareOfArrows ( bdy, act ) | ( operation ) |
Let \(G\) be a groupoid with object set \(\Omega\) and object group \(g\). Let \(\Box\) be the set of squares with objects from \(\Omega\) at each corner; plus two vertical arrows and two horizontal arrows from Arr\((G)\). Further, let \(\calP = (\partial : S \to R)\) be a pre-crossed module, and let \(m_1 \in S\) be placed at the centre of the square. The following picture illustrates the situation where \(u_1,v_1,w_1,x_1 \in \Omega\) and \(a_1,b_1,c_1,d_1 \in g\).
\[ \vcenter{\xymatrix @=4pc{ u_1 \ar[r]^{a_1} \ar[d]_{b_1}\ar@{}[dr] |{m_1} & v_1 \ar[d]^{c_1} \\ w_1 \ar[r]_{d_1} & x_1 }} \]
We think of the square being based at the bottom, right-hand corner, \(x_1\). The boundary of the square is the loop \((x_1, d_1^{-1}b_1^{-1}a_1c_1,x_1) = (x_1,p_1,x_1)\). The boundary condition which \(m_1\) has to satisfy is that \(\partial m_1 = p_1\). (Beware a possible source of confusion. In the example code it is convenient of define arrow a1 := Arrow( Gs3, (7,8), -6, -5 );
whereas, in the description, \(a_1 = (7,8)\). Similarly for all the other arrows.)
gap> a1 := Arrow( Gs3, (7,8), -6, -5 );; gap> b1 := Arrow( Gs3, (7,9), -6, -1 );; gap> c1 := Arrow( Gs3, (8,9), -5, -3 );; gap> d1 := Arrow( Gs3, (7,8,9), -1, -3 );; gap> sq1 := SquareOfArrows( D1, g*h, a1, b1, c1, d1 ); [-6] ------------- (7,8) ------------> [-5] | | (7,9) (11,16)(12,15)(13,14) (8,9) V V [-1] ------------ (7,8,9) -----------> [-3] gap> m1 := ElementOfSquare( sq1 ); (11,16)(12,15)(13,14) gap> UpArrow( sq1 ); [(7,8) : -6 -> -5] gap> LeftArrow( sq1 ); [(7,9) : -6 -> -1] gap> RightArrow( sq1 ); [(8,9) : -5 -> -3] gap> DownArrow( sq1 ); [(7,8,9) : -1 -> -3] gap> ## check the boundary condition: gap> bdy1 := Boundary( D1!.prexmod );; gap> p1:= BoundaryOfSquare( sq1 ); [(7,9) : -3 -> -3] gap> ImageElm( bdy1, m1 ); (7,9)
‣ HorizontalProduct ( sq1, sq2 ) | ( operation ) |
When defining a horizontal composition, as illustrated by
\[ \vcenter{\xymatrix @=4pc{ u_1 \ar[r]^{a_1} \ar[d]_{b_1} \ar@{}[dr]|{m_1} & v_1 \ar[r]^{a_2} \ar[d]^{c_1} \ar@{}[dr]|{m_2} & v_2 \ar[d]^{c_2} \ar@{}[dr]|= & u_1 \ar[r]^{a_1a_2} \ar[d]_{b_1} \ar@{}[dr]|{m_1^{d_2}m_2} & v_2 \ar[d]^{c_2} \\ w_1 \ar[r]_{d_1} & x_1 \ar[r]_{d_2} & x_2 & w_1 \ar[r]_{d_1d_2} & x_2 }} \]
we have to move \(m_1\), based at \(x_1\), to the new base \(x_2\), and we do this by using the action of the pre-crossed module of \(d_2\) on \(m_1\). Notice that the boundary condition for the product is satisfied, since the first pre-crossed module axiom applies:
\[ \partial(m_1^{d_2}m_2) ~=~ \partial(m_1^{d_2}) (\partial m_2) ~=~ d_2^{-1}(d_1^{-1}b_1^{-1}a_1c_1)d_2(d_2^{-1}c_1^{-1}a_2c_2) ~=~ (d_1d_2)^{-1}b_1^{-1}(a_1a_2)c_2. \]
gap> a2 := Arrow( Gs3, (8,9), -5, -4 );; gap> c2 := Arrow( Gs3, (7,8), -4, -4 );; gap> d2 := Arrow( Gs3, (7,9), -3, -4 );; gap> sq2 := SquareOfArrows( D1, g^2, a2, c1, c2, d2 ); [-5] ------------ (8,9) -----------> [-4] | | (8,9) (11,13,15)(12,14,16) (7,8) V V [-3] ------------ (7,9) -----------> [-4] gap> m2 := ElementOfSquare( sq2 ); (11,13,15)(12,14,16) gap> LeftArrow( sq2 ) = RightArrow( sq1 ); true gap> sq12 := HorizontalProduct( sq1, sq2 ); [-6] ------------ (7,9,8) -----------> [-4] | | (7,9) (11,12)(13,16)(14,15) (7,8) V V [-1] ------------- (7,8) ------------> [-4] gap> ## check the boundary condition: gap> ed2 := ElementOfArrow( d2 );; gap> im1d2 := ImageElmXModAction( X12, m1, ed2 ); (11,16)(12,15)(13,14) gap> m12 := ElementOfSquare( sq12 ); (11,12)(13,16)(14,15) gap> im1d2 * m2 = m12; true
‣ VerticalProduct ( sq1, sq2 ) | ( operation ) |
Similarly, vertical composition is illustrated by
\[ \vcenter{\xymatrix @=2pc{ u_1 \ar[rr]^{a_1} \ar[dd]_{b_1} \ar@{}[ddrr]|{m_1} && v_1 \ar[dd]^{c_1} & & && \\ && & & u_1 \ar[rr]^{a_1} \ar[dd]_{b_1b_3} \ar@{}[ddrr]|{m_3m_1^{c_3}} && v_1 \ar[dd]^{c_1c_3} \\ w_1 \ar[rr]_{d_1} \ar[dd]_{b_3} \ar@{}[ddrr]|{m_3} && x_1 \ar[dd]^{c_3} &=& && \\ && & & w_3 \ar[rr]_{d_3} && x_3 \\ w_3 \ar[rr]_{d_3} && x_3 }} \]
Again the boundary condition is satisfied:
\[ \partial(m_3m_1^{c_3}) ~=~ (\partial m_3) \partial(m_1^{c_3}) ~=~ (d_3^{-1}b_3^{-1}d_1c_3)c_3^{-1}(d_1^{-1}b_1^{-1}a_1c_1)c_3 ~=~ d_3^{-1}(b_1b_3)^{-1}a_1(c_1c_3). \]
gap> b3 := Arrow( Gs3, (8,9), -1, -2 );; gap> c3 := Arrow( Gs3, (7,9,8), -3, -2 );; gap> d3 := Arrow( Gs3, (7,9), -2, -2 );; gap> sq3 := SquareOfArrows( D1, g, d1, b3, c3, d3 ); [-1] ------------ (7,8,9) -----------> [-3] | | (8,9) (11,12,13,14,15,16) (7,9,8) V V [-2] ------------- (7,9) ------------> [-2] gap> m3 := ElementOfSquare( sq3 ); (11,12,13,14,15,16) gap> UpArrow( sq3 ) = DownArrow( sq1 ); true gap> sq13 := VerticalProduct( sq1, sq3 ); [-6] ---------- (7,8) ---------> [-5] | | (7,8,9) (11,13)(14,16) (7,9) V V [-2] ---------- (7,9) ---------> [-2] gap> ## check the boundary condition: gap> ec3 := ElementOfArrow( c3 );; gap> im1c3 := ImageElmXModAction( X12, m1, ec3 ); (11,14)(12,13)(15,16) gap> m13 := ElementOfSquare( sq13 ); (11,13)(14,16) gap> m3 * im1c3 = m13; true
The HorizontalProduct
and VerticalProduct
commute, so we may construct products such as:
\[ \vcenter{\xymatrix @=2pc{ u_1 \ar[rr]^{a_1} \ar[dd]_{b_1} \ar@{}[ddrr]|{m_1} && v_1 \ar[rr]^{a_2} \ar[dd]|{c_1} \ar@{}[ddrr]|{m_2} && v_2 \ar[dd]^{c_2} & & &&& \\ && && & & u_1 \ar[rrr]^{a_1a_2} \ar[dd]_{b_1b_3} \ar@{}[ddrrr]|{m_3^{d_4}m_4\left(m_1^{d_2}m_2\right)^{c_4}} &&& v_2 \ar[dd]^{c_1c_4} \\ w_1 \ar[rr]|{d_1} \ar[dd]_{b_3} \ar@{}[ddrr]|{m_3} && x_1 \ar[rr]|{d_2} \ar[dd]|{c_3} \ar@{}[ddrr]|{m_4} && x_2 \ar[dd]^{c_4} &=& &&& \\ && && & & w_3 \ar[rrr]_{d_3d_4} &&& x_4 \\ w_3 \ar[rr]_{d_3} && x_3 \ar[rr]_{d_4} && x_4 }} \]
where
\[ m_3^{d_4}m_4 (m_1^{d_2}m_2)^{c_4} ~=~ (m_3m_1^{c_3})^{d_4} m_4m_2^{c_4} ~=~ (d_3d_4)^{-1}(b_1b_3)^{-1}(a_1a_2)(c_3c_4). \]
Continuing with our example, we check that the two ways of computing the product of four squares below agree.
\[ \vcenter{\xymatrix @=2pc{ -6 \ar[rr]^{(7,8)} \ar[dd]_{(7,9)} \ar@{}[ddrr]|{gh} && -5 \ar[rr]^{(8,9)} \ar[dd]|{(8,9)} \ar@{}[ddrr]|{g^2} && -4 \ar[dd]^{(7,8)} & & &&& \\ && && & & -6 \ar[rrr]^{(7,9,8)} \ar[dd]_{(7,8,9)} \ar@{}[ddrrr]|{(11,15,13)(12,16,14)} &&& -4 \ar[dd]^{(7,9,8)} \\ -1 \ar[rr]|{(7,8,9)} \ar[dd]_{(8,9)} \ar@{}[ddrr]|{g} && -3 \ar[rr]|{(7,9)} \ar[dd]|{(7,9,8)} \ar@{}[ddrr]|{h} && -4 \ar[dd]^{(8,9)} &=& &&& \\ && && & & -2 \ar[rrr]_{(7,9,8)} &&& -3 \\ -2 \ar[rr]_{(7,9)} && -2 \ar[rr]_{(7,8)} && -3 }} \]
gap> c4 := Arrow( Gs3, (8,9), -4, -3 );; gap> d4 := Arrow( Gs3, (7,8), -2, -3 );; gap> sq4 := SquareOfArrows( D1, h, d2, c3, c4, d4 );; gap> UpArrow(sq4)=DownArrow(sq2) and LeftArrow(sq4)=RightArrow(sq3); true gap> sq24 := VerticalProduct( sq2, sq4 ); [-5] ---------- (8,9) ---------> [-4] | | (7,9) (11,15)(12,14) (7,9,8) V V [-2] ---------- (7,8) ---------> [-3] gap> sq34 := HorizontalProduct( sq3, sq4 ); [-1] ------------- (7,8) ------------> [-4] | | (8,9) (11,12)(13,16)(14,15) (8,9) V V [-2] ------------ (7,9,8) -----------> [-3] gap> sq1324 := HorizontalProduct( sq13, sq24 ); [-6] ------------- (7,9,8) ------------> [-4] | | (7,8,9) (11,15,13)(12,16,14) (7,9,8) V V [-2] ------------- (7,9,8) ------------> [-3] gap> sq1234 := VerticalProduct( sq12, sq34 );; gap> sq1324 = sq1234; true
As mentioned earlier, double groupoids were introduced in the Groupoids package, but these were basic double groupoids, without any pre-crossed module. The element of a square was simply its boundary. Here we introduce an operation which converts such a basic double groupoid into the more general case considered in this package.
‣ EnhancedBasicDoubleGroupoid ( bdg ) | ( operation ) |
We need to add a pre-crossed module to the definition of a basic double groupoid. We choose to add \((G \to G)\) where \(G\) is the root group of the underlying groupoid. (This is only valid for groupoids which are the direct product with a complete graph.) The example is taken from section 7.1 of the Groupoids package, converting basic B0
to D0
, and we check that the same square is produced in each case.
gap> g2 := (1,2,3,4);; h2 := (1,3);; gap> gend8 := [ g2, h2 ];; gap> d8 := Group( gend8 );; gap> SetName( d8, "d8" ); gap> Gd8 := Groupoid( d8, [-9..-7] );; gap> SetName( Gd8, "Gd8" ); gap> B0 := SinglePieceBasicDoubleGroupoid( Gd8 );; gap> B0!.groupoid; Gd8 gap> B0!.objects; [ -9 .. -7 ] gap> a0 := Arrow(Gd8,(),-9,-7);; b0 := Arrow(Gd8,g2,-9,-9);; gap> c0 := Arrow(Gd8,h2,-7,-8);; d0 := Arrow(Gd8,(2,4),-9,-8);; gap> bdy0 := d0![2]^-1 * b0![2]^-1 * a0![2] * c0![2];; gap> bsq0 := SquareOfArrows( B0, bdy0, a0, b0, c0, d0 ); [-9] ---------- () ---------> [-7] | | (1,2,3,4) (1,4,3,2) (1,3) V V [-9] --------- (2,4) --------> [-8] gap> D0 := EnhancedBasicDoubleGroupoid( B0 );; gap> D0!.prexmod; [d8->d8] gap> bsq0 = SquareOfArrows( D0, bdy0, a0, b0, c0, d0 ); true
A double groupoid square
\[ \vcenter{\xymatrix @=4pc{ u_1 \ar[r]^{a_1} \ar[d]_{b_1}\ar@{}[dr] |{m} & v_1 \ar[d]^{c_1} \\ w_1 \ar[r]_{d_1} & x_1 }} \]
is commutative if \(a_1c_1 = b_1d_1\), which means that its boundary is the identity. So a double groupoid which consists only of commutative squares must have a pre-crossed module with zero boundary. Commutative squares compose horizontally and vertically provided only that they have the correct common arrow.
‣ DoubleGroupoidWithZeroBoundary ( gpd, src ) | ( operation ) |
The data for a double groupoid of commutative squares therefore consists of a groupoid and a source group. We may use the operation PreXModWithTrivialRange
(2.3-1) to provide a pre-crossed module. We take for our example the groupoid Gd8
and the pre-crossed module Q16
of section 2.3. We introduce a new right arrow to construct a square which commutes.
gap> D16 := DoubleGroupoidWithZeroBoundary( Gs3, d16 );; gap> D16!.prexmod; [d16->Group( [ () ] )] gap> e16 := Arrow( Gs3, (7,9,8), -5, -3 );; gap> sq16 := SquareOfArrows( D16, (12,18)(13,17)(14,16), a1, b1, e16, d1 ); [-6] -------------- (7,8) -------------> [-5] | | (7,9) (12,18)(13,17)(14,16) (7,9,8) V V [-1] ------------- (7,8,9) ------------> [-3]
generated by GAPDoc2HTML