Calculate how well features are represented in a solution.

# S4 method for ConservationProblem,numeric
feature_representation(x, solution)

# S4 method for ConservationProblem,matrix
feature_representation(x, solution)

# S4 method for ConservationProblem,data.frame
feature_representation(x, solution)

# S4 method for ConservationProblem,Spatial
feature_representation(x, solution)

# S4 method for ConservationProblem,Raster
feature_representation(x, solution)

Arguments

x

ConservationProblem-class object.

solution

numeric, matrix, data.frame, Raster-class, or Spatial-class object. See the Details section for more information.

Value

tibble containing the amount ("absolute_held") and proportion ("relative_held") of the distribution of each feature held in the solution. Here, each row contains data that pertain to a specific feature in a specific management zone (if multiple zones are present). This object contains the following columns:

feature

character name of the feature.

zone

character name of the zone (not included when the argument to x contains only one management zone).

absolute_held

numeric total amount of each feature secured in the solution. If the problem contains multiple zones, then this column shows how well each feature is represented in a each zone.

relative_held

numeric proportion of the feature's distribution held in the solution. If the problem contains multiple zones, then this column shows how well each feature is represented in each zone.

Details

Note that all arguments to solution must correspond to the planning unit data in the argument to x in terms of data representation, dimensionality, and spatial attributes (if applicable). This means that if the planning unit data in x is a numeric vector then the argument to solution must be a numeric vector with the same number of elements, if the planning unit data in x is a RasterLayer-class then the argument to solution must also be a RasterLayer-class with the same number of rows and columns and the same resolution, extent, and coordinate reference system, if the planning unit data in x is a Spatial-class object then the argument to solution must also be a Spatial-class object and have the same number of spatial features (e.g. polygons) and have the same coordinate reference system, if the planning units in x are a data.frame then the argument to solution must also be a data.frame with each column correspond to a different zone and each row correspond to a different planning unit, and values correspond to the allocations (e.g. values of zero or one).

Valid solutions should not have non-zero allocations for planning units in zones that have NA cost values in the argument to x. In other words, planning units that have NA cost values in x should always have a value of zero in the argument to solution. If an argument is supplied to solution where this is not the case, then an error will be thrown. Additionally, note that when calculating the proportion of each feature represented in the solution, the denominator is calculated using all planning units---including any planning units with NA cost values in the argument to x.

See also

Examples

