Advertisement
Guest User

Dijkstra2

a guest
Nov 17th, 2019
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 3.90 KB | None | 0 0
  1.  
  2.  
  3.  
  4. import java.util.*
  5. import java.util.concurrent.Phaser
  6. import java.util.concurrent.atomic.AtomicInteger
  7. import java.util.concurrent.locks.Lock
  8. import java.util.concurrent.locks.ReentrantLock
  9. import kotlin.Comparator
  10. import kotlin.collections.ArrayList
  11. import kotlin.concurrent.thread
  12.  
  13. var isDone = AtomicInteger(0)
  14.  
  15. private val NODE_DISTANCE_COMPARATOR = Comparator<Node> { o1, o2 -> Integer.compare(o1!!.distance, o2!!.distance) }
  16.  
  17. class MultiPriorityQueue(size: Int, comparator: Comparator<Node>) {
  18.     private val numOfQueues: Int = size;
  19.  
  20.     private val _locks = List(2 * numOfQueues) { ReentrantLock() }
  21.     val lockList: List<Lock> = ArrayList(_locks)
  22.  
  23.     private val _queues = List(2 * numOfQueues) { PriorityQueue<Node>(comparator) }
  24.     val queueList: List<PriorityQueue<Node>> = ArrayList(_queues)
  25.  
  26.     fun poll(): Node? {
  27.         val random1 = (1 until numOfQueues).random()
  28.         val random2 = (0 until random1).random()
  29.         val q = queueList[random1]
  30.         val p = queueList[random2]
  31.         val lockQ = lockList[random1]
  32.         val lockP = lockList[random2]
  33.  
  34.         var ans: Node? = null
  35.         if (lockQ.tryLock() && lockP.tryLock()) {
  36.             try {
  37.                 if (p.isEmpty()) {
  38.                     if (!q.isEmpty()) {
  39.                         ans = q.poll()
  40.                     }
  41.                 } else {
  42.                     if (q.isEmpty()) {
  43.                         ans = p.poll()
  44.                     } else {
  45.                         if (p.peek().distance < q.peek().distance) {
  46.                             ans = p.poll()
  47.                         } else {
  48.                             ans = q.poll()
  49.                         }
  50.                     }
  51.                 }
  52.             } finally {
  53.                 lockQ.unlock()
  54.                 lockP.unlock()
  55.             }
  56.  
  57.         }
  58.         return ans
  59.     }
  60.  
  61.     fun add(n: Node){
  62.  
  63.         while (true) {
  64.             val r = (0 until numOfQueues).random()
  65.  
  66.             val q = queueList[r]
  67.             val l = lockList[r]
  68.  
  69.             if (l.tryLock()) {
  70.                 try {
  71.                     q.add(n)
  72.                 } finally {
  73.                     l.unlock();
  74.                 }
  75.                 break
  76.             }
  77.         }
  78.     }
  79. }
  80.  
  81.  
  82.  
  83. // Returns `Integer.MAX_VALUE` if a path has not been found.
  84. fun shortestPathParallel(start: Node) {
  85.     val workers = Runtime.getRuntime().availableProcessors()
  86.  
  87.     // The distance to the start node is `0`
  88.     start.distance = 0
  89.     // Create a priority (by distance) queue and add the start node into it
  90.  
  91.     val q = MultiPriorityQueue(workers, NODE_DISTANCE_COMPARATOR) // TODO replace me with a multi-queue based PQ!
  92.     q.add(start)
  93.  
  94.     isDone.incrementAndGet()
  95.  
  96.     // Run worker threads and wait until the total work is done
  97.     val onFinish = Phaser(workers + 1) // `arrive()` should be invoked at the end by each worker
  98.  
  99.     repeat(workers) {
  100.         thread {
  101.             while (true) {
  102.                 val cur: Node = q.poll()
  103.                         ?: if (isDone.get() <= 0) {
  104.                             break
  105.                         } else {
  106.                             continue
  107.                         }
  108.  
  109.                 for (e in cur.outgoingEdges) {
  110.                     while (e.to.distance > cur.distance + e.weight) {
  111.                         val curD: Int = e.to.distance
  112.                         val newD: Int = cur.distance + e.weight
  113.                         if (curD > newD) {
  114.                             if (e.to.casDistance(curD, newD)) {
  115.                                 q.add(e.to)
  116.                                 isDone.incrementAndGet()
  117.                                 break
  118.                             }
  119.                         }
  120.                     }
  121.                 }
  122.                 isDone.decrementAndGet()
  123.             }
  124.             onFinish.arrive()
  125.         }
  126.     }
  127.     onFinish.arriveAndAwaitAdvance()
  128. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement