Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/GAP/lib/   (Algebra von RWTH Aachen Version 4.15.1©)  Datei vom 18.9.2025 mit Größe 115 kB image not shown  

Quelle  algrep.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Willem de Graaf.
##
##  Copyright of GAP belongs to its developers, whose names are too numerous
##  to list here. Please refer to the COPYRIGHT file for details.
##
##  SPDX-License-Identifier: GPL-2.0-or-later
##
##  This file contains the methods for general modules over algebras.
##


#############################################################################
##
#M  PrintObj( <obj> ) . . . . . . . . . . . . . . . . for an algebra module
#M  ViewObj( <obj> ) . . . . . . . . . . . . . . . .  for an algebra module
##
InstallMethod( PrintObj,
    "for algebra module",
    true, [ IsVectorSpace and IsAlgebraModule ], 0,
    function( V )

      if HasDimension( V ) then
         Print("<", Dimension(V), "-dimensional " );
      else
         Print( "<" );
      fi;
      if IsLeftAlgebraModuleElementCollection( V ) then
          if IsRightAlgebraModuleElementCollection( V ) then
              Print("bi-module over ");
              Print( LeftActingAlgebra( V ) );
              Print( " (left) and " );
              Print( RightActingAlgebra( V ) );
              Print( " (right)>" );
          else
              Print("left-module over ");
              Print( LeftActingAlgebra( V ) );
              Print(">");
          fi;
      else
          Print("right-module over ");
          Print( RightActingAlgebra( V ) );
          Print(">");
      fi;

  end );

  InstallMethod( ViewObj,
    "for algebra module",
    true, [ IsVectorSpace and IsAlgebraModule ], 0,
    function( V )

      if HasDimension( V ) then
         Print("<", Dimension(V), "-dimensional " );
      else
         Print( "<" );
      fi;
      if IsLeftAlgebraModuleElementCollection( V ) then
          if IsRightAlgebraModuleElementCollection( V ) then
              Print("bi-module over ");
              View( LeftActingAlgebra( V ) );
              Print( " (left) and " );
              View( RightActingAlgebra( V ) );
              Print( " (right)>" );
          else
              Print("left-module over ");
              View( LeftActingAlgebra( V ) );
              Print(">");
          fi;
      else
          Print("right-module over ");
          View( RightActingAlgebra( V ) );
          Print(">");
      fi;

end );

############################################################################
##
#M  ExtRepOfObj( <elm> )  . . . . . . . . . . . .  for algebra module elements
##
InstallMethod( ExtRepOfObj,
    "for algebra module element in packed element rep",
    true,
    [ IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
        elm -> elm![1] );

#############################################################################
##
#M  ObjByExtRep( <Fam>, <descr> ) . . . . . . . .  for algebra module elements
##
##
InstallMethod( ObjByExtRep,
    "for algebra module elements family, object",
    true,
    [ IsAlgebraModuleElementFamily, IsObject ], 0,
        function( Fam, vec )

    if Fam!.underlyingModuleEltsFam <> FamilyObj( vec ) then
        TryNextMethod();
    fi;
    return Objectify( Fam!.packedType, [ vec ] );
    end );



#############################################################################
##
#F  BasisOfAlgebraModule( <V>, <vecs> )  for space of algebra module elements
##                           and a list of elements thereof
##
##  Note that the work is delegated to a basis of the module
##  generated by the <v>![1] vectors, for <v> in <vecs>. This basis
##  is stored in the basis of the algebra module as <B>!.delegateBasis.
##
BindGlobal( "BasisOfAlgebraModule",
    function( V, vectors )
    local B, delmod, vecs;

    B:= Objectify( NewType( FamilyObj( V ),
                            IsFiniteBasisDefault and
                            IsBasisOfAlgebraModuleElementSpace and
                            IsAttributeStoringRep ),
                   rec() );
    SetUnderlyingLeftModule( B, V );
    SetBasisVectors( B, vectors );
    if IsEmpty( vectors ) then
        delmod:= VectorSpace( LeftActingDomain(V), [ ],
                         ExtRepOfObj( Zero(V) ) );
        B!.delegateBasis:= Basis( delmod );
    else
        vecs:= List( vectors, ExtRepOfObj );
        delmod:= VectorSpace( LeftActingDomain(V), vecs, "basis" );
        B!.delegateBasis:= Basis( delmod, vecs );
    fi;
    return B;
    end );


#############################################################################
##
#M  CanonicalBasis( <V> ) . . . . . .  for a space of algebra module elements
##
InstallMethod( CanonicalBasis,
    "for algebra module",
    [ IsVectorSpace and IsAlgebraModuleElementCollection ],
    function( V )
    local B, fam, vecs;

    B:= CanonicalBasis( VectorSpace( LeftActingDomain( V ),
            List( GeneratorsOfLeftModule( V ), ExtRepOfObj ) ) );
    fam:= ElementsFamily( FamilyObj( V ) );
    vecs:= List( BasisVectors( B ), x -> ObjByExtRep( fam, x ) );
    return BasisOfAlgebraModule( V, vecs );
    end );


#############################################################################
##
#M  LeftAlgebraModuleByGenerators( <A>, <op>, <gens> )
#M  LeftAlgebraModuleByGenerators( <A>, <op>, <gens>, "basis" )
##
##  The elements of an algebra module lie in the representation
##  `IsPackedElementDefaultRep': if <v> is an element of an algebra
##  module, then v![1] is an element of a vector space on which there
##  is an action of the algebra defined.
##
InstallMethod( LeftAlgebraModuleByGenerators,
    "for algebra, function of 2 args, module generators",
    true, [ IsAlgebra, IS_FUNCTION, IsHomogeneousList], 0,
    function( A, op, gens )

      local F,V;

      F:= LeftActingDomain( A );
      V:= VectorSpace( F, gens );
      return LeftAlgebraModule( A, op, V );

  end );

InstallOtherMethod( LeftAlgebraModuleByGenerators,
    "for algebra, function of 2 args, generators, string",
    true, [ IsAlgebra, IS_FUNCTION, IsHomogeneousList, IsString], 0,
    function( A, op, gens, str )

      local F,V;

      if str<>"basis" then
         Error( "Usage: LeftAlgebraModuleByGenerators( <A>, <op>, <gens>, <str>) where the last argument is the string \"basis\"" );
      fi;

      F:= LeftActingDomain( A );
      V:= VectorSpace( F, gens, str );
      return LeftAlgebraModule( A, op, V );

end );


#############################################################################
##
#M  RightAlgebraModuleByGenerators( <A>, <op>, <gens> )
#M  RightAlgebraModuleByGenerators( <A>, <op>, <gens>, "basis" )
##
##  The elements of an algebra module lie in the representation
##  `IsPackedElementDefaultRep': if <v> is an element of an algebra
##  module, then v![1] is an element of a vector space on which there
##  is an action of the algebra defined.
##
InstallMethod( RightAlgebraModuleByGenerators,
    "for algebra, function of 2 args, module generators",
    true, [ IsAlgebra, IS_FUNCTION, IsHomogeneousList], 0,
    function( A, op, gens )

      local F,V;

      F:= LeftActingDomain( A );
      V:= VectorSpace( F, gens );
      return RightAlgebraModule( A, op, V );

end );


InstallOtherMethod( RightAlgebraModuleByGenerators,
    "for algebra, function of 2 args, generators, string",
    true, [ IsAlgebra, IS_FUNCTION, IsHomogeneousList, IsString], 0,
    function( A, op, gens, str )

      local F,V;

      if str<>"basis" then
         Error( "Usage: RightAlgebraModuleByGenerators( <A>, <op>, <gens>, <str>) where the last argument is the string \"basis\"" );
      fi;

      F:= LeftActingDomain( A );
      V:= VectorSpace( F, gens, str );
      return RightAlgebraModule( A, op, V );

  end );

#############################################################################
##
#M  BiAlgebraModuleByGenerators( <A>, <B>, <opl>, <opr>, <gens> )
#M  BiAlgebraModuleByGenerators( <A>, <B>, <opl>, <opr>, <gens>, "basis" )
##
##  The elements of an algebra module lie in the representation
##  `IsPackedElementDefaultRep': if <v> is an element of an algebra
##  module, then v![1] is an element of a vector space on which there
##  is an action of the algebra defined.
##
InstallMethod( BiAlgebraModuleByGenerators,
 "for 2 algebras, function of 2 args, function of 2 args, module generators",
     true,
     [ IsAlgebra, IsAlgebra, IS_FUNCTION, IS_FUNCTION, IsHomogeneousList], 0,
    function( A, B, opl, opr, gens )

      local F,V;

      F:= LeftActingDomain( A );
      V:= VectorSpace( F, gens );
      return BiAlgebraModule( A, B, opl, opr, V );

  end );


InstallOtherMethod( BiAlgebraModuleByGenerators,
"for 2 algebras, function of 2 args, function of 2 args, generators, string",
true,
[ IsAlgebra, IsAlgebra, IS_FUNCTION, IS_FUNCTION, IsHomogeneousList, IsString],
        0,
    function( A, B, opl, opr, gens, str )

      local F,V;

      if str<>"basis" then
         Error( "Usage: BiAlgebraModuleByGenerators( <A>, <B>, <opl>, <opr>, <gens>, <str>) where the last argument is the string \"basis\"" );
      fi;

      F:= LeftActingDomain( A );
      V:= VectorSpace( F, gens, str );
      return BiAlgebraModule( A, B, opl, opr, V );

end );

#############################################################################
##
#M  LeftAlgebraModule( <A>, <op>, <V> )
##
##  The elements of an algebra module lie in the representation
##  `IsPackedElementDefaultRep': if <v> is an element of an algebra
##  module, then v![1] is an element of a vector space on which there
##  is an action of the algebra defined.
##
InstallMethod( LeftAlgebraModule,
    "for algebra, function of 2 args, underlying space",
    true, [ IsAlgebra, IS_FUNCTION, IsVectorSpace ], 0,
    function( A, op, V )

      local F,type,g,W,gens,B;

      F:= LeftActingDomain( A );
      type:= NewType( NewFamily( "AlgModElementsFam",
                                    IsLeftAlgebraModuleElement ),
                     IsPackedElementDefaultRep );
      gens:= GeneratorsOfLeftModule( V );
      if gens <> [] then
          g:= List( GeneratorsOfLeftModule( V ),
                    x -> Objectify( type, [ x ] ) );
      else
          g:= [ Objectify( type, [ Zero(V) ] ) ];
      fi;

      W:= Objectify( NewType( FamilyObj( g ),
                            IsLeftModule and IsAttributeStoringRep ),
                   rec() );
      SetLeftActingDomain( W, F );
      SetGeneratorsOfAlgebraModule( W, g );
      ElementsFamily( FamilyObj( W ) )!.left_operation:= op;
      ElementsFamily( FamilyObj( W ) )!.packedType:= type;
      ElementsFamily( FamilyObj( W ) )!.underlyingModuleEltsFam:=
                                              FamilyObj( Zero(V) );
      SetZero( ElementsFamily( FamilyObj( W ) ), Zero( g[1] ) );
      FamilyObj( W )!.leftAlgebraElementsFam:= ElementsFamily( FamilyObj(A) );
      SetIsAlgebraModule( W, true );
      SetLeftActingAlgebra( W, A );
      SetUnderlyingLeftModule( W, V );

      if HasBasis( V ) then
          B:= Objectify( NewType( FamilyObj( W ),
                      IsFiniteBasisDefault and
                      IsBasisOfAlgebraModuleElementSpace and
                      IsAttributeStoringRep ),
                      rec() );
          SetUnderlyingLeftModule( B, W );
          SetBasisVectors( B, List( Basis(V), x -> Objectify( type, [ x ] ) ));
          B!.delegateBasis:= Basis( V );
          SetDimension( W, Dimension(V) );
          SetBasis( W, B );
      fi;

      return W;

end );


#############################################################################
##
#M  RightAlgebraModule( <A>, <op>, <V> )
##
##  The elements of an algebra module lie in the representation
##  `IsPackedElementDefaultRep': if <v> is an element of an algebra
##  module, then v![1] is an element of a vector space on which there
##  is an action of the algebra defined.
##
InstallMethod( RightAlgebraModule,
    "for algebra, function of 2 args, underlying space",
    true, [ IsAlgebra, IS_FUNCTION, IsVectorSpace ], 0,
    function( A, op, V )

      local F,type,g,W,gens,B;

      F:= LeftActingDomain( A );
      type:= NewType( NewFamily( "AlgModElementsFam",
                                    IsRightAlgebraModuleElement ),
                     IsPackedElementDefaultRep );
      gens:= GeneratorsOfLeftModule( V );
      if gens <> [] then
          g:= List( GeneratorsOfLeftModule( V ),
                    x -> Objectify( type, [ x ] ) );
      else
          g:= [ Objectify( type, [ Zero(V) ] ) ];
      fi;

      W:= Objectify( NewType( FamilyObj( g ),
                            IsLeftModule and IsAttributeStoringRep ),
                   rec() );
      SetLeftActingDomain( W, F );
      SetGeneratorsOfAlgebraModule( W, g );
      ElementsFamily( FamilyObj( W ) )!.right_operation:= op;
      ElementsFamily( FamilyObj( W ) )!.packedType:= type;
      ElementsFamily( FamilyObj( W ) )!.underlyingModuleEltsFam:=
                                              FamilyObj( Zero(V) );
      SetZero( ElementsFamily( FamilyObj( W ) ), Zero( g[1] ) );
      FamilyObj( W )!.rightAlgebraElementsFam:= ElementsFamily( FamilyObj(A) );
      SetIsAlgebraModule( W, true );
      SetRightActingAlgebra( W, A );
      SetUnderlyingLeftModule( W, V );

      if HasBasis( V ) then
          B:= Objectify( NewType( FamilyObj( W ),
                      IsFiniteBasisDefault and
                      IsBasisOfAlgebraModuleElementSpace and
                      IsAttributeStoringRep ),
                      rec() );
          SetUnderlyingLeftModule( B, W );
          SetBasisVectors( B, List( Basis(V), x -> Objectify( type, [ x ] ) ));
          B!.delegateBasis:= Basis( V );
          SetDimension( W, Dimension(V) );
          SetBasis( W, B );
      fi;

      return W;

end );


#############################################################################
##
#M  BiAlgebraModule( <A>, <B>, <opl>, <opr>, <V> )
##
##  The elements of an algebra module lie in the representation
##  `IsPackedElementDefaultRep': if <v> is an element of an algebra
##  module, then v![1] is an element of a vector space on which there
##  is an action of the algebra defined.
##
InstallMethod( BiAlgebraModule,
         "for 2 algebras, function of 2 args, function of 2 args, module generators",
     true,
     [ IsAlgebra, IsAlgebra, IS_FUNCTION, IS_FUNCTION, IsVectorSpace], 0,
    function( A, B, opl, opr, V )

      local   F,  type,  g,  W, Ba, gens;

      F:= LeftActingDomain( A );
      type:= NewType( NewFamily( "AlgModElementsFam",
                          IsLeftAlgebraModuleElement and
                          IsRightAlgebraModuleElement ),
                       IsPackedElementDefaultRep );
      gens:= GeneratorsOfLeftModule( V );
      if gens <> [] then
          g:= List( GeneratorsOfLeftModule( V ),
                    x -> Objectify( type, [ x ] ) );
      else
          g:= [ Objectify( type, [ Zero(V) ] ) ];
      fi;

      W:= Objectify( NewType( FamilyObj( g ),
                            IsLeftModule and IsAttributeStoringRep ),
                   rec() );
      SetLeftActingDomain( W, F );
      SetGeneratorsOfAlgebraModule( W, g );
      ElementsFamily( FamilyObj( W ) )!.left_operation:= opl;
      ElementsFamily( FamilyObj( W ) )!.right_operation:= opr;
      ElementsFamily( FamilyObj( W ) )!.packedType:= type;
      ElementsFamily( FamilyObj( W ) )!.underlyingModuleEltsFam:=
                                              FamilyObj( Zero(V) );
      FamilyObj( W )!.leftAlgebraElementsFam:= ElementsFamily( FamilyObj(A) );
      FamilyObj( W )!.rightAlgebraElementsFam:= ElementsFamily( FamilyObj(B) );
      SetIsAlgebraModule( W, true );
      SetLeftActingAlgebra( W, A );
      SetRightActingAlgebra( W, B );
      SetZero( ElementsFamily( FamilyObj( W ) ), Zero( g[1] ) );
      SetUnderlyingLeftModule( W, V );

      if HasBasis( V ) then
          Ba:= Objectify( NewType( FamilyObj( W ),
                      IsFiniteBasisDefault and
                      IsBasisOfAlgebraModuleElementSpace and
                      IsAttributeStoringRep ),
                      rec() );
          SetUnderlyingLeftModule( Ba, W );
          SetBasisVectors( Ba, List( Basis(V), x -> Objectify( type, [ x ])));
          Ba!.delegateBasis:= Basis( V );
          SetDimension( W, Dimension(V) );
          SetBasis( W, Ba );
      fi;

      return W;

end );


############################################################################
##
#R  IsMutableBasisViaUnderlyingMutableBasisRep( <B> )
##
DeclareRepresentation( "IsMutableBasisViaUnderlyingMutableBasisRep",
    IsComponentObjectRep,
        [ "moduleElementsFam", "underlyingMutableBasis" ] );

############################################################################
##
#M  MutableBasis( <R>, <vectors> )
#M  MutableBasis( <R>, <vectors>, <zero> )
##
##  Mutable bases of algebra modules delegate the work to corresponding
##  mutable bases of the underlying vector spaces.
##
InstallMethod( MutableBasis,
    "for ring and vectors",
    true,
    [ IsRing, IsAlgebraModuleElementCollection ], 0,
    function( R, vectors )
    local B;

    if ForAll( vectors, IsZero ) then
      return MutableBasis( R, [], vectors[1] );
    fi;

    B:= rec(
             moduleElementsFamily:= FamilyObj( vectors[1] ),
             underlyingMutableBasis:= MutableBasis( R,
                                        List( vectors, ExtRepOfObj ) )
            );

    return Objectify( NewType( FamilyObj( vectors ),
                                 IsMutableBasis
                             and IsMutable
                             and IsMutableBasisViaUnderlyingMutableBasisRep ),
                      B );
end );

InstallOtherMethod( MutableBasis,
    "for ring, list and zero",
    true,
    [ IsRing, IsList, IsAlgebraModuleElement ], 0,
    function( R, vectors, zero )
    local B;

    B:= rec(
             moduleElementsFamily:= FamilyObj( zero ),
             underlyingMutableBasis:= MutableBasis( R,
                                        List( vectors, ExtRepOfObj ),
                                        ExtRepOfObj( zero ) )
            );

    return Objectify( NewType( CollectionsFamily( FamilyObj( zero ) ),
                                   IsMutableBasis
                               and IsMutable
                               and IsMutableBasisViaUnderlyingMutableBasisRep ),
                      B );
end );

#############################################################################
##
#M  PrintObj( <MB> ) . . . . . . . . . . . . . . . . . .  view a mutable basis
##
InstallMethod( PrintObj,
    "for mutable basis with underlying mutable basis",
    true,
    [ IsMutableBasis and IsMutableBasisViaUnderlyingMutableBasisRep ], 0,
    function( MB )
    Print( "<mutable basis with " );
    Print( NrBasisVectors( MB ), " vectors>" );
    end );


############################################################################
##
#M  BasisVectors( <MB> )
#M  CloseMutableBasis( <MB>, <v> )
#M  IsContainedInSpan( <MB>, <v> )
##
InstallOtherMethod( BasisVectors,
    "for mutable basis with underlying mutable basis",
    true,
    [ IsMutableBasis and IsMutableBasisViaUnderlyingMutableBasisRep ], 0,
    function( MB )
    # return the basis vectors of the underlying mutable basis, wrapped up.
    return List( BasisVectors( MB!.underlyingMutableBasis ), x ->
       ObjByExtRep( MB!.moduleElementsFamily, x ));
end );

InstallMethod( CloseMutableBasis,
    "for mutable basis with underlying mutable basis, and vector",
    IsCollsElms,
    [ IsMutableBasis and IsMutable and
      IsMutableBasisViaUnderlyingMutableBasisRep, IsVector ], 0,
    function( MB, v )
    return CloseMutableBasis( MB!.underlyingMutableBasis, ExtRepOfObj( v ) );

end );

InstallMethod( IsContainedInSpan,
    "for mutable basis with underlying mutable basis, and vector",
    IsCollsElms,
    [ IsMutableBasis and IsMutable and
      IsMutableBasisViaUnderlyingMutableBasisRep, IsVector ], 0,
    function( MB, v )

       return IsContainedInSpan( MB!.underlyingMutableBasis,
                   ExtRepOfObj( v ) );
end );

#############################################################################
##
#M  ActingAlgebra( <V> ) . . . . . . . . . . . . for an algebra module
##
InstallMethod( ActingAlgebra,
        "for an algebra module",
        true, [ IsAlgebraModule ], 0,
        function( V )

    if IsLeftAlgebraModuleElementCollection( V ) then
        if IsRightAlgebraModuleElementCollection( V ) then
            Error("ActingAlgebra is not defined for bi-modules");
        else
            return LeftActingAlgebra( V );
        fi;
    else
        return RightActingAlgebra( V );
    fi;
end );


#############################################################################
##
#M  PrintObj( <obj> ) . . . . . . . . . . . . . . . for algebra module element
##
InstallMethod( PrintObj,
    "for algebra module element in packed representation",
    true, [ IsAlgebraModuleElement and IsPackedElementDefaultRep], 0,
    function( v ) Print( v![1] ); end );

#############################################################################
##
#M  \=( <u>, <v> ) . . . . . . . . . . . . . . . for algebra module elements
#M  \<( <u>, <v> ) . . . . . . . . . . . . . . . for algebra module elements
#M  \+( <u>, <v> ) . . . . . . . . . . . . . . . for algebra module elements
#M  AdditiveInverseOp( <u> ) . .. . . . . . . . . . . . . . . for an algebra module element
#M  \*( <u>, <scal> ) . . . . . . for an algebra module element and a scalar
#M  \*( <scal>, <u> ) . . . . . . for a scalar and an algebra module element
#M  ZeroOp( <u> ) . . . . . . . . . . . . . . . .for an algebra module element
##
##

InstallMethod(\=,
    "for two algebra module elements in packed representation",
    IsIdenticalObj, [ IsAlgebraModuleElement and IsPackedElementDefaultRep,
              IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( u, v ) return u![1] = v![1]; end );

InstallMethod(\<,
    "for two algebra module elements in packed representation",
    IsIdenticalObj, [ IsAlgebraModuleElement and IsPackedElementDefaultRep,
              IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( u, v ) return u![1] < v![1]; end );

InstallMethod(\+,
    "for two algebra module elements in packed representation",
    IsIdenticalObj, [ IsAlgebraModuleElement and IsPackedElementDefaultRep,
              IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( u, v ) return ObjByExtRep( FamilyObj( u ), u![1]+v![1] ); end );

InstallMethod(\+,
    "for an algebra module element in packed representation and a vector",
    true, [ IsAlgebraModuleElement and IsPackedElementDefaultRep,
              IsVector ], 0,
    function( u, v ) return ObjByExtRep( FamilyObj( u ), u![1]+v ); end );


InstallMethod(\+,
    "for a vector and an algebra module element in packed representation",
    true, [ IsVector,
            IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( u, v ) return ObjByExtRep( FamilyObj( v ), u+v![1] ); end );

InstallMethod( AdditiveInverseOp,
    "for an algebra module element in packed representation",
    true, [ IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( u ) return ObjByExtRep( FamilyObj(u),  -u![1] ); end );

InstallMethod( \*,
    "for an algebra module element in packed representation and a scalar",
    true, [ IsAlgebraModuleElement and IsPackedElementDefaultRep,
            IsScalar ], 0,
    function( u, scal ) return ObjByExtRep( FamilyObj(u), scal*u![1] );
    end );


InstallMethod( \*,
    "for a scalar and an algebra module element in packed representation",
    true, [ IsScalar, IsAlgebraModuleElement and IsPackedElementDefaultRep],0,
    function( scal, u ) return ObjByExtRep( FamilyObj(u), scal*u![1] );
    end );

InstallMethod( ZeroOp,
    "for an algebra module element in packed representation",
    true, [ IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( u ) return ObjByExtRep( FamilyObj(u), 0*u![1] ); end );


#############################################################################
##
#M  \*( <obj>, <vec> ) . . . . . . . . . . . for a Lie object and a row vector
#M  \*( <vec>, <obj> ) . . . . . . . . . . . for a row vector and a Lie object
##
##
InstallMethod( \*,
    "for Lie object and row vector",
    true, [ IsLieObject and IsPackedElementDefaultRep, IsRowVector ], 0,
    function( m, v )
      return m![1]*v;
    end );

InstallMethod( \*,
    "for row vector and Lie object",
    true, [ IsRowVector, IsLieObject and IsPackedElementDefaultRep ], 0,
    function( v, m )
      return v*m![1];
    end );

#############################################################################
##
#M  \^( <a>, <v> ) . . . . . . . . . . . . for algebra elt, and elt of module
##
##  The action of an algebra element <a> on an element <v> of a left module
##  is denoted by <a>^<v>.
##
InstallOtherMethod( \^,
    "for an algebra element and an element of an algebra module",
    function( F1, F2 )
         return CollectionsFamily( F2 )!.leftAlgebraElementsFam = F1;
    end,
    [ IsRingElement,
          IsLeftAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( x, u  )
        return ObjByExtRep( FamilyObj( u ),
                        FamilyObj( u )!.left_operation(x,u![1]));
end );

#############################################################################
##
#M  \^( <a>, <v> ) . . . . . . . . . . . . for algebra elt, and elt of module
##
##  The action of an algebra element <a> on an element <v> of a right module
##  is denoted by <v>^<a>.
##
InstallOtherMethod( \^,
    "for an algebra element and an element of an algebra module",
    function( F1, F2 )
         return CollectionsFamily( F1 )!.rightAlgebraElementsFam = F2;
    end,
    [ IsRightAlgebraModuleElement and IsPackedElementDefaultRep,
          IsRingElement ], 0,
    function( u, x  )
        return ObjByExtRep( FamilyObj( u ),
                       FamilyObj( u )!.right_operation(u![1],x));
end );

#############################################################################
##
#M  Basis( <V> )  . . . . . . . . . . . . . . . . . . . for an algebra module
#M  Basis( <V> )  . . . . . . . . . .  for a space of algebra module elements
##
InstallMethod( Basis,
    "for an algebra module",
    true, [ IsFreeLeftModule and IsAlgebraModule ], 0,
    function( V )

      local A, gens, F, fam, B, vecs, from, op, ready;

      gens:= GeneratorsOfAlgebraModule( V );
      F:= LeftActingDomain( V );
      fam:= ElementsFamily( FamilyObj( V ) );
      if IsLeftAlgebraModuleElementCollection( V ) then
          if IsRightAlgebraModuleElementCollection( V ) then

              # We let the algebra act alternatingly from the left
              # and the right.
              vecs:= List( gens, ExtRepOfObj );
              from:= "left";
              op:= fam!.left_operation;
              ready:= false;
              A:= LeftActingAlgebra( V );

              while not ready do
                  B:= MutableBasisOfClosureUnderAction( F,
                              GeneratorsOfAlgebra( A ),
                              from,
                              vecs,
                              op,
                              ExtRepOfObj( Zero(V) ), "infinity" );
                  if Length( BasisVectors( B ) ) = Length( vecs ) and
                     from = "right" then
                      # from = "right", means that we acted both from the
                      # left and the right, and we did not find anything new.
                      # So we have a set of vectors closed under both the
                      # left and the right action.
                      ready:= true;
                  else
                      vecs:= BasisVectors( B );
                      if from = "left" then
                          from:= "right";
                          op:= fam!.right_operation;
                          A:= RightActingAlgebra( V );
                      else
                          from:= "left";
                          op:= fam!.left_operation;
                          A:= LeftActingAlgebra( V );
                      fi;
                  fi;

              od;

              vecs:= List( vecs, x -> ObjByExtRep( fam, x ) );
              SetDimension( V, Length( vecs ) );
              return BasisOfAlgebraModule( V, vecs );

          else
              from:= "left";
              op:= fam!.left_operation;
              A:= LeftActingAlgebra( V );
          fi;
      else
          from:= "right";
          op:= fam!.right_operation;
          A:= RightActingAlgebra( V );
      fi;
      B:= MutableBasisOfClosureUnderAction( F,
                  GeneratorsOfAlgebra( A ),
                  from,
                  List( gens, ExtRepOfObj ),
                  op,
                  ExtRepOfObj( Zero(V) ), "infinity" );
      vecs:= List( BasisVectors(B), x -> ObjByExtRep( fam, x ) );
      SetDimension( V, Length( vecs ) );
      return BasisOfAlgebraModule( V, vecs );
end );

InstallMethod( Basis,
    "for a space of algebra module elements",
    true, [ IsFreeLeftModule and IsAlgebraModuleElementCollection ], 0,
    function( V )

    local   g,  fam,  B,  vecs;

    if HasIsAlgebraModule( V ) and IsAlgebraModule( V ) then
        TryNextMethod();
    fi;

    # In this case `V' is just a vector space of algebra module
    # elements, so there is no need to apply the action of an
    # algebra to get the basis.

    g:= List( GeneratorsOfLeftModule( V ), ExtRepOfObj );
    fam:= ElementsFamily( FamilyObj( V ) );
    B:= Basis( VectorSpace( LeftActingDomain( V ), g ) );
    vecs:= List( BasisVectors(B), x -> ObjByExtRep( fam, x ) );
    return BasisOfAlgebraModule( V, vecs );
end );




##############################################################################
##
#M  Coefficients( <B>, <v> ). . . . . . for basis of a space of algebra
##                                      module elements and vector
##
InstallMethod( Coefficients,
    "for basis of a space of algebra module elements, and algebra module element",
    true, [ IsBasisOfAlgebraModuleElementSpace,
            IsAlgebraModuleElement and IsPackedElementDefaultRep ], 0,
    function( B, v )

      return Coefficients( B!.delegateBasis, v![1] );
end );

##############################################################################
##
#M  Basis( <V>, <vecs> )
#M  BasisNC( <V>, <vecs> )
##
##  The basis of the space of algebra module elements <V> consisting of the
##  vectors in <vecs>.
##  In the NC version it is not checked whether the elements of <vecs> are
##  linearly independent.
##
InstallMethod( Basis,
    "for a space of algebra module elements and a collection of algebra module elements",
    IsIdenticalObj,
    [ IsFreeLeftModule and IsAlgebraModuleElementCollection,
      IsAlgebraModuleElementCollection and IsList ], 0,
    function( V, vectors )

     local W;

      if not ForAll( vectors, x -> x in V ) then return fail; fi;

      W:= VectorSpace( LeftActingDomain(V), List( vectors, ExtRepOfObj ) );
      if Dimension( W ) <> Length( vectors ) then return fail; fi;
      return BasisOfAlgebraModule( V, vectors );
end );


InstallMethod( BasisNC,
    "for a space of algebra module elements and a collection of algebra module elements",
    IsIdenticalObj,
    [ IsFreeLeftModule and IsAlgebraModuleElementCollection,
      IsAlgebraModuleElementCollection and IsList ], 0,
    function( V, vectors )

      return BasisOfAlgebraModule( V, vectors );
end );

##########################################################################
##
#M  IsFiniteDimensional( <V> ) . . . . . . .  . for a space of algebra module
##                                              elements
##
InstallMethod( IsFiniteDimensional,
        "for a space of algebra module elements",
        true, [ IsFreeLeftModule and IsAlgebraModuleElementCollection ], 0,
        function( V )

    return Length( Basis( V ) ) < infinity;
end );

##########################################################################
##
#M  GeneratorsOfLeftModule( <V> ) . . . . . . .  . for a space of algebra
##                                                 module elements
##
InstallMethod( GeneratorsOfLeftModule,
        "for a space of algebra module elements",
        true, [ IsFreeLeftModule and IsAlgebraModuleElementCollection ], 0,
        function( V )

    return BasisVectors( Basis( V ) );
end );

############################################################################
##
#M  SubAlgebraModule( <V>, <gens> [,<"basis">] )
##
##  Is the submodule of <V> generated by <gens>.
##
BindGlobal("_SubAlgebraModuleHelper", function( V, gens, args... )
    local sub, isBasis;

    if Length(args)>0 and args[1]<>"basis" then
        Error( "Usage: SubAlgebraModule( <V>, <gens>, <str>) where the last argument is string \"basis\"" );
    fi;
    isBasis := Length(gens) = 0 or (Length(args)>0 and args[1]="basis");

    sub:= Objectify( NewType( FamilyObj( V ),
                     IsLeftModule and IsAttributeStoringRep ), rec() );
    SetIsAlgebraModule( sub, true );
    SetLeftActingDomain( sub, LeftActingDomain( V ) );
    SetGeneratorsOfAlgebraModule( sub, gens );

    if HasIsFiniteDimensional( V ) and IsFiniteDimensional( V ) then
        SetIsFiniteDimensional( sub, true );
    fi;

    if IsLeftAlgebraModuleElementCollection( V ) then
        SetLeftActingAlgebra( sub, LeftActingAlgebra( V ) );
    fi;

    if IsRightAlgebraModuleElementCollection( V ) then
        SetRightActingAlgebra( sub, RightActingAlgebra( V ) );
    fi;

    if isBasis then
        SetGeneratorsOfLeftModule( sub, gens );
        SetBasis( sub, BasisOfAlgebraModule( sub, gens ) );
        SetDimension( sub, Length( gens ) );
    fi;

    return sub;
end );

InstallMethod( SubAlgebraModule,
   "for algebra module, and a list of submodule generators",
   IsIdenticalObj,
   [ IsFreeLeftModule and IsAlgebraModule,
     IsAlgebraModuleElementCollection and IsList ],
   _SubAlgebraModuleHelper );

InstallOtherMethod( SubAlgebraModule,
   "for algebra module, and an empty list of submodule generators",
   [ IsFreeLeftModule and IsAlgebraModule,
     IsEmpty and IsList ],
   _SubAlgebraModuleHelper );

InstallOtherMethod( SubAlgebraModule,
   "for algebra module, and a list of submodule generators, and string",
   IsFamFamX,
   [ IsFreeLeftModule and IsAlgebraModule,
     IsAlgebraModuleElementCollection and IsList,
     IsString ],
   _SubAlgebraModuleHelper );

InstallOtherMethod( SubAlgebraModule,
   "for algebra module, and an empty list of submodule generators, and string",
   [ IsFreeLeftModule and IsAlgebraModule,
     IsEmpty and IsList,
     IsString ],
   _SubAlgebraModuleHelper );

##############################################################################
##
#M  LeftModuleByHomomorphismToMatAlg( <A>, <f> ) . . for algebra and hom to
##                                                   matrix algebra
##
InstallMethod( LeftModuleByHomomorphismToMatAlg,
   "for an algebra and a homomorphism to a matrix algebra",
   true, [ IsAlgebra, IsAlgebraHomomorphism ], 0,
   function( A, f )

     local zero,bas;

     if not A = Source(f) then
        Error( "<A> must be the source of the homomorphism <f>" );
     fi;

     zero:= Zero( Range( f ) );
     if not IsMatrix( zero ) then
        Error( "the range of <f> must be a matrix algebra" );
     fi;

     bas:= IdentityMat( Length(zero), LeftActingDomain(A) );
     return LeftAlgebraModuleByGenerators( A,
                      function( x, v ) return Image( f, x )*v; end,
                      bas, "basis");


   end );

##############################################################################
##
#M  RightModuleByHomomorphismToMatAlg( <A>, <f> ) . . for algebra and hom to
##                                                    matrix algebra
##
InstallMethod( RightModuleByHomomorphismToMatAlg,
   "for an algebra and a homomorphism to a matrix algebra",
   true, [ IsAlgebra, IsAlgebraHomomorphism ], 0,
   function( A, f )

     local zero,bas;

     if not A = Source(f) then
        Error( "<A> must be the source of the homomorphism <f>" );
     fi;

     zero:= Zero( Range( f ) );
     if not IsMatrix( zero ) then
        Error( "the range of <f> must be a matrix algebra" );
     fi;

     bas:= IdentityMat( Length(zero), LeftActingDomain(A) );
     return RightAlgebraModuleByGenerators( A,
                    function( v, x ) return v*Image( f, x ); end,
                      bas, "basis");


   end );

##############################################################################
##
#M  AdjointModule( <A> ) . . . . . . . . . . . . . . . . . . . for an algebra
##
##
InstallMethod( AdjointModule,
   "for an algebra",
   true, [ IsAlgebra ], 0,
    function( A )

    return LeftAlgebraModule( A, function( a, b ) return a*b; end, A);

end );


#############################################################################
##
#M  FaithfulModule( <A> ) . . . . . . . . . . . . for an associative algebra
##
##
InstallMethod( FaithfulModule,
   "for an algebra",
   true, [ IsAlgebra ], 0,
   function( A )

    local   bb,  n,  BA,  F,  bv,  i,  M,  j,  col, B;

    if One( A ) <> fail then
        # the adjoint module is faithful.
        return AdjointModule( A );
    fi;

    # construct the adjoint representation of A on the algebra
    # gotten from A by adding a one (Dorroh extension).

    bb:= [];
    n:= Dimension( A );
    BA:= Basis( A );
    F:= LeftActingDomain( A );
    bv:= BasisVectors( BA );

    for i in [1..n] do
        M:=[];
        for j in [1..n] do
            col:= ShallowCopy( Coefficients( BA, bv[i] * bv[j] ) );
            col[n+1]:= Zero( F );
            Add( M, col );
        od;
        col:= [ 1 .. n+1 ] * Zero( F );
        col[i]:= One( F );
        Add( M, col );
        Add( bb, TransposedMat( M ) );
    od;

    B:= Algebra( Rationals, bb, "basis" );

    return LeftModuleByHomomorphismToMatAlg( A,
                   AlgebraHomomorphismByImages( A, B, bv, bb ) );

end );



#############################################################################
##
#M  ModuleByRestriction( <V>, <sub> ) . . .for an alg module and a subalgebra
#M  ModuleByRestriction( <V>, <sub>, <sub> ) for a bi-alg module and
##                                           two subalgebras
##
InstallMethod( ModuleByRestriction,
   "for an algebra module and a subalgebra",
   true, [ IsAlgebraModule, IsAlgebra ], 0,
   function( V, sub )

    local   op, M;

    if IsLeftAlgebraModuleElementCollection( V ) then
        if IsRightAlgebraModuleElementCollection( V ) then
            return ModuleByRestriction( V, sub, sub );
        fi;
        op:= ElementsFamily( FamilyObj( V ) )!.left_operation;
        M:= UnderlyingLeftModule( V );
        if HasBasis( V ) and not HasBasis( M ) then
           if IsBound( Basis(V)!.delegateBasis ) then
              SetBasis( M, Basis(V)!.delegateBasis );
           fi;
        fi;
        return LeftAlgebraModule( sub, op, UnderlyingLeftModule( V ) );
    else
        op:= ElementsFamily( FamilyObj( V ) )!.right_operation;
        M:= UnderlyingLeftModule( V );
        if HasBasis( V ) and not HasBasis( M ) then
           if IsBound( Basis(V)!.delegateBasis ) then
              SetBasis( M, Basis(V)!.delegateBasis );
           fi;
        fi;
        return RightAlgebraModule( sub, op, M );
    fi;

end );


InstallOtherMethod( ModuleByRestriction,
   "for a bi-algebra module and a subalgebra and a subalgebra",
    true, [ IsAlgebraModule, IsAlgebra, IsAlgebra ], 0,
    function( V, subl, subr )

    local  basis, gens, M;

    if IsLeftAlgebraModuleElementCollection( V ) then
        if IsRightAlgebraModuleElementCollection( V ) then
           M:= UnderlyingLeftModule( V );
           if HasBasis( V ) and not HasBasis( M ) then
              if IsBound( Basis(V)!.delegateBasis ) then
                 SetBasis( M, Basis(V)!.delegateBasis );
              fi;
           fi;
            return BiAlgebraModule( subl, subr,
                        ElementsFamily( FamilyObj( V ) )!.left_operation,
                        ElementsFamily( FamilyObj( V ) )!.right_operation,
                               M );
        else
            Error( "<V> must be a bi-module");
        fi;
    else
        Error( "<V> must be a bi-module");
    fi;

end );


########################################################################
##
#M  NaturalHomomorphismBySubAlgebraModule( <V>, <W> )
##
##
InstallMethod( NaturalHomomorphismBySubAlgebraModule,
        "for algebra module and a submodule",
        IsIdenticalObj, [ IsAlgebraModule, IsAlgebraModule ], 0,
        function( V, W )

    local   f,  quot,  left_op,  right_op,  bb,  qmod,  imgs, nathom;

    f:= NaturalHomomorphismBySubspace( V, W );
    quot:= ImagesSource( f );

    if IsTrivial(quot) then
        quot := SubAlgebraModule( V, [], "basis" );
        nathom := ZeroMapping( V, quot );
        SetIsSurjective( nathom, true );
        SetImagesSource(nathom, quot);
        SetKernelOfAdditiveGeneralMapping( nathom, W );
        return nathom;
    fi;

    imgs:= List( Basis( V ), x -> Coefficients( Basis( quot ),
                   ImagesRepresentative(f,x)));

    # We make V/W into an algebra module and produce new linear map from
    # V into this module, doing exactly the same as f does.

    if IsLeftAlgebraModuleElementCollection( V ) then
        if IsRightAlgebraModuleElementCollection( V ) then
            left_op:= function( x, v )
                 return ImagesRepresentative( f, x^PreImagesRepresentative( f, v ) );
            end;
            right_op:= function( v, x )
                 return ImagesRepresentative( f, PreImagesRepresentative( f, v )^x );
            end;
            qmod:= BiAlgebraModule( LeftActingAlgebra( V ),
                           RightActingAlgebra( V ),
                           left_op, right_op, quot );
        else
            left_op:= function( x, v )
                 return ImagesRepresentative( f, x^PreImagesRepresentative( f, v ) );
            end;
            qmod:= LeftAlgebraModule( LeftActingAlgebra( V ),
                           left_op, quot);
        fi;
    else
        right_op:= function( v, x )
             return ImagesRepresentative( f, PreImagesRepresentative( f, v )^x );
        end;
        qmod:= RightAlgebraModule( RightActingAlgebra( V ),
                       right_op, quot );
    fi;

    nathom:= LeftModuleHomomorphismByMatrix( Basis( V ), imgs, Basis( qmod ) );
    SetIsSurjective( nathom, true );

    # Enter the preimages info.
    nathom!.basisimage:= Basis( qmod );
    if IsBound(f!.preimagesbasisimage) then
        nathom!.preimagesbasisimage:= f!.preimagesbasisimage;
    fi;
    SetKernelOfAdditiveGeneralMapping( nathom, W );

    # Run the implications for the factor.
    UseFactorRelation( V, W, qmod );

    return nathom;

end );

#############################################################################
##
#M  \/( <V>, <W> )  . . . . . . .  factor of an algebra module by a submodule
#M  \/( <V>, <vectors> )  . . . .  factor of an algebra module by a submodule
##
InstallOtherMethod( \/,
        "for an algebra module and collection",
        IsIdenticalObj,
        [ IsVectorSpace and IsAlgebraModule, IsCollection ], 0,
        function( V, vectors )
    if IsAlgebraModule( vectors ) then
        TryNextMethod();
    else
        return V / SubAlgebraModule( V, vectors );
    fi;
end );

InstallOtherMethod( \/,
        "for two algebra modules",
        IsIdenticalObj,
        [ IsVectorSpace and IsAlgebraModule, IsAlgebraModule ], 0,
        function( V, W )
    return ImagesSource( NaturalHomomorphismBySubAlgebraModule( V, W ) );
end );


##############################################################################
##
#M  MatrixOfAction( <B>, <x> )
#M  MatrixOfAction( <B>, <x>, <side> )
##
InstallMethod( MatrixOfAction,
        "for a basis of an algebra module and an algebra element",
        true, [ IsBasisOfAlgebraModuleElementSpace, IsObject ], 0,
        function( B, x )


    if IsRightAlgebraModuleElementCollection( B ) then
        if IsLeftAlgebraModuleElementCollection( B ) then
            Error( "usage MatrixOfAction( <B>, <x>, <side> )" );
        fi;

        return List( B, b -> Coefficients( B, b^x ) );
    else
        return TransposedMatDestructive(
                       List( B, b -> ShallowCopy( Coefficients( B, x^b ) ) ) );
    fi;

end );

InstallOtherMethod( MatrixOfAction,
        "for a basis of an algebra module, an algebra element and a side",
        true, [ IsBasisOfAlgebraModuleElementSpace, IsObject, IsObject ], 0,
        function( B, x, side )


    if side = "right" then
        return List( B, b -> Coefficients( B, b^x ) );
    else
        return TransposedMatDestructive(
                       List( B, b -> ShallowCopy( Coefficients( B, x^b ) ) ) );
    fi;

end );


##############################################################################
##
#R  IsMonomialElementRep( <obj> )
##
##  A monomial element is a list of two components: the first component
##  is a list of the form [ t1, c1, t2, c2...] where the ci are coefficients,
##  and the ti are monomials (where the meaning of the word `monomial'
##  may differ according to the context).
##  The second component is `true' or `false',
##  `true' if the monomial element is in normal form, `false' otherwise.
##
DeclareRepresentation( "IsMonomialElementRep", IsPositionalObjectRep, [1,2] );


############################################################################
##
#M  ObjByExtRep( <fam>, <list> ) . . . for a MonomialElementFamily and a list
#M  ExtRepOfObj( <t> )  . . . . . . .  for a monomial element in monomial rep.
##
InstallMethod( ObjByExtRep,
        "for a family of monomial elements and a list",
        true, [ IsMonomialElementFamily, IsList] , 0,
        function( fam, list )
    return Objectify( fam!.monomialElementDefaultType,
                   [ Immutable( list ), false ] );
end );


InstallMethod( ExtRepOfObj,
        "for a monomial element",
        true, [ IsMonomialElement and IsMonomialElementRep ] , 0,
        function( t )  return t![1];
end );

##############################################################################
##
#M  ZeroOp( <m> ) . . . . . . . . . . . . . . for a monomial element
#M  \+( <m1>, <m2> )  . . . . . . . . . . . . for two monomial elements
#M  AdditiveInverseOp( <m> ) . . . . . . . . . . . . . . . for a monomial element
#M  \*( <m>, <scal> ) . . . . . . . . . . for a monomial element and a scalar
#M  \*( <scal>, <m> ) . . . . . . . . . . for scalar and a monomial element
#M  \<( <m1>, <m2> ) . . . . . . . . . . . .  for two monomial elements
#M  \=( <m1>, <m2> ) . . . . . . . . . . . .  for two monomial elements
##
InstallMethod( ZeroOp,
        "for monomial elements",
        true, [ IsMonomialElement and IsMonomialElementRep ], 0,
        function( u )
    local res;
    res:= ObjByExtRep( FamilyObj( u ),
                  [ [], FamilyObj(u)!.zeroCoefficient ] );
    res![2]:= true;
    return res;
end );


InstallMethod(\+,
        "for monomial elements",
        IsIdenticalObj,
        [ IsMonomialElement and IsMonomialElementRep,
          IsMonomialElement and IsMonomialElementRep], 0,
        function( u, v )

    local lu,lv,zero, sum, res;

    # We assume that the monomials in the monomial elements are sorted
    # according to \<.

    lu:= u![1];
    lv:= v![1];
    zero:= FamilyObj( u )!.zeroCoefficient;
    sum:=  ZippedSum( lu, lv, zero, [\<,\+] );
    if Length( sum ) >= 2 then
        if sum[1] = [] and sum[2] = zero then
            Remove( sum, 1 );
            Remove( sum, 1 );
        fi;
    fi;
    if sum = [ ] then sum:= [ [], zero ]; fi;
    res:= ObjByExtRep( FamilyObj( u ), sum );
    if u![2] and v![2] then res![2]:= true; fi;
    return res;

end );

InstallMethod( AdditiveInverseOp,
        "for a monomial element",
        true,
        [ IsMonomialElement and IsMonomialElementRep ], 0,
        function( u )

    local lu,k,res;

    lu:= ShallowCopy( u![1] );
    for k in [2,4..Length(lu)] do
        lu[k]:= -lu[k];
    od;
    res:= ObjByExtRep( FamilyObj( u ), lu );
    if u![2] then res![2]:= true; fi;
    return res;

end );


InstallMethod(\*,
        "for a monomial element and a scalar",
        true,
        [ IsMonomialElement and IsMonomialElementRep, IsRingElement ], 0,
        function( u, scal )
    local lu,k,res;

    if IsZero(scal) then return Zero(u); fi;
    lu:= ShallowCopy( u![1] );
    for k in [2,4..Length(lu)] do
        lu[k]:= scal*lu[k];
    od;
    res:= ObjByExtRep( FamilyObj( u ), lu );
    if u![2] then res![2]:= true; fi;
    return res;

end );

InstallMethod(\*,
        "for a scalar and a monomial element",
        true,
        [ IsRingElement, IsMonomialElement and IsMonomialElementRep ], 0,
        function( scal, u  )
    local lu,k,res;

    if IsZero(scal) then return Zero(u); fi;
    lu:= ShallowCopy( u![1] );
    for k in [2,4..Length(lu)] do
        lu[k]:= scal*lu[k];
    od;
    res:= ObjByExtRep( FamilyObj( u ), lu );
    if u![2] then res![2]:= true; fi;
    return res;

end );


InstallMethod(\<,
        "for monomial elements",
        IsIdenticalObj,
        [ IsMonomialElement and IsMonomialElementRep,
          IsMonomialElement and IsMonomialElementRep], 0,
        function( u, v )
    local u1, v1;

    u1:= ConvertToNormalFormMonomialElement( u );
    v1:= ConvertToNormalFormMonomialElement( v );
    return u1![1] < v1![1];
end );

InstallMethod(\=,
        "for monomial elements",
        IsIdenticalObj,
        [ IsMonomialElement and IsMonomialElementRep,
          IsMonomialElement and IsMonomialElementRep], 0,
        function( u, v )

        local u1, v1;

    u1:= ConvertToNormalFormMonomialElement( u );
    v1:= ConvertToNormalFormMonomialElement( v );
    return u1![1] = v1![1];
end );

############################################################################
##
#F  TriangulizeMonomialElementList( <tt>, <zero>, <LM>, <LC> )
##
##  Here <tt> is a list of monomial elements, <zero> is the zero
##  of the ground field, <LM> is a function that calculates the
##  leading monomial of a monomial element (with respect to the ordering
##  \<), and <LC> is a function calculating the coefficient of the
##  leading monomial of a monomial element.
##
##  This function triangulizes the list <tt>, and returns a record with
##  the following components:
##
##  echelonbas: a list of basis vectors of the space spanned by <tt>,
##              in echelon form (with leading coefficients 1).
##
##  heads: a list of leading monomials of the elements of `echelonbas'.
##
##  basechange: a list of the same length as `ecelonbas' describing
##  the elements of `echlonbas' as linear combinations of the original
##  elements of `tt'. The elements of `basechange' are lists of the form
##  `[ l1, l2,...,lk ]', where the `li' are lists of the form `[ ind, cf ]';
##  the i-th element of `echelonbas' is the sum of `cf*tt[ind]'
##  when we loop over the entire list `basechange[i]'.
##
##  All of this is used to produce a basis of the space spaned by
##  `tt'.
##
BindGlobal( "TriangulizeMonomialElementList", function( tt, zero, LM, LC )

    local   basechange,  heads,  k,  cf,  i,  head,  b,  b1,  pos;

    # Initially `basechange' is just the identity.
    # We sort `tt' to get the smallest leading monomials first.

    basechange:= List( [1..Length(tt)], x -> [ [ x, One( zero ) ] ] );
    SortParallel( tt, basechange,
            function( u, v ) return LM(u) < LM(v); end );

    heads:= [ ];
    k:= 1;

    # We perform a Gaussian elimination...

    while k <= Length( tt ) do

        if IsZero( tt[k] ) then

            # Get rid of it.
            Remove( tt, k );
            Remove( basechange, k );
        else

            # Eliminate all instances of `LM( tt[k] )' that occur `below'
            # `tt[k]'.
            cf:= LC( tt[k] );
            tt[k]:= (1/cf)*tt[k];
            for i in [1..Length(basechange[k])] do
                basechange[k][i][2]:= basechange[k][i][2]/cf;
            od;

            head:= LM( tt[k] );
            Add( heads, head );
            i:= k+1;
            while i <= Length(tt) do
                if LM( tt[i] ) = head then
                    cf:= LC( tt[i] );
                    tt[i]:= tt[i] - cf*tt[k];
                    if IsZero( tt[i] ) then

                        # Get rid of it.
                        Remove( tt, i );
                        Remove( basechange, i );
                    else

                        # Adjust the i-th entry in basechange, we basically
                        # subtract `cf' times the k-th entry of basechange.
                        for b in basechange[k] do
                            b1:= [ b[1], -cf*b[2] ];
                            pos := PositionSorted( basechange[i], [b[1]]);
                            if pos > Length( basechange[i] ) or
                               basechange[i][pos][1] <> b1[1] then
                                Add(basechange[i],b1,pos);
                            else
                               basechange[i][pos][2]:= basechange[i][pos][2]+
                                                                  b1[2];
                            fi;

                        od;
                        i:= i+1;
                    fi;
                else
                    i:= i+1;
                fi;
            od;
            k:= k+1;
        fi;
        # sort the lists again...
        SortParallel( tt, basechange,
                function( u, v ) return LM(u) < LM(v); end );
    od;

    return rec( echelonbas:= tt, heads:= heads, basechange:= basechange );

end );

#############################################################################
##
#R  IsBasisOfMonomialSpaceRep( <B> )
##
##  A basis of a monomial space knows the output of
##  `TriangulizeMonomialElementList' with its basis vectors as input.
##  It also knows the zero of the ground field.
##
DeclareRepresentation( "IsBasisOfMonomialSpaceRep", IsComponentObjectRep,
        [ "echelonBasis", "heads", "baseChange", "zeroCoefficient" ] );


#############################################################################
##
#F  BasisOfMonomialSpace( <V>, <vecs> )  for space of monomial elements
##                           and a list of elements thereof
##
BindGlobal( "BasisOfMonomialSpace",
    function( V, vectors )
    local B;

    B:= Objectify( NewType( FamilyObj( V ),
                            IsFiniteBasisDefault and
                            IsBasisOfMonomialSpaceRep and
                            IsAttributeStoringRep ),
                   rec() );
    SetUnderlyingLeftModule( B, V );
    SetBasisVectors( B, vectors );

    return B;

end );


##############################################################################
##
#M  Basis( <V>, <vecs> )
#M  BasisNC( <V>, <vecs> )
##
##  The basis of the space of monomial elements <V> consisting of the
##  vectors in <vecs>.
##  In the NC version it is not checked whether the elements of <vecs> lie
##  in <V>.
##
##  In both cases the list of vectors <vecs> is triangulized, and the data
##  produced by this is stored in the basis.
##
InstallMethod( Basis,
    "for a space of monomial elements and a list of tensor elements",
    IsIdenticalObj,
    [ IsFreeLeftModule and IsMonomialElementCollection,
      IsMonomialElementCollection and IsList ], SUM_FLAGS,
    function( V, vectors )

      local B, info;

      if not ForAll( vectors, x -> x in V ) then return fail; fi;

      # A call to `ConvertToNormalFormMonomialElement' makes sure
      # that all monomial elements
      # are in normal form, and that they are all sorted. So the leading
      # element is just the first element in the list etc.

      vectors:= List( vectors, x -> ConvertToNormalFormMonomialElement( x ) );
      info:= TriangulizeMonomialElementList( ShallowCopy( vectors ),
                     ElementsFamily(FamilyObj(V))!.zeroCoefficient,
                     x -> ExtRepOfObj(x)[1],
                     x -> ExtRepOfObj(x)[2] );
      if Length( info.echelonbas ) <> Length( vectors ) then return fail; fi;
      B:= BasisOfMonomialSpace( V, vectors );
      B!.echelonBasis:= info.echelonbas;
      B!.heads:= info.heads;
      B!.baseChange:= info.basechange;
      B!.zeroCoefficient:= ElementsFamily(FamilyObj(V))!.zeroCoefficient;
      return B;
end );

InstallMethod( BasisNC,
    "for a space of monomial elements and a list of monomial elements",
    IsIdenticalObj,
    [ IsFreeLeftModule and IsMonomialElementCollection,
      IsMonomialElementCollection and IsList ], SUM_FLAGS,
    function( V, vectors )

      local B, info;

      # A call to `ConvertToNormalFormMonomialElement' makes sure that
      # all monomial elements
      # are in normal form, and that they are all sorted. So the leading
      # element is just the first element in the list etc.

      vectors:= List( vectors, x -> ConvertToNormalFormMonomialElement( x ) );
      info:= TriangulizeMonomialElementList( ShallowCopy( vectors ),
                     ElementsFamily(FamilyObj(V))!.zeroCoefficient,
                     x -> ExtRepOfObj(x)[1],
                     x -> ExtRepOfObj(x)[2] );
      if Length( info.echelonbas ) <> Length( vectors ) then return fail; fi;
      B:= BasisOfMonomialSpace( V, vectors );
      B!.echelonBasis:= info.echelonbas;
      B!.heads:= info.heads;
      B!.baseChange:= info.basechange;
      B!.zeroCoefficient:= ElementsFamily(FamilyObj(V))!.zeroCoefficient;
      return B;
end );

#############################################################################
##
#M  Basis( <V> ) . . . . . . . . . . . . . . for a space of monomial elements
##
InstallMethod( Basis,
    "for a space of monomial elements",
    true, [ IsFreeLeftModule and IsMonomialElementCollection ], SUM_FLAGS,
    function( V )

    local B, vectors, info;

    vectors:= List( GeneratorsOfLeftModule(V), x ->
                    ConvertToNormalFormMonomialElement( x ) );
    info:= TriangulizeMonomialElementList( vectors,
                   ElementsFamily(FamilyObj(V))!.zeroCoefficient,
                   x -> ExtRepOfObj(x)[1],
                   x -> ExtRepOfObj(x)[2] );
    B:= BasisOfMonomialSpace( V, info.echelonbas );
    B!.echelonBasis:= info.echelonbas;
    B!.heads:= info.heads;
    B!.baseChange:= List( [1..Length(info.echelonbas)], x -> [[ x, 1 ]] );
    B!.zeroCoefficient:= ElementsFamily(FamilyObj(V))!.zeroCoefficient;
    return B;

end );


##############################################################################
##
#M  Coefficients( <B>, <v> ). . . . . . for basis of a monomial space
##                                      and vector
##
InstallMethod( Coefficients,
    "for basis of a monomial space, and a vector",
        IsCollsElms, [ IsBasis and IsBasisOfMonomialSpaceRep,
                IsMonomialElement and IsMonomialElementRep], SUM_FLAGS,
    function( B, v )

    local   w,  cf,  i,  b, c;

    # We use the echelon basis that comes with <B>.

    w:= ConvertToNormalFormMonomialElement( v );
    cf:= List( BasisVectors( B ), x -> B!.zeroCoefficient );
    for i in [1..Length(B!.heads)] do

        if IsZero( w ) then return cf; fi;

        if  w![1][1] < B!.heads[i] then
            return fail;
        elif w![1][1] = B!.heads[i] then
            c:= w![1][2];
            w:= w - c*B!.echelonBasis[i];
            for b in B!.baseChange[i] do
                cf[b[1]]:= cf[b[1]] + b[2]*c;
            od;
        fi;
    od;

    if not IsZero( w ) then return fail; fi;
    return cf;

end );

##############################################################################
##
#M  PrintObj( <te> ) . . . . . . . . . . . . . for tensor elements
##
##  The zero tenso is represented by `[ [], 0 ]'.
##
InstallMethod( PrintObj,
        "for tensor elements",
        true, [ IsTensorElement and IsMonomialElementRep ], 0,
        function( u )

    local   eu,  k,  i;

    eu:= u![1];

    if eu[1] = [] then
        Print("<0-tensor>");
    else

        for k in [1,3..Length(eu)-1] do
            Print( eu[k+1], "*(" );
            for i in [1..Length(eu[k])-1] do
                Print(eu[k][i],"<x>");
            od;
            Print( Last(eu[k]), ")" );
            if k+1 <> Length( eu ) then
                if not ( IsRat( eu[k+3] ) and eu[k+3] < 0 ) then
                    Print("+");
                fi;
            fi;
        od;

    fi;

end );

##############################################################################
##
#M  ConvertToNormalFormMonomialElement( <te> ) . . for a tensor element
##
InstallMethod( ConvertToNormalFormMonomialElement,
        "for a tensor element",
        true, [ IsTensorElement ], 0,
        function( u )

    local   eu,  fam,  bases,  rank,  tensors,  cfts,  i,  le,  k,
            tt,  cf,  c,  is_replaced,  j,  tt1,  res, len;

    # We expand every component of every tensor in `u' wrt the bases
    # of the constituents of the tensor product. We assume those bases
    # are stored in the FamilyObj of the tensor element.

    if u![2] then return u; fi;

    eu:= ExtRepOfObj( u );
    fam:= FamilyObj( u );
    bases:= fam!.constituentBases;
    rank:= Length( bases );

    # `tensors' will be a list of tensors, i.e., a list of lists
    # of algebra module elements. `cfts' will be the list of their
    # coefficients.

    tensors:= [ ];
    cfts:= [ ];
    for i in [1,3..Length(eu)-1] do
        if eu[i] <> [ ] then #i.e., if it is not the zero tensor
            Add( tensors, eu[i] );
            Add( cfts, eu[i+1] );
        fi;
    od;
    if tensors = [ ] then
        # the thing is zero...
        res:= ObjByExtRep( fam, [ [], fam!.zeroCoefficient ] );
        res![2]:= true;
        return res;
    fi;

    for i in [1..rank] do

        # in all tensors expand the i-th component

        le:= Length( tensors );
        for k in [1..le] do
            tt:= ShallowCopy( tensors[k] );
            cf:= Coefficients( bases[i], tensors[k][i] );
            c:= cfts[k];

            # we replace the tensor on position `k', and add the rest
            # to the and of the list.

            is_replaced:= false;
            for j in [1..Length(cf)] do
                if cf[j] <> 0*cf[j] then
                    if not is_replaced then
                        tt1:= ShallowCopy( tt );
                        tt1[i]:= bases[i][j];
                        tensors[k]:= tt1;
                        cfts[k]:= c*cf[j];
                        is_replaced:= true;
                    else
                        tt1:= ShallowCopy( tt );
                        tt1[i]:= bases[i][j];
                        Add( tensors, tt1 );
                        Add( cfts, c*cf[j] );
                    fi;
                fi;
            od;
            if not is_replaced then
                # i.e., the tensor is zero, erase it
                Unbind( tensors[k] );
                Unbind( cfts[k] );
            fi;

        od;
        tensors:= Compacted( tensors );
        cfts:= Compacted( cfts );
    od;

    # Merge tensors and coefficients, take equal tensors together.
    SortParallel( tensors, cfts );
    res:= [ ];
    len:= 0;
    for i in [1..Length(tensors)] do
        if len > 0 and tensors[i] = res[len-1] then
            res[len]:= res[len]+cfts[i];
            if res[len] = 0*res[len] then
                Unbind( res[len-1] );
                Unbind( res[len] );
                len:= len-2;
            fi;
        else
            Add( res, tensors[i] );
            Add( res, cfts[i] );
            len:= len+2;
        fi;
    od;
    if res = [] then res:= [ [], fam!.zeroCoefficient ]; fi;

    res:= ObjByExtRep( fam, res );
    res![2]:= true;
    return res;

end );


##############################################################################
##
#M  TensorProductOp( <list> ) . . . . for a list of vectorspaces.
##
InstallMethod( TensorProductOp,
        "for a list of finite dimensional vector spaces, and a space (for method selection)",
        true, [ IsDenseList, IsVectorSpace ], 0,
        function( list, list1 )

    local   F,  fam,  type,  gens,  i,  gV,  gens1,  ten,  v,  ten1,
            VT,  BT;

    # We first make the family of the tensor elements, and construct
    # a basis of the tensor space. Note that if the arguments do not
    # know how to compute bases, then the rewriting of tensors to normal
    # forms will fail. Hence we can assume that every module has a basis,
    # and therefore we have a basis of the tensor space as well.

    F:= LeftActingDomain( list1 );

    if not ForAll( list, x -> LeftActingDomain(x) = F ) then
        Error("all vector spaces must be defined over the same field.");
    fi;

    fam:= NewFamily( "TensorElementsFam", IsTensorElement );
    type:= NewType( fam, IsMonomialElementRep );
    fam!.monomialElementDefaultType:= type;
    fam!.zeroCoefficient:= Zero( F );
    fam!.constituentBases:= List( list, Basis );

    if Length(list)=0 then
        gens := [One(F)];
    else
        gens:= List( Basis( list[1] ), x -> [ x ] );
    fi;
    for i in [2..Length(list)] do
        gV:= Basis( list[i] );
        gens1:= [ ];
--> --------------------

--> maximum size reached

--> --------------------

[ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ]