File: Mathlib/Tactic/Positivity/Core.lean

full_name: positivity
code: /-- Attribute for identifying `positivity` extensions. -/
syntax (name := positivity) "positivity " term,+ : attr
goal: Lean.ParserDescr

full_name: ne_of_ne_of_eq'
code: lemma ne_of_ne_of_eq' {α : Sort*} {a c b : α} (hab : (a : α) ≠ c) (hbc : a = b) : b ≠ c 
goal: b ≠ c

full_name: Mathlib.Meta.Positivity.Strictness.positive
code: /-- The result of `positivity` running on an expression `e` of type `α`. -/
inductive Strictness (e : Q($α)) where
  | positive (pf : Q(0 < $e))
  | nonnegative (pf : Q(0 ≤ $e))
  | nonzero (pf : Q($e ≠ 0))
  | none
  deriving Repr
goal: Mathlib.Meta.Positivity.Strictness zα pα e

full_name: Mathlib.Meta.Positivity.Strictness.nonzero
code: /-- The result of `positivity` running on an expression `e` of type `α`. -/
inductive Strictness (e : Q($α)) where
  | positive (pf : Q(0 < $e))
  | nonnegative (pf : Q(0 ≤ $e))
  | nonzero (pf : Q($e ≠ 0))
  | none
  deriving Repr
goal: Mathlib.Meta.Positivity.Strictness zα pα e

full_name: Mathlib.Meta.Positivity.Strictness.nonnegative
code: /-- The result of `positivity` running on an expression `e` of type `α`. -/
inductive Strictness (e : Q($α)) where
  | positive (pf : Q(0 < $e))
  | nonnegative (pf : Q(0 ≤ $e))
  | nonzero (pf : Q($e ≠ 0))
  | none
  deriving Repr
goal: Mathlib.Meta.Positivity.Strictness zα pα e

full_name: Mathlib.Meta.Positivity.Strictness.none
code: /-- The result of `positivity` running on an expression `e` of type `α`. -/
inductive Strictness (e : Q($α)) where
  | positive (pf : Q(0 < $e))
  | nonnegative (pf : Q(0 ≤ $e))
  | nonzero (pf : Q($e ≠ 0))
  | none
  deriving Repr
goal: Mathlib.Meta.Positivity.Strictness zα pα e

full_name: Mathlib.Meta.Positivity.Strictness
code: /-- The result of `positivity` running on an expression `e` of type `α`. -/
inductive Strictness (e : Q($α)) where
  | positive (pf : Q(0 < $e))
  | nonnegative (pf : Q(0 ≤ $e))
  | nonzero (pf : Q($e ≠ 0))
  | none
  deriving Repr
goal: Type

full_name: Mathlib.Meta.Positivity.instReprStrictness
code: /-- The result of `positivity` running on an expression `e` of type `α`. -/
inductive Strictness (e : Q($α)) where
  | positive (pf : Q(0 < $e))
  | nonnegative (pf : Q(0 ≤ $e))
  | nonzero (pf : Q($e ≠ 0))
  | none
  deriving Repr
goal: {u : Lean.Level} →
  {α : Q(Type u)} →
    {zα : Q(Zero «$α»)} →
      {pα : Q(PartialOrder «$α»)} → {e : Q(«$α»)} → Repr (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.Strictness.toString
code: /-- Gives a generic description of the `positivity` result. -/
def Strictness.toString {e : Q($α)} : Strictness zα pα e → String
  
goal: Mathlib.Meta.Positivity.Strictness zα pα e → String

full_name: Mathlib.Meta.Positivity.Strictness.toNonneg
code: /-- Extract a proof that `e` is nonnegative, if possible, from `Strictness` information about `e`.
-/
def Strictness.toNonneg {e} : Strictness zα pα e → Option Q(0 ≤ $e)
  
goal: Mathlib.Meta.Positivity.Strictness zα pα e → Option Q(0 ≤ «$e»)

full_name: Mathlib.Meta.Positivity.Strictness.toNonzero
code: /-- Extract a proof that `e` is nonzero, if possible, from `Strictness` information about `e`. -/
def Strictness.toNonzero {e} : Strictness zα pα e → Option Q($e ≠ 0)
  
goal: Mathlib.Meta.Positivity.Strictness zα pα e → Option Q(«$e» ≠ 0)

full_name: Mathlib.Meta.Positivity.PositivityExt.eval
code: /-- An extension for `positivity`. -/
structure PositivityExt where
  /-- Attempts to prove an expression `e : α` is `>0`, `≥0`, or `≠0`. -/
  eval {u} {α : Q(Type u)} (zα : Q(Zero $α)) (pα : Q(PartialOrder $α)) (e : Q($α)) :
    MetaM (Strictness zα pα e)
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.PositivityExt
code: /-- An extension for `positivity`. -/
structure PositivityExt where
  /-- Attempts to prove an expression `e : α` is `>0`, `≥0`, or `≠0`. -/
  eval {u} {α : Q(Type u)} (zα : Q(Zero $α)) (pα : Q(PartialOrder $α)) (e : Q($α)) :
    MetaM (Strictness zα pα e)
goal: Type

full_name: Mathlib.Meta.Positivity.mkPositivityExt
code: /-- Read a `positivity` extension from a declaration of the right type. -/
def mkPositivityExt (n : Name) : ImportM PositivityExt 
goal: Lean.ImportM Mathlib.Meta.Positivity.PositivityExt

full_name: Mathlib.Meta.Positivity.discrTreeConfig
code: /-- Configuration for `DiscrTree`. -/
def discrTreeConfig : WhnfCoreConfig 
goal: Lean.Meta.WhnfCoreConfig

full_name: Mathlib.Meta.Positivity.Entry
code: /-- Each `positivity` extension is labelled with a collection of patterns
which determine the expressions to which it should be applied. -/
abbrev Entry 
goal: Type

full_name: Mathlib.Meta.Positivity.initFn._@.Mathlib.Tactic.Positivity.Core._hyg.956
code: /-- Environment extensions for `positivity` declarations -/
initialize positivityExt : PersistentEnvExtension Entry (Entry × PositivityExt)
    (List Entry × DiscrTree PositivityExt) ←
  -- we only need this to deduplicate entries in the DiscrTree
  have : BEq PositivityExt := ⟨fun _ _ => false⟩
  let insert kss v dt := kss.foldl (fun dt ks => dt.insertCore ks v) dt
  registerPersistentEnvExtension {
    mkInitial := pure ([], {})
    addImportedFn := fun s => do
      let dt ← s.foldlM (init := {}) fun dt s => s.foldlM (init := dt) fun dt (kss, n) => do
        pure (insert kss (← mkPositivityExt n) dt)
      pure ([], dt)
    addEntryFn := fun (entries, s) ((kss, n), ext) => ((kss, n) :: entries, insert kss ext s)
    exportEntriesFn := fun s => s.1.reverse.toArray
  }
goal: IO
  (Lean.PersistentEnvExtension Mathlib.Meta.Positivity.Entry
    (Mathlib.Meta.Positivity.Entry × Mathlib.Meta.Positivity.PositivityExt)
    (List Mathlib.Meta.Positivity.Entry × Lean.Meta.DiscrTree Mathlib.Meta.Positivity.PositivityExt))

full_name: Mathlib.Meta.Positivity.positivityExt
code: /-- Environment extensions for `positivity` declarations -/
initialize positivityExt : PersistentEnvExtension Entry (Entry × PositivityExt)
    (List Entry × DiscrTree PositivityExt) ←
  -- we only need this to deduplicate entries in the DiscrTree
  have : BEq PositivityExt := ⟨fun _ _ => false⟩
  let insert kss v dt := kss.foldl (fun dt ks => dt.insertCore ks v) dt
  registerPersistentEnvExtension {
    mkInitial := pure ([], {})
    addImportedFn := fun s => do
      let dt ← s.foldlM (init := {}) fun dt s => s.foldlM (init := dt) fun dt (kss, n) => do
        pure (insert kss (← mkPositivityExt n) dt)
      pure ([], dt)
    addEntryFn := fun (entries, s) ((kss, n), ext) => ((kss, n) :: entries, insert kss ext s)
    exportEntriesFn := fun s => s.1.reverse.toArray
  }
goal: Lean.PersistentEnvExtension Mathlib.Meta.Positivity.Entry
  (Mathlib.Meta.Positivity.Entry × Mathlib.Meta.Positivity.PositivityExt)
  (List Mathlib.Meta.Positivity.Entry × Lean.Meta.DiscrTree Mathlib.Meta.Positivity.PositivityExt)

full_name: Mathlib.Meta.Positivity.initFn._@.Mathlib.Tactic.Positivity.Core._hyg.1294
code: initialize registerBuiltinAttribute {
  name := `positivity
  descr := "adds a positivity extension"
  applicationTime := .afterCompilation
  add := fun declName stx kind => match stx with
    | `(attr| positivity $es,*) => do
      unless kind == AttributeKind.global do
        throwError "invalid attribute 'positivity', must be global"
      let env ← getEnv
      unless (env.getModuleIdxFor? declName).isNone do
        throwError "invalid attribute 'positivity', declaration is in an imported module"
      if (IR.getSorryDep env declName).isSome then return -- ignore in progress definitions
      let ext ← mkPositivityExt declName
      let keys ← MetaM.run' <| es.getElems.mapM fun stx => do
        let e ← TermElabM.run' <| withSaveInfoContext <| withAutoBoundImplicit <|
          withReader ({ · with ignoreTCFailures := true }) do
            let e ← elabTerm stx none
            let (_, _, e) ← lambdaMetaTelescope (← mkLambdaFVars (← getLCtx).getFVars e)
            return e
        DiscrTree.mkPath e discrTreeConfig
      setEnv <| positivityExt.addEntry env ((keys, declName), ext)
    | _ => throwUnsupportedSyntax
}
goal: IO Unit

full_name: Mathlib.Meta.Positivity.lt_of_le_of_ne'
code: lemma lt_of_le_of_ne' {a b : A} [PartialOrder A] :
    (a : A) ≤ b → b ≠ a → a < b 
goal: a ≤ b → b ≠ a → a < b

full_name: Mathlib.Meta.Positivity.pos_of_isNat
code: lemma pos_of_isNat {n : ℕ} [StrictOrderedSemiring A]
    (h : NormNum.IsNat e n) (w : Nat.ble 1 n = true) : 0 < (e : A) 
goal: 0 < e

full_name: Mathlib.Meta.Positivity.nonneg_of_isNat
code: lemma nonneg_of_isNat {n : ℕ} [OrderedSemiring A]
    (h : NormNum.IsNat e n) : 0 ≤ (e : A) 
goal: 0 ≤ e

full_name: Mathlib.Meta.Positivity.nz_of_isNegNat
code: lemma nz_of_isNegNat {n : ℕ} [StrictOrderedRing A]
    (h : NormNum.IsInt e (.negOfNat n)) (w : Nat.ble 1 n = true) : (e : A) ≠ 0 
goal: e ≠ 0

full_name: Mathlib.Meta.Positivity.pos_of_isRat
code: lemma pos_of_isRat {n : ℤ} {d : ℕ} [LinearOrderedRing A] :
    (NormNum.IsRat e n d) → (decide (0 < n)) → ((0 : A) < (e : A))
  
goal: Mathlib.Meta.NormNum.IsRat e n d → decide (0 < n) = true → 0 < e

full_name: Mathlib.Meta.Positivity.nonneg_of_isRat
code: lemma nonneg_of_isRat {n : ℤ} {d : ℕ} [LinearOrderedRing A] :
    (NormNum.IsRat e n d) → (decide (n = 0)) → (0 ≤ (e : A))
  
goal: Mathlib.Meta.NormNum.IsRat e n d → decide (n = 0) = true → 0 ≤ e

full_name: Mathlib.Meta.Positivity.nz_of_isRat
code: lemma nz_of_isRat {n : ℤ} {d : ℕ} [LinearOrderedRing A] :
    (NormNum.IsRat e n d) → (decide (n < 0)) → ((e : A) ≠ 0)
  
goal: Mathlib.Meta.NormNum.IsRat e n d → decide (n < 0) = true → e ≠ 0

full_name: Mathlib.Meta.Positivity.catchNone
code: /-- Converts a `MetaM Strictness` which can fail
into one that never fails and returns `.none` instead. -/
def catchNone {e : Q($α)} (t : MetaM (Strictness zα pα e)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.throwNone
code: /-- Converts a `MetaM Strictness` which can return `.none`
into one which never returns `.none` but fails instead. -/
def throwNone {m : Type → Type*} {e : Q($α)} [Monad m] [Alternative m]
    (t : m (Strictness zα pα e)) : m (Strictness zα pα e) 
goal: m (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.normNumPositivity
code: /-- Attempts to prove a `Strictness` result when `e` evaluates to a literal number. -/
def normNumPositivity (e : Q($α)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.positivityCanon
code: /-- Attempts to prove that `e ≥ 0` using `zero_le` in a `CanonicallyOrderedAddCommMonoid`. -/
def positivityCanon (e : Q($α)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.compareHypLE
code: /-- A variation on `assumption` when the hypothesis is `lo ≤ e` where `lo` is a numeral. -/
def compareHypLE (lo e : Q($α)) (p₂ : Q($lo ≤ $e)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.compareHypLT
code: /-- A variation on `assumption` when the hypothesis is `lo < e` where `lo` is a numeral. -/
def compareHypLT (lo e : Q($α)) (p₂ : Q($lo < $e)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.compareHypEq
code: /-- A variation on `assumption` when the hypothesis is `x = e` where `x` is a numeral. -/
def compareHypEq (e x : Q($α)) (p₂ : Q($x = $e)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.initFn._@.Mathlib.Tactic.Positivity.Core._hyg.4377
code: initialize registerTraceClass `Tactic.positivity
goal: IO Unit

full_name: Mathlib.Meta.Positivity.initFn._@.Mathlib.Tactic.Positivity.Core._hyg.4441
code: initialize registerTraceClass `Tactic.positivity.failure
goal: IO Unit

full_name: Mathlib.Meta.Positivity.compareHyp
code: /-- A variation on `assumption` which checks if the hypothesis `ldecl` is `a [</≤/=] e`
where `a` is a numeral. -/
def compareHyp (e : Q($α)) (ldecl : LocalDecl) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.orElse
code: /-- The main combinator which combines multiple `positivity` results.
It assumes `t₁` has already been run for a result, and runs `t₂` and takes the best result.
It will skip `t₂` if `t₁` is already a proof of `.positive`, and can also combine
`.nonnegative` and `.nonzero` to produce a `.positive` result. -/
def orElse {e : Q($α)} (t₁ : Strictness zα pα e) (t₂ : MetaM (Strictness zα pα e)) :
    MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: Mathlib.Meta.Positivity.core
code: /-- Run each registered `positivity` extension on an expression, returning a `NormNum.Result`. -/
def core (e : Q($α)) : MetaM (Strictness zα pα e) 
goal: Lean.MetaM (Mathlib.Meta.Positivity.Strictness zα pα e)

full_name: _private.Mathlib.Tactic.Positivity.Core.0.Mathlib.Meta.Positivity.OrderRel
code: private inductive OrderRel : Type
| le : OrderRel -- `0 ≤ a`
| lt : OrderRel -- `0 < a`
| ne : OrderRel -- `a ≠ 0`
| ne' : OrderRel
goal: Type

full_name: _private.Mathlib.Tactic.Positivity.Core.0.Mathlib.Meta.Positivity.OrderRel.ne'
code: private inductive OrderRel : Type
| le : OrderRel -- `0 ≤ a`
| lt : OrderRel -- `0 < a`
| ne : OrderRel -- `a ≠ 0`
| ne' : OrderRel
goal: Mathlib.Meta.Positivity.OrderRel

full_name: _private.Mathlib.Tactic.Positivity.Core.0.Mathlib.Meta.Positivity.OrderRel.lt
code: private inductive OrderRel : Type
| le : OrderRel -- `0 ≤ a`
| lt : OrderRel -- `0 < a`
| ne : OrderRel -- `a ≠ 0`
| ne' : OrderRel
goal: Mathlib.Meta.Positivity.OrderRel

full_name: _private.Mathlib.Tactic.Positivity.Core.0.Mathlib.Meta.Positivity.OrderRel.ne
code: private inductive OrderRel : Type
| le : OrderRel -- `0 ≤ a`
| lt : OrderRel -- `0 < a`
| ne : OrderRel -- `a ≠ 0`
| ne' : OrderRel
goal: Mathlib.Meta.Positivity.OrderRel

full_name: _private.Mathlib.Tactic.Positivity.Core.0.Mathlib.Meta.Positivity.OrderRel.le
code: private inductive OrderRel : Type
| le : OrderRel -- `0 ≤ a`
| lt : OrderRel -- `0 < a`
| ne : OrderRel -- `a ≠ 0`
| ne' : OrderRel
goal: Mathlib.Meta.Positivity.OrderRel

full_name: Mathlib.Meta.Positivity.solve
code: /-- An auxillary entry point to the `positivity` tactic. Given a proposition `t` of the form
`0 [≤/</≠] e`, attempts to recurse on the structure of `t` to prove it. It returns a proof
or fails. -/
def solve (t : Q(Prop)) : MetaM Expr 
goal: Lean.MetaM Lean.Expr

full_name: Mathlib.Meta.Positivity.positivity
code: /-- The main entry point to the `positivity` tactic. Given a goal `goal` of the form `0 [≤/</≠] e`,
attempts to recurse on the structure of `e` to prove the goal.
It will either close `goal` or fail. -/
def positivity (goal : MVarId) : MetaM Unit 
goal: Lean.MetaM Unit

full_name: Mathlib.Tactic.Positivity.positivity
code: /-- Tactic solving goals of the form `0 ≤ x`, `0 < x` and `x ≠ 0`.  The tactic works recursively
according to the syntax of the expression `x`, if the atoms composing the expression all have
numeric lower bounds which can be proved positive/nonnegative/nonzero by `norm_num`.  This tactic
either closes the goal or fails.

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

example {a : ℤ} (ha : 1 < a) : 0 < |(3:ℤ) + a| := by positivity

example {b : ℤ} : 0 ≤ max (-3) (b ^ 2) := by positivity
```
-/
elab (name := positivity) "positivity" : tactic => do
  liftMetaTactic fun g => do Meta.Positivity.positivity g; pure []
goal: Lean.ParserDescr

full_name: Mathlib.Tactic.Positivity._aux_Mathlib_Tactic_Positivity_Core___elabRules_Mathlib_Tactic_Positivity_positivity_1
code: /-- Tactic solving goals of the form `0 ≤ x`, `0 < x` and `x ≠ 0`.  The tactic works recursively
according to the syntax of the expression `x`, if the atoms composing the expression all have
numeric lower bounds which can be proved positive/nonnegative/nonzero by `norm_num`.  This tactic
either closes the goal or fails.

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

example {a : ℤ} (ha : 1 < a) : 0 < |(3:ℤ) + a| := by positivity

example {b : ℤ} : 0 ≤ max (-3) (b ^ 2) := by positivity
```
-/
elab (name := positivity) "positivity" : tactic => do
  liftMetaTactic fun g => do Meta.Positivity.positivity g; pure []
goal: Lean.Elab.Tactic.Tactic