ring tactic #
A tactic for solving equations in commutative (semi)rings,
where the exponents can also contain variables.
Based on 
More precisely, expressions of the following form are supported:
- constants (non-negative integers)
- variables
- coefficients (any rational number, embedded into the (semi)ring)
- addition of expressions
- multiplication of expressions (a * b)
- scalar multiplication of expressions (n • a; the multiplier must have typeℕ)
- exponentiation of expressions (the exponent must have type ℕ)
- subtraction and negation of expressions (if the base is a full ring)
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.
The normalisation is guided by building a value in the type ExSum at the meta level,
together with a proof (at the base level) that the original value is equal to
the normalised version.
The outline of the file:
- Define a mutual inductive family of types ExSum,ExProd,ExBase, which can represent expressions with+,*,^and rational numerals. The mutual induction ensures that associativity and distributivity are applied, by restricting which kinds of subexpressions appear as arguments to the various operators.
- Represent addition, multiplication and exponentiation in the ExSumtype, thus allowing us to map expressions toExSum(theevalfunction drives this). We apply associativity and distributivity of the operators here (helped byEx*types) and commutativity as well (by sorting the subterms; unfortunately not helped by anything). Any expression not of the above formats is treated as an atom (the same as a variable).
There are some details we glossed over which make the plan more complicated:
- The order on atoms is not initially obvious. We construct a list containing them in order of initial appearance in the expression, then use the index into the list as a key to order on.
- For pow, the exponent must be a natural number, while the base can be any semiringα. We swap out operations for the base ringαwith those for the exponent ringℕas soon as we deal with exponents.
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
A shortcut instance for CommSemiring ℕ used by ring.
Equations
- Mathlib.Tactic.Ring.instCommSemiringNat = inferInstance
Instances For
A typed expression of type CommSemiring ℕ used when we are working on
ring subexpressions of type ℕ.
Instances For
- atom: {u : Lean.Level} → {α : Q(Type u)} → {sα : Q(CommSemiring «$α»)} → {e : Q(«$α»)} → ℕ → Mathlib.Tactic.Ring.ExBase sα eAn atomic expression ewith idid.Atomic expressions are those which ringcannot parse any further. For instance,a + (a % b)hasaand(a % b)as atoms. Thering1tactic does not normalize the subexpressions in atoms, butring_nfdoes.Atoms in fact represent equivalence classes of expressions, modulo definitional equality. The field index : ℕshould be a unique number for each class, whilevalue : exprcontains a representative of this class. The functionresolve_atomdetermines the appropriate atom for a given expression.
- sum: {u : Lean.Level} →
  {α : Q(Type u)} →
    {sα : Q(CommSemiring «$α»)} → {e : Q(«$α»)} → Mathlib.Tactic.Ring.ExSum sα e → Mathlib.Tactic.Ring.ExBase sα eA sum of monomials. 
The base e of a normalized exponent expression.
Instances For
- const: {u : Lean.Level} →
  {α : Q(Type u)} →
    {sα : Q(CommSemiring «$α»)} → {e : Q(«$α»)} → ℚ → optParam (Option Lean.Expr) none → Mathlib.Tactic.Ring.ExProd sα eA coefficient value, which must not be0.eis a raw rat cast. Ifvalueis not an integer, thenhypshould be a proof of(value.den : α) ≠ 0.
- mul: {u : Lean.Level} → {α : Q(Type u)} → {sα : Q(CommSemiring «$α»)} → {x : Q(«$α»)} → {e : Q(ℕ)} → {b : Q(«$α»)} → Mathlib.Tactic.Ring.ExBase sα x → Mathlib.Tactic.Ring.ExProd Mathlib.Tactic.Ring.sℕ e → Mathlib.Tactic.Ring.ExProd sα b → Mathlib.Tactic.Ring.ExProd sα q(«$x» ^ «$e» * «$b»)
A monomial, which is a product of powers of ExBase expressions,
terminated by a (nonzero) constant coefficient.
Instances For
- zero: {u : Lean.Level} → {α : Q(Type u)} → {sα : Q(CommSemiring «$α»)} → Mathlib.Tactic.Ring.ExSum sα q(0)Zero is a polynomial. eis the expression0.
- add: {u : Lean.Level} →
  {α : Q(Type u)} →
    {sα : Q(CommSemiring «$α»)} →
      {a b : Q(«$α»)} →
        Mathlib.Tactic.Ring.ExProd sα a → Mathlib.Tactic.Ring.ExSum sα b → Mathlib.Tactic.Ring.ExSum sα q(«$a» + «$b»)A sum a + bis a polynomial ifais a monomial andbis another polynomial.
A polynomial expression, which is a sum of monomials.
Instances For
Equality test for expressions. This is not a BEq instance because it is heterogeneous.
Equality test for expressions. This is not a BEq instance because it is heterogeneous.
Equality test for expressions. This is not a BEq instance because it is heterogeneous.
A total order on normalized expressions.
This is not an Ord instance because it is heterogeneous.
A total order on normalized expressions.
This is not an Ord instance because it is heterogeneous.
A total order on normalized expressions.
This is not an Ord instance because it is heterogeneous.
Equations
- Mathlib.Tactic.Ring.instInhabitedSigmaQuotedExBase = { default := { fst := default, snd := Mathlib.Tactic.Ring.ExBase.atom 0 } }
Equations
- Mathlib.Tactic.Ring.instInhabitedSigmaQuotedExSum = { default := { fst := q(0), snd := Mathlib.Tactic.Ring.ExSum.zero } }
Equations
- Mathlib.Tactic.Ring.instInhabitedSigmaQuotedExProd = { default := { fst := default, snd := Mathlib.Tactic.Ring.ExProd.const 0 } }
Converts ExBase sα to ExBase sβ, assuming sα and sβ are defeq.
Converts ExProd sα to ExProd sβ, assuming sα and sβ are defeq.
Converts ExSum sα to ExSum sβ, assuming sα and sβ are defeq.
- expr : Q(«$α»)The normalized result. 
- val : E s.exprThe data associated to the normalization. 
- proof : Q(«$e» = unknown_1)A proof that the original expression is equal to the normalized result. 
The result of evaluating an (unnormalized) expression e into the type family E
(one of ExSum, ExProd, ExBase) is a (normalized) element e'
and a representation E e' for it, and a proof of e = e'.
Instances For
Equations
- Mathlib.Tactic.Ring.instInhabitedResult = match default with | { fst := e', snd := v } => { default := { expr := e', val := v, proof := default } }
Constructs the expression corresponding to .const n.
(The .const constructor does not check that the expression is correct.)
Instances For
Constructs the expression corresponding to .const (-n).
(The .const constructor does not check that the expression is correct.)
Instances For
Constructs the expression corresponding to .const (-n).
(The .const constructor does not check that the expression is correct.)
Equations
- Mathlib.Tactic.Ring.ExProd.mkRat sα x q n d h = { fst := q(Rat.rawCast «$n» «$d»), snd := Mathlib.Tactic.Ring.ExProd.const q (some h) }
Instances For
Embed an exponent (an ExBase, ExProd pair) as an ExProd by multiplying by 1.
Equations
Instances For
Embed ExProd in ExSum by adding 0.
Equations
- Mathlib.Tactic.Ring.ExProd.toSum v = Mathlib.Tactic.Ring.ExSum.add v Mathlib.Tactic.Ring.ExSum.zero
Instances For
Get the leading coefficient of an ExProd.
Instances For
- zero: {u : Lean.Level} →
  {α : Q(Type u)} →
    {sα : Q(CommSemiring «$α»)} →
      {e : Q(«$α»)} → Q(Mathlib.Meta.NormNum.IsNat «$e» 0) → Mathlib.Tactic.Ring.Overlap sα eThe expression e(the sum of monomials) is equal to0.
- nonzero: {u : Lean.Level} →
  {α : Q(Type u)} →
    {sα : Q(CommSemiring «$α»)} →
      {e : Q(«$α»)} → Mathlib.Tactic.Ring.Result (Mathlib.Tactic.Ring.ExProd sα) e → Mathlib.Tactic.Ring.Overlap sα eThe expression e(the sum of monomials) is equal to another monomial (with nonzero leading coefficient).
Two monomials are said to "overlap" if they differ by a constant factor, in which case the constants just add. When this happens, the constant may be either zero (if the monomials cancel) or nonzero (if they add up); the zero case is handled specially.
Instances For
Given monomials va, vb, attempts to add them together to get another monomial.
If the monomials are not compatible, returns none.
For example, xy + 2xy = 3xy is a .nonzero overlap, while xy + xz returns none
and xy + -xy = 0 is a .zero overlap.
Instances For
Adds two polynomials va, vb together to get a normalized result polynomial.
- 0 + b = 0
- a + 0 = 0
- a * x + a * y = a * (x + y)(for- x,- ycoefficients; uses- evalAddOverlap)
- (a₁ + a₂) + (b₁ + b₂) = a₁ + (a₂ + (b₁ + b₂))(if- a₁.lt b₁)
- (a₁ + a₂) + (b₁ + b₂) = b₁ + ((a₁ + a₂) + b₂)(if not- a₁.lt b₁)
Multiplies two monomials va, vb together to get a normalized result monomial.
- x * y = (x * y)(for- x,- ycoefficients)
- x * (b₁ * b₂) = b₁ * (b₂ * x)(for- xcoefficient)
- (a₁ * a₂) * y = a₁ * (a₂ * y)(for- ycoefficient)
- (x ^ ea * a₂) * (x ^ eb * b₂) = x ^ (ea + eb) * (a₂ * b₂)(if- eaand- ebare identical except coefficient)
- (a₁ * a₂) * (b₁ * b₂) = a₁ * (a₂ * (b₁ * b₂))(if- a₁.lt b₁)
- (a₁ * a₂) * (b₁ * b₂) = b₁ * ((a₁ * a₂) * b₂)(if not- a₁.lt b₁)
Multiplies a monomial va to a polynomial vb to get a normalized result polynomial.
- a * 0 = 0
- a * (b₁ + b₂) = (a * b₁) + (a * b₂)
Equations
- One or more equations did not get rendered due to their size.
- Mathlib.Tactic.Ring.evalMul₁ sα va Mathlib.Tactic.Ring.ExSum.zero = { expr := q(0), val := Mathlib.Tactic.Ring.ExSum.zero, proof := q((_ : «$a» * 0 = 0)) }
Instances For
Multiplies two polynomials va, vb together to get a normalized result polynomial.
- 0 * b = 0
- (a₁ + a₂) * b = (a₁ * b) + (a₂ * b)
Equations
- One or more equations did not get rendered due to their size.
- Mathlib.Tactic.Ring.evalMul sα Mathlib.Tactic.Ring.ExSum.zero vb = { expr := q(0), val := Mathlib.Tactic.Ring.ExSum.zero, proof := q((_ : 0 * «$b» = 0)) }
Instances For
Applies Nat.cast to a nat polynomial to produce a polynomial in α.
- An atom ecauses↑eto be allocated as a new atom.
- A sum delegates to ExSum.evalNatCast.
Applies Nat.cast to a nat monomial to produce a monomial in α.
- ↑c = cif- cis a numeric literal
- ↑(a ^ n * b) = ↑a ^ n * ↑b
Applies Nat.cast to a nat polynomial to produce a polynomial in α.
- ↑0 = 0
- ↑(a + b) = ↑a + ↑b
Constructs the scalar multiplication n • a, where both n : ℕ and a : α are normalized
polynomial expressions.
- a • b = a * bif- α = ℕ
- a • b = ↑a * botherwise
Equations
- One or more equations did not get rendered due to their size.
Instances For
Negates a monomial va to get another monomial.
- -c = (-c)(for- ccoefficient)
- -(a₁ * a₂) = a₁ * -a₂
Instances For
Negates a polynomial va to get another polynomial.
- -0 = 0(for- ccoefficient)
- -(a₁ + a₂) = -a₁ + -a₂
Equations
- One or more equations did not get rendered due to their size.
- Mathlib.Tactic.Ring.evalNeg sα rα Mathlib.Tactic.Ring.ExSum.zero = { expr := q(0), val := Mathlib.Tactic.Ring.ExSum.zero, proof := q((_ : -0 = 0)) }
Instances For
Subtracts two polynomials va, vb to get a normalized result polynomial.
- a - b = a + -b
Equations
- One or more equations did not get rendered due to their size.
Instances For
The fallback case for exponentiating polynomials is to use ExBase.toProd to just build an
exponent expression. (This has a slightly different normalization than evalPowAtom because
the input types are different.)
- x ^ e = (x + 0) ^ e * 1
Equations
- One or more equations did not get rendered due to their size.
Instances For
The fallback case for exponentiating polynomials is to use ExBase.toProd to just build an
exponent expression.
- x ^ e = x ^ e * 1 + 0
Equations
- One or more equations did not get rendered due to their size.
Instances For
Attempts to prove that a polynomial expression in ℕ is positive.
- Atoms are not (necessarily) positive
- Sums defer to ExSum.evalPos
Attempts to prove that a monomial expression in ℕ is positive.
- 0 < c(where- cis a numeral) is true by the normalization invariant (- cis not zero)
- 0 < x ^ e * bif- 0 < xand- 0 < b
Attempts to prove that a polynomial expression in ℕ is positive.
- 0 < 0fails
- 0 < a + bif- 0 < aor- 0 < b
The main case of exponentiation of ring expressions is when va is a polynomial and n is a
nonzero literal expression, like (x + y)^5. In this case we work out the polynomial completely
into a sum of monomials.
- x ^ 1 = x
- x ^ (2*n) = x ^ n * x ^ n
- x ^ (2*n+1) = x ^ n * x ^ n * x
There are several special cases when exponentiating monomials:
- 1 ^ n = 1
- x ^ y = (x ^ y)when- xand- yare constants
- (a * b) ^ e = a ^ e * b ^ e
In all other cases we use evalPowProdAtom.
Instances For
- k : Q(ℕ)A raw natural number literal. 
- e' : Q(ℕ)The result of extracting the coefficient is a monic monomial. 
- ve' : Mathlib.Tactic.Ring.ExProd Mathlib.Tactic.Ring.sℕ s.e'e'is a monomial.
The result of extractCoeff is a numeral and a proof that the original expression
factors by this numeral.
Instances For
Given a monomial expression va, splits off the leading coefficient k and the remainder
e', stored in the ExtractCoeff structure.
Instances For
Exponentiates a polynomial va by a monomial vb, including several special cases.
- a ^ 1 = a
- 0 ^ e = 0if- 0 < e
- (a + 0) ^ b = a ^ bcomputed using- evalPowProd
- a ^ b = (a ^ b') ^ kif- b = b' * kand- k > 1
Otherwise a ^ b is just encoded as a ^ b * 1 + 0 using evalPowAtom.
Exponentiates two polynomials va, vb.
- a ^ 0 = 1
- a ^ (b₁ + b₂) = a ^ b₁ * a ^ b₂
Equations
- One or more equations did not get rendered due to their size.
Instances For
- A ring instance on - α, if available.
- dα : Option Q(DivisionRing «$α»)A division ring instance on α, if available.
- A characteristic zero ring instance on - α, if available.
This cache contains data required by the ring tactic during execution.
Instances For
Create a new cache for α by doing the necessary instance searches.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Converts a proof by norm_num that e is a numeral, into a normalization as a monomial:
- e = 0if- norm_numreturns- IsNat e 0
- e = Nat.rawCast n + 0if- norm_numreturns- IsNat e n
- e = Int.rawCast n + 0if- norm_numreturns- IsInt e n
- e = Rat.rawCast n d + 0if- norm_numreturns- IsRat e n d
Instances For
Evaluates an atom, an expression where ring can find no additional structure.
- a = a ^ 1 * 1 + 0
Equations
- One or more equations did not get rendered due to their size.
Instances For
Applies ⁻¹ to a polynomial to get an atom.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Inverts a polynomial va to get a normalized result polynomial.
- c⁻¹ = (c⁻¹)if- cis a constant
- (a ^ b * c)⁻¹ = a⁻¹ ^ b * c⁻¹
Instances For
Inverts a polynomial va to get a normalized result polynomial.
- 0⁻¹ = 0
- a⁻¹ = (a⁻¹)if- ais a nontrivial sum
Equations
- One or more equations did not get rendered due to their size.
Instances For
Divides two polynomials va, vb to get a normalized result polynomial.
- a / b = a * b⁻¹
Equations
- One or more equations did not get rendered due to their size.
Instances For
Checks whether e would be processed by eval as a ring expression,
or otherwise if it is an atom or something simplifiable via norm_num.
We use this in ring_nf to avoid rewriting atoms unnecessarily.
Returns:
- noneif- evalwould process- eas an algebraic ring expression
- some noneif- evalwould treat- eas an atom.
- some (some r)if- evalwould not process- eas an algebraic ring expression, but- NormNum.derivecan nevertheless simplify- e, with result- r.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Evaluates expression e of type α into a normalized representation as a polynomial.
This is the main driver of ring, which calls out to evalAdd, evalMul etc.
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
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
Tactic for solving equations of commutative (semi)rings, allowing variables in the exponent.
- This version of ringfails if the target is not an equality.
- The variant ring1!will use 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
Tactic for solving equations of commutative (semi)rings, allowing variables in the exponent.
- This version of ringfails if the target is not an equality.
- The variant ring1!will use a more aggressive reducibility setting to determine equality of atoms.
Equations
- Mathlib.Tactic.Ring.tacticRing1! = Lean.ParserDescr.node `Mathlib.Tactic.Ring.tacticRing1! 1024 (Lean.ParserDescr.nonReservedSymbol "ring1!" false)