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

Quelle  poset.gi   Sprache: unbekannt

 
Spracherkennung für: .gi vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

#############################################################################
##
#W  poset.gi                   XGAP library                  Max Neunhoeffer
##
##
#Y  Copyright 1998,       Max Neunhoeffer,              Aachen,       Germany
##
##  This file contains the implementations for graphs and posets
##


#############################################################################
##
##  Declarations of representations:
##
#############################################################################


#############################################################################
##
#R  IsGraphicGraphRep . . . . . . . . . . . . . . .  representation for graph
##
if not IsBound(IsGraphicGraphRep) then
  DeclareRepresentation( "IsGraphicGraphRep",
    IsComponentObjectRep and IsAttributeStoringRep and IsGraphicSheet and
    IsGraphicSheetRep,
# we inherit those components from the sheet:        
    [ "name", "width", "height", "gapMenu", "callbackName", "callbackFunc",
      "menus", "objects", "free",
# now our own components:
      "vertices","edges","selectedvertices","menutypes",
      "menuenabled","rightclickfunction","color"],
    IsGraphicSheet );
fi;



#############################################################################
##
#R  IsGraphicPosetRep . . . . . . . . . . . . . . .  representation for poset
##
if not IsBound(IsGraphicPosetRep) then
  DeclareRepresentation( "IsGraphicPosetRep",
        IsComponentObjectRep and IsAttributeStoringRep and 
        IsGraphicSheet and IsGraphicSheetRep and IsGraphicGraphRep,
# we inherit those components from the sheet:        
    [ "name", "width", "height", "gapMenu", "callbackName", "callbackFunc",
      "menus", "objects", "free",
# now our own components:
      "levels",           # list of levels, stores current total ordering
      "levelparams",      # list of level parameters
      "selectedvertices", # list of selected vertices
      "menutypes",        # one entry per menu which contains list of types
      "menuenabled",      # one entry per menu which contains list of flags
      "rightclickfunction",    # the current function which is called when
                               # user clicks right button
      "color",            # some color infos for the case of different models
      "levelboxes",       # little graphic boxes for the user to handle levels
      "showlevelparams",  # flag, if level parameters are shown
      "showlevels"],      # flag, if levelboxes are shown
    IsGraphicSheet );
fi;


#############################################################################
##
#R  IsGPLevel . . . . . . . . . . . . . . . . . . .  representation for level
##
if not IsBound(IsGPLevel) then
  DeclareRepresentation( "IsGPLevel",
        IsComponentObjectRep,
        [ "top",          # y coordinate of top of level, relative to sheet
          "height",       # height in pixels
          "classes",      # list of classes, which are lists of vertices
          "classparams",  # list of class parameters
          "poset"         # poset to which level belongs
        ],
        IsGraphicObject );
fi;

#############################################################################
##
#R  IsGGVertex . . . . . . . . . . . . . . . . . .  representation for vertex
##
if not IsBound(IsGGVertex) then
  DeclareRepresentation( "IsGGVertex",
        IsComponentObjectRep and IsGraphicObject,
        [ "data",         # the mathematical data
          "obj",          # real graphic object
          "x","y",        # coordinates of graphic object within sheet
          "serial",       # a serial number for comparison
          "label"         # the label of the vertex or false
        ],
        IsGraphicObject );
fi;


#############################################################################
##
#R  IsGPVertex . . . . . . . . . . . . . . . . . .  representation for vertex
##
if not IsBound(IsGPVertex) then
  DeclareRepresentation( "IsGPVertex",
        IsComponentObjectRep and IsGraphicObject,
        [ "data",         # the mathematical data
          "obj",          # real graphic object
          "levelparam",   # level parameter
          "classparam",   # class parameter
          "maximals",     # list of vertices which are maximal subobjects
          "maximalin",    # list of vertices where this one is maximal in
          "x","y",        # coordinates of graphic object within level
          "serial",       # a serial number for comparison
          "label"         # the label of the vertex or false
        ],
        IsGraphicObject );
fi;


#############################################################################
##
##  Some global things we all need:
##
#############################################################################


##  We count all vertices:
PosetLastUsedSerialNumber := 0;


##  The following function is installed as a LeftPBDown in every graph or
##  poset. It calls the operation PosetLeftClick.

PosetLeftClickCallback := function(poset,x,y)
  PosetLeftClick(poset,x,y);
end;
  
##  The following function is installed as a RightPBDown in every graph or
##  poset. It calls the operation PosetRightClick.

PosetRightClickCallback := function(poset,x,y)
  PosetRightClick(poset,x,y);
end;
  
##  The following function is installed as a CtrlLeftPBDown and 
##  ShiftLeftPBDown in every graph or poset. It calls the operation 
##  PosetCtrlLeftClick.

PosetCtrlLeftClickCallback := function(poset,x,y)
  PosetCtrlLeftClick(poset,x,y);
end;
    

##  The following is a for a menu entry and just calls another method:
PosetDoRedraw := function(poset,menu,entry)
  DoRedraw(poset);
end;


##  Our menu which goes in all poset sheets:
PosetMenuEntries :=
  ["Redraw","Show Levels","Show Level Parameters",,
   "Delete Vertices","Delete Edge","Merge Classes",,
   "Magnify Lattice", "Shrink Lattice", "Resize Lattice", "Resize Sheet",
   "Move Lattice",,
   "Change Labels","Average Y Positions","Average X Positions",
   "Rearrange Classes"];
PosetMenuTypes :=
  ["forany","forany","forany",,
   "forsubset","foredge","forsubset",,
   "forany","forany","forany","forany","forany",,
   "forsubset","forany","forsubset","forsubset"];
PosetMenuFunctions :=
  [ PosetDoRedraw,PosetShowLevels,PosetShowLevelparams,,
    UserDeleteVerticesOp, UserDeleteEdgeOp, UserMergeClassesOp,,
    UserMagnifyLattice,UserShrinkLattice,UserResizeLattice,UserResizeSheet,
    UserMoveLattice,,
    UserChangeLabels,UserAverageY,UserAverageX,UserRearrangeClasses];


#############################################################################
##
##  Constructors:
##
#############################################################################


## we need this to set up the colors in a sheet:

BindGlobal( "GPMakeColors",
        function( sheet )
  
  # set up color information:
  if sheet!.color.model = "color"  then
    if COLORS.red <> false  then
      sheet!.color.unselected := COLORS.black;
      sheet!.color.selected   := COLORS.red;
    else
      sheet!.color.unselected := COLORS.dimGray;
      sheet!.color.selected   := COLORS.black;
    fi;
    if COLORS.green <> false  then
      sheet!.color.result := COLORS.green;
    else
      sheet!.color.result := COLORS.black; # COLORS.lightGray;
    fi;
  else
    sheet!.color.selected   := COLORS.black;
    sheet!.color.unselected := COLORS.black;
    sheet!.color.result     := false;
  fi;
end);

  
#############################################################################
##
#M  GraphicGraph( <name>, <width>, <height> ) . . . . . . a new graphic graph
##
##  creates a new graphic graph which is a graphic sheet representation
##  with knowledge about vertices and edges and infrastructure for user
##  interfaces.
##
InstallMethod( GraphicGraph,
    "for a string, and two integers",
    true,
    [ IsString,
      IsInt,
      IsInt ],
    0,

function( name, width, height )
  #local ...;
  
end);


#############################################################################
##
#M  GraphicPoset( <name>, <width>, <height> ) . . . . . . a new graphic poset
##
##  creates a new graphic poset which is a specialization of a graphic graph
##  mainly because per definition a poset comes in "layers" or "levels". This
##  leads to some algorithms that are more efficient than the general ones
##  for graphs.
##
InstallMethod( GraphicPoset,
    "for a string, and two integers",
    true,
    [ IsString,
      IsInt,
      IsInt ],
    0,

function( name, width, height )
  local   poset,  tmpEntries,  tmpTypes,  tmpFuncs,  m;
  
  poset := GraphicSheet(name,width,height);
  SetFilterObj(poset,IsGraphicGraphRep);
  SetFilterObj(poset,IsGraphicPosetRep);
  poset!.levels := [];
  poset!.levelparams := [];
  poset!.selectedvertices := [];
  # think of the GAP menu:
  poset!.menutypes := [List(poset!.menus[1]!.entries,x->"forany")];
  poset!.menuenabled := [List(poset!.menus[1]!.entries,x->true)];
  poset!.rightclickfunction := Ignore;
  
  # set up color information:
  poset!.color := rec();
  if COLORS.red <> false or COLORS.lightGray <> false  then
    poset!.color.model := "color";
    # note: if you rename this, think of the "use black&white" below!  
  else
    poset!.color.model := "monochrome";
  fi;
  GPMakeColors(poset);
  
  poset!.levelboxes := [];
  poset!.showlevels := false;
  poset!.lptexts := [];
  poset!.showlevelparams := true;
  
  InstallCallback(poset,"LeftPBDown",PosetLeftClickCallback);
  InstallCallback(poset,"ShiftLeftPBDown",PosetCtrlLeftClickCallback);
  InstallCallback(poset,"CtrlLeftPBDown",PosetCtrlLeftClickCallback);
  InstallCallback(poset,"RightPBDown",PosetRightClickCallback);
  
  tmpEntries := ShallowCopy(PosetMenuEntries);
  tmpTypes := ShallowCopy(PosetMenuTypes);
  tmpFuncs := ShallowCopy(PosetMenuFunctions);
  if poset!.color.model = "color" then
    Append(tmpEntries,["-","Use Black&White"]);
    Append(tmpTypes,["-","forany"]);
    Append(tmpFuncs,["-",UserUseBlackWhite]);
  fi;
  m := Menu(poset,"Poset",tmpEntries,tmpTypes,tmpFuncs);
  Check(m,"Show Level Parameters",true);
  
  return poset;
end);


#############################################################################
##
#M  CreateLevel(<poset>, <levelparam>) . . . . . . creates new level in poset
#M  CreateLevel(<poset>, <levelparam>, <lptext>) . creates new level in poset
##
##  A level in a graphic poset can be thought of as a horizontal slice of
##  the poset. It has a y coordinate of the top of the level relatively to
##  the graphic sheet and a height. Every class of vertices in a graphic
##  poset is in a level. The levels are totally ordered by their y
##  coordinate. No two vertices which are included in each other are in the
##  same level. A vertex containing another one is always "higher" on the
##  screen, meaning in a "higher" level.  Every level has a unique
##  levelparam, which can be any {\GAP} object. The user is responsible for
##  all methods where a levelparam occurs as parameter and is not just an
##  integer. There is NO {\GAP} object representing a level which is visible
##  for the user of posets. All communication about levels goes via the
##  levelparam.  Returns fail if there is already a level with a level
##  parameter which is considered "equal" by CompareLevels or levelparam if
##  everything went well.
##  The second method allows to specify which text appears for the level at
##  the right edge of the sheet.
##
InstallMethod( CreateLevel,
    "for a graphic poset, a level parameter, and a string",
    true,
    [ IsGraphicPosetRep, IsObject, IsString ],
    0,

function( poset, levelparam, lpstr )
  local   level,  box,  str,  strlen,  text,  l,  firstpos,  before,  look,  
          compare,  i,  cl,  v;
      
  # does this level parameter exist already?
  if Position(poset!.levelparams,levelparam) <> fail then
    return fail;
  fi;
  
  # create a level object:
  level := rec(classes := [],
               classparams := [],
               poset := poset);
  Objectify(NewType(GraphicObjectFamily,IsGPLevel),level);
  
  # is it the first level:
  if poset!.levelparams = [] then
    poset!.levelparams := [levelparam];
    poset!.levels := [level];
    level!.top := 0;
    level!.height := 2 * VERTEX.diameter;
    
    # make a level box:
    box := Box(poset,0,level!.top+level!.height-8,8,8);
    if COLORS.blue <> false then
      Recolor(box,COLORS.blue);
    fi;
    if not poset!.showlevels then
      Destroy(box);
    fi;
    
    poset!.levelboxes := [ box ];
    
    # make a text for level parameter:
    if lpstr <> "" then
      str := lpstr;
    else
      str := String(levelparam);
    fi;
    strlen := Length(str);
    text := Text(poset,FONTS.normal,
                 poset!.width - 24 - strlen*FontInfo(FONTS.normal)[3],
                 level!.top + QuoInt(level!.height,2),str);
    if COLORS.blue <> false then
      Recolor(text,COLORS.blue);
    fi;
    if not poset!.showlevelparams then
      Destroy(text);
    fi;
    
    poset!.lptexts := [ text ];
    
    return levelparam;
  fi;
  
  # now find the position, we choose the last position where the new level
  # can be according to the partial order defined by CompareLevels we do a
  # binary search, we insert not before "firstpos" and before "before".
  # Attention: We cannot decide at a level which is not comparable to the
  # new level, so we have to search linearly for a comparable level!
  l := Length(poset!.levelparams);
  firstpos := 1;
  before := l + 1;
  while firstpos < before do
    look := QuoInt(firstpos + before,2);
    repeat  # search first backward up to firstpos, then down
      compare := CompareLevels(poset,levelparam,poset!.levelparams[look]);
      if compare = 0 then 
        return fail;
      elif compare = fail then   # not comparable
        look := look-1;
      fi;
    until compare <> fail or look < firstpos;
    if compare = fail then
      # search now forward down to before
      look := QuoInt(firstpos + before,2)+1;
      if look = before then
        firstpos := before;   # we insert right HERE!
        compare := 0;
      fi;
      while compare = fail do
        compare := CompareLevels(poset,levelparam,poset!.levelparams[look]);
        if compare = 0 then 
          return fail;
        elif compare = fail then     # not comparable
          look := look+1;
          if look = before then     # nothing comparable in between!
            firstpos := before;     # we insert right HERE!
            compare := 0;           # this does exactly that!
          fi;
        fi;
      od;
    fi;
    if compare < 0 then
      before := look;
    elif compare > 0 then
      firstpos := look+1;
    fi;
  od;
  
  # we now insert at position firstpos = before:
  poset!.levelparams{[firstpos+1..l+1]} := poset!.levelparams{[firstpos..l]};
  poset!.levelparams[firstpos] := levelparam;
  poset!.levels{[firstpos+1..l+1]} := poset!.levels{[firstpos..l]};
  poset!.levels[firstpos] := level;
  poset!.levelboxes{[firstpos+1..l+1]} := poset!.levelboxes{[firstpos..l]};
  poset!.lptexts{[firstpos+1..l+1]} := poset!.lptexts{[firstpos..l]};
  
  if firstpos = 1 then
    level!.top := 0;
  else
    level!.top := poset!.levels[firstpos-1]!.top +
                  poset!.levels[firstpos-1]!.height;
  fi;
  level!.height := 2 * VERTEX.diameter;
  
  # move all lower levels down:
  FastUpdate(poset,true);
  for i in [firstpos+1..l+1] do
    poset!.levels[i]!.top := poset!.levels[i]!.top + level!.height;
    for cl in poset!.levels[i]!.classes do
      for v in cl do
        MoveDelta(v!.obj,0,level!.height);
      od;
    od;
    if poset!.showlevels then
      MoveDelta(poset!.levelboxes[i],0,level!.height);
    fi;
    if poset!.showlevelparams then
      MoveDelta(poset!.lptexts[i],0,level!.height);
    fi;
  od;
  FastUpdate(poset,false);
  
  # has the graphic sheet become higher?
  l := l + 1;    # this means:   l := Length(poset!.levels);
  i := poset!.levels[l]!.top + poset!.levels[l]!.height;
  if i > poset!.height then
    Resize(poset,poset!.width,i);
  fi;
  
  # create a level box:
  box := Box(poset,0,level!.top+level!.height-8,8,8);
  if COLORS.blue <> false then
    Recolor(box,COLORS.blue);
  fi;
  if not poset!.showlevels then
    Destroy(box);
  fi;
  poset!.levelboxes[firstpos] := box;
  
  # create a level parameter text:
  if lpstr <> "" then
    str := lpstr;
  else
    str := String(levelparam);
  fi;
  strlen := Length(str);
  text := Text(poset,FONTS.normal,
               poset!.width - 24 - strlen*FontInfo(FONTS.normal)[3],
               level!.top + QuoInt(level!.height,2),str);
  if COLORS.blue <> false then
    Recolor(text,COLORS.blue);
  fi;
  if not poset!.showlevelparams then
    Destroy(text);
  fi;
  poset!.lptexts[firstpos] := text;
  
  return levelparam;
end);


InstallOtherMethod( CreateLevel,
    "for a graphic poset, and a level parameter",
    true,
    [ IsGraphicPosetRep, IsObject ],
    0,
function( poset, levelparam )
  return CreateLevel(poset,levelparam,"");
end);


#############################################################################
##
#M  CreateClass(<poset>,<levelparam>,<classparam>) . . . .  creates new class
##
##  A class in a graphic poset is a collection of vertices within a level
##  which belong together in some sense.  Every vertex in a graphic poset
##  is in a class, which in turn belongs to a level. Every class in a level
##  has a unique classparam, which can be any {\GAP} object. The user is
##  responsible for all methods where a classparam occurs as parameter and
##  is not just an integer. There is NO {\GAP} object representing a class
##  which is visible to the user of posets. All communication about classes
##  goes via the classparam.  Returns fail if there is no level with
##  parameter levelparam or there is already a class in this level with
##  parameter classparam. Returns classparam otherwise.
##
InstallMethod( CreateClass,
    "for a graphic poset, a level parameter, and a class parameter",
    true,
    [ IsGraphicPosetRep, IsObject, IsObject ],
    0,

function( poset, levelparam, classparam )
  local nr, level;
  
  nr := Position(poset!.levelparams,levelparam);
  if nr = fail then
    return fail;
  fi;
  level := poset!.levels[nr];
  
  nr := Position(level!.classparams,classparam);
  if nr <> fail then
    return fail;
  fi;
  
  Add(level!.classparams,classparam);
  Add(level!.classes,[]);
  
  return classparam;
end);

  
#############################################################################
##
#M  Vertex(<graph>,<data>[,<inf>]) . . . . . . . . . . . . creates new vertex
##
##  Creates a new vertex. <inf> is a record in which additional info can be
##  supplied for the new vertex. For general graphic graphs only the
##  "label", "color", "shape", "x" and "y" components are applicable, they
##  contain a short label which will be attached to the vertex, the color,
##  the shape ("circle", "diamond", or "rectangle") and the coordinates
##  relative to the graphic sheet respectively. For graphic posets also the 
##  components "levelparam" and "classparam" are evaluated. If the component
##  "hints" is bound it must be a list of x coordinates which will be
##  delivered to ChoosePosition to help placement. Those x coordinates will
##  be the coordinates of other vertices related to the new one. All values of
##  record components which are not specified will be determined by calling 
##  some methods for graphic graphs or posets. Those are:
##    ChooseLabel for the label,
##    ChooseColor for the color,
##    ChooseShape for the shape,
##    ChoosePosition for the position,
##    ChooseLevel for the levelparam, and
##    ChooseClass for the classparam.
##    ChooseWidth for the line width of the vertex
##  Returns fail no vertex was created. This happens only, if one of the
##  choose functions return fail or no possible value, for example a
##  non-existing level or class parameter.
##  Returns vertex object if everything went well. 
##
InstallOtherMethod( Vertex,
    "for a graphic poset, an object, and a record",
    true,
    [ IsGraphicPosetRep, IsObject, IsRecord ],
    0,

function( poset, data, info )
  local   lp,  lnr,  level,  cp,  cnr,  class,  vertex,  label,  shape,  
          color,  position, width;
  
  # first determine levelparam:
  if not IsBound(info.levelparam) then
    lp := ChooseLevel(poset,data);
  else
    lp := info.levelparam;
  fi;
  if lp = fail then
    return fail;
  fi;
  
  # we search for the level:
  lnr := Position(poset!.levelparams,lp);
  if lnr = fail then
    return fail;
  fi;
  level := poset!.levels[lnr];
  
  # now determine class:
  if not IsBound(info.classparam) then
    cp := ChooseClass(poset,data,lp);
  else
    cp := info.classparam;
  fi;
  if cp = fail then
    return fail;
  fi;
  
  # we search for the class:
  cnr := Position(level!.classparams,cp);
  if cnr = fail then
    return fail;
  fi;
  class := level!.classes[cnr];
  
  # create a new vertex object:
  PosetLastUsedSerialNumber := PosetLastUsedSerialNumber + 1;
  vertex := rec(data := data,
                levelparam := lp,
                classparam := cp,
                maximals := [],
                maximalin := [],
                serial := PosetLastUsedSerialNumber);
  Objectify(NewType(GraphicObjectFamily,IsGPVertex),vertex);
  SetFilterObj(vertex,IsGGVertex);
  SetFilterObj(vertex,IsAlive);
  
  # choose label, shape, color and position:
  if not IsBound(info.label) then
    label := ChooseLabel(poset,data);
    if label = fail then
      return fail;
    fi;
  else
    label := info.label;
  fi;
  if not IsBound(info.shape) then
    shape := ChooseShape(poset,data);
    if shape = fail then
      return fail;
    fi;
  else
    shape := info.shape;
  fi;
  if not IsBound(info.color) then
    color := ChooseColor(poset,data);
    if color = fail then
      return fail;
    fi;
  else
    color := info.color;
  fi;
  if not (IsBound(info.x) and IsBound(info.y)) then
    if IsBound(info.hints) then
      position := ChoosePosition(poset,data,level,class,info.hints);
    else
      position := ChoosePosition(poset,data,level,class,[]);
    fi;
    if IsBound(info.x) then   # this takes precedence!
      vertex!.x := info.x;
    else
      vertex!.x := position[1];
    fi;
    if IsBound(info.y) then   # this takes precedence!
      vertex!.y := info.y;
    else
      vertex!.y := position[2];
    fi;
  else
    vertex!.x := info.x;
    vertex!.y := info.y;
  fi;
  if not IsBound(info.width) then
    width := ChooseWidth(poset,data);
    if width = fail then
      return fail;
    fi;
  fi;
  
  vertex!.label := label;
  
  # create the graphic object:
  vertex!.obj := Vertex(poset,vertex!.x,level!.top + vertex!.y,
                        rec(label := label,color := color,width := width));
  if shape = "diamond" then
    Reshape(vertex!.obj,VERTEX.diamond);
  elif shape = "rectangle" then
    Reshape(vertex!.obj,VERTEX.rectangle);
  fi;
  
  # put it into the class:
  Add(class,vertex);
  
  return vertex;
end);


#############################################################################
##
##  The following function is only internal:
##
##  Use it on your own risk and only if you know what you are doing!
##
GPSearchWay := function(poset,v1,v2,l2)
  local v, p;
  for v in v1!.maximals do
    if v = v2 then
      return true;
    fi;
    
    if Position(poset!.levelparams,v!.levelparam) < l2 then
      if GPSearchWay(poset,v,v2,l2) then
        return true;
      fi;
    fi;
  od;
  return false;
end;


#############################################################################
##
#M  Edge(<poset>,<vertex1>,<vertex2>) . . . . . . . . . . . . adds a new edge
#M  Edge(<poset>,<vertex1>,<vertex2>,<def>) . . . . . . . . . adds a new edge
##
##  Adds a new edge from <vertex1> to <vertex2>. For posets this puts one
##  of the vertices into the other as a maximal subvertex. So either
##  <vertex1> must lie in a "higher" level than <vertex2> or the other way
##  round. There must be no vertex "between" <vertex1> and <vertex2>. If
##  the two vertices are in the same level or one is already indirectly
##  included in the other fail is returned, otherwise true. That means,
##  that in the case where one of the two vertices is already a maximal
##  subobject of the other, then the method does nothing and returns true.
##  The variation with a defaults record just hands this over to the lower
##  levels, meaning that the line width and color are modified.
##
InstallOtherMethod( Edge,
    "for a graphic poset, two vertices, and a defaults record",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex, IsRecord ],
    0,

function( poset, v1, v2, def )
  local   l1,  l2,  dummy,  l,  p;
  
  # we permute v1 and v2 such that v1 is in higher level:
  if CompareLevels(poset,v1!.levelparam,v2!.levelparam) = 0 then
    return fail;
  fi;
  l1 := Position(poset!.levelparams,v1!.levelparam);
  l2 := Position(poset!.levelparams,v2!.levelparam);
  if l1 > l2 then
    dummy := v1; 
    v1 := v2;
    v2 := dummy;
    dummy := l1;
    l1 := l2;
    l2 := dummy;
  fi;
   
  # first we have to perform a few checks:
  if Position(v1!.maximals,v2) <> fail then
    return true;
  fi;
  if GPSearchWay(poset,v1,v2,l2) then
    return fail;
  fi;
  
  # let's think about color, label and width:
  if not IsBound(def.color) then
    def.color := ChooseColor(poset,v1!.data,v2!.data);
    if def.color = fail then
      return fail;
    fi;
  fi;
  if not IsBound(def.label) then
    def.label := ChooseLabel(poset,v1!.data,v2!.data);
    if def.label = fail then
      return fail;
    fi;
  fi;
  if not IsBound(def.width) then
    def.width := ChooseWidth(poset,v1!.data,v2!.data);
    if def.width = fail then
      return fail;
    fi;
  fi;
  
  # now we know that there is no direct or indirect inclusion of v2 in v1.
  # we can safely put v2 "into" v1.
  Add(v1!.maximals,v2);
  Add(v2!.maximalin,v1);
  Connection(v1!.obj,v2!.obj,def);                                               

  return true;
  
end);

InstallOtherMethod( Edge,
    "for a graphic poset, and two vertices",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex ],
    0,

function( poset, v1, v2 )
  return Edge(poset,v1,v2,rec());
end);

        
#############################################################################
##
##  Destructors:
##
#############################################################################


#############################################################################
##
##  Set this variable temporarily to false if you delete many things!
##
GGDeleteModifiesMenu := true;


#############################################################################
##
#M  Delete(<graph>,<obj>) . . . . . . . . . . . . . remove something in graph
##
##  This operation already exists in {\XGAP} for the graphic objects!
##  Applicable for edges, vertices, classes.
##
##  The following method applies to an edge, given by two vertices. It returns
##  fail if not one of the vertices is maximal in the other and true
##  otherwise. 
InstallOtherMethod( Delete,
    "for a graphic poset, and two vertices",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex ],
    0,

function( poset, v1, v2 )
  local   p,  dummy,  l;
  
  # determine which is the "bigger one":
  p := Position(v2!.maximals,v1);
  if p = fail then
    p := Position(v1!.maximals,v2);
    if p = fail then
      return fail;
    fi;
    # swap the vertices:
    dummy := v1;
    v1 := v2;
    v2 := dummy;
  fi;
  # v1 is now maximal in v2 at position p in v2!.maximals
  
  Disconnect(v1!.obj,v2!.obj);
  l := Length(v2!.maximals);
  v2!.maximals[p] := v2!.maximals[l];
  Unbind(v2!.maximals[l]);
  p := Position(v1!.maximalin,v2);
  # fail is not an option here! If that happens we bomb out!
  l := Length(v1!.maximalin);
  v1!.maximalin[p] := v1!.maximalin[l];
  Unbind(v1!.maximalin[l]);
  
  # think about the menus:
  if GGDeleteModifiesMenu then
    ModifyEnabled(poset,1,Length(poset!.menus));
  fi;
  
  return true;
end);  

##  The following method applies to a vertex. It returns fail if the vertex
##  is not in the poset. The vertex is deleted and all connections to other
##  vertices are also deleted! Returns true if vertex is successfully deleted.
InstallOtherMethod( Delete,
    "for a graphic poset, and a vertex",
    true,
    [ IsGraphicPosetRep, IsGPVertex ],
    0,

function( poset, v )
  local   lp,  l,  cp,  cl,  p,  savemaximals,  savemaximalin,  noerror,  
          v1,  v2,  store;
  
  lp := Position(poset!.levelparams,v!.levelparam);
  if lp = fail then
    return fail;
  fi;
  l := poset!.levels[lp];
  
  cp := Position(l!.classparams,v!.classparam);
  if cp = fail then
    return fail;
  fi;
  cl := l!.classes[cp];
  
  p := Position(cl,v);
  if p = fail then
    return fail;
  fi;
  
  # Remember all connections:
  savemaximals := ShallowCopy(v!.maximals);
  savemaximalin := ShallowCopy(v!.maximalin);
  
  # Delete all connections:
  noerror := true;
  store := GGDeleteModifiesMenu;
  GGDeleteModifiesMenu := false;
  while v!.maximals <> [] do
    if Delete(poset,v,v!.maximals[1]) = fail then
      noerror := fail;
    fi;
  od;
  while v!.maximalin <> [] do
    if Delete(poset,v,v!.maximalin[1]) = fail then
      noerror := fail;
    fi;
  od;
  GGDeleteModifiesMenu := store;
  
  # was it selected?
  RemoveSet(poset!.selectedvertices,v);
  
  # now delete vertex:
  Delete(v!.obj);
  ResetFilterObj(v,IsAlive);
  
  l := Length(cl);
  cl[p] := cl[l];
  Unbind(cl[l]);
  
  # now we have to add new inclusions from the maximal subobjects to those
  # where our vertex was maximal in. We should not do that however, if there is
  # already a way. This ensures that the diagram will be again a Hasse diagram
  # of the remaining vertices with the inclusions induced by the poset
  # before deletion.
  for v1 in savemaximals do
    for v2 in savemaximalin do
      if not GPSearchWay(poset,v2,v1,
                         Position(poset!.levelparams,v1!.levelparam)) then
        Edge(poset,v2,v1);
      fi;
    od;
  od;
        
  # think about the menus:
  if GGDeleteModifiesMenu then
    ModifyEnabled(poset,1,Length(poset!.menus));
  fi;
  
  return noerror;
end);

##  The following method applies to a class. It returns fail if the class
##  is not in the poset. The class is deleted and all vertices including
##  their connections to other vertices are also deleted! Returns true 
##  if class is successfully deleted.
##  The two parameters are a level parameter and a class parameter.
InstallOtherMethod( Delete,
    "for a graphic poset, and two objects",
    true,
    [ IsGraphicPosetRep, IsObject, IsObject ],
    0,

function( poset, levelparam, classparam )
  local   lp,  l,  cp,  noerror,  v,  store;
  
  lp := Position(poset!.levelparams,levelparam);
  if lp = fail then
    return fail;
  fi;
  l := poset!.levels[lp];
  
  cp := Position(l!.classparams,classparam);
  if cp = fail then
    return fail;
  fi;
  
  # delete all vertices:
  noerror := true;
  store := GGDeleteModifiesMenu;
  GGDeleteModifiesMenu := false;
  for v in l!.classes[cp] do
    if Delete(poset,v) = fail then
      noerror := fail;
    fi;
  od;
  GGDeleteModifiesMenu := store;
  
  lp := Length(l!.classes);
  l!.classes[cp] := l!.classes[lp];
  Unbind(l!.classes[lp]);
  l!.classparams[cp] := l!.classparams[lp];
  Unbind(l!.classparams[lp]);
  
  # think about the menus:
  if GGDeleteModifiesMenu then
    ModifyEnabled(poset,1,Length(poset!.menus));
  fi;
    
  return noerror;
end);


#############################################################################
##
#M  DeleteLevel(<poset>,<levelparam>) . . . . . . . . . remove level in poset
##
##  The following method applies to a level. It returns `fail' if no level
##  with level parameter <levelparam> is in the poset. Otherwise the level
##  is deleted and all classes within it are also deleted! `DeleteLevel'
##  returns `true' if the level is successfully deleted.
##
InstallOtherMethod( DeleteLevel,
    "for a graphic poset, and an object",
    true,
    [ IsGraphicPosetRep, IsObject ],
    0,

function( poset, levelparam )
  local   lp,  noerror,  cl,  v,  l,  lev,  store;
  
  lp := Position(poset!.levelparams,levelparam);
  if lp = fail then
    return fail;
  fi;
  
  # delete all vertices:
  noerror := true;
  store := GGDeleteModifiesMenu;
  GGDeleteModifiesMenu := false;
  for cl in poset!.levels[lp]!.classes do
    while cl <> [] do
      if Delete(poset,cl[1]) = fail then
        noerror := fail;
      fi;
    od;
  od;
  GGDeleteModifiesMenu := store;
    
  l := Length(poset!.levels);
  # now we have to move all lower levels up:
  FastUpdate(poset,true);
  for lev in [lp+1..l] do
    poset!.levels[lev]!.top := poset!.levels[lev]!.top 
                               - poset!.levels[lp]!.height;
    for cl in poset!.levels[lev]!.classes do
      for v in cl do
        Move(poset,v,v!.x,v!.y);
      od;
    od;
    if IsAlive(poset!.levelboxes[lev]) then
      MoveDelta(poset!.levelboxes[lev],0,-poset!.levels[lp]!.height);
    fi;
    if IsAlive(poset!.lptexts[lev]) then
      MoveDelta(poset!.lptexts[lev],0,-poset!.levels[lp]!.height);
    fi;
  od;
  FastUpdate(poset,false);
  poset!.levels{[lp..l-1]} := poset!.levels{[lp+1..l]};
  Unbind(poset!.levels[l]);
  poset!.levelparams{[lp..l-1]} := poset!.levelparams{[lp+1..l]};
  Unbind(poset!.levelparams[l]);
  if IsAlive(poset!.levelboxes[lp]) then
    Delete(poset,poset!.levelboxes[lp]);
  fi;
  poset!.levelboxes{[lp..l-1]} := poset!.levelboxes{[lp+1..l]};
  Unbind(poset!.levelboxes[l]);
  if IsAlive(poset!.lptexts[lp]) then
    Delete(poset,poset!.lptexts[lp]);
  fi;
  poset!.lptexts{[lp..l-1]} := poset!.lptexts{[lp+1..l]};
  Unbind(poset!.lptexts[l]);
  
  # think about the menus:
  if GGDeleteModifiesMenu then
    ModifyEnabled(poset,1,Length(poset!.menus));
  fi;

  return noerror;
end);

  
#############################################################################
##
##  Modification methods:
##
#############################################################################


#############################################################################
##
#M  ResizeLevel(<poset>,<levelparam>,<height>)  . . .  change height of level
##
##  Changes the height of a level. The y coordinate can only be changed by
##  permuting levels, see below.
##  Attention: can increase the size of the sheet!
##  Returns fail if no level with parameter levelparam exists and true
##  otherwise. 
##
InstallOtherMethod( ResizeLevel,
    "for a graphic poset, an object, and an integer",
    true,
    [ IsGraphicPosetRep, IsObject, IsInt ],
    0,

function( poset, levelparam, height )
  local   lp,  l,  cl,  v,  dist,  len;
  
  lp := Position(poset!.levelparams,levelparam);
  if lp = fail then
    return fail;
  fi;
  l := poset!.levels[lp];
  
  if height < VERTEX.diameter then
    height := VERTEX.diameter;
  fi;
  
  if height = l!.height then
    return true;
  elif height < l!.height then
    # move all vertices within level into the new range
    FastUpdate(poset,true);
    for cl in l!.classes do
      for v in cl do
        if v!.y > height-VERTEX.radius then
          v!.y := height-VERTEX.radius;
          Move(v!.obj,v!.x,v!.y + l!.top);
        fi;
      od;
    od;
         
    # now move all lower levels up:
    dist := height - l!.height;
    l!.height := height;
    
    # move level box and text:
    if poset!.showlevels then
      Move(poset!.levelboxes[lp],0,l!.top + l!.height - 8);
    fi;
    if poset!.showlevelparams then
      Move(poset!.lptexts[lp],poset!.lptexts[lp]!.x,
           l!.top + QuoInt(l!.height,2));
    fi;
    FastUpdate(poset,false);
    
  else   # height > l!.height
    dist := height - l!.height;
    l!.height := height;
    
    # do we have to increase height of sheet?
    len := Length(poset!.levels);
    if poset!.levels[len]!.top + poset!.levels[len]!.height + dist 
       > poset!.height then
      Resize(poset,poset!.width,
             poset!.levels[len]!.top + poset!.levels[len]!.height + dist);
    fi;
    
    if poset!.showlevels then
      Move(poset!.levelboxes[lp],0,l!.top + l!.height - 8);
    fi;
    if poset!.showlevelparams then
      Move(poset!.lptexts[lp],poset!.lptexts[lp]!.x,
           l!.top + QuoInt(l!.height,2));
    fi;
    
    # next move down all the levels below the increased level:
  fi;
  
  FastUpdate(poset,true);
  for l in [lp+1..Length(poset!.levels)] do
    poset!.levels[l]!.top := poset!.levels[l]!.top + dist;
    for cl in poset!.levels[l]!.classes do
      for v in cl do
        MoveDelta(v!.obj,0,dist);
      od;
    od;
    # move level box:
    if poset!.showlevels then
      MoveDelta(poset!.levelboxes[l],0,dist);
    fi;
    if poset!.showlevelparams then
      MoveDelta(poset!.lptexts[l],0,dist);
    fi;
  od;
  FastUpdate(poset,false);
end);


#############################################################################
##
#M  MoveLevel(<poset>,<levelparam>,<position>) move level to another position
##
##  Moves a level to another position. <position> is an absolute index in
##  the list of levels. The level with parameter <levelparam> will be at the
##  position <position> after the operation. This is only allowed if the
##  new ordering is compatible with the partial order given by CompareLevels
##  and if there is no connection of a vertex in the moving level with 
##  another level with which it is interchanged.
##  So <levelparam> is compared with all levelparams between the old and
##  the new position. If there is a contradiction nothing happens and the
##  method returns fail. If everything works the operation returns true.
##  This operation already exists in {\XGAP} for graphic objects.
##
InstallOtherMethod( MoveLevel,
    "for a graphic poset, an object, and an integer",
    true,
    [ IsGraphicPosetRep, IsObject, IsInt ],
    0,

function( poset, levelparam, position )
  local   lp,  i,  compare,  cl,  v,  v2,  p,  list;
  # nonsense position?
  if position < 1 or position > Length(poset!.levels) then
    return fail;
  fi;
  
  # does level exist?
  lp := Position(poset!.levelparams,levelparam);
  if lp = fail then
    return fail;
  fi;
  
  # nothing to do?
  if position = lp then
    return true;  # we are done
  fi;
  
  if position < lp then   # move level UP
    # check with partial ordering:
    for i in [position..lp-1] do
      compare := CompareLevels(poset,poset!.levelparams[i],levelparam);
      if compare <> fail and compare < 0 then
        # that would contradict the partial order
        return fail;
      fi;
    od;
    
    # now check vertices:
    for cl in poset!.levels[lp]!.classes do
      for v in cl do
        for v2 in v!.maximalin do
          p := Position(poset!.levelparams,v2!.levelparam);
          if p >= position then  # < lp is a MUST!
            return fail;
          fi;
        od;
      od;
    od;
    
    # OK, we can do it:
    FastUpdate(poset,true);
    list := Concatenation([lp],[position..lp-1]);
    poset!.levels{[position..lp]} := poset!.levels{list};
    poset!.levelparams{[position..lp]} := poset!.levelparams{list};
    poset!.levelboxes{[position..lp]} := poset!.levelboxes{list};
    poset!.lptexts{[position..lp]} := poset!.lptexts{list};
    poset!.levels[position]!.top := poset!.levels[position+1]!.top;
    if poset!.showlevels then
      Move(poset!.levelboxes[position],0,poset!.levels[position]!.top 
                                  + poset!.levels[position]!.height - 8);
    fi;
    if poset!.showlevelparams then
      Move(poset!.lptexts[position],poset!.lptexts[position]!.x,
           poset!.levels[position]!.top + 
           QuoInt(poset!.levels[position]!.height,2));
    fi;
    
    for cl in poset!.levels[position]!.classes do
      for v in cl do
        Move(poset,v,v!.x,v!.y);
      od;
    od;
    for i in [position+1..lp] do
      poset!.levels[i]!.top := poset!.levels[i]!.top 
                               + poset!.levels[position]!.height;
      
      if poset!.showlevels then
        Move(poset!.levelboxes[i],0,poset!.levels[i]!.top
                                    + poset!.levels[i]!.height - 8);
      fi;
      if poset!.showlevelparams then
        Move(poset!.lptexts[i],poset!.lptexts[i]!.x,
             poset!.levels[i]!.top + QuoInt(poset!.levels[i]!.height,2));
      fi;
      for cl in poset!.levels[i]!.classes do
        for v in cl do
          Move(poset,v,v!.x,v!.y);
        od;
      od;
    od;
    # in case another one has overwritten our box:
    if poset!.showlevels then
      Draw(poset!.levelboxes[position]);
    fi;
    if poset!.showlevelparams then
      Draw(poset!.lptexts[position]);
    fi;
    FastUpdate(poset,false);
    
    # we did it.
  else   # position > lp, move level DOWN
    # check with partial ordering:
    for i in [lp+1..position] do
      compare := CompareLevels(poset,poset!.levelparams[i],levelparam);
      if compare <> fail and compare > 0 then
        # that would contradict the partial order
        return fail;
      fi;
    od;
    
    # now check vertices:
    for cl in poset!.levels[lp]!.classes do
      for v in cl do
        for v2 in v!.maximals do
          p := Position(poset!.levelparams,v2!.levelparam);
          if p <= position then  # > lp is a MUST!
            return fail;
          fi;
        od;
      od;
    od;
    
    # OK, we can do it:
    FastUpdate(poset,true);
    list := Concatenation([lp+1..position],[lp]);
    poset!.levels{[lp..position]} := poset!.levels{list};
    poset!.levelparams{[lp..position]} := poset!.levelparams{list};
    poset!.levelboxes{[lp..position]} := poset!.levelboxes{list};
    poset!.lptexts{[lp..position]} := poset!.lptexts{list};
    poset!.levels[position]!.top := poset!.levels[position-1]!.top
                                  - poset!.levels[position]!.height
                                    + poset!.levels[position-1]!.height;
    if poset!.showlevels then
      Move(poset!.levelboxes[position],0,poset!.levels[position]!.top
                                       + poset!.levels[position]!.height - 8);
    fi;
    if poset!.showlevelparams then
      Move(poset!.lptexts[position],poset!.lptexts[position]!.x,
           poset!.levels[position]!.top + 
           QuoInt(poset!.levels[position]!.height,2));
    fi;
    for cl in poset!.levels[position]!.classes do
      for v in cl do
        Move(poset,v,v!.x,v!.y);
      od;
    od;
    for i in [lp..position-1] do
      poset!.levels[i]!.top := poset!.levels[i]!.top 
                             - poset!.levels[position]!.height;
      if poset!.showlevels then
        Move(poset!.levelboxes[i],0,poset!.levels[i]!.top
                                           + poset!.levels[i]!.height - 8);
      fi;
      if poset!.showlevelparams then
        Move(poset!.lptexts[i],poset!.lptexts[i]!.x,
             poset!.levels[i]!.top + QuoInt(poset!.levels[i]!.height,2));
      fi;
      for cl in poset!.levels[i]!.classes do
        for v in cl do
          Move(poset,v,v!.x,v!.y);
        od;
      od;
    od;
    # in case another one has overwritten our box:
    if poset!.showlevels then
      Draw(poset!.levelboxes[position]);
    fi;
    if poset!.showlevelparams then
      Draw(poset!.lptexts[position]);
    fi;
    FastUpdate(poset,false);
    
    # we did it.
  fi;
  
  return true;
end);


#############################################################################
##
#M  Relabel(<graph>,<vertex>,<label>)  . . . . . . . . change label of vertex
#M  Relabel(<graph>,<vertex>)  . . . . . . . . . . . . change label of vertex
#M  Relabel(<poset>,<vertex1>,<vertex2>,<label>) . . . . change label of edge
#M  Relabel(<poset>,<vertex1>,<vertex2>) . . . . . . . . change label of edge
##
##  Changes the label of the vertex <vertex> or the edge between <vertex1>
##  and <vertex2>. This must be a short string. In the method where no
##  label is specified the new label is chosen functionally: the operation
##  `ChooseLabel' is called. `Relabel' returns `fail' if an error occurs
##  and `true' otherwise.  This operations already exists in {\XGAP} for
##  graphic objects.
##
InstallOtherMethod( Relabel,
    "for a graphic graph, a vertex, and a string",
    true,
    [ IsGraphicGraphRep, IsGGVertex, IsString ],
    0,

function( graph, vertex, label )
  if label = "" then
    label := false;
  fi;
  # we just call the low level routines:
  vertex!.label := label;
  Relabel(vertex!.obj,label);
end);

InstallOtherMethod( Relabel,
    "for a graphic graph, and a vertex",
    true,
    [ IsGraphicGraphRep, IsGGVertex ],    
    0,
        
function( graph, vertex)
  local label;
  
  label := ChooseLabel( graph, vertex!.data );
  if label = "" then
    label := false;
  fi;
  # we just call the low level routines:
  vertex!.label := label;
  Relabel(vertex!.obj,label);
end);
  
InstallOtherMethod( Relabel,
    "for a graphic poset, two vertices, and a string",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex, IsString ],
    0,

function( poset, v1, v2, label )
  local   p;
  p := Position(v1!.maximals,v2);
  if p = fail then
    p := Position(v2!.maximals,v1);
    if p = fail then
      return fail;
    fi;
  fi;
  # we know now that there is a connection!
  p := Position(v1!.obj!.connections,v2!.obj);
  
  if label = "" then
    label := false;
  fi;
  
  # now we just call the low level routines:
  Relabel(v1!.obj!.connectingLines[p],label);
end);

InstallOtherMethod( Relabel,
    "for a graphic poset, and two vertices",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex ],    
    0,
        
function( poset, v1, v2)
  local   label;
  
  label := ChooseLabel( poset, v1!.data, v2!.data );
  if label = "" then
    label := false;
  fi;
  # we just call the low level routines:
  Relabel(poset,v1,v2,label);
end);
  
  
#############################################################################
##
#M  Move(<graph>,<vertex>,<x>,<y>) . . . . . . . . . . . . . . .  move vertex
#M  Move(<graph>,<vertex>) . . . . . . . . . . . . . . . . . . .  move vertex
##
##  Moves vertex <vertex>. For posets coordinates are relative to the level
##  of the vertex. <vertex> must be a vertex object in <graph>. If no
##  coordinates are specified the operation `ChoosePosition' is
##  called. Returns `fail' if an error occurs and `true' otherwise.  This
##  operations already exists in {\XGAP} for graphic objects.
##
InstallOtherMethod( Move,
    "for a graphic poset, a vertex, and two integers",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsInt, IsInt ],
    0,

function( poset, vertex, x, y )
  local l;
  
  if x < VERTEX.radius then 
    x := VERTEX.radius;
  elif x > poset!.width-VERTEX.radius then
    x := poset!.width-VERTEX.radius;
  fi;
  l := Position(poset!.levelparams,vertex!.levelparam);
  l := poset!.levels[l];
  if y < VERTEX.radius then
    y := VERTEX.radius;
  elif y > l!.height-VERTEX.radius then
    y := l!.height-VERTEX.radius;
  fi;
  
  vertex!.x := x;
  vertex!.y := y;
  Move(vertex!.obj,x,y+l!.top);
  
  return true;
end);

InstallOtherMethod( Move,
    "for a graphic poset, and a vertex",
    true,
    [ IsGraphicPosetRep, IsGPVertex ],
    0,

function( poset, vertex )
  local position;
  
  position := ChoosePosition(poset, vertex!.data, vertex!.levelparam,
                             vertex!.classparam); 
  Move(poset,vertex,position[1],position[2]);
end);


#############################################################################
##
#M  Reshape(<graph>,<vertex>,<shape>)  . . . . . . . . change shape of vertex
#M  Reshape(<graph>,<vertex>)  . . . . . . . . . . . . change shape of vertex
##
##  Changes the shape of the vertex <vertex>. <vertex> must be a vertex
##  object in the graph or poset <graph>. For the method where no shape is
##  specified the new shape is chosen functionally: `ChooseShape` is called
##  for the corresponding data.  `Reshape' returns `fail' if an error
##  occurs and `true' otherwise.  This operations already exists in {\XGAP}
##  for graphic objects.
##
InstallOtherMethod( Reshape,
    "for a graphic graph, a vertex, and a string",
    true,
    [ IsGraphicGraphRep, IsGGVertex, IsString ],
    0,

function( graph, vertex, shape )
  if shape = "circle" then
    Reshape(vertex!.obj,VERTEX.circle);
  elif shape = "diamond" then
    Reshape(vertex!.obj,VERTEX.diamond);
  else
    Reshape(vertex!.obj,VERTEX.rectangle);
  fi;
  return true;
end);

InstallOtherMethod( Reshape,
    "for a graphic graph, and a vertex",
    true,
    [ IsGraphicGraphRep, IsGGVertex ],
    0,

function( graph, vertex )
  local shape;
  
  shape := ChooseShape( graph, vertex!.data );
  Reshape(graph, vertex, shape);
  return true;
end);


#############################################################################
##
#M  Recolor(<graph>,<vertex>,<color>)  . . . . . . . . change color of vertex
#M  Recolor(<graph>,<vertex>)  . . . . . . . . . . . . change color of vertex
#M  Recolor(<poset>,<vertex1>,<vertex2>,<color>) . .  change color of an edge
#M  Recolor(<poset>,<vertex1>,<vertex2>) . . . . . .  change color of an edge
##
##  Changes the color of the vertex <vertex> or the edge between <vertex1>
##  and <vertex2>. <vertex> must be a vertex object in <graph>. For the
##  method where no color is specified the new color is chosen
##  functionally: `ChooseColor' is called for the corresponding
##  data. `Recolor' returns `fail' if an error occurs and `true'
##  otherwise. This operation already exists in {\XGAP} for graphic objects.
##
InstallOtherMethod( Recolor,
    "for a graphic graph, a vertex, and a color",
    true,
    [ IsGraphicGraphRep, IsGGVertex, IsColor ],
    0,

function( graph, vertex, color )
  Recolor(vertex!.obj,color);
  return true;
end);

InstallOtherMethod( Recolor,
    "for a graphic graph, and a vertex",
    true,
    [ IsGraphicGraphRep, IsGGVertex ],
    0,

function( graph, vertex )
  local color;
  
  color := ChooseColor( graph, vertex!.data );
  Recolor(graph, vertex, color);
  return true;
end);

InstallOtherMethod( Recolor,
    "for a graphic poset, two vertices, and a color",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex, IsColor ],
    0,

function( poset, vertex1, vertex2, color )
  local   p;
  p := Position(vertex1!.maximals,vertex2);
  if p = fail then
    p := Position(vertex2!.maximals,vertex1);
    if p = fail then
      return fail;
    fi;
  fi;
  # we know now that there is a connection!
  p := Position(vertex1!.obj!.connections,vertex2!.obj);
  Recolor(vertex1!.obj!.connectingLines[p],color);
  return true;
end);

InstallOtherMethod( Recolor,
    "for a graphic poset, and two vertices",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex ],
    0,

function( poset, vertex1, vertex2 )
  local   color;
  
  color := ChooseColor( poset, vertex1!.data, vertex2!.data );
  return Recolor(poset, vertex1, vertex2, color);
end);


#############################################################################
##
#M  SetWidth(<graph>,<vertex1>,<vertex2>,<width>) . change line width of edge
#M  SetWidth(<graph>,<vertex1>,<vertex2>) . . . . . change line width of edge
##
##  Changes the line width of an edge. <vertex1> and <vertex2> must be
##  vertices in the graph <graph>. For the method where no line width is
##  specified the width is chosen functionally: `ChooseWidth' is called for
##  the corresponding data pair. Returns `fail' if an error occurs and
##  `true' otherwise. This operation already exists in {\XGAP} for graphic
##  objects.
##
InstallOtherMethod( SetWidth,
    "for a graphic poset, two vertices, and an integer",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex, IsInt ],
    0,

function( poset, vertex1, vertex2, width )
  local   p;
  p := Position(vertex1!.maximals,vertex2);
  if p = fail then
    p := Position(vertex2!.maximals,vertex1);
    if p = fail then
      return fail;
    fi;
  fi;
  # we know now that there is a connection!
  p := Position(vertex1!.obj!.connections,vertex2!.obj);
  SetWidth(vertex1!.obj!.connectingLines[p],width);
  return true;
end);

InstallOtherMethod( SetWidth,
    "for a graphic poset, and two vertices",
    true,
    [ IsGraphicPosetRep, IsGPVertex, IsGPVertex ],
    0,

function( poset, vertex1, vertex2 )
  local   width;
  
  width := ChooseWidth( poset, vertex1!.data, vertex2!.data );
  return SetWidth(poset, vertex1, vertex2, width);
end);


#############################################################################
##
#M  Highlight(<graph>,<vertex>)  . . . . . . . change highlighting of vertex
#M  Highlight(<graph>,<vertex>,<flag>) . . . . change highlighting of vertex
##
##  Changes the highlighting status of the vertex <vertex>. <vertex> must
##  be a vertex object in <graph>. For the method where no flag is
##  specified the new status is chosen functionally: `ChooseHighlight' is
##  called for the corresponding data. Returns `fail' if an error occurs
##  and `true' otherwise. This operation already exists in {\XGAP} for
##  graphic objects.
##
InstallOtherMethod( Highlight,
    "for a graphic graph, a vertex, and a flag",
    true,
    [ IsGraphicGraphRep, IsGGVertex, IsBool ],
    0,

function( graph, vertex, flag )
  Highlight(vertex!.obj,flag);
  return true;
end);

InstallOtherMethod( Highlight,
    "for a graphic graph, and a vertex",
    true,
    [ IsGraphicGraphRep, IsGGVertex ],
    0,

function( graph, vertex )
  local flag;
  
  flag := ChooseHighlight( graph, vertex!.data );
  Highlight(graph, vertex, flag);
  return true;
end);


#############################################################################
##
##  Set this variable temporarily to false if you change many selections!
##
GGSelectModifiesMenu := true;


#############################################################################
##
#M  Select(<graph>,<vertex>,<flag>) . . . . . . . . . . (de-)selects a vertex
#M  Select(<graph>,<vertex>)  . . . . . . . . . . . . . . .  selects a vertex
##
##  Changes the selection state of the vertex <vertex>. <vertex> must be a
##  vertex object in <graph>. The flag determines whether the vertex
##  should be selected or deselected. This operation already exists in
##  {\XGAP} for graphic objects.  The method without flags assumes `true'.
##
InstallOtherMethod( Select,
    "for a graphic graph, a vertex, and a flag",
    true,
    [ IsGraphicGraphRep, IsGGVertex, IsBool ],
    0,
      
function(graph,vertex,flag)
  local   p,  l;
  p := PositionSet(graph!.selectedvertices,vertex);
  if flag then
    if p <> fail then  
      return;
    fi;
    Highlight(graph,vertex,true);
    Recolor(graph,vertex,graph!.color.selected);
    AddSet(graph!.selectedvertices,vertex);
  else
    if p = fail then
      return;
    fi;
    Highlight(graph,vertex,false);
    Recolor(graph,vertex,graph!.color.unselected);
    RemoveSet(graph!.selectedvertices,vertex);
  fi;
  if GGSelectModifiesMenu then
    ModifyEnabled(graph,1,Length(graph!.menus));
  fi;
  return;
end);

InstallOtherMethod( Select,
    "for a graphic graph, and a vertex",
    true,
    [ IsGraphicGraphRep, IsGGVertex ],
    0,
      
function(graph,vertex)
  Select(graph,vertex,true);
end);  


#############################################################################
##
#M  DeselectAll(<graph>) . . . . . . . . . . . . . . . deselects all vertices
##
##  Deselects all vertices in graph.
##
InstallOtherMethod( DeselectAll,
    "for a graphic graph",
    true,
    [ IsGraphicGraphRep ],
    0,
      
function(graph)
  local   v;
  for v in graph!.selectedvertices do
    Highlight(graph,v,false);
    Recolor(graph,v,graph!.color.unselected);
  od;
  graph!.selectedvertices := [];
end);


#############################################################################
##
#M  Selected(<graph>) . . . . . . . . .  returns set of all selected vertices
##
##  Returns a (shallow-)copy of the set of all selected vertices.
##
InstallOtherMethod( Selected,
    "for a graphic graph",
    true,
    [ IsGraphicGraphRep ],
    0,
      
function(graph)
  return ShallowCopy(graph!.selectedvertices);
end);


#############################################################################
##
##  Methods for functional decisions:
##
#############################################################################


#############################################################################
##
#M  CompareLevels(<poset>,<levelp1>,<levelp2>) . . . compares two levelparams
##
##  Compare two levelparams. -1 means that levelp1 is "higher", 1 means
##  that levelp2 is "higher", 0 means that they are equal. fail means that
##  they are not comparable. This method is for the case if level
##  parameters are integers and lower values mean higher levels like in the
##  case of group lattices and subgroup indices.
##
InstallMethod( CompareLevels,
    "for a graphic poset, and two integers",
    true,
    [ IsGraphicPosetRep, IsInt, IsInt ],
    0,

function( poset, l1, l2 )
  if l1 < l2 then
    return -1;
  elif l1 > l2 then
    return 1;
  else
    return 0;
  fi;
end);


#############################################################################
##
#M  ChooseLabel(<graph>,<data>) . . . . . . . is called while vertex creation
#M  ChooseLabel(<graph>,<data>,<data>)  . . . . is called while edge creation
##
##  This operation is called while vertex or edge creation, if the caller 
##  didn't specify a label for the vertex or edge. It has to return a short 
##  string which will be attached to the vertex. If it returns fail the new 
##  vertex is not generated! This method just returns the empty string, so 
##  no label is generated.
##  This method is also called in the Relabel method without label parameter.
##
InstallMethod( ChooseLabel,
    "for a graphic graph, and an object",
    true,
    [ IsGraphicGraphRep, IsObject ],
    0,

function( graph, data )
  return "";
end);

InstallOtherMethod( ChooseLabel,
    "for a graphic graph, and two objects",
    true,
    [ IsGraphicGraphRep, IsObject, IsObject ],
    0,

function( poset, data1, data2 )
  return "";
end);


#############################################################################
##
#M  ChooseLevel(<poset>,<data>) . . . . . . . is called while vertex creation
##
##  This operation is called while vertex creation, if the caller didn't
##  specify a level where the vertex belongs to. It has to return a
##  levelparam which exists in the poset. If it returns fail the new vertex
##  is not generated!
##  This method just chooses the last, lowest level or fail, if there is no 
##  level in the poset.
##
InstallMethod( ChooseLevel,
    "for a graphic poset, and an object",
    true,
    [ IsGraphicPosetRep, IsObject ],
    0,

function( poset, data )
  local l;
  l := Length(poset!.levelparams);
  if l > 0 then
    return poset!.levelparams[Length(poset!.levelparams)];
  else
    return fail;
  fi;
end);


#############################################################################
##
#M  ChooseClass(<poset>,<data>,<levelp>) . .  is called while vertex creation
##
##  This operation is called while vertex creation, if the caller didn't
##  specify a class where the vertex belongs to. It has to return a
##  classparam which exists in the poset in levelp. If it returns fail the
##  new vertex is not generated!
##  This method just generates a new class in the level with classparam one 
##  bigger than the maximum of all (integer) classparams. It returns fail if
##  this maximum is no integer.
##
InstallMethod( ChooseClass,
    "for a graphic graph, and two objects",
    true,
    [ IsGraphicPosetRep, IsObject, IsObject ],
    0,

function( poset, data, levelparam )
  local l,m;
  
  l := Position(poset!.levelparams,levelparam);
  if l = fail then 
    return fail;
  fi;
  l := poset!.levels[l];
  
  if l!.classparams = [] then
    return CreateClass(poset,levelparam,1);
  fi;
    
  m := Maximum(l!.classparams);
  if not IsInt(m) then
    return fail;
  fi;
  
  return CreateClass(poset,levelparam,m+1);
end);
  

#############################################################################
##
#M  ChooseShape(<graph>,<data>) . . . . . . . is called while vertex creation
##
##  This operation is called while vertex creation.
##  It has to return a string out of the following list:
##  "circle", "diamond", "rectangle"
##  If it returns fail the new vertex is not generated!
##  This method just returns "circle".
##
InstallMethod( ChooseShape,
    "for a graphic graph, and an object",
    true,
    [ IsGraphicGraphRep, IsObject ],
    0,

function( graph, data )
  return "circle";
end);


#############################################################################
##
#M  ChooseWidth(<graph>,<data>) . . . . . . . is called while vertex creation
#M  ChooseWidth(<graph>,<data1>,<data2>)  . . . is called while edge creation
##
##  This operation is called while vertex or edge creation.
##  It has to return a line width.
##  If it returns fail the new vertex or edge is not generated!
##  This is also called by the SetWidth operation without width parameter.
##  This method just returns 1.
##
InstallOtherMethod( ChooseWidth,
    "for a graphic graph, and an object",
    true,
    [ IsGraphicGraphRep, IsObject ],
    0,

function( graph, data )
  return 1;
end);

InstallOtherMethod( ChooseWidth,
    "for a graphic graph, and two objects",
    true,
    [ IsGraphicGraphRep, IsObject, IsObject ],
    0,

function( graph, data1, data2 )
  return 1;
end);


#############################################################################
##
#M  ChooseColor(<graph>,<data>) . . . . . . . is called while vertex creation
#M  ChooseColor(<graph>,<data1>,<data2>). . . . is called while edge creation
##
##  This operation is called while vertex or edge creation. It has to return a
##  color. If it returns fail the new vertex is not generated!
##  It is also called in the Recolor method without color parameter.
##  This method just returns black.
##
InstallMethod( ChooseColor,
    "for a graphic graph, and an object",
    true,
    [ IsGraphicGraphRep, IsObject ],
    0,

function( graph, data )
  return COLORS.black;
end);

InstallOtherMethod( ChooseColor,
    "for a graphic graph, and two objects",
    true,
    [ IsGraphicGraphRep, IsObject, IsObject ],
    0,

function( graph, data1, data2 )
  return COLORS.black;
end);


#############################################################################
##
#M  ChooseHighlight(<graph>,<data>) . . . . . is called while vertex creation
##
##  This operation is called while vertex creation. It has to return a
##  flag which indicates, whether the vertex is highlighted or not. If it 
##  returns fail the new vertex is not generated!
##  It is also called in the Highlight method without flag parameter.
##
##  The following method just returns false.
InstallMethod( ChooseHighlight,
    "for a graphic graph, and an object",
    true,
    [ IsGraphicGraphRep, IsObject ],
    0,

function( graph, data )
  return false;
end);


#############################################################################
##
#M  ChoosePosition(<poset>,<data>,<level>,<class>)  . . . . . . . . . . . . . 
#M  ChoosePosition(<graph>,<data>)  . . . . . is called while vertex creation
##
##  This operation is called while vertex creation.  It has to return a
##  list with two integers: the coordinates. For posets those are relative
##  to the level the vertex resides in.  If it returns fail the new vertex
##  is not generated!  
##  This method positions a new vertex in a nonempty class next to the last
##  member in the class and a new vertex in a new class halfway to the
##  right end of the sheet from the rightmost vertex in the level or
##  halfway to the left end of the sheet from the leftmost vertex in the
##  class, depending where there is more space.
##
InstallMethod( ChoosePosition,
    "for a graphic poset, an object, a level object, a list, and a list",
    true,
    [ IsGraphicPosetRep, IsObject, IsGPLevel, IsList, IsList ],
    0,

function( poset, data, level, class, hints )
  local   position,  ranges,  cl,  gaps,  maxindex,  i;
  
  position := [];
  # not first in class:
  if class <> [] then
    # just near the others in the class:
    position[2] := class[Length(class)]!.y;
    position[1] := class[Length(class)]!.x + VERTEX.diameter + 2;
  else
    # collect all x ranges where classes reside:
    ranges := [[0,0]];
    for cl in level!.classes do
      if cl <> [] then
        Add(ranges,[cl[1]!.x-VERTEX.radius,cl[Length(cl)]!.x+VERTEX.radius]);
      fi;
    od;
    Add(ranges,[poset!.width,poset!.width]);
    ranges := Set(ranges);
    gaps := List([1..Length(ranges)-1],x->ranges[x+1][1]-ranges[x][2]);
    
    # search largest gap:
    maxindex := 1;
    for i in [2..Length(gaps)] do
      if gaps[i] > gaps[maxindex] then
        maxindex := i;
      fi;
    od;
    
    position[1] := QuoInt(ranges[maxindex][2]+ranges[maxindex+1][1],2);
    position[2] := QuoInt(level!.height,2);
  fi;
  return position;
end);



#############################################################################
##
##  Methods for getting information:
##
#############################################################################


#############################################################################
##
--> --------------------

--> maximum size reached

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

[ zur Elbe Produktseite wechseln0.163Quellennavigators  ]