l3lab/ntp-mathlib huggingface dataset:
theorem NodupKeys.kunion (nd₁ : l₁.NodupKeys) (nd₂ : l₂.NodupKeys) : (kunion l₁ l₂).NodupKeys := by
  induction l₁ generalizing l₂ with
  | nil => simp only [nil_kunion, nd₂]
  | cons s l₁ ih =>
    simp? at nd₁ says 

Proof state:
case cons
α : Type u
β : α → Type v
l : List (Sigma β)
inst✝ : DecidableEq α
s : Sigma β
l₁ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, NodupKeys l₁ → NodupKeys l₂ → NodupKeys (List.kunion l₁ l₂)
l₂ : List (Sigma β)
nd₁ : NodupKeys (s :: l₁)
nd₂ : NodupKeys l₂
⊢ NodupKeys (List.kunion (s :: l₁) l₂)

Next tactic:
simp only [nodupKeys_cons] at nd₁
theorem NodupKeys.kunion (nd₁ : l₁.NodupKeys) (nd₂ : l₂.NodupKeys) : (kunion l₁ l₂).NodupKeys := by
  induction l₁ generalizing l₂ with
  | nil => simp only [nil_kunion, nd₂]
  | cons s l₁ ih =>
    simp? at nd₁ says simp only [nodupKeys_cons] at nd₁
    

Proof state:
case cons
α : Type u
β : α → Type v
l : List (Sigma β)
inst✝ : DecidableEq α
s : Sigma β
l₁ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, NodupKeys l₁ → NodupKeys l₂ → NodupKeys (List.kunion l₁ l₂)
l₂ : List (Sigma β)
nd₂ : NodupKeys l₂
nd₁ : s.fst ∉ keys l₁ ∧ NodupKeys l₁
⊢ NodupKeys (List.kunion (s :: l₁) l₂)

Next tactic:
simp [not_or, nd₁.1, nd₂, ih nd₁.2 (nd₂.kerase s.1)]
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  

Proof state:
α : Type u
β : α → Type v
l✝ l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
p : l₁ ~ l₂
l : List (Sigma β)
⊢ kunion l₁ l ~ kunion l₂ l

Next tactic:
induction p generalizing l with
  | nil => rfl
  | cons hd _ ih =>
    simp [ih (List.kerase _ _), Perm.cons]
  | swap s₁ s₂ l => simp [kerase_comm, Perm.swap]
  | trans _ _ ih₁₂ ih₂₃ => exact Perm.trans (ih₁₂ l) (ih₂₃ l)
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  

Proof state:
case nil
α : Type u
β : α → Type v
l✝ l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ l : List (Sigma β)
⊢ kunion [] l ~ kunion [] l

Next tactic:
| nil => rfl
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => 

Proof state:
case nil
α : Type u
β : α → Type v
l✝ l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ l : List (Sigma β)
⊢ kunion [] l ~ kunion [] l

Next tactic:
rfl
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => rfl
  

Proof state:
case cons
α : Type u
β : α → Type v
l✝ l₁✝¹ l₂✝¹ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
hd : Sigma β
l₁✝ l₂✝ : List (Sigma β)
a✝ : l₁✝ ~ l₂✝
ih : ∀ (l : List (Sigma β)), kunion l₁✝ l ~ kunion l₂✝ l
l : List (Sigma β)
⊢ kunion (hd :: l₁✝) l ~ kunion (hd :: l₂✝) l

Next tactic:
| cons hd _ ih =>
    simp [ih (List.kerase _ _), Perm.cons]
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => rfl
  | cons hd _ ih =>
    

Proof state:
case cons
α : Type u
β : α → Type v
l✝ l₁✝¹ l₂✝¹ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
hd : Sigma β
l₁✝ l₂✝ : List (Sigma β)
a✝ : l₁✝ ~ l₂✝
ih : ∀ (l : List (Sigma β)), kunion l₁✝ l ~ kunion l₂✝ l
l : List (Sigma β)
⊢ kunion (hd :: l₁✝) l ~ kunion (hd :: l₂✝) l

Next tactic:
simp [ih (List.kerase _ _), Perm.cons]
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => rfl
  | cons hd _ ih =>
    simp [ih (List.kerase _ _), Perm.cons]
  

Proof state:
case swap
α : Type u
β : α → Type v
l✝¹ l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
s₁ s₂ : Sigma β
l✝ : List (Sigma β)
l : List (Sigma β)
⊢ kunion (s₂ :: s₁ :: l✝) l ~ kunion (s₁ :: s₂ :: l✝) l

Next tactic:
| swap s₁ s₂ l => simp [kerase_comm, Perm.swap]
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => rfl
  | cons hd _ ih =>
    simp [ih (List.kerase _ _), Perm.cons]
  | swap s₁ s₂ l => 

Proof state:
case swap
α : Type u
β : α → Type v
l✝¹ l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
s₁ s₂ : Sigma β
l✝ : List (Sigma β)
l : List (Sigma β)
⊢ kunion (s₂ :: s₁ :: l✝) l ~ kunion (s₁ :: s₂ :: l✝) l

Next tactic:
simp [kerase_comm, Perm.swap]
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => rfl
  | cons hd _ ih =>
    simp [ih (List.kerase _ _), Perm.cons]
  | swap s₁ s₂ l => simp [kerase_comm, Perm.swap]
  

Proof state:
case trans
α : Type u
β : α → Type v
l✝ l₁✝¹ l₂✝¹ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
l₁✝ l₂✝ l₃✝ : List (Sigma β)
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
ih₁₂ : ∀ (l : List (Sigma β)), kunion l₁✝ l ~ kunion l₂✝ l
ih₂₃ : ∀ (l : List (Sigma β)), kunion l₂✝ l ~ kunion l₃✝ l
l : List (Sigma β)
⊢ kunion l₁✝ l ~ kunion l₃✝ l

Next tactic:
| trans _ _ ih₁₂ ih₂₃ => exact Perm.trans (ih₁₂ l) (ih₂₃ l)
theorem Perm.kunion_right {l₁ l₂ : List (Sigma β)} (p : l₁ ~ l₂) (l) :
    kunion l₁ l ~ kunion l₂ l := by
  induction p generalizing l with
  | nil => rfl
  | cons hd _ ih =>
    simp [ih (List.kerase _ _), Perm.cons]
  | swap s₁ s₂ l => simp [kerase_comm, Perm.swap]
  | trans _ _ ih₁₂ ih₂₃ => 

Proof state:
case trans
α : Type u
β : α → Type v
l✝ l₁✝¹ l₂✝¹ : List (Sigma β)
inst✝ : DecidableEq α
l₁ l₂ : List (Sigma β)
l₁✝ l₂✝ l₃✝ : List (Sigma β)
a✝¹ : l₁✝ ~ l₂✝
a✝ : l₂✝ ~ l₃✝
ih₁₂ : ∀ (l : List (Sigma β)), kunion l₁✝ l ~ kunion l₂✝ l
ih₂₃ : ∀ (l : List (Sigma β)), kunion l₂✝ l ~ kunion l₃✝ l
l : List (Sigma β)
⊢ kunion l₁✝ l ~ kunion l₃✝ l

Next tactic:
exact Perm.trans (ih₁₂ l) (ih₂₃ l)
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  

Proof state:
α : Type u
β : α → Type v
l l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
l₁ l₂ : List (Sigma β)
h : a ∈ keys l₁
⊢ dlookup a (kunion l₁ l₂) = dlookup a l₁

Next tactic:
induction' l₁ with s _ ih generalizing l₂
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> 

Proof state:
case nil
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
l₂ : List (Sigma β)
h : a ∈ keys []
⊢ dlookup a (kunion [] l₂) = dlookup a []

Next tactic:
simp at h
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> 

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
s : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys (s :: tail✝)
⊢ dlookup a (kunion (s :: tail✝) l₂) = dlookup a (s :: tail✝)

Next tactic:
simp at h
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; 

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
s : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a = s.fst ∨ a ∈ keys tail✝
⊢ dlookup a (kunion (s :: tail✝) l₂) = dlookup a (s :: tail✝)

Next tactic:
cases' h with h h
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> 

Proof state:
case cons.inl
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
s : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a = s.fst
⊢ dlookup a (kunion (s :: tail✝) l₂) = dlookup a (s :: tail✝)

Next tactic:
cases' s with a'
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> 

Proof state:
case cons.inr
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
s : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys tail✝
⊢ dlookup a (kunion (s :: tail✝) l₂) = dlookup a (s :: tail✝)

Next tactic:
cases' s with a'
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · 

Proof state:
case cons.inl.mk
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
a' : α
snd✝ : β a'
h : a = { fst := a', snd := snd✝ }.fst
⊢ dlookup a (kunion ({ fst := a', snd := snd✝ } :: tail✝) l₂) = dlookup a ({ fst := a', snd := snd✝ } :: tail✝)

Next tactic:
subst h
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · subst h
    

Proof state:
case cons.inl.mk
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
snd✝ : β a
⊢ dlookup a (kunion ({ fst := a, snd := snd✝ } :: tail✝) l₂) = dlookup a ({ fst := a, snd := snd✝ } :: tail✝)

Next tactic:
simp
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · subst h
    simp
  · 

Proof state:
case cons.inr.mk
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys tail✝
a' : α
snd✝ : β a'
⊢ dlookup a (kunion ({ fst := a', snd := snd✝ } :: tail✝) l₂) = dlookup a ({ fst := a', snd := snd✝ } :: tail✝)

Next tactic:
rw [kunion_cons]
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · subst h
    simp
  · rw [kunion_cons]
    

Proof state:
case cons.inr.mk
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys tail✝
a' : α
snd✝ : β a'
⊢ dlookup a ({ fst := a', snd := snd✝ } :: kunion tail✝ (kerase { fst := a', snd := snd✝ }.fst l₂)) =
    dlookup a ({ fst := a', snd := snd✝ } :: tail✝)

Next tactic:
by_cases h' : a = a'
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · subst h
    simp
  · rw [kunion_cons]
    by_cases h' : a = a'
    · 

Proof state:
case pos
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys tail✝
a' : α
snd✝ : β a'
h' : a = a'
⊢ dlookup a ({ fst := a', snd := snd✝ } :: kunion tail✝ (kerase { fst := a', snd := snd✝ }.fst l₂)) =
    dlookup a ({ fst := a', snd := snd✝ } :: tail✝)

Next tactic:
subst h'
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · subst h
    simp
  · rw [kunion_cons]
    by_cases h' : a = a'
    · subst h'
      

Proof state:
case pos
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys tail✝
snd✝ : β a
⊢ dlookup a ({ fst := a, snd := snd✝ } :: kunion tail✝ (kerase { fst := a, snd := snd✝ }.fst l₂)) =
    dlookup a ({ fst := a, snd := snd✝ } :: tail✝)

Next tactic:
simp
@[simp]
theorem dlookup_kunion_left {a} {l₁ l₂ : List (Sigma β)} (h : a ∈ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₁ := by
  induction' l₁ with s _ ih generalizing l₂ <;> simp at h; cases' h with h h <;> cases' s with a'
  · subst h
    simp
  · rw [kunion_cons]
    by_cases h' : a = a'
    · subst h'
      simp
    · 

Proof state:
case neg
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∈ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a tail✝
l₂ : List (Sigma β)
h : a ∈ keys tail✝
a' : α
snd✝ : β a'
h' : ¬a = a'
⊢ dlookup a ({ fst := a', snd := snd✝ } :: kunion tail✝ (kerase { fst := a', snd := snd✝ }.fst l₂)) =
    dlookup a ({ fst := a', snd := snd✝ } :: tail✝)

Next tactic:
simp [h', ih h]
@[simp]
theorem dlookup_kunion_right {a} {l₁ l₂ : List (Sigma β)} (h : a ∉ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₂ := by
  

Proof state:
α : Type u
β : α → Type v
l l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
l₁ l₂ : List (Sigma β)
h : a ∉ keys l₁
⊢ dlookup a (kunion l₁ l₂) = dlookup a l₂

Next tactic:
induction l₁ generalizing l₂ with
  | nil => simp
  | cons _ _ ih => simp [not_or] at h; simp [h.1, ih h.2]
@[simp]
theorem dlookup_kunion_right {a} {l₁ l₂ : List (Sigma β)} (h : a ∉ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  

Proof state:
case nil
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
l₂ : List (Sigma β)
h : a ∉ keys []
⊢ dlookup a (kunion [] l₂) = dlookup a l₂

Next tactic:
| nil => simp
@[simp]
theorem dlookup_kunion_right {a} {l₁ l₂ : List (Sigma β)} (h : a ∉ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => 

Proof state:
case nil
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
l₂ : List (Sigma β)
h : a ∉ keys []
⊢ dlookup a (kunion [] l₂) = dlookup a l₂

Next tactic:
simp
@[simp]
theorem dlookup_kunion_right {a} {l₁ l₂ : List (Sigma β)} (h : a ∉ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
head✝ : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∉ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a l₂
l₂ : List (Sigma β)
h : a ∉ keys (head✝ :: tail✝)
⊢ dlookup a (kunion (head✝ :: tail✝) l₂) = dlookup a l₂

Next tactic:
| cons _ _ ih => simp [not_or] at h; simp [h.1, ih h.2]
@[simp]
theorem dlookup_kunion_right {a} {l₁ l₂ : List (Sigma β)} (h : a ∉ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons _ _ ih => 

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
head✝ : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∉ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a l₂
l₂ : List (Sigma β)
h : a ∉ keys (head✝ :: tail✝)
⊢ dlookup a (kunion (head✝ :: tail✝) l₂) = dlookup a l₂

Next tactic:
simp [not_or] at h
@[simp]
theorem dlookup_kunion_right {a} {l₁ l₂ : List (Sigma β)} (h : a ∉ l₁.keys) :
    dlookup a (kunion l₁ l₂) = dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons _ _ ih => simp [not_or] at h; 

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
head✝ : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, a ∉ keys tail✝ → dlookup a (kunion tail✝ l₂) = dlookup a l₂
l₂ : List (Sigma β)
h : ¬a = head✝.fst ∧ a ∉ keys tail✝
⊢ dlookup a (kunion (head✝ :: tail✝) l₂) = dlookup a l₂

Next tactic:
simp [h.1, ih h.2]
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  

Proof state:
α : Type u
β : α → Type v
l l₁✝ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
l₁ l₂ : List (Sigma β)
⊢ b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ keys l₁ ∧ b ∈ dlookup a l₂

Next tactic:
induction l₁ generalizing l₂ with
  | nil => simp
  | cons s _ ih =>
    cases' s with a'
    by_cases h₁ : a = a'
    · subst h₁
      simp
    · let h₂ := @ih (kerase a' l₂)
      simp? [h₁] at h₂ says
        simp only [Option.mem_def, ne_eq, h₁, not_false_eq_true, dlookup_kerase_ne] at h₂
      simp [h₁, h₂]
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  

Proof state:
case nil
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
l₂ : List (Sigma β)
⊢ b ∈ dlookup a (kunion [] l₂) ↔ b ∈ dlookup a [] ∨ a ∉ keys [] ∧ b ∈ dlookup a l₂

Next tactic:
| nil => simp
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => 

Proof state:
case nil
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
l₂ : List (Sigma β)
⊢ b ∈ dlookup a (kunion [] l₂) ↔ b ∈ dlookup a [] ∨ a ∉ keys [] ∧ b ∈ dlookup a l₂

Next tactic:
simp
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
s : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, b ∈ dlookup a (kunion tail✝ l₂) ↔ b ∈ dlookup a tail✝ ∨ a ∉ keys tail✝ ∧ b ∈ dlookup a l₂
l₂ : List (Sigma β)
⊢ b ∈ dlookup a (kunion (s :: tail✝) l₂) ↔ b ∈ dlookup a (s :: tail✝) ∨ a ∉ keys (s :: tail✝) ∧ b ∈ dlookup a l₂

Next tactic:
| cons s _ ih =>
    cases' s with a'
    by_cases h₁ : a = a'
    · subst h₁
      simp
    · let h₂ := @ih (kerase a' l₂)
      simp? [h₁] at h₂ says
        simp only [Option.mem_def, ne_eq, h₁, not_false_eq_true, dlookup_kerase_ne] at h₂
      simp [h₁, h₂]
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons s _ ih =>
    

Proof state:
case cons
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
s : Sigma β
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, b ∈ dlookup a (kunion tail✝ l₂) ↔ b ∈ dlookup a tail✝ ∨ a ∉ keys tail✝ ∧ b ∈ dlookup a l₂
l₂ : List (Sigma β)
⊢ b ∈ dlookup a (kunion (s :: tail✝) l₂) ↔ b ∈ dlookup a (s :: tail✝) ∨ a ∉ keys (s :: tail✝) ∧ b ∈ dlookup a l₂

Next tactic:
cases' s with a'
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons s _ ih =>
    cases' s with a'
    

Proof state:
case cons.mk
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, b ∈ dlookup a (kunion tail✝ l₂) ↔ b ∈ dlookup a tail✝ ∨ a ∉ keys tail✝ ∧ b ∈ dlookup a l₂
l₂ : List (Sigma β)
a' : α
snd✝ : β a'
⊢ b ∈ dlookup a (kunion ({ fst := a', snd := snd✝ } :: tail✝) l₂) ↔
    b ∈ dlookup a ({ fst := a', snd := snd✝ } :: tail✝) ∨
      a ∉ keys ({ fst := a', snd := snd✝ } :: tail✝) ∧ b ∈ dlookup a l₂

Next tactic:
by_cases h₁ : a = a'
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons s _ ih =>
    cases' s with a'
    by_cases h₁ : a = a'
    · 

Proof state:
case pos
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, b ∈ dlookup a (kunion tail✝ l₂) ↔ b ∈ dlookup a tail✝ ∨ a ∉ keys tail✝ ∧ b ∈ dlookup a l₂
l₂ : List (Sigma β)
a' : α
snd✝ : β a'
h₁ : a = a'
⊢ b ∈ dlookup a (kunion ({ fst := a', snd := snd✝ } :: tail✝) l₂) ↔
    b ∈ dlookup a ({ fst := a', snd := snd✝ } :: tail✝) ∨
      a ∉ keys ({ fst := a', snd := snd✝ } :: tail✝) ∧ b ∈ dlookup a l₂

Next tactic:
subst h₁
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons s _ ih =>
    cases' s with a'
    by_cases h₁ : a = a'
    · subst h₁
      

Proof state:
case pos
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, b ∈ dlookup a (kunion tail✝ l₂) ↔ b ∈ dlookup a tail✝ ∨ a ∉ keys tail✝ ∧ b ∈ dlookup a l₂
l₂ : List (Sigma β)
snd✝ : β a
⊢ b ∈ dlookup a (kunion ({ fst := a, snd := snd✝ } :: tail✝) l₂) ↔
    b ∈ dlookup a ({ fst := a, snd := snd✝ } :: tail✝) ∨
      a ∉ keys ({ fst := a, snd := snd✝ } :: tail✝) ∧ b ∈ dlookup a l₂

Next tactic:
simp
theorem mem_dlookup_kunion {a} {b : β a} {l₁ l₂ : List (Sigma β)} :
    b ∈ dlookup a (kunion l₁ l₂) ↔ b ∈ dlookup a l₁ ∨ a ∉ l₁.keys ∧ b ∈ dlookup a l₂ := by
  induction l₁ generalizing l₂ with
  | nil => simp
  | cons s _ ih =>
    cases' s with a'
    by_cases h₁ : a = a'
    · subst h₁
      simp
    · 

Proof state:
case neg
α : Type u
β : α → Type v
l l₁ l₂✝ : List (Sigma β)
inst✝ : DecidableEq α
a : α
b : β a
tail✝ : List (Sigma β)
ih : ∀ {l₂ : List (Sigma β)}, b ∈ dlookup a (kunion tail✝ l₂) ↔ b ∈ dlookup a tail✝ ∨ a ∉ keys tail✝ ∧ b ∈ dlookup a l₂
l₂ : List (Sigma β)
a' : α
snd✝ : β a'
h₁ : ¬a = a'
⊢ b ∈ dlookup a (kunion ({ fst := a', snd := snd✝ } :: tail✝) l₂) ↔
    b ∈ dlookup a ({ fst := a', snd := snd✝ } :: tail✝) ∨
      a ∉ keys ({ fst := a', snd := snd✝ } :: tail✝) ∧ b ∈ dlookup a l₂

Next tactic:
let h₂ := @ih (kerase a' l₂)