v / examples / graphs / bellman-ford.v
161 lines · 145 sloc · 4.3 KB · 5d99138cb2128ecf274268caff22ea85ebcc45be
Raw
1/*
2A V program for Bellman-Ford's single source
3shortest path algorithm.
4literally adapted from:
5https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
6// Adapted from this site... from C++ and Python codes
7
8For Portuguese reference
9http://rascunhointeligente.blogspot.com/2010/10/o-algoritmo-de-bellman-ford-um.html
10
11code by CCS
12*/
13
14const large = 999999 // almost infinity
15
16// a structure to represent a weighted edge in graph
17struct EDGE {
18mut:
19 src int
20 dest int
21 weight int
22}
23
24// building a map of with all edges etc of a graph, represented from a matrix adjacency
25// Input: matrix adjacency --> Output: edges list of src, dest and weight
26fn build_map_edges_from_graph[T](g [][]T) map[T]EDGE {
27 n := g.len // TOTAL OF NODES for this graph -- its dimensions
28 mut edges_map := map[int]EDGE{} // a graph represented by map of edges
29
30 mut edge := 0 // a counter of edges
31 for i in 0 .. n {
32 for j in 0 .. n {
33 // if exist an arc ... include as new edge
34 if g[i][j] != 0 {
35 edges_map[edge] = EDGE{i, j, g[i][j]}
36 edge++
37 }
38 }
39 }
40 // print('${edges_map}')
41 return edges_map
42}
43
44fn print_sol(dist []int) {
45 n_vertex := dist.len
46 print('\n Vertex Distance from Source')
47 for i in 0 .. n_vertex {
48 print('\n ${i} --> ${dist[i]}')
49 }
50}
51
52// The main function that finds shortest distances from src
53// to all other vertices using Bellman-Ford algorithm. The
54// function also detects negative weight cycle
55fn bellman_ford[T](graph [][]T, src int) {
56 mut edges := build_map_edges_from_graph[int](graph)
57 // this function was done to adapt a graph representation
58 // by a adjacency matrix, to list of adjacency (using a MAP)
59 n_edges := edges.len // number of EDGES
60
61 // Step 1: Initialize distances from src to all other
62 // vertices as INFINITE
63 n_vertex := graph.len // adjc matrix ... n nodes or vertex
64 mut dist := []int{len: n_vertex, init: large} // dist with -1 instead of INFINITY
65 // mut path := []int{len: n , init:-1} // previous node of each shortest path
66 dist[src] = 0
67
68 // Step 2: Relax all edges |V| - 1 times. A simple
69 // shortest path from src to any other vertex can have
70 // at-most |V| - 1 edges
71
72 for _ in 0 .. n_vertex {
73 for j in 0 .. n_edges {
74 mut u := edges[j].src
75 mut v := edges[j].dest
76 mut weight := edges[j].weight
77 if dist[u] != large && dist[u] + weight < dist[v] {
78 dist[v] = dist[u] + weight
79 }
80 }
81 }
82
83 // Step 3: check for negative-weight cycles. The above
84 // step guarantees shortest distances if graph doesn't
85 // contain negative weight cycle. If we get a shorter
86 // path, then there is a cycle.
87 for j in 0 .. n_vertex {
88 mut u := edges[j].src
89 mut v := edges[j].dest
90 mut weight := edges[j].weight
91 if dist[u] != large && dist[u] + weight < dist[v] {
92 print('\n Graph contains negative weight cycle')
93 // If negative cycle is detected, simply
94 // return or an exit(1)
95 return
96 }
97 }
98 print_sol(dist)
99}
100
101fn main() {
102 // adjacency matrix = cost or weight
103 graph_01 := [
104 [0, -1, 4, 0, 0],
105 [0, 0, 3, 2, 2],
106 [0, 0, 0, 0, 0],
107 [0, 1, 5, 0, 0],
108 [0, 0, 0, -3, 0],
109 ]
110 // data from https://www.geeksforgeeks.org/bellman-ford-algorithm-dp-23/
111
112 graph_02 := [
113 [0, 2, 0, 6, 0],
114 [2, 0, 3, 8, 5],
115 [0, 3, 0, 0, 7],
116 [6, 8, 0, 0, 9],
117 [0, 5, 7, 9, 0],
118 ]
119 // data from https://www.geeksforgeeks.org/prims-minimum-spanning-tree-mst-greedy-algo-5/
120 /*
121 The graph:
122 2 3
123 (0)--(1)--(2)
124 | / \ |
125 6| 8/ \5 |7
126 | / \ |
127 (3)-------(4)
128 9
129 */
130
131 /*
132 Let us create following weighted graph
133 From https://www.geeksforgeeks.org/kruskals-minimum-spanning-tree-algorithm-greedy-algo-2/?ref=lbp
134 10
135 0--------1
136 | \ |
137 6| 5\ |15
138 | \ |
139 2--------3
140 4
141 */
142 graph_03 := [
143 [0, 10, 6, 5],
144 [10, 0, 0, 15],
145 [6, 0, 0, 4],
146 [5, 15, 4, 0],
147 ]
148
149 // To find number of columns
150 // mut cols := an_array[0].len
151 mut graph := [][]int{} // the graph: adjacency matrix
152 // for index, g_value in [graph_01, graph_02, graph_03] {
153 for index, g_value in [graph_01, graph_02, graph_03] {
154 graph = g_value.clone() // graphs_sample[g].clone() // choice your SAMPLE
155 // always starting by node 0
156 start_node := 0
157 println('\n\n Graph ${index + 1} using Bellman-Ford algorithm (source node: ${start_node})')
158 bellman_ford(graph, start_node)
159 }
160 println('\n BYE -- OK')
161}
162