org.openprovenance.prov.scala.nf.TransitiveClosure2.scala Maven / Gradle / Ivy
The newest version!
package org.openprovenance.prov.scala.nf
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ListBuffer
object ShortestPath {
/**
* Returns shortest paths between all pairs using Floyd-Warshall algorithm.
* Nodes are assumed to be enumerated without any holes and enumeration
* starts from 0.
*
* @param nodes the set of vertices
* @param links the map of edges with costs
* @return shortest paths between all pairs, including the source and destination
*/
def allPairsShortestPath(nodes: Set[Int], links: Map[Int, Set[Int]]): Map[Int, Map[Int, Seq[Int]]] = {
val n = nodes.size
val inf = Int.MaxValue
// Initialize distance matrix.
val ds = Array.fill[Int](n, n)(inf)
for (i <- 0 until n) ds(i)(i) = 0
for (i <- links.keys)
for (j <- links(i))
ds(i)(j) = 1
// Initialize next vertex matrix.
val ns = Array.fill[Int](n, n)(-1)
// Here goes the magic!
for (k <- 0 until n; i <- 0 until n; j <- 0 until n)
if (ds(i)(k) != inf && ds(k)(j) != inf && ds(i)(k) + ds(k)(j) < ds(i)(j)) {
ds(i)(j) = ds(i)(k) + ds(k)(j)
ns(i)(j) = k
}
// Helper function to carve out paths from the next vertex matrix.
def extractPath(path: ArrayBuffer[Int], i: Int, j: Int): Unit = {
if (ds(i)(j) == inf) return
val k = ns(i)(j)
if (k != -1) {
extractPath(path, i, k)
path.append(k)
extractPath(path, k, j)
}
}
// Extract paths.
val pss = scala.collection.mutable.Map[Int, Map[Int, Seq[Int]]]()
for (i <- 0 until n) {
val ps = scala.collection.mutable.Map[Int, Seq[Int]]()
for (j <- 0 until n)
if (ds(i)(j) != inf) {
val p = new ArrayBuffer[Int]()
p.append(i)
if (i != j) {
extractPath(p, i, j)
p.append(j)
}
ps(j) = p.toSeq
}
pss(i) = ps.toMap
}
// Return extracted paths.
pss.toMap
}
}
object FloydWarshall {
def computeTransitiveClosure(n: Int, ds: Array[Array[Boolean]]): Unit = {
// Here goes the magic!
for (k <- 0 until n; i <- 0 until n) {
if (!(i==k)) { // we know it's reflexive, no need to update the array, we add it at the end in computeMembershipo
val ds_i=ds(i)
if ( ds_i(k) ) {
val ds_k=ds(k)
for (j <- 0 until n) {
if (!(j==i)) { // we know it's reflexive, no need to update the array, we add it at the end in computeMembershipo
if ( ds_k(j) ) {
ds_i(j) = true
}
}
}
}
}
}
}
@inline def symmetricCheck(ds: Array[Array[Boolean]], k: Int, j: Int, ds_k: Array[Boolean]): Boolean = {
if (j < k) {
ds_k(j)
} else {
ds(j)(k)
}
}
def computeTransitiveClosureSymmetric(n: Int, ds: Array[Array[Boolean]]): Unit = {
// Here goes the magic!
for (k <- 0 until n; i <- 0 until n) {
if (!(i==k)) { // we know it's reflexive, no need to update the array, we add it at the end in computeMembershipo
val ds_i=ds(i)
if ( symmetricCheck(ds,i,k,ds_i) ) { //rely on symmetric if appropriate
val ds_k=ds(k)
for (j <- 0 until i) { // OPTIMISATION: j loops till i, ensures ds(i)(j) j {
val i=amap(s.head)
val ds_i=ds(i)
s.foreach { elem => val j=amap(elem)
if (!(i==j)) {
ds_i(j)=true
ds(j)(i)=true
}}
}}
if (optimized) {
//showds(ds)
FloydWarshall.computeTransitiveClosureSymmetric(n, ds)
membership=computeMembershipSymmetric(n,ds,idsVec)
this.ds=ds
} else {
FloydWarshall.computeTransitiveClosure(n, ds)
membership=computeMembership(n,ds,idsVec)
this.ds=ds
}
computed=true
}
membership
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy