[Merged by Bors] - feat: simplification lemmas for Vector.map / Vector.mapAccumr#5558
[Merged by Bors] - feat: simplification lemmas for Vector.map / Vector.mapAccumr#5558alexkeizer wants to merge 17 commits intomasterfrom
Conversation
ChrisHughes24
left a comment
There was a problem hiding this comment.
One thing I'd like to see is that any theorem about Vectors that's proved here should also be proven for Lists, and maybe the Vector version should be a trivial consequence of the List version wherever possible.
Mathlib/Data/Vector/MapLemmas.lean
Outdated
| theorem map_to_mapAccumr (xs : Vector α n) (f : α → β) : | ||
| map f xs = (mapAccumr (fun x _ => (⟨⟩, f x)) xs ()).snd := by |
There was a problem hiding this comment.
I think the equality should be the other way around and named something like mapAccumr_eq_map. Also I'm guessing the ⟨⟩ is type Unit, but I think a similar lemma applies for arbitrary types, as long as we don't depend on that.
There was a problem hiding this comment.
You are right. Actually, the reverse lemma is already present as mapAccumr_redundant_state at the bottom of the file. I'll remove these two
| @[simp] | ||
| theorem mapAccumr_mapAccumr : | ||
| mapAccumr f₁ (mapAccumr f₂ xs s₂).snd s₁ | ||
| = let m := (mapAccumr (fun x s => |
There was a problem hiding this comment.
I'm not a massive fan of lets in theorem statements, you almost always want to reduce them even if the resulting term is longer.
There was a problem hiding this comment.
Hmm, here the let is on the right side of the equation, so I thought it would be fine; these lemmas are intended as rewrite rules, I don't expect a goal of exactly this type to come up. Then again, that does mean we are making the reverse rule <-mapAccumr_mapAccumr more difficult to use.
The reduction is a bit nasty: here is a before/after
let m := (mapAccumr (fun x s =>
let r₂ := f₂ x s.snd
let r₁ := f₁ r₂.snd s.fst
((r₁.fst, r₂.fst), r₁.snd)
) xs (s₁, s₂))
(m.fst.fst, m.snd) Turns into
(
(mapAccumr (fun x s => (
((f₁ (f₂ x s.snd).snd s.fst).fst, (f₂ x s.snd).fst), (f₁ (f₂ x s.snd).snd s.fst).snd)
) xs (s₁, s₂)).fst.fst,
(mapAccumr (fun x s => (
((f₁ (f₂ x s.snd).snd s.fst).fst, (f₂ x s.snd).fst), (f₁ (f₂ x s.snd).snd s.fst).snd)
) xs (s₁, s₂)).snd
) I'll defer to you on whether the readability penalty is worth it
| induction xs using Vector.revInductionOn generalizing s <;> simp_all | ||
|
|
||
| @[simp] | ||
| theorem map_map (f₁ : β → γ) (f₂ : α → β) : |
There was a problem hiding this comment.
Is this not a duplication? It seems like it would already be there.
There was a problem hiding this comment.
Neither apply? nor simp seem to find any such existing lemma, so I don't think we have it
| pair, then we can simplify to just a single element of state | ||
| -/ | ||
| @[simp] | ||
| theorem mapAccumr_redundant_pair (f : α → (σ × σ) → (σ × σ) × β) |
There was a problem hiding this comment.
I feel like this theorem can be generalized. Are there more general conditions where you can replace the state type with a different state type, that proves this lemma as a special case?
There was a problem hiding this comment.
It probably can be, I'll have to think about it a bit more. I choose products in particular, because the earlier folding of nested mapAccumrs has a tendency to produce pairs with redundant state, so this theorem is needed to counterbalance that.
There was a problem hiding this comment.
The most general way to relate two applications of mapAccumr, with potentially different states, is bisimulation. I've added bisimulation lemmas, and proven this result in terms of bisimulation
| theorem mapAccumr₂_unused_input_left [Inhabited α] (f : α → β → σ → σ × γ) | ||
| (h : ∀ a b s, f default b s = f a b s) : | ||
| mapAccumr₂ f xs ys s = mapAccumr (fun b s => f default b s) ys s := by |
There was a problem hiding this comment.
I'm not sure that this is a good simp lemma because we have a hypothesis.
There was a problem hiding this comment.
As in, it won't work, or it's not considered appropriate?
I think it does work, but I can always add it to just the aesop ruleset, instead of as a simp-lemma
I agree that these results shouldn't necessarily be just for |
Co-authored-by: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com>
|
A |
bisimulation lemma
| theorem mapAccumr₂_mapAccumr₂_right_left (f₁ : α → γ → σ₁ → σ₁ × φ) | ||
| (f₂ : α → β → σ₂ → σ₂ × γ) : |
There was a problem hiding this comment.
| theorem mapAccumr₂_mapAccumr₂_right_left (f₁ : α → γ → σ₁ → σ₁ × φ) | |
| (f₂ : α → β → σ₂ → σ₂ × γ) : | |
| theorem mapAccumr₂_mapAccumr₂_right_left | |
| (f₁ : α → γ → σ₁ → σ₁ × φ) (f₂ : α → β → σ₂ → σ₂ × γ) : |
| theorem mapAccumr₂_mapAccumr₂_right_right (f₁ : β → γ → σ₁ → σ₁ × φ) | ||
| (f₂ : α → β → σ₂ → σ₂ × γ) : |
There was a problem hiding this comment.
| theorem mapAccumr₂_mapAccumr₂_right_right (f₁ : β → γ → σ₁ → σ₁ × φ) | |
| (f₂ : α → β → σ₂ → σ₂ × γ) : | |
| theorem mapAccumr₂_mapAccumr₂_right_right | |
| (f₁ : β → γ → σ₁ → σ₁ × φ) (f₂ : α → β → σ₂ → σ₂ × γ) : |
|
|
||
| @[simp] | ||
| theorem mapAccumr₂_mapAccumr₂_left_right | ||
| (f₁ : γ → β → σ₁ → σ₁ × φ) (f₂ : α → β → σ₂ → σ₂ × γ) : |
There was a problem hiding this comment.
| (f₁ : γ → β → σ₁ → σ₁ × φ) (f₂ : α → β → σ₂ → σ₂ × γ) : | |
| (f₁ : γ → β → σ₁ → σ₁ × φ) (f₂ : α → β → σ₂ → σ₂ × γ) : |
| induction xs, ys using Vector.revInductionOn₂ <;> simp_all | ||
|
|
||
| @[simp] | ||
| theorem mapAccumr₂_mapAccumr_right (f₁ : α → γ → σ₁ → σ₁ × ζ) (f₂ : β → σ₂ → σ₂ × γ) : |
There was a problem hiding this comment.
I think I might have changed my mind about the use of lets. It's very unreadable right now. Maybe the lets should be reintroduced on second thoughts.
|
bors merge |
Primarily focused on folding nested applications of `mapAccumr` into a single `mapAccumr` Co-authored-by: Chris Hughes <chrishughes24@gmail.com>
|
Pull request successfully merged into master. Build succeeded! The publicly hosted instance of bors-ng is deprecated and will go away soon. If you want to self-host your own instance, instructions are here. If you want to switch to GitHub's built-in merge queue, visit their help page. |
Primarily focused on folding nested applications of `mapAccumr` into a single `mapAccumr` Co-authored-by: Chris Hughes <chrishughes24@gmail.com>
Primarily focused on folding nested applications of
mapAccumrinto a singlemapAccumr