goraph

package module
v0.0.0-...-9b53f19 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 18, 2023 License: Apache-2.0 Imports: 3 Imported by: 0

README

Golang Graph

Build Status codecov Go Report Card GoDoc License

Goraph is a golang package provides basic graph structures and algorithms.

Goraph is NOT concurrent safe.

Current implemented(√) and planned(×) algorithms:

Algorithm BFS DFS TopologicalSort Kruskal Prim Dijkstra Yen Kisp BellmanFord FloydWarshall EdmondsKarp
Complex O(V+E) O(V+E) O(V+E) O(ElogE) O(E+VlogV)¹ O(E+VlogV)¹ O(KV(E+VlogV)) O(KVlogV) O(VE) O(V3) O(VE2)
Status × × × × × × × ×

¹ With Fibonacci heap.

Algorithms Introduction

  • BFS: breadth first search.

  • DFS: depth first search.

  • TopologicalSort: is a linear ordering of a directed graph's vertices such that for every directed edge uv from vertex u to vertex v, u comes before v in the ordering.

  • Kruskal: is a minimum-spanning-tree algorithm which finds an edge of the least possible weight that connects any two trees in the forest.

  • Prim: is a greedy algorithm that finds a minimum spanning tree for a weighted undirected graph

  • Dijkstra: computes shortest paths from a single source vertex to all of the other vertices in a graph with non-negative edge cost.

  • Yen: computes K-shortest loopless paths between two vertex in a graph with non-negative edge cost.

  • Kisp: computes K-shortest independent paths between two vertex in a graph with non-negative edge cost.

  • BellmanFord: computes shortest paths from a single source vertex to all of the other vertices in a weighted digraph with positive or negative edge weights.

  • FloydWarshall: computes all-pairs shortest paths in a weighted graph with positive or negative edge weights (but with no negative cycles).

  • EdmondsKarp: computes the maximum flow in a flow network(graph).

Requirements

Download this package and its dependency
go get github.com/starwander/GoFibonacciHeap
go get github.com/starwander/goraph
Implements Vertex interface of this package if you want to use AddVertexWithEdges(optional):
type Vertex interface {
	ID() ID
	Edges() []Edge
}

type Edge interface {
	Get() (from ID, to ID, weight float64)
}

Supported Operations

  • Graph operations:
  • GetVertex: get a vertex by input id.
  • GetEdge: gets the edge between the two vertices by input ids.
  • GetEdgeWeight: gets the weight of the edge between the two vertices by input ids.
  • AddVertex: adds a new vertex into the graph.
  • AddEdge: adds a new edge between the vertices by the input ids.
  • UpdateEdgeWeight: updates the weight of the edge between vertices by the input ids.
  • DeleteVertex: deletes a vertex from the graph and gets the value of the vertex.
  • DeleteEdge: deletes the edge between the vertices by the input id from the graph and gets the value of edge.
  • AddVertexWithEdges: adds a vertex value which implements Vertex interface.
  • CheckIntegrity: checks if any edge connects to or from unknown vertex.
  • GetPathWeight: gets the total weight along the path by input ids.
  • DisableEdge: disables the edge for further calculation.
  • DisableVertex: disables the vertex for further calculation.
  • DisablePath: disables all the vertices in the path for further calculation.
  • Reset: enables all vertices and edges for further calculation.
  • Algorithm operations:
  • Dijkstra: gets the shortest path from one vertex to all other vertices in the graph.
  • Yen: gets top k shortest loopless path between two vertex in the graph.
  • Kisp: gets top k shortest independent path between two vertex in the graph.

Example

package main

import (
	"fmt"
	"github.com/starwander/goraph"
)

type myVertex struct {
	id     string
	outTo  map[string]float64
	inFrom map[string]float64
}

type myEdge struct {
	from   string
	to     string
	weight float64
}

func (vertex *myVertex) ID() goraph.ID {
	return vertex.id
}

func (vertex *myVertex) Edges() (edges []goraph.Edge) {
	edges = make([]goraph.Edge, len(vertex.outTo)+len(vertex.inFrom))
	i := 0
	for to, weight := range vertex.outTo {
		edges[i] = &myEdge{vertex.id, to, weight}
		i++
	}
	for from, weight := range vertex.inFrom {
		edges[i] = &myEdge{from, vertex.id, weight}
		i++
	}
	return
}

func (edge *myEdge) Get() (goraph.ID, goraph.ID, float64) {
	return edge.from, edge.to, edge.weight
}

func main() {
	//Dikjstra: The distance from S to T is  44
	//Dikjstra: The path from S to T is: T<-F<-E<-B<-S
	Dijkstra()

	//Yen 1st: The distance from A to D is  2
	//Yen 1st: The path from A to D is:  [A D]
	//Yen 2nd: The distance from A to D is  3
	//Yen 2nd: The path from A to D is:  [A B C D]
	//Yen 3rd: The distance from A to D is  4
	//Yen 3rd: The path from A to D is:  [A B E D]
	Yen()

	//Kisp 1st: The distance from A to D is  5
	//Kisp 1st: The path from A to D is:  [C E F H]
	//Kisp 2nd: The distance from A to D is  11
	//Kisp 2nd: The path from A to D is:  [C D F G H]
	//Kisp 3rd: The distance from A to D is  +Inf
	//Kisp 3rd: The path from A to D is:  []
	Kisp()
}

func Dijkstra() {
	graph := goraph.NewGraph()
	graph.AddVertexWithEdges(&myVertex{"S", map[string]float64{"B": 14}, map[string]float64{"A": 15, "B": 14, "C": 9}})
	graph.AddVertexWithEdges(&myVertex{"A", map[string]float64{"S": 15, "B": 5, "D": 20, "T": 44}, map[string]float64{"B": 5, "D": 20, "T": 44}})
	graph.AddVertexWithEdges(&myVertex{"B", map[string]float64{"S": 14, "A": 5, "D": 30, "E": 18}, map[string]float64{"S": 14, "A": 5, "D": 30, "E": 18}})
	graph.AddVertexWithEdges(&myVertex{"C", map[string]float64{"S": 9, "E": 24}, map[string]float64{"E": 24}})
	graph.AddVertexWithEdges(&myVertex{"D", map[string]float64{"A": 20, "B": 30, "E": 2, "F": 11, "T": 16}, map[string]float64{"A": 20, "B": 30, "E": 2, "F": 11, "T": 16}})
	graph.AddVertexWithEdges(&myVertex{"E", map[string]float64{"B": 18, "C": 24, "D": 2, "F": 6, "T": 19}, map[string]float64{"B": 18, "C": 24, "D": 2, "F": 6, "T": 19}})
	graph.AddVertexWithEdges(&myVertex{"F", map[string]float64{"D": 11, "E": 6, "T": 6}, map[string]float64{"D": 11, "E": 6, "T": 6}})
	graph.AddVertexWithEdges(&myVertex{"T", map[string]float64{"A": 44, "D": 16, "E": 19, "F": 6}, map[string]float64{"A": 44, "D": 16, "E": 19, "F": 6}})

	dist, prev, _ := graph.Dijkstra("S")
	fmt.Println("Dikjstra: The distance from S to T is ", dist["T"])
	fmt.Print("Dikjstra: The path from S to T is: T")
	node := prev["T"]
	for node != nil {
		fmt.Printf("<-%s", node)
		node = prev[node]
	}
	fmt.Println()
}

func Yen() {
	graph := goraph.NewGraph()
	graph.AddVertex("A", nil)
	graph.AddVertex("B", nil)
	graph.AddVertex("C", nil)
	graph.AddVertex("D", nil)
	graph.AddVertex("E", nil)
	graph.AddEdge("A", "B", 1, nil)
	graph.AddEdge("B", "C", 1, nil)
	graph.AddEdge("C", "D", 1, nil)
	graph.AddEdge("A", "D", 2, nil)
	graph.AddEdge("B", "E", 2, nil)
	graph.AddEdge("E", "D", 1, nil)
	dist, path, _ := graph.Yen("A", "D", 3)
	fmt.Println("Yen 1st: The distance from A to D is ", dist[0])
	fmt.Println("Yen 1st: The path from A to D is: ", path[0])
	fmt.Println("Yen 2nd: The distance from A to D is ", dist[1])
	fmt.Println("Yen 2nd: The path from A to D is: ", path[1])
	fmt.Println("Yen 3rd: The distance from A to D is ", dist[2])
	fmt.Println("Yen 3rd: The path from A to D is: ", path[2])
}

