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


Quelle  bipart.gi   Sprache: unbekannt

 
############################################################################
##
##  elements/bipart.gi
##  Copyright (C) 2013-2022                              James D. Mitchell
##
##  Licensing information can be found in the README file of this package.
##
#############################################################################
##

#############################################################################
# Family and type.
#
# One per degree to avoid lists with bipartitions of different degrees
# belonging to IsAssociativeElementCollection.
#############################################################################

BindGlobal("TYPES_BIPART", []);
BindGlobal("TYPE_BIPART",
function(n)
  local fam, type;

  n := n + 1;  # since the degree can be 0

  if IsBound(TYPES_BIPART[n]) then
    return TYPES_BIPART[n];
  fi;

  fam := NewFamily(Concatenation("BipartitionFamily", String(n - 1)),
                   IsBipartition,
                   CanEasilySortElements,
                   CanEasilySortElements);

  type := NewType(fam,
                  IsBipartition and IsInternalRep);
  TYPES_BIPART[n] := type;
  return type;
end);

#############################################################################
# Pickler
#############################################################################

InstallMethod(IO_Pickle, "for a bipartition",
[IsFile, IsBipartition],
function(file, x)
  if IO_Write(file, "BIPA") = fail then
    return IO_Error;
  fi;
  return IO_Pickle(file, IntRepOfBipartition(x));
end);

IO_Unpicklers.BIPA := function(file)
  local blocks;

  blocks := IO_Unpickle(file);
  if blocks = IO_Error then
    return IO_Error;
  fi;
  return BIPART_NC(blocks);
end;

#############################################################################
# Implications
#############################################################################

InstallTrueMethod(IsPermBipartition, IsTransBipartition
                                     and IsDualTransBipartition);

InstallTrueMethod(IsBlockBijection, IsPermBipartition);

#############################################################################
# GAP level - directly using interface to C/C++ level
#############################################################################

# Fundamental attributes

InstallMethod(DegreeOfBipartition, "for a bipartition",
[IsBipartition], BIPART_DEGREE);

InstallMethod(NrBlocks, "for a bipartition",
[IsBipartition], BIPART_NR_BLOCKS);

InstallMethod(NrLeftBlocks, "for a bipartition",
[IsBipartition], BIPART_NR_LEFT_BLOCKS);

InstallMethod(RankOfBipartition, "for a bipartition",
[IsBipartition], x -> BIPART_RANK(x, 0));

# Constructors

InstallGlobalFunction(Bipartition,
function(classes)
  local n, copy, i, j;

  if not IsList(classes)
      or ForAny(classes, x -> not IsHomogeneousList(x)
                              or not IsDuplicateFree(x)) then
    ErrorNoReturn("the argument does not consist of duplicate-free ",
                  "homogeneous lists");
  fi;

  n := Sum(classes, Length) / 2;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the maximum degree of a bipartition is 2 ^ 29 - 1");
  elif not ForAll(classes, x -> ForAll(x,
                                       i -> (IsPosInt(i) or IsNegInt(i))
                                            and AbsInt(i) <= n)) then
    ErrorNoReturn("the argument does not consist of lists of ",
                  "integers from [-", n, " .. -1, 1 .. ", n, "]");
  elif not IsEmpty(classes)
      and Union(classes) <> Concatenation([-n .. -1], [1 .. n]) then
    ErrorNoReturn("the union of the argument <classes> is not ",
                  "[-", n, " .. -1, 1 .. ", n, "]");
  fi;

  copy := List(classes, ShallowCopy);
  for i in [1 .. Length(copy)] do
    for j in [1 .. Length(copy[i])] do
      if copy[i][j] < 0 then
        copy[i][j] := AbsInt(copy[i][j]) + n;
      fi;
    od;
  od;

  Perform(copy, Sort);
  Sort(copy);

  for i in [1 .. Length(copy)] do
    for j in [1 .. Length(copy[i])] do
      if copy[i][j] > n then
        copy[i][j] := -copy[i][j] + n;
      fi;
    od;
  od;
  return BIPART_NC(copy);
end);

