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


Quelle  cw-functions.gi   Sprache: unbekannt

 

# RegularCWMapToCWSubcomplex
################################################################################
############ Input: a strictly cellular map f: Y -> X of regular ###############
################### CW-complexes ###############################################
################################################################################
########### Output: the CW-subcomplex [X,S] corresponding to the ###############
################### image of f #################################################
################################################################################
InstallGlobalFunction(
    RegularCWMapToCWSubcomplex,
    function(f)
    local
        dim, src_bnd, S, i, j;

    dim:=EvaluateProperty(f!.source,"dimension")*1;
    src_bnd:=f!.source!.boundaries*1;
    S:=List([0..dim],x->[]);

    for i in [1..dim+1] do
        for j in [1..Length(src_bnd[i])] do
            Add(S[i],f!.mapping(i-1,j));
        od;
    od;
    
    return [ShallowCopy(f!.target),S];
end);

# CWSubcomplexToRegularCWMap
################################################################################
############ Input: a CW-subcomplex [X,S] ######################################
################################################################################
########### Output: the corresponding inclusion map f: Y -> X ##################
################################################################################
InstallGlobalFunction(
    CWSubcomplexToRegularCWMap,
    function(YS)
    local
        map, src, i, j, trg_cell;

    map:={i,j}->YS[2][i+1][j];

    src:=List([1..Length(Filtered(YS[2],y->y<>[]))+1],x->[]);
    src[1]:=List(YS[2][1],x->[1,0]);

    for i in [2..Length(src)-1] do
        for j in [1..Length(YS[2][i])] do
            trg_cell:=YS[1]!.boundaries[i][YS[2][i][j]]*1;
            trg_cell:=trg_cell{[2..trg_cell[1]+1]};
            trg_cell:=List(trg_cell,x->Position(YS[2][i-1],x));
            Add(trg_cell,Length(trg_cell),1);
            Add(src[i],trg_cell*1);
        od;
    od;

    return Objectify(
        HapRegularCWMap,
        rec(
            source:=RegularCWComplex(src),
            target:=ShallowCopy(YS[1]),
            mapping:=map
        )
    );
end);

# IntersectionCWSubcomplex
################################################################################
############ Input: two CW-subcomplexes [X,S], [X,S'] ##########################
################################################################################
########### Output: the CW-subcomplex [X,S''] corresponding to #################
################### their intersection #########################################
################################################################################
InstallGlobalFunction(
    IntersectionCWSubcomplex,
    function(XS_1,XS_2)
    local
        max, xs_1, xs_2, i, j;
    
    max:=Maximum(Length(XS_1[2]),Length(XS_2[2]));
    xs_1:=ShallowCopy(XS_1[2]);
    xs_2:=ShallowCopy(XS_2[2]);

    for i in [xs_1,xs_2] do
        if Length(i)<max then
            for j in [Length(i)+1..max] do
                Add(i,[]);
            od;
        fi;
    od;

    return[
        ShallowCopy(XS_1[1]),
        List(
            [1..max],
            x->Intersection(xs_1[x],xs_2[x])
        )
    ];
end);

# PathComponentsCWSubcomplex
################################################################################
############ Input: a CW-subcomplex [X,S] ######################################
################################################################################
########### Output: a list of CW-subcomplexes [[X,S1],...,[X,Sn]] ##############
################### arising as the path components of [X,S] ####################
################################################################################
InstallGlobalFunction(
    PathComponentsCWSubcomplex,
    function(XS)
    local   
        ccs, i, j, k, cell, int, l;

    ccs:=List(
        XS[2][1]*1,
        x->Concatenation(
            [[x]],
            List([2..Length(XS[2])],y->[])
        )
    );
    for i in [1..Length(ccs)] do
        for j in [2..Length(ccs[i])] do
            for k in [1..Length(XS[2][j])] do
                cell:=XS[1]!.boundaries[j][XS[2][j][k]]*1;
                cell:=cell{[2..cell[1]+1]};
                int:=Intersection(cell,ccs[i][j-1]);
                if int<>[] then
                    for l in [1..Length(cell)] do
                        Add(ccs[i][j-1],cell[l]);
                    od;
                    Add(ccs[i][j],XS[2][j][k]);
                fi;
            od;
        od;
    od;
    for i in [1..Length(ccs)] do
        for j in Filtered([1..Length(ccs)],x->x<>i) do
            if ccs[i]<>[] and ccs[j]<>[] then
                for k in [1..Length(ccs[i])] do
                    if ccs[j]<>[] then
                        if Intersection(ccs[i][k],ccs[j][k])<>[] then
                            for l in [1..Length(ccs[i])] do
                                ccs[i][l]:=Set(
                                    Concatenation(
                                        ccs[i][l],
                                        ccs[j][l]
                                    )
                                );
                            od;
                            ccs[j]:=[];
                        fi;
                    fi;
                od;
            fi;
        od;
    od;
    ccs:=Filtered(List(ccs,x->List(x,y->Set(y))),z->z<>[]);

    return List(ccs,x->[ShallowCopy(XS[1]),x]);
end);

# ClosureCWCell
################################################################################
############ Input: a CW-complex Y and two integers k>=0 & i>1 #################
################################################################################
########### Output: a CW-subcomplex [Y,S] corresponding to the #################
################### topological closure of the ith k-cell of Y #################
################################################################################
InstallGlobalFunction(
    ClosureCWCell,
    function(Y,k,i)
    local
        complex, clsr, l, m, bnd, n;

    complex:=Y!.boundaries*1;

    clsr:=List([1..k+1],x->[]);
    Add(clsr[k+1],i);
    
    for l in Reversed([2..k+1]) do
        for m in [1..Length(clsr[l])] do
            bnd:=[];
            for n in [2..Length(complex[l][clsr[l][m]])] do
                Add(bnd,complex[l][clsr[l][m]][n]);
            od;
            clsr[l-1]:=Union(clsr[l-1],bnd);
        od;
    od;

    return [RegularCWComplex(complex),clsr];
end);

# HAP_KK_AddCell
################################################################################
############ Input: a cell complex B, an integer k>=0 and lists of #############
################### positive integers b and c ##################################
################################################################################
########### Output: the cell complex B with an added k-cell whose ##############
################### boundary is specified by b and whose coboundary ############
################### is specified by c ##########################################
################################################################################
InstallGlobalFunction(
    HAP_KK_AddCell,
    function(B,k,b,c)
    local
        i;

    Add(b,Length(b),1);
    Add(B[k+1],b);
    
    for i in [1..Length(c)] do
        Add(B[k+2][c[i]],Length(B[k+1]));
        B[k+2][c[i]][1]:=B[k+2][c[i]][1]+1;
    od;
end);

# BarycentricallySubdivideCell
################################################################################
############ Input: an inclusion of cell complexes f:Z->Y and two integers #####
################### k>0 & n>=0 #################################################
################################################################################
########### Output: the regular CW-map f':Z'->Y' corresponding to the same #####
################### spaces but where the kth n-cell of Y has been ##############
################### barycentrically subdivided #################################
################################################################################
InstallGlobalFunction(
    BarycentricallySubdivideCell,
    function(f,n,k)

    local
        inc, Y, clsr, complex,
        Subdivide, i, j;

    inc:=RegularCWMapToCWSubcomplex(ShallowCopy(f));
    Y:=inc[1];

    clsr:=ClosureCWCell(Y,n,k);
    complex:=Y!.boundaries*1;
    clsr:=clsr[2]*1;

    Subdivide:=function(a,b)
    # subdivides the bth a-cell into as many a-cells
    # as there are in its barycentric subdivision
        local
            sub_clsr, i, j, l, ints, bnd_ints,
            bnd, pre_len, m, pre_len_bnd;

        sub_clsr:=ClosureCWCell(RegularCWComplex(complex),a,b)[2];

        Add(complex[1],[1,0]); # the barycentre
        if Length(inc[2])>=a+1 then
            if b in inc[2][a+1] then
                Add(inc[2][1],Length(complex[1]));
            fi;
        fi;

        pre_len_bnd:=List([1..a],x->Length(complex[x]));

        for i in [1..a] do
            pre_len:=Length(complex[i+1])*1;
            for j in [1..Length(sub_clsr[i])] do
                if i=1 then # edge case is dealt with separately
                    if a=1 and j=1 then # we overwrite the bth a-cell with
                    # the first a-cell of its barycentric subdivision
                        complex[2][b]:=[
                            2,
                            sub_clsr[1][1],
                            Length(complex[1])
                        ];
                    else
                        Add(
                            complex[2],
                            [
                                2,
                                sub_clsr[1][j],
                                Length(complex[1])
                            ]
                        );
                        if Length(inc[2])>=a+1 then
                            if b in inc[2][a+1] then
                                Add(inc[2][2],Length(complex[2]));
                            fi;
                        fi;
                    fi;
                else
                    bnd:=[];
                    ints:=List([pre_len_bnd[i]+1..Length(complex[i])]);
                    bnd_ints:=List(
                        ints,
                        x->complex[i][x]{[2..complex[i][x][1]+1]}
                    );
                    bnd_ints:=List(
                        bnd_ints,
                        x->Intersection(
                            x,
                            complex[i][sub_clsr[i][j]]{
                                [2..complex[i][sub_clsr[i][j]][1]+1]
                                }
                        )<>[]
                    );
                    bnd:=Concatenation(
                        [sub_clsr[i][j]],
                        Filtered(ints,x->bnd_ints[Position(ints,x)]=true)
                    );
                    Add(bnd,Length(bnd),1);
                    if i=a and j=1 then # overwrite as before
                        complex[a+1][b]:=bnd;
                    else
                        Add(complex[i+1],bnd);

                        if Length(inc[2])>=a+1 then
                            if b in inc[2][a+1] then
                                Add(inc[2][i+1],Length(complex[i+1]));
                            fi;
                        fi;
                    fi;
                fi;

                if i=a and a<Dimension(Y) then # rewrite the coboundary of
                # the replaced a-cell to contain all the a-cells in its
                # barycentric subdivision
                    for l in [2..Length(Y!.coboundaries[a+1][b])] do
                        for m in [pre_len+1..Length(complex[a+1])] do
                            Add(
                                complex[a+2][Y!.coboundaries[a+1][b][l]],
                                m
                            );
                        od;
                        complex[a+2][Y!.coboundaries[a+1][b][l]][1]:=Length(
                            complex[a+2][Y!.coboundaries[a+1][b][l]]
                        )-1;
                    od;
                fi;
            od;
        od;  
    end;

    for i in [2..Length(clsr)] do # inductively apply Subdivide to obtain the
        for j in [1..Length(clsr[i])] do # barycentric subdivision of the
            Subdivide(i-1,clsr[i][j]); # kth n-cell of Y as required
        od;
    od;

    return CWSubcomplexToRegularCWMap(
        [
            RegularCWComplex(complex),
            inc[2]
        ]
    );
end);

# SubdivideCell
################################################################################
############ Input: an inclusion of cell complexes f:Z->Y and two integers #####
################### k>0 & n>=0 #################################################
################################################################################
########### Output: the regular CW-map f':Z'->Y' corresponding to the same #####
################### spaces but where the kth n-cell of Y has been ##############
################### subdivided into as many n-cells as there are (n-1)-cells ###
################### in the boundary of that cell ###############################
################################################################################
InstallGlobalFunction(
    SubdivideCell,
    function(f,n,k)
    local
        sub, Y, closure, plus1,
        i, j, bnd, Last;
Last:=function(L); return L[Length(L)];end;

    sub:=RegularCWMapToCWSubcomplex(ShallowCopy(f));
    Y:=sub[1]; # the actual CW-complex
    sub:=sub[2]*1; # the indexing of the subcomplex
    closure:=ClosureCWCell(Y,n,k)[2];
    Y:=Y!.boundaries*1;

    Add(Y[1],[1,0]); # the barycentre of the kth n-cell
    plus1:=List([1..Length(closure)],x->[]);
    # this will associate an x-cell in the closure to
    # the resulting (x+1)-cell in the subdivision

    for i in [1..Length(closure)-1] do
        for j in [1..Length(closure[i])] do
            if i=1 then
                Add(Y[2],[2,closure[i][j],Length(Y[1])]);
                Add(plus1[1],Length(Y[2]));
            else
                bnd:=Y[i][closure[i][j]];
                bnd:=bnd{[2..bnd[1]+1]};
                bnd:=List(bnd,x->plus1[i-1][Position(closure[i-1],x)]);
                Add(bnd,closure[i][j],1);
                Add(bnd,Length(bnd),1);
                if i=Length(closure)-1 and j=1 then
                    Y[i+1][closure[i+1][1]]:=bnd;
                    Add(plus1[i],closure[i+1][1]);
                else
                    Add(Y[i+1],bnd);
                    Add(plus1[i],Length(Y[i+1]));
                fi;
            fi;
        od;
    od;
    for i in [1..Length(Y[Length(closure)+1])] do
        if Last(closure)[1] in
            Y[Length(closure)+1][i]{[2..Y[Length(closure)+1][i][1]+1]} then
                Append(Y[Length(closure)+1][i],plus1[Length(closure)]);
                Unbind(Y[Length(closure)+1][i][1]);
                Y[Length(closure)+1][i]:=Set(Y[Length(closure)+1][i]);
                Add(Y[Length(closure)+1][i],Length(Y[Length(closure)+1][i]),1);
        fi;
    od;
    return CWSubcomplexToRegularCWMap(
        [
            RegularCWComplex(Y),
            sub
        ]
    );
end);

