graph Version 0.20 Is Out

graph is a generic Go library for creating and working with graph data structures. The freshly released version 0.20 facilitates the management of vertices and edges.

May 1, 2023 in Go

The most recent release contains important changes that further mature the Graph interface and hence marks an important milestone. While the tests and stability have been improved, version 0.20 also enhances the management of vertices and edges.

Adding Vertices From Another Graph

In the past, adding all vertices from a graph to some other graph required an adjacency map of the original graph, as well as a loop over its vertices. These efforts are not necessary anymore. Graph.AddVerticesFrom allows the user to add all vertices within a single call.

g := graph.New(graph.IntHash)

// Add 100 vertices to the original graph g.
for i := 0; i < 100; i++ {
    _ = g.AddVertex(i)
}


h := graph.New(graph.IntHash)

_ = h.AddVerticesFrom(g) // New!

In this example, the graph h will contain all 100 vertices copied from g. The original graph will remain unchanged, of course.

Adding Edges From Another Graph

Just as with vertices, adding all edges from another graph used to be a manual effort. Fortunately, graph v0.20 also introduces a sister function of Graph.AddVerticesFrom for adding all edges from another graph: Graph.AddEdgesFrom.

_ = g.AddEdgesFrom(g) // New!

Note that all the vertices joined by the added edges have to exit already, so a preceding AddVerticesFrom call might be required.

Retrieving All Edges From a Graph

Getting all edges in a graph wasn't too straight-forward in the past, since it required an adjacency map and two nested loops. This is now much easier using the new Graph.Edges method.

edges, err := g.Edges() // New!

The edges variable is a slice containing all edges in the graph. In an undirected graph, an edge (1,2) will either be contained as (1,2) or (2,1) – so that an Graph.AddEdge call in an iteration over Graph.Edges is always safe to perform.

Updating an Edge

One thing that simply wasn't possible until graph v0.20 is to modify an existing edge and its properties. A workaround was to remove the edge and re-create it with the updated properties. This isn't necessary anymore. Graph.UpdateEdge offers the exact same API as Graph.AddEdge and updates the properties of an existing edge.

_ = g.AddEdge(1, 2, graph.EdgeWeight(10), graph.EdgeAttribute("color", "red"))
_ = g.UpdateEdge(1, 2, graph.EdgeWeight(20), graph.EdgeAttribute("color", "blue")) // New!

The UpdateEdge call updates the weight of the edge joining 1 and 2 to 20 and sets the color attribute to blue. The edge needs to exist, of course.

A New Graph That Is "Like" Another Graph

graph v0.20 also adds support for creating a new graph that has the same type, the same hashing function, and the same traits as another graph. NewLike creates a graph that is "like" the given graph:

g := graph.New(graph.IntHash, graph.Directed())
h := graph.NewLike(g) // New!

In the example above, h is a directed graph of integers just like g. In a way, NewLike is similar to Graph.Clone but without the data.

Setting All Edge Attributes at Once

Multiple calls to graph.EdgeAttribute can get a bit tedious when adding an edge with many attributes. The new EdgeAttributes functional option allows to pass an entire attributes at once.

attributes := map[string]string{
    "color": "red",
    "label": "my-edge",
}

_ = g.AddEdge(1, 2, graph.EdgeAttributes(attributes)) // New!

To try it yourself, go get graph.

💫graph: A library for creating generic graph data structures and modifying, analyzing, and visualizing them.
💫
graph: A library for creating generic graph data structures and modifying, analyzing, and visualizing them.