Zulip Chat Archive

Stream: general

Topic: elaboration issue challenge


Patrick Massot (Mar 20 2020 at 18:19):

I have a great new elaboration issue for the most experts users of this distinguished place. The only bad point is it's not minimized. In order to play, you need to leanproject get mathlib:sgouezel_multilinear, then code mathlib_sgouezel_multilinear and open analysis/normed_space/multilinear and go to line 247. Have a quick look at the statement of the next lemma, and take the firm decision to fix that ugly string of underscores.

Now, before that lemma, end the multilinear_map namespace, and paste the following section:

section
--set_option pp.implicit true
lemma  multilinear_map.restr_norm_le {k n : β„•} (f : multilinear_map π•œ (Ξ» i : fin n, G) Eβ‚‚)
  (s : finset (fin n)) (hk : s.card = k) (z : G) {C : ℝ}
  (H : βˆ€ m, βˆ₯f mβˆ₯ ≀ C * finset.univ.prod (Ξ»i, βˆ₯m iβˆ₯)) (v : fin k β†’ G) :
βˆ₯f.restr  s hk z vβˆ₯ ≀ C * βˆ₯zβˆ₯ ^ (n - k) * finset.univ.prod (Ξ»i, βˆ₯v iβˆ₯)  :=
begin
sorry
end

variables {k : β„•} (f : multilinear_map π•œ (Ξ» i : fin n, G) Eβ‚‚)
  (s : finset (fin n)) (hk : s.card = k) (z : G) {C : ℝ}
  (H : βˆ€ m, βˆ₯f mβˆ₯ ≀ C * finset.univ.prod (Ξ»i, βˆ₯m iβˆ₯)) (v : fin k β†’ G)
include H

lemma multilinear_map.restr_norm_le' : βˆ₯f.restr  s hk z vβˆ₯ ≀ C * βˆ₯zβˆ₯ ^ (n - k) * finset.univ.prod (Ξ»i, βˆ₯v iβˆ₯)
 :=
begin
  sorry
end
end

Patrick Massot (Mar 20 2020 at 18:19):

Note how the first statement is rejected, and the second one is accepted.

Patrick Massot (Mar 20 2020 at 18:20):

On surface level, the only difference is the second lemma has all arguments passed as variables.

Patrick Massot (Mar 20 2020 at 18:20):

Now un-comment the set_option line, replace the first statement by sorry and spot the differences in context.

Patrick Massot (Mar 20 2020 at 18:23):

Did you get it? It's in the [βˆ€i, add_comm_group (M₁ i)] argument to multilinear_map. Here M₁ is the constant function from fin n to Type with value G.

Patrick Massot (Mar 20 2020 at 18:24):

When it works, the inferred instance features boring naked G. In the failing case you'll see (Ξ» (i : fin n), G) i.

Patrick Massot (Mar 20 2020 at 18:24):

Now the challenge is to explain the issue, and PR a fix to Lean 3.7.3.

Patrick Massot (Mar 20 2020 at 18:26):

Let me ping @Sebastien Gouezel since this happens in his PR.

Kevin Buzzard (Mar 20 2020 at 19:30):

Is it documented that leanproject get mathlib:sgouezel_multilinear works to get a mathlib branch? I hadn't realised this, I've been getting mathlib and then switching branches and getting the oleans. This way is much cooler :-)

Kevin Buzzard (Mar 20 2020 at 19:40):

So the failure gives the error

type mismatch at application
  multilinear_map.restr f
term
  f
has type
  multilinear_map π•œ (Ξ» (i : fin n), G) Eβ‚‚ : Type (max wG wβ‚‚)
but is expected to have type
  multilinear_map ?m_1 (Ξ» (i : fin ?m_2), ?m_3) ?m_4 : Type (max ? ?)

which is the kind of frustrating error which one sees occasionally, because clearly one can solve for the metavariables. Are you saying that you might be able to understand this failure and perhaps the prettyprinter is lying to us?

Patrick Massot (Mar 20 2020 at 20:55):

Kevin Buzzard said:

Is it documented that leanproject get mathlib:sgouezel_multilinear works to get a mathlib branch? I hadn't realised this, I've been getting mathlib and then switching branches and getting the oleans. This way is much cooler :-)

Yes, last paragraph of "Getting an existing Lean project" at https://github.com/leanprover-community/mathlib-tools/blob/master/README.md#getting-an-existing-lean-project

Patrick Massot (Mar 20 2020 at 20:57):

Elaboration fails to fill in metavariables presumably because it fails some class instance search, because there is application which is not random.choice(['alpha', 'beta', 'gamma', 'delta', 'zeta'])-reduced.

Johan Commelin (Mar 20 2020 at 20:58):

Aren't you missing eta?

Patrick Massot (Mar 20 2020 at 20:59):

Do you think it's eta? Doesn't sound likely to my ear :grinning:

Johan Commelin (Mar 20 2020 at 21:00):

https://en.wikipedia.org/wiki/Lambda_calculus#Reduction

Patrick Massot (Mar 20 2020 at 21:01):

Wikipedia says beta

Patrick Massot (Mar 20 2020 at 21:01):

Johan was looking there too :)

Johan Commelin (Mar 20 2020 at 21:01):

Ooh, I was just complaining that your Russian roulette was missing out on some options.

Patrick Massot (Mar 20 2020 at 21:01):

I know.

Patrick Massot (Mar 20 2020 at 21:02):

We should have a general purpose Zulip shortcut to insert random.choice(['alpha', 'beta', 'gamma', 'delta', 'eta' 'zeta'])

Patrick Massot (Mar 20 2020 at 21:03):

In the mean time, I hope some expert will have a look, or at least @Sebastian Ullrich will post his standard: "this is fixed in Lean 4" message.

Patrick Massot (Mar 21 2020 at 11:50):

@Sebastien Gouezel it's a bit sad no expert seems to have anything to say here, but I still recommend you but the multilinear map in a variable (you can leave everything else in the lemma), and have the nice statement.

Gabriel Ebner (Mar 21 2020 at 12:20):

Since you're calling the experts, I can give you one more workaround:

lemma  multilinear_map.restr_norm_le {k : β„•} (f : (multilinear_map π•œ (Ξ» i : fin n, G) Eβ‚‚ : _))
  (s : finset (fin n)) (hk : s.card = k) (z : G) {C : ℝ}
  (H : βˆ€ m, βˆ₯f mβˆ₯ ≀ C * finset.univ.prod (Ξ»i, βˆ₯m iβˆ₯)) (v : fin k β†’ G) :
βˆ₯f.restr  s hk z vβˆ₯ ≀ C * βˆ₯zβˆ₯ ^ (n - k) * finset.univ.prod (Ξ»i, βˆ₯v iβˆ₯)  :=
begin
sorry
end

Gabriel Ebner (Mar 21 2020 at 12:21):

I assume that is also the elaboration difference between variables and arguments: types of variables are apparently elaborated without expected type, but arguments are elaborated with expected type Sort*.

Patrick Massot (Mar 21 2020 at 12:40):

Thanks Gabriel!

Patrick Massot (Mar 21 2020 at 12:40):

SΓ©bastien, did you see that?

Kevin Buzzard (Mar 21 2020 at 13:02):

If we went through Lean's library and replaced every (a : A) function input with (a : (A : _)) would anything break?

Mario Carneiro (Mar 21 2020 at 13:34):

it seems unlikely, but lean works in mysterious ways

Sebastian Ullrich (Mar 21 2020 at 14:09):

In Lean 4, there will actually be no difference between variables and regular parameters, because the former are simply macros and are re-elaborated inside each declaration that uses them.

Kevin Buzzard (Mar 21 2020 at 14:13):

Here is a version which uses only mathlib master and uses much less of it:

import analysis.normed_space.basic

variables

{π•œ : Type}
[nondiscrete_normed_field π•œ]
{G : Type}
[normed_group G]
[normed_space π•œ G]
{I J : Type}

structure mm (R : Type) [ring R] (I : Type) (M₁ : I β†’ Type) [βˆ€ i  : I, add_comm_group (M₁ i)]
[βˆ€ i : I, module R (M₁ i)]
.

-- M' is implicit and we will show that Lean can't guess it below
def mmrest (R : Type) [ring R] {M' : Type} [add_comm_group M'] [module R M'] (I : Type)
  (F : mm R I (Ξ» i : I, M')) : mm R I (Ξ» j : I, M') := F

variables (F : mm π•œ I (Ξ» i : I, G))

-- works fine
lemma restr_norm_le : mmrest π•œ I F = mmrest π•œ I F := rfl

-- also works
lemma restr_norm_le' (F : (mm π•œ I (Ξ» i : I, G))) :
@mmrest π•œ _ G _ _  I F = mmrest π•œ I F := by refl -- removing G makes it fail

-- Lean can't guess G
lemma restr_norm_le'' (F : (mm π•œ I (Ξ» i : I, G))) :
mmrest π•œ I F = mmrest π•œ I F := by refl -- fails

/-
type mismatch at application
  mmrest π•œ I F
term
  F
has type
  mm π•œ I (Ξ» (i : I), G)
but is expected to have type
  mm π•œ I (Ξ» (i : I), ?m_1)
-/

Kevin Buzzard (Mar 21 2020 at 14:14):

Lean is failing to infer G from (Ξ» i : I, G)

Kevin Buzzard (Mar 21 2020 at 14:18):

When it succeeds. F has type

F :
  @mm π•œ
    (@normed_ring.to_ring π•œ
       (@normed_field.to_normed_ring π•œ (@nondiscrete_normed_field.to_normed_field π•œ _inst_1)))
    I
    (Ξ» (i : I), G)
    (Ξ» (i : I), @normed_group.to_add_comm_group G _inst_2)
    (Ξ» (i : I),
       @normed_space.to_module π•œ G (@nondiscrete_normed_field.to_normed_field π•œ _inst_1) _inst_2 _inst_3)

and when it fails, it has the defeq type

  @mm π•œ
    (@normed_ring.to_ring π•œ
       (@normed_field.to_normed_ring π•œ (@nondiscrete_normed_field.to_normed_field π•œ _inst_1)))
    I
    (Ξ» (i : I), G)
    (Ξ» (i : I), @normed_group.to_add_comm_group ((Ξ» (i : I), G) i) _inst_2)
    (Ξ» (i : I),
       @normed_space.to_module π•œ ((Ξ» (i : I), G) i) (@nondiscrete_normed_field.to_normed_field π•œ _inst_1) _inst_2
         _inst_3)

Gabriel Ebner (Mar 21 2020 at 14:27):

The issue lies in unification: we need to solve ?m1 =?= (fun x, G) i where ?m1 may not contain i.

Kevin Buzzard (Mar 21 2020 at 14:28):

How about ?m1=G?

Sebastien Gouezel (Mar 21 2020 at 14:33):

I have fixed the PR following @Gabriel Ebner 's advice. Thanks Gabriel!

Kevin Buzzard (Mar 21 2020 at 14:36):

Another fix would be to make the implicit variable explicit -- the one which unification can't guess.

Kevin Buzzard (Mar 21 2020 at 14:37):

You are asking Lean to guess G from (f : multilinear_map π•œ (Ξ» i : fin n, G) Eβ‚‚)` and perhaps we learn here that it is not always capable of such guesses.

Gabriel Ebner (Mar 21 2020 at 14:53):

Kevin Buzzard said:

How about ?m1=G?

This is exactly the solution that we would like, in this case. So you say, "how about we just beta-reduce the right-hand side whenever we assign a meta-variable"? And in this case, it would work. However changes in the unifier have the unfortunate habit of breaking things elsewhere in unexpected places. Since it is not 100% clear to me that this the right behavior, I'm not too eager to change the unifier unless this problem pops up more often.

Kevin Buzzard (Mar 21 2020 at 15:01):

I see!

Patrick Stevens (Mar 21 2020 at 15:58):

Forgive the noob question, but this made me think about a problem I encountered earlier today: is it possible to manually assign a metavariable? If I have m1 in scope in a goal, can I specify m1 somehow without having to track down where exactly the metavariable arose?

Johan Commelin (Mar 21 2020 at 16:00):

It means that you'll have multiple goals.

Johan Commelin (Mar 21 2020 at 16:00):

So you can use swap 4 to jump to goal number 4. And use exact foobar close it.

Johan Commelin (Mar 21 2020 at 16:00):

You will have to figure out manually which goal corresponds to ?m1

Kevin Buzzard (Mar 21 2020 at 16:06):

I think that in general you might want to try and avoid metavariables in goals. Usually when one appears for me, I instantly stomp on it by changing the line which created it. It is often not hard to do this, it is usually an _ which just needed to be filled in explicitly. Having metavariables around can actually mess you up, some tactics can get confused for example.


Last updated: Dec 20 2023 at 11:08 UTC