Define economic profit values for feasible planning unit–action pairs and store them in a profit table.
Profit is stored separately from ecological effects. In particular,
profit is not the same as ecological benefit or
loss as represented in add_effects. This separation
allows the package to distinguish economic returns from ecological
consequences when building objectives, constraints, and reporting summaries.
Arguments
- x
A
Problemobject created withcreate_problem. It must already contain feasible actions and an action catalogue; runadd_actionsfirst.- profit
Profit specification. One of:
NULL: profit is set to 0 for all feasible(pu, action)pairs,a numeric scalar: recycled to all feasible pairs,
a named numeric vector: names are action ids and values define action-level profit,
a
data.frame(action, profit)defining action-level profit,a
data.frame(pu, action, profit)defining pair-specific profit.
Value
An updated Problem object with a stored profit table created
or replaced. The stored table contains columns pu, action,
profit, internal_pu, and internal_action, and
includes only rows with non-zero profit.
Details
When to use add_profit().
Use this function when economic returns, penalties, or other action-specific
financial values are part of the planning problem. Typical downstream uses
include objectives such as add_objective_max_profit and
add_objective_max_net_profit.
Let \(\mathcal{I}\) denote the set of planning units and \(\mathcal{A}\) the set of actions. Let \(\mathcal{D} \subseteq \mathcal{I} \times \mathcal{A}\) denote the set of feasible planning unit–action pairs currently stored in the problem.
This function assigns to each feasible pair \((i,a) \in \mathcal{D}\) a numeric profit value \(\pi_{ia} \in \mathbb{R}\) and stores the result in a profit table.
Thus, the stored table can be interpreted as a mapping $$ \pi : \mathcal{D} \to \mathbb{R}, $$ where \(\pi_{ia}\) represents the economic return associated with selecting action \(a\) in planning unit \(i\).
Profit values may be positive, zero, or negative. Positive values represent gains or revenues, zero represents no net profit contribution, and negative values can be used to encode penalties or net economic losses.
The stored table contains:
pu: external planning-unit id,action: action id,profit: numeric profit value,internal_pu: internal planning-unit index,internal_action: internal action index.
Supported input formats
The profit argument may be specified in several ways:
NULL: assign profit 0 to all feasible(pu, action)pairs,a numeric scalar: assign the same profit value to all feasible pairs,
a named numeric vector: names are action ids, assigning one global profit value per action,
a
data.frame(action, profit): assign one global profit value per action,a
data.frame(pu, action, profit): assign pair-specific profit values.
When action-level profit is supplied, the same profit value is assigned to
all feasible planning units for that action. When pair-specific profit is
supplied, only the listed (pu, action) pairs receive explicit values;
unmatched feasible pairs are interpreted as zero-profit pairs.
Storage behaviour
This function stores only rows with non-zero profit values. Feasible pairs whose final profit is zero are omitted from the stored profit table. Missing values produced during matching or joins are treated as zero before this filtering step. Therefore, the resulting table is a sparse representation of economic returns over the feasible decision space.
Data-only behaviour
This function is purely data-oriented. It does not build or modify the optimization model, and it does not change feasibility. It simply assigns profit values to rows already present in the feasible action table.
In particular:
it does not add new feasible
(pu, action)pairs,it does not remove infeasible pairs,
it does not apply solver-side filtering such as dropping locked-out decisions,
it does not modify ecological effect tables.
Any such filtering is expected to occur later when model-ready tables are
prepared, typically during the build stage invoked by solve().
Use in optimization
Profit values stored by this function can later be used in objectives such as
add_objective_max_profit or
add_objective_max_net_profit, in derived budget expressions, or
in reporting and summary functions.
For example, if \(x_{ia} \in \{0,1\}\) denotes whether action \(a\) is selected in planning unit \(i\), then a profit-maximization objective typically takes the form $$ \max \sum_{(i,a) \in \mathcal{D}} \pi_{ia} x_{ia}. $$
Examples
# Minimal problem
pu <- data.frame(
id = 1:4,
cost = c(2, 3, 1, 4)
)
features <- data.frame(
id = 1:2,
name = c("sp1", "sp2")
)
dist_features <- data.frame(
pu = c(1, 1, 2, 3, 4, 4),
feature = c(1, 2, 1, 2, 1, 2),
amount = c(1, 2, 1, 3, 2, 1)
)
p <- create_problem(
pu = pu,
features = features,
dist_features = dist_features
)
p <- add_actions(
x = p,
actions = data.frame(id = c("harvest", "restoration"))
)
# 1) Constant profit for every feasible (pu, action)
p1 <- add_profit(p, profit = 10)
p1$data$dist_profit
#> pu action profit internal_pu internal_action
#> 1 1 harvest 10 1 1
#> 5 1 restoration 10 1 2
#> 2 2 harvest 10 2 1
#> 6 2 restoration 10 2 2
#> 3 3 harvest 10 3 1
#> 7 3 restoration 10 3 2
#> 4 4 harvest 10 4 1
#> 8 4 restoration 10 4 2
# 2) Profit per action using a named vector
pr <- c(harvest = 50, restoration = -5)
p2 <- add_profit(p, profit = pr)
p2$data$dist_profit
#> pu action profit internal_pu internal_action
#> 1 1 harvest 50 1 1
#> 5 1 restoration -5 1 2
#> 2 2 harvest 50 2 1
#> 6 2 restoration -5 2 2
#> 3 3 harvest 50 3 1
#> 7 3 restoration -5 3 2
#> 4 4 harvest 50 4 1
#> 8 4 restoration -5 4 2
# 3) Profit per action using a data frame
pr_df <- data.frame(
action = c("harvest", "restoration"),
profit = c(40, 15)
)
p3 <- add_profit(p, profit = pr_df)
p3$data$dist_profit
#> pu action profit internal_pu internal_action
#> 1 1 harvest 40 1 1
#> 2 1 restoration 15 1 2
#> 3 2 harvest 40 2 1
#> 4 2 restoration 15 2 2
#> 5 3 harvest 40 3 1
#> 6 3 restoration 15 3 2
#> 7 4 harvest 40 4 1
#> 8 4 restoration 15 4 2
# 4) Profit per (pu, action) pair
pr_pair <- data.frame(
pu = c(1, 2, 3),
action = c("harvest", "harvest", "restoration"),
profit = c(100, 80, 30)
)
p4 <- add_profit(p, profit = pr_pair)
p4$data$dist_profit
#> pu action profit internal_pu internal_action
#> 1 1 harvest 100 1 1
#> 3 2 harvest 80 2 1
#> 6 3 restoration 30 3 2
