Sunday, April 21, 2024

What To Do When Things Go Wrong

Introduction

I’ve been using Woodstock for a long time… a very, VERY long time. So, you might think I never get stumped or encounter oddball results. And you would be wrong. One of the things I miss most about working in a team environment is getting help from a colleague on a Woodstock model that is giving me grief. I recall working on a model build project for a client. The land base was relatively small but there were lots of details. This model required the use of the ALLOCATION and REGIMES modules, and the OUTPUTS section was quite extensive. A second set of eyes could have saved me hours of frustration.

The model tracked a lot of silvicultural costs, and many of those costs occurred in the same planning period. Since this was a new model build, I could define my own outputs rather than using inherited code. I did not want to simply create outputs for each one and then sum them because all those nodes will slow down matrix generation. Instead, I relied on summary coefficients in the YIELDS section to streamline the OUTPUTS section. The resulting matrix generation was very quick. As a test, I compared the values of the client summary outputs to my new outputs based on summary yield coefficients. Not surprisingly, I got the same answers and so I sent off the initial model to the client for review. I got back a simple question.

Why is the Objective Function Value Different than the Calculated NPV?

Sure enough, the objective function value (ordREV – ocdCOST) from the solver was about $5000 higher than my calculated NPV. I reviewed all of my outputs and verified that each one was triggered by the correct action. I also made sure that the yield coefficients were also correct. However, I did not find any errors and my attempts using various rewrites of the output specifications yielded no new insights. I was stumped. So I thought back on my process to see where things stopped working.

I ran one-line AREAS files to test various regime combinations, and these all produced consistent results between the objective function and output calculation. Next, I wrote a constraint to force the choice of a different prescription, and that too worked as expected. It was only when I incorporated a forced activity in the LPSCHEDULE that the results differed. The actions were carried out properly but deliveries in the AO Detailed report looked odd – all of the forced activities that were part of REGIMES had no development types associated with them.

I sent my simplified model off to Remsoft technical support and within a day I received back an email from Ugo. It turns out that there was a bug in Woodstock. I had created the LPSCHEDULE section using the Spatial Woodstock menu option and it wrote the LPSCHEDULE in the newer “Treatments” syntax:

.MASK() Age Area RegimeCode(Period,_RX(RxCode),Transition#)

Woodstock did not handle deliveries properly from the LPSCHEDULE, hence the different objective function values. As a workaround, Ugo told me that if I used the older “Stanley” syntax, the LPSCHEDULE would be processed properly:

.MASK() Age Area RegimeCode Period _RX(RxCode)

Ugo also told me that the bug had been fixed in the subsequent release. Problem solved! But the experience taught me a few important lessons.

Lessons Learned

Don’t waste a lot of time on something that seems to be eluding you. If you have a colleague you can ask for help, do it. Often, they can spot a problem in code that your brain refuses to see. It is also better than thinking you’ve gone insane.

Check ALL your work. I should have spotted the objective function issue before sending it to the client. But I assumed that the model was working properly because it had worked fine before I added any constraints (i.e., LPSCHEDULE).

Don’t assume it is necessarily your fault - software bugs are a fact of life. Once I identified the issue with my model, I created a small instance of the model that replicated the problem and sent it off to Remsoft technical support with a detailed explanation of the problem. That will get you faster solutions than if you just send a large, complicated model with no explanations as to what the problem is or what you have tried.

Do You Need a Second Pair of Eyes? Contact Me!

If your model is misbehaving (calculation errors, memory errors, etc.) then by all means contact Remsoft tech support. Otherwise, if your model is slow, or you want to implement something new and you are not sure how to do it, give me a shout. There are several alternative engagements we could undertake to keep you and your team productive.

No comments:

Post a Comment

Why are MIP models difficult to solve (or not)?

Introduction I recently joined a conversation about why a mixed-integer programming (MIP) problem is so much harder to solve than a regular ...