A Proof that there's No Constructive Proof of the Intermediate Value Theorem
10 Jun 2025 - Tags: topos-theory , sage
The other day my friend Lucas Salim was asking me some questions about categorical logic and constructive math, and he mentioned he’d never seen a proof that there’s no constructive proof of the intermediate value theorem before. I showed him the usual counterexample, and since my recent blog post about choice was so quick to write I decided to quickly write up a post about this too, since I remember being confused by it back when I was first learning it.
The key fact is Soundness and Completeness of the topos semantics of constructive logic. This says that there is a way of interpreting the usual syntax of mathematics into a topos in such a way that
-
(Soundness) If you can constructively prove a statement, then its interpretation in every topos is true
-
(Completeness) If a statement is interpreted as true in every (elementary1) topos, then there must exist a constructive proof
For a proof, see Chapter II of Lambek and Scott’s Introduction to Higher Order Categorical Logic or Section D4.3 of The Elephant.
This means that as long as we’re careful to avoid choice and excluded middle, anything we prove will be true when interpreted in any topos we like! Then there’s a mechanical procedure that lets us convert this interpretation into a corresponding statement in the “real world2”, and this gives us lots of “theorems for free” for each individual constructive theorem! A nice case study is given by the Weierstrass Approximation Theorem, which I gave a talk on years ago3. Since this theorem is constructively provable4…
- by interpreting it in the effective topos we learn there’s a
computer program
which takes as input a function 5 and an and outputs the coefficients of a polynomial approximating . - by interpreting it in a sheaf topos
we learn that for any continuous family of functions , there’s locally6 a polynomial whose coefficients are continuous functions of which approximates each - etc.
If you’re interested in learning how to externalize a statement in a topos to a statement about the real world, I highly recommend Ingo Blechschmidt’s excellent paper Exploring mathematical objects from custom-tailored mathematical universes which gives a high level overview of the topic, while still giving enough details to let you externalize a few statements of your own!
But where were we? The usual proofs of the intermediate value theorem aren’t constructive. See, for instance, Bauer’s Five Stages of Accepting Constructive Mathematics or Section 1 of Taylor’s A Lambda Calculus for Real Analysis for a discussion of how some common proofs fail (as well as great lists of constructively provable alternatives). Since the usual proofs seem to fail, we might guess that IVT is not provable constructively… but how could we prove this?
Say, towards a contradiction, that there were a constructive proof of the intermediate value theorem. Then it would be true in every topos, and thus its various externalizations would all be true in the real world. So to show that there isn’t a constructive proof, all we have to do is find a topos which doesn’t think it’s true!
Following many who came before me7, we’re going to use the topos of
sheaves on
In full symbolic glory, the IVT says
So now using the forcing language for
We cash out the universal quantifiers to get
“for every open
Next, cashing out the implication gives
“for every open
Finally, cashing out the existential quantifer and the stuff inside it we get the external statement:
The IVT is true inside
For every open
for every continuous
so that for all
there is an open cover
for all
What a mouthful!
Of course, we’re trying to prove this fails, so all we have to do is
find an open set
Then we see that, indeed,
The idea is that no matter how hard we try,
xxxxxxxxxx
x,t = var('x,t')
f(t,x) = max_symbolic(min_symbolic(t+x+1, t), t+x-1)
def mkFrame(t):
graph = plot(lambda x: f(t,x), (x,-2,2), ymin=-2, ymax=2)
zero = point((1-t if t<0 else -1-t, 0), size=40, color="orange")
txt = text("t={}".format(t), (-1.5,1.5))
return graph+zero+txt
frames = [mkFrame(t/10) for t in ([-5..5] + [-s for s in [-4..4]])]
a = animate(frames)
a.show()
You can see that when
Indeed, if we plot
xxxxxxxxxx
x,t = var('x,t')
f(t,x) = max_symbolic(min_symbolic(t+x+1, t), t+x-1)
p = implicit_plot(f(t,x), (t,-1,1), (x,-2,2))
p.axes_labels(['$t$', '$x$'])
p.show()
and it’s obvious that this is not the graph of a continuous function in any
neighborhood of
As long as we’re showing pretty graphics, you can also visualize this whole
function
So where did we start, and where did we end? If the IVT were constructively
provable, it would be true inside
Buuuuut, all is not lost! Usually classical theorems do have constructive analogues, either by adding new assumptions, weakening the conclusion, or by finding a different statement of the theorem that’s more positive. Andrej Bauer’s paper Five Stages of Accepting Constructive Mathematics lists many possibilities.
For instance, one way to weaken the conclusion is to prove that for
any
xxxxxxxxxx
x,t = var('x,t')
f(t,x) = max_symbolic(min_symbolic(t+x+1, t), t+x-1)
p = region_plot(abs(f(t,x)) <= 0.1, (t,-1,1), (x,-2,2))
p.axes_labels(['$t$', '$x$'])
p.show()
and it’s easy to fit the graph of a continuous selection function
Another approach is to recognize that the problem comes from
There’s yet another version, coming from Abstract Stone Duality,
where we say that whenever
Ok, thanks for reading, all! It’s nice to get a few quick posts up while I’m working on some longer stuff. I’m still thinking a lot about a cool circle of ideas involving Fukaya Categories, Skein Theory and T(Q)FTs, and Hall Algebras, and I’m slowly making progress on writing posts about all these fun things.
Now, though, I have to go run a review session for a calculus class, haha. I’ll try to resist telling them about the fascinating subtleties that show up when you try to do everything constructively.
Stay safe, and we’ll talk soon 💖
-
Usually on this blog when I talk about topoi I mean grothendieck topoi, but for this completeness result we really do need to allow more general elementary topoi with NNO. Indeed there are statements true in all grothendieck topoi that are not constructively provable (since they fail in some elementary topos). See here for a partial list.
I would actually love to know if there’s a reference for what one has to add to IHOL to get something sound and complete for grothendieck topoi… I spent some time looking, but the only thing I found was Topological Completeness for Higher-Order Logic by Awodey and Butz, but it seems like they use
in place of , so this isn’t the usual interpretation of logic in a grothendieck topos (which is also where the classical completeness comes from). ↩ -
Maybe “base topos” would be less philosophically charged ↩
-
I was really fumbling around with topos theory back then, haha. I’m much more confident now, and in the last few years I’ve just worked through a lot more examples and done more computations and read more papers and generally just learned a lot. Rereading that post was surprisingly… nostalgic isn’t the right word… but it’s fun to see how much I’ve grown! ↩
-
The usual proof with bernstein polynomials works if we’re careful to check some constructively relevant details. I’ll copy it here in case the wikipedia article changes someday:
Fix
.We write
, and note that:These are all provable by just expanding the left hand side, which is constructive.
We also fix a
so that whenever we have . This is because, constructively, every continuous function on a compact sublocale of is uniformly continuous. Note that here we crucially need to be working with locales! (see, eg, Thm 10.7 in Taylor’s A Lambda Calculus for Real Analysis)Lastly, we fix
an upper bound for . This is possible since is compact, overt, and inhabited (see Rmk 10.4 in Bauer and Taylor’s The Dedekind Reals in Abstract Stone Duality) thus the continuous admits a maximum (Thm 12.9 in A Lambda Calculus for Real Analysis).Now let
. We compute:In step (a) we use (1), and in step (b) we use the fact that
is constructively true (since the intervals overlap we don’t need excluded middle here!)But we can bound the first sum by noticing in this region
so that (using (1) again)And since
, we compute:In step (c) we use
to say that , so that we can multiply through by it and make our sum bigger. In step (d) we use (2), and at the end we use the fact that on .Now since
is constructively archimedian (Defn. 1.1 in The Dedekind Reals in Abstract Stone Duality) we see .Since these bounds were uniform in
, we learn thatas desired. ↩
-
A real number
in this topos is a program that eats a natural number and outputs a rational number . We think about this as a sequence of rational approximations converging to some real number . So a function in this topos is a program that takes as input a program (outputting rational approximations between and ) and outputs a new program which outputs rational approximations. ↩ -
Because our statement of Weierstrass
includes an existential quantifier there’s no way to get around the fact that the we build is only defined locally on an open cover.If you were more careful and gave a type theoretic proof that
then you could take to be a single polynomial defined on the whole of … I haven’t thought very hard about how possible this is (mainly because I haven’t spent much time thinking about what theorems about locales are provable in type theory), but I’m sure a talented undergraduate could figure it out. ↩ -
The earliest version of this example which I’ve seen comes from Stout’s Topological Properties of the Real Numbers Object in a Topos back in 1976. I think basically every other paper I’ve cited in this post gives some version of this example too, so it’s very well trodden ground! ↩