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

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