Free Zinbiel Algebras - Algebras

Skip to content
Back to top
View this page
Edit this page

# Free Zinbiel Algebras

AUTHORS:

- Travis Scrimshaw (2015-09): initial version

class sage.algebras.free_zinbiel_algebra.FreeZinbielAlgebra(R, n, names, prefix, side)

  Bases: `CombinatorialFreeModule`

  The free Zinbiel algebra on \(n\) generators.

  Let \(R\) be a ring. A Zinbiel algebra is a non-associative algebra with multiplication \(\circ\) that satisfies

  \[(a \circ b) \circ c = a \circ (b \circ c) + a \circ (c \circ b).\]

  Zinbiel algebras were first introduced by Loday (see [Lod1995] and [LV2012]) as the Koszul dual to Leibniz algebras (hence the name coined by Lemaire).

  By default, the convention above is used. The opposite product, which satisfy the opposite axiom, can be used instead by setting the `side` parameter to `'>'` instead of the default value `'<'`.

  Zinbiel algebras are divided power algebras, in that for

  \[x^{\circ n} = \bigl(x \circ (x \circ \cdots \circ( x \circ x) \cdots ) \bigr)\]

  we have

  \[x^{\circ m} \circ x^{\circ n} = \binom{n+m-1}{m} x^{n+m}\]

  and

  \[\underbrace{\bigl( ( x \circ \cdots \circ x \circ (x \circ x) \cdots ) \bigr)}_{n+1 \text{ times}} = n! x^n.\]

  Note

  This implies that Zinbiel algebras are not power associative.

  To every Zinbiel algebra, we can construct a corresponding commutative associative algebra by using the symmetrized product:

  \[a * b = a \circ b + b \circ a.\]

  The free Zinbiel algebra on \(n\) generators is isomorphic as \(R\)-modules to the reduced tensor algebra \(\bar{T}(R^n)\) with the product

  \[(x_0 x_1 \cdots x_p) \circ (x_{p+1} x_{p+2} \cdots x_{p+q}) = \sum_{\sigma \in S_{p,q}} x_0 (x_{\sigma(1)} x_{\sigma(2)} \cdots x_{\sigma(p+q)},\]

  where \(S_{p,q}\) is the set of \((p,q)\)-shuffles.

  The free Zinbiel algebra is free as a divided power algebra. Moreover, the corresponding commutative algebra is isomorphic to the (non-unital) shuffle algebra.

  INPUT:

  - `R` – a ring

  - `n` – (optional) the number of generators

  - `names` – the generator names

  Warning

  Currently the basis is indexed by all finite words over the variables, including the empty word. This is a slight abuse as it is supposed to be indexed by all non-empty words.

  EXAMPLES:

  We create the free Zinbiel algebra and check the defining relation:

  Sage

      sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
      sage: (x*y)*z
      Z[xyz] + Z[xzy]
      sage: x*(y*z) + x*(z*y)
      Z[xyz] + Z[xzy]

  Python

      >>> from sage.all import *
      >>> Z = algebras.FreeZinbiel(QQ, names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
      >>> (x*y)*z
      Z[xyz] + Z[xzy]
      >>> x*(y*z) + x*(z*y)
      Z[xyz] + Z[xzy]

  We see that the Zinbiel algebra is not associative, not even power associative:

  Sage

      sage: x*(y*z)
      Z[xyz]
      sage: x*(x*x)
      Z[xxx]
      sage: (x*x)*x
      2*Z[xxx]

  [Python]

      >>> from sage.all import *
      >>> x*(y*z)
      Z[xyz]
      >>> x*(x*x)
      Z[xxx]
      >>> (x*x)*x
      2*Z[xxx]

  We verify that it is a divided power algebra:

  Sage

      sage: (x*(x*x)) * (x*(x*(x*x)))
      15*Z[xxxxxxx]
      sage: binomial(3+4-1,4)
      15
      sage: (x*(x*(x*x))) * (x*(x*x))
      20*Z[xxxxxxx]
      sage: binomial(3+4-1,3)
      20
      sage: ((x*x)*x)*x
      6*Z[xxxx]
      sage: (((x*x)*x)*x)*x
      24*Z[xxxxx]

  Python

      >>> from sage.all import *
      >>> (x*(x*x)) * (x*(x*(x*x)))
      15*Z[xxxxxxx]
      >>> binomial(Integer(3)+Integer(4)-Integer(1),Integer(4))
      15
      >>> (x*(x*(x*x))) * (x*(x*x))
      20*Z[xxxxxxx]
      >>> binomial(Integer(3)+Integer(4)-Integer(1),Integer(3))
      20
      >>> ((x*x)*x)*x
      6*Z[xxxx]
      >>> (((x*x)*x)*x)*x
      24*Z[xxxxx]

  A few tests with the opposite convention for the product:

  Sage

      sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ, side='>')
      sage: (x*y)*z
      Z[xyz]
      sage: x*(y*z)
      Z[xyz] + Z[yxz]

  [Python]

      >>> from sage.all import *
      >>> Z = algebras.FreeZinbiel(QQ, side='>', names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
      >>> (x*y)*z
      Z[xyz]
      >>> x*(y*z)
      Z[xyz] + Z[yxz]

  REFERENCES:

  - Wikipedia article Zinbiel_algebra

  - [Lod1995]

  - [LV2012]

  algebra_generators()

    Return the algebra generators of `self`.

    EXAMPLES:

    Sage

        sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
        sage: list(Z.algebra_generators())
        [Z[x], Z[y], Z[z]]

    Python

        >>> from sage.all import *
        >>> Z = algebras.FreeZinbiel(QQ, names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
        >>> list(Z.algebra_generators())
        [Z[x], Z[y], Z[z]]

  change_ring(R)

    Return the free Zinbiel algebra in the same variables over `R`.

    INPUT:

    - `R` – a ring

    The same side convention is used for the product.

    EXAMPLES:

    Sage

        sage: A = algebras.FreeZinbiel(ZZ, 'f,g,h')
        sage: A.change_ring(QQ)
        Free Zinbiel algebra on generators (Z[f], Z[g], Z[h])
        over Rational Field

    Python

        >>> from sage.all import *
        >>> A = algebras.FreeZinbiel(ZZ, 'f,g,h')
        >>> A.change_ring(QQ)
        Free Zinbiel algebra on generators (Z[f], Z[g], Z[h])
        over Rational Field

  construction()

    Return a pair `(F, R)`, where `F` is a `ZinbielFunctor` and `R` is a ring, such that `F(R)` returns `self`.

    EXAMPLES:

    Sage

        sage: P = algebras.FreeZinbiel(ZZ, 'x,y')
        sage: x,y = P.gens()
        sage: F, R = P.construction()
        sage: F
        Zinbiel[x,y]
        sage: R
        Integer Ring
        sage: F(ZZ) is P
        True
        sage: F(QQ)
        Free Zinbiel algebra on generators (Z[x], Z[y]) over Rational Field

    Python

        >>> from sage.all import *
        >>> P = algebras.FreeZinbiel(ZZ, 'x,y')
        >>> x,y = P.gens()
        >>> F, R = P.construction()
        >>> F
        Zinbiel[x,y]
        >>> R
        Integer Ring
        >>> F(ZZ) is P
        True
        >>> F(QQ)
        Free Zinbiel algebra on generators (Z[x], Z[y]) over Rational Field

  coproduct_on_basis(w)

    Return the coproduct of the element of the basis indexed by the word `w`.

    The coproduct is given by deconcatenation.

    INPUT:

    - `w` – a word

    EXAMPLES:

    Sage

        sage: F = algebras.FreeZinbiel(QQ,['a','b'])
        sage: F.coproduct_on_basis(Word('a'))
        Z[] # Z[a] + Z[a] # Z[]
        sage: F.coproduct_on_basis(Word('aba'))
        Z[] # Z[aba] + Z[a] # Z[ba] + Z[ab] # Z[a] + Z[aba] # Z[]
        sage: F.coproduct_on_basis(Word())
        Z[] # Z[]

    Python

        >>> from sage.all import *
        >>> F = algebras.FreeZinbiel(QQ,['a','b'])
        >>> F.coproduct_on_basis(Word('a'))
        Z[] # Z[a] + Z[a] # Z[]
        >>> F.coproduct_on_basis(Word('aba'))
        Z[] # Z[aba] + Z[a] # Z[ba] + Z[ab] # Z[a] + Z[aba] # Z[]
        >>> F.coproduct_on_basis(Word())
        Z[] # Z[]

  counit(S)

    Return the counit of `S`.

    EXAMPLES:

    Sage

        sage: F = algebras.FreeZinbiel(QQ,['a','b'])
        sage: S = F.an_element(); S
        Z[] + 2*Z[a] + 3*Z[b] + Z[bab]
        sage: F.counit(S)
        1

    Python

        >>> from sage.all import *
        >>> F = algebras.FreeZinbiel(QQ,['a','b'])
        >>> S = F.an_element(); S
        Z[] + 2*Z[a] + 3*Z[b] + Z[bab]
        >>> F.counit(S)
        1

  degree_on_basis(t)

    Return the degree of a word in the free Zinbiel algebra.

    This is the length.

    EXAMPLES:

    Sage

        sage: A = algebras.FreeZinbiel(QQ, 'x,y')
        sage: W = A.basis().keys()
        sage: A.degree_on_basis(W('xy'))
        2

    Python

        >>> from sage.all import *
        >>> A = algebras.FreeZinbiel(QQ, 'x,y')
        >>> W = A.basis().keys()
        >>> A.degree_on_basis(W('xy'))
        2

  gens()

    Return the generators of `self`.

    EXAMPLES:

    Sage

        sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
        sage: Z.gens()
        (Z[x], Z[y], Z[z])

    Python

        >>> from sage.all import *
        >>> Z = algebras.FreeZinbiel(QQ, names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
        >>> Z.gens()
        (Z[x], Z[y], Z[z])

  product_on_basis_left(x, y)

    Return the product < of the basis elements indexed by `x` and `y`.

    This is one half of the shuffle product, where the first letter comes from the first letter of the first argument.

    INPUT:

    - `x`, `y` – two words

    EXAMPLES:

    Sage

        sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
        sage: (x*y)*z  # indirect doctest
        Z[xyz] + Z[xzy]

    Python

        >>> from sage.all import *
        >>> Z = algebras.FreeZinbiel(QQ, names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
        >>> (x*y)*z  # indirect doctest
        Z[xyz] + Z[xzy]

  product_on_basis_right(x, y)

    Return the product > of the basis elements indexed by `x` and `y`.

    This is one half of the shuffle product, where the last letter comes from the last letter of the second argument.

    INPUT:

    - `x`, `y` – two words

    EXAMPLES:

    Sage

        sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ, side='>')
        sage: (x*y)*z  # indirect doctest
        Z[xyz]

    Python

        >>> from sage.all import *
        >>> Z = algebras.FreeZinbiel(QQ, side='>', names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
        >>> (x*y)*z  # indirect doctest
        Z[xyz]

  side()

    Return the choice of side for the product.

    This is either `'<'` or `'>'`.

    EXAMPLES:

    Sage

        sage: Z.<x,y,z> = algebras.FreeZinbiel(QQ)
        sage: Z.side()
        '<'

    Python

        >>> from sage.all import *
        >>> Z = algebras.FreeZinbiel(QQ, names=('x', 'y', 'z',)); (x, y, z,) = Z._first_ngens(3)
        >>> Z.side()
        '<'

class sage.algebras.free_zinbiel_algebra.ZinbielFunctor(variables, side)

  Bases: `ConstructionFunctor`

  A constructor for free Zinbiel algebras.

  EXAMPLES:

  Sage

      sage: P = algebras.FreeZinbiel(ZZ, 'x,y')
      sage: x,y = P.gens()
      sage: F = P.construction()[0]; F
      Zinbiel[x,y]

      sage: A = GF(5)['a,b']
      sage: a, b = A.gens()
      sage: F(A)
      Free Zinbiel algebra on generators (Z[x], Z[y])
      over Multivariate Polynomial Ring in a, b over Finite Field of size 5

      sage: f = A.hom([a+b,a-b],A)
      sage: F(f)
      Generic endomorphism of Free Zinbiel algebra on generators (Z[x], Z[y])
      over Multivariate Polynomial Ring in a, b over Finite Field of size 5

      sage: F(f)(a * F(A)(x))
      (a+b)*Z[x]

  Python

      >>> from sage.all import *
      >>> P = algebras.FreeZinbiel(ZZ, 'x,y')
      >>> x,y = P.gens()
      >>> F = P.construction()[Integer(0)]; F
      Zinbiel[x,y]

      >>> A = GF(Integer(5))['a,b']
      >>> a, b = A.gens()
      >>> F(A)
      Free Zinbiel algebra on generators (Z[x], Z[y])
      over Multivariate Polynomial Ring in a, b over Finite Field of size 5

      >>> f = A.hom([a+b,a-b],A)
      >>> F(f)
      Generic endomorphism of Free Zinbiel algebra on generators (Z[x], Z[y])
      over Multivariate Polynomial Ring in a, b over Finite Field of size 5

      >>> F(f)(a * F(A)(x))
      (a+b)*Z[x]

  merge(other)

    Merge `self` with another construction functor, or return `None`.

    EXAMPLES:

    Sage

        sage: functor = sage.algebras.free_zinbiel_algebra.ZinbielFunctor
        sage: F = functor(['x','y'], '<')
        sage: G = functor(['t'], '<')
        sage: F.merge(G)
        Zinbiel[x,y,t]
        sage: F.merge(F)
        Zinbiel[x,y]

    Python

        >>> from sage.all import *
        >>> functor = sage.algebras.free_zinbiel_algebra.ZinbielFunctor
        >>> F = functor(['x','y'], '<')
        >>> G = functor(['t'], '<')
        >>> F.merge(G)
        Zinbiel[x,y,t]
        >>> F.merge(F)
        Zinbiel[x,y]

    With an infinite generating set:

    Sage

        sage: H = functor(ZZ, '<')
        sage: H.merge(H) is H
        True
        sage: H.merge(F) is None
        True
        sage: F.merge(H) is None
        True

    [Python]

        >>> from sage.all import *
        >>> H = functor(ZZ, '<')
        >>> H.merge(H) is H
        True
        >>> H.merge(F) is None
        True
        >>> F.merge(H) is None
        True

    Now some actual use cases:

    Sage

        sage: R = algebras.FreeZinbiel(ZZ, 'x,y,z')
        sage: x,y,z = R.gens()
        sage: 1/2 * x
        1/2*Z[x]
        sage: parent(1/2 * x)
        Free Zinbiel algebra on generators (Z[x], Z[y], Z[z])
        over Rational Field

        sage: S = algebras.FreeZinbiel(QQ, 'z,t')
        sage: z,t = S.gens()
        sage: x * t
        Z[xt]
        sage: parent(x * t)
        Free Zinbiel algebra on generators (Z[z], Z[t], Z[x], Z[y])
        over Rational Field

    Python

        >>> from sage.all import *
        >>> R = algebras.FreeZinbiel(ZZ, 'x,y,z')
        >>> x,y,z = R.gens()
        >>> Integer(1)/Integer(2) * x
        1/2*Z[x]
        >>> parent(Integer(1)/Integer(2) * x)
        Free Zinbiel algebra on generators (Z[x], Z[y], Z[z])
        over Rational Field

        >>> S = algebras.FreeZinbiel(QQ, 'z,t')
        >>> z,t = S.gens()
        >>> x * t
        Z[xt]
        >>> parent(x * t)
        Free Zinbiel algebra on generators (Z[z], Z[t], Z[x], Z[y])
        over Rational Field

  rank = 9