Introduction
Recently, I've been working on a modeling project with a lot of interesting silviculture. In addition to the usual suspects (clearcutting, commercial thinning), this model includes group selection, individual tree selection and variable retention harvesting. Devising the conceptual model for this project was challenging (something I'll talk about in another post), but keeping track of the many different yield tables was equally so. Specifically, it was a challenge to know that I was associating the correct yield table with each stand, AND that I wasn't inadvertently missing tables. So, in this post, I’m going to review errors of omission and commission and highlight a feature in the Woodstock editor that can be a big help.
Errors of Omission
You are committing an error of omission in your model when you reference a cost coefficient that doesn’t exist. For example, if you have stumpage prices by district, but you forgot to include one district in the YIELDS section, Woodstock assumes a value of 0 for prices in the missing district. Normally, that will just generate the familiar Warning 74 (yield not found, assume 0), despite the fact that it is a major problem.
Luckily, you can avoid errors of omission fairly easily by following a simple methodology based on this idea: never rely on Woodstock to assume 0 for you:
Define all yield sets with the same yield components (columns). If a product doesn’t exist in a stand, then print a column of zeros. Yes, Woodstock will complain (Warning 328) that you don’t need that column. You can mute that error code in the CONTROL section.
If you include non-productive areas in your model, assign them an explicit yield set as well. You just need a single row of zeros under each yield component heading for AGE or CP = 1.
If you do this, you should be able to check for missing yields using any of your defined yield components (e.g., ytmvt) using the following report:
*TARGET yield_check.dbfytmvt
Open the report file, and sort the YldNumber column in ascending order. If there are blanks in the YldNumber column, the development types shown do not have yield tables. Woodstock has assumed 0 for you.
How does it work?
Internally, Woodstock maintains a list of YldNumbers (corresponding to each yield component) to which each development type points. If a development type does not point to a yield component, it triggers the warning 74.
By ensuring that every development type points to an instance of every yield component, there should be no gaps in the yield report. Yes, it does require redundant information that must be stored in memory, but the trade-off is knowing that you are not missing any real yield information.
The DevTypes you should be most concerned about are existing types that have never been treated. These ALL should have matching yield tables or else your initial inventory numbers will be off.
You may also have missing yields for specific timing choices of an action, even though all existing untreated stands are accounted for. This can arise when you have specified a general operability statement, but some conditions do not have yields associated with them. You can apply very specific DevType masks on multiple lines to account for every single stand, but this may not be worth the effort to account for them all. If the number of missing yield tables is small and only represents a small subset of some specific timing choices, all may be fine. When Woodstock evaluates those timing choices, the 0 coefficients associated with them should cause those timing choices to never be chosen.
Errors of Commission
You are committing an error of commission when you point to wrong information in your model. For example, this can occur if you associate the wrong price coefficient in your output definition, or if Woodstock matches an incorrect yield table with a development type. Unfortunately, errors of commission are much harder to find than errors of omission. There is no easy "Wrong_Yield" report you can use to identify them.
Avoiding these types of errors requires diligence and a methodical approach to model development. You should use the *GROUP keyword in your OUTPUTS section to develop all your outputs. Just like an outline in a Word document, you can use *GROUP to identify all the potential outputs you will need. Then, within each *GROUP, systematically work through all the variations on outputs that required. Copy and paste operations often result in overlooked edits that lead to errors of commission. Automation tools like Integrator or Python are better at ensuring that you are enumerating all the possible combinations with the right yield component.
CTRL-M - a handy tool
My favorite newer feature of the Woodstock editor is the CTRL-M (mask search) function. This feature works very much like the CTRL-F (Find) function but it isn’t literal like CTRL-F. For example, if you search a file for the string ‘CH00018 ? ? ? ? UT’, Woodstock will look only for strings where there is a single space between question marks. It will not find this string where there are two spaces between the question mark and UT : ‘CH00018 ? ? ? ? UT’. Unless you are very consistent in spacing, CTRL-F can be of limited utility if you’re trying to find a matching yield table for a particular development type.
If you open the CRTL-M dialog, you can enter a fully defined development type mask, with or without global and aggregate attributes. When you click Find, the Woodstock editor searches for masks that match, including global attributes. For example, suppose you input the following string into the CTRL-M dialog:
'FEE NONE NONE FC Y CSP CH00018 FE N WH I UT 250 ZR6024 1 LBC'.
In your YIELDS section, CTRL-M will locate this yield set header:
*Y ? ? ? ? ? ? CH00018 ? ? ? ? UT ? ? ? ?
and this one,
*Y ? ? ? ? ? ? CH00018 ? ? ? ? UT ? ? ? ?
and also this one,
*Y ? ? ? ? ? ? agGRP8 ? ? ? ? ? ? ? ? ?
In the first instance, the mask search matches to global attributes (?) in all themes except TH7 and TH12. The second instance is exactly the same, but spacing does not matter, as it would in the Find function. With the third instance, the mask search also locates yield headers with valid aggregate attributes - the aggregate agGRP8 includes CH00018.
A Potential Use Case for CTRL-M
Let's assume that you’ve noticed you are getting incorrect volumes reported, and you’ve identified one of the development types that is yielding wrong values. Using CTRL-M, you start searching your YIELDS section for matching yields. You expect to find the correct yield in the bottom third of the file, but instead you find a match almost immediately. When you search again, you find the yield set you were expecting. You have a problem! Remember, Woodstock only searches for yield information until it finds a first match; later matches are ignored.
Now that you’ve found the problem yield table, the question is, why is it there? Did your yield generation process include old inventory information that produced the errant yield table? Was this just temporary code used earlier in the development process? Regardless of how it got there, it can be easily removed. However, if you have an automated process or you rely on contractors to provide the data, you need to make sure that future yield updates do not create the problem once again.
Is Your Model Driving You Crazy? Contact Me!
Finding errors of omission and commission can be difficult in a large complex model. If you’d like a new set of eyes to look over your model(s), give me a shout to schedule a model audit Afterwards, we can schedule an on-site training review with your staff to review recommendations for avoiding problems in the future.
If you have a topic that you'd like me to address in a future post, send me a message. I'm always more interested in helping with client issues than ones that I think might be of interest.
No comments:
Post a Comment