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


Quelle  freeinverse.gi   Sprache: unbekannt

 
###############################################################################
##
##  fp/freeinverse.gi
##  Copyright (C) 2013-2022                                Julius Jonusas
##
##  Licensing information can be found in the README file of this package.
##
###############################################################################
##
##  Internal representation of the elements of free inverse semigroups is
##  is given as a list:
##  [
##  number of generators,
##  number of vertices,
##  finish vertex,
##  parent list (for each vertex gives the name of a parent),
##  list of labels (from a parent to a child),
##  adjacency list for every vertex
##  ]
##
##  For example an element xxx^-1yy^-1 is represented by:
##  [2, 4, 2, [fail, 1, 2, 2], [fail, 1, 1, 4], [2, , , ,], [3, 1 , ,4],
##     [ , 2, , ], [, , 2, ]];
##
##  Note that if x1, x2, ... are the generators, then in the internal
##  representation of x1 is 1, x1^-1 by 2, x2 by 3 and so on.
##

InstallTrueMethod(IsGeneratorsOfInverseSemigroup,
                  IsFreeInverseSemigroupElementCollection);

InstallImmediateMethod(IsFinite, IsFreeInverseSemigroup, 0, ReturnFalse);

############################################################################
##
## FreeInverseSemigroup( <rank>[, names] )
## FreeInverseSemigroup( name1, name2, ... )
## FreeInverseSemigroup( names )
##

InstallGlobalFunction(FreeInverseSemigroup,
function(arg...)
  local names, F, type, gens, opts, S, m;

  # Get and check the argument list, and construct names if necessary.
  if Length(arg) = 1 and IsInt(arg[1]) and 0 < arg[1] then
    names := List([1 .. arg[1]],
                  i -> Concatenation("x", String(i)));
    MakeImmutable(names);
  elif Length(arg) = 2 and IsInt(arg[1]) and 0 < arg[1]
      and IsString(arg[2]) then
    names := List([1 .. arg[1]],
                  i -> Concatenation(arg[2], String(i)));
    MakeImmutable(names);
  elif Length(arg) = 1 and IsList(arg[1]) and IsEmpty(arg[1]) then
    names := arg[1];
  elif 1 <= Length(arg) and ForAll(arg, IsString) then
    names := arg;
  elif Length(arg) = 1 and IsList(arg[1])
      and ForAll(arg[1], IsString) then
    names := arg[1];
  else
    ErrorNoReturn("FreeInverseSemigroup(<name1>,<name2>..) or ",
                  "FreeInverseSemigroup(<rank> [, name]),");
  fi;

  if IsEmpty(names) then
    ErrorNoReturn("the number of generators of a free inverse semigroup must ",
                  "be non-zero");
  fi;

  F := NewFamily("FreeInverseSemigroupElementsFamily",
                 IsFreeInverseSemigroupElement,
                 CanEasilySortElements);

  type := NewType(F, IsFreeInverseSemigroupElement and IsPositionalObjectRep);

  gens := EmptyPlist(Length(names));
  for m in [1 .. Length(names)] do
    gens[m] := Objectify(type, [Length(names), 2, 2, [fail, 1],
                                [fail, 2 * m - 1], [], []]);
    gens[m]![6][2 * m - 1] := 2;
    gens[m]![7][2 * m] := 1;
  od;

  names := Concatenation(List(names, x -> [x, Concatenation(x, "^-1")]));
  StoreInfoFreeMagma(F, names, IsFreeInverseSemigroupElement);
  opts := SEMIGROUPS.ProcessOptionsRec(SEMIGROUPS.DefaultOptionsRec,
                                       rec(batch_size := 401));
  # We require a smallish batch_size because otherwise the iterators are
  # unreasonably slow.
  S := Objectify(NewType(FamilyObj(gens),
                         IsFreeInverseSemigroupCategory
                          and IsInverseSemigroup
                          and IsAttributeStoringRep),
                 rec(opts := opts));
  SetGeneratorsOfInverseSemigroup(S, gens);
  SetIsFreeInverseSemigroup(S, true);
  SetIsSimpleSemigroup(S, false);

  FamilyObj(S)!.semigroup := S;
  F!.semigroup := S;

  SetIsWholeFamily(S, true);
  SetIsTrivial(S, IsEmpty(names));

  return S;
end);

############################################################################
##
## ViewObj
##

InstallMethod(ViewObj, "for a free inverse semigroup element",
[IsFreeInverseSemigroupElement], PrintObj);

InstallMethod(PrintObj, "for a free inverse semigroup element",
[IsFreeInverseSemigroupElement],
function(x)

  if UserPreference("semigroups", "FreeInverseSemigroupElementDisplay")
      = "minimal" then
    Print(MinimalWord(x));
  else
    Print(CanonicalForm(x));
  fi;

  return;
end);

InstallMethod(ViewObj,
"for a free inverse semigroup containing the whole family",
[IsFreeInverseSemigroupCategory],
function(S)
  if GAPInfo.ViewLength * 10 < Length(GeneratorsOfMagma(S)) then
    Print("<free inverse semigroup with ",
          Length(GeneratorsOfInverseSemigroup(S)),
           " generators>");
  else
    Print("<free inverse semigroup on the generators ",
          GeneratorsOfInverseSemigroup(S), ">");
  fi;
end);

############################################################################
##
## MinimalWord
##

SEMIGROUPS.InvertGenerator := function(n)
  if n mod 2 = 0 then
    return n - 1;
  fi;
  return n + 1;
end;

InstallMethod(MinimalWord, "for a free inverse semigroup element",
[IsFreeInverseSemigroupElement],
function(x)
  local InvertGenerator, is_a_child_of, gen, stop_start, i, j, path, words,
   pos, part, temp_word, out, names;

  InvertGenerator := SEMIGROUPS.InvertGenerator;

  is_a_child_of := x![4];
  gen := x![5];
  stop_start := [];  # stop_start[i]=j if vertex i is the jth vertex in the path
                     # from the stop to the start vertex.
  i := x![3];
  j := 1;
  path := [];

  while i <> fail do
    stop_start[i] := j;
    path[j] := i;
    j := j + 1;
    i := is_a_child_of[i];  # parent of i
  od;

  words := EmptyPlist(j - 1);
  pos := [];   # keeps track of the vertices already visited
  part := [];  # keeps track of the part of the tree, that vertex i is in

  i := x![2];  # nr of vertices
  while i > 0 do
    temp_word := [];
    j := i;
    while not IsBound(pos[j]) and not IsBound(stop_start[j]) do
      Add(temp_word, InvertGenerator(gen[j]));
      j := is_a_child_of[j];
    od;
    temp_word := Concatenation(List(Reversed(temp_word), InvertGenerator),
                               temp_word);
    if IsBound(stop_start[j]) and not IsBound(words[stop_start[j]]) then
      # first time in this part of the tree
      words[stop_start[j]] := temp_word;
      part[j] := stop_start[j];
      pos[j] := 0;
    else  # been in this part before
      words[part[j]] := Concatenation(words[part[j]]{[1 .. pos[j]]},
                                      temp_word,
                                      words[part[j]]{[pos[j] + 1 ..
                                                      Length(words[part[j]])]});
    fi;
    i := i - 1;
  od;

  out := [];
  path := Reversed(path);

  names := FamilyObj(x)!.names;

  for i in path do
    Append(out, List(words[stop_start[i]], l -> Concatenation(names[l], "*")));
    if i + 1 <= Length(path) then
      Add(out, Concatenation(names[gen[path[i + 1]]], "*"));
    fi;
  od;

  out := Concatenation(out);
  if Last(out) = '*' then
    Remove(out);
  fi;

  return out;
end);

##############################################################################
##
## CanonicalForm( s )
##
##

InstallMethod(CanonicalForm, "for a free inverse semigroup element",
[IsFreeInverseSemigroupElement],
function(tree)
  local InvertGenerator, children, fork, maxleftreducedpath,
  maxleftreduced, groupelem, i, mlr, output, pivot;

  InvertGenerator := SEMIGROUPS.InvertGenerator;

  children := function(n)
    local list, i;

    list := [];
    for i in [1 .. Length(tree![4])] do
      if tree![4][i] = n then
        Add(list, i);
      fi;
    od;
    return list;
  end;

  fork := function(list1, list2)
    local i, result;

    result := [];
    for i in list2 do
      Add(result, Concatenation(list1, [i]));
    od;
    return result;
  end;

  maxleftreducedpath := fork([], children(1));
  for pivot in maxleftreducedpath do
    while children(Last(pivot)) <> [] do
      maxleftreducedpath := fork(pivot, children(Last(pivot)));
      Add(pivot, Last(children(Last(pivot))));
    od;
  od;

  maxleftreduced := [];
  for i in [1 .. Length(maxleftreducedpath)] do
    maxleftreduced[i] := List(maxleftreducedpath[i], x -> tree![5][x]);
    maxleftreduced[i] := Concatenation(maxleftreduced[i],
                                       Reversed(List(maxleftreduced[i],
                                                     InvertGenerator)));
  od;

  groupelem := [];
  i := tree![3];
  while i <> 1 do
    Add(groupelem, i);
    i := tree![4][i];
  od;
  groupelem := Reversed(List(groupelem, x -> tree![5][x]));

  mlr := maxleftreduced;
  if Length(mlr) = 1 and Length(mlr[1]) = 2 and Length(groupelem) > 0 and
      ((mlr[1][1] mod 2 = 1 and mlr[1][2] = mlr[1][1] + 1) or
       (mlr[1][1] mod 2 = 0 and mlr[1][2] = mlr[1][1] - 1)) then
    output := Concatenation(List(groupelem, x -> FamilyObj(tree)!.names[x]));
  else
    output :=
          Concatenation(List(Concatenation(Concatenation(Set(mlr)), groupelem),
                             x -> FamilyObj(tree)!.names[x]));
  fi;
  return output;
end);

##############################################################################
##
## Equality
##

InstallMethod(\=, "for elements of a free inverse semigroup",
IsIdenticalObj,
[IsFreeInverseSemigroupElement, IsFreeInverseSemigroupElement],
function(tree1, tree2)
  local isequal, i;

  isequal := true;
  for i in [1 .. 5 + tree1![2]] do
    if tree1![i] <> tree2![i] then
      isequal := false;
      break;
    fi;
  od;

  if not isequal then
    isequal := CanonicalForm(tree1) = CanonicalForm(tree2);
  fi;
  return isequal;
end);

InstallMethod(\<, "for elements of a free inverse semigroup",
IsIdenticalObj,
[IsFreeInverseSemigroupElement, IsFreeInverseSemigroupElement],
{tree1, tree2} -> CanonicalForm(tree1) < CanonicalForm(tree2));

InstallMethod(ChooseHashFunction, "for a free inverse semigroup element",
[IsFreeInverseSemigroupElement, IsInt],
  function(x, hashlen)
  local sample, record, func;
  sample := List(CanonicalForm(x), IntChar);
  record := ChooseHashFunction(sample, hashlen);
  func := {x, data} -> record.func(List(CanonicalForm(x), IntChar), data);
  return rec(func := func, data := record.data);
end);

##############################################################################
##
## Multiplication
##

InstallMethod(\*, "for elements of a free inverse semigroup",
IsIdenticalObj,
[IsFreeInverseSemigroupElement, IsFreeInverseSemigroupElement],
function(tree1, tree2)
  local new_names, product, i, parent, InvertGenerator;

  InvertGenerator := SEMIGROUPS.InvertGenerator;

  new_names    := [];
  new_names[1] := tree1![3];

  # product := StructuralCopy(tree1);
  product := [];
  for i in [1 .. tree1![2] + 5] do
    product[i] := ShallowCopy(tree1![i]);
  od;

  for i in [2 .. tree2![2]] do
    parent := new_names[tree2![4][i]];
    if parent <= tree1![2] and IsBound(tree1![parent + 5][tree2![5][i]]) then
      new_names[i] := tree1![parent + 5][tree2![5][i]];
    else
      product[2] := product[2] + 1;
      new_names[i] := product[2];
      product[4][product[2]] := parent;
      product[5][product[2]] := tree2![5][i];
      product[product[2] + 5] := [];
      product[product[2] + 5][InvertGenerator(tree2![5][i])] := parent;
      product[parent + 5][tree2![5][i]] := product[2];
    fi;

  od;
  product[3] := new_names[tree2![3]];
  return Objectify(TypeObj(tree1), product);
end);

##############################################################################
##
## Inverse
##

InstallMethod(\^, "for elements of a free inverse semigroup",
[IsFreeInverseSemigroupElement, IsNegInt],
function(tree, n)
  local product, old_names, new_names, label, current_old, result, i, j;

  product := [];
  product[1] := tree![1];
  product[2] := tree![2];
  old_names := [];
  old_names[1] := tree![3];
  new_names := [];
  new_names[tree![3]] := 1;
  product[4] := [];
  product[5] := [];

  label := 2;

  for i in [1 .. tree![2]] do
    product[5 + i] := [];
    for j in [1 .. 2 * tree![1]] do
      if IsBound(tree![old_names[i] + 5][j]) then
        current_old := tree![old_names[i] + 5][j];
        if not IsBound(new_names[current_old]) then
          old_names[label] := current_old;
          new_names[current_old] := label;
          product[4][new_names[current_old]] := i;
          product[5][new_names[current_old]] := j;
          label := label + 1;
        fi;
        product[5 + i][j] := new_names[current_old];
      fi;
    od;
  od;

  product[3] := new_names[1];
  product[4][1] := fail;
  product[5][1] := fail;

  result := Objectify(TypeObj(tree), product);
  return result ^ (-n);
end);

###########################################################################
##
## Size
##

InstallMethod(Size, "for a free inverse semigroup",
[IsFreeInverseSemigroupCategory], S -> infinity);

InstallMethod(IsFreeInverseSemigroup, "for a semigroup",
[IsSemigroup],
function(s)
  local gens, occurs, used, list, g, i;

  if not IsInverseSemigroup(s) then
    return false;
  elif IsFreeInverseSemigroupElementCollection(s) then
    gens := Generators(s);
    occurs := BlistList([1 .. Length(FamilyObj(gens[1])!.names) / 2], []);
    used := BlistList([1 .. Length(FamilyObj(gens[1])!.names) / 2], []);
    for g in gens do
      list := g![5];
      for i in [2 .. Length(list)] do
        used[Int((list[i] + 1) / 2)] := true;
      od;
      if g![2] = 2 then
        occurs[Int((g![5][2] + 1) / 2)] := true;
      fi;
    od;

    if occurs = used then
      return true;
    fi;
  fi;

  ErrorNoReturn("cannot determine the answer");
end);

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