l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem union_empty {s : AList β} : s ∪ (∅ : AList β) = s :=
  ext <| by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s : AList β
⊢ (s ∪ ∅).entries = s.entries

Next tactic:
simp
theorem perm_union {s₁ s₂ s₃ s₄ : AList β} (p₁₂ : s₁.entries ~ s₂.entries)
    (p₃₄ : s₃.entries ~ s₄.entries) : (s₁ ∪ s₃).entries ~ (s₂ ∪ s₄).entries := by
  

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ s₄ : AList β
p₁₂ : s₁.entries ~ s₂.entries
p₃₄ : s₃.entries ~ s₄.entries
⊢ (s₁ ∪ s₃).entries ~ (s₂ ∪ s₄).entries

Next tactic:
simp [p₁₂.kunion s₃.nodupKeys p₃₄]
theorem insert_union {a} {b : β a} {s₁ s₂ : AList β} : insert a b (s₁ ∪ s₂) = insert a b s₁ ∪ s₂ :=
  by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s₁ s₂ : AList β
⊢ insert a b (s₁ ∪ s₂) = insert a b s₁ ∪ s₂

Next tactic:
ext
theorem insert_union {a} {b : β a} {s₁ s₂ : AList β} : insert a b (s₁ ∪ s₂) = insert a b s₁ ∪ s₂ :=
  by ext; 

Proof state:
case a.a.a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
a : α
b : β a
s₁ s₂ : AList β
n✝ : ℕ
a✝ : Sigma β
⊢ a✝ ∈ get? (insert a b (s₁ ∪ s₂)).entries n✝ ↔ a✝ ∈ get? (insert a b s₁ ∪ s₂).entries n✝

Next tactic:
simp
theorem union_assoc {s₁ s₂ s₃ : AList β} : (s₁ ∪ s₂ ∪ s₃).entries ~ (s₁ ∪ (s₂ ∪ s₃)).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ s₃ : AList β
⊢ ∀ (x : α) (y : β x), y ∈ dlookup x (s₁ ∪ s₂ ∪ s₃).entries ↔ y ∈ dlookup x (s₁ ∪ (s₂ ∪ s₃)).entries

Next tactic:
simp [not_or, or_assoc, and_or_left, and_assoc]
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
⊢ ∀ (x : α) (y : β x), y ∈ dlookup x (s₁ ∪ s₂).entries ↔ y ∈ dlookup x (s₂ ∪ s₁).entries

Next tactic:
intros
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; 

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
⊢ y✝ ∈ dlookup x✝ (s₁ ∪ s₂).entries ↔ y✝ ∈ dlookup x✝ (s₂ ∪ s₁).entries

Next tactic:
simp
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      

Proof state:
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
⊢ dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝ ↔
    dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝

Next tactic:
constructor
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> 

Proof state:
case mp
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
⊢ dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝ →
    dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝

Next tactic:
intro h'
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> 

Proof state:
case mpr
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
⊢ dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝ →
    dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝

Next tactic:
intro h'
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · 

Proof state:
case mp
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝
⊢ dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝

Next tactic:
cases' h' with h' h'
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · 

Proof state:
case mp.inl
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₁.entries = some y✝
⊢ dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝

Next tactic:
right
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          

Proof state:
case mp.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₁.entries = some y✝
⊢ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝

Next tactic:
refine' ⟨_, h'⟩
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          

Proof state:
case mp.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₁.entries = some y✝
⊢ x✝ ∉ List.keys s₂.entries

Next tactic:
apply h
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          

Proof state:
case mp.inl.h.a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₁.entries = some y✝
⊢ x✝ ∈ keys s₁

