Skip to content

Commit af5eea3

Browse files
committed
feat: positivity extension for Real.rpow (#4486)
This PR introduces a positivity extension for `Real.rpow`. It is located at the same place as the mathlib3 version, namely in `Analysis/SpecialFunctions/Pow/Real.lean`. Note that the two tests I left commented out fail, but due to coercions from `ℝ≥0∞` not working yet.
1 parent 32e796e commit af5eea3

File tree

2 files changed

+42
-34
lines changed

2 files changed

+42
-34
lines changed

Mathlib/Analysis/SpecialFunctions/Pow/Real.lean

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Authors: Chris Hughes, Abhimanyu Pallavi Sudhir, Jean Lo, Calle Sönne, Sébasti
1010
! if you have ported upstream changes.
1111
-/
1212
import Mathlib.Analysis.SpecialFunctions.Pow.Complex
13+
import Qq
1314

1415

1516
/-! # Power function on `ℝ`
@@ -99,6 +100,8 @@ theorem rpow_pos_of_pos {x : ℝ} (hx : 0 < x) (y : ℝ) : 0 < x ^ y := by
99100
theorem rpow_zero (x : ℝ) : x ^ (0 : ℝ) = 1 := by simp [rpow_def]
100101
#align real.rpow_zero Real.rpow_zero
101102

103+
theorem rpow_zero_pos (x : ℝ) : 0 < x ^ (0 : ℝ) := by simp
104+
102105
@[simp]
103106
theorem zero_rpow {x : ℝ} (h : x ≠ 0) : (0 : ℝ) ^ x = 0 := by simp [rpow_def, *]
104107
#align real.zero_rpow Real.zero_rpow
@@ -699,8 +702,7 @@ theorem exists_rat_pow_btwn {α : Type _} [LinearOrderedField α] [Archimedean
699702

700703
end Real
701704

702-
-- Porting note: tactics removed
703-
-- section Tactics
705+
section Tactics
704706

705707
-- /-!
706708
-- ## Tactic extensions for real powers
@@ -756,32 +758,36 @@ end Real
756758

757759
-- end NormNum
758760

759-
-- namespace Tactic
760-
761-
-- namespace Positivity
762-
763-
-- /-- Auxiliary definition for the `positivity` tactic to handle real powers of reals. -/
764-
-- unsafe def prove_rpow (a b : expr) : tactic strictness := do
765-
-- let strictness_a ← core a
766-
-- match strictness_a with
767-
-- | nonnegative p => nonnegative <$> mk_app `` Real.rpow_nonneg_of_nonneg [p, b]
768-
-- | positive p => positive <$> mk_app `` Real.rpow_pos_of_pos [p, b]
769-
-- | _ => failed
770-
-- #align tactic.positivity.prove_rpow tactic.positivity.prove_rpow
771-
772-
-- end Positivity
773-
774-
-- open Positivity
775-
776-
-- /-- Extension for the `positivity` tactic: exponentiation by a real number is nonnegative when
777-
-- the base is nonnegative and positive when the base is positive. -/
778-
-- @[positivity]
779-
-- unsafe def positivity_rpow : expr → tactic strictness
780-
-- | q(@Pow.pow _ _ Real.hasPow $(a) $(b)) => prove_rpow a b
781-
-- | q(Real.rpow $(a) $(b)) => prove_rpow a b
782-
-- | _ => failed
783-
-- #align tactic.positivity_rpow tactic.positivity_rpow
784-
785-
-- end Tactic
786-
787-
-- end Tactics
761+
namespace Mathlib.Meta.Positivity
762+
763+
open Lean Meta Qq
764+
765+
/-- Extension for the `positivity` tactic: exponentiation by a real number is positive (namely 1)
766+
when the exponent is zero. The other cases are done in `evalRpow`. -/
767+
@[positivity (_ : ℝ) ^ (0 : ℝ), Pow.pow (_ : ℝ) (0 : ℝ), Real.rpow (_ : ℝ) (0 : ℝ)]
768+
def evalRpowZero : Mathlib.Meta.Positivity.PositivityExt where eval {_ _} _ _ e := do
769+
let .app (.app (f : Q(ℝ → ℝ → ℝ)) (a : Q(ℝ))) (_ : Q(ℝ)) ← withReducible (whnf e)
770+
| throwError "not Real.rpow"
771+
guard <|← withDefault <| withNewMCtxDepth <| isDefEq f q(Real.rpow)
772+
pure (.positive (q(Real.rpow_zero_pos $a) : Expr))
773+
774+
/-- Extension for the `positivity` tactic: exponentiation by a real number is nonnegative when
775+
the base is nonnegative and positive when the base is positive. -/
776+
@[positivity (_ : ℝ) ^ (_ : ℝ), Pow.pow (_ : ℝ) (_ : ℝ), Real.rpow (_ : ℝ) (_ : ℝ)]
777+
def evalRpow : Mathlib.Meta.Positivity.PositivityExt where eval {_ _} zα pα e := do
778+
let .app (.app (f : Q(ℝ → ℝ → ℝ)) (a : Q(ℝ))) (b : Q(ℝ)) ← withReducible (whnf e)
779+
| throwError "not Real.rpow"
780+
guard <|← withDefault <| withNewMCtxDepth <| isDefEq f q(Real.rpow)
781+
let ra ← core zα pα a
782+
match ra with
783+
| .positive pa =>
784+
have pa' : Q(0 < $a) := pa
785+
pure (.positive (q(Real.rpow_pos_of_pos $pa' $b) : Expr))
786+
| .nonnegative pa =>
787+
have pa' : Q(0 ≤ $a) := pa
788+
pure (.nonnegative (q(Real.rpow_nonneg_of_nonneg $pa' $b) : Expr))
789+
| _ => pure .none
790+
791+
end Mathlib.Meta.Positivity
792+
793+
end Tactics

test/positivity.lean

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Mathlib.Data.Complex.Exponential
22
import Mathlib.Data.Real.Sqrt
33
import Mathlib.Analysis.Normed.Group.Basic
4+
import Mathlib.Analysis.SpecialFunctions.Pow.Real
45

56
/-! # Tests for the `positivity` tactic
67
@@ -167,11 +168,12 @@ example [LinearOrderedSemifield α] (a : α) : 0 < a ^ (0 : ℤ) := by positivit
167168
-- example {a b : Cardinal.{u}} (ha : 0 < a) : 0 < a ^ b := by positivity
168169
-- example {a b : Ordinal.{u}} (ha : 0 < a) : 0 < a ^ b := by positivity
169170

170-
-- example {a b : ℝ} (ha : 0 ≤ a) : 0 ≤ a ^ b := by positivity
171-
-- example {a b : ℝ} (ha : 0 < a) : 0 < a ^ b := by positivity
172-
-- example {a : ℝ≥0} {b : ℝ} (ha : 0 < a) : 0 < a ^ b := by positivity
171+
example {a b : ℝ} (ha : 0 ≤ a) : 0 ≤ a ^ b := by positivity
172+
example {a b : ℝ} (ha : 0 < a) : 0 < a ^ b := by positivity
173+
example {a : ℝ≥0} {b : ℝ} (ha : 0 < a) : 0 < a ^ b := by positivity
173174
-- example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 ≤ b) : 0 < a ^ b := by positivity
174175
-- example {a : ℝ≥0∞} {b : ℝ} (ha : 0 < a) (hb : 0 < b) : 0 < a ^ b := by positivity
176+
example {a : ℝ} : 0 < a ^ 0 := by positivity
175177

176178
-- example {a : ℝ} (ha : 0 < a) : 0 ≤ ⌊a⌋ := by positivity
177179
-- example {a : ℝ} (ha : 0 ≤ a) : 0 ≤ ⌊a⌋ := by positivity

0 commit comments

Comments
 (0)