# RegularCWComplexComplement
################################################################################
############ Input: an inclusion f: Z -> Y of regular CW-complexes #############
################################################################################
########### Output: let N(Z) denote an open tubular neighbourhood of ###########
################### Z in Y. this will output an inclusion B -> C where C #######
################### is homeomorphic to Y \ N(Z) and B is homeomorphic to the ###
################### boundary of Y \ N(Z) #######################################
################################################################################
InstallGlobalFunction(
    RegularCWComplexComplement,
    function(arg...)
    local
        f, check, subdiv, details, Y, B, IsInternal, count, total,
        path_comp, cobound_subcomplex, cbnd, i, j, clsr, int, crit,
        bary, IsSubpathComponent, ext_cell_2_f_notation,
        f_notation_2_ext_cell, ext_cells, k, ext_cell_bnd, e_n_bar,
        ext_cell_cbnd;

    if Length(arg)=1 then
     arg:=[arg[1],"some","basic",false];
    fi;
    f:=ShallowCopy(arg[1]);
    check:=arg[2]; # which cells we check for the contractible closures:
    # "some" or "all"
    subdiv:=arg[3]; # the subdivision we use:
    # "basic", "barycentric" or "none"
    details:=arg[4]; # do/don't suppress progress bars and other output
    
    Y:=RegularCWMapToCWSubcomplex(f);
    for i in [1..Dimension(Y[1])-Length(Y[2])+2] do
        Add(Y[2],[]);
    od;
    B:=List([1..Dimension(Y[1])+1],x->[]);

    IsInternal:=function(n,k) # is the kth n-cell of Y in Y\Z?
        if n+1>Length(Y[2]) then
            return true;
        elif k in Y[2][n+1] then
            return false;
        fi;
        return true;
    end;

    if details then
        Print("Testing contractibility...\n");
    fi;
    bary:=[];
    path_comp:=List([1..Length(Y[1]!.boundaries)-1],x->[]);

    if check="some" then
    # we check only those cells that are `close' to the subcomplex
    # i.e. those cells lying within the coboundaries of the coboundaries
    # of (...) the cells of the subcomplex
        cobound_subcomplex:=List(
            [1..Length(Y[2])],
            x->List(
                [1..Length(Y[2][x])],
                y->Y[1]!.coboundaries[x][Y[2][x][y]]{
                    [2..Y[1]!.coboundaries[x][Y[2][x][y]][1]+1]
                }
            )
        );
        cobound_subcomplex:=List(cobound_subcomplex,Concatenation);
        cobound_subcomplex:=List(cobound_subcomplex,Set);
        cobound_subcomplex:=List(
            [1..Length(cobound_subcomplex)],
            x->Filtered(cobound_subcomplex[x],y->not y in Y[2][x+1])
        );
        Add(cobound_subcomplex,[],1); # keep indexing w/out 0-cells
        for i in [1..Length(cobound_subcomplex)-1] do
            for j in [1..Length(cobound_subcomplex[i])] do
                cbnd:=Y[1]!.coboundaries[i][cobound_subcomplex[i][j]];
                for k in [2..cbnd[1]+1] do
                    Add(cobound_subcomplex[i+1],cbnd[k]);
                od;
            od;
        od;
        cobound_subcomplex:=List(cobound_subcomplex,Set);
        for i in [1..Length(cobound_subcomplex)-1] do   
            cobound_subcomplex[i]:=Filtered(
                cobound_subcomplex[i],
                x->not x in Y[2][i+1]
            );
        od;
    fi;

    count:=0;
    total:=Sum(List(Y[1]!.boundaries{[1..Length(Y[1]!.boundaries)]},Length));

    # list of all of the path components of the intersection between
    # the closure of each internal cell and the subcomplex Z < Y
    # note: entries may be an empty list if they correspond to an
    #       empty intersection or they may not be assigned a
    #       value at all if the associated cell lies in Z
    for i in [1..Length(Y[1]!.boundaries)] do
        for j in [1..Length(Y[1]!.boundaries[i])] do
            count:=count+1;
            if IsInternal(i-1,j) then
                Add(B[i],Y[1]!.boundaries[i][j]);
                # output will contain all internal cells
                if check="some" then
                    if j in cobound_subcomplex[i] then
                        clsr:=ClosureCWCell(Y[1],i-1,j);
                        int:=IntersectionCWSubcomplex(clsr,Y);
                        path_comp[i][j]:=PathComponentsCWSubcomplex(int);
                    else
                        path_comp[i][j]:=[];
                    fi;
                else
                    clsr:=ClosureCWCell(Y[1],i-1,j);
                    int:=IntersectionCWSubcomplex(clsr,Y);
                    path_comp[i][j]:=PathComponentsCWSubcomplex(int);
                fi; 
                # CONTRACTIBILITY TEST
                # must be a non-empty subcomplex of dimension > 0
                if details then
                    Print(count," out of ",total," cells tested.","\r");
                fi;
                if subdiv<>"none" then
                    # test the contractibility of each path component
                    # if we find anything non-contractible,
                    # subdivide the problematic cells and restart
                    for k in [1..Length(path_comp[i][j])] do
                        if path_comp[i][j][k][2]<>List(path_comp[i][j][k][2],x->[])
                        and path_comp[i][j][k][2][2]<>[] then
                            crit:=CWSubcomplexToRegularCWMap(path_comp[i][j][k]);
                            crit:=Source(crit);
                            crit:=CriticalCellsOfRegularCWComplex(crit);
                            if not Length(crit)=1 then
                                Add(bary,[i-1,j]);
                            fi;
                        fi;
                    od;
                fi;
            else
                Add(B[i],"*"); # temporary entry to keep correct indexing
            fi;
        od;
    od;
    bary:=Set(bary);

    if bary=[] then
        if details then
            Print("\nThe input is compatible with this algorithm.\n");
        fi;
    else
        if details then
            Print("\nSubdividing ",Length(bary)," cell(s):\n");
        fi;
        for i in [1..Length(bary)] do
            if subdiv="basic" then
                f:=SubdivideCell(
                    f,
                    bary[i][1],
                    bary[i][2]
                );
            elif subdiv="barycentric" then
                f:=BarycentricallySubdivideCell(
                    f,
                    bary[i][1],
                    bary[i][2]
                );
            fi;
            if details then
                Print(Int(100*i/Length(bary)),"\% complete. \r");
            fi;
        od;
        Print("\n");
        return RegularCWComplexComplement(f,check,subdiv,details); # really bad
    fi;

    for i in [1..Length(B)] do
        for j in [1..Length(B[i])] do
            if i>1 and B[i][j]<>"*" then
                B[i][j]:=Filtered(
                        B[i][j]{[2..B[i][j][1]+1]},
                        x->"*"<>B[i-1][x]
                    );
                Add(B[i][j],Length(B[i][j]),1);
            fi;
        od;
    od;
    # at this point, B corresponds to the cell complex Y\Z

    IsSubpathComponent:=function(super,sub)
        local
            i;

        for i in [1..Length(sub[2])-1] do
            if not IsSubset(super[2][i],sub[2][i]) then
                return false;
            fi;
        od;

        return true;
    end;

    ext_cell_2_f_notation:=NewDictionary([],true);
    f_notation_2_ext_cell:=NewDictionary([],true);
    # takes a pair [n,k] corresponding to the kth n-cell (external) of B and
    # returns its associated "f notation" i.e. a triple [n+1,k',A] corresponding
    # to the k'th (n+1)-cell (internal) whose closure intersected with Z in the
    # path component A

    ext_cells:=List([1..Length(B)],x->[]);

    for i in [2..Length(path_comp)] do
        for j in [1..Length(path_comp[i])] do
            if IsBound(path_comp[i][j]) then
                if path_comp[i][j]<>[] then
                    # we add as many external (i-1)-cells to B as
                    # there are path components in path_comp[i][j]
                    for k in [1..Length(path_comp[i][j])] do
                        if i=2 then
                            ext_cell_bnd:=[0];
                        else
                            e_n_bar:=ClosureCWCell(Y[1],i-1,j)[2];
                            ext_cell_bnd:=List(
                                ext_cells[i-2],
                                x->LookupDictionary(
                                    ext_cell_2_f_notation,
                                    [i-3,x]
                                )
                            );
                            ext_cell_bnd:=Filtered(
                                ext_cell_bnd,
                                x->
                                    x[2] in e_n_bar[i-1]
                                    and
                                    IsSubpathComponent(path_comp[i][j][k],x[3])
                            );
                            ext_cell_bnd:=List(
                                ext_cell_bnd,
                                x->LookupDictionary(
                                    f_notation_2_ext_cell,
                                    x
                                )[2]
                            );
                        fi;
                        ext_cell_cbnd:=[j];

                        HAP_KK_AddCell(
                            B,
                            i-2,
                            ext_cell_bnd,
                            ext_cell_cbnd
                        );
                        Add(ext_cells[i-1],Length(B[i-1]));
                        AddDictionary(
                            ext_cell_2_f_notation,
                            [i-2,Length(B[i-1])],
                            [i-1,j,path_comp[i][j][k]]
                        );
                        AddDictionary(
                            f_notation_2_ext_cell,
                            [i-1,j,path_comp[i][j][k]],
                            [i-2,Length(B[i-1])]
                        );
                    od;
                fi;
            fi;
        od;
    od;

    # a final reindexing of B and removal of "*"
    # entries that once corresponded to cells of Z
    for i in [2..Length(B)] do
        for j in [1..Length(B[i])] do
            for k in [2..Length(B[i][j])] do
                B[i][j][k]:=
                B[i][j][k]-
                Length(
                    Filtered(
                        B[i-1]{[1..B[i][j][k]]},
                        x->x="*"
                    )
                );
            od;
        od;
    od;
    B:=List(B,x->Filtered(x,y->y<>"*"));
    Add(B,[]);

    return RegularCWComplex(B);
end);

# SequentialRegularCWComplexComplement
InstallGlobalFunction(
    SequentialRegularCWComplexComplement,
    function(arg...)
    local
        subdiv, method, details, map, sub, clsr, seq, tub, i;

    if Length(arg)=1 then
        arg:=[arg[1],"some","basic",false];
    fi;
    method:=arg[2];
    subdiv:=arg[3];
    details:=arg[4];

    map:=RegularCWMapToCWSubcomplex(arg[1]);
    sub:=SortedList(map[2][Length(map[2])]);
    sub:=List(sub,x->x-Position(sub,x)+1);
    clsr:=ClosureCWCell(map[1],2,sub[1])[2];;
    seq:=CWSubcomplexToRegularCWMap([map[1],clsr]);;
    tub:=RegularCWComplexComplement(seq,method,subdiv,details);
    for i in [2..Length(sub)] do
        clsr:=ClosureCWCell(tub,2,sub[i])[2];;
        seq:=CWSubcomplexToRegularCWMap([tub,clsr]);;
        tub:=RegularCWComplexComplement(seq,method,subdiv,details);
    od;
    
    return tub;
end);

# LiftColouredSurface
################################################################################
############ Input: an inclusion i:Y->X of regular CW-complexes ################
################### with component object i!.colour(n,k) returning an integer ##
################### in the range [a,b] associated to the kth n-cell of Y #######
################################################################################
########### Output: an inclusion of regular CW-complexes i~:Y~->Xx[a,b] ########
################### where Y~ is the lifted subcomplex of Xx[a,b] as ############
################### specified by i!.colour #####################################
################################################################################
InstallGlobalFunction(
    LiftColouredSurface,
    function(f)
    local
        src, trg, lens, colours,
        cbnd4_1cells, cbnd4_1cells_bnd,
        i, j, clr, closure, k,
        min, max, l_colours,
        cell, col1, col2, int,
        bnd, bbnd, l, cobnd4,
        l_src, prods;

    trg:=RegularCWMapToCWSubcomplex(f);
    src:=trg[2]*1;
    trg:=trg[1];
    lens:=List([1..Length(trg!.boundaries)-1],x->Length(trg!.boundaries[x]));
    colours:=List([1..Length(src)],x->List([1..trg!.nrCells(x-1)],y->[]));
    cbnd4_1cells:=[]; # list of all 1-cells of src whose coboundary consists of 4 2-cells
    cbnd4_1cells_bnd:=[]; # the boundary of the above 1-cells
    for i in [1..Source(f)!.nrCells(1)] do
        if Source(f)!.coboundaries[2][i][1]=4 then
            Add(cbnd4_1cells,src[2][i]);
            for j in [2,3] do
                Add(
                    cbnd4_1cells_bnd,
                    src[1][Source(f)!.boundaries[2][i][j]]
                );
            od;
        fi;
    od;
    cbnd4_1cells_bnd:=Set(cbnd4_1cells_bnd);
    # we want to compute the inclusion src* -> trg x I where
    # I is the interval [min,max] and where min and max are the
    # smallest/largest integers that f!.colour assigns to 2-cells
    #       we begin by associating to each cell e^n of src a list
    # of integers e.g. [-1,2] indicating that e^n x {-1} and
    # e^n x {2} will be in src x I
    for i in [1..Length(src[Length(src)])] do
        clr:=f!.colour(Length(src)-1,src[Length(src)][i]);
        closure:=ClosureCWCell(trg,Length(src)-1,src[Length(src)][i])[2];
        for j in [1..Length(closure)] do
            for k in [1..Length(closure[j])] do
                colours[j][closure[j][k]]:=Set(
                    Concatenation(
                        colours[j][closure[j][k]],
                        clr
                    )
                );
            od;
        od;
    od;
    min:=Minimum(List(Filtered(colours[Length(colours)],x->x<>[]),Minimum));
    # ^smallest & \/largest 'colours'
    max:=Maximum(List(Filtered(colours[Length(colours)],x->x<>[]),Maximum));
    # make a copy of trg for each colour in [min-1,min+1]
    trg:=trg!.boundaries*1; Add(trg,[]);
    l_colours:=List(
        [1..Length(trg)],
        x->List([1..Length(trg[x])],
            y->[[x-1,y],min-1]
        )
    );
    for i in [min..max+1] do
        for j in [1..lens[1]] do
            Add(trg[1],[1,0]);
            Add(l_colours[1],[[0,j],i]);
        od;
    od;
    for i in [1..Length([min..max+1])] do
        for j in [1..Length(lens)-1] do
            for k in [1..lens[j+1]] do
                cell:=trg[j+1][k]*1;
                cell:=Concatenation(
                    [cell[1]],
                    cell{[2..Length(cell)]}+lens[j]*i
                );
                Add(trg[j+1],cell);
                Add(l_colours[j+1],[[j,k],[min..max+1][i]]);
            od;
        od;
    od;
    # `join' each Target(f) x {i-1} to Target(f) x {i}
    for i in [1..Length(lens)] do
        for j in [1..lens[i]] do
            cell:=[i-1,j];
            for k in [1..Length([min-1..max])] do
                col1:=[min-1..max][k];
                col2:=[min-1..max+1][k+1];
                int:=[col1,col2];
                bnd:=[]; # boundary of cell x int
                Add(
                    bnd,
                    Position(l_colours[i],[cell,col1])
                );
                Add(
                    bnd,
                    Position(l_colours[i],[cell,col2])
                );
                if i>1 then
                    bbnd:=trg[i][j]*1;
                    bbnd:=bbnd{[2..bbnd[1]+1]};
                    bbnd:=List(
                        bbnd,
                        x->[i-2,x]
                    );
                    for l in [1..Length(bbnd)] do
                        Add(
                            bnd,
                            Position(l_colours[i],[bbnd[l],int])
                        );
                    od;
                fi;
                bnd:=Set(bnd); Add(bnd,Length(bnd),1);
                Add(trg[i+1],bnd);
                Add(l_colours[i+1],[cell,int]);
            od;
        od;
    od;
    # identify the correct subcomplex of X x [min-1,max+1]
    cobnd4:=[]; # there are some 1-cells which shouldn't be lifted
    l_src:=List(src,x->[]);
    for i in [1..Length(colours)] do
        for j in [1..Length(colours[i])] do
            if colours[i][j]<>[] then
                prods:=[];
                if Length(colours[i][j])=1 then
                    Add(prods,colours[i][j][1]);
                else
                    int:=[Minimum(colours[i][j]),Maximum(colours[i][j])];
                    for k in [2..Length(int)] do
                        Add(prods,int[k-1]);
                        if not (i=2 and j in cbnd4_1cells) and
                            not (i=1 and j in cbnd4_1cells_bnd) then
                            Add(prods,[int[k-1],int[k]]);
                        fi;
                        Add(prods,int[k]);
                    od;
                    prods:=Set(prods);
                fi;
                for k in [1..Length(prods)] do
                    if IsInt(prods[k]) then
                        Add(
                            l_src[i],
                            Position(
                                l_colours[i],
                                [[i-1,j],prods[k]]
                            )
                        );
                    else
                        Add(
                            l_src[i+1],
                            Position(
                                l_colours[i+1],
                                [[i-1,j],prods[k]]
                            )
                        );
                    fi;
                od;
            fi;
        od;
    od;
    return CWSubcomplexToRegularCWMap(
        [
            RegularCWComplex(trg),
            l_src
        ]
    );
end);

# ViewArc2Presentation
################################################################################
############ Input: three lists a, b, c. a corresponds to an arc ###############
################### presentation. b's entries are either 0, 1 or -1 and they ###
################### determine whether a given crossing in the arc presentation #
################### is an intersection, an overcrossing or an undercrossing. c #
################### is a list whose entries are 1, 2, 3 or 4. they #############
################### correspond to an intersection going from blue to blue, #####
################### blue to red, red to blue or red to red (see manual) ########
################################################################################
########### Output: a png depicting the associated coloured arc diagram ########
################################################################################
InstallGlobalFunction(
    ViewArc2Presentation,
    function(l)
    local
        arc, cross, cols, AppendTo, PrintTo, file, filetxt, filepng,
        bin_arr, coord, res, colours, i, j, x, k, y, z, clr, tmpdir;

    arc:=List(l[1],x->[SignInt(x[1])*x[1],SignInt(x[2])*x[2]]);
    cross:=l[2]*1;
    cols:=l[3]*1;
    AppendTo:=HAP_AppendTo;
    PrintTo:=HAP_PrintTo;
    #file:="/tmp/HAPtmpImage";
    #filetxt:="/tmp/HAPtmpImage.txt";
tmpdir := DirectoryTemporary();;
file:=Filename( tmpdir , "HAPtmpImage" );
filetxt:=Filename( tmpdir , "HAPtmpImage.txt" );
filepng:=Filename( tmpdir , "HAPtmpImage.png" );

    # create a binary array from the arc presentation
    bin_arr:=Sum(PureCubicalKnot(arc)!.binaryArray);
    bin_arr:=TransposedMat(bin_arr); # graham has this backwards!
    bin_arr:=List(
        bin_arr{[2..Length(bin_arr)-3]},
        x->x{[2..Length(bin_arr[1])-3]}
    );
    coord:=Concatenation(
        List(
            [1..Length(bin_arr)],
            x->List(
                [1..Length(bin_arr)],
                y->[x,y]
            )
        )
    );
    coord:=Filtered(coord,x->bin_arr[x[1]][x[2]]=2);

    res:=String(Minimum(50*Length(bin_arr),950));

    PrintTo(
        filetxt,
        "# ImageMagick pixel enumeration: ",
        Length(bin_arr)+2,
        ",",
        Length(bin_arr[1])+2,
        ",255,RGB\n"
    );

    colours:=NewDictionary([0,""],true);
    colours!.entries:=[
        [0,"(255,255,255)"], # white
        [1,"(131,205,131)"], # green
        [2,"(131,205,131)"], # green
        [3,"(131,205,131)"], # green
        [4,"(205,131,131)"], # red
        [5,"(131,131,205)"], # blue
    ];
    
    for i in [1..Length(bin_arr)] do
        for j in [1..Length(bin_arr)] do
            if bin_arr[i][j]=3 then
            # remove vertical bars that have -entry in l[1]
                x:=-1*(Int(j/3)+1);
                if x in Concatenation(l[1]) then
                    for k in [i+1..Length(bin_arr)] do
                        if bin_arr[k][j]=1 then
                            bin_arr[k][j]:=0;
                        fi;
                    od;
                fi;
            elif bin_arr[i][j]=2 then
            # check crossing type and adjust surrounding pixels
                x:=Position(coord,[i,j]);
                y:=cross[x];
                if y=-1 then
                    bin_arr[i][j-1]:=0;
                    bin_arr[i][j+1]:=0;
                elif y=1 then
                    bin_arr[i-1][j]:=0;
                    bin_arr[i+1][j]:=0;
                elif y=0 then
                    z:=cols[Position(Positions(cross,0),x)];
                    if z=1 then
                        bin_arr[i][j-1]:=5;
                        bin_arr[i][j+1]:=5;
                    elif z=2 then
                        bin_arr[i][j-1]:=5;
                        bin_arr[i][j+1]:=4;
                    elif z=3 then
                        bin_arr[i][j-1]:=4;
                        bin_arr[i][j+1]:=5;
                    elif z=4 then
                        bin_arr[i][j-1]:=4;
                        bin_arr[i][j+1]:=4;
                    fi;
                fi;
            fi;
        od;
    od;
    # image gets cropped if i dont do this
    for i in [1..2] do
        Add(bin_arr,bin_arr[1]*0);
    od;
    for j in [1..Length(bin_arr)] do
        bin_arr[j]:=Concatenation(bin_arr[j],[0,0]);
    od;
    #return bin_arr;
    # swap each entry of the binary area with an rgb value
    for i in [1..Length(bin_arr)] do
        for j in [1..Length(bin_arr[i])] do
            clr:=LookupDictionary(colours,bin_arr[i][j]);
            AppendTo(filetxt,j,",",i,": ",clr,"\n");
        od;
    od;

    # convert the binary array to an upscaled 500x500 png
    Exec(
        Concatenation("convert ",filetxt," ","-scale ",res,"x",res," ",file,".png")
    );
    # delete the old txt file
    Exec(
        Concatenation("rm ",filetxt)
    );
    # display the image
    #Exec(
    #    Concatenation(DISPLAY_PATH," ","/tmp/HAPtmpImage.png")
    #);
    Exec(
        Concatenation(DISPLAY_PATH," ",filepng)
    );
    # delete the image on window close
    #Exec(
    #    Concatenation("rm  ","/tmp/HAPtmpImage.png")
    #);
    Exec(
        Concatenation("rm  ",filepng)
    );
end);

