I needed the following lemma from general topology (see e.g., Kuratowski, Introduction to Set Theory and Topology, Chap. XVI, §3, Theorem 4): if X is connected, A⊆X is connected, C is a connected component of X∖A, then X∖C is connected. I wrote a ≈150lines proof of this (this is AxiomC3_general in this code).
Is this lemma actually somewhere in mathlib, to avoid me proving it? Should it? It is important enough that it is one of the four properties of connected sets retained in this axiomatisation of the notion (property (iv) is equivalent to this, cf. top of page 4).
Thanks to everybody! And I'm always happy to hear about ways to write my proofs in a more canonical/idiomatic way :-)
Béranger
Do you know about grind? You are doing a fair number of things manually that grind can help with, e.g. your wlog statements and some intermediate statement like MUNVdisj are handled by a single call to grind
Small style comments, instead of by apply I'd just give a term, e.g. have CinXmA : C ⊆ X \ A := connectedComponentIn_subset _ _ have yinC : y ∈ C := mem_connectedComponentIn ynotinA
Use exact instead of apply when it closes the goal
There is something called dot notaiton, instead of IsOpen.union Mopen Uopen you can make it shorter by writing Mopen.union Uopen since Mopen is of type IsOpen.
Instead of a series of applys/intros, you can often merge these into a single refine statement. Especially as a beginner I found these refines in mathlib a bit hard to read, but once you have done some golfing of your own proofs and combining consecutive applys intro refines, you will find them more concise and therefore readable
I have not tried to golf the first proof much, and I could probably go further with the second proof but I think this is enough to show you some new ideas
importMathlib.Topology.Connected.BasicimportMathlib.Data.Set.BasicopenSet--- Béranger Seguin--- Lean 4.25 (2025-11-30, updated 2025-12-07)--- Formalization of results from "Flimsy Spaces" (arXiv:2511.17745)universeuvariable{α:Typeu}[TopologicalSpaceα]theoremConnectedInSeparated{AUV:Setα}(connA:IsPreconnectedA)(Uopen:IsOpenU)(Vopen:IsOpenV)(UVdisj:A∩(U∩V)=∅)(UVcover:A⊆U∪V):A⊆U∨A⊆V:=byby_contrahapplynonempty_iff_ne_empty.1_UVdisjapplyconnAUVUopenVopenUVcoverall_goalsby_contradisjall_goalsapplyhon_goal1=>righton_goal2=>leftall_goalsintroahaall_goalshavenotin:=eq_empty_iff_forall_notMem.1(not_nonempty_iff_eq_empty.1disj)aall_goalsgrindtheoremAxiomC3_general--- Kuratowski (Introduction to Set Theory and Topology), Chap. XVI, §3, Theorem 4{XA:Setα}(connX:IsPreconnectedX)(connA:IsPreconnectedA)(AinX:A⊆X)(y:α)(ynotinA:y∈X\A):IsPreconnected(X\(connectedComponentIn(X\A)y)):=bysetC:=(connectedComponentIn(X\A)y)--- Write X \ C = (U ∪ V) ∩ (X \ C) for two opens U, V meeting (X \ C)introUVUopenVopenUVcoverUnonemptyVnonempty--- Assume by contradiction that U ∩ V ∩ (X \ C) = ∅by_contra!UVdisjhaveCinXmA:C⊆X\A:=connectedComponentIn_subset__--- A is connected and ⊆ U ∪ V, so is contained in either U or VhaveAUVdisj:A∩(U∩V)=∅:=bygrindhaveAinUorV:=ConnectedInSeparatedconnAUopenVopenAUVdisj(subset_trans(bygrind)UVcover)--- Without loss of generality A ⊆ UwlogAinU:A⊆UgeneralizingUV·grindhaveyinC:y∈C:=mem_connectedComponentInynotinA--- If we show that C ∪ (V ∩ X) is connected, then we are done:--- Indeed: by maximality of C, this implies V∩X⊆C, i.e., V∩(X\C) = ∅sufficesconnCV:IsPreconnected(C∪(V∩X))byrefinenonempty_iff_ne_empty.mpVnonempty<|eq_empty_iff_forall_notMem.mpr(funx⟨⟨inX,notinC⟩,inV⟩↦notinC?_)refinemem_of_subset_of_mem(s₁:=C∪V∩X)?_(Or.inr⟨inV,inX⟩)applyIsPreconnected.subset_connectedComponentInconnCV(Or.inlyinC)simp[CinXmA]introv⟨inV,inX⟩grind[eq_empty_iff_forall_notMem.1AUVdisjv]--- To show that C ∪ (V ∩ X) is connected, we assume that it is covered by two opens M and N--- which meet it and are disjoint within itintroMNMopenNopenMNcoverMnonemptyNnonemptyby_contra!MNdisj--- C connected ⊆ M ∪ N so C is contained in eitherhaveCinMorN:C⊆M∨C⊆N:=byapplyConnectedInSeparated(isPreconnected_connectedComponentIn)MopenNopen<;>grind--- Without loss of generality, C ⊆ M and then C ∩ N = ∅wlogCinM:C⊆MgeneralizingMN·grindhaveCNdisj:C∩N=∅:=bygrindsufficesCVXNdisj:(C∪(V∩X))∩N=∅bygrind[nonempty_iff_ne_empty]simp[union_inter_distrib_right,CNdisj]haveMUNVcover:X⊆(M∪U)∪(N∩V):=byintroxinXby_casesinM:x∈M·simp[inM]·haveinUV:x∈U∪V:=bygrindrcasesinUVwithinU|inV·exactOr.inl(Or.inrinU)·have:=MNcover(Or.inr⟨inV,inX⟩)grindhaveXinMUorNV:X⊆M∪U∨X⊆N∩V:=ConnectedInSeparatedconnX(Mopen.unionUopen)(Nopen.interVopen)(bygrind)MUNVcoverhaveMUXnonempty:(M∪U)∩X≠∅:=nonempty_iff_ne_empty.mp⟨y,bygrind⟩grind
Note in some places I use some syntax like <| where a <| b <| c <| <| d <| e is syntax sugar for a (b (c (d e))) but avoids all the nested parentheses. This is one of those things that I found a bit confusing bit earlier but once you use it a bit yourself you see that it really reduces parentheses and makes proofs more readable.
I have focused solely on golfing downing the proof, I have not looked at the contents of the proof or to see if any improvements may be made by using mathlib itself more.