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

commonMain.io.github.alexandrepiveteau.graphs.NetworkBuilder.kt Maven / Gradle / Ivy

Go to download

Model directed, undirected, weighted and unweighted graphs and perform computations on them in Kotlin multiplatform.

There is a newer version: 0.6.1
Show newest version
package io.github.alexandrepiveteau.graphs

import io.github.alexandrepiveteau.graphs.internal.IntVector
import io.github.alexandrepiveteau.graphs.util.packInts
import io.github.alexandrepiveteau.graphs.util.unpackInt1
import io.github.alexandrepiveteau.graphs.util.unpackInt2

/** A [NetworkBuilder] is a [GraphBuilder] for [Network]s. */
public interface NetworkBuilder : GraphBuilder

// BUILDER HELPERS

/**
 * An implementation of [NetworkBuilder] which uses a [MutableList] to store the neighbors of each
 * vertex.
 *
 * @param neighbors the list of neighbors of each vertex.
 * @param weights the list of weights of each vertex.
 */
@PublishedApi
internal open class MutableListNetworkBuilder(
    private val neighbors: MutableList,
    private val weights: MutableList,
) : MutableListGraphBuilder(neighbors) {
  override fun addVertex(): Vertex = super.addVertex().also { weights += IntVector() }
}

/**
 * Compacts the given [neighbors] and [weights] into a single array of [VertexArray] and [IntArray],
 * suitable for being used in an adjacency list representation.
 *
 * @param neighbors the list of neighbors of each vertex.
 * @param weights the list of weights of each vertex.
 * @return the pair of arrays of [VertexArray]s and [IntArray]s.
 */
@PublishedApi
internal fun compactToVertexAndWeightsArray(
    neighbors: MutableList,
    weights: MutableList,
): Pair, Array> {
  val encoded =
      Array(neighbors.size) {
        var last = -1
        var count = 0
        // Encode the neighbors and weights into a single long, such that the first 32 bits are the
        // neighbor, and the last 32 bits are the weight. This way, we can sort the array of longs
        // by neighbor, and then sum the weights.
        val list =
            LongArray(neighbors[it].size) { i ->
                  val neighbor = neighbors[it][i]
                  val weight = weights[it][i]
                  packInts(neighbor, weight)
                }
                .apply { sort() }
        for (j in list.indices) {
          val neighbor = unpackInt1(list[j])
          val weight = unpackInt2(list[j])
          if (neighbor != last) {
            list[count++] = list[j] // Update the array in place.
            last = neighbor
          } else {
            list[count - 1] = packInts(neighbor, weight + unpackInt2(list[count - 1]))
          }
        }
        list.copyOf(count)
      }

  return Array(encoded.size) { i ->
    VertexArray(encoded[i].size) { j -> Vertex((encoded[i][j] ushr 32).toInt()) }
  } to Array(encoded.size) { i -> IntArray(encoded[i].size) { j -> encoded[i][j].toInt() } }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy