Some Junk Theorems in Lean

(github.com)

46 points | by saithound 4 days ago

7 comments

  • frotaur 1 hour ago
    I don't know much about Lean, but I attended an introductory talk at some point and I was particularly bothered by these partial function definitions. The example was sqrt, which would give 0 on the negatives.

    Now, of course, if you're careful with the definitions you use, there is no problem. But in the (increasingly relevant) context of automatic theorem proving with LLMs, this seems to defeat the 'groundtruthness' of Lean!

    How do you make sure that the LLM doesn't reward hack a proof using these workarounds?

    • akoboldfrying 1 hour ago
      I don't understand why they would make such footgun functions either, especially because (IIUC, and I probably don't) in a way the whole point of Lean's dependent type system is to be able to express arbitrary constraints on the inputs of these functions so that they can be total -- e.g., to be able to define a subtraction function on the nonnegative integers that takes one integer and one {integer that is less than or equal to the first integer}. And to even call this function, you (or perhaps Lean itself) would need to first prove that its second argument is less than or equal to its first.
      • Smaug123 1 hour ago
        You can express those constraints; it just turns out to be less ergonomic in practice if you do. (You can even do so in terms of the junk-valued total functions! Just define `actual_subtraction` to call straight through to `junky_subtraction`, but `actual_subtraction` has these constraints on its domain.)

        The mathlib way to do things is to push those requirements out to the one who wishes to use the theorem. If you find that you're depending on a junk value in a way that's incompatible with what you wanted to prove, then you've simply discovered that you forgot to restrict your own domain to exclude the junk. (And if your desired usage lines up with the junk, then great, you get to omit an annoying busywork hypothesis.) A sqrt function that gives 0 on the negatives isn't breaking any of sqrt's properties on the positives!

        The mathlib way means that instead of every function having to express these constraints and pass proofs down the line, only some functions have to.

        • akoboldfrying 52 minutes ago
          Thanks.

          > If you find that you're depending on a junk value in a way that's incompatible with what you wanted to prove

          This is the part I'm struggling with. How would you actually know/realise that you were doing this? It seems like "the mathlib way" you describe is choosing to rely on programmer discipline for something that could be enforced automatically.

          My fear is that relying on the junk values of functions (values where their "proper" partial counterparts are not defined) is somehow unsound (could lead to proving something untrue). But perhaps my intuition is off here? If so, I think the specific junk values chosen must not matter at all -- e.g., having sqrt return 42 for negative x values should work just as well, am I right?

          • markusde 7 minutes ago
            You can't prove something untrue (in the sense that it implies false) without proving that the theorem prover is is unsound, which I think at the moment is not known to be possible in Lean.

            But you're exactly right. There's nothing linking theorem prover definitions to pen and paper definitions in any formal system.

      • markusde 39 minutes ago
        This is a topic of contention in formalized math with no universal right answer. Some libraries go heavy on the dependent types, and some like mathlib try to avoid them. I do math in both Rocq and Lean and I find I like the latter style a lot more for my work for a couple reasons:

        - Fewer side conditions: Setting a / 0 = 0 means that some laws hold even when a denominator is 0, and so you don't need to prove the denominator is nonzero. This is super nice when the denominator is horrible. I heard once that if you set the junk value for a non-converging Riemann integral to the average of the lim sup and lim inf you can obliterate a huge number of integrability side conditions (though I didn't track down this paper to find out for sure).

        - Some of the wacky junk arithmetic values, especially as it relates to extended reals, do show up in measure theory. Point being: "junk arithmetic" is a different mathematical theory than normal math, but it's no less legitimate, and is closely related.

        - Definition with Hilbert's epsilon operator. If I want to define a function that takes eg. a measurable set S as an argument, I could do the dependent types way

        def MyDef (S) (H : measurable S) := /-- real definition -/

        but then I need to write all of my theorems in terms of (MyDef S H) and this can cause annoying unification problems (moreso in Rocq than in Lean, assuming H is a Prop). Alternatively, I could use junk math

        def MyDef' (S) := if (choose (H : measurable S)) then /-- real definition -/ else /-- junk -/

        I can prove (MyDef' S = MyDef S H) when I have access to (H : measurable S). And the property H here can be be really complex, convergence properties, existence properties, etc. It's nice to avoid trucking them around everywhere.

      • danabramov 29 minutes ago
        There’s a good blog post on this by Kevin Buzzard. I suggest to give it a read: https://xenaproject.wordpress.com/2020/07/05/division-by-zer...

        I found the last section especially helpful.

        • zarzavat 4 minutes ago
          I feel like this aged like milk because it assumes a human mathematician writing the proof but many people are now generating Lean proofs with LLMs.
  • andyjohnson0 2 hours ago
    TIL that "junk theorems" are a thing in mathematics. Not being a mathematician myself, I found this [1] article a useful primer.

    [1] https://www.cantorsparadise.com/what-are-junk-theorems-29868...

    • ttctciyf 18 minutes ago
      Maybe I'm too familiar with the set theoretic construction of the natural numbers (0 is the empty set, 1 = {0}, ..., 5 = {0,1,2,3,4}, etc.) but their example of "3 ∩ 4 = 3" or "4 intersect 3 is 3" doesn't seem weird, problematic or even useless to me, it just looks like a handy set theoretic implementation of the min() function.
    • oersted 1 hour ago
      This is very interesting. What happens if you keep pulling the thread and construct large theories on such abstraction-layer-breaking theorems? Would we arrive at interesting things like pulling the thread on sqrt(-1) for imaginary numbers? Or is it somehow “undefined behavior”, quirks of the various implementation substrates of abstract mathematics that should be (informally) ignored? My gut says the former.

      Are the various alternative axiomatic foundations also equivalent at this level or not? I suppose they are since they can implement/emulate each other, not sure.

    • akoboldfrying 1 hour ago
      This was helpful, thanks.
      • cmrx64 1 hour ago
        the last paragraphs cite why junk theorems are objectionable but then fully misinterprets it to draw the opposite conclusion. the intersection is the S-feature and problematic. 1 + 2 = 4 is a “theorem beyond T” expressed in T theory.

        don’t be mislead about what a junk theorem is!

  • proof_by_vibes 19 minutes ago
    I've been writing [libsodium](https://doc.libsodium.org/) bindings in Lean4 and have ended up using `native_decide` quite liberally, mostly as a convenience. Can any Lean devs provide a more thorough interrogation of this? Should I go back and try to scrub its usage out of my library? Logically it seems consistent with what I'm trying to do with Lean4's FFI (i.e. you really do need to explicitly trust the Lean kernel since I'm adding nontrivial computation using a foreign cryptography library) but I'm curious if this isn't necessary and whether Lean devs would push back on its use.
  • 414owen 2 hours ago
    Wow, okay. I would imagine this makes mathematicians quite angry? I guess you're responsible for all the operations you use in your proof being well-behaved.

    It sounds like subtraction over Nats needs to be split into `sub?`, and `sub!`, the former returning an option, and the latter crashing, on underflow, as is the Lean convention?

    To use the default `sub`, you should need to provide a witness that the minuend is >= the subtrahend...

    The version with silent underflow is still useful, it should just be called `saturatingSub`, or something, so that mathematicians using it know what they're getting themselves into...

  • bjt12345 53 minutes ago
    I'm surprised to learn that lean defines the natural number 1/0 as 0.
    • istjohn 20 minutes ago
      Doesn't this allow one to prove x=y for any x, y?

      x/0 = x(1/0) = x*0 = 0, so x/0 = 0 for all x.

      So x/0 = y/0.

      Multiply both sides by 0: x = y.

      • rnhmjoj 3 minutes ago
        No, because x/y is just an arbitrary operation between x and y. Here you're assuming that 1/x is the inverse of x under *, but it's not.
  • pron 1 hour ago
    I don't think anyone minds this. The purpose of a formal foundation is to prove useful theorems. Junk theorems are just a side effect. But I'm always tickled by logicians who think type theories are philosophically superior to set theories because in some of the latter you might be able to prove something like 1 ∈ 2, whereas type theories, even without their own junk theorems, have a pragmatic difficulty with division (hence they tend to define 1/0 = 0). Junk theorems just come with the territory, and foundations need to be considered based on their utility, not philosophical purity, which is never achieved anyway (at least not without a cost to utility).
    • falcor84 50 minutes ago
      > But I'm always tickled by logicians who think type theories are philosophically superior to set theories because in some of the latter you might be able to prove something like 1 ∈ 2

      Note that this is actually how the basic ZF construction works, where 0 = {} and successor(n) = n ∪ {n}, so you immediately get 2 = {0, 1} and thus 1 ∈ 2 , without any need for a proof.

  • emil-lp 2 hours ago
    I don't understand. What does this mean?

        Theorem 6. The following are equivalent: The binary expansion of 7.
    • tux3 2 hours ago
      This is a junk theorem, it's trying to prove something that will sound strange or meaningless but is technically allowed by the details of the foundations.

      Here it's building a list with one element and saying all elements of this list are equivalent. S̶o̶ ̶t̶h̶e̶ ̶f̶o̶l̶l̶o̶w̶i̶n̶g̶ ̶e̶l̶e̶m̶e̶n̶t̶s̶ ̶o̶f̶ ̶t̶h̶e̶ ̶l̶i̶s̶t̶ ̶a̶r̶e̶ ̶a̶l̶l̶ ̶e̶q̶u̶i̶v̶a̶l̶e̶n̶t̶ ̶t̶o̶ ̶e̶a̶c̶h̶ ̶o̶t̶h̶e̶r̶ ̶(̶t̶h̶e̶r̶e̶ ̶i̶s̶ ̶a̶ ̶s̶i̶n̶g̶l̶e̶ ̶e̶l̶e̶m̶e̶n̶t̶ ̶i̶n̶ ̶t̶h̶e̶ ̶l̶i̶s̶t̶)̶

      • cmrx64 1 hour ago
        the binary expansion of 7 has three elements (you will find them at indexes Fin 0, Fin 1, and Fin 2) and the proof is of their equality.
    • bzax 2 hours ago
      It doesn't mean anything. The point is that the language of lean, and its proof derivation system, are able to express (and prove) statements that do not correspond to any meaningful mathematics.
    • homeless_engi 51 minutes ago
      As I think another commenter hinted, the binary expansion of 7 is 111. And indeed, 1 = 1 = 1
    • cmrx64 1 hour ago
      List.TFAE is a helper definition and it’s invoked on a funny looking term when translated directly into english. I don’t know what I think, yeah it’s kinda junky but not in the way that 57 \mem 100 in a set encoding of the naturals.

          theorem TFAE_7_binary : List.TFAE (7).bits := by
        unfold Nat.bits Nat.binaryRec Nat.binaryRec; simp!
    • silasdavis 2 hours ago
      The following are equivalent: