Skip to content

Commit

Permalink
use cycle methods of Digraphs
Browse files Browse the repository at this point in the history
  • Loading branch information
MeikeWeiss committed Sep 11, 2024
1 parent 37f027f commit f7c28f1
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 268 deletions.
6 changes: 3 additions & 3 deletions gap/Paths/paths.gd
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,8 @@ DeclareAttribute( "AssociatedPolygonalComplex", IsVertexEdgePath );
#! gap> butterfly:=SimplicialSurfaceByDownwardIncidence(
#! > [[1,2],[1,3],[2,3],[3,4],[1,4]],[[1,2,3],[2,4,5]]);;
#! gap> AllClosedVertexEdgePaths(butterfly);
#! [ ( v1, E1, v2, E3, v3, E2, v1 ), ( v1, E1, v2, E3, v3, E4, v4, E5, v1 ),
#! ( v1, E5, v4, E4, v3, E2, v1 ) ]
#! [ ( v3, E2, v1, E5, v4, E4, v3 ), ( v3, E3, v2, E1, v1, E2, v3 ),
#! ( v3, E3, v2, E1, v1, E5, v4, E4, v3 ) ]
#! @EndExampleSession
#! @Returns a list of vertex-edge-paths
#! @Arguments complex
Expand Down Expand Up @@ -1305,7 +1305,7 @@ DeclareAttribute( "AllThreeWaistsOfComplex", IsTwistedPolygonalComplex);
#! For example, consider the double tetrahedron from the start of section <Ref Sect="Section_Waists"/>:
#! @BeginExampleSession
#! gap> AllWaistsOfComplex(doubleTetra);
#! [ ( v5, E10, v4, E7, v3, E8, v5 ), ( v5, E12, v6, E9, v3, E8, v5 ) ]
#! [ ( v4, E10, v5, E8, v3, E7, v4 ), ( v6, E12, v5, E8, v3, E9, v6 ) ]
#! @EndExampleSession
#!
#! @Returns a set of closed vertex-edge-paths
Expand Down
9 changes: 4 additions & 5 deletions gap/Paths/paths.gi
Original file line number Diff line number Diff line change
Expand Up @@ -406,20 +406,19 @@ InstallMethod(AllClosedVertexEdgePaths, "for a complex",
# First calculate all cycles of the edge graph.
# These cycles result in all closed vertex edge path of the complex except cycles of length two.
graph:=EdgeDigraphsGraph(newComplex);
cycles:=__SIMPLICIAL_AllCyclesOfGraph(graph);
cycles:=DigraphAllUndirectedSimpleCircuits(graph);
newCycles:=[];

# Compute for all cycles the corresponding edges in the complex.
for c in cycles do
nodesOfCycle:=Flat(__SIMPLICIAL_NodesOfCycle(c));

# CommonEdgesOfVertices returns all edges that are possible between two vertices.
edgeList:=[];
for e in CommonEdgesOfVertices(newComplex, Last(nodesOfCycle),nodesOfCycle[1]) do
for e in CommonEdgesOfVertices(newComplex, Last(c),c[1]) do
Add(edgeList,[e]);
od;
for i in [1..Length(nodesOfCycle)-1] do
edges:=CommonEdgesOfVertices(newComplex, nodesOfCycle[i],nodesOfCycle[i+1]);
for i in [1..Length(c)-1] do
edges:=CommonEdgesOfVertices(newComplex, c[i],c[i+1]);
newEdgeList:=[];

# Add the possibilities for the next edge to each edge list computed so far.
Expand Down
296 changes: 37 additions & 259 deletions gap/PolygonalComplexes/graphs.gi
Original file line number Diff line number Diff line change
Expand Up @@ -803,272 +803,49 @@ BindGlobal("__SIMPLICIAL_AdjacencyMatrixFromList",
return mat;
end);

BindGlobal("__SIMPLICIAL_EdgesFromCycle",
function(digraph,cycle)

# The following function computes all cycles of a graph <dig> by:
# 1. Calculation of a cycle base (CyclesBasisOfGraph) by first computing a spanning tree and then adding each edge
# which is not in the tree. Each edge gives a different cycle named base cycles.
# 2. Iterate through all possible combinations of base cycles and combine them by applying XOR to the adjacency matrices.
# In this way you get all cycles of the graph.
BindGlobal("__SIMPLICIAL_AllCyclesOfGraph",
function(digraph)

local CycleOnEdge,CycleBasisOfGraph,XORAdjacencyMatrices,
MultipleCyclesInMatrix,cyclebasis, allcycles, nullmat, mat, i, k, pos, neighs,c,cycle;

# Find a cycle in the original graph all of whose edges are in
# tree except for the edge e.
CycleOnEdge := function( tree, root, e )

local cycle, i, path1, path2, l1, l2;

if e[1] = e[2] then
Error("CycleOnEdge: edge is a loop");
return false;
fi;

# first find paths from the root to the two vertices of e
if root = e[1] then path1 := [root];
else path1 := DigraphPath(tree, root, e[1])[1]; fi;
if root = e[2] then path2 := [root];
else path2 := DigraphPath(tree, root, e[2])[1]; fi;
l1 := Length(path1); l2 := Length(path2);

# now skip the common entries in the path
cycle := []; i := 1;
while i <= Minimum(l1,l2) and path1[i] = path2[i] do
i := i + 1;
od;

cycle := [path1[i-1]];
Append(cycle, path1{[i..l1]});
Append(cycle, Reversed(path2{[i..l2]}));

return __SIMPLICIAL_AdjacencyMatrixFromList(cycle,DigraphNrVertices(tree));
end;;

# This function computes a cycle basis for the undirected graph
# dig, which is assumed to be a symmetric digraph.
# The cycle Basis consists of lower triangular matrices whose
# entries are boolean lists.
CycleBasisOfGraph := function( dig )

local tree, dige, base, root, e;

if not IsSymmetricDigraph(dig) then
Error("the digraph is assumed to be symmetric");
fi;

base := Set([]);
tree := UndirectedSpanningTree(dig);
dige := DigraphEdges(tree);

root := DigraphVertices(dig)[1];

for e in DigraphEdges(dig) do
if not e in dige then
AddSet(base, CycleOnEdge(tree,root, e));
fi;
od;


return base;
end;;

# This method combines two adjacency matrices with the operator XOR.
XORAdjacencyMatrices := function( mat1, mat2 )

local j, res, nd;

res :=[];
for j in [1.. Length(mat1)] do
nd := IntersectionBlist(mat1[j],mat2[j]);
FlipBlist(nd);
res[j] := IntersectionBlist( UnionBlist(mat1[j],mat2[j]), nd );
od;

return res;
end;;

cyclebasis := CycleBasisOfGraph( digraph );

if cyclebasis=[] then
return [];
fi;

neighs := OutNeighbours(digraph);
allcycles := [];

nullmat := XORAdjacencyMatrices(cyclebasis[1],cyclebasis[1]);
for k in [0..2^Length(cyclebasis)-1] do
# combine the matrices encoded by k
mat := nullmat;
i := k;
pos := 0;
while i>0 do
pos := pos + 1;
if i mod 2 <> 0 then
mat := XORAdjacencyMatrices(mat,cyclebasis[pos]);
fi;
i := Int(i/2);
od;
local edgesOfCycle, i, edge;

if SizeBlist(Flat(mat))<>0 then
for c in __SIMPLICIAL_NodesOfCycle(mat) do
cycle:=__SIMPLICIAL_AdjacencyMatrixFromList(c,Length(mat));
if not cycle in allcycles then
Add(allcycles,cycle);
fi;
od;
edgesOfCycle:=[];
for i in [1..Length(cycle)] do
if i<Length(cycle) then
edge:=[cycle[i],cycle[i+1]];
else
edge:=[cycle[i],cycle[1]];
fi;
od;
return allcycles;

end
);
Sort(edge);
Add(edgesOfCycle,Reversed(edge));
od;

BindGlobal("__SIMPLICIAL_AllChordlessCyclesOfGraph",
function(digraph)
return edgesOfCycle;

local BlockNeighbours, UnblockNeighbours, DegreeLabeling, Triplets, CCExtension, temp, T, C, blocked, triple;

if not IsSymmetricDigraph(digraph) then
return false;
fi;

BlockNeighbours:=function(digraph,v,blocked)
local u;
for u in OutNeighboursOfVertex(digraph,v) do
blocked[u]:=blocked[u]+1;
od;
return blocked;
end;

UnblockNeighbours:=function(digraph,v,blocked)
local u;
for u in OutNeighboursOfVertex(digraph,v) do
if blocked[u]>0 then
blocked[u]:=blocked[u]-1;
fi;
od;
return blocked;
end;

# Computes the degree labeling
DegreeLabeling:=function(digraph)
local degree,color,labeling,v,u,i,minDegree,x;

degree:=List(DigraphVertices(digraph),i->0);
color:=List(DigraphVertices(digraph),i->false);
labeling:=List(DigraphVertices(digraph),i->0);
degree:=List(DigraphVertices(digraph),i->OutDegreeOfVertex(digraph,i));

for i in [1..DigraphNrVertices(digraph)] do
minDegree:=DigraphNrVertices(digraph);
for x in DigraphVertices(digraph) do
if color[x]=false and degree[x]<minDegree then
v:=x;
minDegree:=degree[x];
fi;
od;
labeling[v]:=i;
color[v]:=true;
for u in OutNeighboursOfVertex(digraph,v) do
if color[u]=false then
degree[u]:=degree[u]-1;
fi;
od;
od;
return labeling;
end;

# Computes all possible triplets
Triplets:=function(digraph)
local T,C,u,pair,x,y,labels;
T:=[];
C:=[];
for u in DigraphVertices(digraph) do
for pair in Combinations(OutNeighboursOfVertex(digraph,u),2) do
x:=pair[1];
y:=pair[2];
labels:=DigraphVertexLabels(digraph);
if labels[u]<labels[x] and labels[x]<labels[y] then
if not IsDigraphEdge(digraph,x,y) then
Add(T,[x,u,y]);
else
Add(C,[x,u,y]);
fi;
elif labels[u]<labels[y] and labels[y]<labels[x] then
if not IsDigraphEdge(digraph,x,y) then
Add(T,[y,u,x]);
else
Add(C,[y,u,x]);
fi;
fi;
od;
od;
return [T,C];
end;

# Extends a given chordless path if possible
CCExtension:=function(digraph,path,C,key,blocked)
local v,extendedPath,data;
blocked:=BlockNeighbours(digraph,Last(path),blocked);
for v in OutNeighboursOfVertex(digraph,Last(path)) do
if DigraphVertexLabel(digraph,v)>key and blocked[v]=1 then
extendedPath:=Concatenation(path,[v]);
if IsDigraphEdge(digraph,v,First(path)) then
Add(C,extendedPath);
else
data:=CCExtension(digraph,extendedPath,C,key,blocked);
C:=data[1];
blocked:=data[2];
fi;
fi;
od;
blocked:=UnblockNeighbours(digraph,Last(path),blocked);
return [C,blocked];
end;

SetDigraphVertexLabels(digraph,DegreeLabeling(digraph));
temp:=Triplets(digraph);
T:=temp[1];
C:=temp[2];
blocked:=List(DigraphVertices(digraph),i->0);
while T<>[] do
triple:=Remove(T);
blocked:=BlockNeighbours(digraph,triple[2],blocked);
temp:=CCExtension(digraph,triple,C,DigraphVertexLabel(digraph,triple[2]),blocked);
C:=temp[1];
blocked:=temp[2];
blocked:=UnblockNeighbours(digraph,triple[2],blocked);
od;
return C;

end
end
);

BindGlobal("__SIMPLICIAL_IsNonSeparating",
function(digraph,cycle)

local edgesOfCycle, e, digraphRemoved;
local edgesOfCycle, e, digraphRemoved;

if not IsSymmetricDigraph(digraph) then
return false;
fi;
if not IsSymmetricDigraph(digraph) then
return false;
fi;

edgesOfCycle:=[];
for e in __SIMPLICIAL_EdgesFromAdjacencyMat(cycle) do
Append(edgesOfCycle,[e,Reversed(e)]);
od;
edgesOfCycle:=__SIMPLICIAL_EdgesFromCycle(digraph,cycle);
#for e in __SIMPLICIAL_EdgesFromAdjacencyMat(cycle) do
# Append(edgesOfCycle,[e,Reversed(e)]);
#od;

digraphRemoved:=DigraphRemoveEdges(digraph,edgesOfCycle);
if IsConnectedDigraph(digraphRemoved) then
return true;
else
return false;
fi;
digraphRemoved:=DigraphRemoveEdges(digraph,edgesOfCycle);
if IsConnectedDigraph(digraphRemoved) then
return true;
else
return false;
fi;

end
end
);

InstallOtherMethod(AllSimplicialSurfacesOfDigraph,"for a digraph",
Expand All @@ -1089,17 +866,18 @@ InstallMethod(AllSimplicialSurfacesOfDigraph,"for a digraph and a Boolean",
Error("SimplicialSurfaceOfDigraph: Given digraph has to be simple, symmetric and connected");
fi;
if vertexFaithful then
allCycles:=List(__SIMPLICIAL_AllChordlessCyclesOfGraph(digraph),c->__SIMPLICIAL_AdjacencyMatrixFromList(c,DigraphNrVertices(digraph)));
allCycles:=Filtered(allCycles,c->__SIMPLICIAL_IsNonSeparating(digraph,c));
#allCycles:=List(DigraphAllChordlessCycles(digraph),c->__SIMPLICIAL_AdjacencyMatrixFromList(c,DigraphNrVertices(digraph)));
allCycles:=DigraphAllChordlessCycles(digraph);
allCycles:=Filtered(allCycles,c->__SIMPLICIAL_IsNonSeparating(digraph,c));
else
allCycles:=__SIMPLICIAL_AllCyclesOfGraph(digraph);
allCycles:=DigraphAllUndirectedSimpleCircuits(digraph);
fi;

edgesOfGraph:=Filtered(DigraphEdges(digraph),e->not IsSortedList(e));

edgesOfCycles:=[];
for cycle in [1..Length(allCycles)] do;
edgesOfCycles[cycle]:=List(__SIMPLICIAL_EdgesFromAdjacencyMat(allCycles[cycle]),e->Position(edgesOfGraph,e));
edgesOfCycles[cycle]:=List(__SIMPLICIAL_EdgesFromCycle(digraph,allCycles[cycle]),e->Position(edgesOfGraph,e));
od;

possibleCyclesPairs:=[];
Expand Down Expand Up @@ -1195,10 +973,10 @@ InstallMethod(AllSimplicialSurfacesOfDigraph,"for a digraph and a Boolean",

# if we search vertex-faithful simplicial surfaces all cycles of length three and four have to be part of the resulting cycle combination
if vertexFaithful and IsIsomorphicDigraph(graph, CompleteDigraph(4)) then
smallCy:=Filtered([1..Length(allCycles)], c->SizeBlist(Flat(allCycles[c]))<4);
smallCy:=Filtered(allCycles, c->Length(c)<4);
smallCy:=BlistList([1..Length(allCycles)],smallCy);
elif vertexFaithful then
smallCy:=Filtered([1..Length(allCycles)], c->SizeBlist(Flat(allCycles[c]))<5);
smallCy:=Filtered(allCycles, c->Length(c)<5);
smallCy:=BlistList([1..Length(allCycles)],smallCy);
fi;

Expand Down Expand Up @@ -1257,7 +1035,7 @@ InstallMethod(AllSimplicialSurfacesOfDigraph,"for a digraph and a Boolean",
umbrellaDesk:=[];

for cycle in ListBlist([1..Length(vertexCycleComb)],vertexCycleComb) do
Add(umbrellaDesk,NodesOfCycle(allCycles[cycle]));
Add(umbrellaDesk,CycleFromList(allCycles[cycle]));
od;

face:=SimplicialSurfaceByUmbrellaDescriptor(umbrellaDesk);
Expand Down
Loading

0 comments on commit f7c28f1

Please sign in to comment.