Reputation: 482
I have a priority queue, which holds several tasks, each task with a numeric non-unique priority, as follows:
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)
I want to get the next task:
pq.dequeue()
But this way, I'll always get back task a, even though there's also task c with the same priority.
Upvotes: 2
Views: 213
Reputation: 55123
This should be a good starting point:
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
}
}
I didn't implement the select
function, which would produce a value with weighted probability, but that shouldn't be too hard to do. In order to implement that function, you will need an additional mapping function (similar to priority
) which has type K => Double
, where Double
is the probability weight attached to a particular key bucket. This makes everything somewhat messier, so it didn't seem worth bothering about.
Also this seems like a remarkably specific set of requirements. You're either doing a very interested bit of distributed scheduling, or homework.
Upvotes: 1