Skip to content

Commit d799b46

Browse files
committed
feat(Positivity): add positivity extensions for NNReal.rpow and ENNReal.rpow (#29463)
1 parent d8b0cfb commit d799b46

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

Mathlib/Analysis/SpecialFunctions/Pow/NNReal.lean

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ theorem coe_rpow (x : ℝ≥0) (y : ℝ) : ((x ^ y : ℝ≥0) : ℝ) = (x : ℝ)
4444
theorem rpow_zero (x : ℝ≥0) : x ^ (0 : ℝ) = 1 :=
4545
NNReal.eq <| Real.rpow_zero _
4646

47+
theorem rpow_zero_pos (x : ℝ≥0) : 0 < x ^ (0 : ℝ) := by rw [rpow_zero]; exact one_pos
48+
4749
@[simp]
4850
theorem rpow_eq_zero_iff {x : ℝ≥0} {y : ℝ} : x ^ y = 0 ↔ x = 0 ∧ y ≠ 0 := by
4951
rw [← NNReal.coe_inj, coe_rpow, ← NNReal.coe_eq_zero]
@@ -456,6 +458,8 @@ theorem rpow_zero {x : ℝ≥0∞} : x ^ (0 : ℝ) = 1 := by
456458
· dsimp only [(· ^ ·), Pow.pow, rpow]
457459
simp
458460

461+
theorem rpow_zero_pos (x : ℝ≥0∞) : 0 < x ^ (0 : ℝ) := by rw [rpow_zero]; exact one_pos
462+
459463
theorem top_rpow_def (y : ℝ) : (⊤ : ℝ≥0∞) ^ y = if 0 < y thenelse if y = 0 then 1 else 0 :=
460464
rfl
461465

@@ -1062,3 +1066,62 @@ end ENNReal
10621066
-- end Tactic
10631067

10641068
-- end Tactics
1069+
1070+
/-! ### Positivity extension -/
1071+
1072+
namespace Mathlib.Meta.Positivity
1073+
open Lean Meta Qq
1074+
1075+
/-- Extension for the `positivity` tactic: exponentiation by a real number is nonnegative when
1076+
the base is nonnegative and positive when the base is positive.
1077+
This is the `NNReal` analogue of `evalRpow` for `Real`. -/
1078+
@[positivity (_ : ℝ≥0) ^ (_ : ℝ)]
1079+
def evalNNRealRpow : PositivityExt where eval {u α} _ _ e := do
1080+
match u, α, e with
1081+
| 0, ~q(ℝ≥0), ~q($a ^ (0 : ℝ)) =>
1082+
assertInstancesCommute
1083+
pure (.positive q(NNReal.rpow_zero_pos $a))
1084+
| 0, ~q(ℝ≥0), ~q($a ^ ($b : ℝ)) =>
1085+
let ra ← core q(inferInstance) q(inferInstance) a
1086+
assertInstancesCommute
1087+
match ra with
1088+
| .positive pa =>
1089+
pure (.positive q(NNReal.rpow_pos $pa))
1090+
| _ => pure (.nonnegative q(zero_le $e))
1091+
| _, _, _ => throwError "not NNReal.rpow"
1092+
1093+
private def isFiniteM? (x : Q(ℝ≥0∞)) : MetaM (Option Q($x ≠ (⊤ : ℝ≥0∞))) := do
1094+
let mvar ← mkFreshExprMVar q($x ≠ (⊤ : ℝ≥0∞))
1095+
let save ← saveState
1096+
let (goals, _) ← Elab.runTactic mvar.mvarId! <|← `(tactic| finiteness)
1097+
if goals.isEmpty then
1098+
pure <| some <|← instantiateMVars mvar
1099+
else
1100+
restoreState save
1101+
pure none
1102+
1103+
/-- Extension for the `positivity` tactic: exponentiation by a real number is nonnegative when
1104+
the base is nonnegative and positive when the base is positive.
1105+
This is the `ENNReal` analogue of `evalRpow` for `Real`. -/
1106+
@[positivity (_ : ℝ≥0∞) ^ (_ : ℝ)]
1107+
def evalENNRealRpow : PositivityExt where eval {u α} _ _ e := do
1108+
match u, α, e with
1109+
| 0, ~q(ℝ≥0∞), ~q($a ^ (0 : ℝ)) =>
1110+
assertInstancesCommute
1111+
pure (.positive q(ENNReal.rpow_zero_pos $a))
1112+
| 0, ~q(ℝ≥0∞), ~q($a ^ ($b : ℝ)) =>
1113+
let ra ← core q(inferInstance) q(inferInstance) a
1114+
let rb ← catchNone <| core q(inferInstance) q(inferInstance) b
1115+
assertInstancesCommute
1116+
match ra, rb with
1117+
| .positive pa, .positive pb =>
1118+
pure (.positive q(ENNReal.rpow_pos_of_nonneg $pa <| le_of_lt $pb))
1119+
| .positive pa, .nonnegative pb =>
1120+
pure (.positive q(ENNReal.rpow_pos_of_nonneg $pa $pb))
1121+
| .positive pa, _ =>
1122+
let some ha ← isFiniteM? a | pure <| .nonnegative q(zero_le $e)
1123+
pure <| .positive q(ENNReal.rpow_pos $pa $ha)
1124+
| _, _ => pure <| .nonnegative q(zero_le $e)
1125+
| _, _, _ => throwError "not ENNReal.rpow"
1126+
1127+
end Mathlib.Meta.Positivity

MathlibTest/positivity.lean

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,13 @@ example [Semifield α] [LinearOrder α] [IsStrictOrderedRing α]
325325

326326
example {a b : ℝ} (ha : 0 ≤ a) : 0 ≤ a ^ b := by positivity
327327
example {a b : ℝ} (ha : 0 < a) : 0 < a ^ b := by positivity
328-
example {a : ℝ≥0} {b : ℝ} (ha : 0 < a) : 0 < (a : ℝ) ^ b := by positivity
329-
-- example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 ≤ b) : 0 < a ^ b := by positivity
330-
-- example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 < b) : 0 < a ^ b := by positivity
328+
example {a : ℝ≥0} {b : ℝ} : 0 ≤ a ^ b := by positivity
329+
example {a : ℝ≥0} {b : ℝ} (ha : 0 < a) : 0 < a ^ b := by positivity
330+
example {a : ℝ≥0∞} {b : ℝ} : 0 ≤ a ^ b := by positivity
331+
example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 ≤ b) : 0 < a ^ b := by positivity
332+
example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 < b) : 0 < a ^ b := by positivity
333+
example {a : ℝ≥0∞} : 0 < a ^ 0 := by positivity
334+
example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hat : a ≠ ⊤) : 0 < a ^ b := by positivity
331335
example {a : ℝ} : 0 < a ^ 0 := by positivity
332336

333337
example {a : ℤ} (ha : 3 < a) : 0 ≤ a ^ 2 + a := by positivity

0 commit comments

Comments
 (0)