InstallMethod(BipartitionByIntRep, "for a list", [IsHomogeneousList],
function(blocks)
  local n, next, seen, i;
  n := Length(blocks);
  if not IsEvenInt(n) then
    ErrorNoReturn("the degree of a bipartition must be even, found ", n);
  elif n >= 2 ^ 30 then
    ErrorNoReturn("the length of the argument (a list) exceeds ",
                  "2 ^ 30 - 1");
  elif not (IsEmpty(blocks) or IsPosInt(blocks[1])) then
    ErrorNoReturn("the items in the argument (a list) must be positive ",
                  "integers");
  fi;

   next := 0;
   seen := BlistList([1 .. Maximum(blocks)], []);

   for i in [1 .. n] do
     if not seen[blocks[i]] then
       next := next + 1;
       if blocks[i] <> next then
         ErrorNoReturn("expected ", next, " but found ", blocks[i],
                       ", in position ", i);
       fi;
       seen[blocks[i]] := true;
    fi;
  od;

  return BIPART_NC(blocks);
end);

InstallMethod(IdentityBipartition, "for zero", [IsZeroCyc],
_ -> Bipartition([]));

InstallMethod(IdentityBipartition, "for a positive integer", [IsPosInt],
function(n)
  local blocks, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the argument (a pos. int) must not exceed 2 ^ 29 - 1");
  fi;
  blocks := EmptyPlist(2 * n);

  for i in [1 .. n] do
    blocks[i] := i;
    blocks[i + n] := i;
  od;

  return BIPART_NC(blocks);
end);

InstallMethod(RandomBipartition, "for a random source and pos int",
[IsRandomSource, IsPosInt],
function(rs, n)
  local out, nrblocks, vals, j, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the argument (a pos. int.) must not exceed 2 ^ 29 - 1");
  fi;
  out := EmptyPlist(2 * n);
  nrblocks := 0;
  vals := [1];

  for i in [1 .. 2 * n] do
    j := Random(rs, vals);
    if j = nrblocks + 1 then
      nrblocks := nrblocks + 1;
      Add(vals, nrblocks + 1);
    fi;
    out[i] := j;
  od;

  return BIPART_NC(out);
end);

InstallMethod(RandomBipartition, "for a pos int", [IsPosInt],
n -> RandomBipartition(GlobalMersenneTwister, n));

InstallMethod(RandomBlockBijection, "for a random source and pos int",
[IsRandomSource, IsPosInt],
function(rs, n)
  local out, nrblocks, j, free, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the argument (a pos. int.) must not exceed 2 ^ 29 - 1");
  fi;

  out := EmptyPlist(2 * n);
  out[1] := 1;
  nrblocks := 1;

  for i in [2 .. n] do
    j := Random(rs, [1 .. nrblocks + 1]);
    if j = nrblocks + 1 then
      nrblocks := nrblocks + 1;
    fi;
    out[i] := j;
  od;

  free := [n + 1 .. 2 * n];
  for i in [1 .. nrblocks] do
    j := Random(rs, free);
    out[j] := i;
    RemoveSet(free, j);
  od;

  for i in free do
    out[i] := Random(rs, [1 .. nrblocks]);
  od;

  return BIPART_NC(out);
end);

InstallMethod(RandomBlockBijection, "for a pos int", [IsPosInt],
n -> RandomBlockBijection(GlobalMersenneTwister, n));

# Operators

InstallMethod(PermLeftQuoBipartition, "for a bipartition and bipartition",
IsIdenticalObj, [IsBipartition, IsBipartition],
function(x, y)

  if LeftBlocks(x) <> LeftBlocks(y) or RightBlocks(x) <> RightBlocks(y) then
    ErrorNoReturn("the arguments (bipartitions) do not have equal left ",
                  "and right blocks");
  fi;
  return BIPART_PERM_LEFT_QUO(x, y);
end);

# Attributes

InstallMethod(DomainOfBipartition, "for a bipartition", [IsBipartition],
function(x)
  local out;
  out := [];
  for x in ExtRepOfObj(LeftBlocks(x)) do
    if IsPosInt(x[1]) then
      Append(out, x);
    fi;
  od;
  return out;
end);

InstallMethod(CodomainOfBipartition, "for a bipartition", [IsBipartition],
function(x)
  local out;
  out := [];
  for x in ExtRepOfObj(RightBlocks(x)) do
    if IsPosInt(x[1]) then
      Append(out, -x);
    fi;
  od;
  return out;
end);

InstallMethod(ExtRepOfObj, "for a bipartition", [IsBipartition],
BIPART_EXT_REP);

InstallMethod(IntRepOfBipartition, "for a bipartition", [IsBipartition],
BIPART_INT_REP);

# xx ^ * - linear - 2 * degree

InstallMethod(LeftProjection, "for a bipartition", [IsBipartition],
BIPART_LEFT_PROJ);

InstallMethod(RightProjection, "for a bipartition", [IsBipartition],
BIPART_RIGHT_PROJ);

# linear - 2 * degree

InstallMethod(StarOp, "for a bipartition", [IsBipartition], BIPART_STAR);

InstallMethod(ChooseHashFunction, "for a bipartition",
[IsBipartition, IsInt],
{_, hashlen} -> rec(func := BIPART_HASH, data := hashlen));

#############################################################################
# GAP level
#############################################################################

# Attributes

# not a synonym since NrTransverseBlocks also applies to blocks

InstallMethod(NrTransverseBlocks, "for a bipartition", [IsBipartition],
RankOfBipartition);

InstallMethod(NrRightBlocks, "for a bipartition", [IsBipartition],
x -> NrBlocks(x) - NrLeftBlocks(x) + NrTransverseBlocks(x));

InstallMethod(OneMutable, "for a bipartition",
[IsBipartition], x -> IdentityBipartition(DegreeOfBipartition(x)));

InstallMethod(OneMutable, "for a bipartition collection",
[IsBipartitionCollection], x ->
IdentityBipartition(DegreeOfBipartitionCollection(x)));

# the Other is to avoid warning on opening GAP

InstallOtherMethod(InverseMutable, "for a bipartition", [IsBipartition],
function(x)
  if IsBlockBijection(x) or IsPartialPermBipartition(x) then
    return Star(x);
  fi;
  return fail;
end);

# Properties

InstallMethod(IsBlockBijection, "for a bipartition",
[IsBipartition],
x -> NrBlocks(x) = NrLeftBlocks(x) and NrRightBlocks(x) = NrLeftBlocks(x));

InstallMethod(IsPartialPermBipartition, "for a bipartition",
[IsBipartition],
function(x)
  return NrLeftBlocks(x) = DegreeOfBipartition(x)
    and NrRightBlocks(x) = DegreeOfBipartition(x);
end);

# a bipartition is a transformation if and only if the second row is a
# permutation of [1 .. n], where n is the degree.

InstallMethod(IsTransBipartition, "for a bipartition",
[IsBipartition],
function(x)
  return NrLeftBlocks(x) = NrTransverseBlocks(x)
   and NrRightBlocks(x) = DegreeOfBipartition(x);
end);

InstallMethod(IsDualTransBipartition, "for a bipartition", [IsBipartition],
function(x)
  return NrRightBlocks(x) = NrTransverseBlocks(x)
   and NrLeftBlocks(x) = DegreeOfBipartition(x);
end);

InstallMethod(IsPermBipartition, "for a bipartition",
[IsBipartition],
function(x)
  return IsPartialPermBipartition(x)
    and NrTransverseBlocks(x) = DegreeOfBipartition(x);
end);

# Fundamental operators

InstallMethod(\*, "for a bipartition and a perm",
[IsBipartition, IsPerm],
function(x, p)
  if LargestMovedPoint(p) <= DegreeOfBipartition(x) then
    return x * AsBipartition(p, DegreeOfBipartition(x));
  fi;
  ErrorNoReturn("the largest moved point of the 2nd argument ",
                "(a permutation) exceeds",
                " the degree of the 1st argument (a bipartition)");
end);

InstallMethod(\*, "for a perm and a bipartition",
[IsPerm, IsBipartition],
function(p, x)
  if LargestMovedPoint(p) <= DegreeOfBipartition(x) then
    return AsBipartition(p, DegreeOfBipartition(x)) * x;
  fi;
  ErrorNoReturn("the largest moved point of the 1st argument ",
                "(a permutation) exceeds",
                " the degree of the 2nd argument (a bipartition)");
end);

InstallMethod(\*, "for a bipartition and a transformation",
[IsBipartition, IsTransformation],
function(x, f)
  if DegreeOfTransformation(f) <= DegreeOfBipartition(x) then
    return x * AsBipartition(f, DegreeOfBipartition(x));
  fi;
  ErrorNoReturn("the degree of the 2nd argument (a transformation)",
                " exceeds the degree of the 1st argument",
                " (a bipartition)");
end);

InstallMethod(\*, "for a transformation and a bipartition",
[IsTransformation, IsBipartition],
function(f, g)
  if DegreeOfTransformation(f) <= DegreeOfBipartition(g) then
    return AsBipartition(f, DegreeOfBipartition(g)) * g;
  fi;
  ErrorNoReturn("the degree of the 1st argument (a transformation)",
                " exceeds the degree of the 2nd argument",
                " (a bipartition)");
end);

InstallMethod(\*, "for a bipartition and a partial perm",
[IsBipartition, IsPartialPerm],
function(f, g)
  local n;
  n := DegreeOfBipartition(f);
  if ForAll([1 .. n], i -> i ^ g <= n) then
    return f * AsBipartition(g, DegreeOfBipartition(f));
  fi;
  ErrorNoReturn("the 2nd argument (a partial perm) does not map ",
                "[1 .. ", String(n), "] into [1 .. ", String(n), "]");
end);

InstallMethod(\*, "for a partial perm and a bipartition",
[IsPartialPerm, IsBipartition],
function(f, g)
  local n;
  n := DegreeOfBipartition(g);
  if ForAll([1 .. n], i -> i ^ f <= n) then
    return AsBipartition(f, DegreeOfBipartition(g)) * g;
  fi;
  ErrorNoReturn("the 1st argument (a partial perm) does not map [1 .. ",
                String(n), "] into [1 .. ", String(n), "]");
end);

InstallMethod(\^, "for a bipartition and permutation",
[IsBipartition, IsPerm],
{f, p} -> p ^ -1 * f * p);

# Other operators

InstallMethod(PartialPermLeqBipartition, "for a bipartition and a bipartition",
IsIdenticalObj, [IsBipartition, IsBipartition],
function(x, y)
  if not (IsPartialPermBipartition(x) and IsPartialPermBipartition(y)) then
    ErrorNoReturn("the arguments (bipartitions) do not both satisfy ",
                  "IsPartialPermBipartition");
  fi;

  return AsPartialPerm(x) < AsPartialPerm(y);
end);

# Changing representations

InstallMethod(AsBipartition, "for a permutation and zero",
[IsPerm, IsZeroCyc],
{f, n} -> Bipartition([]));

InstallMethod(AsBipartition, "for a permutation",
[IsPerm], x -> AsBipartition(x, LargestMovedPoint(x)));

InstallMethod(AsBipartition, "for a partial perm",
[IsPartialPerm],
function(x)
  return AsBipartition(x, Maximum(DegreeOfPartialPerm(x),
                                  CodegreeOfPartialPerm(x)));
end);

InstallMethod(AsBipartition, "for a partial perm and zero",
[IsPartialPerm, IsZeroCyc],
{f, n} -> Bipartition([]));

InstallMethod(AsBipartition, "for a transformation",
[IsTransformation], x -> AsBipartition(x, DegreeOfTransformation(x)));

InstallMethod(AsBipartition, "for a transformation and zero",
[IsTransformation, IsZeroCyc],
{f, n} -> Bipartition([]));

InstallMethod(AsBipartition, "for a bipartition", [IsBipartition], IdFunc);

InstallMethod(AsBipartition, "for a bipartition", [IsBipartition, IsZeroCyc],
{f, n} -> Bipartition([]));

InstallMethod(AsBipartition, "for a pbr and pos int",
[IsPBR, IsZeroCyc],
{x, deg} -> Bipartition([]));

InstallMethod(AsBipartition, "for a pbr and pos int",
[IsPBR, IsPosInt],
function(x, deg)
  if not IsBipartitionPBR(x) then
    ErrorNoReturn("the 1st argument (a pbr) does not satisfy",
                  " 'IsBipartitionPBR'");
  fi;

  return AsBipartition(AsBipartition(x), deg);
end);

InstallMethod(AsBipartition, "for a pbr",
[IsPBR],
function(x)
  if not IsBipartitionPBR(x) then
    ErrorNoReturn("the argument (a pbr) does not satisfy 'IsBipartitionPBR'");
  fi;
  return Bipartition(Union(ExtRepOfObj(x)));
end);

InstallMethod(AsBlockBijection, "for a partial perm",
[IsPartialPerm],
function(x)
  return AsBlockBijection(x, Maximum(DegreeOfPartialPerm(x),
                                     CodegreeOfPartialPerm(x)) + 1);
end);

# Viewing, printing etc

InstallMethod(ViewString, "for a bipartition",
[IsBipartition],
function(x)
  local str, ext, i;

  if DegreeOfBipartition(x) = 0 then
    return "\><empty bipartition>\<";
  elif IsBlockBijection(x) then
    str := "\>\><block bijection:\< ";
  else
    str := "\>\><bipartition:\< ";
  fi;

  ext := ExtRepOfObj(x);
  Append(str, "\>");
  Append(str, String(ext[1]));
  Append(str, "\<");

  for i in [2 .. Length(ext)] do
    Append(str, ", \>");
    Append(str, String(ext[i]));
    Append(str, "\<");
  od;
  Append(str, ">\<");
  return str;
end);

InstallMethod(String, "for a bipartition", [IsBipartition],
x -> Concatenation("Bipartition(", String(ExtRepOfObj(x)), ")"));

InstallMethod(PrintString, "for a bipartition",
[IsBipartition],
function(x)
  local ext, str, i;
  if DegreeOfBipartition(x) = 0 then
    return "\>\>Bipartition(\< \>[]\<)\<";
  fi;
  ext := ExtRepOfObj(x);
  str := Concatenation("\>\>Bipartition(\< \>[ ", PrintString(ext[1]));
  for i in [2 .. Length(ext)] do
    Append(str, ",\< \>");
    Append(str, PrintString(ext[i]));
  od;
  Append(str, " \<]");
  Append(str, " )\<");
  return str;
end);

InstallMethod(PrintString, "for a bipartition collection",
[IsBipartitionCollection],
function(coll)
  local str, i;

  if IsGreensClass(coll) or IsSemigroup(coll) then
    TryNextMethod();
  fi;

  str := "\>[ ";
  for i in [1 .. Length(coll)] do
    if i <> 1 then
      Append(str, " ");
    fi;
    Append(str, "\>");
    Append(str, PrintString(coll[i]));
    if i <> Length(coll) then
      Append(str, ",\<\n");
    else
      Append(str, " ]\<\n");
    fi;
  od;
  return str;
end);

# Bipartition collections

InstallMethod(DegreeOfBipartitionCollection, "for a bipartition semigroup",
[IsBipartitionSemigroup], DegreeOfBipartitionSemigroup);

InstallMethod(DegreeOfBipartitionCollection, "for a bipartition collection",
[IsBipartitionCollection],
{coll} -> DegreeOfBipartition(coll[1]));

#############################################################################
# All of the methods in this section could be done in C/C++
#############################################################################

# Change representations . . .

InstallMethod(AsBipartition, "for a permutation and pos int",
[IsPerm, IsPosInt],
function(x, n)
  if n >= 2 ^ 29 then
    ErrorNoReturn("the 2nd argument (a pos. int.) exceeds 2 ^ 29 - 1");
  elif OnSets([1 .. n], x) <> [1 .. n] then
    ErrorNoReturn("the 1st argument (a permutation) does not permute ",
                  "[1 .. ", String(n), "]");
  fi;
  return BIPART_NC(Concatenation([1 .. n], ListPerm(x ^ -1, n)));
end);

InstallMethod(AsPartialPerm, "for a bipartition", [IsBipartition],
function(x)
  local n, blocks, nrleft, im, out, i;

  if not IsPartialPermBipartition(x) then
    ErrorNoReturn("the argument (a bipartition) does not define ",
                  "a partial perm");
  fi;

  n      := DegreeOfBipartition(x);
  blocks := IntRepOfBipartition(x);
  nrleft := NrLeftBlocks(x);
  im     := [1 .. n] * 0;

  for i in [n + 1 .. 2 * n] do
    if blocks[i] <= nrleft then
      im[blocks[i]] := i - n;
    fi;
  od;

  out := EmptyPlist(n);
  for i in [1 .. n] do
    out[i] := im[blocks[i]];
  od;
  return PartialPermNC(out);
end);

InstallMethod(AsPermutation, "for a bipartition", [IsBipartition],
function(x)
  local n, blocks, im, out, i;

  if not IsPermBipartition(x) then
    ErrorNoReturn("the argument (a bipartition) does not define a ",
                  "permutation");
  fi;

  n      := DegreeOfBipartition(x);
  blocks := IntRepOfBipartition(x);
  im     := EmptyPlist(n);

  for i in [n + 1 .. 2 * n] do
    im[blocks[i]] := i - n;
  od;

  out := EmptyPlist(n);
  for i in [1 .. n] do
    out[i] := im[blocks[i]];
  od;
  return PermList(out);
end);

InstallMethod(AsTransformation, "for a bipartition", [IsBipartition],
function(x)
  local n, blocks, nr, im, out, i;

  if not IsTransBipartition(x) then
    ErrorNoReturn("the argument (a bipartition) does not define a ",
                  "transformation");
  fi;

  n      := DegreeOfBipartition(x);
  blocks := IntRepOfBipartition(x);
  nr     := NrLeftBlocks(x);
  im     := EmptyPlist(n);

  for i in [n + 1 .. 2 * n] do
    if blocks[i] <= nr then
      im[blocks[i]] := i - n;
    fi;
  od;

  out := EmptyPlist(n);
  for i in [1 .. n] do
    out[i] := im[blocks[i]];
  od;
  return TransformationNC(out);
end);

InstallMethod(AsBipartition, "for a partial perm and pos int",
[IsPartialPerm, IsPosInt],
function(x, n)
  local r, out, y, j, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the 2nd argument (a pos. int.) exceeds 2 ^ 29 - 1");
  fi;

  r   := n;
  out := EmptyPlist(2 * n);
  y   := x ^ -1;

  for i in [1 .. n] do
    out[i] := i;
    j      := i ^ y;
    if j <> 0 then
      out[n + i] := j;
    else
      r          := r + 1;
      out[n + i] := r;
    fi;
  od;
  return BIPART_NC(out);
end);

