commonMain.io.github.alexandrepiveteau.graphs.NetworkBuilder.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-graphs Show documentation
Show all versions of kotlin-graphs Show documentation
Model directed, undirected, weighted and unweighted graphs and perform computations on them in Kotlin multiplatform.
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() } }
}