allocate() can return negative allocations, which are meaningless for a
resource allocation.
Cause
When the budget does not bind, allocate() reports the unconstrained solution,
which is the vector of alpha-quantiles of the predictive distributions. If
alpha is small enough that a target's alpha-quantile is negative, that
negative value is returned as is; nothing clamps allocations at zero.
The relevant branch is the qs_OK short circuit: the quantile solution is
accepted whenever sum(w * qs) < K, and a vector of negative quantiles trivially
satisfies any positive budget.
Note that this also makes the "no marginal benefit" branch effectively
unreachable for alpha < 1. That branch triggers when alpha <= F_i(0) for
every target, but that is exactly the condition under which the
alpha-quantiles are non-positive, so the qs_OK check fires first and returns
the negative quantiles instead. The zero-allocation branch is only reached when
the predictive mass itself lies below zero.
Reproducing
library(alloscore2)
fc <- add_pdqr_funs(
tibble::tibble(target_names = c("A", "B", "C"), dist = "norm",
mean = c(5, 8, 12), sd = c(1, 2, 3)),
types = c("p", "q")
)
a <- allocate(fc, K = c(5, 10), alpha = 1e-12)
a$qs_OK # TRUE TRUE
a$x[[1]]
#> A B C
#> -2.034512 -6.069025 -9.103537
This is pre-existing behaviour, inherited from the original package. It is
pinned by a test in tests/testthat/test-allocate.R ("a quantile level below
F(0) yields a negative allocation") so that changing it has to be deliberate.
Fix
Clamp the initial quantile solution at zero, i.e. qs <- pmax(qs, 0), and
re-check feasibility. For a target whose alpha-quantile is negative the
optimal allocation subject to x_i >= 0 is zero, so this is the correct
solution rather than a cosmetic guard.
Changing it alters numerical results in that regime, so the legacy equivalence
fixtures should be checked and the change noted in NEWS.md. None of the
current fixtures exercise alpha that small, so in practice this may be a
no-op for them.
allocate()can return negative allocations, which are meaningless for aresource allocation.
Cause
When the budget does not bind,
allocate()reports the unconstrained solution,which is the vector of
alpha-quantiles of the predictive distributions. Ifalphais small enough that a target'salpha-quantile is negative, thatnegative value is returned as is; nothing clamps allocations at zero.
The relevant branch is the
qs_OKshort circuit: the quantile solution isaccepted whenever
sum(w * qs) < K, and a vector of negative quantiles triviallysatisfies any positive budget.
Note that this also makes the "no marginal benefit" branch effectively
unreachable for
alpha < 1. That branch triggers whenalpha <= F_i(0)forevery target, but that is exactly the condition under which the
alpha-quantiles are non-positive, so theqs_OKcheck fires first and returnsthe negative quantiles instead. The zero-allocation branch is only reached when
the predictive mass itself lies below zero.
Reproducing
This is pre-existing behaviour, inherited from the original package. It is
pinned by a test in
tests/testthat/test-allocate.R("a quantile level belowF(0) yields a negative allocation") so that changing it has to be deliberate.
Fix
Clamp the initial quantile solution at zero, i.e.
qs <- pmax(qs, 0), andre-check feasibility. For a target whose
alpha-quantile is negative theoptimal allocation subject to
x_i >= 0is zero, so this is the correctsolution rather than a cosmetic guard.
Changing it alters numerical results in that regime, so the legacy equivalence
fixtures should be checked and the change noted in
NEWS.md. None of thecurrent fixtures exercise
alphathat small, so in practice this may be ano-op for them.