Zulip Chat Archive

Stream: mathlib4

Topic: Another kind of simp regression


Bhavik Mehta (Nov 06 2023 at 16:52):

Here's another simp regression I found while porting the exponential ramsey project:

import Mathlib.Init.Set
import Std.Logic

structure MySimpleGraph (V : Type u) where
  Adj : V  V  Prop
  loopless :  x, ¬ Adj x x

namespace MySimpleGraph

@[simp] theorem irrefl {G : MySimpleGraph V} {v : V} : ¬G.Adj v v := G.loopless v

def neighbourSet {V : Type _} (G : MySimpleGraph V) (v : V)  :
    Set V := setOf (G.Adj v)

@[simp] theorem mem_neighbourFinset {V : Type _} (G : MySimpleGraph V) (v : V) (w : V) :
    w  G.neighbourSet v  G.Adj v w := Iff.rfl

variable {V V' : Type _} {K : Type _}

structure Foo (V K : Type _) :=
(get : (x y : V)  x  y  K)
(symm :  x y : V, (h : x  y)  get y x h.symm = get x y h)

def Foo.labelGraph (C : Foo V K) (k : K) : MySimpleGraph V where
  Adj x y :=  h : x  y, C.get x y h = k
  loopless := by
    intro x hx
    have h, _ := hx
    exact h rfl

theorem Foo.labelGraph_adj {C : Foo V K} {k : K} (x y : V) :
    (C.labelGraph k).Adj x y   H : x  y, C.get x y H = k :=
  Iff.rfl

theorem SimpleGraph.extracted_1 {K : Type _} [DecidableEq K] {M : Nat}
    (C : Foo (Fin (M + 1)) K) (k' : K) (y : Fin (M + 1)) :
   (hy : y  neighbourSet (C.labelGraph k') 0),
    C.get 0 y (Ne.symm (ne_of_mem_of_not_mem hy (by simp))) = k' := by
  simp only [mem_neighbourFinset, Foo.labelGraph_adj, ne_eq, forall_exists_index]
  simp

The final simp succeeds and closes the goal in Lean 3. I haven't yet managed to isolate mathlib from it, although what's left is hopefully not too bad to remove... hopefully it's pretty clear that originally this had lots of mathlib in it!

Eric Wieser (Nov 06 2023 at 18:07):

I think I understand how to make the mwe here, will report back shortly

Eric Wieser (Nov 06 2023 at 18:10):

import Std.Logic

def getOne (x : Nat) (_hx : x = 1) : Nat := x

example {P : Prop} : P  P := by simp only [imp_self]
example {x} (hx : x = 1) :  h : getOne x hx = 1, getOne x h = 1 := id
example {x} (hx : x = 1) :  h : getOne x hx = 1, getOne x h = 1 := by simp -- fails

Bhavik Mehta (Nov 06 2023 at 18:11):

Hmm I'm not sure that captures the regression since it also fails in Lean 3

Eric Wieser (Nov 06 2023 at 18:17):

This works in Lean 3:

import logic.basic

example {P : Prop} : P → P := by simp

example {α : Prop} {P : α → Prop} {f : ∀ {a}, P a → α} {a : α} : ∀ (h : P a), P (f h) := by
  simp

Eric Wieser (Nov 06 2023 at 18:18):

This fails in lean4:

import Std.Logic

example {P : Prop} : P  P := by simp

example {α : Prop} {P : α  Prop} {f :  {a}, P a  α} {a : α} : (h : P a)  P (f h) := by
  simp

Eric Wieser (Nov 06 2023 at 18:19):

Note that rw [imp_self] works in lean4, so this is another rw vs simp thing

Eric Wieser (Nov 06 2023 at 18:22):

simp (config := { contextual := true}) can do it

Bhavik Mehta (Nov 06 2023 at 18:23):

Yes, this captures it, thanks! Here's a version which doesn't depend on std:

@[simp] theorem imp_self {a : Prop} : (a  a)  True := fun _ => trivial, fun _ => id

example {P : Prop} : P  P := by simp only [imp_self]

example {α : Prop} {P : α  Prop} {f :  {a}, P a  α} {a : α} : (h : P a)  P (f h) := by
  simp only [imp_self]

Bhavik Mehta (Nov 06 2023 at 18:32):

Reported as https://github.com/leanprover/lean4/issues/2835


Last updated: Dec 20 2023 at 11:08 UTC