func Kisp() {
	graph := goraph.NewGraph()
	graph.AddVertexWithEdges(&myVertex{"C", map[string]float64{"D": 3, "E": 2}, map[string]float64{}})
	graph.AddVertexWithEdges(&myVertex{"D", map[string]float64{"F": 4}, map[string]float64{"C": 3, "E": 1}})
	graph.AddVertexWithEdges(&myVertex{"E", map[string]float64{"D": 1, "F": 2, "G": 3}, map[string]float64{"C": 2}})
	graph.AddVertexWithEdges(&myVertex{"F", map[string]float64{"G": 2, "H": 1}, map[string]float64{"D": 4, "E": 2}})
	graph.AddVertexWithEdges(&myVertex{"G", map[string]float64{"H": 2}, map[string]float64{"E": 3, "F": 2}})
	graph.AddVertexWithEdges(&myVertex{"H", map[string]float64{}, map[string]float64{"F": 1, "G": 2}})
	dist, path, _ := graph.Kisp("C", "H", 3)
	fmt.Println("Kisp 1st: The distance from A to D is ", dist[0])
	fmt.Println("Kisp 1st: The path from A to D is: ", path[0])
	fmt.Println("Kisp 2nd: The distance from A to D is ", dist[1])
	fmt.Println("Kisp 2nd: The path from A to D is: ", path[1])
	fmt.Println("Kisp 3rd: The distance from A to D is ", dist[2])
	fmt.Println("Kisp 3rd: The path from A to D is: ", path[2])
}

Reference

GoDoc

LICENSE

goraph source code is licensed under the Apache Licence, Version 2.0.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Edge

type Edge struct {
	TargetVerget *vertex
	SourceVertex *vertex

	LocalPort    string // LocalPort is the port on THIS switch (vertex) that is connected to the OTHER switch
	LocalPortID  string // uuid of the localPort in TFC API
	RemotePort   string // RemotePort is the port on the OTHER switch that is connected to this switch.
	RemotePortID string // uuid of the remotePort in TFC API
	// contains filtered or unexported fields
}

func (*Edge) Disable

func (edge *Edge) Disable()

func (*Edge) Enable

func (edge *Edge) Enable()

func (*Edge) GetMaxWeight

func (edge *Edge) GetMaxWeight() float64

func (*Edge) GetWeight

func (edge *Edge) GetWeight() float64

func (*Edge) IsDisabled

func (edge *Edge) IsDisabled() bool

func (*Edge) IsEnabled

func (edge *Edge) IsEnabled() bool

func (*Edge) ResetTempWeight0

func (edge *Edge) ResetTempWeight0()

func (*Edge) SetMaxWeight

func (edge *Edge) SetMaxWeight(weight float64)

func (*Edge) SetTempWeight0

func (edge *Edge) SetTempWeight0()

func (*Edge) SetWeight

func (edge *Edge) SetWeight(weight float64)

type Graph

type Graph struct {
	// contains filtered or unexported fields
}

Graph is made up of vertices and edges. Vertices in the graph must have an unique id. Each edges in the graph connects two vertices directed with a weight.

func NewGraph

func NewGraph() *Graph

NewGraph creates a new empty graph.

func (*Graph) AddEdge

func (graph *Graph) AddEdge(from ID, to ID, localPort, localPortId, remotePort, remotePortId string, weight float64, maxWeight float64) error

AddEdge adds a new edge between the vertices by the input ids. Try to add an edge with -Inf weight will get an error. Try to add an edge from or to a vertex not in the graph will get an error. Try to add a duplicate edge will get an error.

func (*Graph) AddVertex

func (graph *Graph) AddVertex(id ID, name string) error

AddVertex adds a new vertex into the graph. Try to add a duplicate vertex will get an error.

