Zulip Chat Archive
Stream: general
Topic: Proving cong_arg for function of arity 2
Ben (Oct 21 2024 at 10:38):
I have the following function (that sort of represents natural number subtraction/difference)
def reduce : Nat → Nat → Nat × Nat
| .succ n1, .succ n2 => reduce n1 n2
| 0, .succ n2 => (0, n2.succ)
| .succ n1, 0 => (n1.succ, 0)
| 0, 0 => (0, 0)
#eval reduce 5 2 -- (3, 0)
#eval reduce 10 8 -- (2, 0)
#eval reduce 10 6 -- (4, 0)
#eval reduce 16 12 -- (4, 0)
#eval reduce 8 10 -- (0, 2)
For a larger theorem I need to show that the fixing the left results in a function that does represent congruent argument. But am having a little problem with it. Any help appreciated
theorem reduce.of_zero (n m: Nat) (h1: n = 0 ∨ m = 0) : (reduce n m) = (n, m) := by
cases h1 with
| inl h2 => rw [h2]; induction m; rfl; rfl;
| inr h2 => rw [h2]; induction n; rfl; rfl;
theorem reduce.left_zero (n: Nat) : reduce 0 n = (0, n) := reduce.of_zero _ n (Or.inl rfl)
theorem reduce.left_cong (a b c: Nat) : reduce a b = reduce a c → b = c := by
intro h1
-- want to do something like
-- rw [congrArg] at h1
induction a generalizing b with
| zero => rw [reduce.left_zero, reduce.left_zero] at h1; exact (Prod.ext_iff.mp h1).right;
| succ a ih => {
sorry
}
Eric Wieser (Oct 21 2024 at 10:42):
What you're describing is not "congruent argument", but injectivity
Eric Wieser (Oct 21 2024 at 10:43):
And unfortunately, the rewrite you want to do amounts to the statement you were trying to prove in the first place; so I think you need to rethink your proof strategy here!
Eric Wieser (Oct 21 2024 at 10:45):
I would guess you need to induct on b
and c
as well
Kyle Miller (Oct 21 2024 at 11:27):
Yeah, this is an injectivity theorem — the relationship is that injectivity theorems are converses of congruence theorems. Here's an approach:
def reduce : Nat → Nat → Nat × Nat
| .succ n1, .succ n2 => reduce n1 n2
| 0, .succ n2 => (0, n2.succ)
| .succ n1, 0 => (n1.succ, 0)
| 0, 0 => (0, 0)
theorem reduce_zero_left (a : Nat) : reduce a 0 = (a, 0) := by cases a <;> rfl
theorem reduce_zero_right (a : Nat) : reduce 0 a = (0, a) := by cases a <;> rfl
theorem swap_reduce (a b : Nat) : Prod.swap (reduce a b) = reduce b a := by
induction a generalizing b with
| zero => cases b <;> rfl
| succ _ ih =>
cases b
· rfl
· unfold reduce
rw [ih]
theorem reduce_add_add (a b k : Nat) : reduce (a + k) (b + k) = reduce a b := by
induction k with
| zero => rfl
| succ _ ih => exact ih
theorem reduce_of_le (a b : Nat) (h : a ≤ b) : reduce a b = (0, b - a) := by
obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_le h
have := reduce_add_add 0 k a
rw [Nat.zero_add, Nat.add_comm k] at this
rw [this, reduce_zero_right, Nat.add_sub_cancel_left]
theorem reduce_of_ge (a b : Nat) (h : b ≤ a) : reduce a b = (a - b, 0) := by
rw [← swap_reduce, reduce_of_le _ _ h]
rfl
theorem reduce.left_inj (a b c : Nat) (h : reduce a b = reduce a c) : b = c := by
obtain hb | hb := Nat.le_or_ge a b
<;> obtain hc | hc := Nat.le_or_ge a c
<;> simp [reduce_of_le, reduce_of_ge, hb, hc] at h
<;> omega
Kyle Miller (Oct 21 2024 at 11:29):
These theorems let you prove the stronger property of reduce
:
theorem reduce_eq_iff (a b a' b' : Nat) : reduce a b = reduce a' b' ↔ a + b' = b + a' := by
obtain h1 | h1 := Nat.le_or_ge a b
<;> obtain h2 | h2 := Nat.le_or_ge a' b'
<;> simp [reduce_of_le, reduce_of_ge, h1, h2]
<;> omega
Last updated: May 02 2025 at 03:31 UTC