Zulip Chat Archive

Stream: general

Topic: Any ideas on how to debug this?


Gabriel Ebner (Mar 04 2020 at 14:59):

import all -- current mathlib master

-- simplify tactic failed to simplify
example (z : ) : (complex.conj z).im = -z.im := by simp [complex.conj_im]
example (x : ) : real.sin (-x) = -real.sin x := by simp [real.sin_neg]

-- works just fine
example (z : ) : (complex.conj z).im = -z.im := by simp only [complex.conj_im]
example (x : ) : real.sin (-x) = -real.sin x := by simp only [real.sin_neg]

Sebastien Gouezel (Mar 04 2020 at 15:03):

Ask squeeze_simp, it will give you the offending lemma.

Gabriel Ebner (Mar 04 2020 at 15:17):

Unfortunately, simp fails in the first two calls. So I don't think squeeze simp can do anything.

Reid Barton (Mar 04 2020 at 15:24):

Try set_option trace.simplify.rewrite true

Sebastien Gouezel (Mar 04 2020 at 15:24):

If you do

begin
  squeeze_simp,
  sorry,
end

you will see the simp lemmas that simp uses on your expression (the ones that prevent complex.conj_im from firing).

Gabriel Ebner (Mar 04 2020 at 16:09):

If it was only that easy. squeeze_simp also fails with "simplify tactic failed to simplify". (Internally, squeeze_simp looks at the proof produced by simp to determine the used lemmas; if simp doesn't simplify, then there's no proof.)

Reid Barton (Mar 04 2020 at 16:11):

Oh, that is weird. That error is supposed to mean that simp made no progress, right?

Gabriel Ebner (Mar 04 2020 at 16:11):

Reid Barton said:

Try set_option trace.simplify.rewrite true

That's my go-to option these days, but I don't see anything suspicious. In fact, complex.conj_im even seems to be used:

2. [simplify.rewrite] [complex.conj_im]: (complex.conj z).im ==> -z.im

Reid Barton (Mar 04 2020 at 16:11):

Another option is set_option trace.simplify true and search the log for complex.conj_im

Gabriel Ebner (Mar 04 2020 at 16:13):

It occurs twice in the log, once for z.conj.im and once for z.im. It even seems to rewrite the first term.

Reid Barton (Mar 04 2020 at 16:14):

Seems like simp is just being grumpy then

Gabriel Ebner (Mar 04 2020 at 16:22):

OMG, complex.im seems to disable simp entirely:

example (z : ) : z.conj.im = z.conj.im + 0 := by simp -- fails

Sebastien Gouezel (Mar 04 2020 at 16:30):

A small dichotomy gives a failure with

import algebra.lie_algebra
       data.complex.basic

example (z : ) : (complex.conj z).im = -z.im := by simp [complex.conj_im]

Sebastien Gouezel (Mar 04 2020 at 16:33):

The culprit for me was a memory problem. I increased the maximum memory in my Vscode, and the problem disappeared.

Gabriel Ebner (Mar 04 2020 at 16:36):

I get the error on the command-line as well, even with the imports reduced to algebra.lie_algebra and data.complex.basic.

Gabriel Ebner (Mar 04 2020 at 16:38):

Mmmh, import algebra.lie_algebra seems to be the culprit.

Gabriel Ebner (Mar 04 2020 at 16:40):

Oh wow, it's an instance issue, again.

Reid Barton (Mar 04 2020 at 16:40):

I've had a number of instances in the category theory library in which simp would refuse to apply a lemma for apparently no reason. Some cases were related to simp's handling of syntactic equality of implicit parameters but in other cases there seemed to be no explanation.

Gabriel Ebner (Mar 04 2020 at 16:40):

[class_instances]  class-instance resolution trace
[class_instances] (0) ?x_32 : @lie_ring ℝ real.add_comm_group := @lie_algebra.to_lie_ring ?x_33 ?x_34 ?x_35 ?x_36 ?x_37
[class_instances] (1) ?x_35 : comm_ring ?x_33 := @subalgebra.comm_ring ?x_38 ?x_39 ?x_40 ?x_41 ?x_42 ?x_43
[class_instances] (2) ?x_41 : comm_ring ?x_39 := @subalgebra.comm_ring ?x_44 ?x_45 ?x_46 ?x_47 ?x_48 ?x_49
[class_instances] (3) ?x_47 : comm_ring ?x_45 := @subalgebra.comm_ring ?x_50 ?x_51 ?x_52 ?x_53 ?x_54 ?x_55
[class_instances] (4) ?x_53 : comm_ring ?x_51 := @subalgebra.comm_ring ?x_56 ?x_57 ?x_58 ?x_59 ?x_60 ?x_61
[class_instances] (5) ?x_59 : comm_ring ?x_57 := @subalgebra.comm_ring ?x_62 ?x_63 ?x_64 ?x_65 ?x_66 ?x_67
[class_instances] (6) ?x_65 : comm_ring ?x_63 := @subalgebra.comm_ring ?x_68 ?x_69 ?x_70 ?x_71 ?x_72 ?x_73
[class_instances] (7) ?x_71 : comm_ring ?x_69 := @subalgebra.comm_ring ?x_74 ?x_75 ?x_76 ?x_77 ?x_78 ?x_79
[class_instances] (8) ?x_77 : comm_ring ?x_75 := @subalgebra.comm_ring ?x_80 ?x_81 ?x_82 ?x_83 ?x_84 ?x_85
[class_instances] (9) ?x_83 : comm_ring ?x_81 := @subalgebra.comm_ring ?x_86 ?x_87 ?x_88 ?x_89 ?x_90 ?x_91
[class_instances] (10) ?x_89 : comm_ring ?x_87 := @subalgebra.comm_ring ?x_92 ?x_93 ?x_94 ?x_95 ?x_96 ?x_97

Reid Barton (Mar 04 2020 at 16:42):

In some cases it also seems to get worse over time, that is, with new mathlib the simp stops working and there is no clear reason.

Sebastien Gouezel (Mar 04 2020 at 16:42):

It's really funny. In

example (z : ) : (complex.conj z).im = -z.im := by simp [complex.conj_im]

class lie_algebra (R : Type u) (L : Type v)
  [comm_ring R] [add_comm_group L] extends module R L, lie_ring L :=
(lie_smul :  (t : R) (x y : L), x, t  y = t  x, y)

example (z : ) : (complex.conj z).im = -z.im := by simp [complex.conj_im]

the first example works, and the second one fails. And yes, they are absolutely identical, but just adding a class inbetween has messed up typeclass search.

Reid Barton (Mar 04 2020 at 16:43):

aha! Well this lie_algebra R L extends lie_ring L is a known anti-pattern

Sebastien Gouezel (Mar 04 2020 at 16:43):

We need a linter for this!

Gabriel Ebner (Mar 04 2020 at 16:44):

This works:

example (z : ) : (complex.conj z).im = -z.im := by simp [-lie_skew]

The lie_skew lemma has a [lie_ring L] argument which triggers this ugly search.

Gabriel Ebner (Mar 04 2020 at 16:48):

Thanks @Sebastien Gouezel and @Reid Barton for debugging this!

Gabriel Ebner (Mar 04 2020 at 16:48):

@Reid Barton Is there a standard replacement for this anti-pattern?

Reid Barton (Mar 04 2020 at 16:49):

move [lie_ring L] to before extends, and then add it as another argument in 100 places

Reid Barton (Mar 04 2020 at 16:50):

Although perhaps lie_ring could extend add_comm_group, which would help a bit

Reid Barton (Mar 04 2020 at 16:53):

I also have to say I don't understand why simp gets as far as trying to synthesize this instance

Reid Barton (Mar 04 2020 at 17:03):

So concretely, change

class lie_ring (L : Type v) [add_comm_group L] extends has_bracket L :=

to

class lie_ring (L : Type v) extends has_bracket L, add_comm_group L :=

and

class lie_algebra (R : Type u) (L : Type v)
  [comm_ring R] [add_comm_group L] extends module R L, lie_ring L :=

to

class lie_algebra (R : Type u) (L : Type v)
  [comm_ring R] [lie_ring L] extends module R L :=

Reid Barton (Mar 04 2020 at 17:04):

then delete [add_comm_group L] elsewhere or replace it by [lie_ring L] as appropriate

Gabriel Ebner (Mar 04 2020 at 17:09):

Is there a canonical Lie structure on a ring? Lots of lie_ring definitions are not instances.

Reid Barton (Mar 04 2020 at 17:14):

Yes, there is lie_ring.of_associative_ring ([X,Y]=XYYX[X, Y] = XY - YX). I'm not sure why it is not an instance, but it seems reasonable to have it be opt-in.

Reid Barton (Mar 04 2020 at 17:14):

Is it causing a problem?

Gabriel Ebner (Mar 04 2020 at 17:15):

You have to write more instances by hand now. And the errors that you get when you have an extra add_comm_group instance lying around are not pretty.

Gabriel Ebner (Mar 04 2020 at 17:16):

#2084

Floris van Doorn (Mar 04 2020 at 17:21):

We need a linter for this!

The linter dangerous_instanceshould find this. I will investigate why it doesn't.

Reid Barton (Mar 04 2020 at 17:22):

I see. There seem to be two changes going on here.

  • Since lie_algebra no longer extends lie_ring but is indexed on it you have to write two instances instead of one.
  • In the lie_algebra instance the lie_ring part can't be inferred from the definition, and also can't be inferred from instance search because what I've been calling instances are not actually instances at all.

Reid Barton (Mar 04 2020 at 17:24):

For the second one maybe we can just make lie_ring.of_associative_ring an instance after all. @Oliver Nash @Johan Commelin was there a strong reason to not have it be an instance? I assume it was discussed at some point on the github issue but there are way too many collapsed comments to go looking for it...

Reid Barton (Mar 04 2020 at 17:25):

Gabriel, do you need this to bump the mathlib version or something?

Floris van Doorn (Mar 04 2020 at 17:26):

The linter dangerous_instanceshould find this. I will investigate why it doesn't.

Oh, dangerous_instance does catch this problem:

The following arguments become metavariables. argument 1: (R : Type u)

The problem is that currently linters are disabled for automatically generated definitions. This is necessary for many linters, but linters that check the library more globally (like the instance checking and simp-lemma checking) should be enabled for automatically generated declarations. This in on my to-do list.

Gabriel Ebner (Mar 04 2020 at 17:26):

Kind of, in the lean36 branch the simp_nf linter produces lots of timeouts. This is one of the timeouts.

Reid Barton (Mar 04 2020 at 17:33):

I think https://github.com/leanprover-community/mathlib/pull/1644#discussion_r343902029 is about this lie ring of ring instance/def

Reid Barton (Mar 04 2020 at 17:39):

Yes, I remember now. Another concern is if you have an instance saying a product of Lie algebras is a Lie algebra, then a product of rings becomes a Lie algebra in two ways. In this case I believe the resulting definitions will work out to be defeq, but in general there could be a problem.

Johan Commelin (Mar 04 2020 at 17:44):

Sorry for (partially) causing this mess.

Johan Commelin (Mar 04 2020 at 17:45):

I think we didn't make it an instance because we thought it was better to be conservative for now.

Reid Barton (Mar 04 2020 at 17:46):

Gabriel I think your change looks fine. Actually the ones for matrix n n R really should be instances, I think, because this is the "by definition" instance. (Unless we wanted to make a synonym gl n R := matrix n n R and attach the instance to that instead.) That would save one occurrence of @lie_algebra.

Reid Barton (Mar 04 2020 at 17:47):

Johan I think I even also argued that it should not be an instance.

Johan Commelin (Mar 04 2020 at 17:54):

@Gabriel Ebner What is the best way forward? Should this be fixed in a separate PR?

Johan Commelin (Mar 04 2020 at 17:55):

Because I guess that we are running the risk that the bump PR is going to be a huge mess of little changes, and if multiple people contribute, then there will be nobody who has an overview of whether the PR is still doing only harmless changes...

Reid Barton (Mar 04 2020 at 17:57):

Do you mean other than #2084?

Reid Barton (Mar 04 2020 at 17:57):

or is that already a "separate PR"?

Johan Commelin (Mar 04 2020 at 17:57):

Ooh, I hadn't seen that one yet...

Johan Commelin (Mar 04 2020 at 18:00):

I think this is fine as is. I wouldn't be surprised if we want the gl synonym/abbreviation. We can always turn that def into an instance later.

Johan Commelin (Mar 04 2020 at 18:02):

@Floris van Doorn If you can make the linter catch these errors that would be great. It would prevent future me from messing up again.

Johan Commelin (Mar 04 2020 at 18:04):

@Gabriel Ebner I've put #2084 on the merge queue

Scott Morrison (Mar 04 2020 at 19:21):

The linter is upset with #2084 because of

-- algebra/ordered_group.lean
#print add_neg_le_iff_le_add /- Left-hand side simplifies from
  a + -c ≤ b
to
  a ≤ c + b
using
  [add_neg_le_iff_le_add']
Try to change the left-hand side to the simplified term!
 -/

Scott Morrison (Mar 04 2020 at 19:22):

How was this not a problem previously?

Gabriel Ebner (Mar 04 2020 at 19:46):

Do you remember my original complaint in this thread? Apparently simp refuses to rewrite anything if the type class resolution fails (takes too long? not sure) for a single simp lemma. (This looks like a bug.) The lie_skew seems to apply to some (all?) negations and causes a loop in type class resolution. Hence there were a lot of terms that simp did not rewrite, even though they could be simplified with some by simp only [only simp lemmas here]. Now that the lie_algebra issue is fixed, simp is effectively more powerful and the linter can now detect more problems.

Reid Barton (Mar 04 2020 at 19:54):

What I think is the most surprising thing about this is that these simp failures are indistinguishable from "simp couldn't make any progress", right?

Reid Barton (Mar 04 2020 at 19:55):

So when simp fails to apply the lemma you expect, the reason could be that some other lemma is timing out?

Reid Barton (Mar 04 2020 at 19:56):

while one might naively expect that that would instead result in a timeout?

Gabriel Ebner (Mar 04 2020 at 19:59):

Reid Barton said:

So when simp fails to apply the lemma you expect, the reason could be that some other lemma is timing out?

Yes, this is very counterintuitive. But it's the best explanation I have before looking into the C++ code.

Scott Morrison (Mar 04 2020 at 20:02):

Ah, thanks. Sorry for the noise, I was jumping in halfway through.

Gabriel Ebner (Mar 04 2020 at 20:14):

https://github.com/leanprover-community/lean/issues/137

Gabriel Ebner (Mar 04 2020 at 20:15):

The linter actually ignored all errors from simp on purpose. There is a <|> pure none line in the linter. That's because I was getting lots of errors from type class resolution.

Gabriel Ebner (Mar 04 2020 at 20:19):

I've removed the line from the linter that ignores the errors. Let's say what it says now: https://github.com/leanprover-community/mathlib/runs/485926769

Reid Barton (Mar 04 2020 at 20:20):

okay, but in general interactive use... I will just try the example, thanks

Reid Barton (Mar 04 2020 at 20:20):

"neat"

Oliver Nash (Mar 04 2020 at 21:41):

Argh many apologies for mostly causing this mess, and many thanks for the PR which has fixed it.

Patrick Massot (Mar 04 2020 at 21:43):

As you can see from this discussion, these are very subtle issues, and nobody as a good rule book here.

Oliver Nash (Mar 04 2020 at 21:45):

Thanks @Patrick Massot I have just read through the thread and I still feel guilty, but I am too late to have anything to offer.

Rob Lewis (Mar 04 2020 at 21:46):

This is exactly what the linters are for: hard to know you're doing something dangerous, hard for any reviewer to notice, but the computer can notice easily. Finding this kind of situation is good because we can improve the linters.

Kevin Buzzard (Mar 06 2020 at 23:34):

So I am assuming that G_module_hom G M N should not extend add_monoid_hom M N for the same reason?

Kevin Buzzard (Mar 06 2020 at 23:35):

But I can still add a coercion manually, right?

Reid Barton (Mar 06 2020 at 23:47):

are these structures? The issue described here is only relevant to classes

Kevin Buzzard (Mar 06 2020 at 23:48):

Aah! Great!


Last updated: Dec 20 2023 at 11:08 UTC