All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.backend.konan.GraphAlgorithms.kt Maven / Gradle / Ivy

There is a newer version: 2.1.0-RC2
Show newest version
/*
 * 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()
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy