Documentation

Mathlib.Tactic.Ring.Basic

ring tactic #

A tactic for solving equations in commutative (semi)rings, where the exponents can also contain variables. Based on http://www.cs.ru.nl/~freek/courses/tt-2014/read/10.1.1.61.3041.pdf .

More precisely, expressions of the following form are supported:

The extension to exponents means that something like 2 * 2^n * b = b * 2^(n+1) can be proved, even though it is not strictly speaking an equation in the language of commutative rings.

Implementation notes #

The basic approach to prove equalities is to normalise both sides and check for equality. We use Mathlib.Tactic.Ring.Common to implement the normal forms and normalization procedure.

This file defines the evaluation of basic operations such as addition and multipication of the rational coefficients as embedded inside the (semi)ring. This is done using norm_num.

It further implements the core ring1 tactic.

Caveats and future work #

The normalized form of an expression is the one that is useful for the tactic, but not as nice to read. To remedy this, the user-facing normalization calls ringNFCore.

Subtraction cancels out identical terms, but division does not. That is: a - a = 0 := by ring solves the goal, but a / a := 1 by ring doesn't. Note that 0 / 0 is generally defined to be 0, so division cancelling out is not true in general.

Multiplication of powers can be simplified a little bit further: 2 ^ n * 2 ^ n = 4 ^ n := by ring could be implemented in a similar way that 2 * a + 2 * a = 4 * a := by ring already works. This feature wasn't needed yet, so it's not implemented yet.

Tags #

ring, semiring, exponent, power

@[reducible]
def Mathlib.Tactic.Ring.ExBase {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) (e : Q(«$α»)) :

ExBase BaseType sα e stores the structure of a normalized expression e, which appears as the base of an exponent expression e^n. The sum constructor is only used when the exponent n is not a constant.

Equations
Instances For
    @[reducible]
    def Mathlib.Tactic.Ring.ExProd {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) (e : Q(«$α»)) :

    ExProd BaseType sα e stores the structure of a normalized monomial expression e. A monomial here is a product of powers of ExBase expressions, terminated by a (nonzero) constant coefficient. The data of the constant coefficient is stored in the BaseType.

    Equations
    Instances For
      @[reducible]
      def Mathlib.Tactic.Ring.ExSum {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) (e : Q(«$α»)) :

      ExSum BaseType sα e stores the structure of a normalized polynomial expression e, which is a sum of monomials.

      Equations
      Instances For
        theorem Mathlib.Tactic.Ring.cast_pos {R : Type u_1} [CommSemiring R] {a : R} {n : } :
        theorem Mathlib.Tactic.Ring.cast_zero {R : Type u_1} [CommSemiring R] {a : R} :
        Meta.NormNum.IsNat a 0a = 0
        theorem Mathlib.Tactic.Ring.cast_neg {n : } {R : Type u_2} [Ring R] {a : R} :
        theorem Mathlib.Tactic.Ring.cast_nnrat {n d : } {R : Type u_2} [DivisionSemiring R] {a : R} :
        theorem Mathlib.Tactic.Ring.cast_rat {n : } {d : } {R : Type u_2} [DivisionRing R] {a : R} :
        Meta.NormNum.IsRat a n da = Rat.rawCast n d + 0
        def Mathlib.Tactic.Ring.ExProd.mkNat {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) (n : ) :
        (e : Q(«$α»)) × ExProd e

        Constructs the expression corresponding to .const n. (The .const constructor does not check that the expression is correct.)

        Instances For
          def Mathlib.Tactic.Ring.ExProd.mkNegNat {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) :
          Q(Ring «$α»)(n : ) → (e : Q(«$α»)) × ExProd e

          Constructs the expression corresponding to .const (-n). (The .const constructor does not check that the expression is correct.)

          Instances For
            def Mathlib.Tactic.Ring.ExProd.mkNNRat {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) :
            Q(DivisionSemiring «$α»)(q : ) → (n d : Q()) → (h : Lean.Expr) → (e : Q(«$α»)) × ExProd e

            Constructs the expression corresponding to .const q h for q = n / d and h a proof that (d : α) ≠ 0. (The .const constructor does not check that the expression is correct.)

            Equations
            Instances For
              def Mathlib.Tactic.Ring.ExProd.mkNegNNRat {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) :
              Q(DivisionRing «$α»)(q : ) → (n d : Q()) → (h : Lean.Expr) → (e : Q(«$α»)) × ExProd e

              Constructs the expression corresponding to .const q h for q = -(n / d) and h a proof that (d : α) ≠ 0. (The .const constructor does not check that the expression is correct.)

              Equations
              Instances For
                def Mathlib.Tactic.Ring.evalCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {e : Q(«$α»)} :

                Converts a proof by norm_num that e is a numeral, into a normalization as a monomial:

                Instances For

                  Scalar multiplication by #

                  theorem Mathlib.Tactic.Ring.natCast_mul {R : Type u_1} [CommSemiring R] {b₁ b₃ : R} {a₁ a₃ : } (a₂ : ) :
                  a₁ = b₁a₃ = b₃↑(a₁ ^ a₂ * a₃) = b₁ ^ a₂ * b₃
                  theorem Mathlib.Tactic.Ring.natCast_add {R : Type u_1} [CommSemiring R] {b₁ b₂ : R} {a₁ a₂ : } :
                  a₁ = b₁a₂ = b₂↑(a₁ + a₂) = b₁ + b₂
                  partial def Mathlib.Tactic.Ring.ExBase.evalNatCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} ( : Q(CommSemiring «$β»)) {a : Q()} (va : ExBase a) :
                  AtomM (Common.Result (ExBase ) q(«$a»))

                  Applies Nat.cast to a nat polynomial to produce a polynomial in α.

                  • An atom e causes ↑e to be allocated as a new atom.
                  • A sum delegates to ExSum.evalNatCast.
                  partial def Mathlib.Tactic.Ring.ExProd.evalNatCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} ( : Q(CommSemiring «$β»)) {a : Q()} (va : ExProd a) :
                  AtomM (Common.Result (ExProd ) q(«$a»))

                  Applies Nat.cast to a nat monomial to produce a monomial in α.

                  • ↑c = c if c is a numeric literal
                  • ↑(a ^ n * b) = ↑a ^ n * ↑b
                  partial def Mathlib.Tactic.Ring.ExSum.evalNatCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} ( : Q(CommSemiring «$β»)) {a : Q()} (va : ExSum a) :
                  AtomM (Common.Result (ExSum ) q(«$a»))

                  Applies Nat.cast to a nat polynomial to produce a polynomial in α.

                  • ↑0 = 0
                  • ↑(a + b) = ↑a + ↑b

                  Scalar multiplication by #

                  theorem Mathlib.Tactic.Ring.intCast_mul {R : Type u_2} [CommRing R] {b₁ b₃ : R} {a₁ a₃ : } (a₂ : ) :
                  a₁ = b₁a₃ = b₃↑(a₁ ^ a₂ * a₃) = b₁ ^ a₂ * b₃
                  theorem Mathlib.Tactic.Ring.intCast_add {R : Type u_2} [CommRing R] {b₁ b₂ : R} {a₁ a₂ : } :
                  a₁ = b₁a₂ = b₂↑(a₁ + a₂) = b₁ + b₂
                  def Mathlib.Tactic.Ring.ExBase.evalIntCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} ( : Q(CommSemiring «$β»)) {a : Q()} ( : Q(CommRing «$α»)) (va : ExBase a) :
                  AtomM (Common.Result (ExBase ) q(«$a»))

                  Applies Int.cast to an int polynomial to produce a polynomial in α.

                  • An atom e causes ↑e to be allocated as a new atom.
                  • A sum delegates to ExSum.evalIntCast.
                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    def Mathlib.Tactic.Ring.ExProd.evalIntCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} ( : Q(CommSemiring «$β»)) {a : Q()} ( : Q(CommRing «$α»)) (va : ExProd a) :
                    AtomM (Common.Result (ExProd ) q(«$a»))

                    Applies Int.cast to an int monomial to produce a monomial in α.

                    • ↑c = c if c is a numeric literal
                    • ↑(a ^ n * b) = ↑a ^ n * ↑b
                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For
                      def Mathlib.Tactic.Ring.ExSum.evalIntCast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} ( : Q(CommSemiring «$β»)) {a : Q()} ( : Q(CommRing «$α»)) (va : ExSum a) :
                      AtomM (Common.Result (ExSum ) q(«$a»))

                      Applies Int.cast to an int polynomial to produce a polynomial in α.

                      • ↑0 = 0
                      • ↑(a + b) = ↑a + ↑b
                      Equations
                      Instances For
                        def Mathlib.Tactic.Ring.ExBase.cast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} { : Q(CommSemiring «$β»)} {a : Q(«$α»)} :
                        ExBase a(a : Q(«$β»)) × ExBase a

                        Converts ExBase to ExBase, assuming and are defeq.

                        Equations
                        Instances For
                          def Mathlib.Tactic.Ring.ExProd.cast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} { : Q(CommSemiring «$β»)} {a : Q(«$α»)} :
                          ExProd a(a : Q(«$β»)) × ExProd a

                          Converts ExProd to ExProd, assuming and are defeq.

                          Equations
                          Instances For
                            def Mathlib.Tactic.Ring.ExSum.cast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {v : Lean.Level} {β : Q(Type v)} { : Q(CommSemiring «$β»)} {a : Q(«$α»)} :
                            ExSum a(a : Q(«$β»)) × ExSum a

                            Converts ExSum to ExSum, assuming and are defeq.

                            Equations
                            Instances For
                              theorem Mathlib.Tactic.Ring.smul_eq_mul {α : Type u_2} [Mul α] {a a' : α} (h : a = a') (b : α) :
                              a b = a' * b
                              theorem Mathlib.Tactic.Ring.Nat.smul_eq_mul {R : Type u_1} [CommSemiring R] {n n' : } {r : R} (hr : n = r) (hn : n' = n) (a : R) :
                              n' a = r * a
                              theorem Mathlib.Tactic.Ring.Int.smul_eq_mul {R : Type u_1} {n n' : } {r : R} [CommRing R] (hr : n = r) (hn : n' = n) (a : R) :
                              n' a = r * a
                              def Mathlib.Tactic.Ring.RatCoeff.toResult {u : Lean.Level} {α : Q(Type u)} {a : Q(«$α»)} :

                              Turn coefficient data into a NormNum.Result.

                              Equations
                              Instances For

                                Turn a NormNum.Result into coefficient data.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  def Mathlib.Tactic.Ring.RingCompute.add {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {a b : Q(«$α»)} (za : RatCoeff a) (zb : RatCoeff b) :
                                  Lean.MetaM (Common.Result RatCoeff q(«$a» + «$b») × Option Q(Meta.NormNum.IsNat («$a» + «$b») 0))

                                  Add two rational number expressions. If the result is zero, returns a proof of this fact.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    def Mathlib.Tactic.Ring.RingCompute.mul {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {a b : Q(«$α»)} (za : RatCoeff a) (zb : RatCoeff b) :
                                    Lean.MetaM (Common.Result RatCoeff q(«$a» * «$b»))

                                    Evaluate the product of two rational number expressions.

                                    Equations
                                    Instances For
                                      partial def Mathlib.Tactic.Ring.RingCompute.cast {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) ( : Common.Cache ) (v : Lean.Level) (β : Q(Type v)) ( : Q(CommSemiring «$β»)) (_smul : Q(SMul «$β» «$α»)) (x : Q(«$β»)) :
                                      AtomM ((y : Q(«$α»)) × Common.ExSum RatCoeff q(«$y») × Q(∀ (a : «$α»), «$x» a = «$y» * a))

                                      Cast ℕ and ℤ normalized expressions ExSums into α, used to evaluate scalar multiplications.

                                      def Mathlib.Tactic.Ring.RingCompute.neg {u : Lean.Level} {α : Q(Type u)} {a : Q(«$α»)} (_crα : Q(CommRing «$α»)) (za : RatCoeff a) :

                                      Negate rational number expressions.

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For
                                        def Mathlib.Tactic.Ring.RingCompute.pow {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {a : Q(«$α»)} {b : Q()} (za : RatCoeff a) (vb : Common.ExProdNat q(«$b»)) :

                                        Raise a rational number expression to the power of a natural number.

                                        Fails if the exponent is not a literal.

                                        Instances For
                                          def Mathlib.Tactic.Ring.RingCompute.inv {u : Lean.Level} {α : Q(Type u)} (_sα : Q(CommSemiring «$α»)) {a : Q(«$α»)} (czα : Option Q(CharZero «$α»)) (_sfα : Q(Semifield «$α»)) (za : RatCoeff a) :

                                          Evaluate the inverse of a natural number expression.

                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          Instances For
                                            def Mathlib.Tactic.Ring.RingCompute.derive {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) (x : Q(«$α»)) :

                                            Try to evaluate an expression as a rational constant using norm_num.

                                            Equations
                                            • One or more equations did not get rendered due to their size.
                                            Instances For
                                              def Mathlib.Tactic.Ring.RingCompute.isOne {u : Lean.Level} {α : Q(Type u)} ( : Q(CommSemiring «$α»)) {x : Q(«$α»)} (zx : RatCoeff x) :

                                              Decide if x is 1 and provide a proof if so.

                                              Equations
                                              Instances For

                                                The comarisons on the basetype used to compare normalized ring expressions.

                                                Equations
                                                • One or more equations did not get rendered due to their size.
                                                Instances For
                                                  partial def Mathlib.Tactic.Ring.ringCompute {u : Lean.Level} {α : Q(Type u)} { : Q(CommSemiring «$α»)} ( : Common.Cache ) :

                                                  The data used by the ring tactic to normalize the constant coefficients.

                                                  The data used by ring-like tactics to normalize constant coefficients of natural number expressions.

                                                  Equations
                                                  Instances For
                                                    class Mathlib.Tactic.Ring.CSLift (α : Type u) (β : outParam (Type u)) :

                                                    CSLift α β is a typeclass used by ring for lifting operations from α (which is not a commutative semiring) into a commutative semiring β by using an injective map lift : α → β.

                                                    Instances
                                                      class Mathlib.Tactic.Ring.CSLiftVal {α : Type u} {β : outParam (Type u)} [CSLift α β] (a : α) (b : outParam β) :

                                                      CSLiftVal a b means that b = lift a. This is used by ring to construct an expression b from the input expression a, and then run the usual ring algorithm on b.

                                                      • eq : b = CSLift.lift a

                                                        The output value b is equal to the lift of a. This can be supplied by the default instance which sets b := lift a, but ring will treat this as an atom so it is more useful when there are other instances which distribute addition or multiplication.

                                                      Instances
                                                        @[instance 100]
                                                        instance Mathlib.Tactic.Ring.instCSLiftValLift {α β : Type u_2} [CSLift α β] (a : α) :
                                                        theorem Mathlib.Tactic.Ring.of_lift {α β : Type u_2} [inst : CSLift α β] {a b : α} {a' b' : β} [h1 : CSLiftVal a a'] [h2 : CSLiftVal b b'] (h : a' = b') :
                                                        a = b
                                                        theorem Mathlib.Tactic.Ring.of_eq {α : Sort u_2} {a b c : α} :
                                                        a = cb = ca = b

                                                        This is a routine which is used to clean up the unsolved subgoal of a failed ring1 application. It is overridden in Mathlib/Tactic/Ring/RingNF.lean to apply the ring_nf simp set to the goal.

                                                        Frontend of ring1: attempt to close a goal g, assuming it is an equation of semirings.

                                                        Equations
                                                        • One or more equations did not get rendered due to their size.
                                                        Instances For

                                                          ring1 solves the goal when it is an equality in commutative (semi)rings, allowing variables in the exponent.

                                                          This version of ring fails if the target is not an equality.

                                                          • ring1! uses a more aggressive reducibility setting to determine equality of atoms.
                                                          Equations
                                                          • One or more equations did not get rendered due to their size.
                                                          Instances For

                                                            ring1 solves the goal when it is an equality in commutative (semi)rings, allowing variables in the exponent.

                                                            This version of ring fails if the target is not an equality.

                                                            • ring1! uses a more aggressive reducibility setting to determine equality of atoms.
                                                            Equations
                                                            Instances For