2 * Copyright © 2017-2018 AT&T Intellectual Property.
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
17 package org.onap.ccsdk.apps.controllerblueprints.core.utils
\r
24 * @author Brinda Santh
\r
26 class TopologicalSortingUtils<V> {
\r
28 private val neighbors: MutableMap<V, MutableList<V>> = hashMapOf()
\r
31 get() = topSort() != null
\r
33 override fun toString(): String {
\r
34 val s = StringBuffer()
\r
35 for (v in neighbors.keys)
\r
36 s.append("\n " + v + " -> " + neighbors[v])
\r
40 fun getNeighbors(): Map<V, List<V>> {
\r
44 fun add(vertex: V) {
\r
45 if (neighbors.containsKey(vertex))
\r
47 neighbors[vertex] = arrayListOf()
\r
50 operator fun contains(vertex: V): Boolean {
\r
51 return neighbors.containsKey(vertex)
\r
54 fun add(from: V, to: V) {
\r
57 neighbors[from]?.add(to)
\r
60 fun remove(from: V, to: V) {
\r
61 if (!(this.contains(from) && this.contains(to)))
\r
62 throw IllegalArgumentException("Nonexistent vertex")
\r
63 neighbors[from]?.remove(to)
\r
66 fun outDegree(): Map<V, Int> {
\r
67 var result: MutableMap<V, Int> = hashMapOf()
\r
68 for (v in neighbors.keys)
\r
69 result[v] = neighbors[v]!!.size
\r
74 fun inDegree(): MutableMap<V, Int> {
\r
75 val result = HashMap<V, Int>()
\r
76 for (v in neighbors.keys)
\r
77 result[v] = 0 // All in-degrees are 0
\r
78 for (from in neighbors.keys) {
\r
79 for (to in neighbors[from]!!) {
\r
80 result[to] = result[to]!! + 1 // Increment in-degree
\r
86 fun topSort(): List<V>? {
\r
87 val degree = inDegree()
\r
88 // Determine all vertices with zero in-degree
\r
89 val zeroVerts = Stack<V>() // Stack as good as any here
\r
90 for (v in degree.keys) {
\r
91 if (degree[v] == 0) zeroVerts.push(v)
\r
93 // Determine the topological order
\r
94 val result = ArrayList<V>()
\r
95 while (!zeroVerts.isEmpty()) {
\r
96 val v = zeroVerts.pop() // Choose a vertex with zero in-degree
\r
97 result.add(v) // Vertex v is next in topol order
\r
98 // "Remove" vertex v by updating its neighbors
\r
99 for (neighbor in neighbors[v]!!) {
\r
100 degree[neighbor] = degree[neighbor]!! - 1
\r
101 // Remember any vertices that now have zero in-degree
\r
102 if (degree[neighbor] == 0) zeroVerts.push(neighbor)
\r
105 // Check that we have used the entire graph (if not, there was a cycle)
\r
106 return if (result.size != neighbors.size) null else result
\r
110 fun bfsDistance(start: V): Map<*, *> {
\r
111 var distance: MutableMap<V, Int> = hashMapOf()
\r
112 // Initially, all distance are infinity, except start node
\r
113 for (v in neighbors.keys)
\r
115 distance[start] = 0
\r
116 // Process nodes in queue order
\r
117 val queue = LinkedList<V>()
\r
118 queue.offer(start) // Place start node in queue
\r
119 while (!queue.isEmpty()) {
\r
120 val v = queue.remove()
\r
121 val vDist = distance[v]!!
\r
122 // Update neighbors
\r
123 for (neighbor in neighbors[v]!!) {
\r
124 if (distance[neighbor] != null) continue // Ignore if already done
\r
125 distance[neighbor] = vDist + 1
\r
126 queue.offer(neighbor)
\r