# add_asym_connectivity_penalties: Add asymmetric connectivity penalties In prioritizr: Systematic Conservation Prioritization in R

### Description

Add penalties to a conservation planning `problem()` to account for asymmetric connectivity between planning units. Asymmetric connectivity data describe connectivity information that is directional. For example, asymmetric connectivity data could describe the strength of rivers flowing between different planning units. Since river flow is directional, the level of connectivity from an upstream planning unit to a downstream planning unit would be higher than that from a downstream planning unit to an upstream planning unit.

### Usage

```## S4 method for signature 'ConservationProblem,ANY,ANY,matrix'

## S4 method for signature 'ConservationProblem,ANY,ANY,Matrix'

## S4 method for signature 'ConservationProblem,ANY,ANY,data.frame'

## S4 method for signature 'ConservationProblem,ANY,ANY,dgCMatrix'

## S4 method for signature 'ConservationProblem,ANY,ANY,array'
```

### Arguments

 `x` `problem()` (i.e., `ConservationProblem`) object. `penalty` `numeric` penalty that is used to scale the importance of selecting planning units with strong connectivity between them compared to the main problem objective (e.g., solution cost when the argument to `x` has a minimum set objective set using `add_min_set_objective()`). Higher `penalty` values can be used to obtain solutions with a high degree of connectivity, and smaller `penalty` values can be used to obtain solutions with a small degree of connectivity. Note that negative `penalty` values can be used to obtain solutions that have very little connectivity. `zones` `matrix` or `Matrix` object describing the level of connectivity between different zones. Each row and column corresponds to a different zone in the argument to `x`, and cell values indicate the level of connectivity between each combination of zones. Cell values along the diagonal of the matrix represent the level of connectivity between planning units allocated to the same zone. Cell values must lay between 1 and -1, where negative values favor solutions with weak connectivity. The default argument to `zones` is an identity matrix (i.e., a matrix with ones along the matrix diagonal and zeros elsewhere), so that planning units are only considered to be connected when they are allocated to the same zone. This argument is required when working with multiple zones and the argument to `data` is a `matrix` or `Matrix` object. If the argument to `data` is an `array` or `data.frame` with data for multiple zones (e.g., using the `"zone1"` and `"zone2"` column names), this argument must explicitly be set to `NULL` otherwise an error will be thrown. `data` `matrix`, `Matrix`, `data.frame`, or `array` object containing connectivity data. The connectivity values correspond to the strength of connectivity between different planning units. Thus connections between planning units that are associated with higher values are more favorable in the solution. See the Data format section for more information.

### Details

This function adds penalties to conservation planning problem to penalize solutions that have low connectivity. Specifically, it penalizes solutions that select planning units that share high connectivity values with other planning units that are not selected by the solution (based on Beger et al. 2010).

### Value

Object (i.e., `ConservationProblem`) with the penalties added to it.

### Mathematical formulation

The connectivity penalties are implemented using the following equations. Let I represent the set of planning units (indexed by i or j), Z represent the set of management zones (indexed by z or y), and Xiz represent the decision variable for planning unit i for in zone z (e.g., with binary values one indicating if planning unit is allocated or not). Also, let p represent the argument to `penalty`, D represent the argument to `data`, and W represent the argument to `zones`.

If the argument to `data` is supplied as a `matrix` or `Matrix` object, then the penalties are calculated as:

sum_i^I sum_j^I sum_z^Z sum_y^Z (p * Xiz * Dij * Wzy) - sum_i^I sum_j^I sum_z^Z sum_y^Z (p * Xiz * Xjy * Dij * Wzy)

Otherwise, if the argument to `data` is supplied as an `array` object, then the penalties are calculated as:

sum_i^I sum_j^I sum_z^Z sum_y^Z (p * Xiz * Dijzy) - sum_i^I sum_j^I sum_z^Z sum_y^Z (p * Xiz * Xjy * Dijzy)

Note that when the problem objective is to maximize some measure of benefit and not minimize some measure of cost, the term p is replaced with -p.

### Data format

The argument to `data` can be specified using several different formats.

`data` as a `matrix`/`Matrix` object

where rows and columns represent different planning units and the value of each cell represents the strength of connectivity between two different planning units. Cells that occur along the matrix diagonal are treated as weights which indicate that planning units are more desirable in the solution. The argument to `zones` can be used to control the strength of connectivity between planning units in different zones. The default argument for `zones` is to treat planning units allocated to different zones as having zero connectivity.

`data` as a `data.frame` object

containing the fields (columns) `"id1"`, `"id2"`, and `"boundary"`. Here, each row denotes the connectivity between a pair of planning units (per values in the `"id1"` and `"id2"` columns) following the Marxan format. If the argument to `x` contains multiple zones, then the columns `"zone1"` and `"zone2"` can optionally be provided to manually specify the connectivity values between planning units when they are allocated to specific zones. If the columns `"zone1"` and `"zone2"` are present, then the argument to `zones` must be `NULL`.

