Zulip Chat Archive

Stream: mathlib4

Topic: positivity failure


Alex Meiburg (Nov 29 2024 at 02:54):

I noticed something weird with positivity:

example (x : ) (hx : 0 < x) : 0 < 5 + x := by
  positivity --works :)

example : 0 < 5 - (-3) := by
  positivity --works :)

example (x : ) (hx : 0 < x) : 0 < 5 - (-x) := by
  positivity --Doesn't work!

I don't understand why the first two work but the third doesn't. My current understanding, which (checking the source) is also what it looks like it tries to do and what the docs describe it as, is to classify each subexpression as "positive" or "zero" or "negative" (or some combination of them), and then propagate these structurally. I would expect that, in the third case, -x is structurally negative, and 5 is structurally positive, so that 5 - (-x) is a positive minus a negative and so is positive.

Alex Meiburg (Nov 29 2024 at 02:55):

In this case rw [sub_neg_eq_add]; positivity works, but I would like to understand the general case (where it might not be so obvious)

Daniel Weber (Nov 29 2024 at 03:44):

It seems like the lemma 0 < x -> y < 0 -> 0 < x - y is simply missing

Kevin Buzzard (Nov 29 2024 at 05:48):

That might not be a lemma in mathlib because the hypotheses are too strong (either could be weakened to <=)

David Renshaw (Nov 29 2024 at 13:20):

classify each subexpression as "positive" or "zero" or "negative"

No, the three categories are positive, nonnegative and nonzero: https://github.com/leanprover-community/mathlib4/blob/496527772ac807ef3d1ddd4868f2048f9ea478e1/Mathlib/Tactic/Positivity/Core.lean#L35-L40

David Renshaw (Nov 29 2024 at 13:28):

example : 0 < 5 - (-3) := by
  positivity --works :)

This example works because positivity invokes some NormNum logic, which here successfully evaluates the right hand side to a natural number.

David Renshaw (Nov 29 2024 at 13:32):

Adding nonnegative and negative variants to Positivity.Strictness seems to me like it could work, but I think it would require updating many positivity extensions.

Mario Carneiro (Nov 29 2024 at 13:54):

I believe this is a deliberate design decision, @Heather Macbeth can probably explain it better. The short version of it is that positivity is intended for solving positivity goals which are positive for "obvious reasons", and expects you to preprocess the goal until it is obvious.

Mario Carneiro (Nov 29 2024 at 13:55):

it's supposed to correspond to the lines of a calc proof on paper which can be discharged with no further justification. In a case like this I think you would rewrite the a - (-b) to a + b first

Michael Stoll (Nov 29 2024 at 13:58):

To piggyback on this thread: can positivity be made to accept additional hypotheses (like, e.g., linarith does) as in the following?

import Mathlib

lemma foo (x : ) : 0 < x := sorry

example (x : ) : 0 < x := by
  positivity -- fails as expected

example (x : ) : 0 < x := by
  have := foo x
  positivity -- works as expected

example (x : ) : 0 < x := by
  positivity [foo x] -- syntax error, but would be nice to have

Daniel Weber (Nov 29 2024 at 14:37):

I wonder if we could have some with [term1, term2] <tactic> which adds the terms as temporary local variables for the tactic (perhaps also with some syntax to give them names)

Alex Meiburg (Nov 29 2024 at 16:59):

And that would effectively act as have := term1; have := term2; tactic <;> (clear this; clear this) or so?

Daniel Weber (Nov 29 2024 at 17:00):

Yes

Heather Macbeth (Nov 29 2024 at 17:36):

positivity is used a lot, including silently as a side-goal discharger in field_simp, gcongr, etc. One proof of mine which I was profiling recently used positivity 100 times. It's supposed to be "stupid" but fast and predictable.

Heather Macbeth (Nov 29 2024 at 17:38):

Michael Stoll said:

To piggyback on this thread: can positivity be made to accept additional hypotheses

This seems reasonable enough (but it wouldn't be relevant in the major use case, which is when positivity is used silently).

Daniel Weber (Nov 29 2024 at 17:40):

Daniel Weber said:

I wonder if we could have some with [term1, term2] <tactic> which adds the terms as temporary local variables for the tactic (perhaps also with some syntax to give them names)

Maybe there could also be with only which hides everything else from the tactic


Last updated: May 02 2025 at 03:31 UTC