Zulip Chat Archive

Stream: new members

Topic: addList_assoc


Iocta (Jun 29 2024 at 21:38):

Am I on the right track here? How can I finish?

import Mathlib

def addOptionAll [Semiring α] : Option α  Option α  α
  | none, none => 0
  | none, some y => y
  | some x, none => x
  | some x, some y => x + y

lemma addOptionAll_assoc [Semiring α] (ma mb mc : Option α) :
  addOptionAll (some (addOptionAll ma mb)) mc = addOptionAll ma (some (addOptionAll mb mc)) := by
  unfold addOptionAll
  match ma, mb, mc with
  | none, none, none => simp only
  | some a, none, none => simp only [add_zero]
  | none, some b, none => simp only
  | some a, some b, none => simp only
  | none, none, some c => simp only [zero_add]
  | some a, none, some c => simp only
  | none, some b, some c => simp only
  | some a, some b, some c => simp only [add_assoc]


def addList [Semiring α] (xs ys : List α) : List α :=
  List.zipWithAll addOptionAll xs ys



lemma addList_assoc [Semiring α] (as bs cs : List α) :
  addList (addList as bs) cs = addList as (addList bs cs) := by
  unfold addList
  induction as with
  | nil => {
    rw [List.zipWithAll,List.zipWithAll,]
    simp only [addOptionAll, List.map_id']
  }
  | cons a aa ih => {
    cases bs with
    | nil => {
      rw [List.zipWithAll, List.zipWithAll,]
      simp only [addOptionAll, List.map_cons, List.map_id']
    }
    | cons b bb => {
      rw [List.zipWithAll,]
      cases cs with
      | nil => {
        rw [List.zipWithAll]
        simp only [addOptionAll, List.map_cons, List.map_id', List.zipWithAll_nil_right,
          List.zipWithAll_cons_cons]
      }
      | cons c cc => {
        simp only [List.zipWithAll, addOptionAll, add_assoc, List.cons_inj] at *
        cases aa with
        | nil => {
          simp only [List.zipWithAll_nil_left, addOptionAll, List.map_cons, List.map_id',
            List.zipWithAll_cons_cons] at *
        }
        | cons head tail => {
          rw [List.zipWithAll, addOptionAll] at ih
          simp [List.zipWithAll_cons_cons, List.cons.injEq, addOptionAll] at *
          /-
          case cons.cons.cons.cons
          α : Type u_1
          inst✝ : Semiring α
          a b : α
          bb : List α
          c : α
          cc : List α
          head : α
          tail : List α
          ih : head + b + c = head + (b + c) ∧
            List.zipWithAll addOptionAll (List.zipWithAll addOptionAll tail bb) cc =
              List.zipWithAll addOptionAll tail (List.zipWithAll addOptionAll bb cc)
          ⊢ List.zipWithAll addOptionAll (List.zipWithAll addOptionAll (head :: tail) bb) cc =
            List.zipWithAll addOptionAll (head :: tail) (List.zipWithAll addOptionAll bb cc)
          -/
          sorry
        }
      }
    }
  }

Eric Wieser (Jun 29 2024 at 22:12):

You would have an easier time if your definition was x.getD 0 + y.getD 0

Iocta (Jun 29 2024 at 23:29):

Stuck in basically the same place.

def addD0 [Semiring α] (x y : Option α) : α :=
  (x.getD 0) + (y.getD 0)

lemma addD0_assoc [Semiring α] (ma mb mc : Option α) :
  addD0 (some (addD0 ma mb)) mc = addD0 ma (some (addD0 mb mc)) := by
  unfold addD0
  match ma, mb, mc with
  | none, none, none => simp only [Option.getD, add_zero]
  | some a, none, none => simp only [Option.getD_some, Option.getD_none, add_zero]
  | none, some b, none => simp only [Option.getD_none, Option.getD_some, zero_add, add_zero]
  | some a, some b, none => simp only [Option.getD_some, Option.getD_none, add_zero]
  | none, none, some c => simp only [Option.getD_none, add_zero, Option.getD_some, zero_add]
  | some a, none, some c => simp only [Option.getD_some, Option.getD_none, add_zero, zero_add]
  | none, some b, some c => simp only [Option.getD_none, Option.getD_some, zero_add]
  | some a, some b, some c => simp only [Option.getD_some, add_assoc]

def addList [Semiring α] : List α  List α  List α :=
  List.zipWithAll addD0

lemma addList_assoc [Semiring α] (as bs cs : List α) :
  addList (addList as bs) cs = addList as (addList bs cs) := by
  unfold addList
  induction as with
  | nil => simp only [List.zipWithAll, addD0, Option.getD_none, Option.getD_some, zero_add, List.map_id']
  | cons a aa ih => {
    cases bs with
    | nil => simp only [List.zipWithAll_nil_right, addD0, Option.getD_some, Option.getD_none, add_zero,
        List.map_id', List.zipWithAll_nil_left, zero_add, List.map_cons] at *
    | cons b bb => {
      simp only [List.zipWithAll_cons_cons, addD0, Option.getD]
      cases cs with
      | nil => simp only [List.zipWithAll, addD0, Option.getD_some, Option.getD_none, add_zero,
          List.map_cons, List.map_id']
      | cons c cc => {
        simp only [List.zipWithAll_cons_cons, List.cons.injEq] at *
        simp only [addD0, Option.getD_some] at *
        simp only [add_assoc, true_and]
        /-
        case cons.cons.cons
        α : Type u_1
        inst✝ : Semiring α
        a : α
        aa : List α
        b : α
        bb : List α
        c : α
        cc : List α
        ih : List.zipWithAll addD0 (List.zipWithAll addD0 aa (b :: bb)) (c :: cc) =
          List.zipWithAll addD0 aa ((b + c) :: List.zipWithAll addD0 bb cc)
        ⊢ List.zipWithAll addD0 (List.zipWithAll addD0 aa bb) cc = List.zipWithAll addD0 aa (List.zipWithAll addD0 bb cc)
        -/
      }
    }
  }

Going down yet another level doesn't seem likely.

import Mathlib

def addD0 [Semiring α] (x y : Option α) : α :=
  (x.getD 0) + (y.getD 0)

lemma addD0_assoc [Semiring α] (ma mb mc : Option α) :
  addD0 (some (addD0 ma mb)) mc = addD0 ma (some (addD0 mb mc)) := by
  unfold addD0
  match ma, mb, mc with
  | none, none, none => simp only [Option.getD, add_zero]
  | some a, none, none => simp only [Option.getD_some, Option.getD_none, add_zero]
  | none, some b, none => simp only [Option.getD_none, Option.getD_some, zero_add, add_zero]
  | some a, some b, none => simp only [Option.getD_some, Option.getD_none, add_zero]
  | none, none, some c => simp only [Option.getD_none, add_zero, Option.getD_some, zero_add]
  | some a, none, some c => simp only [Option.getD_some, Option.getD_none, add_zero, zero_add]
  | none, some b, some c => simp only [Option.getD_none, Option.getD_some, zero_add]
  | some a, some b, some c => simp only [Option.getD_some, add_assoc]

def addList [Semiring α] : List α  List α  List α :=
  List.zipWithAll addD0

lemma addList_assoc [Semiring α] (as bs cs : List α) :
  addList (addList as bs) cs = addList as (addList bs cs) := by
  unfold addList
  induction as with
  | nil => simp only [List.zipWithAll, addD0, Option.getD_none, Option.getD_some, zero_add, List.map_id']
  | cons a aa ih => {
    cases bs with
    | nil => simp only [List.zipWithAll_nil_right, addD0, Option.getD_some, Option.getD_none, add_zero,
        List.map_id', List.zipWithAll_nil_left, zero_add, List.map_cons] at *
    | cons b bb => {
      simp only [List.zipWithAll_cons_cons, addD0, Option.getD]
      cases cs with
      | nil => simp only [List.zipWithAll, addD0, Option.getD_some, Option.getD_none, add_zero,
          List.map_cons, List.map_id']
      | cons c cc => {
        simp only [List.zipWithAll_cons_cons, List.cons.injEq] at *
        simp only [addD0, Option.getD_some] at *
        simp only [add_assoc, true_and]
        cases aa with
        | nil => simp only [List.zipWithAll_nil_left, addD0, Option.getD_none, Option.getD_some, zero_add,
            List.map_cons, List.map_id', List.zipWithAll_cons_cons] at *
        | cons a' aa' => {
          simp [addD0, add_assoc] at *
          /-
          case cons.cons.cons.cons
          α : Type u_1
          inst✝ : Semiring α
          a b : α
          bb : List α
          c : α
          cc : List α
          a' : α
          aa' : List α
          ih : List.zipWithAll addD0 (List.zipWithAll addD0 aa' bb) cc = List.zipWithAll addD0 aa' (List.zipWithAll addD0 bb cc)
          ⊢ List.zipWithAll addD0 (List.zipWithAll addD0 (a' :: aa') bb) cc =
            List.zipWithAll addD0 (a' :: aa') (List.zipWithAll addD0 bb cc)
          -/
        }
      }
    }
  }

Daniel Weber (Jun 30 2024 at 06:02):

lemma addD0_assoc [Semiring α] (ma mb mc : Option α) :
  addD0 (some (addD0 ma mb)) mc = addD0 ma (some (addD0 mb mc)) := by
  unfold addD0
  rw [Option.getD_some, add_assoc]

works for addD0_assoc.

Markus Himmel (Jun 30 2024 at 06:51):

I would do it like this:

lemma addList_assoc [Semiring α] (as bs cs : List α) :
    addList (addList as bs) cs = addList as (addList bs cs) := by
  apply List.ext_get?
  intro n
  simp only [addList, List.zipWithAll_get?]
  cases as.get? n <;> cases bs.get? n <;> cases cs.get? n <;> simp [addD0, add_assoc]

Last updated: May 02 2025 at 03:31 UTC