Datatypes for linarith
#
Some of the data structures here are used in multiple parts of the tactic. We split them into their own file.
This file also contains a few convenient auxiliary functions.
A shorthand for tracing the types of a list of proof terms
when the trace.linarith
option is set to true.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Linear expressions #
A linear expression is a list of pairs of variable indices and coefficients, representing the sum of the products of each coefficient with its corresponding variable.
Some functions on Linexp
assume that n : Nat
occurs at most once as the first element of a pair,
and that the list is sorted in decreasing order of the first argument.
This is not enforced by the type but the operations here preserve it.
Instances For
Add two Linexp
s together componentwise.
Preserves sorting and uniqueness of the first argument.
l.get n
returns the value in l
associated with key n
, if it exists, and none
otherwise.
This function assumes that l
is sorted in decreasing order of the first argument,
that is, it will return none
as soon as it finds a key smaller than n
.
Equations
- Linarith.Linexp.get n [] = none
- Linarith.Linexp.get n ((a, b) :: t) = if a < n then none else if a = n then some b else Linarith.Linexp.get n t
Instances For
l.contains n
is true iff n
is the first element of a pair in l
.
Equations
- Linarith.Linexp.contains n = Option.isSome ∘ Linarith.Linexp.get n
Instances For
l.zfind n
returns the value associated with key n
if there is one, and 0 otherwise.
Equations
- Linarith.Linexp.zfind n l = match Linarith.Linexp.get n l with | none => 0 | some v => v
Instances For
l.vars
returns the list of variables that occur in l
.
Instances For
Defines a lex ordering on Linexp
. This function is performance critical.
Equations
- One or more equations did not get rendered due to their size.
- Linarith.Linexp.cmp [] [] = Ordering.eq
- Linarith.Linexp.cmp [] x = Ordering.lt
- x.cmp [] = Ordering.gt
Instances For
Inequalities #
The three-element type Ineq
is used to represent the strength of a comparison between
terms.
- eq: Linarith.Ineq
- le: Linarith.Ineq
- lt: Linarith.Ineq
Instances For
Equations
- Linarith.instDecidableEqIneq x y = if h : x.toCtorIdx = y.toCtorIdx then isTrue ⋯ else isFalse ⋯
Equations
- Linarith.instInhabitedIneq = { default := Linarith.Ineq.eq }
Equations
- Linarith.instReprIneq = { reprPrec := Linarith.reprIneq✝ }
max R1 R2
computes the strength of the sum of two inequalities. If t1 R1 0
and t2 R2 0
,
then t1 + t2 (max R1 R2) 0
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Prints an Ineq
as the corresponding infix symbol.
Equations
- x.toString = match x with | Linarith.Ineq.eq => "=" | Linarith.Ineq.le => "≤" | Linarith.Ineq.lt => "<"
Instances For
Finds the name of a multiplicative lemma corresponding to an inequality strength.
Equations
- x.toConstMulName = match x with | Linarith.Ineq.lt => `Linarith.mul_neg | Linarith.Ineq.le => `Linarith.mul_nonpos | Linarith.Ineq.eq => `Linarith.mul_eq
Instances For
Equations
- Linarith.Ineq.instToString = { toString := Linarith.Ineq.toString }
Equations
- Linarith.Ineq.instToFormat = { format := fun (i : Linarith.Ineq) => Std.Format.text i.toString }
Comparisons with 0 #
The main datatype for FM elimination.
Variables are represented by natural numbers, each of which has an integer coefficient.
Index 0 is reserved for constants, i.e. coeffs.find 0
is the coefficient of 1.
The represented term is coeffs.sum (fun ⟨k, v⟩ ↦ v * Var[k])
.
str determines the strength of the comparison -- is it < 0, ≤ 0, or = 0?
- str : Linarith.Ineq
The strength of the comparison,
<
,≤
, or=
. - coeffs : Linarith.Linexp
The coefficients of the comparison, stored as list of pairs
(i, a)
, wherei
is the index of a recorded atom, anda
is the coefficient.
Instances For
Equations
- Linarith.instInhabitedComp = { default := { str := default, coeffs := default } }
Equations
- Linarith.instReprComp = { reprPrec := Linarith.reprComp✝ }
c.vars
returns the list of variables that appear in the linear expression contained in c
.
Instances For
c.coeffOf a
projects the coefficient of variable a
out of c
.
Equations
- c.coeffOf a = Linarith.Linexp.zfind a c.coeffs
Instances For
c.scale n
scales the coefficients of c
by n
.
Equations
- c.scale n = { str := c.str, coeffs := Linarith.Linexp.scale (↑n) c.coeffs }
Instances For
Comp
has a lex order. First the ineq
s are compared, then the coeff
s.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A Comp
represents a contradiction if its expression has no coefficients and its strength is <,
that is, it represents the fact 0 < 0
.
Equations
- c.isContr = (List.isEmpty c.coeffs && decide (c.str = Linarith.Ineq.lt))
Instances For
Equations
- Linarith.Comp.ToFormat = { format := fun (p : Linarith.Comp) => Std.format p.coeffs ++ Std.Format.text (toString p.str) ++ Std.Format.text "0" }
Parsing into linear form #
Control #
A preprocessor transforms a proof of a proposition into a proof of a different proposition.
The return type is List Expr
, since some preprocessing steps may create multiple new hypotheses,
and some may remove a hypothesis from the list.
A "no-op" preprocessor should return its input as a singleton list.
- name : String
The name of the preprocessor, used in trace output.
- transform : Lean.Expr → Lean.MetaM (List Lean.Expr)
Replace a hypothesis by a list of hypotheses. These expressions are the proof terms.
Instances For
Some preprocessors need to examine the full list of hypotheses instead of working item by item.
As with Preprocessor
, the input to a GlobalPreprocessor
is replaced by, not added to, its
output.
- name : String
The name of the global preprocessor, used in trace output.
- transform : List Lean.Expr → Lean.MetaM (List Lean.Expr)
Replace the collection of all hypotheses with new hypotheses. These expressions are proof terms.
Instances For
Some preprocessors perform branching case splits. A Branch
is used to track one of these case
splits. The first component, an MVarId
, is the goal corresponding to this branch of the split,
given as a metavariable. The List Expr
component is the list of hypotheses for linarith
in this branch.
Equations
Instances For
Some preprocessors perform branching case splits.
A GlobalBranchingPreprocessor
produces a list of branches to run.
Each branch is independent, so hypotheses that appear in multiple branches should be duplicated.
The preprocessor is responsible for making sure that each branch contains the correct goal
metavariable.
- name : String
The name of the global branching preprocessor, used in trace output.
- transform : Lean.MVarId → List Lean.Expr → Lean.MetaM (List Linarith.Branch)
Given a goal, and a list of hypotheses, produce a list of pairs (consisting of a goal and list of hypotheses).
Instances For
A Preprocessor
lifts to a GlobalPreprocessor
by folding it over the input list.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A GlobalPreprocessor
lifts to a GlobalBranchingPreprocessor
by producing only one branch.
Equations
- pp.branching = { name := pp.name, transform := fun (g : Lean.MVarId) (l : List Lean.Expr) => do let __do_lift ← pp.transform l pure [(g, __do_lift)] }
Instances For
process pp l
runs pp.transform
on l
and returns the result,
tracing the result if trace.linarith
is on.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A CertificateOracle
provides a function
produceCertificate : List Comp → Nat → MetaM (HashMap Nat Nat)
.
The default CertificateOracle
used by linarith
is
Linarith.CertificateOracle.simplexAlgorithmSparse
.
Linarith.CertificateOracle.simplexAlgorithmDense
and Linarith.CertificateOracle.fourierMotzkin
are also available (though the Fourier-Motzkin oracle has some bugs).
- produceCertificate : List Linarith.Comp → ℕ → Lean.MetaM (Batteries.HashMap ℕ ℕ)
produceCertificate hyps max_var
tries to derive a contradiction from the comparisons inhyps
by eliminating all variables ≤max_var
. If successful, it returns a mapcoeff : Nat → Nat
as a certificate. This map represents that we can find a contradiction by taking the sum∑ (coeff i) * hyps[i]
.
Instances For
Auxiliary functions #
These functions are used by multiple modules, so we put them here for accessibility.
getRelSides e
returns the left and right hand sides of e
if e
is a comparison,
and fails otherwise.
This function is more naturally in the Option
monad, but it is convenient to put in MetaM
for compositionality.
Equations
- One or more equations did not get rendered due to their size.
Instances For
parseCompAndExpr e
checks if e
is of the form t < 0
, t ≤ 0
, or t = 0
.
If it is, it returns the comparison along with t
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
helper function for error message
Equations
- Linarith.parseCompAndExpr.throwNotZero z = Lean.throwError (Lean.toMessageData "invalid comparison, rhs not zero: " ++ Lean.toMessageData z ++ Lean.toMessageData "")
Instances For
mkSingleCompZeroOf c h
assumes that h
is a proof of t R 0
.
It produces a pair (R', h')
, where h'
is a proof of c*t R' 0
.
Typically R
and R'
will be the same, except when c = 0
, in which case R'
is =
.
If c = 1
, h'
is the same as h
-- specifically, it does not change the type to 1*t R 0
.
Equations
- One or more equations did not get rendered due to their size.