# set seed for reproducibility set.seed(500) # load data data(sim_pu_raster, sim_pu_polygons, sim_features, sim_pu_zones_stack, sim_pu_zones_polygons, sim_features_zones) # create a simple conservation planning data set so we can see exactly # how feature representation is calculated pu <- data.frame(id = seq_len(10), cost = c(0.2, NA, runif(8)), spp1 = runif(10), spp2 = c(rpois(9, 4), NA)) # create problem p1 <- problem(pu, c("spp1", "spp2"), cost_column = "cost") # create a solution s1 <- data.frame(solution = rep(c(1, 0), 5)) # calculate feature representation r1 <- feature_representation(p1, s1) # print feature representation print(r1)
#> # A tibble: 2 x 3 #> feature absolute_held relative_held #> <chr> <dbl> <dbl> #> 1 spp1 3.12 0.541 #> 2 spp2 14 0.424
# verify that feature representation calculations are correct all.equal(r1$absolute_held, c(sum(pu$spp1 * s1[[1]]), sum(pu$spp2 * s1[[1]], na.rm = TRUE)))
#> [1] TRUE
all.equal(r1$relative_held, c(sum(pu$spp1 * s1[[1]]) / sum(pu$spp1), sum(pu$spp2 * s1[[1]], na.rm = TRUE) / sum(pu$spp2, na.rm = TRUE)))
#> [1] TRUE
# build minimal conservation problem with raster data p2 <- problem(sim_pu_raster, sim_features) %>% add_min_set_objective() %>% add_relative_targets(0.1) %>% add_binary_decisions()
# solve the problem 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 [3e+00, 8e+00] #> Found heuristic solution: objective 2337.9617505 #> 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 1.931582e+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 1931.58191 0 4 2337.96175 1931.58191 17.4% - 0s #> H 0 0 1985.6818841 1931.58191 2.72% - 0s #> #> Explored 1 nodes (12 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 1985.68 2337.96 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.985681884076e+03, best bound 1.931581908865e+03, gap 2.7245%
# print solution print(s2)
#> class : RasterLayer #> dimensions : 10, 10, 100 (nrow, ncol, ncell) #> resolution : 0.1, 0.1 (x, y) #> extent : 0, 1, 0, 1 (xmin, xmax, ymin, ymax) #> coord. ref. : NA #> data source : in memory #> names : layer #> values : 0, 1 (min, max) #>
# calculate feature representation in the solution r2 <- feature_representation(p2, s2) print(r2)
#> # A tibble: 5 x 3 #> feature absolute_held relative_held #> <chr> <dbl> <dbl> #> 1 layer.1 8.97 0.108 #> 2 layer.2 3.13 0.100 #> 3 layer.3 7.43 0.103 #> 4 layer.4 4.29 0.101 #> 5 layer.5 6.02 0.106
# plot solution plot(s2, main = "solution", axes = FALSE, box = FALSE)
# build minimal conservation problem with spatial polygon data p3 <- problem(sim_pu_polygons, sim_features, cost_column = "cost") %>% add_min_set_objective() %>% add_relative_targets(0.1) %>% add_binary_decisions()
# solve the problem 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 [3e+00, 7e+00] #> Found heuristic solution: objective 2145.2678910 #> 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 1.732564e+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 1732.56396 0 4 2145.26789 1732.56396 19.2% - 0s #> H 0 0 1785.5315740 1732.56396 2.97% - 0s #> #> Explored 1 nodes (12 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 1785.53 2145.27 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.785531573957e+03, best bound 1.732563961206e+03, gap 2.9665%
# print first six rows of the attribute table print(head(s3))
#> cost locked_in locked_out solution_1 #> 1 215.8638 FALSE FALSE 0 #> 2 212.7823 FALSE FALSE 0 #> 3 207.4962 FALSE FALSE 0 #> 4 208.9322 FALSE TRUE 0 #> 5 214.0419 FALSE FALSE 0 #> 6 213.7636 FALSE FALSE 0
# calculate feature representation in the solution r3 <- feature_representation(p3, s3[, "solution_1"]) print(r3)
#> # A tibble: 5 x 3 #> feature absolute_held relative_held #> <chr> <dbl> <dbl> #> 1 layer.1 8.06 0.108 #> 2 layer.2 2.83 0.101 #> 3 layer.3 6.68 0.103 #> 4 layer.4 3.86 0.101 #> 5 layer.5 5.41 0.107
# plot solution spplot(s3, zcol = "solution_1", main = "solution", axes = FALSE, box = FALSE)
# build multi-zone conservation problem with raster data p4 <- problem(sim_pu_zones_stack, sim_features_zones) %>% add_min_set_objective() %>% add_relative_targets(matrix(runif(15, 0.1, 0.2), nrow = 5, ncol = 3)) %>% add_binary_decisions()
# solve the problem s4 <- solve(p4)
#> 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+01] #> Found heuristic solution: objective 12200.043064 #> Presolve removed 8 rows and 0 columns #> Presolve time: 0.00s #> Presolved: 97 rows, 270 columns, 900 nonzeros #> Variable types: 0 continuous, 270 integer (270 binary) #> Presolved: 97 rows, 270 columns, 900 nonzeros #> #> #> Root relaxation: objective 1.033167e+04, 39 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 10331.6670 0 4 12200.0431 10331.6670 15.3% - 0s #> H 0 0 10667.271164 10331.6670 3.15% - 0s #> #> Explored 1 nodes (39 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 10667.3 12200 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.066727116441e+04, best bound 1.033166695246e+04, gap 3.1461%
# print solution print(s4)
#> class : RasterStack #> dimensions : 10, 10, 100, 3 (nrow, ncol, ncell, nlayers) #> resolution : 0.1, 0.1 (x, y) #> extent : 0, 1, 0, 1 (xmin, xmax, ymin, ymax) #> coord. ref. : NA #> names : layer.1.1, layer.1.2, layer.1.3 #> min values : 0, 0, 0 #> max values : 1, 1, 1 #>
# calculate feature representation in the solution r4 <- feature_representation(p4, s4) print(r4)
#> # A tibble: 15 x 4 #> feature zone absolute_held relative_held #> <chr> <chr> <dbl> <dbl> #> 1 feature_1 zone_1 16.0 0.192 #> 2 feature_2 zone_1 5.13 0.164 #> 3 feature_3 zone_1 13.0 0.181 #> 4 feature_4 zone_1 7.06 0.166 #> 5 feature_5 zone_1 11.2 0.197 #> 6 feature_1 zone_2 14.7 0.177 #> 7 feature_2 zone_2 5.03 0.161 #> 8 feature_3 zone_2 11.7 0.163 #> 9 feature_4 zone_2 8.02 0.188 #> 10 feature_5 zone_2 10.4 0.183 #> 11 feature_1 zone_3 13.0 0.156 #> 12 feature_2 zone_3 6.08 0.195 #> 13 feature_3 zone_3 11.4 0.158 #> 14 feature_4 zone_3 8.33 0.195 #> 15 feature_5 zone_3 8.87 0.156
# plot solution plot(category_layer(s4), main = "solution", axes = FALSE, box = FALSE)
# build multi-zone conservation problem with spatial polygon data p5 <- problem(sim_pu_zones_polygons, sim_features_zones, cost_column = c("cost_1", "cost_2", "cost_3")) %>% add_min_set_objective() %>% add_relative_targets(matrix(runif(15, 0.1, 0.2), nrow = 5, ncol = 3)) %>% add_binary_decisions()
# solve the problem s5 <- solve(p5)
#> 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, 1e+01] #> Found heuristic solution: objective 10551.252008 #> 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 8.973346e+03, 70 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 8973.34608 0 9 10551.2520 8973.34608 15.0% - 0s #> H 0 0 9201.5595283 8973.34608 2.48% - 0s #> #> Explored 1 nodes (70 simplex iterations) in 0.01 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 9201.56 10551.3 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 9.201559528348e+03, best bound 8.973346077498e+03, gap 2.4802%
# print first six rows of the attribute table print(head(s5))
#> cost_1 cost_2 cost_3 locked_1 locked_2 locked_3 solution_1_zone_1 #> 1 215.8638 183.3344 205.4113 FALSE FALSE FALSE 0 #> 2 212.7823 189.4978 209.6404 FALSE FALSE FALSE 0 #> 3 207.4962 193.6007 215.4212 TRUE FALSE FALSE 0 #> 4 208.9322 197.5897 218.5241 FALSE FALSE FALSE 0 #> 5 214.0419 199.8033 220.7100 FALSE FALSE FALSE 0 #> 6 213.7636 203.1867 224.6809 FALSE FALSE FALSE 0 #> solution_1_zone_2 solution_1_zone_3 #> 1 0 0 #> 2 0 0 #> 3 0 0 #> 4 0 0 #> 5 0 0 #> 6 0 0
# calculate feature representation in the solution r5 <- feature_representation(p5, s5[, c("solution_1_zone_1", "solution_1_zone_2", "solution_1_zone_3")]) print(r5)
#> # A tibble: 15 x 4 #> feature zone absolute_held relative_held #> <chr> <chr> <dbl> <dbl> #> 1 feature_1 zone_1 14.3 0.190 #> 2 feature_2 zone_1 4.88 0.174 #> 3 feature_3 zone_1 12.2 0.188 #> 4 feature_4 zone_1 6.25 0.164 #> 5 feature_5 zone_1 9.55 0.187 #> 6 feature_1 zone_2 15.0 0.200 #> 7 feature_2 zone_2 4.61 0.165 #> 8 feature_3 zone_2 13.2 0.204 #> 9 feature_4 zone_2 5.65 0.149 #> 10 feature_5 zone_2 10.3 0.200 #> 11 feature_1 zone_3 11.1 0.147 #> 12 feature_2 zone_3 3.89 0.139 #> 13 feature_3 zone_3 8.45 0.130 #> 14 feature_4 zone_3 6.42 0.169 #> 15 feature_5 zone_3 7.96 0.155
# create new column representing the zone id that each planning unit # was allocated to in the solution s5$solution <- category_vector(s5@data[, c("solution_1_zone_1", "solution_1_zone_2", "solution_1_zone_3")]) s5$solution <- factor(s5$solution) # plot solution spplot(s5, zcol = "solution", main = "solution", axes = FALSE, box = FALSE)