v / examples / graphs / topological_sorting_greedy.v
146 lines · 133 sloc · 4.07 KB · 993546a0a2414a23fe0abf45d0c4f9b5dc31c1c1
Raw
1// The idea of this algorithm follow :
2// https://www.gatevidyalay.com/topological-sort-topological-sorting/ (GREEDY)
3// (no cycles are detected)
4// https://en.wikipedia.org/wiki/Topological_sorting ... just the input data
5// and the Kahn algorithm
6// Author: CCS
7
8// the idea is rude: https://www.gatevidyalay.com/topological-sort-topological-sorting/
9fn topog_sort_greedy(graph map[string][]string) []string {
10 n_nodes := graph.len // numbers of nodes of this graph
11 mut top_order := []string{} // a vector with sequence of nodes visited
12 mut count := 0
13 /*
14 IDEA ( a greedy algorithm ):
15
16 1. choose always the node with smallest input degree
17 2. visit it
18 3. put it in the output vector
19 4. remove it from graph
20 5. update the graph (a new graph)
21 6. find a new vector degree
22 7. until all nodes has been visited
23 Back to step 1 (used the variable count)
24
25 Maybe it seems the Kahn's algorithm
26 */
27 mut v_degree := in_degree(graph) // return: map [string] int
28 print('V Degree ${v_degree}')
29 mut small_degree := min_degree(v_degree)
30 mut new_graph := remove_node_from_graph(small_degree, graph)
31 top_order << small_degree
32 count++
33
34 for (count < n_nodes) {
35 v_degree = in_degree(new_graph) // return: map [string] int
36 print('\nV Degree ${v_degree}')
37 small_degree = min_degree(v_degree)
38 new_graph = remove_node_from_graph(small_degree, new_graph)
39
40 top_order << small_degree
41 count++
42 }
43 // print("\n New Graph ${new_graph}")
44
45 return top_order
46}
47
48// Give a node, return a list with all nodes incidents or fathers of this node
49fn all_fathers(node string, a_map map[string][]string) []string {
50 mut array_of_keys := a_map.keys() // get a key of this map
51 mut all_incident := []string{}
52 for i in array_of_keys {
53 // in : function
54 if node in a_map[i] {
55 all_incident << i // a queue of this search
56 }
57 }
58 return all_incident
59}
60
61// Input: a map with input degree values, return the key with smallest value
62fn min_degree(a_map map[string]int) string {
63 mut array_of_keys := a_map.keys() // get a key of this map
64 mut key_min := array_of_keys.first()
65 mut val_min := a_map[key_min]
66 // print("\n MIN: ${val_min} \t key_min: ${key_min} \n the map inp_degree: ${a_map}")
67 for i in array_of_keys {
68 // there is a smaller
69 if val_min > a_map[i] {
70 val_min = a_map[i]
71 key_min = i
72 }
73 }
74 return key_min // the key with smallest value
75}
76
77// Given a graph ... return a list of integer with degree of each node
78fn in_degree(a_map map[string][]string) map[string]int {
79 mut array_of_keys := a_map.keys() // get a key of this map
80 // print(array_of_keys)
81 mut degree := map[string]int{}
82 for i in array_of_keys {
83 degree[i] = all_fathers(i, a_map).len
84 }
85 // print("\n Degree ${in_degree}" )
86 return degree // a vector of the indegree graph
87}
88
89// REMOVE A NODE FROM A GRAPH AND RETURN ANOTHER GRAPH
90fn remove_node_from_graph(node string, a_map map[string][]string) map[string][]string {
91 // mut new_graph := map [string] string {}
92 mut new_graph := a_map.clone() // copy the graph
93 new_graph.delete(node)
94 mut all_nodes := new_graph.keys() // get all nodes of this graph
95 // FOR THE FUTURE with filter
96 // for i in all_nodes {
97 // new_graph[i] = new_graph[i].filter(index(it) != node)
98 // }
99 // A HELP FROM V discussion GITHUB - thread
100 for key in all_nodes {
101 i := new_graph[key].index(node)
102 if i >= 0 {
103 new_graph[key].delete(i)
104 }
105 }
106 // print("\n NEW ${new_graph}" )
107 return new_graph
108}
109
110fn main() {
111 // A map illustration to use in a graph
112 // adjacency matrix
113 graph_01 := {
114 'A': ['C', 'B']
115 'B': ['D']
116 'C': ['D']
117 'D': []
118 }
119
120 graph_02 := {
121 'A': ['B', 'C', 'D']
122 'B': ['E']
123 'C': ['F']
124 'D': ['G']
125 'E': ['H']
126 'F': ['H']
127 'G': ['H']
128 'H': []
129 }
130 // from: https://en.wikipedia.org/wiki/Topological_sorting
131 graph_03 := {
132 '5': ['11']
133 '7': ['11', '8']
134 '3': ['8', '10']
135 '11': ['2', '9', '10']
136 '8': ['9']
137 '2': []
138 '9': []
139 '10': []
140 }
141
142 println('\nA Topological Sort of G1: ${topog_sort_greedy(graph_01)}')
143 println('\nA Topological Sort of G2: ${topog_sort_greedy(graph_02)}')
144 println('\nA Topological Sort of G3: ${topog_sort_greedy(graph_03)}')
145 // ['2', '9', '10', '11', '5', '8', '7', '3']
146}
147