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


SSL magma.gi   Sprache: unbekannt

 
#############################################################################
##
##  This file is part of GAP, a system for computational discrete algebra.
##  This file's authors include Thomas Breuer.
##
##  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 generic methods for magmas.
##


#############################################################################
##
#M  PrintObj( <M> ) . . . . . . . . . . . . . . . . . . . . . . print a magma
##
InstallMethod( PrintString,
    "for a magma",
    true,
    [ IsMagma ], 0,
    function( M )
    return "Magma( ... )";
    end );

InstallMethod( PrintString,
    "for a magma with generators",
    true,
    [ IsMagma and HasGeneratorsOfMagma ], 0,
    function( M )
    return STRINGIFY( "Magma( ", GeneratorsOfMagma( M ), " )" );
    end );

InstallMethod( PrintString,
    "for a magma-with-one with generators",
    true,
    [ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0,
    function( M )
    if IsEmpty( GeneratorsOfMagmaWithOne( M ) ) then
      return STRINGIFY("MagmaWithOne( ", One( M ), " )" );
    else
      return STRINGIFY( "MagmaWithOne( ", GeneratorsOfMagmaWithOne( M ), " )" );
    fi;
    end );

InstallMethod( PrintString,
    "for a magma-with-inverses with generators",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0,
    function( M )
    if IsEmpty( GeneratorsOfMagmaWithInverses( M ) ) then
      return STRINGIFY("MagmaWithInverses( ", One( M ), " )" );
    else
      return STRINGIFY("MagmaWithInverses( ", GeneratorsOfMagmaWithInverses(M), " )" );
    fi;
    end );


#############################################################################
##
#M  ViewObj( <M> )  . . . . . . . . . . . . . . . . . . . . . .  view a magma
##
InstallMethod( ViewString,
    "for a magma",
    true,
    [ IsMagma ], 0,
    function( M )
    return "<magma>";
    end );

InstallMethod( ViewString,
    "for a magma with generators",
    true,
    [ IsMagma and HasGeneratorsOfMagma ], 0,
    function( M )
    local nrgens;
    nrgens := Length( GeneratorsOfMagma(M) );
    return STRINGIFY( "<magma with ", Pluralize( nrgens, "generator" ), ">" );
    end );

InstallMethod( ViewString,
    "for a magma-with-one with generators",
    true,
    [ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0,
    function( M )
    local nrgens;
    nrgens := Length( GeneratorsOfMagmaWithOne(M) );
    if nrgens = 0 then
      return "<trivial magma-with-one>" ;
    fi;
    return STRINGIFY( "<magma-with-one with ",
                      Pluralize( nrgens, "generator" ), ">" );
    end );

InstallMethod( ViewString,
    "for a magma-with-inverses with generators",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0,
    function( M )
    local nrgens;
    nrgens := Length( GeneratorsOfMagmaWithInverses( M ) );
    if nrgens = 0 then
      return "<trivial magma-with-inverses>";
    fi;
    return STRINGIFY( "<magma-with-inverses with ",
                      Pluralize( nrgens, "generator" ), ">" );
    end );


#############################################################################
##
#M  IsTrivial( <M> )  . . . . . . . . . . . . test whether a magma is trivial
##
InstallImmediateMethod( IsTrivial,
    IsMagmaWithOne and HasGeneratorsOfMagmaWithOne, 0,
    function( M )
    if IsEmpty( GeneratorsOfMagmaWithOne( M ) ) then
      return true;
    else
      TryNextMethod();
    fi;
    end );

InstallMethod( IsTrivial,
    [IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses], 0,
    function( M )
    if IsEmpty( GeneratorsOfMagmaWithInverses( M ) ) then
      return true;
    else
      TryNextMethod();
    fi;
    end );


#############################################################################
##
#M  IsAssociative( <M> )  . . . . .  test whether a collection is associative
##
InstallMethod( IsAssociative,
    "for a collection",
    [ IsCollection ],
    function( M )

    local elms,      # list of elements
          i, j, k;   # loop variables

    # Test associativity for all triples of elements.
    elms:= Enumerator( M );
    for i in elms do
      for j in elms do
        for k in elms do
          if ( i * j ) * k <> i * ( j * k ) then
            return false;
          fi;
        od;
      od;
    od;

    # No associativity test failed.
    return true;
    end );


#############################################################################
##
#M  IsCommutative( <M> )  . . . . .  test whether a collection is commutative
##
InstallImmediateMethod( IsCommutative,
    IsMagma and IsAssociative and HasGeneratorsOfMagma, 0,
    function( M )
    if Length( GeneratorsOfMagma( M ) ) = 1 then
      return true;
    else
      TryNextMethod();
    fi;
    end );

InstallImmediateMethod( IsCommutative,
    IsMagmaWithOne and IsAssociative and HasGeneratorsOfMagmaWithOne, 0,
    function( M )
    if Length( GeneratorsOfMagmaWithOne( M ) ) = 1 then
      return true;
    else
      TryNextMethod();
    fi;
    end );

#  This used to be an immediate method. It was replaced by an ordinary
#  method, as the filter is now set when creating groups.
InstallMethod( IsCommutative,true,
    [IsMagmaWithInverses and IsAssociative
                        and HasGeneratorsOfMagmaWithInverses], 0,
    function( M )
    if Length( GeneratorsOfMagmaWithInverses( M ) ) = 1 then
      return true;
    else
      TryNextMethod();
    fi;
    end );

InstallMethod( IsCommutative,
    "for a collection",
    [ IsCollection ],
    function( C )
      local elms, n, x, y, i, j;

      elms:= Enumerator( C );
      n := Length( elms );
      for i in [ 1 .. n ] do
        for j in [ i + 1 .. n ] do
          x := elms[ i ];
          y := elms[ j ];
          if x * y <> y * x then
            return false;
          fi;
        od;
      od;
      return true;
    end);

InstallMethod( IsCommutative,
    "for a magma",
    true,
    [ IsMagma ], 0,
    IsCommutativeFromGenerators( GeneratorsOfDomain ) );

InstallMethod( IsCommutative,
    "for an associative magma",
    true,
    [ IsMagma and IsAssociative ], 0,
    IsCommutativeFromGenerators( GeneratorsOfMagma ) );

InstallMethod( IsCommutative,
    "for an associative magma with one",
    true,
    [ IsMagmaWithOne and IsAssociative ], 0,
    IsCommutativeFromGenerators( GeneratorsOfMagmaWithOne ) );

InstallMethod( IsCommutative,
    "for an associative magma with inverses",
    true,
    [ IsMagmaWithInverses and IsAssociative ], 0,
    IsCommutativeFromGenerators( GeneratorsOfMagmaWithInverses ) );


#############################################################################
##
#P  IsFinitelyGeneratedMagma( <M> ) . . . . test whether a magma is fin. gen.
##
InstallMethod( IsFinitelyGeneratedMagma,
    [ IsMagma and HasGeneratorsOfMagma ],
    function( M )
    if IsFinite( GeneratorsOfMagma( M ) ) then
      return true;
    fi;
    TryNextMethod();
    end );

InstallMethod( IsFinitelyGeneratedMagma,
    [ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ],
    function( M )
    if IsFinite( GeneratorsOfMagmaWithOne( M ) ) then
      return true;
    fi;
    TryNextMethod();
    end );

InstallMethod( IsFinitelyGeneratedMagma,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ],
    function( M )
    if IsFinite( GeneratorsOfMagmaWithInverses( M ) ) then
      return true;
    fi;
    TryNextMethod();
    end );


#############################################################################
##
#M  Centralizer( <M>, <elm> ) . . . . .  centralizer of an element in a magma
#M  Centralizer( <M>, <N> ) . . . . . . . . centralizer of a magma in a magma
##
InstallMethod( CentralizerOp,
    "for a magma, and a mult. element",
    IsCollsElms,
    [ IsMagma, IsMultiplicativeElement ], 0,
    function( M, obj )
    return Filtered( AsList( M ), x -> x * obj = obj * x );
    end );

InstallMethod( CentralizerOp,
    "for a commutative magma, and a mult. element",
    IsCollsElms,
    [ IsMagma and IsCommutative, IsMultiplicativeElement ],
    SUM_FLAGS, # for commutative magmas this is best possible
  function( M, obj )
    if obj in M then
      return M;
    else
      TryNextMethod();
    fi;
  end );

InstallMethod( CentralizerOp,
    "for two magmas",
    IsIdenticalObj,
    [ IsMagma, IsMagma ], 0,
    function( M, N )
    return Filtered( M, x -> ForAll( N, y -> x * y = y * x ) );
    end );

InstallMethod( CentralizerOp,
    "for two magmas, the first being commutative",
    IsIdenticalObj,
    [ IsMagma and IsCommutative, IsMagma ],
    SUM_FLAGS, # for commutative magmas this is best possible
  function( M, N )
    if IsSubset( M, N ) then
      return M;
    else
      TryNextMethod();
    fi;
  end );

InstallOtherMethod( CentralizerOp,
    "dummy to ignore optional third argument",
    true,
    [ IsMagma, IsObject,IsObject ], 0,
    function( M, obj, x )
    return CentralizerOp( M, obj );
    end );


#############################################################################
##
#M  Centre( <M> ) . . . . . . . . . . . . . . . . . . . . . centre of a magma
##
InstallMethod( Centre,
    "generic method for a magma",
    [ IsMagma ],
    function( M )
    local T;
    T:= Tuples( M, 2 );
    M:= Filtered( M, x -> ForAll( M, y -> x * y = y * x ) and
                          ForAll( T, p -> (p[1]*p[2])*x = p[1]*(p[2]*x) and
                                          (p[1]*x)*p[2] = p[1]*(x*p[2]) and
                                          (x*p[1])*p[2] = x*(p[1]*p[2]) ) );
    if IsDomain( M ) then
      Assert( 1, IsAbelian( M ) );
      SetIsAbelian( M, true );
    fi;
    return M;
    end );

InstallMethod( Centre,
    "for an associative magma",
    [ IsMagma and IsAssociative ],
    function( M )
    M:= Centralizer( M, M );
    if IsDomain( M ) then
      Assert( 1, IsAbelian( M ) );
      SetIsAbelian( M, true );
    fi;
    return M;
    end );

InstallMethod( Centre,
    "for an associative and commutative magma",
    [ IsMagma and IsAssociative and IsCommutative ],
    SUM_FLAGS, # for commutative magmas this is best possible
    IdFunc );


#############################################################################
##
#A  Idempotents( <M> ) . .  . . . . . . . . . . . . . . idempotents of a magma
##
InstallMethod(Idempotents,"for finite magmas", true,
               [IsMagma], 0,
     function(M)
     local I, m;
     I := [];

     for m in AsList(M) do
         if m*m=m then
             Add(I,m);
         fi;
     od;
     return I;
end);

#############################################################################
##
#F  Magma( <gens> )
#F  Magma( <Fam>, <gens> )
##
InstallGlobalFunction( Magma, function( arg )

    # list of generators
    if Length( arg ) = 1 and IsList( arg[1] ) and 0 < Length( arg[1] ) then
      return MagmaByGenerators( arg[1] );

    # family plus list of generators
    elif Length( arg ) = 2 and IsFamily( arg[1] ) and IsList( arg[2] ) then
      return MagmaByGenerators( arg[1], arg[2] );

    # generators
    elif 0 < Length( arg ) then
      return MagmaByGenerators( arg );
    fi;

    # no argument given, error
    Error("usage: Magma(<gens>), Magma(<Fam>,<gens>)");
end );


#############################################################################
##
#F  Submagma( <M>, <gens> ) . . . . . . . submagma of <M> generated by <gens>
##
InstallGlobalFunction( Submagma, function( M, gens )

    if not IsMagma( M ) then
        Error( "<M> must be a magma" );
    elif IsEmpty( gens ) then
        return SubmagmaNC( M, gens );
    elif not IsHomogeneousList(gens)  then
        Error( "<gens> must be a homogeneous list of elements" );
    elif not IsIdenticalObj( FamilyObj(M), FamilyObj(gens) )  then
        Error( "families of <gens> and <M> are different" );
    fi;
    if not ForAll( gens, x -> x in M ) then
        Error( "<gens> must be elements in <M>" );
    fi;
    return SubmagmaNC( M, gens );
end );


#############################################################################
##
#F  SubmagmaNC( <M>, <gens> )
##
##  Note that `SubmagmaNC' is allowed to call `Objectify'
##  in the case that <gens> is empty.
##
InstallGlobalFunction( SubmagmaNC, function( M, gens )
    local K, S;

    if IsEmpty( gens ) then
      K:= NewType( FamilyObj(M),
                       IsMagma
                   and IsEmpty
                   and IsAttributeStoringRep );
      S:= Objectify( K, rec() );
      SetGeneratorsOfMagma( S, [] );
    else
      S:= MagmaByGenerators(gens);
    fi;
    SetParent( S, M );
    return S;
end );


#############################################################################
##
#F  MagmaWithOne( <gens> )
#F  MagmaWithOne( <Fam>, <gens> )
##
InstallGlobalFunction( MagmaWithOne, function( arg )

    # list of generators
    if Length( arg ) = 1 and IsList( arg[1] ) and 0 < Length( arg[1] ) then
      return MagmaWithOneByGenerators( arg[1] );

    # family plus list of generators
    elif Length( arg ) = 2 and IsFamily( arg[1] ) and IsList( arg[2] ) then
      return MagmaWithOneByGenerators( arg[1], arg[2] );

    # generators
    elif 0 < Length( arg ) then
      return MagmaWithOneByGenerators( arg );
    fi;

    # no argument given, error
    Error("usage: MagmaWithOne(<gens>), MagmaWithOne(<Fam>,<gens>)");
end );


#############################################################################
##
#F  SubmagmaWithOne( <M>, <gens> )  . submagma-with-one of <M> gen. by <gens>
##
InstallGlobalFunction( SubmagmaWithOne, function( M, gens )

    if not IsMagmaWithOne( M ) then
        Error( "<M> must be a magma-with-one" );
    elif IsEmpty( gens ) then
        return SubmagmaWithOneNC( M, gens );
    elif not IsHomogeneousList(gens)  then
        Error( "<gens> must be a homogeneous list of elements" );
    elif not IsIdenticalObj( FamilyObj(M), FamilyObj(gens) )  then
        Error( "families of <gens> and <M> are different" );
    fi;
    if not ForAll( gens, x -> x in M ) then
        Error( "<gens> must be elements in <M>" );
    fi;
    return SubmagmaWithOneNC( M, gens );
end );


#############################################################################
##
#F  SubmagmaWithOneNC( <M>, <gens> )
##
##  Note that `SubmagmaWithOneNC' is allowed to call `Objectify'
##  in the case that <gens> is empty.
##
##  Furthermore note that a trivial submagma-with-one is automatically
##  a group.
##
InstallGlobalFunction( SubmagmaWithOneNC, function( M, gens )
    local K, S;

    if IsEmpty( gens ) then
      K:= NewType( FamilyObj(M),
                       IsMagmaWithInverses
                   and IsTrivial
                   and IsAttributeStoringRep );
      S:= Objectify( K, rec() );
      SetGeneratorsOfMagmaWithInverses( S, [] );
      SetSize( S, 1 );
#T should be unnecessary since `IsTrivial' implies a good `Size' method
    else
      S:= MagmaWithOneByGenerators(gens);
    fi;
    SetParent( S, M );
    return S;
end );


#############################################################################
##
#F  MagmaWithInverses( <gens> )
#F  MagmaWithInverses( <Fam>, <gens> )
##
InstallGlobalFunction( MagmaWithInverses, function( arg )

    # list of generators
    if Length( arg ) = 1 and IsList( arg[1] ) and 0 < Length( arg[1] ) then
      return MagmaWithInversesByGenerators( arg[1] );

    # family plus list of generators
    elif Length( arg ) = 2 and IsFamily( arg[1] ) and IsList( arg[2] ) then
      return MagmaWithInversesByGenerators( arg[1], arg[2] );

    # generators
    elif 0 < Length( arg ) then
      return MagmaWithInversesByGenerators( arg );
    fi;

    # no argument given, error
    Error("usage: MagmaWithInverses(<gens>), ",
          "MagmaWithInverses(<Fam>,<gens>)");
end );


#############################################################################
##
#F  SubmagmaWithInverses( <M>, <gens> )
#F                    . . . . . . .  submagma-with-inv. of <M> gen. by <gens>
##
InstallGlobalFunction( SubmagmaWithInverses, function(arg)
local M,gens,S;
    M:=arg[1];
    if not IsMagmaWithInverses( M ) then
        Error( "<M> must be a magma-with-inverses" );
    fi;
    if Length(arg)=1 then
      S:=Objectify(NewType( FamilyObj(M),
                            IsMagmaWithInverses
                            and IsAttributeStoringRep), rec() );
      SetParent(S,M);
      return S;
    else
      gens:=arg[2];
    fi;
    if IsEmpty( gens ) then
        return SubmagmaWithInversesNC( M, gens );
    elif not IsHomogeneousList(gens)  then
        Error( "<gens> must be a homogeneous list of elements" );
    elif not IsIdenticalObj( FamilyObj(M), FamilyObj(gens) )  then
        Error( "families of <gens> and <M> are different" );
    fi;
    if not ForAll( gens, x -> x in M ) then
        Error( "<gens> must be elements in <M>" );
    fi;
    return SubmagmaWithInversesNC( M, gens );
end );


#############################################################################
##
#F  SubmagmaWithInversesNC( <M>, <gens> )
##
##  Note that `SubmagmaWithInversesNC' is allowed to call `Objectify'
##  in the case that <gens> is empty.
##
InstallGlobalFunction( SubmagmaWithInversesNC, function( M, gens )
    local K, S;

    if IsEmpty( gens ) then
      K:= NewType( FamilyObj(M),
                       IsMagmaWithInverses
                   and IsTrivial
                   and IsAttributeStoringRep
                   and HasGeneratorsOfMagmaWithInverses);
      S:=rec();
      ObjectifyWithAttributes(S, K, GeneratorsOfMagmaWithInverses, [] );
    else
      S:= MagmaWithInversesByGenerators(gens);
    fi;
    SetParent( S, M );
    return S;
end );


#############################################################################
##
#M  MagmaByGenerators( <gens> ) . . . . . . . . . . . . . .  for a collection
##
InstallMethod( MagmaByGenerators,
    "for collection",
    true,
    [ IsCollection ] , 0,
    function( gens )
    local M;
    M:= Objectify( NewType( FamilyObj( gens ),
                            IsMagma and IsAttributeStoringRep ),
                   rec() );
    SetGeneratorsOfMagma( M, AsList( gens ) );
    return M;
    end );


#############################################################################
##
#M  MagmaByGenerators( <Fam>, <gens> )  . . . . . . . . . for family and list
##
InstallOtherMethod( MagmaByGenerators,
    "for family and list",
    true,
    [ IsFamily, IsList ], 0,
    function( family, gens )
    local M;
    if not ( IsEmpty(gens) or IsIdenticalObj( FamilyObj(gens), family ) ) then
      Error( "<family> and family of <gens> do not match" );
    fi;
    M:= Objectify( NewType( family,
                            IsMagma and IsAttributeStoringRep ),
                   rec() );
    SetGeneratorsOfMagma( M, AsList( gens ) );
    return M;
    end );


#############################################################################
##
#M  MagmaWithOneByGenerators( <gens> )  . . . . . . . . . .  for a collection
##
InstallMethod( MagmaWithOneByGenerators,
    "for collection",
    true,
    [ IsCollection ] , 0,
    function( gens )
    local M;
    M:= Objectify( NewType( FamilyObj( gens ),
                            IsMagmaWithOne and IsAttributeStoringRep ),
                   rec() );
    SetGeneratorsOfMagmaWithOne( M, AsList( gens ) );
    return M;
    end );


#############################################################################
##
#M  MagmaWithOneByGenerators( <Fam>, <gens> ) . . . . . . for family and list
##
InstallOtherMethod( MagmaWithOneByGenerators,
    "for family and list",
    true,
    [ IsFamily, IsList ], 0,
    function( family, gens )
    local M;
    if not ( IsEmpty(gens) or IsIdenticalObj( FamilyObj(gens), family ) ) then
      Error( "<family> and family of <gens> do not match" );
    fi;
    M:= Objectify( NewType( family,
                            IsMagmaWithOne and IsAttributeStoringRep ),
                   rec() );
    SetGeneratorsOfMagmaWithOne( M, AsList( gens ) );
    return M;
    end );


#############################################################################
##
#M  MagmaWithInversesByGenerators( <gens> ) . . . . . . . .  for a collection
##
BindGlobal( "MakeMagmaWithInversesByFiniteGenerators", function(family,gens)
local M;

  M:=MakeGroupyObj(family, IsMagmaWithInverses, gens, fail);

  if HasIsAssociative( M ) and IsAssociative( M ) then
    SetIsFinitelyGeneratedGroup( M, true );
  fi;
  return M;
end );

InstallMethod( MagmaWithInversesByGenerators, "for collection", true,
    [ IsCollection and IsFinite] , 0,
function( gens )
  return MakeMagmaWithInversesByFiniteGenerators(FamilyObj(gens),gens);
end);

#############################################################################
##
#M  MagmaWithInversesByGenerators( <Fam>, <gens> )  . . . for family and list
##
InstallOtherMethod( MagmaWithInversesByGenerators, "for family and list",
    true, [ IsFamily, IsList and IsFinite], 0,
function( family, gens )
  if not ( IsEmpty(gens) or IsIdenticalObj( FamilyObj(gens), family ) ) then
    Error( "<family> and family of <gens> do not match" );
  fi;
  return MakeMagmaWithInversesByFiniteGenerators(family,gens);
end );


#############################################################################
##
#M  TrivialSubmagmaWithOne( <M> ) . . . . . . . . . . .  for a magma-with-one
##
InstallMethod( TrivialSubmagmaWithOne,
    "for magma-with-one",
    true,
    [ IsMagmaWithOne ], 0,
    # use the `Parent' to avoid too many nonmaximal parents
    M -> SubmagmaWithOneNC( Parent(M), [] ) );


#############################################################################
##
#M  GeneratorsOfMagma( <M> )
##
##  If nothing special is known about the magma <M> we delegate to
##  `GeneratorsOfDomain'.
##
##  If <M> is in fact a magma-with-one or a magma-with-inverses with known
##  generators of one of these kinds then magma generators can be computed
##  from them.
##
##  Adding identity and inverses can be avoided if the elements in the magma
##  are known to have finite order;
##  this holds for example for permutation groups.
##
InstallMethod( GeneratorsOfMagma,
    "generic method for a magma (take domain generators)",
    true,
    [ IsMagma ], 0,
    GeneratorsOfDomain );

InstallMethod( GeneratorsOfMagma,
    "for a magma-with-one with known generators",
    true,
    [ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0,
function(M)
local c;
  c:=Concatenation( GeneratorsOfMagmaWithOne( M ), [ One(M) ] );
  if CanEasilySortElements(One(M)) then
    return Set(c);
  elif CanEasilyCompareElements(One(M)) then
    return Unique(c);
  fi;
  return c;
end);

InstallMethod( GeneratorsOfMagma,
    "for a magma-with-inverses with known generators",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0,
function(M)
local c;
  c:=Concatenation( GeneratorsOfMagmaWithInverses( M ),
              [ One( M ) ],
              List( GeneratorsOfMagmaWithInverses( M ), Inverse ) );
  if CanEasilySortElements(One(M)) then
    return Set(c);
  elif CanEasilyCompareElements(One(M)) then
    return Unique(c);
  fi;
  return c;
end);

InstallMethod( GeneratorsOfMagma,
    "for a magma-with-one with generators, all elms. of finite order",
    true,
    [ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne
      and IsFiniteOrderElementCollection ], 0,
    function( M )
    local gens;
    gens:= GeneratorsOfMagmaWithOne( M );
    if IsEmpty( gens ) then
      return [ One( M ) ];
    else
      return gens;
    fi;
    end );

InstallMethod( GeneratorsOfMagma,
    "for a magma-with-inv. with gens., all elms. of finite order",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses
      and IsFiniteOrderElementCollection ], 0,
    function( M )
    local gens;
    gens:= GeneratorsOfMagmaWithInverses( M );
    if IsEmpty( gens ) then
      return [ One( M ) ];
    else
      return gens;
    fi;
    end );


#############################################################################
##
#M  GeneratorsOfMagmaWithOne( <M> )
##
##  A known `GeneratorsOfMagma' value can be taken for
##  `GeneratorsOfMagmaWithOne'.
##
##  If <M> is in fact a magma-with-inverses with known
##  generators of this kind then magma-with-one generators can be computed
##  from them.
##
##  Adding inverses can be avoided if the elements in the magma
##  are known to have finite order;
##  this holds for example for permutation groups.
##
InstallMethod( GeneratorsOfMagmaWithOne,
    "for a magma-with-one with known magma generators (take them)",
    true,
    [ IsMagmaWithOne and HasGeneratorsOfMagma ], 0,
    GeneratorsOfMagma );

InstallMethod( GeneratorsOfMagmaWithOne,
    "for a magma-with-inverses with generators",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0,
function(M)
local c;
  c:=Concatenation( GeneratorsOfMagmaWithInverses( M ),
              List( GeneratorsOfMagmaWithInverses( M ), Inverse ) );
  if CanEasilySortElements(One(M)) then
    return Set(c);
  elif CanEasilyCompareElements(One(M)) then
    return Unique(c);
  fi;
  return c;
end);

InstallMethod( GeneratorsOfMagmaWithOne,
    "for a magma-with-inv. with gens., all elms. of finite order",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses
      and IsFiniteOrderElementCollection ], 0,
    GeneratorsOfMagmaWithInverses );


#############################################################################
##
#M  GeneratorsOfMagmaWithInverses( <M> )
##
##  A known `GeneratorsOfMagma' or `GeneratorsOfMagmaWithOne' value
##  can be taken for `GeneratorsOfMagmaWithInverses'.
##
InstallMethod( GeneratorsOfMagmaWithInverses,
    "for a magma-with-inverses with known magma generators (take them)",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagma ], 0,
    GeneratorsOfMagma );

InstallMethod( GeneratorsOfMagmaWithInverses,
    "for a magma-with-inverses with known magma-with-one gen.s (take them)",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithOne ], 0,
    GeneratorsOfMagmaWithOne );


#############################################################################
##
#M  Representative( <M> ) . . . . . . . . . . . . . .  one element of a magma
##
InstallMethod( Representative,
    "for magma with generators",
    true,
    [ IsMagma and HasGeneratorsOfMagma ], 0,
    RepresentativeFromGenerators( GeneratorsOfMagma ) );

InstallMethod( Representative,
    "for magma-with-one with generators",
    true,
    [ IsMagmaWithOne and HasGeneratorsOfMagmaWithOne ], 0,
    RepresentativeFromGenerators( GeneratorsOfMagmaWithOne ) );

InstallMethod( Representative,
    "for magma-with-inverses with generators",
    true,
    [ IsMagmaWithInverses and HasGeneratorsOfMagmaWithInverses ], 0,
    RepresentativeFromGenerators( GeneratorsOfMagmaWithInverses ) );

InstallMethod( Representative,
    "for magma-with-one with known one",
    true,
    [ IsMagmaWithOne and HasOne ], SUM_FLAGS,
    One );

InstallMethod( Representative,
    "for magma-with-one with stored parent",
    [ IsMagmaWithOne and HasParentAttr ],
    function( M )
    if not IsIdenticalObj( M, Parent( M ) ) then
      return One( Representative( Parent( M ) ) );
    fi;
    TryNextMethod();
    end );


#############################################################################
##
#M  MultiplicativeNeutralElement( <M> ) . . . . . . . . . . . . . for a magma
##
InstallMethod( MultiplicativeNeutralElement,
    "for a magma",
    true,
    [ IsMagma ], 0,
    function( M )
    local m;
    if IsFinite( M ) then
      for m in M do
        if ForAll( M, n -> n * m = n and m * n = n ) then
          return m;
        fi;
      od;
      return fail;
    else
      TryNextMethod();
    fi;
    end );


#############################################################################
##
##  HasMultiplicativeNeutralElement( <M> )
##
##  always true for a magma-with-one
##
InstallTrueMethod(HasMultiplicativeNeutralElement, IsMagmaWithOne);

#############################################################################
##
#M  MultiplicativeNeutralElement( <M> ) . . . . . . . .  for a magma-with-one
##
InstallMethod(MultiplicativeNeutralElement,
    "for a magma-with-one",
    true,
    [HasMultiplicativeNeutralElement and IsMagmaWithOne], GETTER_FLAGS+1,
    One );