# Tube
################################################################################
############ Input: an arc 2-presentation ######################################
################################################################################
########### Output: a regular CW-complex corresponding to the complement #######
################### of the knotted surface associated to that arc ##############
################### 2-presentation via the Tube map ############################
################################################################################
InstallGlobalFunction(
    Tube,
    function(arc)
    local
        ribbon;

    arc:=KinkArc2Presentation(arc);

    ribbon:=ArcDiagramToTubularSurface(arc);
    ribbon:=LiftColouredSurface(ribbon);
    ribbon:=SequentialRegularCWComplexComplement(ribbon,"some","none",false);

    return ribbon;
end);

# KinkArc2Presentation
################################################################################
############ Input: an arc 2-presentation ######################################
################################################################################
########### Output: an arc 2-presentation with no two crossings occuring #######
################### on the same row/column #####################################
################################################################################
InstallGlobalFunction(
    KinkArc2Presentation,
    function(arc)
    local
        mat, i, x, j, Twist, z, coord, keep, arc_;

    mat:=List([1..Length(arc[1])],x->[1..Length(arc[1])]*0);
    for i in [1..Length(arc[1])] do
        mat[Length(mat)-i+1][AbsoluteValue(arc[1][i][1])]:=3;
        mat[Length(mat)-i+1][AbsoluteValue(arc[1][i][2])]:=3;
    od;
    for x in [1,2] do
        if x=2 then
            mat:=MutableTransposedMat(mat);
        fi;
        for i in [1..Length(mat)] do
            for j in [2..Length(mat)-1] do
                if 3 in mat[i]{[1..j-1]} and
                3 in mat[i]{[j+1..Length(mat)]} then
                    mat[i][j]:=mat[i][j]+1;
                fi;
            od;
        od;
    od;
    mat:=MutableTransposedMat(mat);
    for i in Set(Concatenation(arc[1])) do
        if i<0 then
            for j in [2..Length(mat)-1] do
                if mat[j][-i] in [1,2] then
                    mat[j][-i]:=0;
                fi;
            od;
        fi;
    od;
    # mat models the arc 2-presentation, even should it correspond to
    # (a) knotted sphere(s)

    Twist:=function(i,j)
        local
            x, k, l, left, right, up, down;

        # first create a new row and column in mat 
        for x in [1..Length(mat)] do
            Add(mat[x],4,j);
        od;
        Add(
            mat,
            Concatenation(
                List([1..j-1],y->4),
                [3],
                mat[i]{[j+1..Length(mat)+1]}
            ),
            i+1
        );
        mat[i]:=Concatenation(
            mat[i]{[1..j-1]},
            [3],
            List([j+1..Length(mat)],y->4)
        );

        # now determine the values of the 2n+1 new entries
        # where n is the length of mat before Twist
        for k in [1..Length(mat)] do
            for l in [1..Length(mat[k])] do
                if mat[k][l]=4 then
                    if k in [1,Length(mat)] then
                    # the entry is either in the top/bottom row
                    # so there is no need to check above/below it
                        left:=mat[k]{[1..l-1]};
                        right:=mat[k]{[l+1..Length(mat)]};
                        if 3 in left and 3 in right then
                            if 0 in mat[k]{[l-1,l+1]} then
                            # this is to check if this row corresponds
                            # to an omitted row in the arc 2-pres.
                                mat[k][l]:=0;
                            else
                                mat[k][l]:=1;
                            fi;
                        else
                            mat[k][l]:=0;
                        fi;
                    elif l in [1,Length(mat)] then
                    # the entry is in the first/last column and
                    # we don't need to check to the left/right of it
                        up:=mat{[1..k-1]}[l];
                        down:=mat{[k+1..Length(mat)]}[l];
                        if 3 in up and 3 in down then
                            if 0 in mat{[k,k+1]}[l] then
                                mat[k][l]:=0;
                            else
                                mat[k][l]:=1;
                            fi;
                        else
                            mat[k][l]:=0;
                        fi;
                    else
                    # we are required to check above/below/left/right
                    # of the entry to determine its value
                        left:=mat[k]{[1..l-1]};
                        right:=mat[k]{[l+1..Length(mat)]};
                        up:=mat{[1..k-1]}[l];
                        down:=mat{[k+1..Length(mat)]}[l];
                        if 3 in left and 3 in right then
                            if 0 in mat[k]{[l-1,l+1]} then
                                mat[k][l]:=0;
                            else
                                mat[k][l]:=1;
                            fi;
                        elif 3 in up and 3 in down then
                            if 0 in mat{[k,k+1]}[l] then
                                mat[k][l]:=0;
                            else
                                mat[k][l]:=1;
                            fi;
                        else
                            mat[k][l]:=0;
                        fi;
                    fi;
                fi;
            od;
        od;

        return mat;
    end;

    for z in [1,2] do
        if z=2 then
            mat:=MutableTransposedMat(mat);
        fi;
        for i in [1..Sum(List(mat,y->Maximum(0,Length(Positions(y,2))-1)))] do
        # number of times we need to perform Twist on the rows of mat
            coord:=Filtered(
                Concatenation(
                    List(
                        [1..Length(mat)],
                        x->List(
                            [1..Length(mat)],
                            y->[x,y,mat[x][y]]
                        )
                    )
                ),
                x->x[3]=2
            );
            keep:=[];
            for j in [1..Length(coord)] do
                if coord[j][1] in List(coord,x->x[1]){[1..j-1]} then
                    Add(keep,j);
                fi;
            od;
            coord:=First(coord{keep});
            # the coordinate of the first instance of a crossing that
            # lies in a row where multiple crossings occur
            mat:=Twist(coord[1],coord[2]);
        od;
    od;
    mat:=MutableTransposedMat(mat);

    # before output we need to see if there are any columns that were
    # omitted. if so we need to find their new positions and reflect
    # that with a negative entry in arc[1]
    

    # now to recover the new arc 2-presentation from mat
    arc_:=ShallowCopy(arc);
    arc_[1]:=[];
    for i in Reversed([1..Length(mat)]) do
        Add(
            arc_[1],
            Filtered([1..Length(mat)],y->mat[i][y]=3)
        );
    od;

    return arc_;
end);

# NumberOfCrossingsInArc2Presentation
################################################################################
############ Input: an arc 2-presentation ######################################
################################################################################
########### Output: the number of crossings in the arc 2-presentation ##########
################################################################################
InstallGlobalFunction(
    NumberOfCrossingsInArc2Presentation,
    function(arc)
    local
        mat, i, x, j;

    mat:=List([1..Length(arc[1])],x->[1..Length(arc[1])]*0);
    for i in [1..Length(arc[1])] do
        mat[Length(mat)-i+1][AbsoluteValue(arc[1][i][1])]:=3;
        mat[Length(mat)-i+1][AbsoluteValue(arc[1][i][2])]:=3;
    od;
    for x in [1,2] do
        if x=2 then
            mat:=MutableTransposedMat(mat);
        fi;
        for i in [1..Length(mat)] do
            for j in [2..Length(mat)-1] do
                if 3 in mat[i]{[1..j-1]} and
                3 in mat[i]{[j+1..Length(mat)]} then
                    mat[i][j]:=mat[i][j]+1;
                fi;
            od;
        od;
    od;

    return Sum(List(mat,y->Length(Filtered(y,z->z=2))));
end);

# RandomArc2Presentation
################################################################################
############ Input: nothing ####################################################
################################################################################
########### Output: a random arc 2-presentation arising as the knot sum ########
################### of one or more prime knots on <12 crossings ################
################################################################################
InstallGlobalFunction(
    RandomArc2Presentation,
    function()
    local
        len, rand, prime, cross, final_arc, i, arc;
        
    len:=1;
    rand:=Random([0,1]);

    while rand=1 do
        len:=len+1;
        rand:=Random([0,1]);
    od;

    prime:=[0,0,1,1,2,3,7,21,49,165,552];

    final_arc:=Random([3..11]);
    final_arc:=[final_arc,Random([1..prime[final_arc]])];
    final_arc:=ArcPresentation(
        PureCubicalKnot(final_arc[1],final_arc[2])
    );
    
    for i in [2..len] do
        arc:=Random([3..11]);
        arc:=[arc,Random([1..prime[arc]])];
        final_arc:=ArcPresentation(
            KnotSum(
                PureCubicalKnot(final_arc),
                PureCubicalKnot(arc[1],arc[2])
            )
        );
    od;

    cross:=List(
        [1..NumberOfCrossingsInArc2Presentation([final_arc,[],[]])],
        x->Random([-1,0,1])
    );

    final_arc:=[
        final_arc,
        cross,
        List([1..Length(Filtered(cross,x->x=0))],y->Random([1..4]))    
    ];

    return final_arc;
end);

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