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

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

Arguments

x

problem() (i.e. ConservationProblem) object.

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

Object (i.e. ConservationProblem) 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

Examples

# 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) # \dontrun{ # solve problems s <- stack(solve(p1), solve(p2), solve(p3), solve(p4))
#> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 5 rows, 90 columns and 450 nonzeros #> Model fingerprint: 0xac25e0fe #> 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, 2e+01] #> Found heuristic solution: objective 4544.4850483 #> 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.899056e+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 3899.05601 0 4 4544.48505 3899.05601 14.2% - 0s #> H 0 0 3988.8131278 3899.05601 2.25% - 0s #> #> Explored 1 nodes (12 simplex iterations) in 0.00 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 2: 3988.81 4544.49 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 3.988813127763e+03, best bound 3.899056011987e+03, gap 2.2502% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 293 rows, 234 columns and 1026 nonzeros #> Model fingerprint: 0xb7af95e4 #> Variable types: 0 continuous, 234 integer (234 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+01, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 2e+01] #> Found heuristic solution: objective 18847.196992 #> Found heuristic solution: objective 4724.4850483 #> Presolve time: 0.00s #> Presolved: 293 rows, 234 columns, 1026 nonzeros #> Variable types: 0 continuous, 234 integer (234 binary) #> Presolved: 293 rows, 234 columns, 1026 nonzeros #> #> #> Root relaxation: objective 4.064320e+03, 186 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 4064.31993 0 52 4724.48505 4064.31993 14.0% - 0s #> H 0 0 4196.4791919 4064.31993 3.15% - 0s #> #> Explored 1 nodes (186 simplex iterations) in 0.01 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 3: 4196.48 4724.49 18847.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 4.196479191930e+03, best bound 4.064319933597e+03, gap 3.1493% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 293 rows, 234 columns and 1026 nonzeros #> Model fingerprint: 0x2604fb63 #> Variable types: 0 continuous, 234 integer (234 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+02, 4e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 2e+01] #> Found heuristic solution: objective 20287.196992 #> Found heuristic solution: objective 5594.4850483 #> Presolve time: 0.00s #> Presolved: 293 rows, 234 columns, 1026 nonzeros #> Variable types: 0 continuous, 234 integer (234 binary) #> Presolved: 293 rows, 234 columns, 1026 nonzeros #> #> #> Root relaxation: objective 4.531725e+03, 219 iterations, 0.01 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 4531.72483 0 234 5594.48505 4531.72483 19.0% - 0s #> 0 0 4604.44812 0 232 5594.48505 4604.44812 17.7% - 0s #> 0 0 4664.43086 0 225 5594.48505 4664.43086 16.6% - 0s #> 0 0 4667.41801 0 229 5594.48505 4667.41801 16.6% - 0s #> 0 0 4669.60093 0 229 5594.48505 4669.60093 16.5% - 0s #> 0 0 4685.65525 0 222 5594.48505 4685.65525 16.2% - 0s #> 0 0 4694.51190 0 204 5594.48505 4694.51190 16.1% - 0s #> 0 0 4694.56564 0 204 5594.48505 4694.56564 16.1% - 0s #> 0 0 4694.56564 0 204 5594.48505 4694.56564 16.1% - 0s #> H 0 0 5330.7252629 4694.56564 11.9% - 0s #> H 0 0 5175.1807047 4694.56564 9.29% - 0s #> #> Cutting planes: #> Gomory: 5 #> #> Explored 1 nodes (470 simplex iterations) in 0.14 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 4: 5175.18 5330.73 5594.49 20287.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 5.175180704712e+03, best bound 4.694565636923e+03, gap 9.2869% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 293 rows, 234 columns and 1026 nonzeros #> Model fingerprint: 0xb7af95e4 #> Variable types: 0 continuous, 234 integer (234 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+01, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [6e+00, 2e+01] #> Found heuristic solution: objective 18847.196992 #> Found heuristic solution: objective 4724.4850483 #> Presolve time: 0.00s #> Presolved: 293 rows, 234 columns, 1026 nonzeros #> Variable types: 0 continuous, 234 integer (234 binary) #> Presolved: 293 rows, 234 columns, 1026 nonzeros #> #> #> Root relaxation: objective 4.064320e+03, 186 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 4064.31993 0 52 4724.48505 4064.31993 14.0% - 0s #> H 0 0 4196.4791919 4064.31993 3.15% - 0s #> #> Explored 1 nodes (186 simplex iterations) in 0.01 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 3: 4196.48 4724.49 18847.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 4.196479191930e+03, best bound 4.064319933597e+03, gap 3.1493%
# plot solutions plot(s, main = c("basic solution", "small penalties", "high penalties", "precomputed data"), axes = FALSE, box = FALSE)
# } # 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)
#> [,1] [,2] [,3] #> [1,] 1 0 0 #> [2,] 0 1 0 #> [3,] 0 0 1
# 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)
#> [,1] [,2] [,3] #> [1,] 0 1 1 #> [2,] 1 0 1 #> [3,] 1 1 0
# 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)
#> [,1] [,2] [,3] #> [1,] 1.0 0.3 0 #> [2,] 0.3 1.0 0 #> [3,] 0.0 0.0 1
# 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)
#> [,1] [,2] [,3] #> [1,] 1 0 0 #> [2,] 0 1 0 #> [3,] 0 0 -1
# create problem with the zone matrix p10 <- p5 %>% add_boundary_penalties(500, zone = zm10) # \dontrun{ # 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)))
#> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 105 rows, 270 columns and 1620 nonzeros #> Model fingerprint: 0x168289c2 #> 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 13103.242827 #> Presolve time: 0.00s #> Presolved: 105 rows, 270 columns, 1620 nonzeros #> Variable types: 0 continuous, 270 integer (270 binary) #> Presolved: 105 rows, 270 columns, 1620 nonzeros #> #> #> Root relaxation: objective 1.199145e+04, 211 iterations, 0.00 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 11991.4483 0 18 13103.2428 11991.4483 8.48% - 0s #> #> Explored 0 nodes (211 simplex iterations) in 0.01 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 1: 13103.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.310324282660e+04, best bound 1.199144828715e+04, gap 8.4849% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 975 rows, 705 columns and 3360 nonzeros #> Model fingerprint: 0x9ae2b322 #> Variable types: 0 continuous, 705 integer (705 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+01, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 2e+01] #> Found heuristic solution: objective 14008.242827 #> Presolve time: 0.01s #> Presolved: 975 rows, 705 columns, 3360 nonzeros #> Variable types: 0 continuous, 705 integer (705 binary) #> Presolved: 975 rows, 705 columns, 3360 nonzeros #> #> #> Root relaxation: objective 1.228259e+04, 575 iterations, 0.02 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 12282.5861 0 310 14008.2428 12282.5861 12.3% - 0s #> H 0 0 13778.654077 12282.5861 10.9% - 0s #> H 0 0 13659.707836 12282.5861 10.1% - 0s #> H 0 0 13451.469667 12282.5861 8.69% - 0s #> #> Explored 1 nodes (575 simplex iterations) in 0.04 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 4: 13451.5 13659.7 13778.7 14008.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.345146966676e+04, best bound 1.228258611787e+04, gap 8.6896% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 975 rows, 705 columns and 3360 nonzeros #> Model fingerprint: 0x3ccabb57 #> Variable types: 0 continuous, 705 integer (705 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+02, 4e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 2e+01] #> Found heuristic solution: objective 22153.242827 #> Presolve time: 0.01s #> Presolved: 975 rows, 705 columns, 3360 nonzeros #> Variable types: 0 continuous, 705 integer (705 binary) #> Presolved: 975 rows, 705 columns, 3360 nonzeros #> #> #> Root relaxation: objective 1.362015e+04, 655 iterations, 0.02 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 13620.1452 0 655 22153.2428 13620.1452 38.5% - 0s #> H 0 0 20154.993440 13620.1452 32.4% - 0s #> 0 0 13770.3047 0 624 20154.9934 13770.3047 31.7% - 0s #> H 0 0 19969.144300 13770.3047 31.0% - 0s #> 0 0 13878.2308 0 604 19969.1443 13878.2308 30.5% - 0s #> 0 0 13881.4949 0 614 19969.1443 13881.4949 30.5% - 0s #> 0 0 13911.8533 0 611 19969.1443 13911.8533 30.3% - 0s #> H 0 0 18843.311920 13911.8533 26.2% - 0s #> 0 0 13911.8533 0 611 18843.3119 13911.8533 26.2% - 0s #> H 0 0 16204.385441 13911.8533 14.1% - 0s #> H 0 0 15678.285614 13911.8533 11.3% - 0s #> 0 2 13912.0561 0 611 15678.2856 13912.0561 11.3% - 0s #> H 135 104 15521.904375 14011.2044 9.73% 32.6 0s #> #> Cutting planes: #> Gomory: 8 #> #> Explored 136 nodes (5394 simplex iterations) in 0.74 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 7: 15521.9 15678.3 16204.4 ... 22153.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.552190437486e+04, best bound 1.401120436180e+04, gap 9.7327% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 1845 rows, 1140 columns and 5100 nonzeros #> Model fingerprint: 0xada27267 #> Variable types: 0 continuous, 1140 integer (1140 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+02, 2e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 2e+01] #> Found heuristic solution: objective 8303.2428266 #> Presolve time: 0.02s #> Presolved: 1845 rows, 1140 columns, 6840 nonzeros #> Variable types: 0 continuous, 1140 integer (1140 binary) #> Presolve removed 870 rows and 0 columns #> Presolved: 975 rows, 1140 columns, 4230 nonzeros #> #> #> Root relaxation: objective 2.576990e+03, 1715 iterations, 0.05 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 2576.99025 0 235 8303.24283 2576.99025 69.0% - 0s #> H 0 0 2881.3718971 2576.99025 10.6% - 0s #> H 0 0 2794.5621583 2576.99025 7.79% - 0s #> #> Explored 1 nodes (1800 simplex iterations) in 0.13 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 3: 2794.56 2881.37 8303.24 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 2.794562158270e+03, best bound 2.576990253978e+03, gap 7.7855% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 1555 rows, 995 columns and 4520 nonzeros #> Model fingerprint: 0xae681357 #> Variable types: 0 continuous, 995 integer (995 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [3e+01, 4e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 2e+01] #> Found heuristic solution: objective 21613.242827 #> Presolve time: 0.02s #> Presolved: 1555 rows, 995 columns, 5680 nonzeros #> Variable types: 0 continuous, 995 integer (995 binary) #> Presolve removed 580 rows and 0 columns #> Presolved: 975 rows, 995 columns, 3940 nonzeros #> #> #> Root relaxation: objective 1.362015e+04, 729 iterations, 0.03 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 13620.1452 0 655 21613.2428 13620.1452 37.0% - 0s #> H 0 0 20679.750176 13620.1452 34.1% - 0s #> H 0 0 20023.371279 13620.1452 32.0% - 0s #> 0 0 13745.4959 0 683 20023.3713 13745.4959 31.4% - 0s #> H 0 0 16814.522531 13745.4959 18.3% - 0s #> 0 0 13745.7308 0 683 16814.5225 13745.7308 18.3% - 0s #> 0 0 13831.7639 0 604 16814.5225 13831.7639 17.7% - 0s #> 0 0 13844.7800 0 593 16814.5225 13844.7800 17.7% - 0s #> 0 0 13863.6022 0 594 16814.5225 13863.6022 17.5% - 0s #> 0 0 13863.6022 0 594 16814.5225 13863.6022 17.5% - 0s #> 0 2 13864.0559 0 594 16814.5225 13864.0559 17.5% - 0s #> H 27 27 15944.410066 13866.0795 13.0% 53.9 0s #> H 54 54 15730.031779 13866.0795 11.8% 41.9 1s #> H 116 75 15585.976112 13876.1302 11.0% 36.8 1s #> #> Cutting planes: #> Gomory: 9 #> #> Explored 290 nodes (11724 simplex iterations) in 1.59 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 7: 15586 15730 15944.4 ... 21613.2 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.558597611216e+04, best bound 1.403676075946e+04, gap 9.9398% #> Gurobi Optimizer version 9.0.2 build v9.0.2rc0 (linux64) #> Optimize a model with 1120 rows, 705 columns and 3795 nonzeros #> Model fingerprint: 0xe02f3708 #> Variable types: 0 continuous, 705 integer (705 binary) #> Coefficient statistics: #> Matrix range [2e-01, 1e+00] #> Objective range [1e+01, 4e+02] #> Bounds range [1e+00, 1e+00] #> RHS range [1e+00, 2e+01] #> Found heuristic solution: objective 15601.521733 #> Presolve time: 0.01s #> Presolved: 1120 rows, 705 columns, 3940 nonzeros #> Variable types: 0 continuous, 705 integer (705 binary) #> Presolved: 1120 rows, 705 columns, 3940 nonzeros #> #> #> Root relaxation: objective 9.328641e+03, 598 iterations, 0.02 seconds #> #> Nodes | Current Node | Objective Bounds | Work #> Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time #> #> 0 0 9328.64105 0 481 15601.5217 9328.64105 40.2% - 0s #> H 0 0 13044.004782 9328.64105 28.5% - 0s #> H 0 0 12904.982021 9328.64105 27.7% - 0s #> 0 0 9365.33880 0 432 12904.9820 9365.33880 27.4% - 0s #> 0 0 9366.98721 0 433 12904.9820 9366.98721 27.4% - 0s #> 0 0 9419.01666 0 495 12904.9820 9419.01666 27.0% - 0s #> H 0 0 12721.479342 9419.01666 26.0% - 0s #> 0 0 9437.43529 0 445 12721.4793 9437.43529 25.8% - 0s #> H 0 0 12537.815277 9437.43529 24.7% - 0s #> 0 0 9438.92869 0 439 12537.8153 9438.92869 24.7% - 0s #> 0 0 9468.77042 0 444 12537.8153 9468.77042 24.5% - 0s #> H 0 0 12536.982752 9468.77042 24.5% - 0s #> 0 0 9468.97121 0 452 12536.9828 9468.97121 24.5% - 0s #> 0 0 9476.40339 0 490 12536.9828 9476.40339 24.4% - 0s #> 0 0 9481.28491 0 494 12536.9828 9481.28491 24.4% - 0s #> 0 0 9481.28491 0 494 12536.9828 9481.28491 24.4% - 0s #> H 0 0 10821.329400 9481.28491 12.4% - 0s #> 0 2 9481.69481 0 494 10821.3294 9481.69481 12.4% - 0s #> H 54 42 10555.622013 9510.15787 9.90% 52.0 0s #> #> Cutting planes: #> Gomory: 3 #> Zero half: 29 #> #> Explored 55 nodes (3884 simplex iterations) in 0.76 seconds #> Thread count was 1 (of 4 available processors) #> #> Solution count 8: 10555.6 10821.3 12537 ... 15601.5 #> #> Optimal solution found (tolerance 1.00e-01) #> Best objective 1.055562201321e+04, best bound 9.510157867559e+03, gap 9.9043%
# 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)
# }