Answers the reverse of the usual LAGO question. Instead of "what
is the least costly intervention that reaches an outcome goal?"
(lago_optimization()), lago_budget() asks "given a fixed budget, what is
the best outcome I can reach, and with which intervention?".
The best-outcome-within-budget intervention always lies on the same
least-cost frontier that lago_optimization() traces out (for any target
outcome, the cheapest way to reach it is what the optimizer already finds), so
lago_budget() sweeps the outcome goal across the outcome's range with
lago_sensitivity(), reads the recommended cost and estimated outcome at each
goal, and returns the reachable goal whose recommended cost is highest without
exceeding the budget (for outcome_goal_intention = "maximize"; the lowest
reachable outcome within budget for "minimize"). It does not touch the
optimizer internals, so it inherits the same model, cost functions and bounds.
Arguments
- object
An optional
lagoresult fromlago_optimization(). When supplied, the baseline optimization arguments are read from the call it carries, so the whole call need not be retyped, and anything in...overrides those stored values. WhenNULL(the default), the baseline arguments come from.... Passing a non-lagoobject, or alagoresult from a version that did not record its call arguments, is an error.- ...
The baseline
lago_optimization()arguments (the user's own optimization call), forwarded unchanged to every run.outcome_goalis swept and so need not be supplied;include_confidence_setandquietare overridden (the confidence set is never computed during the search).- budget
A single positive, finite numeric value. The maximum total cost allowed, in the same units as the supplied
cost_list_of_vectors(orunit_costs).- n_grid
A single integer (>= 2) giving how many outcome goals to try across the outcome's range. Larger values give a finer, more precise answer at the cost of more optimization runs. A second refinement pass tries
n_gridmore goals strictly inside the gap at the affordability boundary, so the effective resolution is finer thann_gridalone. Default 25.- quiet
A boolean forwarded to
lago_optimization()vialago_sensitivity(). Defaults toTRUEso the search is not noisy.
Value
An object of class "lago_budget", a list with:
- budget
The supplied budget.
- feasible
TRUEif at least one reachable intervention was affordable.- binding
TRUEif the budget constrained the choice: a strictly better outcome was reachable but cost more than the budget.FALSEif the best reachable outcome was already affordable.- rec_int
The recommended intervention (one value per component), or
NAwhen notfeasible.- rec_int_cost
Its cost (at most
budget), orNA.- est_outcome
Its estimated outcome, or
NA.- outcome_goal
The outcome goal that produced the recommendation (equal to
est_outcomeup to the grid resolution), orNA.- frontier
A
data.frameof the reachable goals searched (the cost/outcome tradeoff curve):outcome_goal,rec_int_cost,est_outcome,affordable,status.- component_names
The intervention component names.
- intention
The
outcome_goal_intentionused.- run_error
The error of the first failed run when every run of a sweep failed, otherwise
NULL.
Details
The candidate outcome goals span the outcome's range: (0, 1) for a
binary outcome, or the observed range of the outcome column (padded by half a
span on each side) for a continuous one. Each goal is one
lago_optimization() run with the confidence set off. A goal beyond the
reachable range does not error: the optimizer's shrinking method returns a
recommendation whose estimated outcome falls short of the goal, so such a goal
is not counted as genuinely reached and does not become a candidate (only
goals the recommendation actually delivers are considered). Among the reached
goals whose recommended cost is at most budget, the one with the best
estimated outcome is chosen (largest for "maximize", smallest for
"minimize"). Goals that tie on the estimated outcome return the same
intervention, and the one furthest in the improving direction is taken. The
grid is extended in the improving direction until goals stop being reached
or affordable, up to 30 times with a warning if that is not enough, and a
refinement sweep is then run near the affordability boundary to tighten the
estimate.
If no reachable goal is affordable (the budget is below the cost of even the
cheapest reachable intervention), the result has feasible = FALSE and NA
recommendation fields. If every reachable goal is affordable, the budget does
not bind (binding = FALSE) and the maximum reachable outcome is returned.
If lago_optimization() fails for every goal of a sweep, for example because
the outcome model cannot be fitted, the result has feasible = FALSE, the
warning and the printed result give the error of the first failed run, and
run_error holds it.
See also
lago_optimization(), lago_sensitivity()
Other LAGO functions:
get_confidence_set(),
lago_optimization(),
lago_report(),
lago_sensitivity(),
visualize_cost()
Examples
# \donttest{
# How good an outcome can a budget of 100 buy? (mtcars, continuous.)
b <- lago_budget(
data = mtcars,
outcome_name = "mpg",
outcome_type = "continuous",
glm_family = "gaussian",
link = "identity",
intervention_components = c("gear", "qsec"),
intervention_lower_bounds = c(0, 0),
intervention_upper_bounds = c(10, 350),
cost_list_of_vectors = list(c(0, 4), c(4, 6)),
outcome_goal_intention = "maximize",
budget = 100
)
b
#>
#> ── LAGO budget-constrained optimization ──
#>
#> Budget: 100 (maximize).
#> Recommended intervention: gear = 10.00000, qsec = 9.29699
#> Cost: 99.7819396146112 (of 100).
#> Estimated outcome: 35.1051282051282.
plot(b)
# Reuse a fitted result's call instead of retyping it.
opt <- lago_optimization(
data = mtcars, outcome_name = "mpg", outcome_type = "continuous",
glm_family = "gaussian", link = "identity",
intervention_components = c("gear", "qsec"),
intervention_lower_bounds = c(0, 0),
intervention_upper_bounds = c(10, 350),
cost_list_of_vectors = list(c(0, 4), c(4, 6)),
outcome_goal = 30, outcome_goal_intention = "maximize",
include_confidence_set = FALSE, quiet = TRUE
)
lago_budget(opt, budget = 100)
#>
#> ── LAGO budget-constrained optimization ──
#>
#> Budget: 100 (maximize).
#> Recommended intervention: gear = 10.00000, qsec = 9.29699
#> Cost: 99.7819396146112 (of 100).
#> Estimated outcome: 35.1051282051282.
# }