Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


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.53 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge