Zulip Chat Archive

Stream: mathlib4

Topic: invalid occurrence of universe level


Kevin Buzzard (Nov 18 2022 at 19:48):

I have a universe error which I can't fathom out; this arises when porting Logic.Equiv.Basic.

import Mathlib.Logic.Equiv.Defs
import Mathlib.Data.Prod.Basic

namespace Equiv

def prodCongr {α₁ β₁ α₂ β₂ : Type _} (e₁ : α₁  α₂) (e₂ : β₁  β₂) : α₁ × β₁  α₂ × β₂ :=
  Prod.map e₁ e₂, Prod.map e₁.symm e₂.symm, fun a, b => by simp, fun a, b => by simp
#align equiv.prod_congr Equiv.prodCongr

def prodPUnit (α : Type _) : α × PUnit.{u + 1}  α :=
  fun p => p.1, fun a => (a, PUnit.unit), fun _, PUnit.unit => rfl, fun _ => rfl

def prodUnique (α β : Type _) [Unique β] : α × β  α :=
  ((Equiv.refl α).prodCongr <| equivPUnit β).trans <| prodPUnit α
/-
invalid occurrence of universe level 'u_3' at 'Equiv.prodUnique', it does not occur at the declaration type, nor it is explicit universe level provided by the user, occurring at expression
  Equiv.trans.{max (u_1 + 1) (u_2 + 1), max (u_1 + 1) (u_3 + 1), u_1 + 1}
    (prodCongr.{u_1, u_2, u_1, u_3} (Equiv.refl.{u_1 + 1} α) (equivPUnit.{u_2 + 1, u_3 + 1} β)) (prodPUnit.{u_3, u_1} α)
at declaration body
  fun (α : Type u_1) (β : Type u_2) [Unique β] => Equiv.trans (prodCongr (Equiv.refl α) (equivPUnit β)) (prodPUnit α)
-/

Any clues?

Gabriel Ebner (Nov 18 2022 at 19:52):

It means that the universe level of the PUnit is unspecified in the body of the definition.

Gabriel Ebner (Nov 18 2022 at 19:52):

It could be v+1 or v+100 or etc. (if β : Type v)

Gabriel Ebner (Nov 18 2022 at 19:53):

def prodUnique (α : Type u) (β : Type v) [Unique β] : α × β  α :=
  ((Equiv.refl α).prodCongr <| equivPUnit.{v+1,v+10} β).trans <| prodPUnit α

Gabriel Ebner (Nov 18 2022 at 19:53):

Not sure where to best put the level annotation.

Kevin Buzzard (Nov 18 2022 at 19:53):

Thanks! This worked in Lean 3. Is this something which needs flagging?

Kevin Buzzard (Nov 18 2022 at 19:54):

wooah I went for v + 37 of course, and I got

maximum universe level offset threshold (32) has been reached, you can increase the limit using option `set_option maxUniverseOffset <limit>`, but you are probably misusing universe levels since offsets are usually small natural numbers

Kevin Buzzard (Nov 18 2022 at 19:55):

lol at "you are probably misusing universe levels"

Kevin Buzzard (Nov 18 2022 at 19:57):

PS is the name pUnitProd for PUnit × α ≃ α? My understanding is that we're not going for lE but perhaps pUnit is less bad

Mario Carneiro (Nov 18 2022 at 19:58):

I've been using punitProd when it shows up at the beginning of a word... I guess that's not consistent with the current advice

Scott Morrison (Nov 19 2022 at 01:37):

I like punit too.

Arien Malec (Nov 19 2022 at 02:32):

Can someone have a look at PR 649 which typecheck but lints with similar issues?

Arien Malec (Nov 19 2022 at 02:38):

Sorry PR #638

Arien Malec (Nov 19 2022 at 02:39):

(On mobile- excuse the bad link)

Yakov Pechersky (May 14 2023 at 17:38):

Related question: why is the second style of epi invalid?

def epi {A B Z : Type _} (f : A  B) : Prop :=
     g g' : B  Z⦄, g  f = g'  f  g = g'

def epi' {A B : Type _} (f : A  B) : Prop :=
     {Z : Type _} g g' : B  Z (h : g  f = g'  f), g = g'
/-
invalid occurrence of universe level 'u_3' at 'epi'', it does not occur at the declaration type, nor it is explicit universe level provided by the user, occurring at expression
  ∀ {Z : Type u_3} ⦃g g' : B → Z⦄,
    Eq.{max (u_1 + 1) (u_3 + 1)} (Function.comp.{u_1 + 1, u_2 + 1, u_3 + 1} g f)
        (Function.comp.{u_1 + 1, u_2 + 1, u_3 + 1} g' f) →
      Eq.{max (u_2 + 1) (u_3 + 1)} g g'
at declaration body
  fun {A : Type u_1} {B : Type u_2} (f : A → B) => ∀ {Z : Type u_3} ⦃g g' : B → Z⦄, g ∘ f = g' ∘ f → g = g'
-/

Kevin Buzzard (May 14 2023 at 17:52):

Does anything change if you make all universes explicit?

Yakov Pechersky (May 14 2023 at 18:09):

Yes, that's better, thanks!

set_option autoImplicit false

universe u v w

def epi {A B Z : Sort _} (f : A  B) : Prop :=
     g g' : B  Z⦄, g  f = g'  f  g = g'

def epi' {A : Sort u} {B : Sort v} (f : A  B) : Prop :=
     {Z : Sort w} g g' : B  Z⦄, g  f = g'  f  g = g'

def Surjective {α β : Sort _} (f : α  β) : Prop :=  b,  a, f a = b

example {A B : Sort _} (f : A  B) :
    Surjective f   Z, epi (Z := Z) f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h Prop (λ x =>  a, f a = x) (λ _ => True) _
    · funext a
      exact eq_true a, rfl
    · simp [congrFun h b]

example {A B : Sort _} (f : A  B) :
    Surjective f  epi' f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h Prop (λ x =>  a, f a = x) (λ _ => True) _
    · funext a
      exact eq_true a, rfl
    · simp [congrFun h b]

Kevin Buzzard (May 14 2023 at 18:58):

Is this expected behaviour or a bug? I'm surprised by it.

Sophie Morel (May 15 2023 at 20:33):

Kevin Buzzard said:

I have a universe error which I can't fathom out; this arises when porting Logic.Equiv.Basic.
<snip>

I am having a similar problem while trying to port Shing Tak Lam's formalization of abstract simplicial complexes from Lean3 to Lean4. I am also not sure how to adapt Gabriel's solution to my case, I tried sticking universes everywhere but, well, I'm not that good with Lean4 and I just get more errors. I'm getting really sleepy now, so I'll try some more tomorrow and maybe extract a MWE if nothing works.

Kevin Buzzard (May 15 2023 at 20:34):

Universes are a bit of a dark art in Lean 4; I guess the community are slowly learning how to tame them. Is your port part of the official porting effort? If so you could post a link to the PR.

Sophie Morel (May 15 2023 at 21:08):

No, it's part of my translating my personal project into Lean4., though I do hope that abstract simplicial complexes eventually are integrated into mathlib4. (I started learning Lean4 about a week ago, so I'm not sure I should be trusted anywhere near the official porting effort.)

Sophie Morel (May 16 2023 at 05:38):

Okay, I think one of my problems is coming from the fact that I define a Bot instance using the empty set, but Lean doesn't know which universe this empty set lives in. How do I tell it "you know, I mean the smallest element of (Set (Finset α)), it's definitely still in the same universe u" ? I've been embarrassingly stuck on this particular point for like 30 minutes. :sad:
Uh, never mind, it was ∅ : Set (Finset V) of course.

Sophie Morel (May 16 2023 at 05:50):

Okay, the problem seems to have gone away but I have no idea why... I was trying to put a CompleteLattice instance on the type of abstract simplicial complex on a type V (defined as a set of finsets of V with some properties), I had already defined Bot and Top instances, Lean was complaining that there was some universe problem to do with them. So I defined OrderBot and OrderTop instances separately with explicit universe declarations, used them in the definition of the CompleteLattice instance (instead of just using Bot and Top plus proofs of bot_le and le_top), and suddenly Lean is happy ? :astonished:

Sophie Morel (May 16 2023 at 05:51):

Tune back in for the next 5 minutes, when I will try to make the CompleteLattice`` into a CompleteDistribLattice``` and the problem will come back with a vengeance...

Reid Barton (May 16 2023 at 06:50):

Whether or not the epi/epi' behavior was intended, it definitely seems good to me--it's very rare that you want to make a declaration like epi', and if you do you should be explicit about what you're doing.

Reid Barton (May 16 2023 at 06:53):

A priori the propositions epi'.{u v w} f are all different for different w--in this case we know they actually are equal. Though I'm pretty sure your example only proves this for epi'.{u v 0} f. Note you can't even see this by looking at the statement, you have to look at the proof!

Yaël Dillies (May 16 2023 at 07:31):

@Sophie Morel, if you give us a #mwe we can have a go at debugging.

Sophie Morel (May 16 2023 at 08:08):

@Yaël Dillies Thanks, but I solved the problem by myself. I'm still not sure what happened, but Lean is happy, so I am happy.

Sophie Morel (May 16 2023 at 08:53):

(In fact it was while trying to produce a MWE short enough for Zulip that I accidentally solved the problem.)

Patrick Massot (May 16 2023 at 13:20):

This is actually one of the reasons why we ask for MWE. Note this also happen with real life math conversations.

Yakov Pechersky (May 16 2023 at 16:25):

@Reid, how would you formalize this exercise?
image.png
image.png

Yakov Pechersky (May 16 2023 at 16:26):

BTW, switching from example to theorem breaks the proofs

Reid Barton (May 16 2023 at 16:29):

Just use one universe for everything

Yakov Pechersky (May 16 2023 at 16:29):

So one has to specify universes more explicitly, and yes, the proofs end up in Sort 1:

set_option autoImplicit false
set_option pp.universes true

universe u v w

def epi {A : Sort u} {B : Sort v} {Z : Sort w} (f : A  B) : Prop :=
     g g' : B  Z⦄, g  f = g'  f  g = g'

def epi' {A : Sort u} {B : Sort v} (f : A  B) : Prop :=
     {Z : Sort w} g g' : B  Z⦄, g  f = g'  f  g = g'

def Surjective {α β : Sort _} (f : α  β) : Prop :=  b,  a, f a = b

theorem foo {A B : Sort _} (f : A  B) :
    Surjective f   Z, epi.{u, v, 1} (Z := Z) f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h Prop (λ x =>  a, f a = x) (λ _ => True) _
    · funext a
      exact eq_true a, rfl
    · simp [congrFun h b]

theorem bar {A : Sort u} {B : Sort v} (f : A  B) :
    Surjective f  epi'.{u, v, 1} f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h Prop (λ x =>  a, f a = x) (λ _ => True) _
    · funext a
      exact eq_true a, rfl
    · simp [congrFun h b]

Reid Barton (May 16 2023 at 16:29):

That's what the author of those texts meant anyways

Yakov Pechersky (May 16 2023 at 16:30):

Yes, I guess so:

theorem foo {A B : Type} (f : A  B) :
    Surjective f   Z, epi (Z := Z) f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h Prop (λ x =>  a, f a = x) (λ _ => True) _
    · funext a
      exact eq_true a, rfl
    · simp [congrFun h b]

theorem bar {A B : Type} (f : A  B) :
    Surjective f  epi' f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h Prop (λ x =>  a, f a = x) (λ _ => True) _
    · funext a
      exact eq_true a, rfl
    · simp [congrFun h b]

Yakov Pechersky (May 16 2023 at 16:31):

What would be the proof in other universes? With ulift Prop?

Reid Barton (May 16 2023 at 16:31):

You can also make your theorem bar work for any w, by using ULift Prop, and some extra messing about. (Okay, maybe not w = 0, didn't think about it.)

Reid Barton (May 16 2023 at 16:33):

(There are also other constructions that work, e.g., take Z to be the quotient of two copies of B by the relation that identifies the two copies of f(a) for each a in A)

Reid Barton (May 16 2023 at 16:39):

If this was a general notion of epimorphism in a category being specialized to the category of types, then you would be forced to put A, B, Z all in a single universe anyways.

Reid Barton (May 16 2023 at 16:42):

But the main point I think is that your epi' does not say that "for all sets ZZ and ...". Rather, there is a whole family of different epi'.{u,v,w} which say that "for all w-small sets ZZ and ...", i.e., you've defined what it means for f to be a w-epimorphism for each w, where w is some universe variable that is totally independent of f.

Reid Barton (May 16 2023 at 16:44):

In this case the meanings of those statements seem to be

  • Every map f is a 0-epimorphism (because any two maps into a propositions are equal), while
  • a map f is w+1-epimorphism if and only if it is an epimorphism in the usual sense

Reid Barton (May 16 2023 at 16:44):

I think we can assume that this is not what the author of those texts had in mind.

Reid Barton (May 16 2023 at 16:45):

I'm not saying it is a useless thing or that you don't want to do it, just that probably it should not be as easy to do accidentally as writing a Type _ on autopilot.

Yakov Pechersky (May 16 2023 at 16:46):

Thanks for that detailed explanation

Yakov Pechersky (May 16 2023 at 16:47):

So, having one universe for A B Z, and probably just doing Type is good enough. For posterity, this is what I now have, just experimentation that does compile:

set_option autoImplicit false
-- set_option pp.universes true

universe u

def epi {A : Sort u} {B : Sort u} {Z : Sort u} (f : A  B) : Prop :=
     g g' : B  Z⦄, g  f = g'  f  g = g'

def epi' {A : Sort u} {B : Sort u} (f : A  B) : Prop :=
     {Z : Sort u} g g' : B  Z⦄, g  f = g'  f  g = g'

def Surjective {α β : Sort _} (f : α  β) : Prop :=  b,  a, f a = b

theorem foo {A B : Type u} (f : A  B) :
    Surjective f   (Z : Type u), epi (Z := Z) f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h (ULift Prop) (λ x => ULift.up $  a, (f a = x)) (λ _ => ULift.up True) _
    · funext a
      simp [eq_true (⟨a, rfl :  x, f x = f a)]
    · have := congrArg ULift.down (congrFun h b)
      rw [ULift.down_up, ULift.down_up] at this
      simp [this]

theorem bar {A B : Type u} (f : A  B) :
    Surjective f  epi' f := by
  constructor
  · intro h Z g g' hg
    funext b
    cases h b with
    | intro a ha =>
      rw [ha]
      exact congrFun hg a
  · intro h b
    specialize @h (ULift Prop) (λ x => ULift.up $  a, (f a = x)) (λ _ => ULift.up True) _
    · funext a
      simp [eq_true (⟨a, rfl :  x, f x = f a)]
    · have := congrArg ULift.down (congrFun h b)
      rw [ULift.down_up, ULift.down_up] at this
      simp [this]

Reid Barton (May 16 2023 at 16:48):

Probably what you'd really like to write is epi'' f := "for all universes w and Z : Type w, and ..." but Lean doesn't allow this.


Last updated: Dec 20 2023 at 11:08 UTC