W07: The reach and limits of computational proof
On this page
- Prerequisites and observable goals
- The central question: which class of objects is being decided?
- A finite automaton carries only a finite summary
- Equivalence becomes reachability in a product graph
- A proof that finite states are insufficient for one language
- Why a universal halting decider leads to contradiction
- Reductions transfer a problem, not an adjective
- Independent practice
- Complete solutions: W07
- Retention and readiness
Prerequisites and observable goals#
C04–C08 and C15–C16: logic, graphs, automata, grammars, reductions, and complexity classes.
Construct a finite-model equivalence algorithm and its proof; distinguish nonregularity, undecidability, and intractability; use a reduction in the correct direction.
The central question: which class of objects is being decided?#
A program that checks every state of a finite model may prove a property of that model. It does not thereby decide the property for every unbounded program. A language that cannot be recognized by a finite automaton may still have a simple stack algorithm. A problem believed computationally difficult can still be decidable. These distinctions matter in compiler tooling, protocol verification, security review, and algorithm selection.
State the input class, acceptance condition, and resource measure before using a word such as “impossible.” Three claims are different: no machine of a specified restricted kind solves the task; no algorithm always decides the task for arbitrary inputs; and no known efficient algorithm solves the task under a specified complexity model. A finite counterexample can refute a universal claim; a million successful cases cannot establish an arbitrary universal statement without a covering argument.
A finite automaton carries only a finite summary#
A deterministic finite automaton (DFA) consists of a finite state set , finite alphabet , total transition function , start state , and accepting set . After a word , its current state summarizes all relevant history for future acceptance. Two prefixes ending in the same state cannot be distinguished by any common continuation.
For parity of the number of ones in a binary string, two states suffice: even and odd. A 0 leaves the state unchanged and a 1 toggles it. If the start and accepting state are even, the empty string is accepted. That last case must be tested; a word of length zero is not the same object as “no result found.”
Equivalence becomes reachability in a product graph#
Given DFAs and over the same alphabet, form states . Start at the pair of start states. A symbol advances both machines. A reachable pair where exactly one component accepts is a distinguishing state: the word used to reach it is accepted by exactly one automaton. If no such pair is reachable, they accept the same language.
The proof is induction on word length. The empty word leaves the start pair. Appending a symbol applies exactly the paired transition, so the product’s state is always the pair of individual states after that word. Every possible word corresponds to a path. Breadth-first search explores reachable pairs in nondecreasing path length, so the first acceptance mismatch gives a shortest distinguishing word. Exhausting the finite graph proves no word distinguishes them, not merely no short word in a sampled list.
If there are and states, at most pairs exist. With alphabet size , a direct BFS examines at most transitions. A shortest path to a mismatching reachable state need not repeat a product state, so its length is at most . This is a finite automaton result; a similar claim for arbitrary program states would lack the finite bound.
A proof that finite states are insufficient for one language#
Consider . Suppose some DFA with states recognizes it. While reading the first copies of in , the machine visits prefix states including the start. By the pigeonhole principle, two states coincide after and letters with . The segment of copies of forms a loop. Repeating that loop once leaves the machine in the same state before the remaining input, so it must also accept . The counts differ, contradicting the definition of . Therefore no DFA recognizes .
This does not prove that is undecidable. A stack machine can push for each , then pop for each , reject an after the phase or an unmatched pop, and accept exactly when the input ends with an empty stack. The grammar generates the same language. More memory changes what the model can express. The proof is a concrete pumping argument, not permission to “pump any chosen substring” without connecting it to repeated states.
Why a universal halting decider leads to contradiction#
Assume an algorithm always terminates and correctly decides whether program halts on input . Programs are encoded as finite strings, so one program can receive another’s encoding. Construct : ask ; if it predicts halting, loop forever; otherwise halt. Now run on its own encoding. If predicts that halts, its definition makes it loop. If predicts nonhalting, its definition makes it halt. Both predictions contradict correctness, so the assumed universal decider cannot exist.
The argument does not say we can never prove that a particular program terminates. The binary search variant in W02 and the forward-only bytecode verifier in GP1 provide such proofs within bounded or structured classes. A timeout does not decide the universal question: after the deadline an uncompleted execution might halt later or never halt. A tool may also conservatively answer “unknown.” That is not the always-correct yes/no decider assumed in the contradiction.
Reductions transfer a problem, not an adjective#
To show that solving would solve , construct a transformation such that exactly when . Then a hypothetical solver for applied to solves . To transfer undecidability from a known undecidable to , reduce to , not the reverse. A simple problem reducing to does not establish that is difficult.
For complexity reductions, also bound the transformation’s resources. Polynomial-time many-one reductions preserve a particular computational relationship. A decision problem is in NP when yes instances have polynomial-size certificates verifiable in polynomial time, under the standard model. NP does not mean “not polynomial.” Every problem in P is in NP. NP-hardness says every NP problem reduces to the target under the chosen reduction notion; NP-completeness adds that the target itself lies in NP. The general equality P=NP remains unresolved; using these distinctions does not assume an answer. [PNP]
A shortest-path certificate and a maximum-flow/minimum-cut certificate show how existence and optimality can have checkable evidence. Not every optimization task has a similarly simple known optimality certificate. When presenting a heuristic, separate “found a feasible result,” “proved the optimum,” and “measured useful performance on this distribution.”
Independent practice#
F foundation C standard course work T transfer S optional stretch L runnable lab or project. Attempt the complete set before opening its solutions.
Construct a complete binary DFA that accepts exactly strings with an even number of ones. Trace the empty word, 101, and 111. Explain which state property is the invariant.
Automaton A accepts even parity of ones; B accepts every binary string. Find a shortest distinguishing word. Explain why BFS on their product finds one, and give the general state/word-length bound for DFAs with states.
Prove that is not regular using repeated states. Then describe a terminating algorithm deciding it and explain why the two claims are compatible.
A report says, “We reduced sorting to our problem, therefore our problem is NP-hard. Our solver timed out, proving this instance has no solution.” Identify both invalid conclusions and give the type of evidence each stronger claim would require.
Implement distinguishing_word and accepts for the complete bounded DFA schema in integration_code/starters/dfa_compare.py. Validate states, alphabets, total transitions, start, and accepting states. Return a shortest witness string, including the empty string when appropriate, or None for equivalence. Test isomorphic machines and acceptance mismatches, and explain the exhaustive finite-model guarantee.
Optional small hints
For .02 the shortest witness need not contain both alphabet symbols. For .03 focus on the states reached before any is read. For .05 distinguish "" from None; a truthiness check alone loses that distinction.
Complete solutions: W07#
Compare the first step where your work differs. A corrected answer is not yet an independent success.
W07.01Show solution
The state records parity, not the whole prefix
Use states E and O, start E, accepting set , and transitions , , , . The invariant is that E means the processed prefix contains an even number of ones and O means an odd number. It holds for the empty prefix and each transition preserves it. The empty word is accepted, 101 ends E and is accepted, and 111 ends O and is rejected. This proves all strings by induction, not just the three traces.
Back to W07.01W07.02Show solution
Reach an acceptance mismatch
The empty word is accepted by both. Word 0 is also accepted by both; word 1 is rejected by A and accepted by B, so 1 is a shortest witness. The product-state induction proves that the paired acceptance flags represent the same consumed word. BFS first reaches a mismatching state at minimum path length. There are at most states, and a shortest witnessing path has no repeated state, giving length at most . If BFS exhausts all reachable pairs without a mismatch, every word ends with matching acceptance and the machines are equivalent.
Back to W07.02W07.03Show solution
A restricted model can fail while an algorithm exists
Assume a -state DFA recognizes the language. Among the prefix states after zero through letters of , two repeat at . Inserting the loop of additional ’s yields the same state before the remaining suffix, hence an accepted word with more ’s than ’s. Contradiction. A deciding algorithm scans left to right, counts the ’s, then decrements for each , rejecting wrong order or negative count and accepting at the end exactly when count is zero. It terminates after finitely many input characters. Its unbounded counter across arbitrary input lengths is not finite-state memory, so no contradiction follows.
Back to W07.03W07.04Show solution
An easy source and a timeout establish neither claim
Sorting has efficient algorithms; reducing it to another task does not show the target can express every NP problem. An NP-hardness proof needs a suitable reduction from a known NP-hard problem (or all NP problems through established transitivity), with a valid resource bound and equivalence of yes instances. A timeout establishes only that this run did not complete by the deadline. Proving infeasibility needs a valid mathematical argument, exhaustive coverage of a correctly bounded search space, or another sound certificate. Neither a slow run nor failure to find a witness establishes nonexistence. Also distinguish sorting’s function problem from the precise decision formulation used in a complexity claim.
Back to W07.04W07.05Show solution
A finite exhaustive proof connected to code
The reference checks that every state has a transition for every alphabet symbol. It stores visited state pairs and predecessor symbols, so reaching a mismatch reconstructs a shortest word. It checks the initial pair before expanding, preserving the empty-word case. The validation bounds keep the educational state space manageable; they are not a theorem that all protocol models fit those bounds.
"""W07: a complete DFA comparison, not an arbitrary program-equivalence solver."""
from collections import deque
def validate(machine,alphabet):
if type(machine) is not dict or set(machine)!={'states','start','accept','transition'}:
raise ValueError("wrong DFA schema")
n=machine['states']
if type(n) is not int or not 1<=n<=100 or type(machine['start']) is not int or not 0<=machine['start']<n:
raise ValueError("bounded state count and valid start required")
if any(type(q) is not int or not 0<=q<n for q in machine['accept']):raise ValueError("bad accepting state")
expected={(q,a) for q in range(n) for a in alphabet}
if set(machine['transition'])!=expected:raise ValueError("complete transition table required")
if any(type(q) is not int or not 0<=q<n for q in machine['transition'].values()):raise ValueError("bad target")
def distinguishing_word(left,right,alphabet=('a','b')):
alphabet=tuple(alphabet)
if not alphabet or len(set(alphabet))!=len(alphabet) or any(type(a) is not str or len(a)!=1 for a in alphabet):
raise ValueError("unique one-character alphabet symbols required")
validate(left,alphabet);validate(right,alphabet)
start=(left['start'],right['start'])
parent={start:None};todo=deque([start])
while todo:
pair=todo.popleft()
if (pair[0] in left['accept']) != (pair[1] in right['accept']):
symbols=[]
while parent[pair] is not None:
previous,symbol=parent[pair];symbols.append(symbol);pair=previous
return ''.join(reversed(symbols))
for symbol in alphabet:
nxt=(left['transition'][pair[0],symbol],right['transition'][pair[1],symbol])
if nxt not in parent:
parent[nxt]=pair,symbol;todo.append(nxt)
return None
def accepts(machine,word):
state=machine['start']
for symbol in word:state=machine['transition'][state,symbol]
return state in machine['accept']
if __name__=='__main__':
even={'states':2,'start':0,'accept':{0},
'transition':{(0,'a'):1,(1,'a'):0,(0,'b'):0,(1,'b'):1}}
everything={'states':1,'start':0,'accept':{0},'transition':{(0,'a'):0,(0,'b'):0}}
print(repr(distinguishing_word(even,everything)))Tests compare renamed equivalent machines, a one-symbol mismatch, an empty-word mismatch, and malformed transitions. The correctness argument covers every word for the supplied complete machines because it exhausts their finite reachable product, not because the tests enumerate a large prefix set. Extending this tool to nondeterministic automata, pushdown machines, or arbitrary programs requires a new representation, algorithm, complexity analysis, and claim boundary.
Back to W07.05Retention and readiness#
Explain nonregular, undecidable, and NP-hard using different examples. Draw the direction of a reduction before stating the conclusion. When a verification tool says “proved,” ask what model, assumptions, and state-space bound its proof concerns.