`data` as an `array` object

containing four-dimensions where cell values indicate the strength of connectivity between planning units when they are assigned to specific management zones. The first two dimensions (i.e., rows and columns) indicate the strength of connectivity between different planning units and the second two dimensions indicate the different management zones. Thus the `data[1, 2, 3, 4]` indicates the strength of connectivity between planning unit 1 and planning unit 2 when planning unit 1 is assigned to zone 3 and planning unit 2 is assigned to zone 4.

### References

Beger M, Linke S, Watts M, Game E, Treml E, Ball I, and Possingham, HP (2010) Incorporating asymmetric connectivity into spatial decision making for conservation, Conservation Letters, 3: 359–368.

See penalties for an overview of all functions for adding penalties.

Other penalties: `add_boundary_penalties()`, `add_connectivity_penalties()`, `add_feature_weights()`, `add_linear_penalties()`

### Examples

```## Not run:
library(Matrix)

# set seed for reproducibility
set.seed(600)

data(sim_pu_sf, sim_pu_zones_stack, sim_features, sim_features_zones)

# define function to rescale values between zero and one so that we
# can compare solutions from different connectivity matrices
rescale <- function(x, to = c(0, 1), from = range(x, na.rm = TRUE)) {
(x - from[1]) / diff(from) * diff(to) + to[1]
}

# create basic problem
p1 <- problem(sim_pu_sf, sim_features, "cost") %>%

# create an asymmetric connectivity matrix. Here, connectivity occurs between
# adjacent planning units and, due to rivers flowing southwards
# through the study area, connectivity from northern planning units to
# southern planning units is ten times stronger than the reverse.
acm1 <- matrix(0, nrow(sim_pu_sf), nrow(sim_pu_sf))
acm1 <- as(acm1, "Matrix")
centroids <- sf::st_coordinates(suppressWarnings(sf::st_centroid(sim_pu_sf)))
adjacent_units <- sf::st_intersects(sim_pu_sf, sparse = FALSE)
for (i in seq_len(nrow(sim_pu_sf))) {
for (j in seq_len(nrow(sim_pu_sf))) {
# find if planning units are adjacent
# find if planning units lay north and south of each other
# i.e., they have the same x-coordinate
if (centroids[i, 1] == centroids[j, 1]) {
if (centroids[i, 2] > centroids[j, 2]) {
# if i is north of j add 10 units of connectivity
acm1[i, j] <- acm1[i, j] + 10
} else if (centroids[i, 2] < centroids[j, 2]) {
# if i is south of j add 1 unit of connectivity
acm1[i, j] <- acm1[i, j] + 1
}
}
}
}
}

# linearly re-scale matrix values to range between zero and one
acm1[] <- rescale(acm1[])

# visualize asymmetric connectivity matrix
image(acm1)

# create penalties
penalties <- c(1, 50)

# create problems using the different penalties
p2 <- list(
p1,
p1 %>% add_asym_connectivity_penalties(penalties[1], data = acm1),
p1 %>% add_asym_connectivity_penalties(penalties[2], data = acm1))

# assign names to the problems
names(p2) <- c("basic problem", paste0("acm1 (", penalties,")"))

# solve problems
s2 <- lapply(p2, solve)

# plot solutions
par(mfrow = c(1, 3))
for (i in seq_along(s2)) {
plot(s2[[i]], main = names(p2)[i], cex = 1.5, col = "white")
plot(s2[[i]][s2[[i]]\$solution_1 == 1, ], col = "darkgreen", add = TRUE)
}

# create minimal multi-zone problem and limit solver to one minute
# to obtain solutions in a short period of time
p3 <- problem(sim_pu_zones_stack, sim_features_zones) %>%
add_relative_targets(matrix(0.15, nrow = 5, ncol = 3)) %>%
add_default_solver(time_limit = 60, verbose = FALSE)

# crate asymmetric connectivity data by randomly simulating values
acm2 <- matrix(runif(ncell(sim_pu_zones_stack) ^ 2),
nrow = ncell(sim_pu_zones_stack))

# create multi-zone problems using the penalties
p4 <- list(
p3,
p3 %>% add_asym_connectivity_penalties(penalties[1], data = acm2),
p3 %>% add_asym_connectivity_penalties(penalties[2], data = acm2))

# assign names to the problems
names(p4) <- c("basic problem", paste0("acm2 (", penalties,")"))

# solve problems
s4 <- lapply(p4, solve)
s4 <- lapply(s4, category_layer)
s4 <- stack(s4)

# plot solutions
plot(s4, main = names(p4), axes = FALSE, box = FALSE)

## End(Not run)

```

prioritizr documentation built on Sept. 18, 2022, 1:05 a.m.