= Solution
Add a generic mapping method inside the supplied trait. Snapshot the finitely many source masses, and sum masses when different entries have the same image:
``
def map[U](f: T => U): FiniteDist[U] = {
val entries = getDom.map(x => (f(x), getProb(x)))
val support = entries.map(_._1).distinct
new FiniteDist[U] {
def getDom: List[U] = support
def getProb(y: U): Double =
entries.foldLeft(0.0) { case (sum, (image, mass)) =>
if (image == y) sum + mass else sum
}
}
}
``
Here the mapping is a mathematical <function>, and keys are assumed to have stable equality consistent with their intended identity. Each source atom is evaluated once when the new distribution is constructed. The distinct image <list> is exactly the finite support because all listed source atoms have positive mass. Summing collisions, rather than overwriting a previous mass, implements the <probability> pushforward.
The sets of source atoms with a fixed image partition the original support. Hence nonnegativity is preserved and, in exact <probability> arithmetic,
$$
\sum_y p_2(y)=\sum_y\sum_{x:f(x)=y}p_1(x)=\sum_xp_1(x)=1.
$$
Thus the result is a <finite probability distribution>. For a constant mapping, every atom merges into one outcome of mass one. Floating-point <additions> in the implementation can introduce rounding error, so numerical tests of normalization should use a suitable tolerance rather than demand exact equality of `Double` sums.
Back to article page