Introduction
One of my favorites experiences of trimming unfruitful work directions thanks to theoretical results happened when I discovered this 2001 article from Jeroen Voeten: On the fundamental limitations of transformational design.
For context, when I discovered this article (around 2010), I was working on delivering an “optimizing compiler” for a novel microprocessor architecture. Some more senior researcher than me had been floating the idea that compiler technology was underrated, because (paraphrasing) “with a sufficiently advanced compiler, we could take an arbitrary human specification and produce an optimal implementation given a target architecture”. With my past experience building compilers, I found this claim fantastical—a case of magical thinking, really—but I was not able to fully explain why. Reading Jeroen Voeten’s article, soon afterwards, put a rest to this argument: no, such compilers can’t be made. Or we couldn’t call them “compilers.”
Jeroen Voeten’s original argument was motivated by research in microchip specification systems (e.g. VHDL). However, as we see below, it also applies to any computing system where we use algorithms to transform one system into another (e.g. program transformation, software refactoring, etc.) and desire confidence that the transformation is semantics-preserving, e.g. it does not introduce new problems that were not there originally.
How this relates to generative AI: yesterday, I offered to model the combination of a human operator + AI programming agent as a computing system, which we called “HACS”, and explore if results from computing theory could apply. Today, we explore how yesterday’s argument expands when we focus on the findings from Jeroen Voeten’s article, to explore the following question: in which areas can we expect theoretical limits to the ability of AI programming workflows to transform software?
Remember, again, that I am not a computer theoretist. While I am familiar with the theory, I am unable to formalize the ideas that follow as a professional theoretist would. This is an exploration.
I. The core insight from Jeroen Voeten (2001)
Setup:
- Design space \(\mathcal{D}\): all syntactically valid programs/designs
- Semantic equivalence \(\equiv\): programs with the same meaning
- Transformation system \(\mathcal{T}\): a set of transformations \(t: \mathcal{D} \rightarrow \mathcal{D}\)
- Correctness: transformations preserve equivalence: \(d \equiv t(d)\)
The partition argument: if each transformation \(t \in \mathcal{T}\) is:
- Semantics-preserving: \(d \equiv t(d)\)
- Invertible: there exists \(t^{-1}\) such that \(t^{-1}(t(d)) = d\)
Then \(\mathcal{T}\) generates a group action on \(\mathcal{D}\), and the orbits of this action partition \(\mathcal{D}\) into disjoint equivalence classes under reachability.
SEMANTIC EQUIVALENCE CLASS [d]≡ ┌──────────────────────────────────────────────────┐ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Subspace 1 │ │ Subspace 2 │ │ │ │ (orbit │ │ (orbit │ │ │ │ under T) │ │ under T) │ │ │ │ ●──● │ │ ●──●──● │ │ │ │ / \ │ │ │ │ │ │ │ │ ● ● │ │ ●─────● │ │ │ └─────────────┘ └─────────────┘ │ │ ╳ UNREACHABLE ╳ │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Subspace 3 │ ... │ Subspace ∞ │ │ │ │ ●──●──● │ │ ●──● │ │ │ └─────────────┘ └─────────────┘ │ │ │ └──────────────────────────────────────────────────┘ All designs in the big box are SEMANTICALLY EQUIVALENT. But you can only REACH designs within your starting subspace.
The fundamental result: your starting point determines your reachable solutions.
Even if there exists a “better” implementation (faster, smaller, cleaner) that is semantically equivalent to your specification, it may be provably unreachable through any sequence of correctness-preserving transformations.
II. Mapping to HACS (Coding Agents)
The agent as a transformation system
A coding agent applies transformations to a codebase:
| Jeroen Voeten’s Framework | HACS Coding Agent |
|---|---|
| Design space \(\mathcal{D}\) | All possible workspace states |
| Transformation \(t\) | One agent action (edit, refactor, add file) |
| Semantic equivalence \(\equiv\) | Produces same behavior |
| Transformation system \(\mathcal{T}\) | Set of actions the agent can take |
It’s worth looking at the semantic equivalence closely. If we are satisfied when a change by an AI agent merely “passes all tests”, the verification is limited to the test cases, which covers a finite set of inputs. In that case, the results from Jeroen Voeten do not apply because complete transformation systems are possible when we choose a finite domain equivalence.
We can easily argue that practitioners desire stronger guarantees than what their current test suite covers. One argument is the observation of how frequently the user adds more tests after discovering that a change was, in fact, incorrect, and the test coverage was incomplete regarding the user’s intentions. Another argument is the observation of how the industry is still pushing for human reviews, with the understanding that humans aspire to higher confidence about correctness beyond finite test coverage.
Therefore, the remainder of the text below assumes that we are interested in a semantic equivalence that goes beyond the finite domain of pre-existing test suites. That is the area where the article from Jeroen Voeten can help us.
Agent transformations are not invertible, therefore more limits
Voeten shows that even with a group structure (invertible transformations), you get infinitely many unreachable subspaces.
However, coding agents may not be able to invert actions, because:
- The inverse requires knowing the previous state
- The previous state may have fallen out of the context window
- Therefore the agent has “forgotten” how to undo
This means the agent’s effective transformation system is actually a monoid (or worse, just a semigroup), not a group. The algebraic structure is weaker. So we have:
- Not all transformations are invertible
- So we don’t even get clean partitions, we get directed reachability
- Some states are “sinks” you can reach but not escape
- The reachability relation is a preorder, not an equivalence
NON-INVERTIBLE TRANSFORMATION SYSTEM
●──→──●──→──●
↘ ↓
●──→──●──→──● (sink: can enter, can't leave)
↗
●──→──●──→──●
Arrows show reachability. No inverse arrows means no escape.
This doesn’t weaken the fundamental limitation; if anything, it strengthens it. Not only are some equivalent programs unreachable, but the agent can also wander into “sink” regions from which better solutions become unreachable even if they weren’t originally.
For the remainder of this essay, when we refer to “partitions” or “subspaces,” we mean this informally: regions of the design space that are mutually unreachable. The formal object in the HACS case is more complex than Voeten’s clean partitions, but the practical implication is the same or worse.
III. The “over-specification” problem for agents
Key phrase from the original article: “each specification is an over-specification.”
For HACS, this translates to the following.
The prompt is an over-specification
When a human gives a task like: “Refactor this codebase to be more maintainable”
The starting codebase implicitly constrains which “maintainable” states are reachable. According to Voeten’s reasoning, there may be a beautiful architecture that is:
- Semantically equivalent
- Objectively better by all metrics
- Yet provably unreachable from the starting point via the agent’s transformations
Note that the stochastic nature of the LLM does not improve the situation: while randomization could allow the agent to reach separate partitions (by “jumping” into them randomly), the transformation would not then be provably semantically equivalent.
The initial commit determines the ceiling
This suggests a principle: the quality of outcomes is bounded by the starting point, not just the agent’s capability.
An arbitrarily powerful agent, given a sufficiently pathological starting codebase, may be unable to reach a good solution through incremental transformation.
IV. The Halting Problem connection
This is the connection to our earlier halting problem discussion.
The reachability problem
Question: Given designs \(d_1, d_2 \in \mathcal{D}\), is \(d_2\) reachable from \(d_1\) via transformations in \(\mathcal{T}\)?
Theorem from the article (paraphrasing): For sufficiently expressive design languages, this is undecidable.
Proof sketch:
- Semantic equivalence is not semi-decidable for Turing-complete languages: you cannot algorithmically determine whether two programs in a Turing-complete language compute the same function.
- Why? If you could semi-decide “does program w compute the same function as program v?”, you could solve the halting problem. (The proof constructs a program whose equivalence to v depends on whether a specific TM halts.)
- The article then says: if semantic equivalence isn’t semi-decidable, no complete transformation system can exist.
- Why? If a complete transformation system existed, you could enumerate all reachable programs from v. Since “reachable” = “equivalent” (by completeness), you’d have a semi-decision procedure for equivalence. Contradiction.
I learned this from Jeroen Voeten, but it’s really the core idea from Rice’s theorem: any non-trivial semantic property of programs in a Turing-complete language is undecidable.
HACS interpretation
The agent cannot, in general, determine:
- Whether a desired end state is reachable
- How many steps it would take to reach it
- Whether it’s “stuck” in a subspace that excludes the goal
This is a theoretical limit, not a limitation of current LLMs.
V. Escape hatches: how to break out of subspaces
If Voeten’s result is so limiting, how do we ever make progress? There are several “escape hatches”.
1. Non-semantics-preserving transformations
If we allow transformations that temporarily break correctness, we can escape subspaces:
Subspace A ─(break semantics)-> Invalid state ─(fix)-> Subspace B
HACS interpretation: “I need to break the build temporarily to do this major refactor.”
This is why large refactorings often require:
- Accepting temporary breakage
- Multiple commits that don’t individually pass tests
- Human judgment about when breakage is acceptable
2. The human oracle as subspace bridge
The human can provide information that lets the agent “jump” between subspaces:
- “Here’s a completely different approach, start from this instead”
- “Delete everything and use this library”
- “The real requirement is actually X, not Y”
When we do so, we step out of semantic-preserving transformations: we’re introducing an “oracle query” that returns a new starting point. The oracle (the human in this case) bears the responsibility of asserting the adequacy of the new starting point.
If we do so however, the human becomes load-bearing in our confidence that the transformations are correct. This can teach us something about our ambitions to reduce the human participation where AI agents are involved.
3. Expanding the transformation set
Adding new transformations can merge previously separate subspaces:
- Before: Subspaces \(\{A, B, C, D, \ldots\}\)
- Add transformation \(t_{\text{new}}\)
- After: Subspaces \(\{A\cup B, C, D, \ldots\}\) (A and B merge)
HACS interpretation: New tools, libraries, or capabilities can make previously unreachable solutions reachable.
This is why agents with more tools are more capable: they have access to more transformations.
4. Restricting the design language
The article notes that restricted languages can have complete transformation systems.
Example: For regular expressions, there exist complete axiomatizations; any equivalent regex can be reached from any other through algebraic transformations.
HACS interpretation: Working in constrained domains (DSLs, configuration languages, structured data) may allow more complete exploration than working in general-purpose languages.
VI. Relating to complexity classes
Let’s try to revisit our earlier HACS complexity hierarchy.
Transformation complexity
Define \(T(d_1, d_2)\) = minimum number of transformations to reach \(d_2\) from \(d_1\) (or \(\infty\) if unreachable).
| Complexity Class | Definition |
|---|---|
| \(\text{REACH}_k\) | Pairs \((d_1, d_2)\) where \(T(d_1, d_2) \leq k\) |
| \(\text{REACH}_{\text{poly}}\) | Pairs where \(T(d_1, d_2) \leq p(|d_1| + |d_2|)\) for some polynomial \(p\) |
| \(\text{REACH}_{\text{finite}}\) | Pairs where \(T(d_1, d_2) < \infty\) |
| \(\text{UNREACH}\) | Pairs where \(d_2\) is unreachable from \(d_1\) |
Voeten’s Result, Restated: for expressive languages, \(|\text{UNREACH}| = \infty\)
There are infinitely many pairs of semantically equivalent designs that are mutually unreachable.
HACS Implication: even with unlimited time and a perfect agent, some problems are unsolvable from some starting points
\(\exists\ d_{\text{start}}, d_{\text{goal}}: d_{\text{start}} \equiv d_{\text{goal}} \land (d_{\text{start}}, d_{\text{goal}}) \in \text{UNREACH}\)
VII. Practical implications
1. The value of “clean slate” rewrites
Sometimes the only way to reach a better subspace is to discard the current design entirely.
HACS implication: An agent should be able to recognize when it’s trapped in a subspace and recommend a clean-slate approach rather than endless incremental attempts.
2. Specification language matters
The language/format of the initial specification determines which subspace you start in.
- Natural language spec → ambiguous, could start in any of several subspaces
- Formal spec (types, contracts, tests) → more constrained starting point
- Executable prototype → very specific subspace
HACS implication: The form of the prompt, not just its content, shapes what outcomes are reachable.
3. Transformation libraries are load-bearing
The completeness of the transformation system determines how fragmented the design space is. More transformations result in larger reachable subspaces.
HACS implication: Investment in diverse, composable code transformation capabilities may have superlinear returns: each new transformation potentially bridges multiple subspaces.
VIII. Prompt interpretation as implicit specification
Question: Is the agent’s “understanding” a form of implicit specification?
When an agent interprets a prompt with specific semantics (e.g. with references to working code), it collapses ambiguity into a specific understanding. That understanding may implicitly place the agent in a particular subspace before any new code is written.
If true, then:
- Chain-of-thought reasoning is “early specification”
- Different reasoning traces result in different subspaces
- “Prompt engineering” is partly subspace selection
This suggests that how the agent interprets the prompt (not just what code it writes) is subject to the same partition constraints.
IX. Open questions
- Is the partition structure empirically observable? Can we find real examples of codebases where a “better” implementation is provably unreachable? I suspect yes, but I don’t have a concrete case.
- How fragmented is the space in practice? The original article proves infinite partitions exist, but maybe most practical cases are in “well-connected” regions?
- Is finite-domain equivalence a useful approximation? The original article shows that restricting to finite input domains makes equivalence decidable. Does this suggest a practical middle ground, i.e. transformations that preserve behavior on “sufficiently large” test sets?
References
- J.P.M. Voeten, On the fundamental limitations of transformational design, 2001. ACM TDAES, Vol 6(4), pp. 533-552. DOI 10.1145/502175.502181
- Wikipedia, Rice’s theorem
Comments
Interested to discuss? Leave your comments below.