Zulip Chat Archive

Stream: general

Topic: integral_undef


Yaël Dillies (Jun 09 2023 at 18:15):

Do we agree that docs#integral_undef is a terrible name? I've been looking several times in the past for the lemma that says that a non-integrable function has integral zero, and I'm only finding it now. I was looking for not_integrable.

Ruben Van de Velde (Jun 09 2023 at 18:17):

integral_eq_zero_of_not_integrable? Maybe a little long

Sebastien Gouezel (Jun 09 2023 at 18:18):

Yes, that's a terrible name. You get used to it, but it's pretty much impossible to discover unless you browse the file. integral_of_not_integrable would be better.

Yaël Dillies (Jun 09 2023 at 18:22):

integral_of_not_integrable is the name I guessed, yes. I will add an alias for discoverability, unless you hate the current name so much that you want a rename.

Anatole Dedecker (Jun 09 2023 at 18:39):

Actually I would say that we could make it a naming pattern for all the default values like that, I would be happy with integral_of_undef, deriv_of_under, csSup_of_undef and so on

Yaël Dillies (Jun 09 2023 at 18:44):

Okay but now you must know whether something holds by definition or because it's a consequence of something earlier.

Yaël Dillies (Jun 09 2023 at 18:45):

That sounds implementation-detaily.

Anatole Dedecker (Jun 09 2023 at 18:50):

Well I only have examples in mind where it is clear what is needed for a definition to make sense, but I get your point. I don’t have strong feelings about this anyway, just felt like the name is not that bad

Yury G. Kudryashov (Jun 09 2023 at 19:23):

In each case listed by @Anatole Dedecker, "of undef" means "in a situation when the textbooks say that the value is undefined".

Yaël Dillies (Jun 09 2023 at 19:24):

Then let's at least have a discoverable alias. I don't mind too much about removing the undef name.

Eric Rodriguez (Jun 09 2023 at 19:24):

I wonder if we could have a tactic that does this sort of stuff, much like nontriviality (that is, gives you that wlog it's integrable by discharging the other case with simp)

Yaël Dillies (Jun 10 2023 at 10:11):

That would be great, but we would need it to handle not just integrability, but also measurability, nonemptiness, nonzeroness...

Damiano Testa (Jun 10 2023 at 10:57):

I can try to give it a go, beginning with a simple case-split: is this non-integrable/integrable, trying to discharge the main goal replacing the integral with zero in one branch, and adding the hypothesis integrable ... in the other.

Damiano Testa (Jun 10 2023 at 12:15):

Here is a very quick implementation:

import Mathlib.MeasureTheory.Integral.Bochner

open Lean Elab Tactic Meta

macro "unint " f:ident : tactic => do
  (`(tactic| (
      (by_cases h_int : MeasureTheory.Integrable $f)
      (pick_goal 2)
      (simp [h_int, MeasureTheory.integral_undef] <;> done )
    )
  ))

open MeasureTheory

universe u v

variable {α : Type u} {E : Type v}

variable [NormedAddCommGroup E] [NormedSpace  E] [CompleteSpace E] [MeasureSpace α]

example (f : α  E) : ( (a : α), f a) = 0 := by
  unint f
  sorry
  /- state:
  α: Type u
  E: Type v
  inst✝³: NormedAddCommGroup E
  inst✝²: NormedSpace ℝ E
  inst✝¹: CompleteSpace E
  inst✝: MeasureSpace α
  f: α → E
  h_int✝: Integrable f
  ⊢ (∫ (a : α), f a) = 0
  -/

Damiano Testa (Jun 10 2023 at 12:16):

If anyone has any "real world" example where they would like to test this tactic, I would be happy to take a look and see what goes wrong with it!

Yaël Dillies (Jun 10 2023 at 12:18):

I really want the general tactic to be called junk.

Damiano Testa (Jun 10 2023 at 12:18):

Sure, junk would probably also case-split on Nat-subtraction, right? :smile:

Damiano Testa (Jun 10 2023 at 12:19):

Since macros can be expanded, maybe this could be the first iteration of junk...

Yaël Dillies (Jun 10 2023 at 12:22):

Yes and yes, that's exactly what I'm thinking. You have a general tactic junk which calls extensions that each deal with junk values in a specific case (0 in a group_with_zero, a ≤ b when b - a : ℕ is in the goal, integrability, nonemptiness, ...).

Damiano Testa (Jun 10 2023 at 12:23):

I agree with you, Yaël, and had a "split nat_sub" tactic in mathlib3. I'd be happy to implement and extend it in mathlib4, but would start with this one, that seems easier.

Damiano Testa (Jun 10 2023 at 12:24):

Maybe we should have a Tactic.Junk namespace and put all the helper tactics for junk in there.

Damiano Testa (Jun 10 2023 at 12:25):

So, the tactic above could be a stub for Tactic.Junk.integrable.

Damiano Testa (Jun 10 2023 at 12:26):

And junk matches the target with all the Junk.whatever that are implemented and adds the various assumptions.

Damiano Testa (Jun 10 2023 at 12:31):

We could even try to have a meta-tactic that takes the predicate and the "junk lemmas" as input and produces a macro expansion like unint above.

Damiano Testa (Jun 10 2023 at 12:32):

Then we could feed all of these trivial case splits to the meta-tactic and get rid of a bunch of junk cases.

Yaël Dillies (Jun 10 2023 at 12:32):

I think we don't want to hardcode the "junk lemmas" into the tactic because that would be too much work to maintain. Instead, we should assume these junk lemmas are in the simp set and try to discharge the goal using simp.

Damiano Testa (Jun 10 2023 at 12:33):

Naturally, some case-splits will be harder and would not fall under this scheme, but many of the ones proposed above probably would.

Damiano Testa (Jun 10 2023 at 12:33):

I am a little wary of leaving a "not-only" simp call in a tactic...

Damiano Testa (Jun 10 2023 at 12:34):

Maybe we could have a junk attribute and use simp only [junk-attribute-lemmas].

Yaël Dillies (Jun 10 2023 at 12:35):

That's still more work than just calling simp, but it's at least less work than curating the list from within the tactic.

Damiano Testa (Jun 10 2023 at 12:35):

(Wrt to simp [no-only], note that above I followed the simp by done to try to mitigate this...)

Yaël Dillies (Jun 10 2023 at 12:35):

I don't see the problem in calling simp to finish a goal, though.

Damiano Testa (Jun 10 2023 at 12:35):

Anyway, we can try with a simple simp and see how it works out.

Damiano Testa (Jun 10 2023 at 12:36):

Ok, I'll try to write the meta-tactic that basically does the above, but takes MeasureTheory.Integrable as a user-input.

Yaël Dillies (Jun 10 2023 at 12:37):

The interesting part of the tactic would be for it to figure out what you want to junk on.

Damiano Testa (Jun 10 2023 at 12:37):

Btw, MeasureTheory.integral_undef is not a simp-lemma.

Yaël Dillies (Jun 10 2023 at 12:37):

It really should :grimacing:

Damiano Testa (Jun 10 2023 at 12:37):

So, simp [h_int] does not actually work.

Damiano Testa (Jun 10 2023 at 12:38):

Anyway, I'll experiment with whatever simp-call works, and we can then discuss about the best way of proceeding.

Damiano Testa (Jun 10 2023 at 12:39):

Yaël Dillies said:

The interesting part of the tactic would be for it to figure out what you want to junk on.

To begin with, it could probably match the head-symbol of the target with the implemented junk-tactics. It might even recurse inside the target goal, looking for applicable junks.

Damiano Testa (Jun 10 2023 at 12:40):

However, this seems like a problem to be addressed later, once the "basic junk-tactics" already work.

Damiano Testa (Jun 10 2023 at 12:51):

docs4#tsum_eq_zero_of_not_summable is also not simp.

Yury G. Kudryashov (Jun 10 2023 at 13:15):

Why integral_undef should be a simp lemma, as opposed to a @[junk] lemma?

Yaël Dillies (Jun 10 2023 at 13:20):

For the same reason that docs#div_zero is a simp lemma.

Yury G. Kudryashov (Jun 10 2023 at 16:31):

div_zero matches syntactically. tsum_eq_zero_of_not_summable tries to prove not (summable _) for each tsum you have.

Yaël Dillies (Jun 10 2023 at 16:33):

Does that actually make any difference performance-wise?

Damiano Testa (Jun 10 2023 at 16:36):

Regardless of performance, here is some reason why I think that having a junk attribute could be useful.

Damiano Testa (Jun 10 2023 at 16:37):

The junk tactic should make a case split on some Prop. If some lemmas are marked @junk, then the tactic could try to match the expression of the target with some of the assumption of the junk-lemmas and "understand" automatically what Prop it should split on, simply inspecting the type of the target.

Damiano Testa (Jun 10 2023 at 16:40):

The junk attribute could even have an optional hypothesis, defaulting to the first assumption that begins with not.

Yaël Dillies (Jun 10 2023 at 16:42):

But then you're going to need tagging many lemmas with @[junk], or do you want to also fall back on simp?

Damiano Testa (Jun 10 2023 at 16:42):

So far, the junk tactic is basically a way of doing

  by_cases [...]
  . simp [something]
  . _

I think that the more it can figure out what to case on and which lemmas to use in simp automatically, the better.

Damiano Testa (Jun 10 2023 at 16:43):

I am happy to fall back on simp, but all considerations of efficiency and workability would have to be tested against some attempt, I think.

Damiano Testa (Jun 10 2023 at 16:44):

Also, I think that the heuristic "case on an assumption that is a negation" is probably getting you a good chunk of junk splits correctly right away.

Damiano Testa (Jun 10 2023 at 16:45):

For the remaining ones, like Summable, Integrable,... we use the attribute.

Damiano Testa (Jun 10 2023 at 16:46):

I am imagining something like what used to happen with to_additive: you have to teach it a dictionary, and then it takes off. Same here: if you introduce a suitable junk value, you teach it to junk.

Yaël Dillies (Jun 10 2023 at 16:46):

So you want to tag the possible case splits, not the lemmas to use? That's what I had in mind too.

Damiano Testa (Jun 10 2023 at 16:47):

The case splits take a Prop, so this is certainly one piece of the equation. In some cases, simp will close the junk goal, but in some others it will not. The junk attribute might guide in this choice.

Yury G. Kudryashov (Jun 10 2023 at 16:49):

nontriviality relies on the default simp set + lemmas tagged with nontriviality

Yury G. Kudryashov (Jun 10 2023 at 16:51):

Because after you apply lemmas that assume Subsingleton, you may get a goal like a * 0 = 0

Damiano Testa (Jun 10 2023 at 16:54):

In a current attempt, this works:

attribute [simp] tsum_eq_zero_of_not_summable
attribute [simp] MeasureTheory.integral_undef

example (f : α  E) : ( a, f a) = 0  Integrable f := by
  junk_gen Integrable f
  exact Or.inr _

example (f :   E) : (∑' x, f x) = 0  Summable f := by
  junk_gen Summable f
  exact Or.inr _

The two "features" are

  • I tagged as simp lemmas, two lemmas that are not simp and
  • that I give explicitly the Prop on which to case split.

I think that the junk tag could help with making the tactic automatically select the right Prop and also using a more suitable simp set.

Damiano Testa (Jun 10 2023 at 16:55):

Ideally, junk would try to produce the Prop and then call simp + junk-attribute to close the trivial goal.

Damiano Testa (Jun 10 2023 at 16:55):

And like nontriviality, it could ask for a hint, in case it does not find a good Prop.

Yury G. Kudryashov (Jun 10 2023 at 17:08):

BTW, !4#4955

Damiano Testa (Jun 10 2023 at 17:10):

I wonder whether it is better to have

  • several ad hoc tactics and then a unified one that simply tries each one of the ad hoc ones, or
  • a single tactic that does all the splitting internally.

Damiano Testa (Jun 10 2023 at 17:11):

Maybe it is the tactics that should be tagged with junk, not the lemmas.

Damiano Testa (Jun 10 2023 at 17:14):

So each tactic could get its special support and then the junk tactic brings them all together.

Yury G. Kudryashov (Jun 10 2023 at 17:15):

In case of inhabit and nontriviality, you often need to speciry the type.

Eric Wieser (Jun 10 2023 at 17:16):

I'm not convinced it's worth buildings tactics for what seems to amount to by_cases something, { simp }.

Eric Wieser (Jun 10 2023 at 17:17):

Even nontriviality R isn't really much more useful that casesI subsingleton_or_nontrivial R

Yury G. Kudryashov (Jun 10 2023 at 17:19):

I like nontriviality

Damiano Testa (Jun 10 2023 at 17:20):

I kind of like the idea of having a tactic that dispatches with the trivial cases-splits. I agree though, that it is essentially doing by_cases X; { simp }; and not much else.

Damiano Testa (Jun 10 2023 at 17:37):

Another situation with special support could be Polynomial, where the case-split on whether the polynomial is 0 or not, could also replace degrees with nat_degree and reduce as much as possible to Nat, instead of WithBot Nat.

Yury G. Kudryashov (Jun 10 2023 at 17:37):

The issue with doing case split on, e.g., Integrable is that often you have two integrals and the formula works because either both functions are integrable, or both functions are not integrable.

Damiano Testa (Jun 10 2023 at 17:38):

Yuri, if you have a good example of where the case-split would help with the proof, let me know and I can try out the junk tactic.

Yury G. Kudryashov (Jun 10 2023 at 18:25):

See, e.g., src4#tsum_mul_left

Yury G. Kudryashov (Jun 10 2023 at 18:26):

The case else is not trivial and depends on whether a = 0 or not.


Last updated: Dec 20 2023 at 11:08 UTC