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

hu.bme.mit.theta.xcfa.cli.portfolio.stm.kt Maven / Gradle / Ivy

There is a newer version: 6.8.5
Show newest version
/*
 *  Copyright 2024 Budapest University of Technology and Economics
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package hu.bme.mit.theta.xcfa.cli.portfolio

import hu.bme.mit.theta.analysis.algorithm.SafetyResult
import hu.bme.mit.theta.xcfa.cli.params.XcfaConfig

abstract class Node(val name: String) {

    val outEdges: MutableSet = LinkedHashSet()
    var parent: STM? = null

    abstract fun execute(): Pair
    abstract fun visualize(): String
}

class HierarchicalNode(name: String, private val innerSTM: STM) : Node(name) {

    override fun execute(): Pair = innerSTM.execute()
    override fun visualize(): String = """state $name {
${innerSTM.visualize()}
}""".trimIndent()
}

class ConfigNode(name: String, private val config: XcfaConfig<*, *>,
    private val check: (config: XcfaConfig<*, *>) -> SafetyResult<*, *>) : Node(name) {

    override fun execute(): Pair {
        println("Current configuration: $config")
        return Pair(config, check(config))
    }

    override fun visualize(): String = config.toString().lines() // TODO: reintroduce visualize()
        .map { "state ${name.replace(Regex("[:\\.-]+"), "_")}: $it" }.reduce { a, b -> "$a\n$b" }
}

data class Edge(val source: Node,
    val target: Node,
    val trigger: (Exception) -> Boolean,
    val guard: (Node, Edge) -> Boolean = { _, _ -> true }) {

    init {
        source.outEdges.add(this)
    }

    fun visualize(): String = """${source.name.replace(Regex("[:\\.-]+"), "_")} --> ${
        target.name.replace(Regex("[:\\.-]+"), "_")
    } : $trigger """

}

// if the exceptions set is empty, it catches all exceptions
class ExceptionTrigger(
    val exceptions: Set = emptySet(),
    val fallthroughExceptions: Set = emptySet(),
    val label: String? = null
) : (Exception) -> Boolean {

    constructor(vararg exceptions: Exception, label: String? = null) : this(exceptions.toSet(),
        label = label)

    override fun invoke(e: Exception): Boolean =
        if (exceptions.isNotEmpty())
            exceptions.contains(e) && !fallthroughExceptions.contains(e)
        else
            !fallthroughExceptions.contains(e)

    override fun toString(): String =
        label ?: ((if (exceptions.isNotEmpty()) exceptions.toString() else "*") +
            (if (fallthroughExceptions.isNotEmpty()) ", not $fallthroughExceptions" else ""))
}

data class STM(val initNode: Node, val edges: Set) {
    init {
        val nodes = edges.map { listOf(it.source, it.target) }.flatten().toSet()
        nodes.forEach {
            check(
                it.parent == null || it.parent === this) { "Edges to behave encapsulated (offender: $it)" }
            it.parent = this
        }
    }

    private fun visualizeNodes(): String = edges.map { listOf(it.source, it.target) }.flatten()
        .toSet().map { it.visualize() }.reduce { a, b -> "$a\n$b" }

    fun visualize(): String = """
${visualizeNodes()}

[*] --> ${initNode.name.replace(Regex("[:\\.-]+"), "_")}
${edges.map { it.visualize() }.reduce { a, b -> "$a\n$b" }}
""".trimMargin()

    fun execute(): Pair {
        var currentNode: Node = initNode
        while (true) {
            try {
                return currentNode.execute()
            } catch (e: Exception) {
                println("Caught exception: $e")
                val edge: Edge? = currentNode.outEdges.find { it.trigger(e) }
                if (edge != null) {
                    println("Handling exception as ${edge.trigger}")
                    currentNode = edge.target
                } else {
                    println("Could not handle trigger $e (Available triggers: ${
                        currentNode.outEdges.map { it.trigger }.toList()
                    })")
                    throw e
                }
            }
        }
    }
}

//fun XcfaConfig<*, CegarConfig>.visualize(inProcess: Boolean): String =
//    """solvers: $abstractionSolver, $refinementSolver
//    |domain: $domain, search: $search, initprec: $initPrec, por: $porLevel
//    |refinement: $refinement, pruneStrategy: $pruneStrategy
//    |timeout: $timeoutMs ms, inProcess: $inProcess""".trimMargin()




© 2015 - 2024 Weber Informatics LLC | Privacy Policy