【问题标题】:Scala Probabilistic Priority Queue - dequeue with probability by priorityScala Probabilistic Priority Queue - 按优先级概率出列
【发布时间】:2016-11-28 21:35:04
【问题描述】:

我有一个优先级队列,里面有几个任务,每个任务都有一个数字非唯一的优先级,如下:

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()

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

  1. 如何随机获取优先级最高的项目之一?即以 50/50 的几率获得任务 a 或任务 c。
  2. 如何根据优先级随机获得任何物品?即得到45%的任务a,10%的任务b,45%的任务c。

【问题讨论】:

  • 您可以根据轮盘选择算法排序优先级
  • 我不知道 Scala,但在我知道的许多语言中,我会为优先级实现一个自定义比较器,当优先级被考虑时,随机选择作为次要排序标准相等。
  • 根据您想要的准确度和队列的大小,Ordering.by(Random.nextDouble*_.priorty) 可能就是您想要的。

标签: scala data-structures priority-queue


【解决方案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 是附加到特定密钥桶的概率权重。这让一切变得有些混乱,所以似乎不值得费心。

此外,这似乎是一组非常具体的要求。你要么在做一些非常感兴趣的分布式调度,要么做功课。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 2013-03-25
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多