Reasoning about Correctness

The Role of Proofs

How do we know if an algorithm is correct? We need rigorous reasoning—typically in the form of a proof.

A mathematical proof consists of:

  1. A clear statement of what you're trying to prove

  2. A set of assumptions (things taken as true)

  3. A logical chain of reasoning from assumptions to conclusion

  4. A marker indicating completion (□ or QED)

circle-info

This book de-emphasizes formal proofs because they're difficult to execute properly and can be misleading when done incorrectly. Instead, the focus is on clear, honest arguments that explain why an algorithm works.

Problem Specifications

Before designing an algorithm, you need a precise problem definition with two components:

  1. Input: The set of allowed instances

  2. Output: The required properties of the solution

circle-exclamation

Common Specification Pitfalls

Pitfall 1: Input too broad

Remember the movie scheduling problem? If we allowed films with production gaps (filming in September and November, but not October), our earliest-completion algorithm would fail. The problem would become much harder—in fact, no efficient algorithm exists for this generalized version.

circle-check

Pitfall 2: ill-defined output

"Find the best route between two cities" is meaningless without defining "best":

  • Shortest distance?

  • Fastest time?

  • Fewest turns?

Each leads to a different, well-defined optimization problem.

Pitfall 3: Compound goals

"Find the shortest route that doesn't use more than twice as many turns as necessary" is well-defined but complicated. Simple, single-objective problems are easier to solve and reason about.

Expressing Algorithms

Algorithms can be described in three ways:

Method
Precision
Ease of Expression

English

Low

High

Pseudocode

Medium

Medium

Real code

High

Low

English is natural but imprecise. Real code (Java, C++, Python) is precise but verbose. Pseudocode is a "programming language that never complains about syntax errors"—a happy medium.

circle-exclamation

Example: Good vs. Bad Pseudocode

Bad (obscures the idea):

Good (reveals the idea):

circle-check

Demonstrating Incorrectness

The fastest way to prove an algorithm wrong is to find a counterexample—an input where the algorithm produces an incorrect answer.

Properties of Good Counterexamples

1. Verifiable

  • You can calculate what the algorithm returns

  • You can show a better answer exists

2. Simple

  • Strip away unnecessary details

  • Make the failure mechanism crystal clear

  • Keep it small enough to reason about mentally

Hunting for Counterexamples

Think small

The robot tour counterexamples used ≤6 points. The scheduling counterexamples used ≤3 intervals. When algorithms fail, they usually fail on simple cases. Don't draw large messy instances—analyze small, clear ones.

Think exhaustively

For small n, enumerate all possible configurations. For two intervals, there are only three cases:

  • Disjoint

  • Overlapping

  • Nested (one inside the other)

For three intervals, systematically add a third to each of these cases.

Hunt for the weakness

If an algorithm is greedy ("always pick the biggest/smallest/earliest"), ask: when would that choice be wrong?

Go for a tie

Break greedy heuristics by making everything equal. If all items are the same size, the heuristic has nothing to decide on and might return something suboptimal.

Seek extremes

Mix huge and tiny, left and right, near and far. Extreme cases are easier to analyze.

Example: Two tight clusters of points separated by distance d. The optimal TSP tour is approximately 2d regardless of cluster size—what happens inside each cluster barely matters.

circle-check

Summary: The Three-Step Process

When evaluating an algorithm:

  1. Define the problem precisely (inputs and required outputs)

  2. Express the algorithm clearly (reveal the core idea)

  3. Test correctness (search for counterexamples; prove correctness if none exist)

This disciplined approach separates correct algorithms from plausible-looking heuristics that fail in subtle cases.

Last updated