InstallMethod(AsBipartition, "for a transformation and a positive integer",
[IsTransformation, IsPosInt],
function(f, n)
  local r, ker, out, g, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the 2nd argument (a pos. int.) exceeds 2 ^ 29 - 1");
  elif n < DegreeOfTransformation(f) then
    # Verify f is a transformation on [1 .. n].
    for i in [1 .. n] do
      if i ^ f > n then
        ErrorNoReturn("the 1st argument (a transformation) does not map [1 .. ",
                      String(n), "] to itself");
      fi;
    od;
  fi;

  r := RankOfTransformation(f, n);
  ker := FlatKernelOfTransformation(f, n);

  out := EmptyPlist(2 * n);
  g := List([1 .. n], x -> 0);

  # The inverse of f.
  for i in [1 .. n] do
    g[i ^ f] := i;
  od;

  for i in [1 .. n] do
    out[i] := ker[i];
    if g[i] <> 0 then
      out[n + i] := ker[g[i]];
    else
      r := r + 1;
      out[n + i] := r;
    fi;
  od;
  return BIPART_NC(out);
end);

InstallMethod(AsBipartition, "for a bipartition and pos int",
[IsBipartition, IsPosInt],
function(f, n)
  local deg, blocks, out, nrblocks, nrleft, lookup, j, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the 2nd argument (a pos. int.) exceeds 2 ^ 29 - 1");
  fi;
  deg := DegreeOfBipartition(f);
  if n = deg then
    return f;
  fi;
  blocks := IntRepOfBipartition(f);
  out := [];
  nrblocks := 0;

  if n < deg then
    for i in [1 .. n] do
      out[i] := blocks[i];
      if out[i] > nrblocks then
        nrblocks := nrblocks + 1;
      fi;
    od;
    nrleft := nrblocks;
    lookup := EmptyPlist(NrBlocks(f));
    for i in [n + 1 .. 2 * n] do
      j := blocks[i + deg - n];
      if j > nrleft then
        if not IsBound(lookup[j]) then
          nrblocks := nrblocks + 1;
          lookup[j] := nrblocks;
        fi;
        j := lookup[j];
      fi;
      out[i] := j;
    od;
  else  # n > deg
    for i in [1 .. deg] do
      out[i] := blocks[i];
    od;
    nrblocks := NrLeftBlocks(f);
    for i in [deg + 1 .. n] do
      nrblocks := nrblocks + 1;
      out[i] := nrblocks;
    od;
    nrleft := nrblocks;  # = n - deg + NrLeftBlocks(f)
    for i in [n + 1 .. n + deg] do
      if blocks[i - n + deg] <= nrleft - n + deg then  # it's a left block
        out[i] := blocks[i - n + deg];
      else
        out[i] := blocks[i - n + deg] + n - deg;
      fi;
    od;
    nrblocks := NrBlocks(f) + n - deg;
    for i in [n + deg + 1 .. 2 * n] do
      nrblocks := nrblocks + 1;
      out[i] := nrblocks;
    od;
  fi;
  return BIPART_NC(out);
end);

# same as AsBipartition except that all undefined points are in a single block
# together with an extra (pair of) points.

InstallMethod(AsBlockBijection, "for a partial perm and pos int",
[IsPartialPerm, IsPosInt],
function(f, n)
  local bigblock, nr, out, i;

  if n >= 2 ^ 29 then
    ErrorNoReturn("the 2nd argument (a pos. int.) exceeds 2 ^ 29 - 1");
  elif n <= Maximum(DegreeOfPartialPerm(f), CodegreeOfPartialPerm(f)) then
    ErrorNoReturn("the 2nd argument (a pos. int.) is less than or equal to ",
                  "the maximum of the degree and codegree of the ",
                  "1st argument (a partial perm)");
  fi;

  nr := 0;
  out := [1 .. 2 * n] * 0;
  bigblock := n;

  for i in [1 .. n - 1] do
    if i ^ f = 0 then
      if bigblock = n then
        nr := nr + 1;
        bigblock := nr;
      fi;
      out[i] := bigblock;
    else
      nr := nr + 1;
      out[i] := nr;
      out[n + i ^ f] := nr;
    fi;
  od;

  out[n] := bigblock;
  out[2 * n] := bigblock;

  for i in [n + 1 .. 2 * n - 1] do
    if out[i] = 0 then
      out[i] := bigblock;
    fi;
  od;

  return BIPART_NC(out);
end);

InstallMethod(AsBlockBijection, "for a bipartition and pos int",
[IsBipartition, IsPosInt],
function(x, n)
  if not IsPartialPermBipartition(x) then
    ErrorNoReturn("the 1st argument (a bipartition) is not a ",
                  "partial perm bipartition");
  fi;
  return AsBlockBijection(AsPartialPerm(x), n);
end);

InstallMethod(AsBlockBijection, "for a bipartition",
[IsBipartition],
function(x)
  if not IsPartialPermBipartition(x) then
    ErrorNoReturn("the argument (a bipartion) does not satisfy ",
                  "IsPartialPermBipartition");
  fi;
  return AsBlockBijection(AsPartialPerm(x));
end);

InstallMethod(NaturalLeqBlockBijection, "for a bipartition and bipartition",
IsIdenticalObj, [IsBipartition, IsBipartition],
function(x, y)
  local xblocks, yblocks, n, lookup, i;

  if not IsBlockBijection(x) or not IsBlockBijection(y) then
    ErrorNoReturn("the arguments (bipartitions) are not block bijections");
  elif NrBlocks(x) > NrBlocks(y) then
    return false;
  fi;

  xblocks := IntRepOfBipartition(x);
  yblocks := IntRepOfBipartition(y);
  n       := DegreeOfBipartition(x);

  lookup := [];
  for i in [1 .. n] do
    if IsBound(lookup[yblocks[i]]) and lookup[yblocks[i]] <> xblocks[i] then
      return false;
    else
      lookup[yblocks[i]] := xblocks[i];
    fi;
  od;
  for i in [n + 1 .. 2 * n] do
    if lookup[yblocks[i]] <> xblocks[i] then
      return false;
    fi;
  od;
  return true;
end);

InstallMethod(NaturalLeqPartialPermBipartition,
"for a bipartition and bipartition",
IsIdenticalObj, [IsBipartition, IsBipartition],
function(x, y)
  local n, xblocks, yblocks, val, i;

  if not IsPartialPermBipartition(x) or not IsPartialPermBipartition(y) then
    ErrorNoReturn("the arguments (bipartitions) are not partial perm ",
                  "bipartitions");
  fi;

  n := DegreeOfBipartition(x);

  xblocks := IntRepOfBipartition(x);
  yblocks := IntRepOfBipartition(y);

  for i in [n + 1 .. 2 * n] do
    val := xblocks[i];
    if val <= n and val <> yblocks[i] then
      return false;
    fi;
  od;
  return true;
end);

InstallMethod(IsUniformBlockBijection, "for a bipartition",
[IsBipartition],
function(x)
  local blocks, n, sizesleft, sizesright, i;

  if not IsBlockBijection(x) then
    return false;
  fi;

  blocks := IntRepOfBipartition(x);
  n := DegreeOfBipartition(x);
  sizesleft := [1 .. NrBlocks(x)] * 0;
  sizesright := [1 .. NrBlocks(x)] * 0;

  for i in [1 .. n] do
    sizesleft[blocks[i]] := sizesleft[blocks[i]] + 1;
  od;
  for i in [n + 1 .. 2 * n] do
    sizesright[blocks[i]] := sizesright[blocks[i]] + 1;
  od;
  for i in [1 .. NrBlocks(x)] do
    if sizesright[i] <> sizesleft[i] then
      return false;
    fi;
  od;

  return true;
end);

InstallMethod(IndexPeriodOfSemigroupElement, "for a bipartition",
[IsBipartition],
x -> SEMIGROUPS.IndexPeriodByRank(x, RankOfBipartition));

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