Skip to content
Problem Formulation

Problem Formulation

For decades, the rate-limiting step in computing was translating an idea into code. Large language models have collapsed that step: describe a program clearly and one appears in seconds. What did not collapse — what actually became the bottleneck — is producing the clear description. Problem formulation is the new decomposition: the front half of computational thinking, promoted from prelude to main event.

Why formulation now dominates

An LLM is an extraordinarily capable executor of stated intent and an unreliable guesser of unstated intent. Every ambiguity in your request is resolved by the model’s statistical priors — that is, by what people on the internet usually meant — rather than by what you meant. The result compiles, runs, and solves a problem adjacent to yours.

This is why prompt quality varies so wildly between users given identical tools. Research on prompting as an emerging skill consistently finds that effective prompts are exercises in classical CT: they decompose the task, abstract the relevant context, specify the output form, and define acceptance criteria. “Prompt engineering” is a misleading name for what is mostly specification thinking.

Specification thinking

A specification is a description of a problem complete enough that a competent stranger — human or model — could solve it without asking you anything. Writing one forces the discoveries that vague requests defer:

  • Inputs — what exactly comes in, in what format, with what nasty edge cases (empty, huge, malformed, Unicode, February 29)?
  • Outputs — what exactly comes out, and what does the output look like for the edge cases?
  • Constraints — performance bounds, dependencies allowed, style rules, things that must not change.
  • Acceptance criteria — concrete examples of input → expected output. If you cannot produce three such examples, you do not yet understand your own problem; no model can fix that for you.
  • Context — the surrounding system, the audience, the purpose. “Why” is context that lets an executor make the thousand micro-decisions you did not specify, in your favor.
The old joke was that programming is the art of discovering what you actually wanted. Specification thinking front-loads that discovery. The paradox of the AI era: to get the machine to write the code, you must do the thinking that was always the hard part of writing the code.

Decomposition, reborn as prompt design

The classical pillar of decomposition maps one-to-one onto working with AI:

One task per request. “Build me a dashboard” fails for the same reason it fails as a project plan: it is forty tasks in a trench coat. Decompose first — schema, queries, chart components, auth — then delegate pieces. Each piece gets a scoped prompt with its own acceptance criteria, and each response gets verified before the next piece builds on it. This is exactly high-cohesion, low-coupling decomposition, with the model as the implementing team.

Sequence by dependency. Ask for the data model before the API before the UI, feeding verified earlier outputs into later prompts as context. A conversation with an LLM is a data-flow decomposition where you are the pipeline.

Iterate as designed refinement, not slot-machine pulls. When output misses, diagnose which part of the specification was missing or wrong, and fix the spec. Re-rolling the same vague prompt and hoping is the shotgun debugging of the AI era — occasionally lucky, never informative.

A worked contrast

Weak formulation:

Write a function to clean up user data.

The model must guess the language, the shape of the data, what “clean” means, and what to do with rows that resist cleaning. Whatever comes back, the real spec will now be negotiated through a frustrating series of “no, not like that” turns — discovery at the most expensive point.

Strong formulation:

Write a Python 3.11 function normalize_contacts(rows: list[dict]) -> tuple[list[dict], list[dict]] for a CRM import.

Each dict has keys name, email, phone (all strings, possibly empty or None).

  • Trim whitespace; lowercase emails; strip non-digits from phone, then format 10-digit US numbers as 555-123-4567.
  • A row is valid only if email matches a standard pattern OR phone has exactly 10 digits.
  • Return (valid_rows, rejected_rows); never raise on bad data. No dependencies outside the standard library.

Examples: {“name”:" Ann “,“email”:“ANN@X.COM”,“phone”:”"} → valid, email “ann@x.com”. {“name”:“Bo”,“email”:“bad”,“phone”:“12345”} → rejected.

Every sentence is a decision the model no longer has to guess. Note what the strong version required from you: data-shape analysis, edge-case enumeration, a validity policy (an actual business decision), and testable examples. That is computational thinking; the prompt is merely its transcript.

Formulation beyond prompts

The same skill scales up. Writing a design doc an AI agent can execute overnight, defining evaluation datasets for an ML system, framing an A/B test, scoping a research question — all are problem formulation. Organizations are relearning an old truth at new speed: the quality ceiling of any delegated work, to humans or machines, is set by the quality of the problem statement. As generation gets cheaper, that ceiling is the whole game.

Two follow-on questions complete the loop: how do you check what comes back (Verification Thinking), and how do you decide what to delegate at all (Human–AI Division of Labor)?

References