Next tactic:
rw [keys, ← List.dlookup_isSome, h']
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          

Proof state:
case mp.inl.h.a
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₁.entries = some y✝
⊢ Option.isSome (some y✝) = true

Next tactic:
exact rfl
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · 

Proof state:
case mp.inr
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝
⊢ dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝

Next tactic:
left
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          

Proof state:
case mp.inr.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝
⊢ dlookup x✝ s₂.entries = some y✝

Next tactic:
rw [h'.2]
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · 

Proof state:
case mpr
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝ ∨ x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝
⊢ dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝

Next tactic:
cases' h' with h' h'
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · 

Proof state:
case mpr.inl
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝
⊢ dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝

Next tactic:
right
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          

Proof state:
case mpr.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝
⊢ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝

Next tactic:
refine' ⟨_, h'⟩
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          

Proof state:
case mpr.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝
⊢ x✝ ∉ List.keys s₁.entries

Next tactic:
intro h''
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          intro h''
          

Proof state:
case mpr.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝
h'' : x✝ ∈ List.keys s₁.entries
⊢ False

Next tactic:
apply h _ h''
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          intro h''
          apply h _ h''
          

Proof state:
case mpr.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝
h'' : x✝ ∈ List.keys s₁.entries
⊢ x✝ ∈ keys s₂

Next tactic:
rw [keys, ← List.dlookup_isSome, h']
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          intro h''
          apply h _ h''
          rw [keys, ← List.dlookup_isSome, h']
          

Proof state:
case mpr.inl.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : dlookup x✝ s₂.entries = some y✝
h'' : x✝ ∈ List.keys s₁.entries
⊢ Option.isSome (some y✝) = true

Next tactic:
exact rfl
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          intro h''
          apply h _ h''
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · 

Proof state:
case mpr.inr
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝
⊢ dlookup x✝ s₁.entries = some y✝ ∨ x✝ ∉ List.keys s₁.entries ∧ dlookup x✝ s₂.entries = some y✝

Next tactic:
left
theorem union_comm_of_disjoint {s₁ s₂ : AList β} (h : Disjoint s₁ s₂) :
    (s₁ ∪ s₂).entries ~ (s₂ ∪ s₁).entries :=
  lookup_ext (AList.nodupKeys _) (AList.nodupKeys _)
    (by
      intros; simp
      constructor <;> intro h'
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          apply h
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          rw [h'.2]
      · cases' h' with h' h'
        · right
          refine' ⟨_, h'⟩
          intro h''
          apply h _ h''
          rw [keys, ← List.dlookup_isSome, h']
          exact rfl
        · left
          

Proof state:
case mpr.inr.h
α : Type u
β : α → Type v
inst✝ : DecidableEq α
s₁ s₂ : AList β
h : Disjoint s₁ s₂
x✝ : α
y✝ : β x✝
h' : x✝ ∉ List.keys s₂.entries ∧ dlookup x✝ s₁.entries = some y✝
⊢ dlookup x✝ s₁.entries = some y✝

Next tactic:
rw [h'.2]
theorem degrees_neg (p : MvPolynomial σ R) : (-p).degrees = p.degrees := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p✝ q p : MvPolynomial σ R
⊢ degrees (-p) = degrees p

Next tactic:
rw [degrees, support_neg]
theorem degrees_neg (p : MvPolynomial σ R) : (-p).degrees = p.degrees := by
  rw [degrees, support_neg]; 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p✝ q p : MvPolynomial σ R
⊢ (Finset.sup (support p) fun s => toMultiset s) = degrees p

Next tactic:
rfl
theorem degrees_sub [DecidableEq σ] (p q : MvPolynomial σ R) :
    (p - q).degrees ≤ p.degrees ⊔ q.degrees := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p✝ q✝ : MvPolynomial σ R
inst✝ : DecidableEq σ
p q : MvPolynomial σ R
⊢ degrees (p - q) ≤ degrees p ⊔ degrees q

Next tactic:
simpa only [sub_eq_add_neg] using le_trans (degrees_add p (-q)) (by rw [degrees_neg])
theorem degrees_sub [DecidableEq σ] (p q : MvPolynomial σ R) :
    (p - q).degrees ≤ p.degrees ⊔ q.degrees := by
  simpa only [sub_eq_add_neg] using le_trans (degrees_add p (-q)) (by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p✝ q✝ : MvPolynomial σ R
inst✝ : DecidableEq σ
p q : MvPolynomial σ R
⊢ degrees p ⊔ degrees (-q) ≤ degrees p ⊔ degrees q

Next tactic:
rw [degrees_neg]
@[simp]
theorem vars_neg : (-p).vars = p.vars := by 

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝ : CommRing R
p q : MvPolynomial σ R
⊢ vars (-p) = vars p

Next tactic:
simp [vars, degrees_neg]
theorem vars_sub_subset [DecidableEq σ] : (p - q).vars ⊆ p.vars ∪ q.vars := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
⊢ vars (p - q) ⊆ vars p ∪ vars q

Next tactic:
convert vars_add_subset p (-q) using 2
theorem vars_sub_subset [DecidableEq σ] : (p - q).vars ⊆ p.vars ∪ q.vars := by
  convert vars_add_subset p (-q) using 2 <;> 

Proof state:
case h.e'_3.h.e'_4
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
⊢ p - q = p + -q

Next tactic:
simp [sub_eq_add_neg]
theorem vars_sub_subset [DecidableEq σ] : (p - q).vars ⊆ p.vars ∪ q.vars := by
  convert vars_add_subset p (-q) using 2 <;> 

Proof state:
case h.e'_4.h.e'_4
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
⊢ vars q = vars (-q)

Next tactic:
simp [sub_eq_add_neg]
@[simp]
theorem vars_sub_of_disjoint [DecidableEq σ] (hpq : Disjoint p.vars q.vars) :
    (p - q).vars = p.vars ∪ q.vars := by
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
hpq : Disjoint (vars p) (vars q)
⊢ vars (p - q) = vars p ∪ vars q

Next tactic:
rw [← vars_neg q] at hpq
@[simp]
theorem vars_sub_of_disjoint [DecidableEq σ] (hpq : Disjoint p.vars q.vars) :
    (p - q).vars = p.vars ∪ q.vars := by
  rw [← vars_neg q] at hpq
  

Proof state:
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
hpq : Disjoint (vars p) (vars (-q))
⊢ vars (p - q) = vars p ∪ vars q

Next tactic:
convert vars_add_of_disjoint hpq using 2
@[simp]
theorem vars_sub_of_disjoint [DecidableEq σ] (hpq : Disjoint p.vars q.vars) :
    (p - q).vars = p.vars ∪ q.vars := by
  rw [← vars_neg q] at hpq
  convert vars_add_of_disjoint hpq using 2 <;> 

Proof state:
case h.e'_2.h.e'_4
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
hpq : Disjoint (vars p) (vars (-q))
⊢ p - q = p + -q

Next tactic:
simp [sub_eq_add_neg]
@[simp]
theorem vars_sub_of_disjoint [DecidableEq σ] (hpq : Disjoint p.vars q.vars) :
    (p - q).vars = p.vars ∪ q.vars := by
  rw [← vars_neg q] at hpq
  convert vars_add_of_disjoint hpq using 2 <;> 

Proof state:
case h.e'_3.h.e'_4
R : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R
p q : MvPolynomial σ R
inst✝ : DecidableEq σ
hpq : Disjoint (vars p) (vars (-q))
⊢ vars q = vars (-q)

Next tactic:
simp [sub_eq_add_neg]
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p q : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x : MvPolynomial R ℤ
⊢ eval₂ c (⇑f ∘ X) x = f x

Next tactic:
apply MvPolynomial.induction_on x
    (fun n => by
      rw [hom_C f, eval₂_C]
      exact eq_intCast c n)
    (fun p q hp hq => by
      rw [eval₂_add, hp, hq]
      exact (f.map_add _ _).symm)
    (fun p n hp => by
      rw [eval₂_mul, eval₂_X, hp]
      exact (f.map_mul _ _).symm)
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  apply MvPolynomial.induction_on x
    (fun n => by
      

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n✝ m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p q : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x : MvPolynomial R ℤ
n : ℤ
⊢ eval₂ c (⇑f ∘ X) (C n) = f (C n)

Next tactic:
rw [hom_C f, eval₂_C]
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  apply MvPolynomial.induction_on x
    (fun n => by
      rw [hom_C f, eval₂_C]
      

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n✝ m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p q : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x : MvPolynomial R ℤ
n : ℤ
⊢ c n = ↑n

Next tactic:
exact eq_intCast c n
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  apply MvPolynomial.induction_on x
    (fun n => by
      rw [hom_C f, eval₂_C]
      exact eq_intCast c n)
    (fun p q hp hq => by
      

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p✝ q✝ : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x p q : MvPolynomial R ℤ
hp : eval₂ c (⇑f ∘ X) p = f p
hq : eval₂ c (⇑f ∘ X) q = f q
⊢ eval₂ c (⇑f ∘ X) (p + q) = f (p + q)

Next tactic:
rw [eval₂_add, hp, hq]
/-- A ring homomorphism f : Z[X_1, X_2, ...] → R
is determined by the evaluations f(X_1), f(X_2), ... -/
@[simp]
theorem eval₂Hom_X {R : Type u} (c : ℤ →+* S) (f : MvPolynomial R ℤ →+* S) (x : MvPolynomial R ℤ) :
    eval₂ c (f ∘ X) x = f x := by
  apply MvPolynomial.induction_on x
    (fun n => by
      rw [hom_C f, eval₂_C]
      exact eq_intCast c n)
    (fun p q hp hq => by
      rw [eval₂_add, hp, hq]
      

Proof state:
R✝ : Type u
S : Type v
σ : Type u_1
a a' a₁ a₂ : R✝
e : ℕ
n m : σ
s : σ →₀ ℕ
inst✝¹ : CommRing R✝
p✝ q✝ : MvPolynomial σ R✝
inst✝ : CommRing S
f✝ : R✝ →+* S
g : σ → S
R : Type u
c : ℤ →+* S
f : MvPolynomial R ℤ →+* S
x p q : MvPolynomial R ℤ
hp : eval₂ c (⇑f ∘ X) p = f p
hq : eval₂ c (⇑f ∘ X) q = f q
⊢ f p + f q = f (p + q)

Next tactic:
exact (f.map_add _ _).symm