Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Ind
 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 

23 Example Implementations
 23.1 StronglyConnectedComponentOfFace
 23.2 VertexCounter

23 Example Implementations

This chapter contains examples of implementations of some of the methods in the package SimplicialSurfaces. We chose examples which illustrate many of the different fundamental features and methods of the package while at the same time require only a few lines of code to implement. Every section discusses the implementation of an already existing method by giving:

  1. A short explanation of the method

  2. A presentation of the code

  3. The development of the code

23.1 StronglyConnectedComponentOfFace

The method StronglyConnectedComponentOfFace (8.6-4) finds all faces that are connected to a given face by edge-face-paths (8.3) and returns the polygonal complex consisting of these faces.

We illustrate this with an octahedron (14.3-4):

gap> octa := Octahedron();;
gap> octa = StronglyConnectedComponentOfFace(octa,7);
true

This could be implemented like this:

gap> StrongComponent_custom := function( complex, face )
>        local component, f, edge, newFace;
>  
>        component := [ face ];
>        for f in component do
>            for edge in EdgesOfFace(complex, f) do
>                newFace := NeighbourFaceByEdge( complex, f, edge );
>                if not newFace in component then
>                    Add(component, newFace);
>                fi;
>            od;
>        od;
> 
>        return SubcomplexByFaces( complex, component );
>    end;;
gap> 
gap> StrongComponent_custom(octa,7) = StronglyConnectedComponentOfFace(octa,7);
true

To develop this code we first have to find an algorithm to compute the strongly connected component of an face. We begin with the starting face (for example 7) and add all faces to the strong component that are adjacent to it (so 1, 5 and 6). Then we add the neighbours of those faces (and so on). We will end up with all faces of the strongly connected component of 7. The initialization of this algorithm is easy.

gap> component := [ 7 ];
[ 7 ]

For each edge of this face there is a neighbour. Therefore we need the edges of this face.

gap> EdgesOfFace( octa, 7 );
[ 2, 3, 8 ]

The neighbours can be computed by calling the method NeighbourFaceByEdge (10.3-3).

gap> newFace := NeighbourFaceByEdge( octa, 7, 2 );
1

If this face is not already accounted for, we have to add it to our component.

gap> if not newFace in component then
>        Add( component, newFace );
>    fi;

To check all neighbours, we loop over the incident edges:

gap> for edge in EdgesOfFace(octa, 7) do
>        newFace := NeighbourFaceByEdge( octa, 7, edge );
>        if not newFace in component then
>            Add( component, newFace );
>        fi;
>    od;

Finally we have to loop over all faces in the component. At this point we use a feature of GAP: We can loop over a list that is changed during the loop. So our algorithm can simply be written as

gap> for f in component do
>        for edge in EdgesOfFace(octa, f) do
>            newFace := NeighbourFaceByEdge( octa, f, edge );
>            if not newFace in component then
>                Add(component, newFace);
>            fi;
>        od;
>    od;
gap> component;
[ 7, 1, 5, 6, 3, 4, 8, 2 ]

Now we have computed all faces of the strongly connected component of our starting face. To make a polygonal complex out of it, we use the method SubcomplexByFaces that returns the induced subcomplex of a given list of faces.

gap> SubcomplexByFaces( octa, component ) = octa;
true

23.2 VertexCounter

The method CounterOfVertices (9.2-4) creates a list of pairs [degree,multiplicity] such that the second entry of each pair counts the number of vertices that have exactly degree incident faces.

We illustrate it on the example of a pyramid with square base.

gap> pyr := PolygonalSurfaceByVerticesInFaces( 
>            [ [3,4,5,6], [1,3,4], [1,4,5], [1,5,6], [1,6,3] ]);;
gap> ListCounter(CounterOfVertices( pyr ));
[ [ 3, 4 ], [ 4, 1 ] ]

This could be implemented like this:

gap> VertexCounter_custom := function( complex )
>     local faceDegrees;
> 
>     faceDegrees := List( FacesOfVertices(complex), Size );
>     return Collected( Compacted( faceDegrees ) );
> end;;
gap> 
gap> VertexCounter_custom( pyr );
[ [ 3, 4 ], [ 4, 1 ] ]

How do we arrive at this code? First of all we have to find the relevant information. We want to count how many faces are incident to a vertex. Therefore we use the method FacesOfVertices (3.2-2) that gives us exactly this information. Since we only want to know the number of faces, we apply the method Size to every component.

gap> faceDegrees := List( FacesOfVertices(pyr), Size );
[ 4, , 3, 3, 3, 3 ]

Alternatively we could have used the specialized method FaceDegreesOfVertices (9.2-2) directly.

gap> FaceDegreesOfVertices( pyr );
[ 4, , 3, 3, 3, 3 ]

Now we need to count how often each entry appears. This can be done by a loop but we will use the GAP-function Collected instead. Unfortunately it only works for lists without holes:

gap> Collected( faceDegrees );
Error, List Element: <list>[2] must have an assigned value

If we want to program with this package, we have to expect holes. In this case it is sufficient to remove all holes with the GAP-function Compacted.

gap> Compacted( faceDegrees );
[ 4, 3, 3, 3, 3 ]
gap> colDegrees := Collected( Compacted( faceDegrees ) );
[ [ 3, 4 ], [ 4, 1 ] ]

This is exactly the result we aimed for.

 [Top of Book]  [Contents]   [Previous Chapter]   [Next Chapter] 
Goto Chapter: Top 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Ind

generated by GAPDoc2HTML