containsGAGA(inString): returns “yes” if input contains “GAGA”, else “no”
yes(inString): always returns “yes” regardless of input or input characteristics
longerThan1K(inString): returns “yes” if input length > 1000, else “no”
Are these programs computable? Yes!
Are these programs decidable? Yes!
Are these programs tractable? Yes!
But, wait, what about yesOnString? Woah, hold on!
Or, what about crashOnString? Woah, hold on!
Hypothetical yesOnString
Definition: yesOnString(P, I) returns:
“yes” if P is a valid Python program, P(I) is defined, and P(I)=“yes”
“no” otherwise (invalid program, undefined output, or non-“yes”)
Question it answers: Does program P return “yes” on input string I?
Important note: We don’t provide the source code for yesOnString
Reason: We will prove it’s impossible to write such a program!
The yesOnString program would solve a fundamental question about program behavior. Yet, as we’ll see, asking this question leads to logical contradictions that make the program impossible!
Approximates yesOnString for known programs and inputs
The yesOnSelf simplification
Definition: yesOnSelf(P) returns:
"yes" if P is a valid Python program and P(P) = “yes”
"no" otherwise
Relationship to yesOnString:
yesOnSelf(P) = yesOnString(P, P)
Asks: “Does program P return ‘yes’ when given itself as input?”
Why this matters for proofgrammers:
Simpler to analyze than the two-parameter version
Self-application creates the conditions for contradiction
Examples with yesOnSelf
yesOnSelf(“not a program”) returns “no”
yesOnSelf(“letters and numbers 1431”) returns “no”
yesOnSelf(“containsGAGA.py”) returns “yes”
yesOnSelf(“longerThan1K.py”) returns “no”
yesOnSelf(“yesOnSelf.py”) returns “yes” or “no” or \(...\)?
Get Ready: What is the behavior of the yesOnSelf program when it is run on itself? We are going to introduce a “troublemaker” program that will create a contradiction and shed light on this issue!
Using hypothetical yesOnSelf
# hypothetical behavior of yesOnSelfdef hypothetical_yesOnSelf(P: str) ->str:"""HYPOTHETICAL: Check if program P returns 'yes' on itself."""if P =="yes.py":return"yes"elif P =="containsGAGA.py":return"yes"else:return"no"# show examplestest_programs = ["yes.py", "containsGAGA.py", "longerThan1K.py"]print("Hypothetical yesOnSelf behavior:")for prog in test_programs: result = hypothetical_yesOnSelf(prog)print(f"yesOnSelf('{prog}') = {result}")
# here's where the contradiction emerges!def notYesOnSelf(P: str) ->str:"""Return the opposite of what yesOnSelf would return.""" result = hypothetical_yesOnSelf(P)return"no"if result =="yes"else"yes"# test on some programstest_cases = ["yes.py", "containsGAGA.py"]for prog in test_cases: yes_result = hypothetical_yesOnSelf(prog) not_result = notYesOnSelf(prog) print(f"yesOnSelf('{prog}') = {yes_result}")print(f"notYesOnSelf('{prog}') = {not_result}")
yesOnSelf('yes.py') = yes
notYesOnSelf('yes.py') = no
yesOnSelf('containsGAGA.py') = yes
notYesOnSelf('containsGAGA.py') = no
Running notYesOnSelf
notYesOnSelf(“not a program”) returns “yes”
notYesOnSelf(“letters and numbers 1431”) returns “yes”
Amazing: Since no output is correct when notYesOnSelf is run on itself, we have discovered that yesOnSelf cannot exist! Let’s explore these scenarios in greater detail to build understanding.
Revealing the contradiction
Consider: What happens when we run notYesOnSelf("notYesOnSelf.py")?
Case 1: Suppose it returns "yes"
If notYesOnSelf returns “yes” on itself, then by definition, notYesOnSelf should return “no” (opposite of what it actually returned). Contradiction!
Case 2: Suppose it returns "no"
If notYesOnSelf returns “no” on itself, then by definition, notYesOnSelf should return “yes” (opposite of what it actually returned). Contradiction!
No output is correct! Whether notYesOnSelf returns “yes” or “no” on itself, it contradicts its own definition. Therefore, notYesOnSelf cannot exist and is a logical impossibility!
Since assuming yesOnString exists leads to contradiction
This means that yesOnString cannot logically exist
Practical implications
No perfect bug finder
Cannot create a program that finds all bugs in all programs
Static analysis tools work on many cases but not universally
Software companies invest heavily in partial solutions
No universal crash detector
Cannot predict crashes for all possible program inputs
Testing and runtime monitoring remain essential
Impossibility doesn’t mean “useless” — it means “not universal”!
Fundamental computational limits
Some problems are unsolvable even with infinite resources
Proofgrammers must understand these boundaries
Theory versus practice
What is impossible
Universal bug detection for all programs
Perfect crash prediction for all inputs
Determining if any arbitrary program halts
What is possible
Bug detection for many specific program classes
Crash prediction for many common scenarios
Static analysis tools that work on practical codebases
Proofgrammer perspective
Impossibility results guide what tools to build
Focus effort on solvable sub-problems
Understand fundamental computational boundaries
Why impossibility matters
Scientific understanding:
Reveals fundamental limits of computation itself
Not about hardware limitations or current technology
Shows logical boundaries that no algorithm can cross
Practical guidance:
Helps avoid impossible engineering goals
Guides research toward productive directions
Informs realistic expectations for automated tools
Understanding impossibility is as important as understanding possibility. It prevents wasted effort on unsolvable problems and focuses innovation on achievable goals.
Key takeaways
Proof by contradiction: Natural technique for impossibility results