Conservation planning problems that aim to maximize the representation of features given a budget often will not able to conserve all of the features unless the budget is very high. In such budget-limited problems, it may be desirable to prefer the representation of some features over other features. This information can be incorporated into the problem using weights. Weights can be applied to a problem to favor the representation of some features over other features when making decisions about how the budget should be allocated.

# S4 method for ConservationProblem,numeric
add_feature_weights(x, weights)

# S4 method for ConservationProblem,matrix
add_feature_weights(x, weights)

Arguments

x

ConservationProblem-class object.

weights

numeric or matrix of weights. See the Details section for more information.

Value

ConservationProblem-class object with the weights added to it.

Details

Weights can only be applied to problems that have an objective that is budget limited (e.g. add_max_cover_objective). #' They can be applied to problems that aim to maximize phylogenetic representation (add_max_phylo_objective) to favor the representation of specific features over the representation of some phylogenetic branches. Weights cannot be negative values and must have values that are equal to or larger than zero. Note that planning unit costs are scaled to 0.01 to identify the cheapest solution among multiple optimal solutions. This means that the optimization process will favor cheaper solutions over solutions that meet feature targets (or occurrences) when feature weights are lower than 0.01.

numeric

containing weights for each feature. Note that this type of argument cannot be used to specify weights for problems with multiple zones.

matrix

containing weights for each feature in each zone. Here, each row corresponds to a different feature in argument to x, each column corresponds to a different zone in argument to x, and each cell contains the weight value for a given feature that the solution can to secure in a given zone. Note that if the problem contains targets created using add_manual_targets then a matrix should be supplied containing a single column that indicates that weight for fulfilling each target.

See also

Examples

# load ape package require(ape)
#> Loading required package: ape
#> #> Attaching package: 'ape'
#> The following objects are masked from 'package:raster': #> #> rotate, zoom
# load data data(sim_pu_raster, sim_features, sim_phylogeny, sim_pu_zones_stack, sim_features_zones) # create minimal problem that aims to maximize the number of features # adequately conserved given a total budget of 3800. Here, each feature # needs 20 % of its habitat for it to be considered adequately conserved p1 <- problem(sim_pu_raster, sim_features) %>% add_max_features_objective(budget = 3800) %>% add_relative_targets(0.2) %>% add_binary_decisions() # create weights that assign higher importance to features with less # suitable habitat in the study area (w2 <- exp((1 / cellStats(sim_features, "sum")) * 200))
#> layer.1 layer.2 layer.3 layer.4 layer.5 #> 11.03585 606.63186 16.11015 108.65716 34.01731
# create problem using rarity weights p2 <- p1 %>% add_feature_weights(w2) # create manually specified weights that assign higher importance to # certain features. These weights could be based on a pre-calculated index # (e.g. an index measuring extinction risk where higher values # denote higher extinction risk) w3 <- c(0, 0, 0, 100, 200) p3 <- p1 %>% add_feature_weights(w3)
# solve problems s1 <- stack(solve(p1), solve(p2), solve(p3))
#> Optimize a model with 6 rows, 95 columns and 545 nonzeros #> Variable types: 0 continuous, 95 integer (95 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [1e-04, 1e+00] #> Bounds range [1e+00, 1e+00] #> RHS range [4e+03, 4e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve time: 0.00s #> Presolved: 6 rows, 95 columns, 545 nonzeros #> Variable types: 0 continuous, 95 integer (95 binary) #> Presolved: 6 rows, 95 columns, 545 nonzeros #> #> #> Root relaxation: objective 4.909018e+00, 30 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 4.90902 0 6 -0.00000 4.90902 - - 0s #> H 0 0 1.9979863 4.90902 146% - 0s #> H 0 0 2.9979659 4.90902 63.7% - 0s #> 0 0 4.90824 0 8 2.99797 4.90824 63.7% - 0s #> 0 0 4.90824 0 9 2.99797 4.90824 63.7% - 0s #> 0 0 4.90731 0 9 2.99797 4.90731 63.7% - 0s #> 0 0 4.90717 0 10 2.99797 4.90717 63.7% - 0s #> 0 0 4.90697 0 11 2.99797 4.90697 63.7% - 0s #> 0 0 4.90693 0 12 2.99797 4.90693 63.7% - 0s #> 0 0 4.90633 0 14 2.99797 4.90633 63.7% - 0s #> 0 0 4.90622 0 14 2.99797 4.90622 63.7% - 0s #> 0 0 4.90340 0 12 2.99797 4.90340 63.6% - 0s #> 0 0 4.90215 0 12 2.99797 4.90215 63.5% - 0s #> 0 0 4.90146 0 11 2.99797 4.90146 63.5% - 0s #> 0 0 4.90135 0 11 2.99797 4.90135 63.5% - 0s #> 0 0 4.90127 0 12 2.99797 4.90127 63.5% - 0s #> 0 2 4.89994 0 12 2.99797 4.89994 63.4% - 0s #> #> Cutting planes: #> Cover: 2 #> MIR: 2 #> StrongCG: 2 #> #> Explored 8 nodes (234 simplex iterations) in 0.04 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 3: 2.99797 1.99799 -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.997965888532e+00, best bound 3.095183750543e+00, gap 3.2428% #> Optimize a model with 6 rows, 95 columns and 545 nonzeros #> Variable types: 0 continuous, 95 integer (95 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [1e-04, 6e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [4e+03, 4e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve time: 0.00s #> Presolved: 6 rows, 95 columns, 545 nonzeros #> Variable types: 0 continuous, 95 integer (95 binary) #> Presolved: 6 rows, 95 columns, 545 nonzeros #> #> #> Root relaxation: objective 7.747768e+02, 18 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 774.77680 0 6 -0.00000 774.77680 - - 0s #> 0 0 774.74919 0 7 -0.00000 774.74919 - - 0s #> 0 0 774.68915 0 9 -0.00000 774.68915 - - 0s #> 0 0 774.68652 0 10 -0.00000 774.68652 - - 0s #> 0 0 774.68452 0 10 -0.00000 774.68452 - - 0s #> 0 0 774.67599 0 11 -0.00000 774.67599 - - 0s #> 0 0 774.65683 0 12 -0.00000 774.65683 - - 0s #> 0 0 774.65490 0 12 -0.00000 774.65490 - - 0s #> 0 0 774.65433 0 13 -0.00000 774.65433 - - 0s #> 0 0 774.62032 0 10 -0.00000 774.62032 - - 0s #> 0 0 774.61987 0 9 -0.00000 774.61987 - - 0s #> 0 0 774.57547 0 10 -0.00000 774.57547 - - 0s #> H 0 0 142.6724257 774.57547 443% - 0s #> 0 0 774.57044 0 11 142.67243 774.57044 443% - 0s #> 0 0 774.56518 0 12 142.67243 774.56518 443% - 0s #> 0 2 774.50629 0 12 142.67243 774.50629 443% - 0s #> H 52 38 715.2870222 749.30428 4.76% 5.7 0s #> #> Cutting planes: #> Cover: 5 #> MIR: 5 #> StrongCG: 2 #> #> Explored 52 nodes (386 simplex iterations) in 0.05 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 3: 715.287 142.672 -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 7.152870222066e+02, best bound 7.493042811185e+02, gap 4.7557% #> Optimize a model with 6 rows, 95 columns and 545 nonzeros #> Variable types: 0 continuous, 95 integer (95 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [1e-04, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [4e+03, 4e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve removed 3 rows and 3 columns #> Presolve time: 0.00s #> Presolved: 3 rows, 92 columns, 272 nonzeros #> Variable types: 0 continuous, 92 integer (92 binary) #> Presolved: 3 rows, 92 columns, 272 nonzeros #> #> #> Root relaxation: objective 2.999981e+02, 23 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 299.99806 0 2 -0.00000 299.99806 - - 0s #> H 0 0 299.9980622 299.99806 0.00% - 0s #> #> Explored 1 nodes (23 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 299.998 -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.999980621935e+02, best bound 2.999980621935e+02, gap 0.0000%
# plot solutions plot(s1, main = c("equal weights", "rarity weights", "manual weights"), axes = FALSE, box = FALSE)
# plot the example phylogeny par(mfrow = c(1, 1)) plot(sim_phylogeny, main = "simulated phylogeny")
# create problem with a maximum phylogenetic representation objective, # where each feature needs 10 % of its distribution to be secured for # it to be adequately conserved and a total budget of 1900 p4 <- problem(sim_pu_raster, sim_features) %>% add_max_phylo_objective(1900, sim_phylogeny) %>% add_relative_targets(0.1) %>% add_binary_decisions()
# solve problem s4 <- solve(p4)
#> Optimize a model with 14 rows, 103 columns and 567 nonzeros #> Variable types: 0 continuous, 103 integer (103 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [5e-06, 9e-01] #> Bounds range [1e+00, 1e+00] #> RHS range [2e+03, 2e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve removed 5 rows and 5 columns #> Presolve time: 0.00s #> Presolved: 9 rows, 98 columns, 557 nonzeros #> Variable types: 0 continuous, 98 integer (98 binary) #> Presolved: 9 rows, 98 columns, 557 nonzeros #> #> #> Root relaxation: objective 4.337104e+00, 26 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 4.33710 0 5 -0.00000 4.33710 - - 0s #> 0 0 4.21288 0 6 -0.00000 4.21288 - - 0s #> H 0 0 2.1552851 4.21288 95.5% - 0s #> 0 0 4.20947 0 7 2.15529 4.20947 95.3% - 0s #> 0 0 4.20920 0 8 2.15529 4.20920 95.3% - 0s #> 0 0 4.20824 0 8 2.15529 4.20824 95.3% - 0s #> 0 0 4.20672 0 8 2.15529 4.20672 95.2% - 0s #> 0 0 4.20663 0 9 2.15529 4.20663 95.2% - 0s #> 0 2 4.15328 0 9 2.15529 4.15328 92.7% - 0s #> H 6 3 2.7445309 3.44216 25.4% 5.0 0s #> H 6 3 2.7445310 3.44216 25.4% 5.0 0s #> #> Cutting planes: #> Cover: 1 #> MIR: 3 #> #> Explored 9 nodes (113 simplex iterations) in 0.02 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 4: 2.74453 2.74453 2.15529 -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.744531030426e+00, best bound 2.744531030426e+00, gap 0.0000%
# plot solution plot(s4, main = "solution", axes = FALSE, box = FALSE)
# find which features have their targets met targets_met4 <- cellStats(s4 * sim_features, "sum") > (0.1 * cellStats(sim_features, "sum")) # plot the example phylogeny and color the represented features in red plot(sim_phylogeny, main = "represented features", tip.color = replace(rep("black", nlayers(sim_features)), which(targets_met4), "red"))
# we can see here that the third feature ("layer.3", i.e. # sim_features[[3]]) is not represented in the solution. Let us pretend # that it is absolutely critical this feature is adequately conserved # in the solution. For example, this feature could represent a species # that plays important role in the ecosystem, or a species that is # important commercial activities (e.g. eco-tourism). So, to generate # a solution that conserves the third feature whilst also aiming to # maximize phylogenetic diversity, we will create a set of weights that # assign a particularly high weighting to the third feature w5 <- c(0, 0, 1000, 0, 0) # we can see that this weighting (i.e. w5[3]) has a much higher value than # the branch lengths in the phylogeny so solutions that represent this # feature be much closer to optimality print(sim_phylogeny$edge.length)
#> [1] 0.92935310 0.04601484 0.19467348 0.42153320 0.83343759 0.48469318 0.85434472 #> [8] 0.58924564
# create problem with high weighting for the third feature and solve it s5 <- p4 %>% add_feature_weights(w5) %>% solve()
#> Optimize a model with 14 rows, 103 columns and 567 nonzeros #> Variable types: 0 continuous, 103 integer (103 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [5e-06, 9e-01] #> Bounds range [1e+00, 1e+00] #> RHS range [2e+03, 2e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve removed 5 rows and 5 columns #> Presolve time: 0.00s #> Presolved: 9 rows, 98 columns, 557 nonzeros #> Variable types: 0 continuous, 98 integer (98 binary) #> Presolved: 9 rows, 98 columns, 557 nonzeros #> #> #> Root relaxation: objective 4.337104e+00, 26 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 4.33710 0 5 -0.00000 4.33710 - - 0s #> 0 0 4.21288 0 6 -0.00000 4.21288 - - 0s #> H 0 0 2.1552851 4.21288 95.5% - 0s #> 0 0 4.20947 0 7 2.15529 4.20947 95.3% - 0s #> 0 0 4.20920 0 8 2.15529 4.20920 95.3% - 0s #> 0 0 4.20824 0 8 2.15529 4.20824 95.3% - 0s #> 0 0 4.20672 0 8 2.15529 4.20672 95.2% - 0s #> 0 0 4.20663 0 9 2.15529 4.20663 95.2% - 0s #> 0 2 4.15328 0 9 2.15529 4.15328 92.7% - 0s #> H 6 3 2.7445309 3.44216 25.4% 5.0 0s #> H 6 3 2.7445310 3.44216 25.4% 5.0 0s #> #> Cutting planes: #> Cover: 1 #> MIR: 3 #> #> Explored 9 nodes (113 simplex iterations) in 0.02 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 4: 2.74453 2.74453 2.15529 -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.744531030426e+00, best bound 2.744531030426e+00, gap 0.0000%
# plot solution plot(s5, main = "solution", axes = FALSE, box = FALSE)
# find which features have their targets met targets_met5 <- cellStats(s5 * sim_features, "sum") > (0.1 * cellStats(sim_features, "sum")) # plot the example phylogeny and color the represented features in red # here we can see that this solution only adequately conserves the # third feature. This means that, given the budget, we are faced with the # trade-off of conserving either the third feature, or a phylogenetically # diverse set of three different features. plot(sim_phylogeny, main = "represented features", tip.color = replace(rep("black", nlayers(sim_features)), which(targets_met5), "red"))
# create multi-zone problem with maximum features objective, # with 10 % representation targets for each feature, and set # a budget such that the total maximum expenditure in all zones # cannot exceed 3000 p6 <- problem(sim_pu_zones_stack, sim_features_zones) %>% add_max_features_objective(3000) %>% add_relative_targets(matrix(0.1, ncol = 3, nrow = 5)) %>% add_binary_decisions() # create weights that assign equal weighting for the representation # of each feature in each zone except that it does not matter if # feature 1 is represented in zone 1 and it really important # that feature 3 is really in zone 1 w7 <- matrix(1, ncol = 3, nrow = 5) w7[1, 1] <- 0 w7[3, 1] <- 100 # create problem with weights p7 <- p6 %>% add_feature_weights(w7)
# solve problems s6 <- solve(p6)
#> Optimize a model with 106 rows, 285 columns and 1905 nonzeros #> Variable types: 0 continuous, 285 integer (285 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [3e-05, 1e+00] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 3e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve time: 0.01s #> Presolved: 106 rows, 285 columns, 1905 nonzeros #> Variable types: 0 continuous, 285 integer (285 binary) #> Presolved: 106 rows, 285 columns, 1905 nonzeros #> #> #> Root relaxation: objective 7.938175e+00, 243 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 7.93818 0 11 -0.00000 7.93818 - - 0s #> H 0 0 3.9996549 7.93818 98.5% - 0s #> H 0 0 4.9996180 7.93818 58.8% - 0s #> 0 0 7.56188 0 18 4.99962 7.56188 51.2% - 0s #> 0 0 7.56101 0 19 4.99962 7.56101 51.2% - 0s #> 0 0 7.27065 0 11 4.99962 7.27065 45.4% - 0s #> 0 0 7.26884 0 12 4.99962 7.26884 45.4% - 0s #> 0 0 7.26873 0 13 4.99962 7.26873 45.4% - 0s #> 0 0 7.26293 0 14 4.99962 7.26293 45.3% - 0s #> H 0 0 4.9996480 7.26293 45.3% - 0s #> 0 0 7.26286 0 14 4.99965 7.26286 45.3% - 0s #> 0 0 7.25824 0 18 4.99965 7.25824 45.2% - 0s #> 0 0 7.25824 0 18 4.99965 7.25824 45.2% - 0s #> H 0 0 4.9996494 7.25824 45.2% - 0s #> 0 2 7.25729 0 18 4.99965 7.25729 45.2% - 0s #> #> Cutting planes: #> Gomory: 1 #> Cover: 6 #> MIR: 6 #> StrongCG: 2 #> GUB cover: 1 #> Inf proof: 2 #> #> Explored 63 nodes (1030 simplex iterations) in 0.09 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 5: 4.99965 4.99965 4.99962 ... -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 4.999649366173e+00, best bound 5.273354104240e+00, gap 5.4745%
s7 <- solve(p7)
#> Optimize a model with 106 rows, 285 columns and 1905 nonzeros #> Variable types: 0 continuous, 285 integer (285 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [3e-05, 1e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 3e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve removed 1 rows and 1 columns #> Presolve time: 0.01s #> Presolved: 105 rows, 284 columns, 1814 nonzeros #> Variable types: 0 continuous, 284 integer (284 binary) #> Presolved: 105 rows, 284 columns, 1814 nonzeros #> #> #> Root relaxation: objective 1.058784e+02, 121 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 105.87844 0 10 -0.00000 105.87844 - - 0s #> H 0 0 102.9996465 105.87844 2.79% - 0s #> #> Explored 1 nodes (121 simplex iterations) in 0.01 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 103 -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.029996464541e+02, best bound 1.058784434632e+02, gap 2.7950%
# plot solutions plot(stack(category_layer(s6), category_layer(s7)), main = c("equal weights", "manual weights"), axes = FALSE, box = FALSE)
# create minimal problem to show the correct method for setting # weights for problems with manual targets p8 <- problem(sim_pu_raster, sim_features) %>% add_max_features_objective(budget = 1500) %>% add_manual_targets(data.frame(feature = c("layer.1", "layer.4"), type = "relative", target = 0.1)) %>% add_feature_weights(matrix(c(1, 200), ncol = 1)) %>% add_binary_decisions()
# solve problem s8 <- solve(p8)
#> Optimize a model with 3 rows, 92 columns and 272 nonzeros #> Variable types: 0 continuous, 92 integer (92 binary) #> Coefficient statistics: #> Matrix range [2e-01, 2e+02] #> Objective range [1e-04, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [2e+03, 2e+03] #> Found heuristic solution: objective -0.0000000 #> Presolve removed 3 rows and 92 columns #> Presolve time: 0.00s #> Presolve: All rows and columns removed #> #> Explored 0 nodes (0 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 1: -0 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective -0.000000000000e+00, best bound -0.000000000000e+00, gap 0.0000%
# plot solution plot(s8, main = "solution", axes = FALSE, box = FALSE)