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.
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 : ℕ 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.
l.scale c scales the values in
c without modifying the order or keys.
l.get n returns the value in
l associated with key
n, if it exists, and
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
l.zfind n returns the value associated with key
n if there is one, and 0 otherwise.
Defines a lex ordering on
linexp. This function is performance critical.
- linarith.linexp.cmp ((n1, z1) :: t1) ((n2, z2) :: t2) = ite (n1 < n2) ordering.lt (ite (n2 < n1) ordering.gt (ite (z1 < z2) ordering.lt (ite (z2 < z1) ordering.gt (linarith.linexp.cmp t1 t2))))
- linarith.linexp.cmp ((fst, snd) :: tl) list.nil = ordering.gt
- linarith.linexp.cmp list.nil (hd :: tl) = ordering.lt
- linarith.linexp.cmp list.nil list.nil = ordering.eq
max R1 R2 computes the strength of the sum of two inequalities. If
t1 R1 0 and
t2 R2 0,
t1 + t2 (max R1 R2) 0.
- linarith.ineq.lt.max linarith.ineq.lt = linarith.ineq.lt
- linarith.ineq.lt.max linarith.ineq.le = linarith.ineq.lt
- linarith.ineq.lt.max linarith.ineq.eq = linarith.ineq.lt
- linarith.ineq.le.max linarith.ineq.lt = linarith.ineq.lt
- linarith.ineq.le.max linarith.ineq.le = linarith.ineq.le
- linarith.ineq.le.max linarith.ineq.eq = linarith.ineq.le
- linarith.ineq.eq.max linarith.ineq.lt = linarith.ineq.lt
- linarith.ineq.eq.max linarith.ineq.le = linarith.ineq.le
- linarith.ineq.eq.max linarith.ineq.eq = linarith.ineq.eq
ineq is ordered
eq < le < lt.
- linarith.ineq.lt.cmp linarith.ineq.lt = ordering.eq
- linarith.ineq.lt.cmp linarith.ineq.le = ordering.gt
- linarith.ineq.lt.cmp linarith.ineq.eq = ordering.gt
- linarith.ineq.le.cmp linarith.ineq.lt = ordering.lt
- linarith.ineq.le.cmp linarith.ineq.le = ordering.eq
- linarith.ineq.le.cmp linarith.ineq.eq = ordering.gt
- linarith.ineq.eq.cmp linarith.ineq.lt = ordering.lt
- linarith.ineq.eq.cmp linarith.ineq.le = ordering.lt
- linarith.ineq.eq.cmp linarith.ineq.eq = ordering.eq
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 (λ ⟨k, v⟩, v * Var[k]).
str determines the strength of the comparison -- is it < 0, ≤ 0, or = 0?
Parsing into linear form #
A preprocessor transforms a proof of a proposition into a proof of a different propositon.
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.
Some preprocessors perform branching case splits. A
branch is used to track one of these case
splits. The first component, an
expr, is the goal corresponding to this branch of the split,
given as a metavariable. The
list expr component is the list of hypotheses for
in this branch. Every
expr in this list should be type correct in the context of the associated
Some preprocessors perform branching case splits.
global_branching_preprocessor 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
certificate_oracle is a function
produce_certificate : list comp → ℕ → tactic (rb_map ℕ ℕ).
produce_certificate hyps max_var tries to derive a contradiction from the comparisons in
by eliminating all variables ≤
If successful, it returns a map
coeff : ℕ → ℕ as a certificate.
This map represents that we can find a contradiction by taking the sum
∑ (coeff i) * hyps[i].
certificate_oracle used by
- discharger : tactic unit
- restrict_type : option Type
- restrict_type_reflect : reflected self.restrict_type . "apply_instance"
- exfalso : bool
- transparency : tactic.transparency
- split_hypotheses : bool
- split_ne : bool
- preprocessors : option (list linarith.global_branching_preprocessor)
- oracle : option linarith.certificate_oracle
A configuration object for
cfg.update_reducibility reduce_semi will change the transparency setting of
reduce_semi is true. In this case, it also sets the discharger to
since this is typically needed when using stronger unification.
Auxiliary functions #
These functions are used by multiple modules, so we put them here for accessibility.
mk_single_comp_zero_pf 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.
R' will be the same, except when
c = 0, in which case
c = 1,
h' is the same as
h -- specifically, it does not change the type to
1*t R 0.