Rafael Mrden
Rafael Mrden

Reputation: 115

Plotting non-injective labels on vertices in a graph in SageMath

I have a graph with vertices labeled by some pairs (a,b). Can I plot it in such a way that I only see the first component "a" printed over each vertex? I cannot just relabel, since my map (a,b)->a is not injective.

For a small example, take

G = Graph()
G.add_edge((1,1),(1,2))

The usual G.plot() gives (1,1)---(1,2). Instead, how to produce only 1---1 ?

Upvotes: 1

Views: 399

Answers (1)

Samuel Lelièvre
Samuel Lelièvre

Reputation: 3453

Plot a Sage graph with non-injective vertex labals

We describe a slightly tedious workaround, and then a way to recover our comfort.

New class for vertices

One solution consists in writing a new class for vertices that inherits from tuple and has a custom __str__ method that returns a string for only the first entry in the tuple.

class MyVertex(tuple):
    r"""
    Class for vertices for special plotting of graphs.

    Use with tuples, and only the first entry in the tuple
    will be used as a vertex label when plotting the graph.
    """
    def __init__(self, v):
        self.vertex = v

    def __str__(self):
        return str(self.vertex[0])

Using this to define the vertices of the graph, we obtain the desired behaviour.

Define a graph and add an edge from (1, 1) to (1, 2):

sage: G = Graph()
sage: G.add_edge(MyVertex((1, 1)), MyVertex((1, 2)))

When plotting the graph, both vertices have the label 1.

sage: G.plot()
Launched png viewer for Graphics object consisting of 4 graphics primitives

When listing the vertices, they still appear fully:

sage: G.vertices()
[(1, 1), (1, 2)]

Using usual graphs

To avoid having to use MyVertex explicitly, we write a graph-plotting function that creates an intermediate "MyVertex"-style copy of a usual graph for the sake of plotting.

def plot_graph(G):
    r"""
    Return a plot of this graph with special vertex labels.

    The graph vertices are assumed to be tuples. The plot
    uses the first component of each tuple as a vertex label.
    """
    E = [(MyVertex(a), MyVertex(b)) for (a, b) in G.edges(labels=False)]
    return Graph(E).plot()

Now compare:

sage: G = graphs.Grid2dGraph(3, 4)
sage: G.plot()
Launched png viewer for Graphics object consisting of 30 graphics primitives
sage: plot_graph(G)
Launched png viewer for Graphics object consisting of 30 graphics primitives

Upvotes: 1

Related Questions