4 ms·
Naturally, this proof only works for arbitrary-precision integers: when you use fixed-precision integers, the algorithm will wrongfully report "false" for array
by Joker_vD 1y ago
Naturally, this proof only works for arbitrary-precision integers: when you use fixed-precision integers, the algorithm will wrongfully report "false" for arrays like e.g. [INT_MIN, -1] or (if you insist on C semantics) [UINT_MAX, 1].
Hopefully the proof would break if one tried to transfer it over?
- Jtsummers 1y ago> the algorithm will wrongfully report "false" for arrays like e.g. [INT_MIN, -1] `INT_MIN + -1` is not 0 so it should report false in that case. For UINT_MAX, the algorithm would need to be reconsidered, though, since it's written with signed integers in mind. > Hopefully the proof would break if one tried to transfer it over? Hopefully. The proof would have to be modified to account for the actual types. If you're using bounded integers you'd need to write a different proof.
- derdi 1y ago> For UINT_MAX, the algorithm would need to be reconsidered, though, since it's written with signed integers in mind. The algorithm is written assuming that unary - produces the additive inverse. That is also true for C's unsigned integers. -1U == UINT_MAX, -UINT_MAX == 1U. It Just Works.
- junon 1y agoINT_MIN - 1 is undefined behavior in C.
- deleted 1y ago[deleted]
- zelphirkalt 1y agoWait, so much effort and it doesn't even consider this widely known issue? That would mean, that even though all this effort has been spent, a decent programmer still has a better idea of whether something is correct than the proof system used here. And worse this might lull one into thinking, that it must be correct, while actually for a simple case it breaks.
- Jtsummers 1y ago> a decent programmer still has a better idea of whether something is correct than the proof system used here. The proof is correct in the language it's written for, Lean. If you change the context (axioms) of a proof then the proof may be invalidated. This is not a surprising thing to anyone who spends a second thinking about it.
- Joker_vD 1y ago> anyone who spends a second thinking about it. Except most programmers don't spend even a second to think about it, and we end up with "int mid = (low + high) / 2;" bugs in standard implementations of binary search in e.g. Java. And that implementation even had a written proof accompanying it!
- Jtsummers 1y agoTry that in SPARK/Ada. It'll stop you there [if it can't prove that low + high won't overflow]. Don't take a proof written with one set of assumptions (in this case how integers are expected to behave) and translate it to another language where those assumptions don't hold.
- zelphirkalt 1y agoAre writing our next program in Lean then? Where does that run? There seems to be a fundamental difficulty here. Either we prove things in the language we want to use, which means modelling the behavior of the things we use in that language, or we prove things in Lean, but then cannot apply that to an actual implementation, because of issues like the one above. I would be surprised, if there was no standard approach for modelling bounded integers and their specific properties in a language (which can differ) in a proof language like this. There must have been more people having thought about this and come up with solutions.
- bollu 1y agoyes, Lean is executable, and the proof of natural numbers runs with arbitrary width integers. they're stored as tagged pointers, with upto 63bit numbers being normal numbers, and larger numbers become GMP encoded.
- DavidVoid 1y ago> the algorithm will wrongfully report "false" for arrays like e.g. [INT_MIN, -1] If you have INT_MIN along with any other negative number in the array then your program has undefined behavior in C. Signed integer overflow is UB (but unsigned overflow is not).
- addaon 1y ago> If you have INT_MIN along with any other negative number in the array then your program has undefined behavior in C. What? Why? There’s no addition needed to solve this problem. The example implementation does invert each element, which is undefined for INT_MIN, but it would be trivial to just skip INT_MIN elements (since their additive inverse is never in the set).
- raphlinus 1y agoYes. The problem here is the -x operation. If INT_MIN is in the array, then the negation operation itself is UB. As you say, the fix is to skip values equal to INT_MIN; it's not possible that its negation is in the array, as that number is not representable. Rust is only a little better. With default settings, it will panic if isize::MIN is in the input slice in a debug build, and in a release build will incorrectly return true if there are two such values in the input. But in C you'll get unicorns and rainbows.
- andrepd 1y agoBut false is the correct result for those cases. Addition is addition and overflow is undefined (= can assume that doesn't happen), it's not addition modulo 2^n.
- Joker_vD 1y agoWe are not talking about C here. Imagine it was e.g. Java, or C#, or Rust in release mode, or heck, even Lean itself but with fixed-precision integers.
- alternatex 1y agoOverflow/underflow does happen in C# though. You have to manually opt-out by using a `checked` block anywhere you do arithmetic.
- necunpri 1y agoThis is the strength of typing, right? If I can specify the type of my input I can ensure the verification.
- sureglymop 1y agoHow so? If you specify the type int how would that save you from an overflow/underflow at runtime?
- alternatex 1y agoNot sure if types are supposed to protect against overflow/underflow, it's more in the arithmetic territory. Interesting idea though, I wonder if some programming language allows overflow/underflow checks directly in the types.
- Joker_vD 1y agoYes, it's actually quite easy: +: (int<N>, int<N>) -> int<N+1> // or (int<N>, bit) as the return type *: (int<N>, int<N>) -> int<2*N> etc. Those are the actual types of those arithmetic operations.
- ethan_smith 1y agoGood point about overflow - Lean can actually model machine integers with bounded arithmetic operations, allowing you to formally verify these edge cases by explicitly reasoning about overflow behavior.
- rck 1y agoDo you know of any short examples of this? Yesterday I was trying to prove some "easy" theorems that involved machine number representations, and I couldn't find anything in Lean.