Configure a Problem object to be solved with the augmented
epsilon-constraint method (AUGMECON).
AUGMECON is an exact multi-objective optimization method in which one objective is treated as the primary objective and the remaining objectives are converted into \(\varepsilon\)-constraints. In the augmented formulation, each secondary objective is associated with a non-negative slack variable, and the primary objective is augmented with a small reward term based on the normalized slacks. This augmentation is used to avoid weakly efficient solutions, following Mavrotas (2009).
This function does not solve the problem directly. It stores the AUGMECON
configuration in x$data$method, to be used later by
solve.
Usage
set_method_augmecon(
x,
primary,
aliases = NULL,
grid = NULL,
n_points = 10,
include_extremes = TRUE,
lexicographic = TRUE,
lexicographic_tol = 1e-09,
augmentation = 0.001,
slack_upper_bound = 1e+06
)Arguments
- x
A
Problemobject.- primary
Character string giving the alias of the primary objective, that is, the objective optimized directly in the AUGMECON formulation.
- aliases
Optional character vector of objective aliases to include in the method. If
NULL, all registered objective aliases are used. The value ofprimarymust be included inaliases.- grid
Optional named list defining manual epsilon levels for the secondary objectives. Each name must correspond to a secondary objective alias, and each element must be a non-empty numeric vector of finite values. If
NULL, the grid is generated automatically.- n_points
Number of automatically generated epsilon levels per secondary objective when
grid = NULL. Must be at least 2. Ignored whengridis supplied.- include_extremes
Logical. If
TRUE, automatically generated grids include extreme values of each secondary objective.- lexicographic
Logical. If
TRUE, use lexicographic anchoring when computing extreme points for automatic grid construction.- lexicographic_tol
Non-negative numeric tolerance used in lexicographic anchoring.
- augmentation
Positive numeric augmentation coefficient \(\rho\). The effective coefficient of each secondary slack is computed internally as \(\rho / R_k\), where \(R_k\) is the payoff-table range of the corresponding secondary objective.
- slack_upper_bound
Positive numeric upper bound imposed on the explicit non-negative slack variables associated with the secondary objectives.
Details
Use this method when one objective should be optimized directly, the remaining objectives should be controlled through epsilon levels, and weakly efficient solutions should be reduced through the augmented formulation.
General idea
Suppose that \(m \ge 2\) objective functions have already been registered in the problem: $$ f_1(x), f_2(x), \dots, f_m(x). $$
AUGMECON selects one of them as the primary objective, say \(f_p(x)\), and treats the remaining \(m - 1\) objectives as secondary objectives.
For a fixed combination of epsilon levels, the method solves a sequence of single-objective subproblems of the form:
$$ \max \; f_p(x) + \rho \sum_{k \in \mathcal{S}} \frac{s_k}{R_k} $$
subject to
$$ f_k(x) - s_k = \varepsilon_k, \qquad k \in \mathcal{S}, $$
$$ s_k \ge 0, \qquad k \in \mathcal{S}, $$
together with all original feasibility constraints of the planning problem.
Here:
\(f_p(x)\) is the primary objective,
\(\mathcal{S}\) is the set of secondary objectives,
\(\varepsilon_k\) is the imposed level for secondary objective \(k\),
\(s_k\) is a non-negative slack variable,
\(R_k\) is the payoff-table range used to normalize objective \(k\),
\(\rho > 0\) is a small augmentation coefficient.
In the original AUGMECON formulation of Mavrotas (2009), the augmentation term ensures that, among solutions with the same primary objective value, the solver prefers those with larger normalized slack, thereby avoiding weakly efficient points and improving Pareto-front generation.
Secondary-objective equalities and slacks
The key difference between standard epsilon-constraint and AUGMECON is that the secondary objectives are written as equalities with slacks rather than as simple inequalities. For a maximization-type secondary objective, this takes the form:
$$ f_k(x) - s_k = \varepsilon_k, \qquad s_k \ge 0. $$
This implies: $$ f_k(x) \ge \varepsilon_k, $$
while explicitly measuring the excess above the imposed epsilon level through \(s_k\). The augmentation term then rewards such excess in normalized form.
In implementation terms, the exact sign convention for each objective depends on whether it is internally treated as a minimization or maximization objective, but the method always preserves the same AUGMECON principle:
one objective is optimized directly,
all others are turned into constrained objectives,
non-negative slacks measure controlled deviation from the imposed epsilon levels,
the primary objective is augmented with a small slack-based reward.
Manual and automatic epsilon grids
AUGMECON requires a grid of epsilon levels for each secondary objective.
If grid is supplied, it must be a named list with one numeric vector
per secondary objective. Each vector defines the exact epsilon levels to be
explored for that objective.
If grid = NULL, the grid is generated automatically later during
solve. In that case, the method first computes extreme points
and payoff-table ranges for the secondary objectives, and then generates
n_points levels for each one.
If include_extremes = TRUE, the automatic grid includes the extreme
values of each secondary objective.
If lexicographic = TRUE, extreme points are computed using
lexicographic anchoring, which can improve payoff-table quality when
objectives are tightly competing. The tolerance used for lexicographic
anchoring is controlled by lexicographic_tol.
Normalization and augmentation
The augmentation term is scaled using the payoff-table ranges of the secondary objectives. If \(R_k\) denotes the range of secondary objective \(k\), then the effective coefficient applied to the slack is:
$$ \frac{\rho}{R_k}, $$
where \(\rho = \code{augmentation}\).
This normalization is important because different objectives may be measured on very different numerical scales. Without normalization, a slack belonging to a large-scale objective could dominate the augmentation term simply due to units.
In this implementation, the user supplies augmentation as the base
coefficient \(\rho\), while the normalized slack coefficients are computed
internally at solve time using the corresponding payoff-table ranges.
Stored configuration
This function stores the method definition in x$data$method with:
name = "augmecon",the primary objective alias,
the full set of participating aliases,
the set of secondary aliases,
either a manual grid or the information required to generate one automatically,
augmentation and slack-bound parameters.
The actual payoff table, grid construction, and subproblem solution loop are
performed later by solve.
References
Mavrotas, G. (2009). Effective implementation of the \(\varepsilon\)-constraint method in multi-objective mathematical programming problems. Applied Mathematics and Computation, 213(2), 455–465.
Examples
# Small toy problem
pu_tbl <- data.frame(
id = 1:4,
cost = c(1, 2, 3, 4)
)
feat_tbl <- data.frame(
id = 1:2,
name = c("feature_1", "feature_2")
)
dist_feat_tbl <- data.frame(
pu = c(1, 1, 2, 3, 4),
feature = c(1, 2, 2, 1, 2),
amount = c(5, 2, 3, 4, 1)
)
actions_df <- data.frame(
id = c("conservation", "restoration"),
name = c("conservation", "restoration")
)
effects_df <- data.frame(
pu = c(1, 2, 3, 4, 1, 2, 3, 4),
action = c("conservation", "conservation", "conservation", "conservation",
"restoration", "restoration", "restoration", "restoration"),
feature = c(1, 1, 1, 1, 2, 2, 2, 2),
benefit = c(2, 1, 0, 1, 3, 0, 1, 2),
loss = c(0, 0, 1, 0, 0, 1, 0, 0)
)
x <- create_problem(
pu = pu_tbl,
features = feat_tbl,
dist_features = dist_feat_tbl,
cost = "cost"
) |>
add_actions(actions_df, cost = c(conservation = 1, restoration = 2)) |>
add_effects(effects_df) |>
add_objective_max_benefit(alias = "benefit") |>
add_objective_min_cost(alias = "cost") |>
add_objective_min_loss(alias = "loss")
# Automatic epsilon grids generated later during solve()
x1 <- set_method_augmecon(
x,
primary = "benefit",
aliases = c("benefit", "cost"),
n_points = 5,
include_extremes = TRUE,
lexicographic = TRUE,
augmentation = 1e-3
)
x1$data$method
#> $name
#> [1] "augmecon"
#>
#> $primary
#> [1] "benefit"
#>
#> $aliases
#> [1] "benefit" "cost"
#>
#> $secondary
#> [1] "cost"
#>
#> $grid
#> NULL
#>
#> $n_points
#> [1] 5
#>
#> $include_extremes
#> [1] TRUE
#>
#> $lexicographic
#> [1] TRUE
#>
#> $lexicographic_tol
#> [1] 1e-09
#>
#> $augmentation
#> [1] 0.001
#>
#> $slack_upper_bound
#> [1] 1e+06
#>
# Manual epsilon grids for two secondary objectives
x2 <- set_method_augmecon(
x,
primary = "benefit",
aliases = c("benefit", "cost", "loss"),
grid = list(
cost = c(4, 6, 8),
loss = c(0, 1)
),
augmentation = 1e-3,
slack_upper_bound = 1e6
)
x2$data$method
#> $name
#> [1] "augmecon"
#>
#> $primary
#> [1] "benefit"
#>
#> $aliases
#> [1] "benefit" "cost" "loss"
#>
#> $secondary
#> [1] "cost" "loss"
#>
#> $grid
#> $grid$cost
#> [1] 4 6 8
#>
#> $grid$loss
#> [1] 0 1
#>
#>
#> $n_points
#> NULL
#>
#> $include_extremes
#> [1] TRUE
#>
#> $lexicographic
#> [1] TRUE
#>
#> $lexicographic_tol
#> [1] 1e-09
#>
#> $augmentation
#> [1] 0.001
#>
#> $slack_upper_bound
#> [1] 1e+06
#>
