-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add max area threshold for zone and dealing with fragmented zones #307
Comments
Hi @Tegan151, Awesome! Yeah, to set a threshold for the maximum area selected, you can use the linear constraints (see https://prioritizr.net/reference/add_linear_constraints.html). Note that if you're using a min set problem formulation (menaing that the targets must be met), then you might need to switch to a budget limited objective if you get errors about problem feasibility (e.g. min shortfall objective, https://prioritizr.net/reference/add_min_shortfall_objective.html). These problem feasbility errors (in this particular case) mean that there's no way to meet the target whilst also meeting the maximum area constraint. How does that sound? Yeah, may I ask if you rescaled the boundary data for the prioritization? Although we recommended using the The Let me know if you have any further questions? |
Hi Jeff, Thanks for the quick reply. I understand the linear constraints and have used it to make sure thresholds of certain features are met within different zones but I am still unsure how to tell the problem that I would only like the conservation zone to cover a max of 50 planning units, for example, so that our new suggested MPA does not take up too much space in my solution. I have pasted a figure of my most recent solution to help you visualize. I did not rescale the boundary data. I will give this a go. Thank you. I did have a look through your calibration tutorial at one stage but I found it difficult to implement for a multi-zone problem. I will give another go and let you know if I have any problems. Thanks again for your help reply and and assistance. |
No worries! Yeah, I can put togeather an example showing how to use the linear constraints - what data format are your planning units in (raster, shapefile)? I can write the example so it uses the same data format to make adapting it easier. Ah, yeah, the tutorial only covers single zones, so let me know if you run into any issues. Broadly speaking, I would first create a |
Also, just out of curiosity, is that the Bay of Plenty in New Zealand? |
Thanks, Jeff! You have been so great. No, this is Algoa Bay in South Africa. The 'bay of plenty' is what we have named the scenario that is 'fair' to humans and biodiversity by setting targets and cost layers the same way for each feature/use and zone. We will also have scenario called 'eerie bay' (human use focused) and 'deserted bay' (biodiversity focused). I am using shapefiles. I have paste my problem below to show you what I have done. p0 <-
add_locked_in_constraints(c("lock_in_conres",'lock_in_concon','lock_in_CmmNnEx','lock_in_CmmExtr','lock_in_CmmFshr','lock_in_Trnsprt','lock_in_ADZ')) %>% |
Ok, here's a reproducible example. Let's start by creating a simple multi-zone problem. Here we will use the minimum shortfall objective. This means our objective is to get as close to possible as meeting the targets, whilst ensuring that a particular budget is not exceeded. Note that we are using the minimum shortfall objective because it is a type of budget-limited objective -- meaning that the optimization problem will have feasible solution even if all of the targets cannot be met -- which is useful when we later add in linear constraints. Also, we will set a budget equal to 15% of the total cost across all zones.
We can see that many planning units were selected in the first zone. Let's pretend that we have stakeholders who say that no more than 10 planning units should be allocated to the first zone. We can achieve this using linear constraints. To specify the constraints, we will add some columns to the planning unit data (one column per zone) that have a value of 1 for the first zone (because that's the zone we want to control) and a value of 0 for the remaining zones (because we don't want this constraint to affect the other zones). Note that if we wanted to set maximum limit for each zone, then we would need to add a seperate constraint for each zone. Alternatively, if we wanted to set maximum limits for combinations of zones, then we would set a value of 1 in multiple columns (e.g., if we wanted to ensure that the total number of planning units selected in zones 1 and zone 3 should not exceed 12 planning units, then we would have 1s in the columns for zones 1 and 3, and 0s in the column for zone 2).
How does that sound? Let me know if you have any questions? |
Re scenarios: Oh I see! Thanks for explaining that. Yeah, those pretty good names for scenarios. |
Thanks Jeff! I will run over the weekend and let you know if I have any questions on Monday. |
Hi Jeff, Your code worked like a dream! Thank you. I am still getting random block in the middle of zones so I have added a connectivity penalty in addition to the boundary penalty using the following code: rescale matrix values to have a maximum value of 1d_matrix <- rescale_matrix(d_matrix, max = 1) And the problem:
add_locked_in_constraints(c("lock_in_conres",'lock_in_concon','lock_in_CmmNnEx','lock_in_CmmExtr','lock_in_CmmFshr','lock_in_Trnsprt','lock_in_ADZ')) %>% Is that the best way to add this penalty? Thank you again for all your help! Is has been incredibly useful. |
Yeah that looks good to me! Note that having both connectivity and boundary penalties will slow things down a fair bit though. Also, here's some other ideas for the random planning unit issues:
How does that sound? |
Thanks, Jeff! I will definitely give it a go and let you know how I get on. I am leaving today for a 3 week work trip so I will be slow to response. |
@Tegan151, I just wanted to follow up and ask if those suggestions were able to resolve the issue? Also, did you have any further questions? |
Hi Jeff, Sorry I have been so slow to get back to you. No - the issue is not quite solved yet. I went back and reformatted and simplified all of my data so that the problem would run faster. This took a bit of time. I am currently trying a few things to get the zones to cluster better. I will let you know how I get on. |
No worries! Sorry to hear it's not solved yet. Sounds good, let me know if I can help with any further questions. |
Hi @Tegan151, No worries! I'm sorry those suggestions weren't able to fix this. Could you remind me which objective function you're using? If you're using min set, then I wonder if it might be useful to see if there's any features in those random red blocks that are causing them to be selected? E.g., if you have some features that only occur in the middle part of the study area and you have targets for the commercial fisheries zone saying that you need a certain percent of each feature, then the prioritization will have to prioritize some planning units in the middle of the study area for fisheries to meet the targets (no matter how you change the boundary or connectivity penalties)? After identifying which features are causing the planning units in the middle to be selected, you could then reduce the targets. If you're using min shortfall, then I would expect increasing the connectivity Also, how close is the total area of planning units allocated to the community non-extractive zone to its maximum area constraint? Is it possible that the prioritization is allocating those planning units to the commerical fisheries zone, because the maximum area constraint is preventing the prioritization from allocating all those planning units to the community non-extractive zone? How does that sound? |
Hi Jeff, Thanks again for quick response! I have checked my feature layers, and it is one of the commercial fisheries layers that pretty much only occurs in those blocks. Well, in a very high intensity in those blocks and much lower intensities in all other planning units. I will take this to the rest of the team and see what they think. I am using the min_set_objective. Thanks so much for all off your patience. I really have learnt so much in these interactions with you. One last question, for publication, to show how I selected the connectivity and boundary penalty factors., could I just show the cost of solution and number of planning units selected per zone? Something like below? I know you have a calibrating tradeoffs tutorial on your website but it hasn't been written for zones. |
No worries! Ah - yeah that would definitely explain why the penalties aren't affecting the red blocks. In addition to changing the fisheries target for this feature, another option could be to try using the locked out constraints to specify that none of the planning units in the middle of the planning region should be assigned to the fisheries zone. However, if you're using percentage-based targets, this would probably lead to problem infeasibility (where there is no valid solution that meets all the targets). Yeah, a figure like that is perfectly reasonable. Many studies don't bother with a proper calibration exercise and simply say something like "Preliminary analyses were used to identify a suitable boundary length penalty factor." - so a figure like that is already doing better than some published papers. Also, since you're using both boundary and connectiivity penalties, running a full calibration process could be a bit tricky. If you're interested, the code for a boundary length calibration for multiple zones is pretty similar to that described in the tutorial. The main difference is that when you calculate the boundary length, you need to extract the overall boundary length. E.g., using something like this:
How does that sound? |
Hi Jeff, Thanks again for your reply. I have written some code following the hierarchical approach tutorial. It is taking forever to run, so no results yet. Would you please double check it for me? It was a bit fiddley. #calibrating boundary penalty pp1 <- readRDS('p1.rds') targets <- readRDS('targets.rds') zone_features <- zones(names(pp1),names(pp2),names(pp3),names(pp4),names(pp5),names(pp6), zone_names = c("ConsRes", "ConsCon",'CmmNnEx','CmmExtr','CmmFshr','Trnsprt'),feature_names = feature) #Set up penalty factor #Step one - set cost of lockin PUs to 0 polygon$ConsRes[polygon$lock_in_ConsRes ==T] <- F polygon$ConsRes[polygon$lock_in_ConsCon ==T] <- F polygon$ConsRes[polygon$lock_in_CmmNnEx ==T] <- F polygon$ConsRes[polygon$lock_in_Trnsprt ==T] <- F Hierarchical approachdefine a problem without boundary penalties to optimality (gap = 0)p1 <- calculate costs1_cost <- eval_cost_summary(p1, s1[, c("solution_1_ConsRes","solution_1_ConsCon","solution_1_CmmNnEx", "solution_1_CmmExtr","solution_1_CmmFshr",'solution_1_Trnsprt')])$cost calculate cost threshold values for each zonethreshold_consres <- s1_cost[1] + (s1_cost[1] * seq(1e-5, 4, length.out = 4)) threshold_concon <- s1_cost[2] + (s1_cost[2] * seq(1e-5, 4, length.out = 4)) threshold_cmmN<- s1_cost[3] + (s1_cost[3] * seq(1e-5, 4, length.out = 4)) threshold_CmmE <- s1_cost[4] + (s1_cost[4] * seq(1e-5, 4, length.out = 4)) threshold_Fish <- s1_cost[5] + (s1_cost[5] * seq(1e-5, 4, length.out = 4)) threshold_Trpt <- s1_cost[6] + (s1_cost[6] * seq(1e-5, 4, length.out = 4)) add a column with zerospolygon$zerosCR <- 0 define a problem with zero cost values and boundary penaltiesp2 <- generate prioritizations based on each cost thresholdlist <- llist() } |
Hmm, if I understand correctly, you're setting linear constraints to specify a budget for each zone? I think there might be an issue with this block:
I would have expected these constraints to use the original cost values for each of the zones. E.g., something like this:
How does that sound? Sorry if I'm misunderstanding something. |
Hi Jeff, You are 100% correct except that the 'Trnsprt' zone is just a dummy zone where I lock in certain features like anchorage areas and mariculture. I have one more question, the script above has been running forever and is just not finishing. Is there a way to add a linear constraint for the total cost of the solution rather than for each zone separately? |
Sorry for the slow response, I've been on holiday with limited internet access for the last couple of weeks. Hmm, to clarify, did the script get to the step where it starts solving the problem (e.g., you can see messages from the solver), or does it hang before this? Yeah, to add constraints for the overall cost, you could do something like this (where
How does that sound? |
Hi Jeff, Thank you, I managed to figure out the piece of code in your response. It has been running since last Wednesday. It quickly solved the first problem but the second problem with a threshold of total_cost_budget + ( total_cost_budget * 0.5) is not solving. The problems are starting to be solved but the gap never falls below 16% so it is never solved. I found a paper that ran problems with a boundary penalty at different increment and then selected the appropriate boundary penalty as the inflection point between cost and sum of the perimeters of the solution zones. What do you think of this approach? |
Ah - I see - thanks for clarifying that! Hmm, I can't think of any immediate reason for why it's only getting to 16% and then not making much progress. Could you please share (or copy and paste) the Gurobi solver output text shown on the R console? There might be some information that might help with diagnosing this behavior. I wonder if you could try using the solution for the first problem as a starting solution in subsequent problems to help speed things up? E.g., replace this line:
with this line:
Yeah, I would expect the current approach -- which involves using hierachical optimization -- to solve faster than that approach (which involves using blended optimization). You could certainly give this a go though. |
Just had an idea: rather than boundary penalties, you could try using connecitivity penalties with an adjacency matrix. This would be a bit simpler mathematically, and would give very similar results when you have planning units that conform to a regular grid. E.g., you can create the adjacency matrix like this:
and then replace the lines where you use
Broadly speaking, this approach would say that we want to promote connectivity by allocating pairs of planning units that are next to each other (i.e., adjacent, defined in How does that sound? |
Hi Jeff,
I have a multizone problem that I am trying to run. The conservation zone tends to dominate the solution, which is great, in my view, but is not practical for implementation purposes. Is there a way to set a max area threshold for the zone? So for example, the government says that they are only willing to implement a 50 hectare protected area, can I build this into the prioritizr problem?
Secondly, most of my zones are nicely congregated together but I do sometimes have a random planning unit assigned to a zone in the middle of another zone. I have added a boundary and connectivity penalties to try solve this but I still have the same problem. Is there a way around this? Also, what is the connectivity penalty value in this function? Is there any way to meaning select this value? What is the different, for example, between a connectivity penalty value of 1 and 50?
Warmest,
Tegan
The text was updated successfully, but these errors were encountered: