|
| 1 | +/- |
| 2 | +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Paul Reichert |
| 5 | +-/ |
| 6 | +prelude |
| 7 | +import Std.Data.Iterators.Basic |
| 8 | +import Std.Data.Iterators.Consumers.Collect |
| 9 | +import Std.Data.Iterators.Consumers.Loop |
| 10 | +import Std.Data.Iterators.Internal.Termination |
| 11 | + |
| 12 | +namespace Std.Iterators |
| 13 | + |
| 14 | +variable {m : Type w → Type w'} |
| 15 | + {α₁ : Type w} {β₁ : Type w} [Iterator α₁ m β₁] |
| 16 | + {α₂ : Type w} {β₂ : Type w} [Iterator α₂ m β₂] |
| 17 | + |
| 18 | +@[unbox] |
| 19 | +structure Zip (α₁ : Type w) (m : Type w → Type w') {β₁ : Type w} [Iterator α₁ m β₁] (α₂ : Type w) (β₂ : Type w) where |
| 20 | + left : IterM (α := α₁) m β₁ |
| 21 | + memoizedLeft : (Option { out : β₁ // ∃ it : IterM (α := α₁) m β₁, it.IsPlausibleOutput out }) |
| 22 | + right : IterM (α := α₂) m β₂ |
| 23 | + |
| 24 | +inductive Zip.PlausibleStep (it : IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)) : |
| 25 | + IterStep (IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)) (β₁ × β₂) → Prop where |
| 26 | + | yieldLeft (hm : it.internalState.memoizedLeft = none) {it' out} (hp : it.internalState.left.IsPlausibleStep (.yield it' out)) : |
| 27 | + PlausibleStep it (.skip ⟨⟨it', (some ⟨out, _, _, hp⟩), it.internalState.right⟩⟩) |
| 28 | + | skipLeft (hm : it.internalState.memoizedLeft = none) {it'} (hp : it.internalState.left.IsPlausibleStep (.skip it')) : |
| 29 | + PlausibleStep it (.skip ⟨⟨it', none, it.internalState.right⟩⟩) |
| 30 | + | doneLeft (hm : it.internalState.memoizedLeft = none) (hp : it.internalState.left.IsPlausibleStep .done) : |
| 31 | + PlausibleStep it .done |
| 32 | + | yieldRight {out₁} (hm : it.internalState.memoizedLeft = some out₁) {it₂' out₂} (hp : it.internalState.right.IsPlausibleStep (.yield it₂' out₂)) : |
| 33 | + PlausibleStep it (.yield ⟨⟨it.internalState.left, none, it₂'⟩⟩ (out₁, out₂)) |
| 34 | + | skipRight {out₁} (hm : it.internalState.memoizedLeft = some out₁) {it₂'} (hp : it.internalState.right.IsPlausibleStep (.skip it₂')) : |
| 35 | + PlausibleStep it (.skip ⟨⟨it.internalState.left, (some out₁), it₂'⟩⟩) |
| 36 | + | doneRight {out₁} (hm : it.internalState.memoizedLeft = some out₁) (hp : it.internalState.right.IsPlausibleStep .done) : |
| 37 | + PlausibleStep it .done |
| 38 | + |
| 39 | +instance Zip.instIterator [Monad m] : |
| 40 | + Iterator (Zip α₁ m α₂ β₂) m (β₁ × β₂) where |
| 41 | + IsPlausibleStep := PlausibleStep |
| 42 | + step it := |
| 43 | + match hm : it.internalState.memoizedLeft with |
| 44 | + | none => do |
| 45 | + match ← it.internalState.left.step with |
| 46 | + | .yield it₁' out hp => |
| 47 | + pure <| .skip ⟨⟨it₁', (some ⟨out, _, _, hp⟩), it.internalState.right⟩⟩ (.yieldLeft hm hp) |
| 48 | + | .skip it₁' hp => |
| 49 | + pure <| .skip ⟨⟨it₁', none, it.internalState.right⟩⟩ (.skipLeft hm hp) |
| 50 | + | .done hp => |
| 51 | + pure <| .done (.doneLeft hm hp) |
| 52 | + | some out₁ => do |
| 53 | + match ← it.internalState.right.step with |
| 54 | + | .yield it₂' out₂ hp => |
| 55 | + pure <| .yield ⟨⟨it.internalState.left, none, it₂'⟩⟩ (out₁, out₂) (.yieldRight hm hp) |
| 56 | + | .skip it₂' hp => |
| 57 | + pure <| .skip ⟨⟨it.internalState.left, (some out₁), it₂'⟩⟩ (.skipRight hm hp) |
| 58 | + | .done hp => |
| 59 | + pure <| .done (.doneRight hm hp) |
| 60 | + |
| 61 | +@[inline] |
| 62 | +def IterM.zip |
| 63 | + (left : IterM (α := α₁) m β₁) (right : IterM (α := α₂) m β₂) : |
| 64 | + IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) := |
| 65 | + toIterM ⟨left, none, right⟩ m _ |
| 66 | + |
| 67 | +-- TODO: put this into core. This is also duplicated in FlatMap |
| 68 | +theorem Zip.wellFounded_optionLt {α} {rel : α → α → Prop} (h : WellFounded rel) : |
| 69 | + WellFounded (Option.lt rel) := by |
| 70 | + refine ⟨?_⟩ |
| 71 | + intro x |
| 72 | + have hn : Acc (Option.lt rel) none := by |
| 73 | + refine Acc.intro none ?_ |
| 74 | + intro y hyx |
| 75 | + cases y <;> cases hyx |
| 76 | + cases x |
| 77 | + · exact hn |
| 78 | + · rename_i x |
| 79 | + induction h.apply x |
| 80 | + rename_i x' h ih |
| 81 | + refine Acc.intro _ ?_ |
| 82 | + intro y hyx' |
| 83 | + cases y |
| 84 | + · exact hn |
| 85 | + · exact ih _ hyx' |
| 86 | + |
| 87 | +variable (m) in |
| 88 | +def Zip.Rel₁ [Finite α₁ m] [Productive α₂ m] : |
| 89 | + IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → Prop := |
| 90 | + InvImage (Prod.Lex |
| 91 | + IterM.TerminationMeasures.Finite.Rel |
| 92 | + (Prod.Lex (Option.lt emptyRelation) IterM.TerminationMeasures.Productive.Rel)) |
| 93 | + (fun it => (it.internalState.left.finitelyManySteps, (it.internalState.memoizedLeft, it.internalState.right.finitelyManySkips))) |
| 94 | + |
| 95 | +theorem Zip.rel₁_of_left [Finite α₁ m] [Productive α₂ m] {it' it : IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)} |
| 96 | + (h : it'.internalState.left.finitelyManySteps.Rel it.internalState.left.finitelyManySteps) : |
| 97 | + Zip.Rel₁ m it' it := |
| 98 | + Prod.Lex.left _ _ h |
| 99 | + |
| 100 | +theorem Zip.rel₁_of_memoizedLeft [Finite α₁ m] [Productive α₂ m] |
| 101 | + {left : IterM (α := α₁) m β₁} {b' b} {right' right : IterM (α := α₂) m β₂} |
| 102 | + (h : Option.lt emptyRelation b' b) : |
| 103 | + Zip.Rel₁ m ⟨left, b', right'⟩ ⟨left, b, right⟩ := |
| 104 | + Prod.Lex.right _ <| Prod.Lex.left _ _ h |
| 105 | + |
| 106 | +theorem Zip.rel₁_of_right [Finite α₁ m] [Productive α₂ m] |
| 107 | + {left : IterM (α := α₁) m β₁} {b b' : _} {it' it : IterM (α := α₂) m β₂} |
| 108 | + (h : b' = b) |
| 109 | + (h' : it'.finitelyManySkips.Rel it.finitelyManySkips) : |
| 110 | + Zip.Rel₁ m ⟨left, b', it'⟩ ⟨left, b, it⟩ := by |
| 111 | + cases h |
| 112 | + exact Prod.Lex.right _ <| Prod.Lex.right _ h' |
| 113 | + |
| 114 | +def Zip.instFinitenessRelation₁ [Monad m] [Finite α₁ m] [Productive α₂ m] : |
| 115 | + FinitenessRelation (Zip α₁ m α₂ β₂) m where |
| 116 | + rel := Zip.Rel₁ m |
| 117 | + wf := by |
| 118 | + apply InvImage.wf |
| 119 | + refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩ |
| 120 | + · exact WellFoundedRelation.wf |
| 121 | + · refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩ |
| 122 | + · apply Zip.wellFounded_optionLt |
| 123 | + exact emptyWf.wf |
| 124 | + · exact WellFoundedRelation.wf |
| 125 | + subrelation {it it'} h := by |
| 126 | + obtain ⟨step, h, h'⟩ := h |
| 127 | + cases h' |
| 128 | + case yieldLeft hm it' out hp => |
| 129 | + cases h |
| 130 | + apply Zip.rel₁_of_left |
| 131 | + exact IterM.TerminationMeasures.Finite.rel_of_yield ‹_› |
| 132 | + case skipLeft hm it' hp => |
| 133 | + cases h |
| 134 | + apply Zip.rel₁_of_left |
| 135 | + exact IterM.TerminationMeasures.Finite.rel_of_skip ‹_› |
| 136 | + case doneLeft hm hp => |
| 137 | + cases h |
| 138 | + case yieldRight out₁ hm it₂' out₂ hp => |
| 139 | + cases h |
| 140 | + apply Zip.rel₁_of_memoizedLeft |
| 141 | + simp [Option.lt, hm] |
| 142 | + case skipRight out₁ hm it₂' hp => |
| 143 | + cases h |
| 144 | + apply Zip.rel₁_of_right |
| 145 | + · simp_all |
| 146 | + · exact IterM.TerminationMeasures.Productive.rel_of_skip ‹_› |
| 147 | + case doneRight out₁ hm hp => |
| 148 | + cases h |
| 149 | + |
| 150 | +instance Zip.instFinite₁ [Monad m] [Finite α₁ m] [Productive α₂ m] : |
| 151 | + Finite (Zip α₁ m α₂ β₂) m := |
| 152 | + Finite.of_finitenessRelation Zip.instFinitenessRelation₁ |
| 153 | + |
| 154 | +def Zip.lt_with_top {α} (r : α → α → Prop) : Option α → Option α → Prop |
| 155 | + | none, _ => false |
| 156 | + | some _, none => true |
| 157 | + | some a', some a => r a' a |
| 158 | + |
| 159 | +theorem Zip.wellFounded_lt_with_top {α} {r : α → α → Prop} (h : WellFounded r) : |
| 160 | + WellFounded (lt_with_top r) := by |
| 161 | + refine ⟨?_⟩ |
| 162 | + intro x |
| 163 | + constructor |
| 164 | + intro x' hlt |
| 165 | + match x' with |
| 166 | + | none => contradiction |
| 167 | + | some x' => |
| 168 | + clear hlt |
| 169 | + induction h.apply x' |
| 170 | + rename_i ih |
| 171 | + constructor |
| 172 | + intro x'' hlt' |
| 173 | + match x'' with |
| 174 | + | none => contradiction |
| 175 | + | some x'' => exact ih x'' hlt' |
| 176 | + |
| 177 | +variable (m) in |
| 178 | +def Zip.Rel₂ [Productive α₁ m] [Finite α₂ m] : |
| 179 | + IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → Prop := |
| 180 | + InvImage (Prod.Lex |
| 181 | + IterM.TerminationMeasures.Finite.Rel |
| 182 | + (Prod.Lex (Zip.lt_with_top emptyRelation) IterM.TerminationMeasures.Productive.Rel)) |
| 183 | + (fun it => (it.internalState.right.finitelyManySteps, (it.internalState.memoizedLeft, it.internalState.left.finitelyManySkips))) |
| 184 | + |
| 185 | +theorem Zip.rel₂_of_right [Productive α₁ m] [Finite α₂ m] {it' it : IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)} |
| 186 | + (h : it'.internalState.right.finitelyManySteps.Rel it.internalState.right.finitelyManySteps) : Zip.Rel₂ m it' it := |
| 187 | + Prod.Lex.left _ _ h |
| 188 | + |
| 189 | +theorem Zip.rel₂_of_memoizedLeft [Productive α₁ m] [Finite α₂ m] |
| 190 | + {right : IterM (α := α₂) m β₂} {b' b} {left' left : IterM (α := α₁) m β₁} |
| 191 | + (h : lt_with_top emptyRelation b' b) : |
| 192 | + Zip.Rel₂ m ⟨left, b', right⟩ ⟨left', b, right⟩ := |
| 193 | + Prod.Lex.right _ <| Prod.Lex.left _ _ h |
| 194 | + |
| 195 | +theorem Zip.rel₂_of_left [Productive α₁ m] [Finite α₂ m] |
| 196 | + {right : IterM (α := α₂) m β₂} {b b' : _} {it' it : IterM (α := α₁) m β₁} |
| 197 | + (h : b' = b) |
| 198 | + (h' : it'.finitelyManySkips.Rel it.finitelyManySkips) : |
| 199 | + Zip.Rel₂ m ⟨it', b', right⟩ ⟨it, b, right⟩ := by |
| 200 | + cases h |
| 201 | + exact Prod.Lex.right _ <| Prod.Lex.right _ h' |
| 202 | + |
| 203 | +def Zip.instFinitenessRelation₂ [Monad m] [Productive α₁ m] [Finite α₂ m] : |
| 204 | + FinitenessRelation (Zip α₁ m α₂ β₂) m where |
| 205 | + rel := Zip.Rel₂ m |
| 206 | + wf := by |
| 207 | + apply InvImage.wf |
| 208 | + refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩ |
| 209 | + · exact WellFoundedRelation.wf |
| 210 | + · refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩ |
| 211 | + · apply Zip.wellFounded_lt_with_top |
| 212 | + exact emptyWf.wf |
| 213 | + · exact WellFoundedRelation.wf |
| 214 | + subrelation {it it'} h := by |
| 215 | + obtain ⟨step, h, h'⟩ := h |
| 216 | + cases h' |
| 217 | + case yieldLeft hm it' out hp => |
| 218 | + cases h |
| 219 | + apply Zip.rel₂_of_memoizedLeft |
| 220 | + simp_all [Zip.lt_with_top] |
| 221 | + case skipLeft hm it' hp => |
| 222 | + cases h |
| 223 | + apply Zip.rel₂_of_left |
| 224 | + · simp_all |
| 225 | + · exact IterM.TerminationMeasures.Productive.rel_of_skip ‹_› |
| 226 | + case doneLeft hm hp => |
| 227 | + cases h |
| 228 | + case yieldRight out₁ hm it₂' out₂ hp => |
| 229 | + cases h |
| 230 | + apply Zip.rel₂_of_right |
| 231 | + exact IterM.TerminationMeasures.Finite.rel_of_yield ‹_› |
| 232 | + case skipRight out₁ hm it₂' hp => |
| 233 | + cases h |
| 234 | + apply Zip.rel₂_of_right |
| 235 | + exact IterM.TerminationMeasures.Finite.rel_of_skip ‹_› |
| 236 | + case doneRight out₁ hm hp => |
| 237 | + cases h |
| 238 | + |
| 239 | +instance Zip.instFinite₂ [Monad m] [Productive α₁ m] [Finite α₂ m] : |
| 240 | + Finite (Zip α₁ m α₂ β₂) m := |
| 241 | + Finite.of_finitenessRelation Zip.instFinitenessRelation₂ |
| 242 | + |
| 243 | +variable (m) in |
| 244 | +def Zip.Rel₃ [Productive α₁ m] [Productive α₂ m] : |
| 245 | + IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂) → Prop := |
| 246 | + InvImage (Prod.Lex |
| 247 | + (lt_with_top emptyRelation) |
| 248 | + (Prod.Lex (IterM.TerminationMeasures.Productive.Rel) IterM.TerminationMeasures.Productive.Rel)) |
| 249 | + (fun it => (it.internalState.memoizedLeft, (it.internalState.left.finitelyManySkips, it.internalState.right.finitelyManySkips))) |
| 250 | + |
| 251 | +theorem Zip.rel₃_of_memoizedLeft [Productive α₁ m] [Productive α₂ m] {it' it : IterM (α := Zip α₁ m α₂ β₂) m (β₁ × β₂)} |
| 252 | + (h : lt_with_top emptyRelation it'.internalState.memoizedLeft it.internalState.memoizedLeft) : |
| 253 | + Zip.Rel₃ m it' it := |
| 254 | + Prod.Lex.left _ _ h |
| 255 | + |
| 256 | +theorem Zip.rel₃_of_left [Productive α₁ m] [Productive α₂ m] |
| 257 | + {left' left : IterM (α := α₁) m β₁} {b} {right' right : IterM (α := α₂) m β₂} |
| 258 | + (h : left'.finitelyManySkips.Rel left.finitelyManySkips) : |
| 259 | + Zip.Rel₃ m ⟨left', b, right'⟩ ⟨left, b, right⟩ := |
| 260 | + Prod.Lex.right _ <| Prod.Lex.left _ _ h |
| 261 | + |
| 262 | +theorem Zip.rel₃_of_right [Productive α₁ m] [Productive α₂ m] |
| 263 | + {left : IterM (α := α₁) m β₁} {b b' : _} {it' it : IterM (α := α₂) m β₂} |
| 264 | + (h : b' = b) |
| 265 | + (h' : it'.finitelyManySkips.Rel it.finitelyManySkips) : |
| 266 | + Zip.Rel₃ m ⟨left, b', it'⟩ ⟨left, b, it⟩ := by |
| 267 | + cases h |
| 268 | + exact Prod.Lex.right _ <| Prod.Lex.right _ h' |
| 269 | + |
| 270 | +def Zip.instProductivenessRelation [Monad m] [Productive α₁ m] [Productive α₂ m] : |
| 271 | + ProductivenessRelation (Zip α₁ m α₂ β₂) m where |
| 272 | + rel := Zip.Rel₃ m |
| 273 | + wf := by |
| 274 | + apply InvImage.wf |
| 275 | + refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩ |
| 276 | + · apply Zip.wellFounded_lt_with_top |
| 277 | + exact emptyWf.wf |
| 278 | + · refine ⟨fun (a, b) => Prod.lexAccessible (WellFounded.apply ?_ a) (WellFounded.apply ?_) b⟩ |
| 279 | + · exact WellFoundedRelation.wf |
| 280 | + · exact WellFoundedRelation.wf |
| 281 | + subrelation {it it'} h := by |
| 282 | + cases h |
| 283 | + case yieldLeft hm it' out hp => |
| 284 | + apply Zip.rel₃_of_memoizedLeft |
| 285 | + simp [lt_with_top, hm] |
| 286 | + case skipLeft hm it' hp => |
| 287 | + obtain ⟨⟨left, memoizedLeft, right⟩⟩ := it |
| 288 | + simp only at hm |
| 289 | + rw [hm] |
| 290 | + apply Zip.rel₃_of_left |
| 291 | + exact IterM.TerminationMeasures.Productive.rel_of_skip ‹_› |
| 292 | + case skipRight out₁ hm it₂' hp => |
| 293 | + apply Zip.rel₃_of_right |
| 294 | + · simp_all |
| 295 | + · exact IterM.TerminationMeasures.Productive.rel_of_skip ‹_› |
| 296 | + |
| 297 | +instance Zip.instProductive [Monad m] [Productive α₁ m] [Productive α₂ m] : |
| 298 | + Productive (Zip α₁ m α₂ β₂) m := |
| 299 | + Productive.of_productivenessRelation Zip.instProductivenessRelation |
| 300 | + |
| 301 | +instance Zip.instIteratorCollect [Monad m] [Monad n] : |
| 302 | + IteratorCollect (Zip α₁ m α₂ β₂) m n := |
| 303 | + .defaultImplementation |
| 304 | + |
| 305 | +instance Zip.instIteratorCollectPartial [Monad m] [Monad n] : |
| 306 | + IteratorCollectPartial (Zip α₁ m α₂ β₂) m n := |
| 307 | + .defaultImplementation |
| 308 | + |
| 309 | +instance Zip.instIteratorLoop [Monad m] [Monad n] : |
| 310 | + IteratorLoop (Zip α₁ m α₂ β₂) m n := |
| 311 | + .defaultImplementation |
| 312 | + |
| 313 | +instance Zip.instIteratorLoopPartial [Monad m] [Monad n] : |
| 314 | + IteratorLoopPartial (Zip α₁ m α₂ β₂) m n := |
| 315 | + .defaultImplementation |
| 316 | + |
| 317 | +end Std.Iterators |
0 commit comments