Purity
Let $\mathcal{F}_s$ be the non-dominated front returned by solver $s$ and $\mathcal{F}$ the non-dominated points of $\bigcup_s \mathcal{F}_s$. Purity is the fraction of the points of $\mathcal{F}_s$ that remain non-dominated when all fronts are merged [1] (eq. 7–8), [2] (Section 5.3.2):
\[\bar t_s = \frac{|\mathcal{F}_s \cap \mathcal{F}|}{|\mathcal{F}_s|} \in [0, 1].\]
The denominator is the size of the solver's own front. Higher is better; in a performance profile use $t_s = 1/\bar t_s$, which is $+\infty$ when the solver contributes no point to $\mathcal{F}$.
In purity, membership in $\mathcal{F}$ means equivalence to some point of R under the tolerance, and equivalent points of A count once, since the source treats fronts as sets.
julia> using MultiObjectiveMetrics
julia> A = [[0.0, 1.0], [0.6, 0.6], [1.0, 0.0]]; B = [[0.5, 0.5]];
julia> R = nondominated(vcat(A, B));
julia> purity(A, R), purity(B, R)
(0.6666666666666666, 1.0)MultiObjectiveMetrics.purity — Function
purity(A, R; tol = Tolerance())Purity of the front A of one solver with respect to the reference front R [1], [2]:
purity(A, R) = |A ∩ R| / |A|R is normally the non-dominated set of the union of the fronts of all solvers compared, nondominated(reduce(vcat, fronts)). A point of A belongs to R when it is equivalent to some point of R under tol. Equivalent points of A count once (see unique_points); otherwise A is used as given, so pass the non-dominated front of the solver. The result lies in [0, 1], higher is better; for performance profiles use 1 / purity.
Returns NaN when A is empty.
Examples
julia> A = [[0.0, 1.0], [0.6, 0.6]]; B = [[0.5, 0.5], [1.0, 0.0]];
julia> R = nondominated(vcat(A, B));
julia> purity(A, R), purity(B, R)
(0.5, 1.0)