sclass ProbabilisticList extends AbstractList {
TreeSetWithDuplicates entries = new(byProbability());
bool verbose;
// must be >= 0. probability 0 is never added
double cutoffProbabilityOnAdd = 0;
Comparator byProbability() { ret (a, b) -> cmp(b.probability, a.probability); }
persistable class Entry {
double probability;
A element;
*(double *probability, A *element) {}
toString {
ret str(WithProbability(probability, element));
}
}
public void add aka at(double probability, A element) {
if (element == null) ret;
if (probability <= cutoffProbabilityOnAdd) ret;
entries.add(new Entry(probability, element));
}
A first() {
Entry s = first(entries);
ret s?.element;
}
void clear {
entries.clear();
}
run {
stepAll(this);
}
void run(int maxSteps) {
stepMax(maxSteps, this);
}
void printStats() {
Entry first = entries.first(), last = entries.last();
Entry next = nextSteppable();
print("ProbabilisticScheduler. "
+ nEntries(entries)
+ ", highest probability in queue: " + (first == null ? "-" : first.probability)
+ ", lowest probability in queue: " + (last == null ? "-" : last.probability)
+ ", cutoff probability: " + cutoffProbabilityOnAdd + "/" + cutoffProbabilityOnExecute
+ ", " + (next == null ? "done" : "next step: " + next.action));
}
// Get probability of this thread's Runnable.
// Or 1.0 when we are coming from "outside" (so you don't _have_ to
// run your first step through the scheduler).
public double currentProbability aka current() {
ret or(threadProbability!, 1.0);
}
/*IProbabilisticScheduler freeze() {
double prob = currentProbability();
ret new IProbabilisticScheduler {
public void at(double probability, Runnable action) {
ProbabilisticScheduler.this.at(prob*probability, action);
}
public double currentProbability() {
ret prob;
}
public long stepCount() { ret stepCount; }
};
}*/
double remainingProbability() {
Entry s = nextSteppable();
ret s == null ? 0.0 : s.probability;
}
public double lastExecutedProbability() { ret lastExecutedProbability; }
public long stepCount() { ret stepCount; }
}