Zulip Chat Archive

Stream: mathlib4

Topic: !4#3484, Analysis.Seminorm


Jeremy Tan (Apr 17 2023 at 14:42):

(deleted)

Jeremy Tan (Apr 17 2023 at 14:46):

!4#3484 Most of the remaining errors in this file stem from the comp declaration at line 302:

/-- Composition of a seminorm with a linear map is a seminorm. -/
def comp (p : Seminorm π•œβ‚‚ Eβ‚‚) (f : E β†’β‚›β‚—[σ₁₂] Eβ‚‚) : Seminorm π•œ E :=
  { p.toAddGroupSeminorm.comp f.toAddMonoidHom with
    toFun := fun x => p (f x)
    smul' := fun _ _ => by rw [map_smulβ‚›β‚—, map_smul_eq_mul, RingHomIsometric.is_iso] }
#align seminorm.comp Seminorm.comp

If I could make this definition compile without making another error at [IsScalarTower R ℝβ‰₯0 ℝ] (L299) I'd cut the error count by about half

Jeremy Tan (Apr 17 2023 at 14:55):

Note that I haven't committed any :eta:s yet

Scott Morrison (Apr 21 2023 at 04:20):

I've done a bunch of work on !4#3484, dealing with most but not quite all of the errors. If anyone would like to take another look that would be great. This is the highest priority file for now!

Thomas Murrills (Apr 24 2023 at 20:27):

I was taking a look just out of curiosity and noted this terrible way to get comp_smul to typecheck:

theorem comp_smul (p : Seminorm π•œβ‚‚ Eβ‚‚) (f : E β†’β‚›β‚—[σ₁₂] Eβ‚‚) (c : π•œβ‚‚) :
    (set_option synthInstance.etaExperiment true in p.comp (c β€’ f)) = β€–cβ€–β‚Š β€’ p.comp f :=
  ext fun _ => by
    rw [comp_apply, smul_apply, LinearMap.smul_apply, map_smul_eq_mul, NNReal.smul_def, coe_nnnorm,
      smul_eq_mul, comp_apply]

I'd assume this is a last resort. (Note: set_option at least doesn't appear in the type of the lemma when used later on.) What do you do when the lhs needs eta experiment but the rhs needs to not have eta experiment?

Eric Wieser (Apr 24 2023 at 20:42):

Often "needs to not have eta experiment" is just "needs a higher heartbeat limit with eta experiment than without"

Thomas Murrills (Apr 24 2023 at 20:55):

Hmm, that does work eventually...but I will note that in this case upping the heartbeats causes the declaration to take 116 seconds instead of 6 seconds :woozy_face:

Thomas Murrills (Apr 24 2023 at 21:02):

Hesitantly offering

/-- Elaborate the following term with `set_option synthInstance.etaExperiment true`. -/
macro "eta% " a:term : term => `(term|set_option synthInstance.etaExperiment true in $a)

for legibility and speedups during this eta era. But, I don't know if that ~2 minutes is actually fine and negligible, or if there's another, better way to fix this lemma

Patrick Massot (Apr 24 2023 at 21:07):

I think we can't stay with a declaration taking two minutes, especially when the proof is two lines long.

Scott Morrison (Apr 24 2023 at 21:28):

I'm game to use eta%, perhaps renamed to etaExperiment% so it's a big easier to track / more obviously a hack. :-)

Thomas Murrills (Apr 25 2023 at 04:21):

Ok, sounds good! (I think snake case is the standard for elaborators, so I guess it ought to be eta_experiment%!) What's a good location to put the macro in?

Thomas Murrills (Apr 25 2023 at 05:50):

Different issue: I took a look at the remaining error and fixed it, but it's weird: I needed to force Subtype.val to be used as the coercion instead of .toAddGroupSeminorm. Or, at least, that's what I think is happening.

...
          refine' csupα΅’_le fun i =>
            ((i : Seminorm π•œ E).add_le' x y).trans <| add_le_add
              -- Porting note: `f` is provided to force `Subtype.val` to appear.
              -- A type ascription on `_` would have also worked, but would have been more verbose.
              (le_csupα΅’ (f := fun i => (Subtype.val i : Seminorm π•œ E).toFun x) ⟨q x, _⟩ i)
              (le_csupα΅’ (f := fun i => (Subtype.val i : Seminorm π•œ E).toFun y) ⟨q y, _⟩ i)
...

Removing Subtype.val produces the following error message

application type mismatch
  add_le_add (le_csupα΅’ (Exists.intro (q x) ?m.711983) ↑i)
argument
  le_csupα΅’ (Exists.intro (q x) ?m.711983) ↑i
has type
  AddGroupSeminorm.toFun (↑i).toAddGroupSeminorm x ≀ ⨆ i, AddGroupSeminorm.toFun i.toAddGroupSeminorm x : Prop
but is expected to have type
  AddGroupSeminorm.toFun (↑i).toAddGroupSeminorm x ≀ ⨆ i, ↑↑i x : Prop

Removing f altogether causes lean to struggle to unify the type (?m.711950 i ≀ supα΅’ ?m.711950 : Prop).

Is the above an acceptable fix? Or is there an obvious better way to do this?

Thomas Murrills (Apr 25 2023 at 07:17):

Ok, I pushed since I'm going to sleep soonish and I know this is a high-prio file; that should fix all the errors, unless something's weird with my setup (it might be). if any choices I made were suboptimal, we can always change them :)

Thomas Murrills (Apr 25 2023 at 07:18):

I put the eta_experiment% macro in Mathlib/Lean/Meta.lean, where it's imported by most things. (synthInstance.etaExperiment was registered in Lean.Meta.SynthInstance, but I didn't think we should make a whole file for just this macroβ€”especially because Mathlib's Lean.Meta file is a grab-bag of Meta utilities, unlike Lean's version of that file.)

Thomas Murrills (Apr 25 2023 at 08:59):

(Well, couldn't sleep.) Huh, that's really weird. The file does just fine in my VS code, but fails under lake build (both in CI and locally). The Lean version is the same according to #eval Lean.versionString...what could be going on?

Thomas Murrills (Apr 25 2023 at 09:27):

Whoa, this is weird. Writing set_option synthInstance.etaExperiment false in before the first offending declaration (smul_le_smul) causes it to error the same way lake doesβ€”but omitting that shows no errors. Can anyone reproduce?

Thomas Murrills (Apr 25 2023 at 09:27):

(Note that #eval show MetaM Bool from do return synthInstance.etaExperiment.get (← getOptions) evaluated the line just before returns false, so it's definitely not trueβ€”and turning eta on instead causes worse errors.)

Thomas Murrills (Apr 25 2023 at 09:31):

Interestingly, setting other options to either true or false (such as pp.explicit) also causes the (correct?) lake-like erroring behavior. Setting them at the top of the file works too. But other commands, like #check or #eval, don't.

Thomas Murrills (Apr 25 2023 at 09:47):

Anyway, the actual problem here seems to be something like "HSMul can't find the return type, even when it's provided as a type ascription"β€”I'm not sure what to do about that.

Thomas Murrills (Apr 25 2023 at 09:56):

Wow, if the return type of smul_le_smul is anything less than

(HSMul.hSMul (Ξ³ := Seminorm π•œ E) a p : Seminorm π•œ E) ≀ b β€’ q

then HSMul can't find its return type in time, giving the error failed to synthesize HSMul ℝβ‰₯0 (Seminorm π•œ E) ?m.454788 (deterministic) timeout at 'typeclass'.... Both means of specifying the output type need to be there...but I don't quite understand why there's a metavariable in the first place when we supply the argument directly? Does this have to do with outParam shenanigans somehow?

Thomas Murrills (Apr 25 2023 at 10:14):

MWE, sufficiently far down in the file:

#synth HSMul ℝβ‰₯0 (Seminorm π•œ E) (Seminorm π•œ E)
-- failed to synthesize HSMul ℝβ‰₯0 (Seminorm π•œ E) ?m.202055 (deterministic) timeout at 'typeclass', maximum number of heartbeats (20000) has been reached (use 'set_option synthInstance.maxHeartbeats <num>' to set the limit)

Huh?? The argument is right there! Why is it a metavariable?

Mario Carneiro (Apr 25 2023 at 10:14):

probably because it is an out param

Thomas Murrills (Apr 25 2023 at 10:15):

But why doesn't it get unified with what is there?

Mario Carneiro (Apr 25 2023 at 10:15):

the typeclass problem is solved without it

Mario Carneiro (Apr 25 2023 at 10:16):

it appears to have timed out before returning

Thomas Murrills (Apr 25 2023 at 10:17):

Weird! Isn't that a lot of heartbeats to figure out what you "already know", so to speak...?

Mario Carneiro (Apr 25 2023 at 10:18):

it's not trying to figure out the out param, it's trying to figure out the instance to get there

Thomas Murrills (Apr 25 2023 at 10:20):

Oh, I seeβ€”which I could see making sense if you didn't want to venture on a long unification search. But I feel like an exception should be made when the info is "immediate" somehow, lest this happen...ofc I have no idea what this entails, tho.

Mario Carneiro (Apr 25 2023 at 10:21):

I'm saying that the value of the out param doesn't help much to find the instance, and it can get in the way sometimes so it is temporarily replaced by a metavariable

Mario Carneiro (Apr 25 2023 at 10:22):

the real question is why the instance problem HSMul ℝβ‰₯0 (Seminorm π•œ E) ?_ isn't being solved

Thomas Murrills (Apr 25 2023 at 10:22):

ahh ok

Thomas Murrills (Apr 25 2023 at 10:33):

Anyway, I'm pretty sure that accounts for the last two errors in the file. I'll leave the decision of whether to increase max heartbeats, make everything explicit as above, or figure out the underlying problem to othersβ€”I'm heading to sleep :)

Thomas Murrills (Apr 25 2023 at 10:38):

(Also, that "invisible error" issue above all this maybe deserves a separate thread if anyone can reproduce it (if relevant, I'm on macOS ventura)β€”not seeing errors that are actually there is quite jarring)

Scott Morrison (Apr 26 2023 at 03:25):

This instance problem HSMul ℝβ‰₯0 (Seminorm π•œ E) ?_ is in fact solved, it just needs slightly beyond the 20000 heartbeat limit.

Scott Morrison (Apr 26 2023 at 03:29):

Okay, I have this building, and given this file is on the critical path and has been for a long while, I think I would like to merge. We still have some signs of sickness here, that we should keep thinking about.

The worst one, with a double porting note, is:

-- Porting note: unhappily, turning on `synthInstance.etaExperiment` isn't enough here:
-- we need to elaborate a fragment of the type using `eta_experiment%`, but then can't use it for the proof!
-- Porting note:
-- finding the instance `SMul ℝβ‰₯0 (Seminorm π•œ E)` is slow,
-- and needs an increase to `synthInstance.maxHeartbeats`.
set_option synthInstance.maxHeartbeats 30000 in
theorem comp_smul (p : Seminorm π•œβ‚‚ Eβ‚‚) (f : E β†’β‚›β‚—[σ₁₂] Eβ‚‚) (c : π•œβ‚‚) :
    p.comp (eta_experiment% c β€’ f) = β€–cβ€–β‚Š β€’ p.comp f :=
  ext fun _ => by
    rw [comp_apply, smul_apply, LinearMap.smul_apply, map_smul_eq_mul, NNReal.smul_def, coe_nnnorm,
      smul_eq_mul, comp_apply]

Jeremy Tan (Apr 26 2023 at 04:53):

It passes CI now. Since (the apparently now correct) coe_smul is not needed in the rest of the file, should I revert the last changes I made that replaced coe_smul with rfl?

Scott Morrison (Apr 26 2023 at 04:57):

I don't think there's any need to revert. It's not like the rfls you added are expensive.

Scott Morrison (Apr 26 2023 at 04:57):

I've hit merge.


Last updated: Dec 20 2023 at 11:08 UTC