Zulip Chat Archive
Stream: lean4
Topic: proof 1 ≠ 2 the hard way
James Sully (Jun 01 2023 at 07:16):
How do I prove 1 ≠ 2? I can always use by simp
, but what about without it?
I know this is the same as 1 = 2 → False
, so presumably I want something along these lines?
example : 1 ≠ 2 :=
fun h1eq2 : 1 = 2 =>
show False from _
Ruben Van de Velde (Jun 01 2023 at 07:17):
What type are your numbers?
James Sully (Jun 01 2023 at 07:17):
Nat
James Sully (Jun 01 2023 at 07:18):
let's say
Mario Carneiro (Jun 01 2023 at 07:19):
fun.
Mario Carneiro (Jun 01 2023 at 07:19):
or fun h => nomatch h
Mario Carneiro (Jun 01 2023 at 07:22):
one more step lower in abstraction is
example : 1 ≠ 2 :=
fun (h : 1 = 2) =>
Nat.noConfusion h fun (h : 0 = 1) =>
Nat.noConfusion h
James Sully (Jun 01 2023 at 07:25):
Thanks! ok, the nomatch
one works (I'll have to look up nomatch)
theorem oneNeqTwo : (1 : Nat) ≠ 2 :=
fun h => nomatch h
But i'm not sure where to put that fun.
syntax. This is a syntax error:
theorem oneNeqTwo : (1 : Nat) ≠ 2 :=
fun.
Mario Carneiro (Jun 01 2023 at 07:25):
import Std.Tactic.NoMatch
Mario Carneiro (Jun 01 2023 at 07:26):
it's just syntax over nomatch
, to allow empty pattern matches in match
and fun
James Sully (Jun 01 2023 at 07:26):
unknown package 'Std'
Mario Carneiro (Jun 01 2023 at 07:28):
put this in your lakefile:
require std from git "https://github.com/leanprover/std4" @ "main"
Mario Carneiro (Jun 01 2023 at 07:29):
the lean core distribution basically only contains the compiler and facilities needed to write the compiler
James Sully (Jun 01 2023 at 07:29):
Ah, I see. I'm just working through Theorem Proving, so I'm not in a project, I'm just using the vscode extension on a standalone file.
Mario Carneiro (Jun 01 2023 at 07:30):
You will hit on limitations of that mode pretty quickly
Mario Carneiro (Jun 01 2023 at 07:30):
not being able to import anything being the main one
Mario Carneiro (Jun 01 2023 at 07:31):
You can start a lake project depending on mathlib using lake new myproj math
, you will want to do that to play with more advanced library stuff
James Sully (Jun 01 2023 at 07:32):
makes sense.
I'm also not seeing Nat.noConfusion
when I search the docs?
https://leanprover-community.github.io/mathlib4_docs/search.html?sitesearch=https%3A%2F%2Fleanprover-community.github.io%2Fmathlib4_docs&q=Nat.noConfusion
Mario Carneiro (Jun 01 2023 at 07:32):
It's an automatically generated definition created for every inductive type
Mario Carneiro (Jun 01 2023 at 07:33):
recommended reading: https://xenaproject.wordpress.com/2018/03/24/no-confusion-over-no_confusion/
Mario Carneiro (Jun 01 2023 at 07:33):
you can use #print Nat.noConfusion
and #print Nat.noConfusionType
to see the definitions
James Sully (Jun 01 2023 at 07:34):
Ok, cheers! Doing a quick search, it looks like it comes up in chapter 8 of Theorem Proving as well
Kyle Miller (Jun 01 2023 at 07:54):
Here's another alternative:
example : 1 ≠ 2 :=
fun h1eq2 : 1 = 2 => by cases h1eq2
cases
on an equality means it tries to unify the LHS and RHS since rfl
is the only constructor, and cases
knows how to peel off constructors and that different constructors can't be equal, so it sees 1 = 2
, turns it into 0 = 1
, and then knows 0
can't equal Nat.succ
so recognizes the contradiction.
Kyle Miller (Jun 01 2023 at 07:58):
match
/nomatch
can do the same kinds of calculations
Kyle Miller (Jun 01 2023 at 07:59):
A term proof is
example : 1 ≠ 2 :=
fun h1eq2 : 1 = 2 =>
Nat.zero_ne_one (Nat.succ_inj'.mp h1eq2)
though these are probably proved using match
or Nat.noConfusion
Mario Carneiro (Jun 01 2023 at 08:01):
It is worth noting that the actual proof that simp comes up with is actually a bit closer to
example : 1 ≠ 2 := Nat.ne_of_beq_eq_false rfl
taking advantage of the fact that natural number equality has a primitive implementation in the kernel. This is especially important if the proof is not about 1 ≠ 2
but rather 1000000000 ≠ 2000000000
, because the methods involving noConfusion
involve peeling one constructor off at a time, which would mean a billion steps to prove this
Kevin Buzzard (Jun 01 2023 at 08:11):
It's all very well explaining these cute hacky methods/tricks but by norm_num
is really the correct answer because this is the technique which generalises. norm_num
is the tactic which proves equalities and inequalities between numerals.
James Sully (Jun 01 2023 at 08:17):
how do I look at the term proof a tactic produces?
Henrik Böving (Jun 01 2023 at 08:18):
#print mytheorem
James Sully (Jun 01 2023 at 08:19):
ah, of course lol
Kevin Buzzard (Jun 01 2023 at 08:20):
You don't want to look at the term proof that norm_num
produces though :-)
Mario Carneiro (Jun 01 2023 at 08:21):
you know, saying that is just going to make people want to look at it
James Sully (Jun 01 2023 at 08:22):
I'm staying away from std for the duration of this book. The book hasn't told me to use it and I assume there are pedagogical reasons not to yet
James Sully (Jun 01 2023 at 08:22):
or mathlib rather
Kevin Buzzard (Jun 01 2023 at 08:22):
Now I've found that James is a "let me look at the proof term" kind of person (ie not a mathematician) I wish I'd not opened my mouth :-)
James Sully (Jun 01 2023 at 08:23):
hahaha
James Sully (Jun 01 2023 at 08:23):
my cover's blown
Kevin Buzzard (Jun 01 2023 at 08:24):
Re pedagogical reasons -- it depends what you're trying to teach. "Mathematics in Lean" uses mathlib from page 1
James Sully (Jun 01 2023 at 08:24):
I actually started on Functional Programming in lean and then switched halfway through out of curiosity
Kevin Buzzard (Jun 01 2023 at 08:24):
I teach maths undergraduates lean from scratch using mathlib, but I don't teach them anything about term mode at all, or proof terms etc
Kevin Buzzard (Jun 01 2023 at 08:25):
It all depends on the level of abstraction you're interested in
Mario Carneiro (Jun 01 2023 at 08:25):
lol, I tried it and got:
example : 1 ≠ 2 := show_term by norm_num
-- Try this: of_eq_true (eq_true_of_decide (Eq.refl true))
James Sully (Jun 01 2023 at 08:25):
yeah, I'm more interested in the FP side and potentially bringing insights back with me to other languages
Mario Carneiro (Jun 01 2023 at 08:25):
which is not a norm_num proof at all
Mario Carneiro (Jun 01 2023 at 08:26):
using norm_num1
produces the expected horror:
example : 1 ≠ 2 := show_term by norm_num1
-- Try this: of_eq_true
-- (eq_true
-- (Mathlib.Meta.NormNum.isNat_eq_false (Mathlib.Meta.NormNum.isNat_ofNat ℕ (Eq.refl 1))
-- (Mathlib.Meta.NormNum.isNat_ofNat ℕ (Eq.refl 2)) (Eq.refl false)))
Mario Carneiro (Jun 01 2023 at 08:27):
(which BTW is just an obfuscated version of the same proof)
Kevin Buzzard (Jun 01 2023 at 08:27):
James can take that insight back with them to other languages
Last updated: Dec 20 2023 at 11:08 UTC