Showing posts with label Areas. Show all posts
Showing posts with label Areas. Show all posts

Tuesday, July 15, 2025

What is the Big-M Method, and Why Should I Care?

The Big-M method is a common modeling technique used in Mixed Integer Programming (MIP) to represent logical conditions or implications using linear constraints. It introduces a large constant, typically denoted as M, to "turn on" or "turn off" constraints based on the value of binary variables. I usually call these “switch constraints”.

How It Works

Suppose you have a binary variable y ∈ {0,1} and a constraint that should only be active when y=1. You can use the Big-M method to model this:

Example:

You want the constraint:

x ≤ b only if y = 1

Using Big-M, you rewrite it as:

x ≤ b + M(1−y)

  • When y = 1: the constraint becomes x ≤ b
  • When y = 0: the constraint becomes x ≤ b+M which is effectively non-binding if M is large enough

Common Use Cases

  1. Indicator constraints: Linking binary decisions to continuous variables.
  2. Conditional constraints: Enforcing constraints only when certain binary variables are active.
  3. Modeling piecewise linear functions.
  4. Disjunctive constraints: Representing "either-or" logic.

Choosing the Right M

Choosing M is critical:

  • Too small: The model may become infeasible.
  • Too large: It can cause numerical instability and slow down the solver.

A good practice is to estimate the smallest possible M that still ensures correctness, based on the problem's data bounds.

Example:

Suppose we wanted to know if any of stand 234 was harvested? If we have a theme (TH3) in the LANDSCAPE section that tracks standID, we can do this easily. We need to know the area of stand 234, a theme-based output that tracks harvest area by stand (oaHarv(_TH3)  and a binary variable (vb234).  The setup is straightforward:

OUTPUTS
*OUTPUT oaHarv(_TH3) Harvest area
*SOURCE .MASK() aHARV _AREA

OPTIMIZE
*VARIABLE
vb234 _BINARYARRAY ; valid for any planning period

*CONSTRAINTS
oaHARV(234) – M * vb234 <= 0 1.._LENGTH

So, what should be the value of M? Suppose that the AREAS section lists the area of stand 234 as 8.23483834 acres? If you use 8.2 as the value of M in the constraint, it will be too small to completely offset the harvest area if the entire stand is harvested. If you use M = 1E6, the constraint will be arithmetically correct, but the value of M is way too large and may cause problems with the solver. Remember, the value of M should be just big enough to offset the maximum value of your continuous variable (oaHarv). That means we should use the same value used in the AREAS section: 8.23483834.

Tip 1: Remember that stands may be composed of different polygons, so make sure that your total stand area includes all polygons (area records).

Tip 2: Consider carrying at least 8 decimal places for area records. Representing real numbers in computers is not always exact, so the more significant figures you carry, the less likely you’ll introduce numerical difficulties.

Tip 3: In Woodstock models, almost everything is a function of land area. If you are setting up a lot of constraints involving binary variables, consider using thematic indexing to represent stand area. In this construct, all area records have a value of 1 and the true area of the stand is introduced in the LANDSCAPE section. Doing so will simplify the writing of switch constraints because the value of M is always integer (usually 1 but may be larger depending on the number of area records represented). In turn, the value of M will necessarily be of small magnitude.

Wrap-Up

If you’re interested in learning more about mixed integer programming or how to deploy thematic indexing in your models, give me a shout! If you have questions, don’t hesitate to ask in the comments.


Tuesday, October 1, 2024

Hide & Seek In Woodstock

Introduction

Most times, Woodstock modelers are working to report on outcomes and activities. But there are also times when you don't want to see something. Luckily, the syntax provides you with a few different keywords that can do this for you. First, we'll cover a few that have been around a long time, and a new one that was introduced in the latest release. As always, you should understand what's going on when you deploy a Woodstock keyword before using it in an analysis.

*EXCLUDE Keyword

The *EXCLUDE keyword can be applied in both the OPTIMIZE and AREAS sections, but the way the work is quite different in each section. Let's go over the syntax and rules for each

Optimize Section

The keyword tells the interpreter not to generate decision variables for the specified action(s) in the specified period(s). You might want to do this for a few reasons.

  • Resources needed to perform the action are unavailable.
  • A policy directive expires after a few years.
  • A pre-planned schedule (*LPSchedule) already includes enough acres of the specific treatment and you do not want to do more.

After *EXCLUDE, on the next line you type the action code and the period(s) in which you do not want the action to appear.

*EXCLUDE
aCC 1..5        ; considered in periods 6 onward
aTH 1.._LENGTH  ; never considered

The interpreter will not generate any decision variables for the clearcut action aCC in the first 5 periods. However, it will generate decision variables for actions in the LPSCHEDULE, regardless of any directives to exclude actions. The requirement for LPSCHEDULE actions to be implemented always trumps the *EXCLUDE statement.

Although you can write constraints to force the area treated to zero, most of the time using constraints like this is undesirable. The biggest problem is that the interpreter generates decision variables that not needed, and this inflates size of the LP matrix (i.e., making it harder to solve). Using the *EXCLUDE keyword makes it obvious that there will be no outputs related to the action. 

On the other hand, if you're trying to show the potential value of an action to a skeptical client, it may be better to use the constraints because there will be shadow prices. If the shadow price is zero, that indicates that the action provides no additional value. Otherwise, non-zero shadow prices would indicate the potential for a better solution.

Areas Section

The keyword tells the interpreter not to consider portions of the forest for a specified period of time. Again, you might want to do this for a number of reasons.

  • There are leases that expire in the near term.
  • You are considering a land acquisition and want to compare the estate NPV with and without the acquisition
  • Your agency is evaluating policy options that affect public land management.

Again, the syntax is easy. The *EXCLUDE keyword must appear before any area records. Below the keyword, you write full development type masks to represent areas you want excluded. Clearly, the easiest way to achieve this is through a particular theme and set of thematic attributes (e.g., an ownership them and attributes separating fee simple from leases). These also must appear before any area records that are prefaced by A.

*EXCLUDE
 ? ? ? ? TL2022 ? ? ? ? 3.._LENGTH ; timber lease expires in 2022
 ? ? ? ? TL2023 ? ? ? ? 4.._LENGTH ; timber lease expires in 2023
 ? ? ? ? TL2024 ? ? ? ? 5.._LENGTH ; timber lease expires in 2024
*A ABC 1023 PL PE FEE SI80 TM N E3000 37 124.32 ; 2 polygons
... 

Don't be misled, however. The excluded areas do not really disappear – if they did, the model would be infeasible because initial area constraints would be violated. Instead, the excluded areas are transferred to an internal pool of acres that are cannot be accessed by the user. They are not eligible for treatments nor are they reported in inventory measures.

*COMPRESSTIME Keyword

The *COMPRESSTIME keyword is a switch used in the CONTROL section. Its purpose is to limit the number of decision variables generated by the LP matrix. 

*COMPRESSTIME 41,2

I've found that a lot of people don't really understand how it works. Here are some rules:

  • Timing choice pruning commences in the first period (x) following the *COMPRESSTIME keyword, and continues until the end of the planning horizon.
  • The number of timing choices skipped (y) is specified after the starting period of *COMPRESTIME. 
  • It only applies to future development types that have undergone at least one transition. If your model has too many timing choices in existing DevTypes, *COMPRESSTIME will have no effect.
  • If the action has only one or two timing-choices per period, *COMPRESSTIME has no effect. The first and last timing choices are always generated.

I'm not a big fan of this feature because it potentially wastes a lot of time for biometricians. Imagine generating a ton of regen yield tables for commercial thinning for ages 10-24 in one-year increments. That's a LOT of yield tables, and if you're using *COMPRESSTIME, up to half of them are not being used. Consider the number of timing choices BEFORE commencing yield generation!

The New Not (!) Operator in the LANDSCAPE section

Basic landscape attributes and aggregate attributes provide a very flexible system for identifying development types, from very specific to very general. However, it has always been somewhat cumbersome to report on the "everyone but X" category if there are lots of attributes in the theme.

*THEME 5-Lease
 TL2024
 TL2025
 TL2026
 ...
 TL2055
 FEE
*AGGREGATE LEASES
 TL2024 TL2025 TL2026 ... TL2055
*AGGREGATE NO2024 ; everyone but 2024
 TL2025 TL2026 ... TL2055

The 2024 release of Woodstock now allows you to use a ! operator in a DevType mask in place of an aggregate. For example, suppose we want to report on inventory in unexpired leases in period 1. Previously we would need to use an aggregate like NO2024 shown above. In the new release, we don't need an aggregate and instead we write this:

*OUTPUT oiNo2024
*SOURCE ? ? ? ? !TL2024 ? ? ? ? _INVENT yiMBF

Discussion

Your action definitions are not affected by *EXCLUDE; the interpreter still processes the code. It is NOT the same as if you commented out the action specifications entirely. If you remove the action specifications, the interpreter will still see the code referenced in the TRANSITIONS and OUTPUTS sections, and will generate errors.

On the other hand, when you exclude development types from the AREAS section for the entire planning horizon, the effect is the same as if you commented out area records entirely. If you exclude area as a way to preclude harvesting, be careful! Any output derived from the excluded area will be zero, including outputs like habitat or hydrological maturity. Constraints that depend on the ratio of these types of habitats may no longer be feasible once the area is excluded. Let's consider an example.

Suppose you want to evaluate reallocations of land from one management emphasis to another. It is better to recognize those options within a landscape theme. Define actions that are restricted to one management emphasis. Evaluate the impact of reallocation by characterizing your forest with and without the new designation. If needed, create separate AREAS sections for each and run the analysis with scenarios.

Is Woodstock Syntax Eluding You? Contact Me!

If you’d like a new set of eyes to look over your model(s), give me a shout. I'm happy to review your model, and if needed, we can conduct an on-site training review with your team.

What is the Big-M Method, and Why Should I Care?

The  Big-M method  is a common modeling technique used in  Mixed Integer Programming (MIP)  to represent  logical conditions  or  implicatio...