Zulip Chat Archive
Stream: mathlib4
Topic: Regression in continuity
Bhavik Mehta (Oct 23 2023 at 23:00):
import Mathlib.Analysis.Calculus.ContDiffDef
example {x : ℝ} {n : ℕ} : Continuous (fun t : ℝ => (x - t) ^ (n + 1)) :=
by continuity
This fails, but the equivalent works in mathlib3. The error message is
aesop: exceeded maximum number of normalisation iterations (100). This means normalisation probably got stuck in an infinite loop.
Scott Morrison (Oct 23 2023 at 23:09):
I remain unconvinced that continuity
should be implemented on top of aesop
, and think that the mathlib3 implementation on top of solve_by_elim
is likely to be more performant. It just doesn't need the full power of aesop
.
Jireh Loreaux (Oct 23 2023 at 23:28):
Is this the HPow
bug?
Kevin Buzzard (Oct 23 2023 at 23:29):
Can someone remind me why we haven't just merged that one line of gobble-de-gook which fixes it 9 times out of 10?
Eric Wieser (Oct 23 2023 at 23:31):
We don't even need to merge that one line, we can remove the line in core that makes us need the gobble-de-gook
Eric Wieser (Oct 23 2023 at 23:32):
I think the problem is that a better solution is in the pipeline, and so no one wants to think about the fast solution
Bhavik Mehta (Oct 23 2023 at 23:41):
Jireh Loreaux said:
Is this the
HPow
bug?
No - adding the usual incantation doesn't help, nor does it change how the goal here is elaborated
Jireh Loreaux (Oct 23 2023 at 23:44):
I'm curious how elaboration gets it right here but wrong everywhere else. That's strange.
Yaël Dillies (Oct 24 2023 at 06:13):
because it doesn't import Analysis.SpecialFunctions.Pow.Real
Jannis Limperg (Oct 24 2023 at 11:14):
The cause of the timeout is that npowRec
is registered as an unfold
rule. Aesop unfold
works like the unfold
tactic, so it'll unfold recursive functions over and over again, until timeout. (I should probably just forbid unfold
rules for recursive declarations.) Registering npowRec
as a simp
rule instead makes progress:
import Mathlib.Analysis.Calculus.ContDiffDef
erase_aesop_rules [npowRec (rule_sets [Continuous])]
attribute [aesop simp] npowRec
example {x : ℝ} {n : ℕ} : Continuous (fun t : ℝ => (x - t) ^ (n + 1)) := by
continuity
This leaves the goal Continuous (npowRec n)
.
Bhavik Mehta (Oct 24 2023 at 16:03):
Hmm, this still isn't a complete fix because in mathlib3 continuity closes the goal, rather than leaving another goal...
Eric Wieser (Oct 24 2023 at 16:19):
docs#npowRec shouldn't be a rule at all... It should be pow_succ
or similar if we really want such a rule
Eric Wieser (Oct 24 2023 at 16:19):
npowRec
is an implementation detail used to implement Monoid.npow
for only some types.
Moritz Doll (Oct 25 2023 at 01:35):
This works:
import Mathlib.Analysis.Calculus.ContDiffDef
erase_aesop_rules [npowRec (rule_sets [Continuous])]
attribute [aesop apply norm] Continuous.pow
example {x : ℝ} {n : ℕ} : Continuous (fun t : ℝ => (x - t) ^ (n + 1)) := by
continuity
Jireh Loreaux (Oct 25 2023 at 02:08):
I think we may need a separate theorem when the exponent is a numeric literal, but I may be wrong.
Moritz Doll (Oct 25 2023 at 02:14):
example {x : ℝ} : Continuous (fun t : ℝ => (x - t) ^ 5) := by
continuity
works as well
Moritz Doll (Oct 25 2023 at 02:18):
the problem seems to be that the safe
version does not fire, but the norm
-one does and the standard way of adding continuity lemmas is through apply safe
.
Moritz Doll (Oct 25 2023 at 04:12):
Junyan Xu (Oct 25 2023 at 04:32):
I'm puzzled why the first two succeeds but the last fails:
import Mathlib.Topology.ContinuousOn
example {α} [TopologicalSpace α] : Continuous fun p : α × α ↦ p.1 := by continuity -- succeeds
example {α} [TopologicalSpace α] : Continuous fun p : {x : α // x = x} ↦ p.1 := by continuity -- succeeds
example {α} [TopologicalSpace α] : Continuous fun p : {p : α × α // p.1 = p.2} ↦ p.val.1 := by continuity
/- tactic 'aesop' failed, failed to prove the goal. Some goals were not explored because the
maximum rule application depth (30) was reached. Set option 'maxRuleApplicationDepth' to
increase the limit. -/
I have to switch to apply_rules [continuous_fst, continuous_subtype_val, Continuous.comp]
here.
Jannis Limperg (Oct 25 2023 at 08:38):
Moritz Doll said:
the problem seems to be that the
safe
version does not fire, but thenorm
-one does and the standard way of adding continuity lemmas is throughapply safe
.
This is just a bandaid; please don't start adding continuity rules as norm
rules. The underlying issue is:
- Aesop runs
apply
rules withdefault
transparency. - Usually, this is somewhat hidden because Aesop's index selects rules which match the goal at
reducible
transparency. - The index doesn't seem to work well for
continuity
rules, in the sense that it just returns any rule matchingContinuous _
(making it quite pointless :fear:). - As a result,
Continuous.mul
is applied to the goal, since it is defeq to a multiplication after unfoldingnpowRec
.Continuous.mul
also happens to fire beforeContinuous.pow
, so the latter doesn't get a chance any more.
The correct fix is to make sure that continuity
rules are only applied at reducible
transparency:
import Mathlib.Analysis.Calculus.ContDiffDef
erase_aesop_rules [npowRec (rule_sets [Continuous]), Continuous.mul (rule_sets [Continuous])]
attribute [aesop safe (apply (transparency! := reducible))] Continuous.pow Continuous.mul
example {x : ℝ} {n : ℕ} : Continuous (fun t : ℝ => (x - t) ^ (n + 1)) := by
continuity
example {x : ℝ} : Continuous (fun t : ℝ => (x - t) ^ 5) := by
continuity
(I learned all this from set_option trace.aesop true
.)
Jannis Limperg (Oct 25 2023 at 09:04):
Jannis Limperg said:
The index doesn't seem to work well for
continuity
rules, in the sense that it just returns any rule matchingContinuous _
(making it quite pointless :fear:).
This is a limitation of DiscrTree
as currently implemented: it doesn't index lambdas, treating them as wildcards.
Jannis Limperg (Oct 25 2023 at 09:39):
Junyan Xu said:
I'm puzzled why the first two succeeds but the last fails:
import Mathlib.Topology.ContinuousOn example {α} [TopologicalSpace α] : Continuous fun p : α × α ↦ p.1 := by continuity -- succeeds example {α} [TopologicalSpace α] : Continuous fun p : {x : α // x = x} ↦ p.1 := by continuity -- succeeds example {α} [TopologicalSpace α] : Continuous fun p : {p : α × α // p.1 = p.2} ↦ p.val.1 := by continuity /- tactic 'aesop' failed, failed to prove the goal. Some goals were not explored because the maximum rule application depth (30) was reached. Set option 'maxRuleApplicationDepth' to increase the limit. -/
I have to switch to
apply_rules [continuous_fst, continuous_subtype_val, Continuous.comp]
here.
The issue here is that simp
rewrites the goal
⊢ Continuous (β := α × α) fun (x : { p : α × α // p.1 = p.2 }) ↦ ↑x
to
⊢ (Continuous (β := α) fun (x : { p : α × α // p.1 = p.2 }) ↦ x.1.1) ∧
Continuous (β := α) fun (x : { p : α × α // p.1 = p.2 }) ↦ x.1.2
and from there Aesop doesn't do anything useful any more. So Aesop with simp
disabled solves it:
example {α} [TopologicalSpace α] : Continuous fun p : {p : α × α // p.1 = p.2} ↦ p.val.1 := by
aesop (rule_sets [Continuous]) (simp_options := { enabled := false })
Possible fixes:
- Disable the
simp
rule incontinuity
(also good for performance). - Erase this particular
simp
lemma. - Teach Aesop how to make progress from the 'simplified' goal.
Bhavik Mehta (Oct 26 2023 at 01:20):
Without trying any of these, my feeling is that removing the simp rule from continuity
is the most sensible. It brings continuity
back to its old method (which seemed to work reasonably well) of trying continuity rules until you can't any more, it's a performance boost as you say, and it makes the continuity
tactic more modular.
Moritz Doll (Oct 26 2023 at 01:22):
I am testing out these changes right now, let's hope that they don't break anything major.
Notification Bot (Oct 26 2023 at 01:28):
Adomas Baliuka has marked this topic as resolved.
Notification Bot (Oct 26 2023 at 01:29):
Adomas Baliuka has marked this topic as unresolved.
Adomas Baliuka (Oct 26 2023 at 01:33):
Sorry, I misclicked... (Wanted to mark the topic to get notifications)
To add some content to the useless apology, the idea of removing the simp
rule also suggested itself while working on a new differentiability
tactic modeled after continuity
. Since I probably won't get any more comments on the PR or the previous topics discussing it: does anyone have insights into how much the two tactics should be the same? Is there any significant conceptual difference I should keep in mind?
Jireh Loreaux (Oct 26 2023 at 02:10):
@Adomas Baliuka can you link to the PR please?
Adomas Baliuka (Oct 26 2023 at 02:28):
PR, WIP. I asked about it here. It's basically exactly like continuity
(maybe it should be slightly different) but it's slow (often needs heartbeat increase) and I'm confused by some of the behaviours, need to keep looking into it.
Jannis Limperg (Nov 02 2023 at 21:48):
@Moritz Doll let me know if you'd like me to take a look at this.
Eric Wieser (Nov 08 2023 at 02:22):
Jannis Limperg said:
Jannis Limperg said:
The index doesn't seem to work well for
continuity
rules, in the sense that it just returns any rule matchingContinuous _
(making it quite pointless :fear:).This is a limitation of
DiscrTree
as currently implemented: it doesn't index lambdas, treating them as wildcards.
Is there a tracking issue for this?
Tomas Skrivan (Nov 08 2023 at 14:03):
Eric Wieser said:
Is there a tracking issue for this?
I would be very interested in this! In the tactic I'm writing I stopped using DiscrTree
for this exact reason as it was returning too many candidates.
Does anybody know how to properly index lambdas? At least in principle, I would be happy to implement it.
What I'm concerned is how to properly handle eta reduction such that Continuous fun x => Real.exp x
matches Continuous fun x => Real.exp (f x)
with f = fun x => x
and Continuous fun x => exp x + x
matches Continuous fun x => (f x) + (g x)
. Or what to do when there are move bound variables and they appear in the head of the lambda body like Continuous fun array i => array (i+1)
.
Tomas Skrivan (Nov 09 2023 at 19:13):
Eric Wieser said:
Is there a tracking issue for this?
I have created thread for it on #lean4 dev . If it is really considered an issue I can convert it into github issue.
Last updated: Dec 20 2023 at 11:08 UTC