Zulip Chat Archive

Stream: new members

Topic: Code review / What (things) am I doing wrong


Chris Ahn (Feb 02 2024 at 04:51):

I've been trying to write up the structure defined here; more specifically I've almost finished writing up a proof that addition is in fact a commutative monoid except for one case in add_comm (the code is at the bottom of the post).

The main problem I am having is that for some reason simp/rw is unable to find the instances of monoidNPlus2.add_zero even though it seems "obvious" where it should be applied. I have marked the relevant position in code with a sorry.

There are some other things obviously wrong with this: currently I'm using unfold_projs unfold addAux as a bad way of only expanding out the addition of NPlus2, since using simp [HAdd.hAdd] also expands out natural addition, which makes it impossible to apply Nat lemmas. I'm sure there's a more proper way to do this but for some reason I have been unable to find it.

Additionally, I'm unsure about how case based proofs are usually structured in lean: I tried building up the proof with pattern matching but it seemed that lean was unable to deduce basic facts such as a ≠ 0 in certain branches.

If anyone has some time to look over this example I would appreciate it greatly. If there are any other errors/unorthodox constructions apart from those pointed out above I would also appreciate feedback on those. (I am aware the names of lemmas do not exactly follow conventions but as this is more of a personal working draft I have not taken great care in naming them).

import Mathlib.Data.ZMod.Basic
import Mathlib.RingTheory.Subsemiring.Basic
import Mathlib.Algebra.Order.Monoid.Basic
import Mathlib.Algebra.Ring.Basic

inductive NPlus2
  | two'
  | nat:   NPlus2
  deriving DecidableEq

namespace NPlus2

instance : Zero NPlus2 :=
  nat 0

instance : One NPlus2 :=
  nat 1

@[simp]
def aux1 : NPlus2  
  | two' => 2
  | nat a => a

instance inhabited : Inhabited NPlus2 :=
  two'

lemma aux1nat {n: }: aux1 (nat n) = n := by
  unfold aux1
  simp

@[simp]
lemma zero_eq : 0 = nat Nat.zero := by rfl

@[simp]
lemma one_eq : 1 = nat 1 := by rfl

def addAux: NPlus2  NPlus2  NPlus2
  | 0, x => x
  | x, 0 => x
  | a, b => nat (aux1 a + aux1 b)

instance monoidNPlus2 : AddCommMonoid NPlus2 where
  add := addAux
  zero_add a := by
    unfold_projs
    unfold addAux
    simp
  add_zero a := by
    unfold_projs
    unfold addAux
    by_cases ha: a = nat 0 <;> simp [ha]
  add_comm a b := by
    unfold_projs
    unfold addAux
    by_cases ha : a = nat 0 <;> {
      by_cases hb: b = nat 0 <;> {
        simp [ha, hb]
        try { ring }
      }
    }
  add_assoc a b c := by
    have lem1 {n: } : ¬(nat n = nat 0)  ¬(n = 0) := by simp
    have lem2 {n m: } : ¬(n = 0)  ¬(n + m = 0) := by cases' m <;> simp
    by_cases ha: a = nat 0
    · unfold_projs
      unfold addAux
      simp [ha]
    · by_cases hb: b = nat 0
      · unfold_projs
        unfold addAux
        simp [hb]
      · by_cases hc: c = nat 0
        · rw [hc, zero_eq]
          simp [monoidNPlus2.add_zero]
          sorry
        · unfold_projs
          unfold addAux
          have ne_zero {n m: NPlus2}  (h: ¬(n = nat 0)) : ¬(nat (aux1 n + aux1 m) = nat 0) := by
            cases' n with n n
            · simp
            · simp only [aux1nat]
              rw [lem1] at *
              apply lem2 (m := aux1 m) at h
              exact h
          have ab_ne_zero: ¬(nat (aux1 a + aux1 b ) = nat 0) := ne_zero ha
          have bc_ne_zero: ¬(nat (aux1 b + aux1 c ) = nat 0) := ne_zero hb
          simp only [addAux, ab_ne_zero, bc_ne_zero, aux1nat, Nat.add_assoc]

Matt Diamond (Feb 02 2024 at 04:55):

What is semiNPlus2? I don't see it defined anywhere

Chris Ahn (Feb 02 2024 at 04:57):

Matt Diamond said:

What is semiNPlus2? I don't see it defined anywhere

Sorry I made a mistake while copying the code over, it was the old name of the AddCommMonoid instance

Chris Ahn (Feb 02 2024 at 04:57):

Have edited the post now


Last updated: May 02 2025 at 03:31 UTC