Scala概率优先级队列 - 优先级按概率出列

时间:2016-11-28 21:35:04

标签: scala data-structures priority-queue

我有一个优先级队列,它包含多个任务,每个任务都有一个数字非唯一优先级,如下所示:

import scala.collection.mutable

class Task(val name: String, val priority: Int) {
  override def toString = s"Task(name=$name, priority=$priority)"
}

val task_a = new Task("a", 5)
val task_b = new Task("b", 1)
val task_c = new Task("c", 5)

val pq: mutable.PriorityQueue[Task] =
    new mutable.PriorityQueue()(Ordering.by(_.priority))

pq.enqueue(task_a)
pq.enqueue(task_b)
pq.enqueue(task_c)

我想接下来的任务:

pq.dequeue()

但是这样,即使还有任务c 具有相同的优先级,我总会回来任务a

  1. 如何随机获得优先级最高的项目之一?那就是获得任务a或任务c,有50/50的机会。
  2. 如何根据优先级随机获取任何项目?那就是获得45%的任务a,10%的任务b和45%的任务c。

1 个答案:

答案 0 :(得分:1)

这应该是一个很好的起点:

abstract class ProbPriorityQueue[V] {
  protected type K
  protected implicit def ord: Ordering[K]
  protected val impl: SortedMap[K, Set[V]]
  protected val priority: V => K

  def isEmpty: Boolean = impl.isEmpty

  def dequeue: Option[(V, ProbPriorityQueue[V])] = {
    if (isEmpty) {
      None
    } else {
      // I wish Scala allowed us to collapse these operations...
      val k = impl.lastKey
      val s = impl(k)

      val v = s.head
      val s2 = s - v

      val impl2 = if (s2.isEmpty)
        impl - k
      else
        impl.updated(k, s2)

      Some((v, ProbPriorityQueue.create(impl2, priority)))
    }
  }
}

object ProbPriorityQueue {

  def apply[K: Ordering, V](vs: V*)(priority: V => K): ProbPriorityQueue = {
    val impl = vs.foldLeft(SortedMap[K, Set[V]]()) {
      case (acc, v) =>
        val k = priority(v)

        acc get k map { s => acc.updated(k, s + v) } getOrElse (acc + (k -> Set(v)))
    }

    create(impl, priority)
  }

  private def create[K0:, V](impl0: SortedMap[K0, Set[V]], priority0: V => K0)(implicit ord0: Ordering[K0]): ProbPriorityQueue[V] =
    new ProbPriorityQueue[V] {
      type K = K0
      def ord = ord0
      val impl = impl0
      val priority = priority0
    }
}

我没有实现select函数,它会产生加权概率值,但这不应该太难。为了实现该功能,您需要一个额外的映射函数(类似于priority),其类型为K => Double,其中Double是附加到特定密钥桶的概率权重。这使得一切都变得更加混乱,因此似乎不值得为此烦恼。

此外,这似乎是一组非常具体的要求。你要么对分布式调度或家庭作业感兴趣。