Invariant Identification¶
Why It Matters¶
Invariants are anchors for reasoning. If you can establish an invariant, you've found something you don't have to keep re-checking. They reduce complex dynamic systems to stable properties. Most importantly, identifying what must stay constant forces you to be precise about what's allowed to change and what must be preserved.
The Key Move¶
When analyzing any process, ask: "What property remains true throughout?" For loops: what's true before, after each iteration, and at the end? For systems: what never changes despite state transitions? Express it precisely, then verify it holds at initialization and is preserved by each operation.
Classic Application¶
Loop correctness proofs. To prove a while loop computes the right result, find an invariant that:
- is true initially,
- is maintained by the loop body, and
- combined with the termination condition, implies the desired outcome. Example: for computing factorial, the invariant might be "result * factorial(remaining) = factorial(n)."
Surprising Application¶
Habit formation. The invariant isn't "I exercise every day" (too strict) but "I have a system for deciding about exercise every day." The invariant is the meta-level commitment to make the decision, not the decision itself. This explains why successful habit systems focus on maintaining the decision ritual, not perfect compliance.
Failure Modes¶
Mistaking correlated properties for true invariants - something that's been true so far but isn't guaranteed. Making invariants too weak (trivially true but uninformative) or too strong (false in valid cases). Forgetting to check preservation - proving it's true initially but not that operations maintain it.
Go Deeper¶
Dijkstra, A Discipline of Programming, Chapter 14; Mitchell, Concepts in Programming Languages, Section 7.3