ToInt α I asserts that α can be embedded faithfully into an interval I in the integers.
Instance Constructor
Lean.Grind.ToInt.mk.{u}
The linear integer arithmetic solver implements a model-based decision procedure for linear integer arithmetic.
The solver can process four categories of linear polynomial constraints (where p is a linear polynomial):
p = 0
d ∣ p
p ≤ 0
p ≠ 0
It is complete for linear integer arithmetic, and natural numbers are supported by converting them to integers with Int.ofNat.
Support for additional types that can be embedded into Int can be added via instances of Lean.Grind.ToInt.
Nonlinear terms (e.g. x * x) are allowed, and are represented as variables.
The solver is additionally capable of propagating information back to the metaphorical grind whiteboard, which can trigger further progress from the other subsystems.
By default, it is enabled; it can be disabled using the flag -lia
All of these statements can be proved using the linear integer arithmetic solver. In the first example, the left-hand side must be a multiple of 2, and thus cannot be 5:
example {x y : Int} : 2 * x + 4 * y ≠ 5 := x:Inty:Int⊢ 2 * x + 4 * y ≠ 5
All goals completed! 🐙
The solver supports mixing equalities and inequalities:
example {x y : Int} :
2 * x + 3 * y = 0 →
1 ≤ x →
y < 1 := x:Inty:Int⊢ 2 * x + 3 * y = 0 → 1 ≤ x → y < 1
All goals completed! 🐙
It also supports linear divisibility constraints:
example (a b : Int) :
2 ∣ a + 1 →
2 ∣ b + a →
¬ 2 ∣ b + 2 * a := a:Intb:Int⊢ 2 ∣ a + 1 → 2 ∣ b + a → ¬2 ∣ b + 2 * a
All goals completed! 🐙
Without lia, grind cannot prove the statement:
example (a b : Int) :
2 ∣ a + 1 →
2 ∣ b + a →
¬ 2 ∣ b + 2 * a := a:Intb:Int⊢ 2 ∣ a + 1 → 2 ∣ b + a → ¬2 ∣ b + 2 * a
All goals completed! 🐙
The solver is complete for linear integer arithmetic.
However, the search can become vast with very few constraints, but the solver was not designed to perform massive case-analysis.
The qlia option to grind reduces the search space by instructing the solver to accept rational solutions.
With this option, the solver is likely to be faster, but it is incomplete.
The following example has a rational solution, but does not have integer solutions:
example {x y : Int} :
27 ≤ 13 * x + 11 * y →
13 * x + 11 * y ≤ 30 →
-10 ≤ 9 * x - 7 * y →
9 * x - 7 * y > 4 := x:Inty:Int⊢ 27 ≤ 13 * x + 11 * y → 13 * x + 11 * y ≤ 30 → -10 ≤ 9 * x - 7 * y → 9 * x - 7 * y > 4
All goals completed! 🐙
Because it uses the rational solution, grind fails to refute the negation of the goal when +qlia is specified:
example {x y : Int} :
27 ≤ 13 * x + 11 * y →
13 * x + 11 * y ≤ 30 →
-10 ≤ 9 * x - 7 * y →
9 * x - 7 * y > 4 := x:Inty:Int⊢ 27 ≤ 13 * x + 11 * y → 13 * x + 11 * y ≤ 30 → -10 ≤ 9 * x - 7 * y → 9 * x - 7 * y > 4
All goals completed! 🐙
The rational model constructed by the solver is in the section Assignment satisfying linear constraints in the goal diagnostics.
The solver currently does support nonlinear constraints, and treats nonlinear terms such as x * x as variables.
The linear integer arithmetic solver fails to prove this theorem:
example (x : Int) : x * x ≥ 0 := x:Int⊢ x * x ≥ 0
All goals completed! 🐙
From the perspective of the linear integer arithmetic solver, it is equivalent to:
example {y : Int} (x : Int) : y ≥ 0 := y:Intx:Int⊢ y ≥ 0
All goals completed! 🐙
This can be seen by setting the option trace.grind.lia.assert to true, which traces all constraints processed by the solver.
example (x : Int) : x*x ≥ 0 := x:Int⊢ x * x ≥ 0
set_option trace.grind.lia.assert true in
All goals completed! 🐙
The term x ^ 2 is “quoted” in 「x ^ 2」 + 1 ≤ 0 to indicate that x ^ 2 is treated as a variable.
The solver supports linear division and modulo operations.
The solver normalizes commutative (semi)ring expressions.
The solver also implements model-based theory combination, which is a mechanism for propagating equalities back to the metaphorical shared whiteboard.
These additional equalities may in turn trigger new congruences.
Model-based theory combination increases the size of the search space; it can be disabled using the option grind -mbtc.
In the example above, the linear inequalities and disequalities imply y = 0:
example (f : Int → Int) (x y : Int) :
f x = 0 →
0 ≤ y → y ≤ 1 → y ≠ 1 →
f (x + y) = 0 := f:Int → Intx:Inty:Int⊢ f x = 0 → 0 ≤ y → y ≤ 1 → y ≠ 1 → f (x + y) = 0
All goals completed! 🐙
Consequently x = x + y, so f x = f (x + y) by congruence.
Without model-based theory combination, the proof gets stuck:
example (f : Int → Int) (x y : Int) :
f x = 0 →
0 ≤ y → y ≤ 1 → y ≠ 1 →
f (x + y) = 0 := f:Int → Intx:Inty:Int⊢ f x = 0 → 0 ≤ y → y ≤ 1 → y ≠ 1 → f (x + y) = 0
All goals completed! 🐙
The LIA solver can also process linear constraints that contain natural numbers.
It converts them into integer constraints using Int.ofNat.
There is an extensible mechanism via the Lean.Grind.ToInt type class to tell the solver that a type embeds in the integers.
Using this, we can solve goals such as:
example (a b c : Fin 11) : a ≤ 2 → b ≤ 3 → c = a + b → c ≤ 5 := a:Fin 11b:Fin 11c:Fin 11⊢ a ≤ 2 → b ≤ 3 → c = a + b → c ≤ 5
All goals completed! 🐙
example (a : Fin 2) : a ≠ 0 → a ≠ 1 → False := a:Fin 2⊢ a ≠ 0 → a ≠ 1 → False
All goals completed! 🐙
example (a b c : UInt64) : a ≤ 2 → b ≤ 3 → c - a - b = 0 → c ≤ 5 := a:UInt64b:UInt64c:UInt64⊢ a ≤ 2 → b ≤ 3 → c - a - b = 0 → c ≤ 5
All goals completed! 🐙
ToInt α I asserts that α can be embedded faithfully into an interval I in the integers.
Instance Constructor
Lean.Grind.ToInt.mk.{u}
An interval in the integers (either finite, half-infinite, or infinite).
Constructors
Lean.Grind.IntInterval.co (lo hi : Int) : Lean.Grind.IntInterval
The finite interval [lo, hi).
Lean.Grind.IntInterval.ci (lo : Int) : Lean.Grind.IntInterval
The half-infinite interval [lo, ∞).
Lean.Grind.IntInterval.io (hi : Int) : Lean.Grind.IntInterval
The half-infinite interval (-∞, hi).
Lean.Grind.IntInterval.ii : Lean.Grind.IntInterval
The infinite interval (-∞, ∞).
The implementation of the linear integer arithmetic solver is inspired by Section 4 of Jovanović and de Moura (2023)Dejan Jovanović and Leonardo de Moura, 2023. “Cutting to the Chase: Solving Linear Integer Arithmetic”. In Automated Deduction: CADE '23. (LNCS 6803). Compared to the paper, it includes several enhancements and modifications such as:
extended constraint support (equality and disequality),
an optimized encoding of the Cooper-Left rule using a “big”-disjunction instead of fresh variables, and
decision variable tracking for case splits (disequalities, Cooper-Left, Cooper-Right).
The solver procedure builds a model (that is, an assignment of the variables in the term) incrementally, resolving conflicts through constraint generation.
For example, given a partial model {x := 1} and constraint 3 ∣ 3 * y + x + 1:
The solver cannot extend the model to y because 3 ∣ 3 * y + 2 is unsatisfiable.
Thus, it resolves the conflict by generating the implied constraint 3 ∣ x + 1.
The new constraint forces the solver to find a new assignment for x.
When assigning a variable y, the solver considers:
The best upper and lower bounds (inequalities).
A divisibility constraint.
All disequality constraints where y is the maximal variable.
The Cooper-Left and Cooper-Right rules handle the combination of inequalities and divisibility.
For unsatisfiable disequalities p ≠ 0, the solver generates the case split: p + 1 ≤ 0 ∨ -p + 1 ≤ 0.