
value.Graph.kt Maven / Gradle / Ivy
package io.toolisticon.kotlin.avro.value
/**
* A Graph implementation that represents the dependencies (ars) between its vertexes.
*
* This is used to determinate the order of dependencies, returning the dependant elements last.
*/
@JvmInline
value class Graph> private constructor(
private val map: Map>
) : Iterable {
private operator fun Map>.plus(entry: Pair>): Map> = this.toMutableMap().apply {
compute(entry.first) { _, existing ->
(existing ?: emptySet()) + entry.second
}
}.toMap()
private operator fun Map>.minus(vertex: T): Map> = this.toMutableMap().apply {
remove(vertex)
entries.forEach {
computeIfPresent(it.key) { _, existing -> existing - vertex }
}
}.toMap()
constructor() : this(mapOf())
constructor(vertex: T) : this((Graph() + vertex).map)
constructor(vararg arcs: Pair) : this(arcs.toList())
constructor(arcs: List>) : this(arcs.fold(Graph()) { acc, cur -> acc + cur }.map)
operator fun plus(arc: Pair): Graph = if (arc.first == arc.second) {
plus(arc.first)
} else {
Graph(map + (arc.first to setOf(arc.second)) + (arc.second to emptySet()))
}
operator fun plus(arcs: List>) = arcs.fold(this) { acc, cur -> acc + cur }
operator fun plus(graph: Graph): Graph = graph.arcs.fold(this) { acc, cur -> acc + cur }
operator fun plus(vertex: T): Graph = Graph(map + (vertex to emptySet()))
operator fun minus(vertex: T): Graph = Graph(map - vertex)
internal fun copy() = Graph(map)
val vertexes: List get() = map.values.fold(map.keys) { acc, cur -> acc + cur }.sorted()
val arcs: List>
get() = map.entries
.sortedBy { it.key }
.fold(listOf()) { acc, cur ->
acc + cur.value.map { cur.key to it }
}
fun contains(arc: Pair): Boolean = map[arc.first]?.contains(arc.second) ?: false
fun contains(vertex: T): Boolean = map.containsKey(vertex)
val sequence: Sequence
get() = sequence {
var graph = copy()
while (graph.map.isNotEmpty()) {
val vertex = graph.map.filter { it.value.isEmpty() }.map { it.key }.minOf { it }
graph -= vertex
yield(vertex)
}
}
fun subGraphFor(vararg vertexes: T): Graph {
require(vertexes.all { contains(it) }) { "Unknown vertexes: ${vertexes.toList() - this.vertexes.toSet()}" }
val keep = vertexes.flatMap { map[it]!!+it }.toSet()
val remove = this.vertexes - keep
return remove.fold(this.copy()) { graph, removeVertex ->
graph - removeVertex
}
}
fun isEmpty() = map.isEmpty()
override fun iterator(): Iterator = sequence.iterator()
override fun toString() = map.toString()
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy