omega — Linear Arithmetic
omega is a decision procedure for linear arithmetic over integers and natural numbers. It automatically solves goals involving <, ≤, =, +, -, and multiplication by constants. When you see an arithmetic goal that feels "obviously true," omega is usually your answer.
Why omega Matters
Arithmetic reasoning appears constantly in programming and mathematics. Array bounds, loop termination, index validity—all require proving facts about numbers. Withoutomega, you'd need to manually construct these proofs using lemmas like transitivity, commutativity, and associativity. With omega, you just state what you need and let Lean figure out the details.
Think of omega as a calculator for proofs. You don't explain how 2 + 3 = 5—you just know it's true. Similarly, omega "knows" facts like "if x < y and y < z, then x < z" without you spelling out every step.
What omega Solves
omega handles linear arithmetic—inequalities and equations where variables are only multiplied by constants. This includes:
- Comparisons: <, ≤, =, ≠, >, ≥
- Operations: +, -, multiplication by constants
- Division/modulo: /, % by constants
- Types:
NatandInt
1-- Simple inequalities2example (n : Nat) : n ≤ n + 1 := by omega3example (a b : Nat) (h : a < b) : a + 1 ≤ b := by omega4example (x : Int) (h : x > 0) : x ≥ 1 := by omega56-- Arithmetic combinations7example (a b c : Nat) : a + b + c = c + b + a := by omega8example (n : Nat) : 2 * n = n + n := by omega9example (x y : Int) : x - y + y = x := by omega1011-- Constants are OK12example (n : Nat) : 3 * n + 5 * n = 8 * n := by omega13example (x : Int) : 100 * x - 99 * x = x := by omegaomega for any goal that's "obviously true" by arithmetic reasoning. It handles +, -, *, /, %, <, ≤, =, ≠ on Nat and Int.Understanding "Linear"
The word "linear" means variables appear with degree 1 at most. You can have3 * x (constant times variable), but notx * y (variable times variable) orx * x (variable squared).
1-- ✅ Linear: variables multiplied by constants2example (x y : Int) : 3*x + 2*y = 2*y + 3*x := by omega34-- ❌ Non-linear: variables multiplied by variables5-- example (x y : Int) : x * y = y * x := by omega -- Fails!6-- Use 'ring' instead for polynomial equality78-- ✅ This is still linear (100 is a constant)9example (n : Nat) : 100 * n > 99 * n ↔ n > 0 := by omegaNat vs Int: Key Differences
omega works on both Nat andInt, but there are important behavioral differences—especially for subtraction.
Natural Number Subtraction is Truncated
In Nat, subtraction can't go negative. Instead,a - b = 0 when a < b. This is called "truncated subtraction" and omega understands it:
1-- omega knows Nat subtraction is truncated (can't go negative)2example (n : Nat) : n - n = 0 := by omega3example (a b : Nat) : a - b ≤ a := by omega -- Always true!45-- When a ≥ b, subtraction works normally6example (a b : Nat) (h : a ≥ b) : a - b + b = a := by omega78-- When a < b, a - b = 09example (a b : Nat) (h : a < b) : a - b = 0 := by omegaInteger Subtraction is Standard
1-- Int subtraction works as expected (can be negative)2example (n : Int) : n - n = 0 := by omega3example (a b : Int) : a - b + b = a := by omega -- Always true!45-- Negative numbers are fine6example (x : Int) (h : x < 0) : x ≤ -1 := by omega7example (a b : Int) : a - b = -(b - a) := by omegaNat and omega is struggling, try adding a hypothesis like h : a ≥ bto ensure the subtraction doesn't truncate.Using Hypotheses
omega automatically uses all relevant hypotheses in your context. You don't need to tell it which ones to use—it examines them all:
1-- omega uses all hypotheses automatically2example (a b c : Nat) (h1 : a ≤ b) (h2 : b ≤ c) : a ≤ c := by omega34example (x y : Int) (h1 : x < y) (h2 : y < x + 2) : y = x + 1 := by omega56-- It can combine many constraints7example (n : Nat) (h1 : n > 0) (h2 : n < 3) : n = 1 ∨ n = 2 := by omega89-- Complex chains work too10example (a b c d e : Nat) 11 (h1 : a ≤ b) (h2 : b < c) (h3 : c ≤ d) (h4 : d < e) 12 : a < e := by omegaDivision and Modulo
omega handles integer division and modulo operations, which is particularly useful for proving termination arguments and index bounds:
1-- Division bounds2example (n : Nat) : n / 2 ≤ n := by omega3example (n : Nat) (h : n > 1) : n / 2 < n := by omega45-- Modulo bounds6example (n : Nat) : n % 2 < 2 := by omega7example (n m : Nat) (h : m > 0) : n % m < m := by omega89-- The fundamental division identity10example (n : Nat) : 2 * (n / 2) + n % 2 = n := by omega11example (n m : Nat) (h : m > 0) : m * (n / m) + n % m = n := by omega1213-- Parity14example (n : Nat) (h : n % 2 = 0) : 2 * (n / 2) = n := by omega15example (n : Nat) (h : n % 2 = 1) : 2 * (n / 2) + 1 = n := by omegaomega is complete for linear arithmetic—if a goal is provable using only linear reasoning, omega will find the proof.What omega Cannot Do
Understanding omega's limitations helps you know when to reach for other tactics:
Non-linear Multiplication
1-- ❌ Variable × variable is non-linear2-- example (x y : Nat) : x * y = y * x := by omega -- Fails!3example (x y : Nat) : x * y = y * x := by ring -- Use ring instead45-- ❌ Squaring is non-linear6-- example (x : Int) : x * x ≥ 0 := by omega -- Fails!7example (x : Int) : x * x ≥ 0 := by nlinarith [sq_nonneg x]Abstract Functions
1-- ❌ omega doesn't understand function behavior2-- example (f : Nat → Nat) (h : f 0 = 0) : f 0 ≤ 1 := by omega34-- ✅ But it works if you extract the needed fact5example (f : Nat → Nat) (h : f 0 = 0) : f 0 ≤ 1 := by6 rw [h] -- Now goal is: 0 ≤ 17 omega -- This works!When to Use Alternatives
| Situation | Use |
|---|---|
| Linear arithmetic (Nat/Int) | omega |
| Polynomial equality | ring |
| Non-linear inequalities | nlinarith |
| Decidable propositions | decide |
| Definitional equality | rfl |
Deep Dive: How omega Works: The Omega Test
omega implements the Omega test algorithm, invented by William Pugh in 1991. It works by:
- Normalization: Convert the goal to a conjunction of linear constraints
- Negation: Negate the goal and add it to the hypotheses
- Variable Elimination: Use Fourier-Motzkin elimination to remove variables one by one
- Contradiction Check: If the remaining constraints are unsatisfiable (like 1 ≤ 0), the original goal is proven
1-- omega proves by contradiction:2-- "The negation of the goal + hypotheses is unsatisfiable"34-- Example: Prove a < c from a < b and b < c5-- omega adds ¬(a < c), i.e., a ≥ c6-- Combined with a < b and b < c, this is impossible7-- Therefore a < c must be true89example (a b c : Nat) (h1 : a < b) (h2 : b < c) : a < c := by10 omega -- Finds that a ≥ c contradicts h1 and h21112-- Detecting impossible constraint sets13example (a b : Nat) (h1 : a < b) (h2 : b < a) : False := by14 omega -- Detects a < b ∧ b < a is impossibleCommon Patterns
Termination Arguments
When writing recursive functions, you often need to prove that arguments decrease.omega is perfect for this:
1-- Proving arguments decrease for termination2def myFun (n : Nat) : Nat :=3 if n < 2 then n4 else myFun (n / 2) + myFun (n / 2)5termination_by n6decreasing_by all_goals omega78-- Why it works: omega proves n / 2 < n when n ≥ 29example (n : Nat) (h : n ≥ 2) : n / 2 < n := by omegaIndex Bounds
1-- Array and list index bounds2example (arr : Array Nat) (i : Nat) (h : i < arr.size) : 3 i < arr.size + 1 := by omega45example (xs : List Nat) (i : Nat) (hi : i < xs.length) (hj : i + 1 < xs.length) 6 : i < xs.length := by omega78-- Off-by-one reasoning9example (n i : Nat) (h : i < n) : i ≤ n - 1 := by omega10example (n i : Nat) (h : i ≤ n - 1) (hn : n > 0) : i < n := by omegaRange Proofs
1-- Proving values are in range2example (n : Nat) (h1 : n ≥ 5) (h2 : n ≤ 10) : n > 0 := by omega34-- Combining constraints5example (x y : Nat) (h1 : x + y = 10) (h2 : x ≤ 3) : y ≥ 7 := by omega67-- Disjunction from range8example (n : Nat) (h1 : n ≥ 1) (h2 : n ≤ 3) : n = 1 ∨ n = 2 ∨ n = 3 := by omegaChained Inequalities
1-- Transitivity chains2example (a b c d e : Nat) 3 (h1 : a ≤ b) (h2 : b ≤ c) (h3 : c ≤ d) (h4 : d ≤ e) 4 : a ≤ e := by omega56-- Mixed strict and non-strict7example (a b c d : Nat) 8 (h1 : a ≤ b) (h2 : b < c) (h3 : c ≤ d) 9 : a < d := by omegaCombining with Other Tactics
1-- omega after simplification2example (xs : List Nat) : xs.length ≤ xs.length + 1 := by3 omega45-- omega in subgoals6example (n : Nat) : n = 0 ∨ n > 0 := by7 cases n with8 | zero => left; rfl9 | succ m => right; omega1011-- omega after rewriting12example (a b c : Nat) (h : a = b + c) : a ≥ b := by13 rw [h]14 omega1516-- omega with cases17example (n : Nat) (h : n % 2 = 0 ∨ n % 2 = 1) : n % 2 < 2 := by18 omegaExamples
Triangle Inequality Consequence
1example (a b c : Nat) (h1 : a + b > c) (h2 : b + c > a) (h3 : c + a > b) 2 : a < b + c := by omegaDivision Properties
1example (n : Nat) (h : n ≥ 2) : n / 2 ≥ 1 := by omega2example (n : Nat) (h : n % 2 = 0) : 2 * (n / 2) = n := by omegaLet omega solve a basic inequality using a hypothesis.
1example (n : Nat) (h : n ≤ 7) : n + 1 ≤ 8 := by omegaProve a fact that requires combining two hypotheses.
1example (x y : Nat) (h1 : x ≤ y) (h2 : y ≤ x + 5) : y ≤ x + 5 := by omegaProve that division by 2 is strictly smaller (when n > 1).
1example (n : Nat) (h : n > 1) : n / 2 < n := by omega