Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Added LexUP
Browse files Browse the repository at this point in the history
  • Loading branch information
giorgosgiapis committed Jul 15, 2019
1 parent 6593331 commit fe62167
Showing 1 changed file with 156 additions and 0 deletions.
156 changes: 156 additions & 0 deletions src/sage/graphs/traversals.pyx
Expand Up @@ -193,6 +193,162 @@ def lex_BFS(G, reverse=False, tree=False, initial_vertex=None):
else:
return value

def lex_UP(G, reverse=False, tree=False, initial_vertex=None):
r"""
Perform a lexicographic UP search (LexUP) on the graph.
INPUT:
- ``G`` -- a sage graph
- ``reverse`` -- boolean (default: ``False``); whether to return the
vertices in discovery order, or the reverse
- ``tree`` -- boolean (default: ``False``); whether to return the
discovery directed tree (each vertex being linked to the one that saw
it for the first time)
- ``initial_vertex`` -- (default: ``None``); the first vertex to
consider
ALGORITHM:
This algorithm maintains for each vertex left in the graph a code
corresponding to the vertices already removed. The vertex of maximal
code (according to the lexicographic order) is then removed, and the
codes are updated.
Time complexity is `O(n+m)` where `n` is the number of vertices and `m` is
the number of edges.
EXAMPLES:
A Lex BFS is obviously an ordering of the vertices::
sage: g = graphs.CompleteGraph(6)
sage: len(g.lex_BFS()) == g.order()
True
Lex BFS ordering of the 3-sun graph::
sage: g = Graph([(1, 2), (1, 3), (2, 3), (2, 4), (2, 5), (3, 5), (3, 6), (4, 5), (5, 6)])
sage: g.lex_BFS()
[1, 2, 3, 5, 4, 6]
The method also works for directed graphs::
sage: G = DiGraph([(1, 2), (2, 3), (1, 3)])
sage: G.lex_BFS(initial_vertex=2)
[2, 3, 1]
For a Chordal Graph, a reversed Lex BFS is a Perfect Elimination Order::
sage: g = graphs.PathGraph(3).lexicographic_product(graphs.CompleteGraph(2))
sage: g.lex_BFS(reverse=True) # py2
[(2, 0), (2, 1), (1, 1), (1, 0), (0, 0), (0, 1)]
sage: g.lex_BFS(reverse=True) # py3
[(2, 1), (2, 0), (1, 1), (1, 0), (0, 1), (0, 0)]
And the vertices at the end of the tree of discovery are, for chordal
graphs, simplicial vertices (their neighborhood is a complete graph)::
sage: g = graphs.ClawGraph().lexicographic_product(graphs.CompleteGraph(2))
sage: v = g.lex_BFS()[-1]
sage: peo, tree = g.lex_BFS(initial_vertex = v, tree=True)
sage: leaves = [v for v in tree if tree.in_degree(v) ==0]
sage: all(g.subgraph(g.neighbors(v)).is_clique() for v in leaves)
True
TESTS:
Lex BFS ordering of a graph on one vertex::
sage: Graph(1).lex_BFS(tree=True)
([0], Digraph on 1 vertex)
Lex BFS ordering of an empty (di)graph is an empty sequence::
sage: g = Graph()
sage: g.lex_BFS()
[]
Lex BFS ordering of a symmetric digraph should be the same as the Lex BFS
ordering of the corresponding undirected graph::
sage: G = Graph([(1, 2), (1, 3), (2, 3), (2, 4), (2, 5), (3, 5), (3, 6), (4, 5), (5, 6)])
sage: H = DiGraph(G)
sage: G.lex_BFS() == H.lex_BFS()
True
"""
# Loops and multiple edges are not needed in Lex BFS
if G.allows_loops() or G.allows_multiple_edges():
G = G.to_simple(immutable=False)

cdef int nV = G.order()

if not nV:
if tree:
from sage.graphs.digraph import DiGraph
g = DiGraph(sparse=True)
return [], g
else:
return []

# Build adjacency list of G
cdef list int_to_v = list(G)

cdef short_digraph sd
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_v)

# Perform Lex UP

cdef list code = [[] for i in range(nV)]

def l_func(x):
return code[x]

cdef list value = []

# Initialize the predecessors array
cdef MemoryAllocator mem = MemoryAllocator()
cdef int *pred = <int *>mem.allocarray(nV, sizeof(int))
memset(pred, -1, nV * sizeof(int))

cdef set vertices = set(range(nV))

cdef int source = 0 if initial_vertex is None else int_to_v.index(initial_vertex)
code[source].append(nV + 1)

cdef int now = 1, v, int_neighbor
while vertices:
v = max(vertices, key=l_func)
vertices.remove(v)
for i in range(0, out_degree(sd, v)):
int_neighbor = sd.neighbors[v][i]
if int_neighbor in vertices:
code[int_neighbor].append(now)
pred[int_neighbor] = v
value.append(int_to_v[v])
now += 1

free_short_digraph(sd)

if reverse:
value.reverse()

if tree:
from sage.graphs.digraph import DiGraph
g = DiGraph(sparse=True)
g.add_vertices(G)
edges = [(int_to_v[i], int_to_v[pred[i]]) for i in range(nV) if pred[i] != -1]
g.add_edges(edges)
return value, g

else:
return value

def lex_DFS(G, reverse=False, tree=False, initial_vertex=None):
r"""
Perform a lexicographic depth first search (LexDFS) on the graph.
Expand Down

0 comments on commit fe62167

Please sign in to comment.