Zulip Chat Archive
Stream: mathlib4
Topic: Aesop and Lambdas
Moritz Doll (Mar 07 2023 at 11:37):
Aesop (more precisely the continuity
macro) seems to have a major problem when dealing with lambdas. For example we have the continuity lemma Continuous (fun x => f x - f y)
(provided f
and g
are continuous), but aesop
is incapable of proving Continuous (f - g)
from that.
Moritz Doll (Mar 07 2023 at 11:39):
We did add a duplicate theorem for Function.const
, but I don't think that is a good solution, since it will come up more and more
Moritz Doll (Mar 07 2023 at 11:41):
Maybe we need an aesop rule set that unfolds all the fancy names into lambdas and then we flag only the applied version with continuity
.
Jannis Limperg (Mar 07 2023 at 12:21):
Do you know what Lean 3 continuity
did to make this work?
Frédéric Dupuis (Mar 07 2023 at 13:41):
What happens with Continuous ((fun x => f x) - (fun x => g x))
?
Floris van Doorn (Mar 07 2023 at 14:36):
I don't think this is a regression compared to Lean 3. In a random file that imports a bunch of continuity stuff, I get
example {f g : ℝ → ℝ} (hf : continuous f) (hg : continuous g) : continuous (λ x, f x - g x) :=
by continuity -- succeeds
example {f g : ℝ → ℝ} (hf : continuous f) (hg : continuous g) : continuous (f - g) :=
by continuity -- fails
Floris van Doorn (Mar 07 2023 at 14:38):
Note that continuity!
does succeed on both, which applies lemmas up to semireducible transparency.
Jannis Limperg (Mar 08 2023 at 10:53):
This makes sense, but Aesop should be applying lemmas up to default
transparency anyway. I'll investigate. @Moritz Doll if you could extract the relevant defs into an MWE, that would be very helpful.
Eric Wieser (Mar 08 2023 at 12:13):
Isn't default transparency "don't unfold semireducible"?
Jannis Limperg (Mar 08 2023 at 12:18):
In Lean 4, default
transparency is the same as Lean 3's semireducible
afaik.
Eric Wieser (Mar 08 2023 at 12:25):
Does "apply lemmas up to r
" mean "unfold everything more reducible than r
", or does it also include unfolding things with reducibility r
?
Jannis Limperg (Mar 08 2023 at 12:29):
I intended it to mean 'unfold constants with reducibility r
and lower' (where reducible
< instances
< default
< irreducible
). Not sure whether that's standard terminology.
Kyle Miller (Mar 08 2023 at 13:04):
@Eric Wieser Default transparency unfolds semireducible (think what rfl
can do by default). Example:
def f (n : Nat) : Nat := n + 1
example : f n = n + 1 := by rfl
example : f n = n + 1 := by with_reducible rfl -- fails
attribute [reducible] f
example : f n = n + 1 := by with_reducible rfl -- succeeds
Moritz Doll (Mar 08 2023 at 13:27):
@Jannis Limperg
thank you so much for looking into this (and for creating aesop in the first place).
import Mathlib.Topology.Algebra.Group.Basic
variable [TopologicalSpace X] [TopologicalSpace Y] [Sub Y] [ContinuousSub Y]
example (f g : X → Y) (hf : Continuous f) (hg : Continuous g) : Continuous (f - g) := by
continuity
example (f g : X → Y) (hf : Continuous f) (hg : Continuous g) : Continuous (fun x => f x - g x) := by
continuity
example (f g : X → Y) : f - g = fun x => f x - g x := by rfl
Moritz Doll (Mar 08 2023 at 13:41):
There is something very weird going on. I've tried to remove the Mathlib.Topology.Algebra.Group.Basic
dependency and now everything works..
import Mathlib.Topology.Algebra.Group.Basic
variable [TopologicalSpace X] [TopologicalSpace Y] [Sub Y] [ContinuousSub Y]
variable (p : (X → Y) → Prop)
@[continuity] lemma sub' (f g : X → Y) (hf : p f) (hg : p g) : p (fun x => f x - g x) := sorry
example (f g : X → Y) (hf : p f) (hg : p g) : p (f - g) := by
continuity
example (f g : X → Y) (hf : Continuous f) (hg : Continuous g) : Continuous (f - g) := by
continuity
example (f g : X → Y) (hf : Continuous f) (hg : Continuous g) : Continuous (fun x => f x - g x) := by
continuity
Moritz Doll (Mar 08 2023 at 13:50):
more mwe'ified: this works, so the problem is probably not in aesop
.
import Mathlib.Tactic.Continuity
import Mathlib.Algebra.Group.Pi
def p (f : X → Y) : Prop := sorry
variable [Sub Y]
@[continuity] theorem sub' (f g : X → Y) (hf : p f) (hg : p g) : p (fun x => f x - g x) := sorry
example (f g : X → Y) (hf : p f) (hg : p g) : p (f - g) := by
continuity
Moritz Doll (Mar 08 2023 at 13:52):
I will look into this tomorrow.
Moritz Doll (Mar 09 2023 at 11:13):
Ok, my previous example had too many sorry
s and was succeeding because of that. New mwe without any topology and sorry
-free.
import Mathlib.Tactic.Continuity
import Mathlib.Algebra.Group.Pi
variable [AddGroup X] [AddGroup Y]
def p (h : X → Y) : Prop := h 0 = 0
@[aesop safe apply (rule_sets [Continuous])] theorem sub (f g : X → Y) (hf : p f) (hg : p g) :
p (f - g) := by
rw [p] at *
simp [hf, hg]
theorem sub' (f g : X → Y) (hf : p f) (hg : p g) : p (fun x => f x - g x) := by
aesop (rule_sets [Continuous])
Moritz Doll (Mar 09 2023 at 11:18):
(aesop also fails to prove the statement of sub
with the knowledge of sub'
)
Moritz Doll (Mar 18 2023 at 02:18):
I am starting to wonder whether we should just have a intermediate step that transforms functions into the λ
version and then have all lemmas for λ
. In a recent PR for mathlib3 the same issue came up, where a variant for f + g
and λ x, f x + g x
was needed and for many operations there several un-applied ways (bundled up to different structures) to spell the same thing.
Kyle Miller (Mar 18 2023 at 02:41):
Maybe we could do something like the @[elementwise]
attribute that's used in category theory (or @[higher_order]
), where we generate one of the lemmas from the other. @[elementwise]
takes a lemma that's an equation involving morphisms and creates a new lemma that's an equation involving those morphisms applied to some value.
We could also have a tactic that eta expands functions and applies some simp lemmas, to turn f + g
into fun x => f x + g x
for example. I'm not sure what a general interface would be... but doing it for specific arguments to functions like Continuous
is easy enough.
Moritz Doll (Mar 18 2023 at 02:49):
I think having several two (or more) copies of each continuity statement is cluttering the library too much (I want to use aesop
to prove UniformContinuous
, Differentiable
, and ContDiff
as well, so we would have lots of duplicate lemmas). Your second suggestion is what I was thinking of.
Maybe we don't even need that, we can just write all continuity-lemmas and in the λ
-expanded variant and I have some hope that everything might just fit together.
Moritz Doll (Mar 21 2023 at 03:36):
I think I found an aesop bug. According to the trace, aesop fails to apply any lemmas in the second case. @Jannis Limperg
import Mathlib.Topology.Algebra.Group.Basic
-- Plus an import that imports Aesop and contains the line `declare_aesop_rule_sets [Continuous2]`
attribute [aesop unsafe apply (rule_sets [Continuous2])] continuous_id'
attribute [aesop unsafe apply (rule_sets [Continuous2])] continuous_const
attribute [aesop unsafe apply (rule_sets [Continuous2])] Continuous.mul
variable [TopologicalSpace M] [Mul M] [ContinuousMul M]
set_option trace.aesop.steps true
example (y : M) :
Continuous (fun x => x * y) := by
aesop (rule_sets [Continuous2]) -- no problem
example (y : M) :
Continuous (fun x => y * x) := by
aesop (rule_sets [Continuous2]) -- fails
Moritz Doll (Mar 21 2023 at 03:38):
If I take an arbitrary function instead of the identity, then everything works in both cases:
example (f : M → M) (hf : Continuous f) (y : M):
Continuous (fun x => f x * y) := by
aesop (rule_sets [Continuous2])
example (f : M → M) (hf : Continuous f) (y : M) :
Continuous (fun x => y * f x) := by
aesop (rule_sets [Continuous2])
Jireh Loreaux (Mar 21 2023 at 13:59):
I'm not sure that's a bug because the first contains no explicit identity. What if you add continuous_mul
to the list of continuity lemmas?
Moritz Doll (Mar 22 2023 at 02:06):
If one proof is continuous_id'.mul continuous_const
and the other is continuous_const.mul continuous_id'
then I expect aesop
to find them, but of course it is Jannis' call what is a bug and what is intended behaviour.
Adding continuous_mul
does not help, however.
Moritz Doll (Mar 22 2023 at 02:12):
example (y : M) :
Continuous (Function.const M y * id) := by
change Continuous (fun _ => _)
aesop (rule_sets [Continuous2])
does not work either and that has a rather explicit identity in there.
Moritz Doll (Mar 22 2023 at 02:13):
(aesop
normalizes to the function to fun x => y * x
first and then fails)
Last updated: Dec 20 2023 at 11:08 UTC