org.jetbrains.kotlin.backend.konan.GraphAlgorithms.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-native-compiler-embeddable Show documentation
Show all versions of kotlin-native-compiler-embeddable Show documentation
Embeddable JAR of Kotlin/Native compiler
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.utils.addToStdlib.popLast
internal interface DirectedGraphNode {
val key: K
val directEdges: List?
val reversedEdges: List?
}
internal interface DirectedGraph> {
val nodes: Collection
fun get(key: K): N
}
internal class DirectedGraphMultiNode(val nodes: Set)
internal class DirectedGraphCondensation(val topologicalOrder: List>)
// The Kosoraju-Sharir algorithm.
internal class DirectedGraphCondensationBuilder>(private val graph: DirectedGraph) {
private val visited = mutableSetOf()
private val order = mutableListOf()
private val nodeToMultiNodeMap = mutableMapOf>()
private val multiNodesOrder = mutableListOf>()
fun build(): DirectedGraphCondensation {
// First phase.
graph.nodes.forEach {
if (!visited.contains(it.key))
findOrder(it)
}
// Second phase.
visited.clear()
val multiNodes = mutableListOf>()
order.reversed().forEach {
if (!visited.contains(it.key)) {
val nodes = mutableSetOf()
paint(it, nodes)
multiNodes += DirectedGraphMultiNode(nodes)
}
}
return DirectedGraphCondensation(multiNodes)
}
private fun findOrder(node: N) {
val stack = mutableListOf>>()
visited += node.key
stack.add(node to (node.directEdges ?: emptyList()).iterator())
while (stack.isNotEmpty()) {
if (stack.last().second.hasNext()) {
val nextKey = stack.last().second.next()
if (!visited.contains(nextKey)) {
visited += nextKey
val nextNode = graph.get(nextKey)
stack.add(nextNode to (nextNode.directEdges ?: emptyList()).iterator())
}
} else {
order += stack.last().first
stack.popLast()
}
}
}
private fun paint(node: N, multiNode: MutableSet) {
val stack = mutableListOf>>()
visited += node.key
multiNode += node.key
stack.add(node to (node.reversedEdges ?: emptyList()).iterator())
while (stack.isNotEmpty()) {
if (stack.last().second.hasNext()) {
val nextKey = stack.last().second.next()
if (!visited.contains(nextKey)) {
visited += nextKey
multiNode += nextKey
val nextNode = graph.get(nextKey)
stack.add(nextNode to (nextNode.reversedEdges ?: emptyList()).iterator())
}
} else {
stack.popLast()
}
}
}
}