R/add_feature_contiguity_constraints.R
add_feature_contiguity_constraints.Rd
Add constraints to a problem()
to ensure that each feature is
represented in a contiguous unit of dispersible habitat. These constraints
are a more advanced version of those implemented in the
add_contiguity_constraints()
function, because they ensure that
each feature is represented in a contiguous unit and not that the entire
solution should form a contiguous unit. Additionally, this function
can use data showing the distribution of dispersible habitat for each
feature to ensure that all features can disperse through out the areas
designated for their conservation.
# S4 method for ConservationProblem,ANY,Matrix add_feature_contiguity_constraints(x, zones, data) # S4 method for ConservationProblem,ANY,data.frame add_feature_contiguity_constraints(x, zones, data) # S4 method for ConservationProblem,ANY,matrix add_feature_contiguity_constraints(x, zones, data) # S4 method for ConservationProblem,ANY,ANY add_feature_contiguity_constraints(x, zones, data)
x 


zones 

data 

Object (i.e. ConservationProblem
) with the constraints
added to it.
This function uses connection data to identify solutions that represent features in contiguous units of dispersible habitat. It was inspired by the mathematical formulations detailed in Önal and Briers (2006) and Cardeira et al. 2010. For an example that has used these constraints, see Hanson et al. (2019). Please note that these constraints require the expanded formulation and therefore cannot be used with feature data that have negative vales. Please note that adding these constraints to a problem will drastically increase the amount of time required to solve it.
The argument to data
can be specified using the following formats.
NULL
connection data should be calculated automatically
using the adjacency_matrix()
function. This is the default
argument and means that all adjacent planning units are treated
as potentially dispersible for all features.
Note that the connection 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 indicates if the
two planning units are connected or not. Cell values should be binary
numeric
values (i.e. one or zero). Cells that occur along the
matrix diagonal have no effect on the solution at all because each
planning unit cannot be a connected with itself. Note that pairs
of connected planning units are treated as being potentially dispersible
for all features.
data.frame
containing the fields (columns)
"id1"
, "id2"
, and "boundary"
. Here, each row
denotes the connectivity between two planning units following the
Marxan format. The field boundary
should contain
binary numeric
values that indicate if the two planning units
specified in the fields "id1"
and "id2"
are connected
or not. This data can be used to describe symmetric or
asymmetric relationships between planning units. By default,
input data is assumed to be symmetric unless asymmetric data is
also included (e.g. if data is present for planning units 2 and 3, then
the same amount of connectivity is expected for planning units 3 and 2,
unless connectivity data is also provided for planning units 3 and 2).
Note that pairs of connected planning units are treated as being
potentially dispersible for all features.
list
containing matrix
, Matrix
, or
data.frame
objects showing which planning units
should be treated as connected for each feature. Each element in the
list
should correspond to a different feature (specifically,
a different target in the problem), and should contain a matrix
,
Matrix
, or data.frame
object that follows the conventions
detailed above.
In early versions, it was named as the add_corridor_constraints
function.
Önal H and Briers RA (2006) Optimal selection of a connected reserve network. Operations Research, 54: 379388.
Cardeira JO, Pinto LS, Cabeza M and Gaston KJ (2010) Species specific connectivity in reservenetwork design using graphs. Biological Conservation, 2: 408415.
Hanson JO, Fuller RA, & Rhodes JR (2019) Conventional methods for enhancing connectivity in conservation planning do not always maintain gene flow. Journal of Applied Ecology, 56: 913922.
# load data data(sim_pu_raster, sim_pu_zones_stack, sim_features, sim_features_zones) # create minimal problem p1 < problem(sim_pu_raster, sim_features) %>% add_min_set_objective() %>% add_relative_targets(0.3) %>% add_binary_decisions() %>% add_default_solver(verbose = FALSE) # create problem with contiguity constraints p2 < p1 %>% add_contiguity_constraints() # create problem with constraints to represent features in contiguous # units p3 < p1 %>% add_feature_contiguity_constraints() # create problem with constraints to represent features in contiguous # units that contain highly suitable habitat values # (specifically in the top 1.5th percentile) cm4 < lapply(seq_len(nlayers(sim_features)), function(i) { # create connectivity matrix using the i'th feature's habitat data m < connectivity_matrix(sim_pu_raster, sim_features[[i]]) # convert matrix to TRUE/FALSE values in top 20th percentile m < m > quantile(as.vector(m), 1  0.015, names = FALSE) # convert matrix from TRUE/FALSE to sparse matrix with 0/1s m < as(m, "dgCMatrix") # remove 0s from the sparse matrix m < Matrix::drop0(m) # return matrix m }) p4 < p1 %>% add_feature_contiguity_constraints(data = cm4) # \dontrun{ # solve problems s1 < stack(solve(p1), solve(p2), solve(p3), solve(p4))#> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 2147483647 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #> #> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 2147483647 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #> #> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 2147483647 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #> #> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 2147483647 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #># plot solutions plot(s1, axes = FALSE, box = FALSE, main = c("basic solution", "contiguity constraints", "feature contiguity constraints", "feature contiguity constraints with data"))# } # create minimal problem with multiple zones, and limit the solver to # 30 seconds to obtain solutions in a feasible period of time p5 < problem(sim_pu_zones_stack, sim_features_zones) %>% add_min_set_objective() %>% add_relative_targets(matrix(0.1, ncol = 3, nrow = 5)) %>% add_binary_decisions() %>% add_default_solver(time_limit = 30, verbose = FALSE) # create problem with contiguity constraints that specify that the # planning units used to conserve each feature in different management # zones must form separate contiguous units p6 < p5 %>% add_feature_contiguity_constraints(diag(3)) # create problem with contiguity constraints that specify that the # planning units used to conserve each feature must form a single # contiguous unit if the planning units are allocated to zones 1 and 2 # and do not need to form a single contiguous unit if they are allocated # to zone 3 zm7 < matrix(0, ncol = 3, nrow = 3) zm7[seq_len(2), seq_len(2)] < 1 print(zm7)#> [,1] [,2] [,3] #> [1,] 1 1 0 #> [2,] 1 1 0 #> [3,] 0 0 0p7 < p5 %>% add_feature_contiguity_constraints(zm7) # create problem with contiguity constraints that specify that all of # the planning units in all three of the zones must conserve first feature # in a single contiguous unit but the planning units used to conserve the # remaining features do not need to be contiguous in any way zm8 < lapply(seq_len(number_of_features(sim_features_zones)), function(i) matrix(ifelse(i == 1, 1, 0), ncol = 3, nrow = 3)) print(zm8)#> [[1]] #> [,1] [,2] [,3] #> [1,] 1 1 1 #> [2,] 1 1 1 #> [3,] 1 1 1 #> #> [[2]] #> [,1] [,2] [,3] #> [1,] 0 0 0 #> [2,] 0 0 0 #> [3,] 0 0 0 #> #> [[3]] #> [,1] [,2] [,3] #> [1,] 0 0 0 #> [2,] 0 0 0 #> [3,] 0 0 0 #> #> [[4]] #> [,1] [,2] [,3] #> [1,] 0 0 0 #> [2,] 0 0 0 #> [3,] 0 0 0 #> #> [[5]] #> [,1] [,2] [,3] #> [1,] 0 0 0 #> [2,] 0 0 0 #> [3,] 0 0 0 #>p8 < p5 %>% add_feature_contiguity_constraints(zm8) # \dontrun{ # solve problems s2 < lapply(list(p5, p6, p7, p8), solve)#> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 30 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #> #> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 30 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #> #> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 30 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #> #> $LogToConsole #> [1] 0 #> #> $LogFile #> [1] "" #> #> $Presolve #> [1] 2 #> #> $MIPGap #> [1] 0.1 #> #> $TimeLimit #> [1] 30 #> #> $Threads #> [1] 1 #> #> $NumericFocus #> [1] 0 #>s2 < stack(lapply(s2, category_layer)) # plot solutions plot(s2, main = c("p5", "p6", "p7", "p8"), axes = FALSE, box = FALSE)# }