func (*Graph) DeleteEdge

func (graph *Graph) DeleteEdge(from ID, to ID) interface{}

DeleteEdge deletes the edge between the vertices by the input id from the graph and gets the value of edge. Try to delete an edge from or to a vertex not in the graph will get an error. Try to delete an edge between disconnected vertices will get a nil.

func (*Graph) DeleteEdgeByLocalPort

func (graph *Graph) DeleteEdgeByLocalPort(from ID, localPort string) *Edge

DeleteEdge deletes the edge between the vertices by the input id from the graph and gets the value of edge. Try to delete an edge from or to a vertex not in the graph will get an error. Try to delete an edge between disconnected vertices will get a nil.

func (*Graph) DeleteVertex

func (graph *Graph) DeleteVertex(id ID) interface{}

DeleteVertex deletes a vertex from the graph and gets the value of the vertex. Try to delete a vertex not in the graph will get an nil.

func (*Graph) Dijkstra

func (graph *Graph) Dijkstra(source ID) (dist map[ID]float64, prev map[ID]ID, err error)

Dijkstra gets the shortest path from one vertex to all other vertices in the graph. https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

func (*Graph) DisableEdge

func (graph *Graph) DisableEdge(from, to ID)

DisableEdge disables the edge for further calculation.

func (*Graph) DisablePath

func (graph *Graph) DisablePath(path []ID)

DisablePath disables all the vertices in the path for further calculation.

func (*Graph) DisableVertex

func (graph *Graph) DisableVertex(vertex ID)

DisableVertex disables the vertex for further calculation.

func (*Graph) EnableVertex

func (graph *Graph) EnableVertex(vertex ID)

EnableVertex disables the vertex for further calculation.

func (*Graph) GetAllEdges

func (graph *Graph) GetAllEdges() map[ID]map[ID][]*Edge

func (*Graph) GetAllVertices

func (graph *Graph) GetAllVertices() map[ID]*vertex

func (*Graph) GetEdge

func (graph *Graph) GetEdge(from ID, to ID, localPort, remotePort string) (*Edge, error)

func (*Graph) GetEdgeWeight

func (graph *Graph) GetEdgeWeight(from ID, to ID) (float64, error)

GetEdgeWeight gets the weight of the edge between the two vertices by input ids. Try to get the weight of the edge from or to a vertex not in the graph will get an error. Try to get the weight of the edge between two disconnected vertices will get +Inf.

func (*Graph) GetEdges

func (graph *Graph) GetEdges(from ID, to ID) ([]*Edge, error)

GetEdge gets the edge between the two vertices by input ids. Try to get the edge from or to a vertex not in the graph will get an error. Try to get the edge between two disconnected vertices will get an error.

func (*Graph) GetPathWeight

func (graph *Graph) GetPathWeight(path []ID) (totalWeight float64)

GetPathWeight gets the total weight along the path by input ids. It will get -Inf if the input path is nil or empty. It will get -Inf if the path contains vertex not in the graph. It will get +Inf if the path contains vertices not connected.

func (*Graph) GetVertex

func (graph *Graph) GetVertex(id ID) (vertex *vertex, err error)

GetVertex get a vertex by input id. Try to get a vertex not in the graph will get an error.

func (*Graph) HasEdge

func (graph *Graph) HasEdge(from ID, to ID, localPort, remotePort string) bool

func (*Graph) HasVertex

func (graph *Graph) HasVertex(id ID) bool

GetVertex get a vertex by input id. Try to get a vertex not in the graph will get an error.

func (*Graph) Kisp

func (graph *Graph) Kisp(source, destination ID, topK int) ([]float64, [][]ID, error)

Kisp gets top k shortest independent path between two vertex in the graph. Independent means no vertex is shared between path.

func (*Graph) Reset

func (graph *Graph) Reset()

Reset enables all vertices and edges for further calculation.

type ID

type ID interface{}

ID uniquely identify a vertex.

type Vertex

type Vertex interface {
	// ID get the unique id of the vertex.
	ID() ID
	// Edges get all the edges connected to the vertex
	Edges() []Edge
}

Vertex interface represents a vertex with edges connected to it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL