Zulip Chat Archive
Stream: general
Topic: Don't repeat a proof branch with a single different name
nrs (Nov 19 2024 at 03:09):
def getMatchLocsFromBack [DecidableEq α] [Inhabited α] : Array α -> Array α -> Array Nat
| ara, arb =>
let rec counter : Array α -> Array α -> Nat -> Array Nat
| ara', arb', count =>
if hh : ara'.isEmpty || arb'.isEmpty then #[]
else
if ara'.back! = arb'.back!
then Array.singleton count ++ counter ara'.pop arb'.pop count.succ
else counter ara' arb'.pop count.succ
termination_by _ arb' _ => arb'.size
decreasing_by
all_goals
simp_all [@List.length_pos_iff_ne_nil]
counter ara arb 0
theorem counterMonotonicityPart1 [DecidableEq α] [Inhabited α] {ara arb : Array α} {n : Nat} : getMatchLocsFromBack.counter ara arb n = Array.singleton n ++ (getMatchLocsFromBack.counter ara.pop arb.pop n.succ) ∨ getMatchLocsFromBack.counter ara arb n = getMatchLocsFromBack.counter ara arb.pop n.succ := by
rw [getMatchLocsFromBack.counter]
split
· simp_all
rename_i h
cases h
· rename_i h
rw [getMatchLocsFromBack.counter]
match ara with
| Array.mk artolist =>
simp_all [getMatchLocsFromBack.counter]
· rename_i h
rw [getMatchLocsFromBack.counter]
match arb with
| Array.mk artolist =>
simp_all [getMatchLocsFromBack.counter]
· split
all_goals
simp_all
I'm working towards proving monotonicity wrt. argument size for the first argument of getMatchLocsFromBack
, which is a function that returns an array that contains all the positions where two arrays match, beginning from the back.
In the counterMonotonicityPart1
, the two branches resulting from cases h
are nearly the same with the sole exception of ara
and arb
. How could I prove them both at the same time? (general style/writing tips are also welcome)
cases h
· rename_i h
rw [getMatchLocsFromBack.counter]
match ara with
| Array.mk artolist =>
simp_all [getMatchLocsFromBack.counter]
· rename_i h
rw [getMatchLocsFromBack.counter]
match arb with
| Array.mk artolist =>
simp_all [getMatchLocsFromBack.counter]
nrs (Nov 19 2024 at 03:54):
Using rcases
works for this purpose in this case:
theorem counterMonotonicity1' [DecidableEq α] [Inhabited α] {ara arb : Array α} {n : Nat} : getMatchLocsFromBack.counter ara arb n = Array.singleton n ++ (getMatchLocsFromBack.counter ara.pop arb.pop n.succ) ∨ getMatchLocsFromBack.counter ara arb n = getMatchLocsFromBack.counter ara arb.pop n.succ := by
rw [getMatchLocsFromBack.counter]
split
· simp_all
rename_i h
cases h
all_goals
rename_i h
rw [getMatchLocsFromBack.counter]
rcases ara
rcases arb
simp_all [getMatchLocsFromBack.counter]
· split
all_goals
simp_all
Marcus Rossel (Nov 19 2024 at 17:39):
Here's another shorter version:
import Mathlib
variable [DecidableEq α] [Inhabited α]
def getMatchLocsFromBack (ara arb : Array α) : Array Nat :=
counter ara arb 0
where
counter (ara arb count) : Array Nat :=
if ara.isEmpty || arb.isEmpty then
#[]
else if ara.back! = arb.back! then
#[count] ++ counter ara.pop arb.pop (count + 1)
else
counter ara arb.pop (count + 1)
termination_by arb.size
decreasing_by all_goals simp_all [List.length_pos_iff_ne_nil]
theorem counterMonotonicityPart1 {ara arb : Array α} :
getMatchLocsFromBack.counter ara arb n = #[n] ++ getMatchLocsFromBack.counter ara.pop arb.pop (n + 1) ∨
getMatchLocsFromBack.counter ara arb n = getMatchLocsFromBack.counter ara arb.pop (n + 1) := by
rw [getMatchLocsFromBack.counter]
split_ifs <;> simp_all
cases ara; cases arb; cases ‹_ ∨ _› <;> simp_all [getMatchLocsFromBack.counter]
nrs (Nov 19 2024 at 17:48):
Marcus Rossel said:
Here's another shorter version:
import Mathlib variable [DecidableEq α] [Inhabited α] def getMatchLocsFromBack (ara arb : Array α) : Array Nat := counter ara arb 0 where counter (ara arb count) : Array Nat := if ara.isEmpty || arb.isEmpty then #[] else if ara.back! = arb.back! then #[count] ++ counter ara.pop arb.pop (count + 1) else counter ara arb.pop (count + 1) termination_by arb.size decreasing_by all_goals simp_all [List.length_pos_iff_ne_nil] theorem counterMonotonicityPart1 {ara arb : Array α} : getMatchLocsFromBack.counter ara arb n = #[n] ++ getMatchLocsFromBack.counter ara.pop arb.pop (n + 1) ∨ getMatchLocsFromBack.counter ara arb n = getMatchLocsFromBack.counter ara arb.pop (n + 1) := by rw [getMatchLocsFromBack.counter] split_ifs <;> simp_all cases ara; cases arb; cases ‹_ ∨ _› <;> simp_all [getMatchLocsFromBack.counter]
woah very cool! thank you very much, I've learned a lot from reading your version!!
Last updated: May 02 2025 at 03:31 UTC