InstallMethod(SetMultiplicativeNeutralElement,
    "for a magma-with-one",
    true,
    [IsMagma, IsBool], 0,
function(m, b)
    if b<>fail then
      TryNextMethod();
    fi;
end);


#############################################################################
##
#M  One( <M> )  . . . . . . . . . . . . . . . . . . . . . identity of a magma
##
InstallOtherMethod( One,
    "for a magma",
    true,
    [ IsMagma ], 0,
    function( M )
    local one;
    one:= One( Representative( M ) );
    if one <> fail and one in M then
      return one;
    else
      return fail;
    fi;
    end );

InstallOtherMethod( One,
    "partial method for a magma-with-one (ask family)",
    true,
    [ IsMagmaWithOne ], 100,
#T high priority?
    function( M )
    M:= ElementsFamily( FamilyObj( M ) );
    if HasOne( M ) then
      return One( M );
    else
      TryNextMethod();
    fi;
    end );

InstallOtherMethod( One,
    "for a magma-with-one that has a parent",
    true,
    [ IsMagmaWithOne and HasParent ], SUM_FLAGS,
    function( M )
    if not IsIdenticalObj( M, Parent( M ) ) then
      return One( Parent( M ) );
    fi;
    TryNextMethod();
    end );

InstallOtherMethod( One,
    "for a magma-with-one",
    true,
    [ IsMagmaWithOne ], 0,
    M -> One( Representative( M ) ) );


#############################################################################
##
#M  Enumerator( <M> ) . . . . . . . . .  enumerator of trivial magma with one
##
BindGlobal( "EnumeratorOfTrivialMagmaWithOne",
    M -> Immutable( [ One( M ) ] ) );

InstallMethod( Enumerator,
    "for trivial magma-with-one",
    true,
    [ IsMagmaWithOne and IsTrivial ], 0,
    EnumeratorOfTrivialMagmaWithOne );


#############################################################################
##
#F  ClosureMagmaDefault( <M>, <elm> ) . . . . . closure of magma with element
##
BindGlobal( "ClosureMagmaDefault", function( M, elm )

    local   C,          # closure of `M' with `obj', result
            gens,       # generators of `M'
            gen,        # generator of `M' or `C'
            Celements,  # intermediate list of elements
            len;        # current number of elements

    gens:= GeneratorsOfMagma( M );

    # try to avoid adding an element to a magma that already contains it
    if   elm in gens
      or ( HasAsSSortedList( M ) and elm in AsSSortedList( M ) )
    then
        return M;
    fi;

    # make the closure magma
    gens:= Concatenation( gens, [ elm ] );
    C:= MagmaByGenerators( gens );
    UseSubsetRelation( C, M );

    # if the elements of <M> are known then extend this list
    # (multiply each element from the left and right with the new
    # generator, and then multiply with all elements until the
    # list becomes stable)
    if HasAsSSortedList( M ) then

        Celements := ShallowCopy( AsSSortedList( M ) );
        AddSet( Celements, elm );
        UniteSet( Celements, Celements * elm );
        UniteSet( Celements, elm * Celements );
        repeat
            len:= Length( Celements );
            for gen in Celements do
                UniteSet( Celements, Celements * gen );
                UniteSet( Celements, gen * Celements );
            od;
        until len = Length( Celements );

        SetAsSSortedList( C, AsSSortedList( Celements ) );
        SetIsFinite( C, true );
        SetSize( C, Length( Celements ) );

    fi;

    # return the closure
    return C;
end );


#############################################################################
##
#M  Enumerator( <M> ) . . . . . . . . . . . .  set of the elements of a magma
##
BindGlobal( "EnumeratorOfMagma", function( M )

    local   gens,       # magma generators of <M>
            H,          # submagma of the first generators of <M>
            gen;        # generator of <M>

    # The following code only does not work infinite magmas.
    if HasIsFinite( M ) and not IsFinite( M ) then
      TryNextMethod();
    fi;

    # handle the case of an empty magma
    gens:= GeneratorsOfMagma( M );
    if IsEmpty( gens ) then
      return [];
    fi;

    # start with the empty magma and its element list
    H:= Submagma( M, [] );
    SetAsSSortedList( H, Immutable( [ ] ) );

    # Add the generators one after the other.
    # We use a function that maintains the elements list for the closure.
    for gen in gens do
      H:= ClosureMagmaDefault( H, gen );
    od;

    # return the list of elements
    Assert( 2, HasAsSSortedList( H ) );
    return AsSSortedList( H );
end );

InstallMethod( Enumerator,
    "generic method for a magma",
    true,
    [ IsMagma and IsAttributeStoringRep ], 0,
    EnumeratorOfMagma );


#############################################################################
##
#M  IsCentral( <M>, <N> )
##
InstallMethod( IsCentral,
    "for two magmas",
    IsIdenticalObj,
    [ IsMagma, IsMagma ], 0,
    IsCentralFromGenerators( GeneratorsOfMagma, GeneratorsOfMagma ) );

InstallMethod( IsCentral,
    "for two magmas-with-one",
    IsIdenticalObj,
    [ IsMagmaWithOne, IsMagmaWithOne ], 0,
    IsCentralFromGenerators( GeneratorsOfMagmaWithOne,
                             GeneratorsOfMagmaWithOne ) );

InstallMethod( IsCentral,
    "for two magmas-with-inverses",
    IsIdenticalObj,
    [ IsMagmaWithInverses, IsMagmaWithInverses ], 0,
    IsCentralFromGenerators( GeneratorsOfMagmaWithInverses,
                             GeneratorsOfMagmaWithInverses ) );

#############################################################################
##
#M  IsCentral( <M>, <elm> )
##
InstallMethod( IsCentral,
    "for a magma and an element",
    IsCollsElms,
    [ IsMagma, IsObject ], 0,
    IsCentralElementFromGenerators( GeneratorsOfMagma ) );

InstallMethod( IsCentral,
    "for a magma-with-one and an element",
    IsCollsElms,
    [ IsMagmaWithOne, IsObject ], 0,
    IsCentralElementFromGenerators( GeneratorsOfMagmaWithOne ) );

InstallMethod( IsCentral,
    "for a magma-with-inverses and an element",
    IsCollsElms,
    [ IsMagmaWithInverses, IsObject ], 0,
    IsCentralElementFromGenerators( GeneratorsOfMagmaWithInverses ) );


#############################################################################
##
#M  IsSubset( <M>, <N> )  . . . . . . . . . . . . . . . . . .  for two magmas
##
InstallMethod( IsSubset,
    "for two magmas",
    IsIdenticalObj,
    [ IsMagma, IsMagma ], 0,
    function( M, N )
    return IsSubset( M, GeneratorsOfMagma( N ) );
    end );


#############################################################################
##
#M  IsSubset( <M>, <N> )  . . . . . . . . . . . . . . for two magmas with one
##
InstallMethod( IsSubset,
    "for two magmas with one",
    IsIdenticalObj,
    [ IsMagmaWithOne, IsMagmaWithOne ], 0,
    function( M, N )
    return IsSubset( M, GeneratorsOfMagmaWithOne( N ) );
    end );


#############################################################################
##
#M  IsSubset( <M>, <N> )  . . . . . . . . . . .  for two magmas with inverses
##
InstallMethod( IsSubset,
    "for two magmas with inverses",
    IsIdenticalObj,
    [ IsMagmaWithInverses, IsMagmaWithInverses ], 0,
    function( M, N )
    return IsSubset( M, GeneratorsOfMagmaWithInverses( N ) );
    end );


#############################################################################
##
#M  AsMagma( <D> ) . . . . . . . . . . . . . .  domain <D>, regarded as magma
##
InstallMethod( AsMagma,
    "for a magma (return the argument)",
    true,
    [ IsMagma ], 100,
    IdFunc );

InstallMethod( AsMagma,
    "generic method for collections",
    true,
    [ IsCollection ], 0,
    function( D )
    local   M,  L;

    D := AsSSortedList( D );
    L := ShallowCopy( D );
    M := Submagma( MagmaByGenerators( D ), [] );
    SubtractSet( L, AsSSortedList( M ) );
    while not IsEmpty(L)  do
        M := ClosureMagmaDefault( M, L[1] );
        SubtractSet( L, AsSSortedList( M ) );
    od;
    if Length( AsSSortedList( M ) ) <> Length( D )  then
        return fail;
    fi;
    M := MagmaByGenerators( GeneratorsOfMagma( M ) );
    SetAsSSortedList( M, D );
    SetIsFinite( M, true );
    SetSize( M, Length( D ) );

    # return the magma
    return M;
    end );


#############################################################################
##
#M  AsSubmagma( <G>, <U> )
##
InstallMethod( AsSubmagma,
    "generic method for a domain and a collection",
    IsIdenticalObj,
    [ IsDomain, IsCollection ], 0,
    function( G, U )
    local S;
    if not IsSubset( G, U ) then
      return fail;
    fi;
    if IsMagma( U ) then
      S:= SubmagmaNC( G, GeneratorsOfMagma( U ) );
    else
      S:= SubmagmaNC( G, AsList( U ) );
    fi;
    UseIsomorphismRelation( U, S );
    UseSubsetRelation( U, S );
    return S;
    end );


#############################################################################
##
#M  IsEmpty( <M> )  . . . . . . . . . . . . . . test whether a magma is empty
##
InstallMethod(IsEmpty, "for a magma with generators of magma",
[IsMagma and HasGeneratorsOfMagma],
M -> IsEmpty(GeneratorsOfMagma(M)));

[ Verzeichnis aufwärts0.50unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


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