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 ConservationProblem-class object. 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. 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. 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. 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

ConservationProblem-class object 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.

penalties.

## Examples

# set seed for reproducibility
set.seed(500)

data(sim_pu_raster, sim_features, sim_pu_zones_stack, sim_features_zones)

# create minimal problem
p1 <- problem(sim_pu_raster, sim_features) %>%

# 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)# solve problems
s <- stack(solve(p1), solve(p2), solve(p3), 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, 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                    3994.8945897 3899.05601  2.40%     -    0s
#>
#> Explored 1 nodes (12 simplex iterations) in 0.00 seconds
#> Thread count was 1 (of 4 available processors)
#>
#> Solution count 2: 3994.89 4544.49
#>
#> Optimal solution found (tolerance 1.00e-01)
#> Best objective 3.994894589653e+03, best bound 3.899056011987e+03, gap 2.3990%
#> Optimize a model with 293 rows, 234 columns and 1026 nonzeros
#> 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%
#> Optimize a model with 293 rows, 234 columns and 1026 nonzeros
#> 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.00 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  226 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.75922    0  225 5594.48505 4685.75922  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 (456 simplex iterations) in 0.13 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%
#> Optimize a model with 293 rows, 234 columns and 1026 nonzeros
#> 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_relative_targets(matrix(0.2, nrow = 5, ncol = 3)) %>%

# 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)# 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)))#> 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 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 1 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%
#> Optimize a model with 975 rows, 705 columns and 3360 nonzeros
#> 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.02s
#> 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, 618 iterations, 0.03 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                    13450.185104 12282.5861  8.68%     -    0s
#>
#> Explored 1 nodes (618 simplex iterations) in 0.05 seconds
#> Thread count was 1 (of 4 available processors)
#>
#> Solution count 2: 13450.2 14008.2
#>
#> Optimal solution found (tolerance 1.00e-01)
#> Best objective 1.345018510397e+04, best bound 1.228258611787e+04, gap 8.6809%
#> Optimize a model with 975 rows, 705 columns and 3360 nonzeros
#> 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.02s
#> 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, 713 iterations, 0.07 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                    20128.117363 13620.1452  32.3%     -    0s
#> H    0     0                    19796.492982 13620.1452  31.2%     -    0s
#>      0     0 13772.8695    0  664 19796.4930 13772.8695  30.4%     -    0s
#> H    0     0                    19578.669240 13772.8695  29.7%     -    0s
#>      0     0 13775.6927    0  659 19578.6692 13775.6927  29.6%     -    0s
#>      0     0 13798.1920    0  611 19578.6692 13798.1920  29.5%     -    0s
#> H    0     0                    19552.871081 13798.1920  29.4%     -    0s
#>      0     0 13823.3790    0  611 19552.8711 13823.3790  29.3%     -    0s
#>      0     0 13823.4016    0  616 19552.8711 13823.4016  29.3%     -    0s
#>      0     0 13834.6267    0  640 19552.8711 13834.6267  29.2%     -    0s
#> H    0     0                    19360.827217 13834.6267  28.5%     -    0s
#>      0     0 13867.3124    0  663 19360.8272 13867.3124  28.4%     -    0s
#>      0     0 13868.1508    0  658 19360.8272 13868.1508  28.4%     -    0s
#>      0     0 13868.1508    0  658 19360.8272 13868.1508  28.4%     -    0s
#> H    0     0                    16529.592722 13868.1508  16.1%     -    1s
#> H    0     0                    15922.309412 13868.1508  12.9%     -    1s
#>      0     2 13869.2667    0  658 15922.3094 13869.2667  12.9%     -    1s
#>    527   430 14213.7844    7  610 15922.3094 14112.4138  11.4%  29.6    5s
#> H  527   408                    15780.713406 14112.4138  10.6%  29.6    5s
#> H  527   387                    15656.048982 14112.4138  9.86%  29.6    5s
#>
#> Cutting planes:
#>   Gomory: 18
#>
#> Explored 527 nodes (18491 simplex iterations) in 5.55 seconds
#> Thread count was 1 (of 4 available processors)
#>
#> Solution count 10: 15656 15780.7 15922.3 ... 22153.2
#>
#> Optimal solution found (tolerance 1.00e-01)
#> Best objective 1.565604898208e+04, best bound 1.411241378650e+04, gap 9.8597%
#> Optimize a model with 1845 rows, 1140 columns and 5100 nonzeros
#> 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.05s
#> 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, 1905 iterations, 0.12 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 (2016 simplex iterations) in 0.28 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%
#> Optimize a model with 1555 rows, 995 columns and 4520 nonzeros
#> 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.07s
#> 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, 714 iterations, 0.11 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                    20845.425726 13620.1452  34.7%     -    0s
#> H    0     0                    19467.036465 13620.1452  30.0%     -    0s
#>      0     0 13728.2763    0  637 19467.0365 13728.2763  29.5%     -    0s
#> H    0     0                    18893.082095 13728.2763  27.3%     -    0s
#>      0     0 13729.6980    0  642 18893.0821 13729.6980  27.3%     -    0s
#>      0     0 13730.2911    0  642 18893.0821 13730.2911  27.3%     -    0s
#>      0     0 13790.5901    0  627 18893.0821 13790.5901  27.0%     -    1s
#>      0     0 13801.0123    0  598 18893.0821 13801.0123  27.0%     -    1s
#>      0     0 13822.5175    0  551 18893.0821 13822.5175  26.8%     -    1s
#> H    0     0                    18751.740399 13822.5175  26.3%     -    1s
#>      0     0 13826.9360    0  563 18751.7404 13826.9360  26.3%     -    1s
#>      0     0 13826.9360    0  563 18751.7404 13826.9360  26.3%     -    1s
#> H    0     0                    17431.702421 13826.9360  20.7%     -    2s
#> H    0     0                    17347.291320 13826.9360  20.3%     -    2s
#> H    0     0                    16456.518756 13826.9360  16.0%     -    2s
#>      0     2 13827.3898    0  563 16456.5188 13827.3898  16.0%     -    3s
#> H  105   103                    16310.857489 13832.3864  15.2%  30.0    3s
#>    340   311 15087.2823   21  296 16310.8575 13979.9747  14.3%  33.0    5s
#> H  510   446                    16294.105380 13988.8212  14.1%  29.6    6s
#> H  513   426                    15987.920808 13988.8212  12.5%  29.4    6s
#> H  516   406                    15894.561955 13988.8212  12.0%  29.3    7s
#>    523   411 15894.5620   70  667 15894.5620 13988.8212  12.0%  28.9   10s
#>
#> Cutting planes:
#>   Gomory: 17
#>
#> Explored 523 nodes (17825 simplex iterations) in 10.00 seconds
#> Thread count was 1 (of 4 available processors)
#>
#> Solution count 10: 15894.6 15987.9 16294.1 ... 19467
#>
#> Time limit reached
#> Best objective 1.589456195550e+04, best bound 1.398882115772e+04, gap 11.9899%
#> Optimize a model with 1120 rows, 705 columns and 3795 nonzeros
#> 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.04s
#> 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, 523 iterations, 0.04 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                    14404.516545 9328.64105  35.2%     -    0s
#>      0     0 9376.71069    0  435 14404.5165 9376.71069  34.9%     -    0s
#> H    0     0                    13853.093457 9376.71069  32.3%     -    0s
#> H    0     0                    13263.346834 9376.71069  29.3%     -    0s
#>      0     0 9388.30013    0  435 13263.3468 9388.30013  29.2%     -    0s
#>      0     0 9433.68734    0  467 13263.3468 9433.68734  28.9%     -    0s
#> H    0     0                    12771.763887 9433.68734  26.1%     -    0s
#>      0     0 9440.54053    0  473 12771.7639 9440.54053  26.1%     -    0s
#>      0     0 9440.69940    0  473 12771.7639 9440.69940  26.1%     -    0s
#>      0     0 9467.62898    0  467 12771.7639 9467.62898  25.9%     -    0s
#> H    0     0                    12676.412706 9467.62898  25.3%     -    0s
#>      0     0 9473.57609    0  476 12676.4127 9473.57609  25.3%     -    0s
#>      0     0 9478.31995    0  478 12676.4127 9478.31995  25.2%     -    0s
#>      0     0 9479.01242    0  477 12676.4127 9479.01242  25.2%     -    0s
#>      0     0 9481.17466    0  480 12676.4127 9481.17466  25.2%     -    0s
#>      0     0 9484.66372    0  479 12676.4127 9484.66372  25.2%     -    1s
#>      0     0 9485.82314    0  478 12676.4127 9485.82314  25.2%     -    1s
#>      0     0 9486.99589    0  479 12676.4127 9486.99589  25.2%     -    1s
#>      0     0 9488.66317    0  465 12676.4127 9488.66317  25.1%     -    1s
#> H    0     0                    12658.741688 9488.66317  25.0%     -    1s
#>      0     0 9488.66317    0  465 12658.7417 9488.66317  25.0%     -    1s
#> H    0     0                    11278.322052 9488.66317  15.9%     -    1s
#>      0     2 9489.13316    0  465 11278.3221 9489.13316  15.9%     -    1s
#> H   27    27                    10938.370123 9538.34579  12.8%  61.7    1s
#> H  108    52                    10332.698302 9546.30398  7.61%  50.0    1s
#>
#> Cutting planes:
#>   Gomory: 6
#>   Zero half: 9
#>
#> Explored 108 nodes (6428 simplex iterations) in 1.91 seconds
#> Thread count was 1 (of 4 available processors)
#>
#> Solution count 10: 10332.7 10938.4 11278.3 ... 15601.5
#>
#> Optimal solution found (tolerance 1.00e-01)
#> Best objective 1.033269830160e+04, best bound 9.546303983599e+03, gap 7.6107%
# 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)