Learn R Programming

prioritizr (version 4.1.5)

add_boundary_penalties: Add boundary penalties

Description

Add penalties to a conservation planning problem to favor solutions that have planning units clumped together into contiguous areas.

Usage

add_boundary_penalties(x, penalty, edge_factor = rep(0.5,
  number_of_zones(x)), zones = diag(number_of_zones(x)), data = NULL)

Arguments

penalty

numeric penalty that is used to scale the importance of selecting planning units that are spatially clumped together 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 will return solutions with a higher degree of spatial clumping, and smaller penalty values will return solutions with a smaller degree of clumping. Note that negative penalty values will return solutions that are more spread out. This parameter is equivalent to the boundary length modifier (BLM) parameter in Marxan.

edge_factor

numeric proportion to scale planning unit edges (or borders) that do not have any neighboring planning units. For example, an edge factor of 0.5 is commonly used for planning units along the coast line. Note that this argument must have an element for each zone in the argument to x.

zones

matrix or Matrix object describing the clumping scheme for different zones. Each row and column corresponds to a different zone in the argument to x, and cell values indicate the relative importance of clumping planning units that are allocated to a pair of zones. Cell values along the diagonal of the matrix represent the relative importance of clumping planning units that are allocated to the same zone. Cell values must lay between 1 and -1, where negative values favor solutions that spread out planning units. The default argument to zones is an identity matrix (i.e. a matrix with ones along the matrix diagonal and zeros elsewhere), so that penalties are incurred when neighboring planning units are not assigned to the same zone. Note that if the cells along the matrix diagonal contain markedly lower values than cells found elsewhere in the matrix, then the optimal solution may surround planning units with planning units that are allocated to different zones.

data

NULL, data.frame, matrix, or Matrix object containing the boundary data. The boundary values correspond to the shared boundary length between different planning units and the amount of exposed boundary length that each planning unit has which is not shared with any other planning unit. Given a certain penalty value, it is more desirable to select combinations of planning units which do not expose larger boundaries that are shared between different planning units. See the Details section for more information.

Value

ConservationProblem-class object with the penalties added to it.

Details

This function adds penalties to a conservation planning problem to penalize fragmented solutions. It was is inspired by Ball et al. (2009) and Beyer et al. (2016). The penalty argument is equivalent to the boundary length modifier (BLM) used in Marxan. Note that this function can only be used to represent symmetric relationships between planning units. If asymmetric relationships are required, use the add_connectivity_penalties function.

The argument to data can be specified in several different ways:

NULL

the boundary data are automatically calculated using the boundary_matrix function. This argument is the default. Note that the boundary data must be manually defined using one of the other formats below when the planning unit data in the argument to x is not spatially referenced (e.g. in data.frame or numeric format).

matrix, Matrix

where rows and columns represent different planning units and the value of each cell represents the amount of shared boundary length between two different planning units. Cells that occur along the matrix diagonal represent the amount of exposed boundary associated with each planning unit that has no neighbor (e.g. these value might pertain the length of coastline in a planning unit).

data.frame

containing the columns "id1", "id2", and "boundary". The values in the column "boundary" show the total amount of shared boundary between the two planning units indicated the columns "id1" and "id2". This format follows the the standard Marxan input format. Note that this function requires symmetric boundary data, and so the argument to data cannot have the columns "zone1" and code"zone2" to specify different amounts of shared boundary lengths for different zones. Instead, when dealing with problems with multiple zones, the argument to zones should be used to control the relative importance of spatially clumping planning units together when they are allocated to different zones.

The boundary penalties are calculated 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 \(X_{iz}\) 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, \(E\) represent the argument to edge_factor, \(B\) represent the matrix argument to data (e.g. generated using boundary_matrix), and \(W\) represent the matrix argument to zones.

$$ \sum_{i}^{I} \sum_{j}^{I} \sum_{z}^{Z} (\mathit{ifelse}(i == j, E_z, 1) \times p \times W_{zz} B_{ij}) + \sum_{i}^{I} \sum_{j}^{I} \sum_{z}^{Z} \sum_{y}^{Z} (-2 \times p \times X_{iz} \times X_{jy} \times W_{zy} \times B_{ij})$$

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\).

References

Ball IR, Possingham HP, and Watts M (2009) Marxan and relatives: Software for spatial conservation prioritisation in Spatial conservation prioritisation: Quantitative methods and computational tools. Eds Moilanen A, Wilson KA, and Possingham HP. Oxford University Press, Oxford, UK.

Beyer HL, Dujardin Y, Watts ME, and Possingham HP (2016) Solving conservation planning problems with integer linear programming. Ecological Modelling, 228: 14--22.

See Also

penalties.

Examples

Run this code
# NOT RUN {
# set seed for reproducibility
set.seed(500)

# load data
data(sim_pu_raster, sim_features, sim_pu_zones_stack, sim_features_zones)

# create minimal problem
p1 <- problem(sim_pu_raster, sim_features) %>%
      add_min_set_objective() %>%
      add_relative_targets(0.2) %>%
      add_binary_decisions() %>%
      add_default_solver()

# create problem with low boundary penalties
p2 <- p1 %>% add_boundary_penalties(50, 1)

# create problem with high boundary penalties but outer edges receive
# half the penalty as inner edges
p3 <- p1 %>% add_boundary_penalties(500, 0.5)

# create a problem using precomputed boundary data
bmat <- boundary_matrix(sim_pu_raster)
p4 <- p1 %>% add_boundary_penalties(50, 1, data = bmat)

# }
# NOT RUN {
# solve problems
s <- stack(solve(p1), solve(p2), solve(p3), solve(p4))

# plot solutions
plot(s, main = c("basic solution", "small penalties", "high penalties",
                 "precomputed data"), axes = FALSE, box = FALSE)
# }
# NOT RUN {
# create minimal problem with multiple zones and limit the run-time for
# solver to 10 seconds so this example doesn't take too long
p5 <- problem(sim_pu_zones_stack, sim_features_zones) %>%
      add_min_set_objective() %>%
      add_relative_targets(matrix(0.2, nrow = 5, ncol = 3)) %>%
      add_binary_decisions() %>%
      add_default_solver(time_limit = 10)

# create zone matrix which favors clumping planning units that are
# allocated to the same zone together - note that this is the default
zm6 <- diag(3)
print(zm6)

# create problem with the zone matrix and low penalties
p6 <- p5 %>% add_boundary_penalties(50, zone = zm6)

# create another problem with the same zone matrix and higher penalties
p7 <- p5 %>% add_boundary_penalties(500, zone = zm6)

# create zone matrix which favors clumping units that are allocated to
# different zones together
zm8 <- matrix(1, ncol = 3, nrow = 3)
diag(zm8) <- 0
print(zm8)

# create problem with the zone matrix
p8 <- p5 %>% add_boundary_penalties(500, zone = zm8)

# create zone matrix which strongly favors clumping units
# that are allocated to the same zone together. It will also prefer
# clumping planning units in zones 1 and 2 together over having
# these planning units with no neighbors in the solution
zm9 <- diag(3)
zm9[upper.tri(zm9)] <- c(0.3, 0, 0)
zm9[lower.tri(zm9)] <- zm9[upper.tri(zm9)]
print(zm9)

# create problem with the zone matrix
p9 <- p5 %>% add_boundary_penalties(500, zone = zm9)

# create zone matrix which favors clumping planning units in zones 1 and 2
# together, and favors planning units in zone 3 being spread out
# (i.e. negative clumping)
zm10 <- diag(3)
zm10[3, 3] <- -1
print(zm10)

# create problem with the zone matrix
p10 <- p5 %>% add_boundary_penalties(500, zone = zm10)

# }
# NOT RUN {
# solve problems
s2 <- stack(category_layer(solve(p5)), category_layer(solve(p6)),
            category_layer(solve(p7)), category_layer(solve(p8)),
            category_layer(solve(p9)), category_layer(solve(p10)))

# plot solutions
plot(s2, main = c("basic solution", "within zone clumping (low)",
                  "within zone clumping (high)", "between zone clumping",
                  "within + between clumping", "negative clumping"),
     axes = FALSE, box = FALSE)
# }

Run the code above in your browser using DataLab