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


Quelle  mwo.gi   Sprache: unbekannt

 
############################################################################# 
## 
#W  mwo.gi                 GAP4 package `groupoids'             Chris Wensley 
##
##  This file contains the declarations of elements, magma, etc., and their 
##  families in the case of many objects.  So each algebraic structure comes 
##  with a set of objects, and each element $e$ has a tail object $te$ and a 
##  head object $he$, and multiplies partially if composable: on the left 
##  with those elements in its family which have head $te$, and on the right 
##  with those elements of its family which have tail $he$.  Non-composable 
##  elements return $fail$ when multiplied. 
##  

###########################  DOMAIN WITH OBJECTS  ########################### 

############################################################################# 
## 
#M  KindOfDomainWithObjects( <dwo> ) 
##
InstallMethod( KindOfDomainWithObjects, "for a list of domains with objects", 
    true, [ IsList ], 0, 
function( pieces ) 

    local kind; 

    ## kind:  1=gpd, 2=mon, 3=sgp, 4=mgm, 5=dom 
    kind := 0; 
    if ForAll( pieces, p -> ( FamilyObj(p) =  IsGroupoidFamily ) ) then 
        kind := 1; 
    elif ForAll( pieces, p -> ( ( FamilyObj(p) = IsMonoidWithObjectsFamily ) 
                             or ( FamilyObj(p) = IsGroupoidFamily ) ) ) then
        kind := 2; 
    elif ForAll( pieces, p -> ( ( FamilyObj(p) = IsSemigroupWithObjectsFamily ) 
                             or ( FamilyObj(p) = IsMonoidWithObjectsFamily ) 
                             or ( FamilyObj(p) = IsGroupoidFamily ) ) ) then 
        kind := 3; 
    elif ForAll( pieces, p -> 
        ( "IsMagmaWithObjects" in CategoriesOfObject(p) ) ) then 
        kind := 4; 
    elif ForAll( pieces, p -> 
        ( "IsDomainWithObjects" in CategoriesOfObject(p) ) ) then 
        kind := 5; 
    else 
        Info( InfoGroupoids, 2, "just an ordinary list?" ); 
    fi; 
    return kind; 
end );

#####################  MULT ELTS WITH OBJECTS  ############################## 

############################################################################# 
## 
#M  Arrow( <mwo>, <elt>, <tail>, <head> ) 
#M  ArrowNC( <mwo> <isgpdelt>, <elt>, <tail>, <head> ) 
##
InstallMethod( ArrowNC, 
    "for mwo, boolean, element, tail and head", true,  
    [ IsMagmaWithObjects, IsBool, IsMultiplicativeElement, IsObject, IsObject ],
    0, 
function( mwo, isge, e, t, h ) 

    local obs, elt, fam;

    Info( InfoGroupoids, 3, "standard method for ArrowNC" );
    if isge then 
        fam := IsGroupoidElementFamily; 
        elt := Objectify( IsGroupoidElementType, [ mwo, e, t, h ] );
    else 
        fam := IsMultiplicativeElementWithObjectsFamily; 
        elt := Objectify( IsMultiplicativeElementWithObjectsType,
                   [ mwo, e, t, h ] ); 
    fi; 
    return elt; 
end ); 

InstallMethod( Arrow, 
    "for general magma with objects, element, tail and head", true, 
    [ IsMagmaWithObjects, IsMultiplicativeElement, IsObject, IsObject ], 0, 
function( mwo, e, t, h ) 

    local piece, obs, fam, mag, pwo, pos, homset, pose; 

    if IsSinglePiece( mwo ) then 
        piece := mwo; 
    else 
        piece := PieceOfObject( mwo, t );
    fi;
    mag := piece!.magma; 
    if not ( e in mag ) then 
        Error( "<e> not in magma <mag>," ); 
    fi;
    obs := piece!.objects; 
    if not ( ( t in obs ) and ( h in obs ) ) then  
        Error( "<t> and <h> must be objects in <piece>," ); 
    fi;
    if not IsDirectProductWithCompleteDigraph( piece ) then 
        if not IsBound( piece!.table ) then 
            TryNextMethod(); 
        fi;
        pos := [ Position( obs, t ), Position( obs, h ) ]; 
        if not HasMultiplicationTable( mag ) then 
            Error( "expecting magma defined by multiplication table," ); 
        fi; 
        homset := piece!.table[pos[1]][pos[2]]; 
        pose := Position( GeneratorsOfMagma( mag ), e ); 
        if not ( pose in homset ) then 
            Error( "(e : t -> h) not an element in <piece>," ); 
        fi;   
    fi; 
    return ArrowNC( mwo, false, e, t, h ); 
end );

#############################################################################
## 
#M  ElementOfArrow
#M  TailOfArrow
#M  HeadOfArrow
#M  GroupoidOfArrow
##
InstallMethod( ElementOfArrow, "generic method for magma with objects element", 
    true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![2] ); 

InstallMethod( TailOfArrow, "generic method for magma with objects element", 
    true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![3] ); 

InstallMethod( HeadOfArrow, "generic method for magma with objects element", 
    true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![4] ); 

InstallMethod( GroupoidOfArrow, "generic method for magma with objects element", 
    true, [ IsMultiplicativeElementWithObjects ], 0, e -> e![1] ); 

#############################################################################
##
#M  String, ViewString, PrintString, ViewObj, PrintObj 
##  . . . . . . . . . . . . . . . . . . for elements in a magma with objects 
##
InstallMethod( String, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, 
function( e ) 
    return( STRINGIFY( "[", String( e![2] ), " : ", String( e![3] ), 
                       " -> ", String( e![4] ), "]" ) ); 
end );

InstallMethod( ViewString, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, String ); 

InstallMethod( PrintString, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, String ); 

InstallMethod( ViewObj, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, PrintObj ); 

InstallMethod( PrintObj, "for an element in a magma with objects",
    [ IsMultiplicativeElementWithObjects ],
function ( e )
    Print( "[", e![2], " : ", e![3], " -> ", e![4], "]" );
end );

InstallMethod( ViewObj, "for an element in a magma with objects",
    [ IsMultiplicativeElementWithObjects ], PrintObj );

#############################################################################
##
#M  \=( <e1>, <e2> ) . . . . . . equality of elements in a magma with objects
##
InstallMethod( \=, "for two multiplicative elements with objects", 
    IsIdenticalObj, [ IsMultiplicativeElementWithObjects, 
                      IsMultiplicativeElementWithObjects ], 0,
function( e1, e2 )
    return ForAll( [1..4], i -> ( e1![i] = e2![i] ) ); 
end );

#############################################################################
##
#M  \<( <e1>, <e2> ) . . . . . . equality of elements in a magma with objects
##
InstallMethod( \<, "for two multiplicative elements with objects", 
    IsIdenticalObj, [ IsMultiplicativeElementWithObjects, 
                      IsMultiplicativeElementWithObjects ], 0,
function( e1, e2 )
    if ( e1![1] <> e2![1] ) then
        Error( "e1, e2 belong to different mwos" );
    fi;
    if ( e1![3] < e2![3] ) then 
        return true; 
    elif ( (e1![3] = e2![3]) and (e1![4] < e2![4]) ) then 
        return true; 
    elif ( (e1![3] = e2![3]) and (e1![4] = e2![4]) and (e1![2] < e2![2]) ) then 
        return true; 
    else 
        return false; 
    fi;
end );

############################################################################# 
## 
#M  \*( e1, e2 ) . . . . . . composition of elements in a magma with objects 
## 
InstallMethod( \*, "for two elements in a magma with objects", IsIdenticalObj,
    [IsMultiplicativeElementWithObjects, IsMultiplicativeElementWithObjects], 
    0, 
function( e1, e2 ) 

    local prod; 

    if ( e1![1] <> e2![1] ) then
        Error( "e1, e2 belong to different mwos" );
    fi;
    ## elements are composable? 
    if ( e1![4] = e2![3] ) then 
        return ArrowNC( e1![1], false, e1![2]*e2![2], e1![3], e2![4] ); 
    else 
        return fail; 
    fi;  
end );

############################################################################# 
## 
#M  \^( e, p ) . . . . . . power (inverse) of element in a magma with objects 
## 
InstallMethod( \^, "for an element in a magma with objects and a PosInt", 
    true, [ IsMultiplicativeElementWithObjects, IsPosInt ], 0, 
function( e, p ) 
    ##  should be able to invert an identity element 
    ##  groupoids use their own method 
    if ( e![4] = e![3] ) then 
        return ArrowNC( e![1], false, e![2]^p, e![3], e![4] ); 
    else 
        return fail; 
    fi;  
end );

#############################################################################
##
#M  Order( <e> )  . . . . . . . . . . . . . . . . . . . . . of an mwo element
##
InstallOtherMethod( Order, "for a multiplicative element with objects", true,
    [ IsMultiplicativeElementWithObjects ], 0,
function( e ) 

    local ord;

    if not ( e![3] = e![4] ) then
        Error( "tail of e <> head of e," );
    fi;
    return Order( e![2] );
end );


################################  MAGMAS  ################################### 

############################################################################# 
## 
#F  MagmaWithObjects( <mag>, <obs> ) 
##
InstallGlobalFunction( MagmaWithObjects, function( arg ) 

    local obs, mag;

    # list of objects and a magma 
    if ( ( Length(arg) = 2 ) and IsMagma( arg[1] ) and IsSet( arg[2] ) ) then 
        mag := arg[1]; 
        obs := arg[2]; 
        if ( HasIsGeneratorsOfMagmaWithInverses( mag ) 
            and IsGeneratorsOfMagmaWithInverses( mag ) 
            and HasIsAssociative( mag ) and IsAssociative( mag ) ) then 
            Info( InfoGroupoids, 1, "SinglePieceGroupoid:-" );
            return SinglePieceGroupoid( mag, obs ); 
        elif ( HasIsMonoid( mag ) and IsMonoid( mag ) ) then 
            Info( InfoGroupoids, 1, "SinglePieceMonoidWithObjects:-" ); 
            return SinglePieceMonoidWithObjects( mag, obs ); 
        elif ( HasIsSemigroup( mag ) and IsSemigroup( mag ) ) then 
            Info( InfoGroupoids, 1, "SinglePieceSemigroupWithObjects:-" ); 
            return SinglePieceSemigroupWithObjects( mag, obs ); 
        else  ## it's just a magma 
            Info( InfoGroupoids, 1, "SinglePieceMagmaWithObjects:-" );
            return SinglePieceMagmaWithObjects( mag, obs ); 
        fi; 
    else 
        Error( "Current usage: MagmaWithObjects( <mag>, <obs> )," ); 
    fi; 
end ); 

############################################################################# 
## 
#M  SinglePieceMagmaWithObjects( <mag>, <obs> ) . . . . for magma and objects 
##
InstallMethod( SinglePieceMagmaWithObjects, 
    "for magma, objects", true, [ IsMagma, IsCollection ], 0, 
function( mag, obs ) 

    local cf, one, r, gens, mwo, fmwo, cmwo, isa, isc; 

    mwo := rec( objects := obs, magma := mag); 
    ObjectifyWithAttributes( mwo, IsMagmaWithObjectsType, 
        IsAssociative, IsAssociative( mag ), 
        IsCommutative, IsCommutative( mag ), 
        IsFinite, IsFinite( mag ), 
        IsSinglePieceDomain, true, 
        IsDirectProductWithCompleteDigraphDomain, true );
    gens := GeneratorsOfMagmaWithObjects( mwo );
    return mwo; 
end ); 

#############################################################################
##
#M  \=( <m1>, <m2> )  . . . . . . . test if two magmas with objects are equal
##
InstallMethod( \=, "for magmas with objects", IsIdenticalObj,
    [ IsMagmaWithObjects, IsMagmaWithObjects ], 0, 
function ( m1, m2 ) 

    local i, p1, p2;

    if ( IsSinglePiece(m1) and IsSinglePiece(m2) ) then 
        return ( ( m1!.objects=m2!.objects ) and ( m1!.magma=m2!.magma ) ); 
    elif ( IsSinglePiece(m1) or IsSinglePiece(m2) ) then 
        return false; 
    else 
        p1 := Pieces( m1 ); 
        p2 := Pieces( m2 ); 
        if not ( Length( p1 ) = Length( p2 ) ) then 
            return false; 
        else 
            for i in [1..Length( p1 )] do 
                if ( p1[i] <> p2[i] ) then 
                    return false; 
                fi; 
            od; 
            return true; 
        fi; 
    fi;
end );

#############################################################################
##
#M  \in( <elt>, <mwo> ) . . . . test if an element is in a magma with objects 
##

InstallMethod( \in, "for mwo element and a standard magma with objects", true, 
    [ IsMultiplicativeElementWithObjects, 
      IsMagmaWithObjects and IsSinglePiece ], 0,
function( e, mwo ) 
    return ( e![1] = mwo );
end ); 

InstallMethod( \in, "for mwo element and a union of pieces", true, 
    [ IsMultiplicativeElementWithObjects, IsMagmaWithObjects and HasPieces ], 0,
function( e, mwo )
    return e in PieceOfObject( mwo, e![3] ); 
end );

#############################################################################
##
#M  Size 
##
InstallOtherMethod( Size, "generic method for a magma with objects", true,
    [ IsMagmaWithObjects ], 0,
function( mwo )

    local p, s;

    if ( HasIsDirectProductWithCompleteDigraph( mwo ) and 
            IsDirectProductWithCompleteDigraph( mwo ) ) then 
        return Size( mwo!.magma ) * Length( mwo!.objects )^2; 
    elif ( HasIsDiscreteDomainWithObjects( mwo ) and 
              IsDiscreteDomainWithObjects( mwo ) ) then 
        return Size( mwo!.magma ) * Length( mwo!.objects ); 
    elif ( HasIsSinglePieceDomain( mwo ) and 
              IsSinglePieceDomain( mwo ) ) then 
        return Size( mwo!.magma ) * Length( mwo!.objects )^2;
Print("reached here\n");
    elif HasPieces( mwo ) then 
        s := 0; 
        for p in Pieces( mwo ) do 
            s := s + Size(p); 
        od;
        return s; 
    else 
        TryNextMethod();  
    fi;
end );

#############################################################################
##
#M  String, ViewString, PrintString, ViewObj, PrintObj 
##  . . . . . . . . . . . . . . . . . . . . . . . . for a magma with objects 
##
InstallMethod( String, "for a magma with objects", true, 
    [ IsMagmaWithObjects ], 0, 
function( mwo ) 

    local kind; 

    kind := KindOfDomainWithObjects( [ mwo ] ); 
    if ( kind = 1 ) then 
        return( STRINGIFY( "groupoid" ) ); 
    elif ( kind = 2 ) then 
        return( STRINGIFY( "monoid with objects" ) ); 
    elif ( kind = 3 ) then 
        return( STRINGIFY( "semigroup with objects" ) ); 
    elif ( kind = 4 ) then 
        return( STRINGIFY( "magma with objects" ) ); 
    else 
        return( STRINGIFY( "domain with objects" ) ); 
    fi; 
end );

InstallMethod( ViewString, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, String ); 

InstallMethod( PrintString, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, String ); 

InstallMethod( ViewObj, "for an element in a magma with objects", true, 
    [ IsMultiplicativeElementWithObjects ], 0, PrintObj ); 

InstallMethod( ViewObj, "for a single piece magma with objects", true, 
    [ IsSinglePiece ], 0,   
function( mwo )

    local kind; 

    kind := KindOfDomainWithObjects( [ mwo ] ); 
    if ( kind = 1 ) or ( kind = 5 ) then 
        Print( "#I  should be using special groupoid method!\n" ); 
    elif ( kind = 2 ) then 
        Print( "monoid with objects :-\n" ); 
    elif ( kind = 3 ) then 
        Print( "semigroup with objects :-\n" ); 
    elif ( kind = 4 ) then 
        Print( "magma with objects :-\n" ); 
    else 
        Print( "not yet implemented for general domains with objects\n" ); 
    fi; 
    Print( "    magma = ", mwo!.magma, "\n" ); 
    Print( "  objects = ", mwo!.objects, "\n" ); 
end );

InstallMethod( PrintObj, "for a single piece magma with objects", true, 
    [ IsSinglePiece ], 0, 
function( mwo )

    local kind; 

    kind := KindOfDomainWithObjects( [ mwo ] ); 
    if ( kind = 1 ) or ( kind = 5 ) then 
        Print( "#I  should be using special groupoid method!\n" ); 
    elif ( kind = 2 ) then 
        Print( "monoid with objects :-\n" ); 
    elif ( kind = 3 ) then 
        Print( "semigroup with objects :-\n" ); 
    elif ( kind = 4 ) then 
        Print( "magma with objects :-\n" ); 
    else 
        Print( "not yet implemented for general domains with objects\n" ); 
    fi; 
    Print( "    magma = ", mwo!.magma, "\n" ); 
    Print( "  objects = ", mwo!.objects, "\n" ); 
end );

InstallMethod( ViewObj, "for more than one piece", true, 
    [ IsDomainWithObjects and IsPiecesRep ], 10,   
function( dwo )

    local i, pieces, np, kind; 

    pieces := Pieces( dwo ); 
    np := Length( pieces ); 
    kind := KindOfDomainWithObjects( Pieces( dwo ) ); 
    if (kind=1) then Print( "groupoid" );  
      elif (kind=2) then Print( "monoid with objects" ); 
      elif (kind=3) then Print( "semigroup with objects" ); 
      elif (kind=4) then Print( "magma with objects" ); 
      elif (kind=5) then Print( "double groupoid" ); 
      elif (kind=0) then Error( "invalid domain with objects," ); 
    fi;
    Print( " having ", np, " pieces :-\n" ); 
    for i in [1..np] do 
        Print( i, ": ", pieces[i] ); 
        if HasName( pieces[i] ) then 
            Print( "\n" ); 
        fi; 
    od; 
end ); 

InstallMethod( PrintObj, "for more than one piece", true, 
    [ IsMagmaWithObjects and IsPiecesRep ], 0,   
function( mwo )

    local i, pieces, np; 

    pieces := Pieces( mwo ); 
    np := Length( pieces ); 
    Print( "domain with objects having ", np, " pieces :-\n" ); 
    for i in [1..np] do 
        Print( pieces[i] ); 
        if HasName( pieces[i] ) then 
            Print( "\n" ); 
        fi; 
    od; 
end ); 

##############################################################################
##
#M  Display( <mwo> ) . . . . . . . . . . . . . .  display a magma with objects
##
InstallMethod( Display, "for a mwo", true, [ IsMagmaWithObjects ], 0, 
function( mwo )
    
    local comp, c, i, m, len;

    if IsSinglePiece( mwo ) then 
        if IsDirectProductWithCompleteDigraph( mwo ) then 
            Print( "Single constituent magma with objects: " );
            if HasName( mwo ) then
                Print( mwo );
            fi;
            Print( "\n" ); 
            Print( "  objects: ", mwo!.objects, "\n" );
            m := mwo!.magma;
            Print( "    magma: " );
            if HasName( m ) then
                Print( m, " = <", GeneratorsOfMagma( m ), ">\n" );
            else
                Print( m, "\n" );
            fi;
        else
            TryNextMethod(); 
        fi; 
    else
        comp := Pieces( mwo );
        len := Length( comp );
        Print( "Magma with objects with ", len, " pieces:\n" );
        for i in [1..len] do
            c := comp[i];
            if IsDirectProductWithCompleteDigraph( c ) then 
                Print( "< objects: ", c!.objects, "\n" );
                m := c!.magma;
                Print( "    magma: " );
                if HasName( m ) then
                    Print( m, " = <", GeneratorsOfMagma( m ), "> >\n" );
                else
                    Print( m, " >\n" );
                fi;
            else 
                TryNextMethod(); 
            fi; 
        od;
    fi;
end );

#############################################################################
##
#M  RootObject( <mwo> )      for a connected or many-piece magma with objects
##
InstallMethod( RootObject, "for a single piece mwo", true, 
    [ IsSinglePiece ], 0,
function( mwo )
    return mwo!.objects[1]; 
end ); 

InstallOtherMethod( RootObject, "for a mwo with pieces", true, 
    [ IsDomainWithObjects and IsPiecesRep ], 0,
function( mwo )
    Print( "#I only a single piece magma with objects has a root object\n" ); 
    return fail; 
end ); 

#############################################################################
##
#M  GeneratorsOfMagmaWithObjects( <mwo> )  for a connected magma with objects 
#M  GeneratorsOfSemigroupWithObjects( <swo> )
#M  GeneratorsOfMonoidWithObjects( <mwo> )
##
InstallMethod( GeneratorsOfMagmaWithObjects, "for a single piece mwo", 
    true, [ IsSinglePiece ], 0,
function( mwo )

    local obs, nobs, o1, m, mgens, kind, gens, i, j, k, g; 

    obs := mwo!.objects;
    nobs := Length( obs );
    o1 := obs[1];
    m := mwo!.magma; 
    kind := 1; 
    if ( "IsGroupoid" in CategoriesOfObject( mwo ) ) then 
        return GeneratorsOfGroupoid( mwo ); 
    fi;
    if not ( HasIsDirectProductWithCompleteDigraph( mwo ) and 
                IsDirectProductWithCompleteDigraph( mwo ) ) then 
        Info( InfoGroupoids, 1, "expecting product with complete graph" ); 
        return fail; 
    fi;
    if ( "IsMonoidWithObjects" in CategoriesOfObject( mwo ) ) then 
        return GeneratorsOfMonoidWithObjects( mwo ); 
    fi; 
    if ( "IsSemigroupWithObjects" in CategoriesOfObject( mwo ) ) then 
        kind := 2; 
        mgens := GeneratorsOfSemigroup( m ); 
    else 
        mgens := GeneratorsOfMagma( m ); 
    fi; 
    gens := ListWithIdenticalEntries( nobs * nobs * Length(mgens), 0 ); 
    k := 0; 
    for i in obs do 
        for j in obs do 
            for g in mgens do
                k := k+1; 
                gens[k] := ArrowNC( mwo, false, g, i, j ); 
            od;
        od;
    od;
    if ( kind = 2 ) then 
        SetGeneratorsOfSemigroupWithObjects( mwo, gens ); 
    fi;
    return gens; 
end );

InstallMethod( GeneratorsOfMagmaWithObjects, "for discrete domain",
    true, [ IsGroupoid and IsSinglePiece and IsDiscreteDomainWithObjects ], 0,
function( mwo ) 

    local o, ogens, gens;  

    gens := [ ];
    for o in mwo!.objects do 
        ogens := GeneratorsOfGroup( ObjectGroup( mwo, o ) ); 
        Add( gens, List( ogens, g -> GroupoidElement( mwo, g, o, o ) ) ); 
    od; 
    return gens; 
end ); 

InstallMethod( GeneratorsOfMagmaWithObjects, "for mwo with >1 piece",
    true, [ IsMagmaWithObjects ], 0,
function( mwo ) 
    return Concatenation( List( Pieces( mwo ), 
               GeneratorsOfMagmaWithObjects ) ); 
end );

InstallMethod( GeneratorsOfSemigroupWithObjects, "for a semigroup with objects", 
    true, [ IsSemigroupWithObjects ], 0, GeneratorsOfMagmaWithObjects );

InstallMethod( GeneratorsOfMonoidWithObjects, "for a monoid with objects", 
    true, [ IsMonoidWithObjects and IsSinglePiece], 0, 
function( mwo )

    local obs, nobs, o1, m, mgens, id, gens1, gens2, gens, i, k;

    obs := mwo!.objects;
    nobs := Length( obs );
    o1 := obs[1];
    m := mwo!.magma; 
    mgens := GeneratorsOfMonoid( m ); 
    id := One( m ); 
    gens1 := List( mgens, g -> ArrowNC( mwo, false, g, o1, o1 ) );
    gens2 := ListWithIdenticalEntries( (nobs-1)^2, 0 ); 
    k := 0;
    for i in [2..nobs] do 
        gens2[k+1] := ArrowNC( mwo, false, id, o1, obs[i] ); 
        gens2[k+2] := ArrowNC( mwo, false, id, obs[i], o1 ); 
        k := k+2; 
    od;
    gens := Immutable( Concatenation( gens1, gens2 ) ); 
    SetGeneratorsOfMonoidWithObjects( mwo, gens ); 
    return gens; 
end );



#############################  MORE THAN ONE PIECE  ######################### 

#############################################################################
##
#M  Pieces . . . . . . . . . . connected components of a domain with objects 
##
InstallMethod( Pieces, "for a single piece domain with objects",
    true, [ IsSinglePieceDomain ], 0,
function( dwo )
    return [ dwo ];
end );

#############################################################################
##
#M  ObjectList . . . . . . . . . . . . . . . . . . . for a magma with objects
##
InstallMethod( ObjectList, "for a magma with objects",
    true, [ IsMagmaWithObjects ], 0,
function( mwo )

    local obs; 

    if ( HasIsSinglePiece( mwo ) and IsSinglePiece( mwo ) ) then
        return mwo!.objects;
    else
        obs := Concatenation( 
            List( Pieces( mwo ), c -> c!.objects ) );
        if not IsDuplicateFree( obs ) then
            Error( "same object in more than one constituent," );
        fi;
        Sort( obs );
        return obs;
    fi;
end );

#############################################################################
##
#M  UnionOfPieces . . . . . . . . for a list of connected magmas with objects
#M  UnionOfPiecesOp 
##
InstallGlobalFunction( UnionOfPieces, 
function( arg )

    local L, npa, part, pieces, p, nco, obs, obp, i, gi, nobj;

    if IsList( arg[1] ) then 
        L := arg[1]; 
    else 
        L := arg; 
    fi; 
    npa := Length( L );
    pieces := [ ]; 
    if ( Length( L ) = 1 ) then 
        return L[1]; 
    fi; 
    for part in L do 
        if not IsDomainWithObjects( part ) then
            Info( InfoGroupoids, 1, "part ", part, "not an mwo" );
            return fail;
        fi;
        if ( HasIsSinglePiece(part) and IsSinglePiece(part) ) then
            Add( pieces, part );
        else
            Append( pieces, Pieces( part ) );
        fi;
    od; 
    obs := [ ]; 
    for p in pieces do 
        obp := ObjectList( p );
        if ( Intersection( obs, obp ) <> [ ] ) then
            Info( InfoGroupoids, 1, 
                  "pieces must have disjoint object sets" );
            return fail;
        fi;
        obs := Union( obs, obp ); 
    od;
    return UnionOfPiecesOp( pieces, pieces[1] );
end );

InstallMethod( UnionOfPiecesOp, "method for magmas with objects",
    true, [ IsList, IsDomainWithObjects ], 0,
function( comps, dom )

    local kind, len, pieces, L, fam, filter, mwo, i, obs, par;

    ## determine which kind:  1=gpd, 2=mon, 3=sgp, 4=mgm, 5=dgpd, 6=dom 
    if ForAll( comps, c -> "IsGroupoid" in CategoriesOfObject( c ) ) then 
        kind := 1; 
    elif ForAll( comps,
                 c -> "IsDoubleGroupoid" in CategoriesOfObject( c ) ) then
        kind := 5;
    elif ForAll( comps, 
                 c -> "IsMonoidWithObjects" in CategoriesOfObject( c ) ) then 
        kind := 2; 
    elif ForAll( comps, 
                 c -> "IsSemigroupWithObjects" in CategoriesOfObject( c ) ) then 
        kind := 3; 
    elif ForAll( comps, 
                 c -> "IsMagmaWithObjects" in CategoriesOfObject( c ) ) then 
        kind := 4;
    else 
        Print( "kind not in {1,2,3,4,5} so TryNextMethod()\n" ); 
        TryNextMethod(); 
    fi;
    Info( InfoGroupoids, 2, "kind = ", kind ); 
    ## order pieces by first object
    len := Length( comps ); 
    obs := List( comps, g -> g!.objects[1] );
    L := [1..len];
    SortParallel( obs, L );
    if ( L = [1..len] ) then 
        pieces := comps; 
    else 
        Info( InfoGroupoids, 2, "reordering pieces by first object" ); 
        pieces := List( L, i -> comps[i] );
    fi;
    if ( kind = 1 ) then 
        fam := IsGroupoidFamily; 
        filter := IsPiecesRep and IsGroupoid and IsAssociative; 
        mwo := Objectify( IsGroupoidPiecesType, rec() );
    elif ( kind = 5 ) then 
        fam := IsDoubleGroupoidFamily; 
        filter := IsPiecesRep and IsDoubleGroupoid and IsAssociative; 
        mwo := Objectify( IsDoubleGroupoidPiecesType, rec() ); 
    elif ( kind = 2 ) then 
        fam := IsMonoidWithObjectsFamily; 
        filter := IsPiecesRep and IsMonoidWithObjects; 
        mwo := Objectify( IsMonoidWOPiecesType, rec() );
    elif ( kind = 3 ) then 
        fam := IsSemigroupWithObjectsFamily; 
        filter := IsPiecesRep and IsSemigroupWithObjects; 
        mwo := Objectify( IsSemigroupWOPiecesType, rec() );
    elif ( kind = 4 ) then 
        fam := IsMagmaWithObjectsFamily; 
        filter := IsPiecesRep and IsMagmaWithObjects; 
        mwo := Objectify( IsMagmaWOPiecesType, rec() ); 
    else 
        ## ?? (23/04/10) fam := FamilyObj( [ pieces ] ); 
        Error( "union of unstructured domains not yet implemented," ); 
    fi; 
    SetIsSinglePieceDomain( mwo, false ); 
    SetIsDirectProductWithCompleteDigraphDomain( mwo, false ); 
    SetPieces( mwo, pieces ); 
    if HasParent( pieces[1] ) then 
        par := Ancestor( pieces[1] ); 
        if ForAll( pieces, c -> ( Ancestor( c ) = par ) ) then 
            SetParent( mwo, par ); 
        fi; 
    fi; 
    if ( kind = 1 ) then 
        if ForAll( pieces, p -> HasIsPermGroupoid(p) and IsPermGroupoid(p) )
             then SetIsPermGroupoid( mwo, true ); 
        elif ForAll( pieces, p -> HasIsPcGroupoid(p) and IsPcGroupoid(p) )
             then SetIsPcGroupoid( mwo, true ); 
        elif ForAll( pieces, p -> HasIsFpGroupoid(p) and IsFpGroupoid(p) )
             then SetIsFpGroupoid( mwo, true ); 
        fi; 
    fi; 
    return mwo; 
end );

#############################################################################
##
#M  MagmaWithSingleObject
##
##  Note that there is another method for [ IsGroup, IsObject ] in gpd.gi 
##
InstallMethod( MagmaWithSingleObject, "generic method for magma, object",
    true, [ IsMagma, IsObject ], 0,
function( mgm, obj ) 

    local o; 

    if ( IsList( obj ) and ( Length(obj) = 1 ) ) then
        Info( InfoGroupoids, 2, "object given as a singleton list" );
        o := obj[1]; 
    else
        o := obj;
    fi; 
    if not IsObject( o ) then 
        Error( "<obj> not a scalar or singleton list," ); 
    fi; 
    if ( HasIsAssociative( mgm ) and IsAssociative( mgm ) 
         and ( "IsMagmaWithInverses" in CategoriesOfObject( mgm ) ) 
         and IsMagmaWithInverses( mgm ) ) then 
        return SinglePieceGroupoidNC( mgm, [o] ); 
    elif ( HasIsMonoid( mgm ) and IsMonoid( mgm ) ) then 
        return SinglePieceMonoidWithObjects( mgm, [o] ); 
    elif ( HasIsSemigroup( mgm ) and IsSemigroup( mgm ) ) then 
        return SinglePieceSemigroupWithObjects( mgm, [o] ); 
    elif ( ( "IsMagma" in CategoriesOfObject(mgm) ) and IsMagma(mgm) ) then 
        return SinglePieceMagmaWithObjects( mgm, [o] ); 
    else 
        Error( "unstructured domains with objects not yet implemented," ); 
    fi; 
end );

############################################################################# 
## 
#M  PieceOfObject
## 
InstallMethod( PieceOfObject, "generic method for magma with objects", 
    true, [ IsDomainWithObjects, IsObject ], 0,
function( dwo, obj )

    local pieces, p, objp;

    if IsSinglePiece( dwo ) then
        if not ( obj in dwo!.objects ) then
            Error( "<obj> not an object of <dwo>," );
        else
            return dwo;
        fi;
    elif not ( obj in ObjectList( dwo ) ) then
        Info( InfoGroupoids, 1, "<obj> not an object of <dwo>" );
        return fail;
    fi;
    pieces := Pieces( dwo );
    for p in pieces do
        objp := p!.objects;
        if ( obj in objp ) then
            return p;
        fi;
    od;
    Info( InfoGroupoids, 1, "it appears that <obj> is not an object in <dwo>" );
    return fail;
end );

############################################################################# 
## 
#M  PieceNrOfObject
## 
InstallMethod( PieceNrOfObject, "generic method for domain with objects",
    true, [ IsDomainWithObjects, IsObject ], 0,
function( dwo, obj )

    local pieces, i, objp, np; 

    pieces := Pieces( dwo );
    for i in [1..Length( pieces )] do
        objp := pieces[i]!.objects;
        if ( obj in objp ) then
            return i;
        fi;
    od;
    Info( InfoGroupoids, 1, "it appears that <obj> is not an object in <dwo>" );
    return fail;
end );

#############################################################################
##
#M  IsDiscreteDomainWithObjects 
##
InstallMethod( IsDiscreteDomainWithObjects, "for a magma with objects", true,
    [ IsDomainWithObjects ], 0,
function( dwo )

    local p; 

    for p in Pieces( dwo ) do
        if not ( Length( p!.objects ) = 1 ) then
            return false;
        fi;
    od;
    return true;
end );

#############################################################################
##
#M  IsHomogeneousDomainWithObjects 
##
InstallMethod( IsHomogeneousDomainWithObjects, "for a magma with objects", 
    true, [ IsDiscreteDomainWithObjects ], 0,
function( dwo )

    local pieces, g, j, iso; 

    pieces := Pieces( dwo ); 
    g := pieces[1]!.magma; 
    return ForAll( [2..Length(pieces)], j -> ( g = pieces[j]!.magma ) ); 
end );

InstallMethod( IsHomogeneousDomainWithObjects, "for a magma with objects", 
    true, [ IsDomainWithObjects ], 0,
function( dwo )

    local pieces, sizes, g, j, iso; 

    pieces := Pieces( dwo ); 
    sizes := Set( List( pieces, Size ) ); 
    if not ( Length( sizes ) = 1 ) then 
        return false; 
    fi;
    g := pieces[1]!.magma; 
    return ForAll( [2..Length(pieces)], j -> ( g = pieces[j]!.magma ) ); 
end );


#################################  SUBDOMAINS  ############################## 

#############################################################################
##
#F  IsSubdomainWithObjects( <M>, <U> )
##
InstallMethod( IsSubdomainWithObjects, "for two domains with objects", true, 
    [ IsDomainWithObjects, IsDomainWithObjects ], 0, 
function( D, U )

    local compU, obj, genU, p, ok; 

    ##  insisting that a subdomain of a groupoid is a groupoid 
    ok := false; 
    if not ( IsMagmaWithObjects(D) and IsMagmaWithObjects(U) ) then
        Error( "not yet implemented for unstructured domains," ); 
    fi;
    if ( HasParentAttr(U) and ( ParentAttr(U) = D ) ) then 
        return true;
    fi;
    if not IsSubset( ObjectList(D), ObjectList(U) ) then
        return false;
    fi; 
    if ( IsSinglePiece(D) and IsSinglePiece(U) ) then
        obj := U!.objects[1];
        if ( IsGroupoid(D) and IsGroupoid(U) ) then 
            genU := GeneratorsOfGroupoid(U); 
            ok := ForAll( genU, g -> g in D ); 
##      elif ( IsMonoid(D) and IsMonoid(U) ) then 
##          ok := ( IsSubsemigroup( D!.magma, U!.magma ) 
##                  and IsMonoid( D!.magma ) ); 
##      elif ( IsSemigroup(D) and IsSemigroup(U) ) then 
##          ok := IsSubsemigroup( D!.magma, U!.magma ); 
        else 
            ok := IsSubset( GeneratorsOfMagma( D!.magma ), 
                            GeneratorsOfMagma( U!.magma ) ); 
        fi;
    elif IsSinglePiece(U) then
        obj := U!.objects[1];
        p := PieceOfObject( D, obj ); 
        ok := IsSubdomainWithObjects( p, U );
    else
        compU := Pieces(U);
        ok := ForAll( compU, p -> IsSubdomainWithObjects( D, p ) );
    fi;
    if ( ok and not HasParentAttr( U ) ) then 
        SetParent( U, D ); 
    fi; 
    return ok; 
end );

#############################################################################
##
#F  SubdomainWithObjects( <M>, <U> )
##
InstallGlobalFunction( SubdomainWithObjects, function( arg ) 

    local nargs, dwo, isgpd; 

    nargs := Length( arg ); 
    dwo := arg[1]; 
    isgpd := ( "IsGroupoid" in CategoriesOfObject( dwo ) ); 
    if isgpd then 
        if ( nargs = 2 ) then 
            return Subgroupoid( arg[1], arg[2] ); 
        elif ( nargs = 3 ) then 
            return Subgroupoid( arg[1], arg[2], arg[3] ); 
        elif ( nargs = 4 ) then 
            return Subgroupoid( arg[1], arg[2], arg[3], arg[4] ); 
        else 
            Error( "expecting 2, 3 or 4 arguments" ); 
        fi;
    else 
        Error( "SubdomainWithObjects needs more implementation" ); 
    fi; 
end );


################################  SEMIGROUPS  ############################### 

############################################################################# 
## 
#F  SemigroupWithObjects( <sgp>, <obs> ) 
##
InstallGlobalFunction( SemigroupWithObjects, function( arg ) 

    local obs, sgp; 

    # list of objects and a semigroup 
    if ( (Length(arg) = 2) and IsSemigroup( arg[1] ) and IsSet( arg[2] ) ) then 
        sgp := arg[1]; 
        obs := arg[2]; 
        if HasGeneratorsOfMagmaWithInverses( sgp ) then  
            return SinglePieceGroupoid( sgp, obs ); 
        elif ( HasIsMonoid( sgp ) and IsMonoid( sgp ) ) then 
            return SinglePieceMonoidWithObjects( sgp, obs ); 
        else  ## it's just a semigroup
            return SinglePieceSemigroupWithObjects( sgp, obs ); 
        fi; 
    else 
        Error( "Current usage: SemigroupWithObjects( <sgp>, <obs> )," ); 
    fi; 
end ); 

############################################################################# 
## 
#M  SinglePieceSemigroupWithObjects( <sgp>, <obs> ) . for semigroup, objects
##
InstallMethod( SinglePieceSemigroupWithObjects, 
    "for objects, semigroup", true, [ IsSemigroup, IsCollection ], 0, 
function( sgp, obs ) 

    local gens, swo; 

    swo := rec( objects := obs, magma := sgp ); 
    ObjectifyWithAttributes( swo, IsSemigroupWithObjectsType, 
        IsAssociative, IsAssociative( sgp ), 
        IsCommutative, IsCommutative( sgp ), 
        IsFinite, IsFinite( sgp ), 
        IsSinglePieceDomain, true, 
        IsDirectProductWithCompleteDigraphDomain, true ); 
    gens := GeneratorsOfSemigroupWithObjects( swo ); 
    return swo; 
end ); 


##################################  MONOIDS  ################################ 

############################################################################# 
## 
#F  MonoidWithObjects( <mon>, <obs> ) 
##
InstallGlobalFunction( MonoidWithObjects, function( arg ) 

    local obs, mon; 

    # list of objects and a monoid 
    if ( ( Length(arg) = 2 ) and IsMonoid( arg[1] )  and IsSet( arg[2] ) ) then 
        mon := arg[1]; 
        obs := arg[2]; 
        if HasGeneratorsOfMagmaWithInverses( mon ) then  
            return SinglePieceGroupoid( mon, obs ); 
        else  ## it's just a monoid
            return SinglePieceMonoidWithObjects( mon, obs ); 
        fi; 
    else 
        Error( "Current usage: MonoidWithObjects( <mon>, <obs> )," ); 
    fi; 
end ); 

############################################################################# 
## 
#M  SinglePieceMonoidWithObjects( <mon>, <sgp> ) . . . for semigroup, objects 
##
InstallMethod( SinglePieceMonoidWithObjects, 
    "for objects, monoid", true, [ IsMonoid, IsCollection ], 0, 
function( mon, obs ) 

    local gens, mwo; 

    mwo := rec( objects := obs, magma := mon ); 
    ObjectifyWithAttributes( mwo, IsMonoidWithObjectsType, 
        IsAssociative, IsAssociative( mon ), 
        IsCommutative, IsCommutative( mon ), 
        IsSinglePieceDomain, true, 
        IsDirectProductWithCompleteDigraphDomain, true, 
        IsFinite, HasIsFinite( mon ) and IsFinite( mon ) );
    gens := GeneratorsOfMonoidWithObjects( mwo ); 
    return mwo; 
end ); 


##################################  GROUPS  ################################# 
##  A *group with objects* is a magma with objects where the vertex magmas 
##  are groups, and so is a *groupoid* - see file gpd.gi.


#################################  SUBMAGMAS  ############################### 

############################################################################# 
## 
#M  IsSubmagmaWithObjectsGeneratingTable( <mag>, <A> ) 
##
InstallMethod( IsSubmagmaWithObjectsGeneratingTable, "for magma and array", 
    true, [ IsMagma, IsList ], 0, 
function( mag, A ) 

    local n, s, a, b, e;

    n := Length( A );    ## number of objects 
    s := Size( mag );  
    e := [1..s]; 
    for a in A do 
        if not ( IsList(a) and ( Length(a) = n ) ) then 
            return false; 
        fi; 
        for b in a do 
            if not IsSubset( e, b ) then 
                return false; 
            fi; 
        od; 
    od; 
    return true; 
end ); 

############################################################################# 
## 
#M  SubmagmaWithObjectsElementsTable( <mag>, <A> ) 
##
InstallMethod( SubmagmaWithObjectsElementsTable, "for magma and array", 
    true, [ IsMagma, IsList ], 0, 
function( mag, A ) 

    local t, done, B, C, T, n, s, i, j, k, Lij, Lik, Ljk, a, b, ab; 

    if not IsSubmagmaWithObjectsGeneratingTable( mag, A ) then 
        Error( "array A is not a generating table for a submagma over mag," ); 
    fi; 
    T := MultiplicationTable( mag ); 
    s := Size( mag ); 
    n := Length( A ); 
    done := false; 
    C := StructuralCopy( A ); 
    t := 0; 
    while not done do 
        t := t+1; 
        B := StructuralCopy( C );   ## C stores all the elements 
        for i in [1..n] do 
            for j in [1..n] do 
                Lij := C[i][j]; 
                for k in [1..n] do 
                    Ljk := C[j][k]; 
                    for a in Lij do 
                        for b in Ljk do 
                            ab := T[a][b]; 
                            C[i][k] := Union( C[i][k], [ab] ); 
                        od; 
                    od; 
                od; 
            od; 
        od; 
        done := ( B = C ); 
    od;
    return C;        
end ); 

############################################################################# 
## 
#M  SubmagmaWithObjectsByElementsTable( <mwo>, <A> ) . . for mwo and elements 
##
InstallMethod( SubmagmaWithObjectsByElementsTable, 
    "for objects, magma and table of generating elements", true, 
    [ IsSinglePiece, IsList ], 0, 
function( mwo, A ) 

    local C, mag, obs, cf, isa, isc, swo; 

    obs := mwo!.objects; 
    mag := mwo!.magma; 
    C := SubmagmaWithObjectsElementsTable( mag, A ); 
    ## ?? (23/04/10)  cf := mwo!.eltsfam; 
    cf := IsMagmaWithObjectsFamily; 
    isa := IsAssociative( mag ); 
    isc := IsCommutative( mag ); 
    swo := rec( objects := obs, magma := mag, table := C ); 
    ObjectifyWithAttributes( swo, 
        NewType( cf, IsSubmagmaWithObjectsTableRep ), 
        ParentAttr, mwo,
        IsAssociative, IsAssociative( mag ), 
        IsCommutative, IsCommutative( mag ), 
        IsFinite, IsFinite( mag ), 
        IsSinglePieceDomain, true ); 
    #? (13/10/08)  still need to set GeneratorsOfMagmaWithObjects ?? 
    return swo; 
end ); 

############################################################################# 
## 
#M  PrintObj( <swo> ) . . . . .  for submagma with objects and elements table
##

InstallMethod( PrintObj, "for a submagma with objects and elements table", 
    true, [ IsSubmagmaWithObjectsTableRep ], 0, 
function( M ) 
    Print( "submagma with objects:-\n" ); 
    Print( "objects = ", M!.objects, "\n" );
    Print( "  magma = ", M!.magma, "\n" );  
    Print( "  table = ", M!.table, "\n" ); 
end );


#################################  UTILITIES  ############################### 

############################################################################# 
## 
#M  Ancestor 
## 
InstallMethod( Ancestor, "method for a domain with objects", 
    true, [ IsDomainWithObjects ], 0,
function( dom ) 

    local found, d; 

    d := dom; 
    found := ( HasParent( d ) and ( Parent( d ) = d ) ); 
    while not found do 
        if not HasParent( d ) then 
            return fail; 
        else
            d := Parent( d ); 
            found := ( Parent( d ) = d ); 
        fi; 
    od; 
    return d; 
end );


#############################################################################
##
#M  Iterator( <mwo> ) . . . .  iterator for a single piece magma with objects
##
InstallMethod( Iterator, "for a single piece magma with objects", 
    [ IsSinglePiece ], 
function( mwo )
    return IteratorByFunctions( rec( 
        IsDoneIterator := function( iter )
            return ( IsDoneIterator( iter!.magmaIterator ) 
                     and ( iter!.tpos = iter!.len )
                     and ( iter!.hpos = iter!.len ) );
            end, 
        NextIterator := function( iter )
            if ( iter!.tpos = 0 ) then
                iter!.melt := NextIterator( iter!.magmaIterator );
                iter!.tpos := 1;
                iter!.hpos := 1;
            elif ((iter!.tpos = iter!.len) and (iter!.hpos = iter!.len)) then 
                iter!.melt := NextIterator( iter!.magmaIterator );
                iter!.tpos := 1;
                iter!.hpos := 1;
            elif ( iter!.hpos = iter!.len ) then
                iter!.hpos := 1;
                iter!.tpos := iter!.tpos + 1;
            else 
                iter!.hpos := iter!.hpos + 1;
            fi;
            if ( HasIsDirectProductWithCompleteDigraph( mwo ) 
                 and IsDirectProductWithCompleteDigraph( mwo ) ) then 
               return Arrow( mwo, iter!.melt, 
                   iter!.obs[iter!.tpos], iter!.obs[iter!.hpos] );
            else 
               return fail;
            fi; 
            end, 
        ShallowCopy := iter -> 
            rec( magmaIterator := ShallowCopy( iter!.magmaIterator ), 
                 melt := iter!.melt,
                 obs := iter!.obs,
                 len := iter!.len,
                 tpos := iter!.tpos,
                 hpos := iter!.hpos ),
        magmaIterator := Iterator( mwo!.magma ), 
        melt := 0, 
        obs := mwo!.objects,
        len := Length( mwo!.objects ),
        tpos := 0,
        hpos := 0 ) );
end );

InstallMethod( Iterator, "generic method for a magma with objects", 
    [ IsMagmaWithObjects ], 
function( mwo )
    return IteratorByFunctions( rec( 
        IsDoneIterator := function( iter )
            return ( IsDoneIterator( iter!.mwoIterator ) 
                     and ( iter!.cpos = iter!.len ) );
            end, 
        NextIterator := function( iter )
            if IsDoneIterator( iter!.mwoIterator ) then 
                iter!.cpos := iter!.cpos + 1;
                iter!.mwoIterator := 
                    Iterator( iter!.pieces[iter!.cpos] );
            fi;
            return NextIterator( iter!.mwoIterator );
            end,
        ShallowCopy := iter -> 
            rec( pieces := iter!.pieces,
                 len := iter!.len,
                 mwoIterator := ShallowCopy( iter!.mwoIterator ),
                 cpos := iter!.cpos ),
        pieces := Pieces( mwo ),
        len := Length( Pieces( mwo ) ),
        mwoIterator := Iterator( Pieces( mwo )[1] ),
        cpos := 1 ) );
end );

#############################################################################
##
#E  mwo.gi  . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
##  

[ Dauer der Verarbeitung: 0.56 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