% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/add_effects.R
\name{add_effects}
\alias{add_effects}
\title{Add action effects to a planning problem}
\usage{
add_effects(
  x,
  effects = NULL,
  effect_type = c("delta", "after"),
  effect_aggregation = c("sum", "mean"),
  component = c("any", "benefit", "loss")
)
}
\arguments{
\item{x}{A \code{Problem} object created with \code{\link{create_problem}}. It
must already contain feasible actions; run \code{\link{add_actions}} first.}

\item{effects}{Effect specification. One of:
\itemize{
\item \code{NULL}, to store an empty effects table,
\item a \code{data.frame(action, feature, multiplier)},
\item a \code{data.frame(pu, action, feature, ...)} with explicit effects,
\item a named list of \code{terra::SpatRaster} objects, one per action.
}}

\item{effect_type}{Character string indicating how supplied effect values are
interpreted. Must be one of:
\itemize{
\item \code{"delta"}: values represent signed net changes,
\item \code{"after"}: values represent after-action amounts and are
converted to net changes relative to baseline feature amounts.
}}

\item{effect_aggregation}{Character string giving the aggregation used when
converting raster values to planning-unit level. Must be one of
\code{"sum"} or \code{"mean"}.}

\item{component}{Character string controlling which component of the
canonical effects table is retained. Must be one of:
\itemize{
\item \code{"any"}: keep all non-zero rows,
\item \code{"benefit"}: keep only rows with \code{benefit > 0},
\item \code{"loss"}: keep only rows with \code{loss > 0}.
}}
}
\value{
An updated \code{Problem} object containing:
\describe{
\item{\code{dist_effects}}{A canonical effects table with columns
\code{pu}, \code{action}, \code{feature}, \code{benefit}, \code{loss},
\code{internal_pu}, \code{internal_action}, \code{internal_feature}, and
optional labels such as \code{feature_name} and \code{action_name}.}
\item{\code{effects_meta}}{Metadata describing how effects were
interpreted and stored.}
}
}
\description{
Define the effects of management actions on features across planning units.

Effects are stored in a canonical representation in a effects table, with one
row per \code{(pu, action, feature)} triple and two non-negative columns:
\itemize{
\item \code{benefit}: the positive component of the effect,
\item \code{loss}: the magnitude of the negative component of the effect.
}

The net effect is therefore interpreted as
\deqn{
\Delta_{iaf} = \mathrm{benefit}_{iaf} - \mathrm{loss}_{iaf},
}
where \eqn{i} indexes planning units, \eqn{a} indexes actions, and
\eqn{f} indexes features.

Under the semantics adopted by this package, each
\code{(pu, action, feature)} triple represents a single net effect.
Consequently, after validation and aggregation, a stored row cannot have both
\code{benefit > 0} and \code{loss > 0} at the same time.
}
\details{
\strong{When to use \code{add_effects()}.}

Use this function when you want to specify what feasible actions do to
features. It is the stage at which an action-based decision space is linked
to feature-level ecological or functional consequences.

This function provides a unified interface for specifying action effects from
several input formats while enforcing a single internal representation.
Regardless of how the user supplies the effects, the stored output always
follows the same canonical structure based on non-negative
\code{benefit}/\code{loss} components.

Let \eqn{i \in \mathcal{I}} index planning units,
\eqn{a \in \mathcal{A}} index actions, and
\eqn{f \in \mathcal{F}} index features.
Let \eqn{b_{if}} denote the baseline amount of feature \eqn{f} in planning
unit \eqn{i}, as given by the feature-distribution table. Let
\eqn{\Delta_{iaf}} denote the net change caused by applying action
\eqn{a} in planning unit \eqn{i} to feature \eqn{f}. The canonical stored
representation is:

\deqn{
\mathrm{benefit}_{iaf} = \max(\Delta_{iaf}, 0),
}

\deqn{
\mathrm{loss}_{iaf} = \max(-\Delta_{iaf}, 0).
}

Hence:
\itemize{
\item if \eqn{\Delta_{iaf} > 0}, then \code{benefit > 0} and \code{loss = 0},
\item if \eqn{\Delta_{iaf} < 0}, then \code{benefit = 0} and \code{loss > 0},
\item if \eqn{\Delta_{iaf} = 0}, then both are zero.
}

\strong{Why split effects into benefit and loss?}

This representation avoids ambiguity in downstream optimization models. It
allows the package to support, for example, objectives that maximize
beneficial effects, minimize damages, impose no-net-loss conditions, or
combine both components differently in multi-objective formulations.

\strong{Supported effect specifications}

The \code{effects} argument may be provided in one of the following forms:

\enumerate{
\item \code{NULL}. An empty effects table is stored.

\item A \code{data.frame(action, feature, multiplier)}. In this case,
effects are constructed by multiplying baseline feature amounts by the
supplied multiplier:
\deqn{
  \Delta_{iaf} = b_{if} \times m_{af},
  }
where \eqn{m_{af}} is the multiplier associated with action \eqn{a} and
feature \eqn{f}. This specification is expanded over all feasible
\code{(pu, action)} pairs.

\item A \code{data.frame(pu, action, feature, ...)} giving explicit effects
for individual triples. The table may contain:
\itemize{
\item \code{delta} or \code{effect}: interpreted as signed net changes,
\item \code{after}: interpreted as after-action amounts if
\code{effect_type = "after"},
\item \code{benefit} and/or \code{loss}: explicit non-negative split
components,
\item legacy signed \code{benefit} without \code{loss}: interpreted as a
signed net effect for backwards compatibility.
}

\item A named list of \code{terra::SpatRaster} objects, one per action. In
this case, names must match action ids, and each raster must contain one
layer per feature. Raster values are aggregated to planning-unit level
using \code{effect_aggregation}.
}

\strong{Interpretation of \code{effect_type}}

If \code{effect_type = "delta"}, supplied values are interpreted as net
changes directly.

If \code{effect_type = "after"}, supplied values are interpreted as
after-action amounts and converted internally to net effects using:

\deqn{
\Delta_{iaf} = \mathrm{after}_{iaf} - b_{if}.
}

Missing baseline values are treated as zero.

\strong{Feasibility and locked-out decisions}

Effects are only retained for feasible \code{(pu, action)} pairs. Thus,
\code{add_actions()} must be called first. Pairs marked as locked out
(\code{status == 3}) are removed before storing the final effects table.

This function does not define the action-decision layer itself; it builds on
the feasible \code{(pu, action)} pairs already stored in the problem.

\strong{Duplicate rows and semantic validation}

If multiple rows are supplied for the same \code{(pu, action, feature)}
triple, they are aggregated by summing \code{benefit} and \code{loss}
separately. The resulting triple must still respect the package semantics,
namely that both components cannot be strictly positive simultaneously.
Inputs violating this rule are rejected.

\strong{Component filtering}

After canonicalization and validation, rows can be restricted to:
\itemize{
\item \code{component = "any"}: keep all non-zero effects,
\item \code{component = "benefit"}: keep only rows with \code{benefit > 0},
\item \code{component = "loss"}: keep only rows with \code{loss > 0}.
}

Rows with \code{benefit = 0} and \code{loss = 0} are always removed.

\strong{Raster handling}

When effects are supplied as rasters, they are automatically aligned to the
planning-unit raster or geometry when needed before extraction or zonal
aggregation.

\strong{Stored output}

The resulting effects table contains user-facing ids, internal integer ids,
and optional labels for actions and features. Metadata describing the stored
representation and input interpretation are written to an effects metadata
field.

After defining effects, typical next steps include adding objectives that use
beneficial or harmful effects, and then solving the configured problem.
}
\examples{
# ------------------------------------------------------
# Minimal problem with actions
# ------------------------------------------------------
pu <- data.frame(
  id = 1:3,
  cost = c(1, 2, 3)
)

features <- data.frame(
  id = 1:2,
  name = c("sp1", "sp2")
)

dist_features <- data.frame(
  pu = c(1, 1, 2, 3),
  feature = c(1, 2, 1, 2),
  amount = c(10, 5, 8, 4)
)

p <- create_problem(
  pu = pu,
  features = features,
  dist_features = dist_features
)

actions <- data.frame(
  id = c("conservation", "restoration"),
  name = c("Conservation", "Restoration")
)

p <- add_actions(
  x = p,
  actions = actions,
  cost = c(conservation = 2, restoration = 4)
)

print(p)

# ------------------------------------------------------
# 1) Empty effects
# ------------------------------------------------------
p0 <- add_effects(p, effects = NULL)
p0$data$dist_effects

# ------------------------------------------------------
# 2) Multipliers by action and feature
# delta = baseline amount * multiplier
# ------------------------------------------------------
mult <- data.frame(
  action = c("conservation", "conservation",
             "restoration", "restoration"),
  feature = c("sp1", "sp2", "sp1", "sp2"),
  multiplier = c(0.10, 0.00, -0.20, 0.25)
)

p1 <- add_effects(
  x = p,
  effects = mult,
  effect_type = "delta"
)

p1$data$dist_effects

# ------------------------------------------------------
# 3) Explicit net effects using signed deltas
# ------------------------------------------------------
eff_delta <- data.frame(
  pu = c(1, 2, 3, 3),
  action = c("conservation", "restoration", "restoration", "conservation"),
  feature = c(1, 1, 2, 2),
  delta = c(2, -3, 1, 0.5)
)

p2 <- add_effects(
  x = p,
  effects = eff_delta
)

p2$data$dist_effects

# ------------------------------------------------------
# 4) Explicit after-action amounts
# delta = after - baseline
# ------------------------------------------------------
eff_after <- data.frame(
  pu = c(1, 2, 3),
  action = c("conservation", "restoration", "restoration"),
  feature = c(1, 1, 2),
  after = c(12, 5, 6)
)

p3 <- add_effects(
  x = p,
  effects = eff_after,
  effect_type = "after"
)

p3$data$dist_effects

# ------------------------------------------------------
# 5) Keep only beneficial effects
# ------------------------------------------------------
p4 <- add_effects(
  x = p,
  effects = eff_delta,
  component = "benefit"
)

p4$data$dist_effects

}
\seealso{
\code{\link{add_actions}},
\code{\link{add_benefits}},
\code{\link{add_losses}}
}
