Skip to content

allocate() can return negative allocations when the alpha-quantile is negative #3

Description

@nickreich

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions