Add constraints to a conservation planning problem to ensure that specific planning units are selected (or allocated to a specific zone) in the solution. For example, it may be desirable to lock in planning units that are inside existing protected areas so that the solution fills in the gaps in the existing reserve network. If specific planning units should be locked out of a solution, use add_locked_out_constraints. For problems with non-binary planning unit allocations (e.g. proportions), the add_manual_locked_constraints function can be used to lock planning unit allocations to a specific value.

add_locked_in_constraints(x, locked_in)

# S4 method for ConservationProblem,numeric
add_locked_in_constraints(x, locked_in)

# S4 method for ConservationProblem,logical
add_locked_in_constraints(x, locked_in)

# S4 method for ConservationProblem,matrix
add_locked_in_constraints(x, locked_in)

# S4 method for ConservationProblem,character
add_locked_in_constraints(x, locked_in)

# S4 method for ConservationProblem,Spatial
add_locked_in_constraints(x, locked_in)

# S4 method for ConservationProblem,Raster
add_locked_in_constraints(x, locked_in)

Arguments

x

ConservationProblem-class object.

locked_in

Object that determines which planning units that should be locked in. See the Details section for more information.

Details

The locked planning units can be specified in several different ways. Generally, the locked data should correspond to the planning units in the argument to x. To help make working with Raster-class planning unit data easier, the locked data should correspond to cell indices in the Raster-class data. For example, integer arguments should correspond to cell indices and logical arguments should have a value for each cell---regardless of which planning unit cells contain NA values.

integer

vector of indices pertaining to which planning units should be locked in the solution. This argument is only compatible with problems that contain a single zone.

logical

vector containing TRUE and/or FALSE values that indicate which planning units should be locked in the solution. This argument is only compatible with problems that contain a single zone.

matrix

containing logical TRUE and/or FALSE values which indicate if certain planning units are should be locked to a specific zone in the solution. Each row corresponds to a planning unit, each column corresponds to a zone, and each cell indicates if the planning unit should be locked to a given zone. Thus each row should only contain at most a single TRUE value.

character

field (column) name(s) that indicate if planning units should be locked in the solution. This type of argument is only compatible if the planning units in the argument to x are a Spatial-class or data.frame object. The fields (columns) must have logical (i.e. TRUE or FALSE) values indicating if the planning unit is to be locked in the solution. For problems containing multiple zones, this argument should contain a field (column) name for each management zone.

Raster-class

planning units in x that intersect with non-zero and non-NA raster cells are locked in the solution. For problems that contain multiple zones, the Raster-class object must contain a layer for each zone. Note that for multi-band arguments, each pixel must only contain a non-zero value in a single band.

See also

Examples

# set seed for reproducibility set.seed(500) # load data data(sim_pu_polygons, sim_features, sim_locked_in_raster) # create minimal problem p1 <- problem(sim_pu_polygons, sim_features, "cost") %>% add_min_set_objective() %>% add_relative_targets(0.2) %>% add_binary_decisions() # create problem with added locked in constraints using integers p2 <- p1 %>% add_locked_in_constraints(which(sim_pu_polygons$locked_in)) # create problem with added locked in constraints using a field name p3 <- p1 %>% add_locked_in_constraints("locked_in") # create problem with added locked in constraints using raster data p4 <- p1 %>% add_locked_in_constraints(sim_locked_in_raster) # create problem with added locked in constraints using spatial polygon data locked_in <- sim_pu_polygons[sim_pu_polygons$locked_in == 1, ] p5 <- p1 %>% add_locked_in_constraints(locked_in)
# solve problems s1 <- solve(p1)
#> Optimize a model with 5 rows, 90 columns and 450 nonzeros #> Variable types: 0 continuous, 90 integer (90 binary) #> Coefficient statistics: #> Matrix range [2e-01, 9e-01] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 1e+01] #> Found heuristic solution: objective 3934.6218396 #> Presolve time: 0.00s #> Presolved: 5 rows, 90 columns, 450 nonzeros #> Variable types: 0 continuous, 90 integer (90 binary) #> Presolved: 5 rows, 90 columns, 450 nonzeros #> #> #> Root relaxation: objective 3.496032e+03, 16 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 3496.03193 0 4 3934.62184 3496.03193 11.1% - 0s #> H 0 0 3585.9601335 3496.03193 2.51% - 0s #> #> Explored 1 nodes (16 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3585.96 3934.62 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.585960133519e+03, best bound 3.496031931890e+03, gap 2.5078%
s2 <- solve(p2)
#> Optimize a model with 5 rows, 90 columns and 450 nonzeros #> Variable types: 0 continuous, 90 integer (90 binary) #> Coefficient statistics: #> Matrix range [2e-01, 9e-01] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 1e+01] #> Found heuristic solution: objective 4017.6427161 #> Presolve removed 0 rows and 10 columns #> Presolve time: 0.00s #> Presolved: 5 rows, 80 columns, 400 nonzeros #> Variable types: 0 continuous, 80 integer (80 binary) #> Presolved: 5 rows, 80 columns, 400 nonzeros #> #> #> Root relaxation: objective 3.610717e+03, 15 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 3610.71743 0 4 4017.64272 3610.71743 10.1% - 0s #> H 0 0 3649.3763088 3610.71743 1.06% - 0s #> #> Explored 1 nodes (15 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3649.38 4017.64 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.649376308848e+03, best bound 3.610717428789e+03, gap 1.0593%
s3 <- solve(p3)
#> Optimize a model with 5 rows, 90 columns and 450 nonzeros #> Variable types: 0 continuous, 90 integer (90 binary) #> Coefficient statistics: #> Matrix range [2e-01, 9e-01] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 1e+01] #> Found heuristic solution: objective 4017.6427161 #> Presolve removed 0 rows and 10 columns #> Presolve time: 0.00s #> Presolved: 5 rows, 80 columns, 400 nonzeros #> Variable types: 0 continuous, 80 integer (80 binary) #> Presolved: 5 rows, 80 columns, 400 nonzeros #> #> #> Root relaxation: objective 3.610717e+03, 15 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 3610.71743 0 4 4017.64272 3610.71743 10.1% - 0s #> H 0 0 3649.3763088 3610.71743 1.06% - 0s #> #> Explored 1 nodes (15 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3649.38 4017.64 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.649376308848e+03, best bound 3.610717428789e+03, gap 1.0593%
s4 <- solve(p4)
#> Optimize a model with 5 rows, 90 columns and 450 nonzeros #> Variable types: 0 continuous, 90 integer (90 binary) #> Coefficient statistics: #> Matrix range [2e-01, 9e-01] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 1e+01] #> Found heuristic solution: objective 4017.6427161 #> Presolve removed 0 rows and 10 columns #> Presolve time: 0.00s #> Presolved: 5 rows, 80 columns, 400 nonzeros #> Variable types: 0 continuous, 80 integer (80 binary) #> Presolved: 5 rows, 80 columns, 400 nonzeros #> #> #> Root relaxation: objective 3.610717e+03, 15 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 3610.71743 0 4 4017.64272 3610.71743 10.1% - 0s #> H 0 0 3649.3763088 3610.71743 1.06% - 0s #> #> Explored 1 nodes (15 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3649.38 4017.64 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.649376308848e+03, best bound 3.610717428789e+03, gap 1.0593%
s5 <- solve(p5)
#> Optimize a model with 5 rows, 90 columns and 450 nonzeros #> Variable types: 0 continuous, 90 integer (90 binary) #> Coefficient statistics: #> Matrix range [2e-01, 9e-01] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 1e+01] #> Found heuristic solution: objective 4017.6427161 #> Presolve removed 0 rows and 10 columns #> Presolve time: 0.00s #> Presolved: 5 rows, 80 columns, 400 nonzeros #> Variable types: 0 continuous, 80 integer (80 binary) #> Presolved: 5 rows, 80 columns, 400 nonzeros #> #> #> Root relaxation: objective 3.610717e+03, 15 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 3610.71743 0 4 4017.64272 3610.71743 10.1% - 0s #> H 0 0 3649.3763088 3610.71743 1.06% - 0s #> #> Explored 1 nodes (15 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3649.38 4017.64 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.649376308848e+03, best bound 3.610717428789e+03, gap 1.0593%
# plot solutions par(mfrow = c(3,2), mar = c(0, 0, 4.1, 0)) plot(s1, main = "none locked in") plot(s1[s1$solution_1 == 1, ], col = "darkgreen", add = TRUE) plot(s2, main = "locked in (integer input)") plot(s2[s2$solution_1 == 1, ], col = "darkgreen", add = TRUE) plot(s3, main = "locked in (character input)") plot(s3[s3$solution_1 == 1, ], col = "darkgreen", add = TRUE) plot(s4, main = "locked in (raster input)") plot(s4[s4$solution_1 == 1, ], col = "darkgreen", add = TRUE) plot(s5, main = "locked in (polygon input)") plot(s5[s5$solution_1 == 1, ], col = "darkgreen", add = TRUE)
# create minimal multi-zone problem with spatial data p6 <- problem(sim_pu_zones_polygons, sim_features_zones, cost_column = c("cost_1", "cost_2", "cost_3")) %>% add_min_set_objective() %>% add_absolute_targets(matrix(rpois(15, 1), nrow = 5, ncol = 3)) %>% add_binary_decisions() # create multi-zone problem with locked in constraints using matrix data locked_matrix <- sim_pu_zones_polygons@data[, c("locked_1", "locked_2", "locked_3")] locked_matrix <- as.matrix(locked_matrix) p7 <- p6 %>% add_locked_in_constraints(locked_matrix)
# solve problem s6 <- solve(p6)
#> Optimize a model with 105 rows, 270 columns and 1620 nonzeros #> Variable types: 0 continuous, 270 integer (270 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 3e+00] #> Found heuristic solution: objective 3524.7950998 #> Presolve removed 7 rows and 0 columns #> Presolve time: 0.00s #> Presolved: 98 rows, 270 columns, 990 nonzeros #> Variable types: 0 continuous, 270 integer (270 binary) #> Presolved: 98 rows, 270 columns, 990 nonzeros #> #> #> Root relaxation: objective 2.642776e+03, 9 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 2642.77567 0 5 3524.79510 2642.77567 25.0% - 0s #> H 0 0 2875.8073247 2642.77567 8.10% - 0s #> #> Explored 1 nodes (9 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 2875.81 3524.8 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.875807324677e+03, best bound 2.642775673413e+03, gap 8.1032%
# create new column representing the zone id that each planning unit # was allocated to in the solution s6$solution <- category_vector(s6@data[, c("solution_1_zone_1", "solution_1_zone_2", "solution_1_zone_3")]) s6$solution <- factor(s6$solution) # plot solution spplot(s6, zcol = "solution", main = "solution", axes = FALSE, box = FALSE)
# create multi-zone problem with locked in constraints using field names p8 <- p6 %>% add_locked_in_constraints(c("locked_1", "locked_2", "locked_3"))
# solve problem s8 <- solve(p8)
#> Optimize a model with 105 rows, 270 columns and 1620 nonzeros #> Variable types: 0 continuous, 270 integer (270 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 3e+00] #> Found heuristic solution: objective 3335.9942703 #> Presolve removed 27 rows and 118 columns #> Presolve time: 0.00s #> Presolved: 78 rows, 152 columns, 304 nonzeros #> Variable types: 0 continuous, 152 integer (152 binary) #> Presolved: 78 rows, 152 columns, 304 nonzeros #> #> #> Root relaxation: objective 3.324542e+03, 2 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> * 0 0 0 3324.5423913 3324.54239 0.00% - 0s #> #> Explored 0 nodes (2 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3324.54 3335.99 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.324542391321e+03, best bound 3.324542391321e+03, gap 0.0000%
# create new column representing the zone id that each planning unit # was allocated to in the solution s8$solution <- category_vector(s8@data[, c("solution_1_zone_1", "solution_1_zone_2", "solution_1_zone_3")]) s8$solution[s8$solution == 1 & s8$solution_1_zone_1 == 0] <- 0 s8$solution <- factor(s8$solution) # plot solution spplot(s8, zcol = "solution", main = "solution", axes = FALSE, box = FALSE)
# create multi-zone problem with raster planning units p9 <- problem(sim_pu_zones_stack, sim_features_zones) %>% add_min_set_objective() %>% add_absolute_targets(matrix(rpois(15, 1), nrow = 5, ncol = 3)) %>% add_binary_decisions() # create raster stack with locked in units locked_in_stack <- sim_pu_zones_stack[[1]] locked_in_stack[!is.na(locked_in_stack)] <- 0 locked_in_stack <- locked_in_stack[[c(1, 1, 1)]] locked_in_stack[[1]][1] <- 1 locked_in_stack[[2]][2] <- 1 locked_in_stack[[3]][3] <- 1 # plot locked in stack plot(locked_in_stack)
# add locked in raster units to problem p9 <- p9 %>% add_locked_in_constraints(locked_in_stack)
# solve problem s9 <- solve(p9)
#> Optimize a model with 105 rows, 270 columns and 1620 nonzeros #> Variable types: 0 continuous, 270 integer (270 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [2e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 2e+00] #> Found heuristic solution: objective 2881.4469505 #> Presolve removed 12 rows and 9 columns #> Presolve time: 0.00s #> Presolved: 93 rows, 261 columns, 783 nonzeros #> Variable types: 0 continuous, 261 integer (261 binary) #> Presolved: 93 rows, 261 columns, 783 nonzeros #> #> #> Root relaxation: objective 2.289262e+03, 12 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 2289.26159 0 6 2881.44695 2289.26159 20.6% - 0s #> H 0 0 2666.3302066 2289.26159 14.1% - 0s #> H 0 0 2463.5687146 2289.26159 7.08% - 0s #> #> Explored 1 nodes (12 simplex iterations) in 0.01 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 3: 2463.57 2666.33 2881.45 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.463568714567e+03, best bound 2.289261594758e+03, gap 7.0754%
# plot solution plot(category_layer(s9), main = "solution", axes = FALSE, box = FALSE)