Source File
graph.go
Belonging Package
github.com/dominikbraun/graph
// Package graph is a library for creating generic graph data structures and// modifying, analyzing, and visualizing them.//// # Hashes//// A graph consists of vertices of type T, which are identified by a hash value// of type K. The hash value for a given vertex is obtained using the hashing// function passed to [New]. A hashing function takes a T and returns a K.//// For primitive types like integers, you may use a predefined hashing function// such as [IntHash] – a function that takes an integer and uses that integer as// the hash value at the same time://// g := graph.New(graph.IntHash)//// For storing custom data types, you need to provide your own hashing function.// This example takes a City instance and returns its name as the hash value://// cityHash := func(c City) string {// return c.Name// }//// Creating a graph using this hashing function will yield a graph of vertices// of type City identified by hash values of type string.//// g := graph.New(cityHash)//// # Operations//// Adding vertices to a graph of integers is simple. [graph.Graph.AddVertex]// takes a vertex and adds it to the graph.//// g := graph.New(graph.IntHash)//// _ = g.AddVertex(1)// _ = g.AddVertex(2)//// Most functions accept and return only hash values instead of entire instances// of the vertex type T. For example, [graph.Graph.AddEdge] creates an edge// between two vertices and accepts the hash values of those vertices. Because// this graph uses the [IntHash] hashing function, the vertex values and hash// values are the same.//// _ = g.AddEdge(1, 2)//// All operations that modify the graph itself are methods of [Graph]. All other// operations are top-level functions of by this library.//// For detailed usage examples, take a look at the README.package graphimportvar (ErrVertexNotFound = errors.New("vertex not found")ErrVertexAlreadyExists = errors.New("vertex already exists")ErrEdgeNotFound = errors.New("edge not found")ErrEdgeAlreadyExists = errors.New("edge already exists")ErrEdgeCreatesCycle = errors.New("edge would create a cycle")ErrVertexHasEdges = errors.New("vertex has edges"))// Graph represents a generic graph data structure consisting of vertices of// type T identified by a hash of type K.type Graph[ comparable, any] interface {// Traits returns the graph's traits. Those traits must be set when creating// a graph using New.Traits() *Traits// AddVertex creates a new vertex in the graph. If the vertex already exists// in the graph, ErrVertexAlreadyExists will be returned.//// AddVertex accepts a variety of functional options to set further edge// details such as the weight or an attribute://// _ = graph.AddVertex("A", "B", graph.VertexWeight(4), graph.VertexAttribute("label", "my-label"))//AddVertex(value , options ...func(*VertexProperties)) error// AddVerticesFrom adds all vertices along with their properties from the// given graph to the receiving graph.//// All vertices will be added until an error occurs. If one of the vertices// already exists, ErrVertexAlreadyExists will be returned.AddVerticesFrom(g Graph[, ]) error// Vertex returns the vertex with the given hash or ErrVertexNotFound if it// doesn't exist.Vertex(hash ) (, error)// VertexWithProperties returns the vertex with the given hash along with// its properties or ErrVertexNotFound if it doesn't exist.VertexWithProperties(hash ) (, VertexProperties, error)// RemoveVertex removes the vertex with the given hash value from the graph.//// The vertex is not allowed to have edges and thus must be disconnected.// Potential edges must be removed first. Otherwise, ErrVertexHasEdges will// be returned. If the vertex doesn't exist, ErrVertexNotFound is returned.RemoveVertex(hash ) error// AddEdge creates an edge between the source and the target vertex.//// If either vertex cannot be found, ErrVertexNotFound will be returned. If// the edge already exists, ErrEdgeAlreadyExists will be returned. If cycle// prevention has been activated using PreventCycles and if adding the edge// would create a cycle, ErrEdgeCreatesCycle will be returned.//// AddEdge accepts functional options to set further edge properties such as// the weight or an attribute://// _ = g.AddEdge("A", "B", graph.EdgeWeight(4), graph.EdgeAttribute("label", "my-label"))//AddEdge(sourceHash, targetHash , options ...func(*EdgeProperties)) error// AddEdgesFrom adds all edges along with their properties from the given// graph to the receiving graph.//// All vertices that the edges are joining have to exist already. If needed,// these vertices can be added using AddVerticesFrom first. Depending on the// situation, it also might make sense to clone the entire original graph.AddEdgesFrom(g Graph[, ]) error// Edge returns the edge joining two given vertices or ErrEdgeNotFound if// the edge doesn't exist. In an undirected graph, an edge with swapped// source and target vertices does match.Edge(sourceHash, targetHash ) (Edge[], error)// Edges returns a slice of all edges in the graph. These edges are of type// Edge[K] and hence will contain the vertex hashes, not the vertex values.Edges() ([]Edge[], error)// UpdateEdge updates the edge joining the two given vertices with the data// provided in the given functional options. Valid functional options are:// - EdgeWeight: Sets a new weight for the edge properties.// - EdgeAttribute: Adds a new attribute to the edge properties.// - EdgeAttributes: Sets a new attributes map for the edge properties.// - EdgeData: Sets a new Data field for the edge properties.//// UpdateEdge accepts the same functional options as AddEdge. For example,// setting the weight of an edge (A,B) to 10 would look as follows://// _ = g.UpdateEdge("A", "B", graph.EdgeWeight(10))//// Removing a particular edge attribute is not possible at the moment. A// workaround is to create a new map without the respective element and// overwrite the existing attributes using the EdgeAttributes option.UpdateEdge(source, target , options ...func(properties *EdgeProperties)) error// RemoveEdge removes the edge between the given source and target vertices.// If the edge cannot be found, ErrEdgeNotFound will be returned.RemoveEdge(source, target ) error// AdjacencyMap computes an adjacency map with all vertices in the graph.//// There is an entry for each vertex. Each of those entries is another map// whose keys are the hash values of the adjacent vertices. The value is an// Edge instance that stores the source and target hash values along with// the edge metadata.//// For a directed graph with two edges AB and AC, AdjacencyMap would return// the following map://// map[string]map[string]Edge[string]{// "A": map[string]Edge[string]{// "B": {Source: "A", Target: "B"},// "C": {Source: "A", Target: "C"},// },// "B": map[string]Edge[string]{},// "C": map[string]Edge[string]{},// }//// This design makes AdjacencyMap suitable for a wide variety of algorithms.AdjacencyMap() (map[]map[]Edge[], error)// PredecessorMap computes a predecessor map with all vertices in the graph.//// It has the same map layout and does the same thing as AdjacencyMap, but// for ingoing instead of outgoing edges of each vertex.//// For a directed graph with two edges AB and AC, PredecessorMap would// return the following map://// map[string]map[string]Edge[string]{// "A": map[string]Edge[string]{},// "B": map[string]Edge[string]{// "A": {Source: "A", Target: "B"},// },// "C": map[string]Edge[string]{// "A": {Source: "A", Target: "C"},// },// }//// For an undirected graph, PredecessorMap is the same as AdjacencyMap. This// is because there is no distinction between "outgoing" and "ingoing" edges// in an undirected graph.PredecessorMap() (map[]map[]Edge[], error)// Clone creates a deep copy of the graph and returns that cloned graph.//// The cloned graph will use the default in-memory store for storing the// vertices and edges. If you want to utilize a custom store instead, create// a new graph using NewWithStore and use AddVerticesFrom and AddEdgesFrom.Clone() (Graph[, ], error)// Order returns the number of vertices in the graph.Order() (int, error)// Size returns the number of edges in the graph.Size() (int, error)}// Edge represents an edge that joins two vertices. Even though these edges are// always referred to as source and target, whether the graph is directed or not// is determined by its traits.type Edge[ any] struct {SourceTargetProperties EdgeProperties}// EdgeProperties represents a set of properties that each edge possesses. They// can be set when adding a new edge using the corresponding functional options://// g.AddEdge("A", "B", graph.EdgeWeight(2), graph.EdgeAttribute("color", "red"))//// The example above will create an edge with a weight of 2 and an attribute// "color" with value "red".type EdgeProperties struct {Attributes map[string]stringWeight intData any}// Hash is a hashing function that takes a vertex of type T and returns a hash// value of type K.//// Every graph has a hashing function and uses that function to retrieve the// hash values of its vertices. You can either use one of the predefined hashing// functions or provide your own one for custom data types://// cityHash := func(c City) string {// return c.Name// }//// The cityHash function returns the city name as a hash value. The types of T// and K, in this case City and string, also define the types of the graph.type Hash[ comparable, any] func()// New creates a new graph with vertices of type T, identified by hash values of// type K. These hash values will be obtained using the provided hash function.//// The graph will use the default in-memory store for persisting vertices and// edges. To use a different [Store], use [NewWithStore].func [ comparable, any]( Hash[, ], ...func(*Traits)) Graph[, ] {return NewWithStore(, newMemoryStore[, ](), ...)}// NewWithStore creates a new graph same as [New] but uses the provided store// instead of the default memory store.func [ comparable, any]( Hash[, ], Store[, ], ...func(*Traits)) Graph[, ] {var Traitsfor , := range {(&)}if .IsDirected {return newDirected(, &, )}return newUndirected(, &, )}// NewLike creates a graph that is "like" the given graph: It has the same type,// the same hashing function, and the same traits. The new graph is independent// of the original graph and uses the default in-memory storage.//// g := graph.New(graph.IntHash, graph.Directed())// h := graph.NewLike(g)//// In the example above, h is a new directed graph of integers derived from g.func [ comparable, any]( Graph[, ]) Graph[, ] {:= func( *Traits) {.IsDirected = .Traits().IsDirected.IsAcyclic = .Traits().IsAcyclic.IsWeighted = .Traits().IsWeighted.IsRooted = .Traits().IsRooted.PreventCycles = .Traits().PreventCycles}var Hash[, ]if .Traits().IsDirected {= .(*directed[, ]).hash} else {= .(*undirected[, ]).hash}return New(, )}// StringHash is a hashing function that accepts a string and uses that exact// string as a hash value. Using it as Hash will yield a Graph[string, string].func ( string) string {return}// IntHash is a hashing function that accepts an integer and uses that exact// integer as a hash value. Using it as Hash will yield a Graph[int, int].func ( int) int {return}// EdgeWeight returns a function that sets the weight of an edge to the given// weight. This is a functional option for the [graph.Graph.Edge] and// [graph.Graph.AddEdge] methods.func ( int) func(*EdgeProperties) {return func( *EdgeProperties) {.Weight =}}// EdgeAttribute returns a function that adds the given key-value pair to the// attributes of an edge. This is a functional option for the [graph.Graph.Edge]// and [graph.Graph.AddEdge] methods.func (, string) func(*EdgeProperties) {return func( *EdgeProperties) {.Attributes[] =}}// EdgeAttributes returns a function that sets the given map as the attributes// of an edge. This is a functional option for the [graph.Graph.AddEdge] and// [graph.Graph.UpdateEdge] methods.func ( map[string]string) func(*EdgeProperties) {return func( *EdgeProperties) {.Attributes =}}// EdgeData returns a function that sets the data of an edge to the given value.// This is a functional option for the [graph.Graph.Edge] and// [graph.Graph.AddEdge] methods.func ( any) func(*EdgeProperties) {return func( *EdgeProperties) {.Data =}}// VertexProperties represents a set of properties that each vertex has. They// can be set when adding a vertex using the corresponding functional options://// _ = g.AddVertex("A", "B", graph.VertexWeight(2), graph.VertexAttribute("color", "red"))//// The example above will create a vertex with a weight of 2 and an attribute// "color" with value "red".type VertexProperties struct {Attributes map[string]stringWeight int}// VertexWeight returns a function that sets the weight of a vertex to the given// weight. This is a functional option for the [graph.Graph.Vertex] and// [graph.Graph.AddVertex] methods.func ( int) func(*VertexProperties) {return func( *VertexProperties) {.Weight =}}// VertexAttribute returns a function that adds the given key-value pair to the// vertex attributes. This is a functional option for the [graph.Graph.Vertex]// and [graph.Graph.AddVertex] methods.func (, string) func(*VertexProperties) {return func( *VertexProperties) {.Attributes[] =}}// VertexAttributes returns a function that sets the given map as the attributes// of a vertex. This is a functional option for the [graph.Graph.AddVertex] methods.func ( map[string]string) func(*VertexProperties) {return func( *VertexProperties) {.Attributes =}}
![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |