Coq: How to prove max a b <= a + b?
Question (re3el)
I am unable to prove the simple logic max a b <= a + b using coq's tactics. How should I go about solving it? Below is the code that I worked on till now. s_le_n is proved but not mentioned here for the sake of simplicity.
forall a b : nat, a <= b -> S a <= S bAdmitted.forall a b : nat, a <= b -> S a <= S bforall a b : nat, Nat.max a b <= a + bforall a b : nat, Nat.max a b <= a + ba, b: natNat.max a b <= a + bb: natNat.max 0 b <= 0 + ba, b: nat
IHa: Nat.max a b <= a + bNat.max (S a) b <= S a + bb: natNat.max 0 b <= 0 + bapply le_n.b: natb <= ba, b: nat
IHa: Nat.max a b <= a + bNat.max (S a) b <= S a + ba, b: nat
IHa: Nat.max a b <= a + bNat.max (S a) b <= S (a + b)a: nat
IHa: Nat.max a 0 <= a + 0Nat.max (S a) 0 <= S (a + 0)a, b: nat
IHa: Nat.max a (S b) <= a + S b
IHb: Nat.max a b <= a + b -> Nat.max (S a) b <= S (a + b)Nat.max (S a) (S b) <= S (a + S b)a: nat
IHa: Nat.max a 0 <= a + 0Nat.max (S a) 0 <= S (a + 0)a: nat
IHa: Nat.max a 0 <= a + 0S a <= S (a + 0)apply le_n.a: nat
IHa: Nat.max a 0 <= a + 0S a <= S aa, b: nat
IHa: Nat.max a (S b) <= a + S b
IHb: Nat.max a b <= a + b -> Nat.max (S a) b <= S (a + b)Nat.max (S a) (S b) <= S (a + S b)a, b: nat
IHa: Nat.max a (S b) <= a + S b
IHb: Nat.max a b <= a + b -> Nat.max (S a) b <= S (a + b)Nat.max (S a) (S b) <= S a + S ba, b: nat
IHa: Nat.max a (S b) <= a + S b
IHb: Nat.max a b <= a + b -> Nat.max (S a) b <= S (a + b)S (Nat.max a b) <= S (a + S b)a, b: nat
IHa: Nat.max a (S b) <= a + S b
IHb: Nat.max a b <= a + b -> Nat.max (S a) b <= S (a + b)Nat.max a b <= a + S ba, b: nat
IHa: Nat.max a (S b) <= a + S b
IHb: Nat.max a b <= a + b -> Nat.max (S a) b <= S (a + b)Nat.max a b <= a + S b
Q (ejgallego): The proof is less than 40 characters using the library, I could post it; however, let me ask you something, how would you prove this lemma using pen and paper?
A (re3el): @ejgallego if (a > b) then max a b = a, a < a + b; else max a b = b, b < a + b. I am unable to use this logic in coq.
Answer (ejgallego)
Taking into account @re3el comment, we start from their "pen and paper proof":
if (a > b) then max a b = a, a < a + b; else max a b = b, b < a + b
Let's now translate that into Coq! In fact, the first thing we need to do is case on the decidability of <, this is done using the le_lt_dec a b lemma. The rest is routine:
Require Import Arith.a, b: natInit.Nat.max a b <= a + ba, b: natInit.Nat.max a b <= a + ba, b: nata <= b -> Init.Nat.max a b <= a + ba, b: natb < a -> Init.Nat.max a b <= a + bnow rewrite <- Nat.max_r_iff; intros ->; apply le_plus_r.a, b: nata <= b -> Init.Nat.max a b <= a + ba, b: natb < a -> Init.Nat.max a b <= a + bnow rewrite ha; apply le_plus_l. Qed.a, b: nat
ha: Nat.max a b = aInit.Nat.max a b <= a + b
However, we can improve this proof quite a bit. There are various candidates, a good one using the stdlib is:
a, b: natInit.Nat.max a b <= a + bnow rewrite Nat.max_lub_iff; split; [apply le_plus_l | apply le_plus_r]. Qed.a, b: natInit.Nat.max a b <= a + b
Using my library of choice [math-comp], you can chain the rewrites to get a more compact proof:
a, b: natmaxn a b <= a + bby rewrite geq_max leq_addl leq_addr. Qed.a, b: natmaxn a b <= a + b
In fact, on the light of short proof, maybe the original lemma was not even needed in the first place.
edit: @Jason Gross mentions another style of proof a more seasoned used would use:
apply Max.max_case_strong; lia. Qed.a, b: natNat.max a b <= a + b
However, this proof involves the use of a heavyweight automation tactic, lia; I strongly advise all beginners to avoid such tactics for a while, and learn how to do proofs more "manually". In fact, using any of the SMT-enabled tactics, the original goal can be simply solved with a call to a SMT.
A (Jason Gross): There's also a short proof without ssr: Require Import Lia. apply Max.max_case_strong; lia. It might be nice to mention this in the answer.
A (ejgallego): Thanks Jason; I tend to prefer not to teach lia and other automated tactics to beginners, IMHO it is very important that they learn how to do proofs without automation first.