\chapter{Numbers and Automation: Making the Machine Do the Boring Parts}
\label{ch:automation}

\section{The 90/10 rule of verification}

Here is a trade secret: most of a real verification effort is not clever.
Opening the correctness proof of Ed25519 field multiplication, you will find
that the overwhelming majority of proof obligations are statements like

\[
a < 2^{51} \;\wedge\; b < 2^{51} \;\Longrightarrow\; a + b < 2^{52},
\qquad\qquad
(a + b) \cdot c = a\cdot c + b\cdot c,
\]

--- bookkeeping a patient undergraduate could verify by hand in a minute
each. There are \emph{thousands} of them. The craft of modern verification is
to hand exactly this 90\% to decision procedures --- tactics that implement a
complete algorithm for a well-defined logical fragment --- and save the human
for the 10\% that needs insight. This chapter is your tour of the arsenal.

\section{\texttt{omega}: linear arithmetic, decided}

The tactic you will use more than any other in this book's domain is
\lean{omega}. It completely decides \emph{linear arithmetic} over integers
and naturals: any goal built from variables, constants, $+$, $-$,
multiplication \emph{by constants}, $=$, $<$, $\le$, $\lnot$, $\wedge$,
$\vee$, including the hypotheses in context.

\begin{lstlisting}[language=Lean]
example (a b : Nat) (h1 : a < 2^51) (h2 : b < 2^51) :
    a + b < 2^52 := by omega

example (a b : Nat) (h : a ≤ b) : a + (b - a) = b := by omega
  -- note: truncated Nat subtraction handled CORRECTLY -- omega knows
\end{lstlisting}

That second example deserves a salute: \lean{omega} understands \lean{Nat}
truncation natively, defusing the Chapter~\ref{ch:lean} pitfall by algorithm
rather than by vigilance. When the goal is false, \lean{omega} \emph{fails} ---
it is a decision procedure, so failure on a linear goal means the goal (with
the hypotheses in view) is simply not true. That property turns \lean{omega}
into a \emph{statement-debugging} tool: if it refuses your ``obviously true''
bound, go find the counterexample; there is one.

\begin{worked}{when omega says no --- hunting the boundary by hand}
Train the counterexample reflex on a real-shaped bound. Claim: ``if
$a, b < 2^{51}$ then $a + b < 2^{52} - 2$.'' It \emph{sounds} safely true
--- each term is below half of $2^{52}$, surely the sum clears the bar
with room? \lean{omega} refuses. Instead of doubting the tool, hunt at the
\emph{boundary}, because linear claims fail at corners of the allowed
region: take both variables at their maximum, $a = b = 2^{51} - 1$. Then
\[
a + b \;=\; 2^{52} - 2
\;\not<\; 2^{52} - 2 .
\]
The claim fails by exactly one at exactly one corner --- the true theorem
is $a + b \le 2^{52} - 2$, or strictly $a + b < 2^{52} - 1$. Now recall
Chapter~\ref{ch:why}: the carry bugs that motivated this book are
precisely off-by-a-hair failures at corners of the input region that
sampling never visits. The refusal of a decision procedure is the same
boundary being found for you, before the code ships instead of after.
Standing rule: \textbf{when \lean{omega} refuses a linear goal, the
statement is wrong; evaluate the goal at the extreme values of every
hypothesis, and one of those corners is your counterexample.}
\end{worked}

\begin{worked}{the bound-then-omega pattern at real field scale}
Here is the exact arithmetic that stands between the Ed25519
multiplication routine and a machine-word overflow --- the central safety
computation of the whole field layer, fully pen-and-paper. The bounds
discipline lets limbs grow to $a_i, b_j < 2^{54}$
(Chapter~\ref{ch:rust}). Multiplication forms \emph{column sums} of limb
products (Chapter~\ref{ch:denotation}); the widest column is
\[
c_4 \;=\; a_0 b_4 + a_1 b_3 + a_2 b_2 + a_3 b_1 + a_4 b_0
\qquad\text{(five products).}
\]
The products land in $128$-bit words. Does $c_4$ fit? Work the exponents:
\[
a_i b_j \;<\; 2^{54} \cdot 2^{54} \;=\; 2^{108},
\qquad
c_4 \;<\; 5 \cdot 2^{108} \;<\; 2^{3} \cdot 2^{108} \;=\; 2^{111}
\;<\; 2^{128}. \;\checkmark
\]
Margin: $128 - 111 = 17$ bits to spare --- room for the carry-in each
column also absorbs. Every number in this computation is real: the $54$
comes from the invariant, the $5$ from the limb count, the $128$ from the
hardware. Change any one --- say a hypothetical radix-$58$ variant:
$2 \cdot 58 = 116$, $5 \cdot 2^{116} < 2^{119}$, still fine; radix-$62$:
$5 \cdot 2^{124} < 2^{127}$, one bit from the cliff --- and you can
re-run the audit in your head. \emph{This} is what the automation
divides between itself: \lean{a\_i * b\_j < 2\textasciicircum{}108} is the nonlinear atom you
must name (one monotonicity lemma), and everything after it ---
$5 \cdot 2^{108} < 2^{128}$ with the atom opaque --- is linear, which is
to say, \lean{omega} food. The pattern in the pitfall below is this
computation, industrialized.
\end{worked}

\begin{pitfall}
\lean{omega} does not touch multiplication of two \emph{variables}
($a \cdot b$ is not linear), division in general, or bit-shifts by variables.
For a goal mixing $a \cdot b$ with bounds, you often first name the product
--- \lean{have hab : a * b ≤ 2\textasciicircum{}102 := ...} using a multiplication
monotonicity lemma --- and then let \lean{omega} finish with \lean{hab} as an
opaque atom. This two-step, \emph{bound the nonlinear part, then release the
linear solver}, is the single most-used proof pattern in verified field
arithmetic. You will write it dozens of times, and by Chapter~\ref{ch:field}
it will feel like breathing.
\end{pitfall}

\section{\texttt{decide}: when truth is a computation}

Some propositions can be checked by running an algorithm to completion:
``$97$ is prime,'' ``these two sorted lists are equal,'' ``$x^3 = x$ for all
$x$ in $\Zmod{6}$'' (six cases --- check them all). For any such
\emph{decidable} proposition, the \lean{decide} tactic runs the decision
algorithm inside Lean's kernel and turns the answer into a proof:

\begin{lstlisting}[language=Lean]
example : Nat.Prime 97 := by decide
example : ∀ x : ZMod 6, x^3 = x^3 := by decide   -- finite: try all six
\end{lstlisting}

The magic and the limitation are the same fact: the \emph{kernel itself}
re-executes the computation. That makes \lean{decide} unimpeachable --- and
completely hopeless for our 77-digit prime $2^{255}-19$, where trial division
would outlast the universe. There is a variant, \lean{native_decide}, that
compiles the check to native code first --- fast enough! --- but it makes the
compiler part of your trusted base, an IOU we will scrutinize hard in
Chapters~\ref{ch:prime} and~\ref{ch:honesty}. For now, the rule of the house:
\textbf{\lean{decide} yes, \lean{native_decide} never in a final certificate.}

\section{\texttt{ring} and \texttt{norm\_num}: algebra on tap}

The five-line commutativity shuffle from Chapter~\ref{ch:tactics}? Here is
the grown-up version:

\begin{lstlisting}[language=Lean]
example (a b c : Nat) : a + b + c = c + b + a := by ring

example (a b : ZMod p) : (a + b)^2 = a^2 + 2*a*b + b^2 := by ring

example : (2:Int)^255 - 19 > 2^254 := by norm_num
\end{lstlisting}

\lean{ring} proves any identity that holds in every commutative ring ---
polynomial rearrangements, binomial expansions, distributivity avalanches ---
by normalizing both sides to a canonical polynomial form and comparing.
\lean{norm_num} evaluates concrete numeric facts, comfortable with numbers of
any size. Between \lean{omega}, \lean{ring}, and \lean{norm_num} you now hold
the three keys that open most arithmetic doors:

\begin{center}
\begin{tikzpicture}[
  key/.style={draw=ink2,thick,rounded corners=3pt,fill=white,align=center,
              minimum width=3.55cm,minimum height=1.5cm},
]
  \node[key,fill=accentsoft] (o) at (0,0)
    {\textbf{\code{omega}}\\[1pt]\small linear $+,-,<,\le$\\\small bounds \& carries};
  \node[key,fill=provensoft] (r) at (4.1,0)
    {\textbf{\code{ring}}\\[1pt]\small polynomial identities\\\small in any comm.\ ring};
  \node[key,fill=warnsoft] (n) at (8.2,0)
    {\textbf{\code{norm\_num}}\\[1pt]\small concrete numerals\\\small any size};
  \node[font=\small\color{ink2},align=center] at (4.1,-1.55)
    {the three keys of verified arithmetic --- learn what each fragment
     \emph{excludes}\\ and you will always know which door you are standing in front of};
\end{tikzpicture}
\end{center}

\section{\texttt{simp}: the rewriting engine, and how to hold it}

\lean{simp} rewrites the goal to exhaustion using a curated database of
thousands of ``simplification'' lemmas ($x + 0 \rightsquigarrow x$,
\lean{List.length (a :: l)} $\rightsquigarrow$ \lean{l.length + 1}, ...). It
is the most powerful tactic in Lean and the easiest to misuse. Used well, it
clears brush so the real argument stands out. Used lazily ---
\lean{simp [*]} with every hypothesis thrown in, in a context of sixty
accumulated facts --- it becomes a search over an enormous rewrite space:
slow, fragile under library updates, and occasionally a memory monster.

This is not hypothetical. During the development this book accompanies, a
single over-broad \lean{simp}-style discharge in a fat context consumed
twelve gigabytes of RAM and took down the machine. The postmortem produced
house rules worth adopting from day one:

\begin{itemize}[leftmargin=1.4em]
\item Prefer \lean{simp only [lemma1, lemma2]} --- an explicit lemma list ---
  in anything you intend to keep.
\item Let \lean{simp?} tell you the list: run it once interactively, then
  paste the \lean{simp only [...]} it suggests into the file.
\item Keep contexts lean (pun intended): a proof with sixty hypotheses in
  scope wants to be five \lean{have}-steps with twelve each.
\end{itemize}

\begin{bigidea}
Automation is a \emph{contract}, not a slot machine. Each tactic decides a
known fragment: \lean{omega} linear arithmetic, \lean{ring} ring identities,
\lean{decide} finite computation, \lean{simp only} a rewrite system you
chose. The professional habit is to know \emph{which} contract you are
invoking --- then failure is information (``this goal is not linear''; ``this
identity needs the modulus''), never mystery.
\end{bigidea}

\begin{tryit}
Open \code{exercises/Ch05.lean}: ten arithmetic goals, each solvable by
exactly one of \lean{omega} / \lean{ring} / \lean{norm_num} / \lean{decide}.
Your task is not just to close them but to close each with the \emph{right}
tool --- the file rejects overkill by design. Goal number ten is the
Chapter~\ref{ch:tactics} cliffhanger:
\lean{a < 2\textasciicircum{}51 → a * 19 < 2\textasciicircum{}56}. (It is not linear --- $19$ is a constant, so
it is! Think, then fire.)
\end{tryit}

\section*{Exercises}

\exercise{For each, name the tactic and predict success before running:
(a) \lean{(a+b)*(a-b) = a*a - b*b} over \lean{Int};
(b) \lean{a < 100 → b < 100 → a*b < 10000} over \lean{Nat};
(c) \lean{Nat.Prime 65537};
(d) \lean{2\textasciicircum{}51 + 2\textasciicircum{}51 = 2\textasciicircum{}52}.}

\exercise{Goal (b) above is nonlinear, yet \lean{omega} alone fails while the
two-step pattern (bound the product with
\lean{Nat.mul_lt_mul} machinery, then \lean{omega}) succeeds. Carry it out.
Time yourself; the pattern should take under five minutes by the second
attempt.}

\exercise{Find a true statement about \lean{Nat} that \emph{no} tactic in
this chapter proves in one shot, and sketch in prose how you would decompose
it. (Anything genuinely inductive works --- automation here decides
arithmetic fragments, not all of mathematics.)}

\exercise{(Paper) Re-run the worked column-sum audit for the
\emph{scalar} arithmetic of the companion projects, which uses radix-52
limbs bounded by $2^{52}$ multiplied into $128$-bit words with
\emph{nine}-term columns at the widest (schoolbook $5\times 5$, column
$k=4$ has five terms, but the Montgomery pass adds four more products).
Does $9 \cdot 2^{104}$ fit in $2^{128}$? With how many bits of margin?}

\section*{Solutions and pathways}
\solutionsintro

\solhead{5.1}
\pathway For each goal, name the \emph{fragment} it lives in before naming
a tactic: linear with constants? polynomial identity? concrete numerals?
finite check? Then the table from this chapter is a lookup, not a guess.
\answer
(a) $(a+b)(a-b) = a\,a - b\,b$ over \lean{Int}: polynomial identity in a
commutative ring $\to$ \lean{ring}. Succeeds. (Over \lean{Nat} it would be
trickier --- truncated subtraction breaks ring reasoning; part of why the
exercise says \lean{Int}.)
(b) $a<100 \to b<100 \to ab < 10000$: \emph{nonlinear} (product of two
variables) $\to$ no single tool from the table; needs the two-step
pattern (5.2).
(c) \lean{Nat.Prime 65537}: decidable, and small enough $\to$
\lean{decide} works (with a noticeable pause); \lean{norm_num} is faster
--- Chapter~\ref{ch:prime} explains the difference as certificate versus
grind.
(d) $2^{51} + 2^{51} = 2^{52}$: concrete numerals $\to$ \lean{norm_num}
(or \lean{decide}; but build the habit of matching tool to fragment, not
firing the biggest gun).

\solhead{5.2}
\pathway The product $ab$ is one opaque quantity as far as linear
reasoning is concerned. So: (i) bound the atom with a monotonicity lemma
--- both factors grow, so the product grows; (ii) hand the bounded atom to
\lean{omega}. Finding the lemma name is part of the exercise:
\lean{exact?} on the goal \lean{a * b < 100 * 100}, or search Mathlib for
``mul\_lt\_mul''.
\answer
\begin{lstlisting}[language=Lean]
example (a b : Nat) (ha : a < 100) (hb : b < 100) : a * b < 10000 := by
  have hab : a * b < 100 * 100 := Nat.mul_lt_mul'' ha hb
  omega
\end{lstlisting}
Two lines, and the division of labor is visible: the \lean{have} names the
one nonlinear fact (with the lemma doing the monotonicity), then
\lean{omega} finishes since \lean{100 * 100} is a numeral and \lean{a * b}
is now an opaque atom below it. Under five minutes by the second attempt
is a realistic bar --- this exact two-line shape appears \emph{dozens} of
times in the field-layer proofs, with $2^{54}$ in place of $100$.

\solhead{5.3}
\pathway Look for statements whose truth genuinely needs induction ---
i.e.\ not expressible in a decided fragment. Anything universally
quantified over \emph{all} \lean{n} about a recursively defined function
qualifies.
\answer (Model answer.) $\forall n,\ \mathtt{fib}(n) < 2^n$ (with
\lean{fib} from Chapter~\ref{ch:lean}). Not linear (contains \lean{fib}
and $2^n$), not a ring identity, not concrete, not finite --- every tool
in this chapter shrugs. Decomposition sketch: induction on $n$ with
\emph{two} base cases ($n = 0, 1$) and a step using
$\mathtt{fib}(n{+}2) = \mathtt{fib}(n{+}1) + \mathtt{fib}(n) <
2^{n+1} + 2^n < 2^{n+2}$ --- where the \emph{final} inequality, with the
induction hypotheses as opaque atoms, IS an \lean{omega} goal. That is the
grown-up division of labor: induction supplies the skeleton, decision
procedures clear each rib.

\solhead{5.4}
\pathway Same three lines as the worked example; only the constants move.
\answer Products: $2^{52} \cdot 2^{52} = 2^{104}$. Nine terms:
$9 \cdot 2^{104} < 2^4 \cdot 2^{104} = 2^{108} < 2^{128}$ --- fits, with
$128 - 108 = 20$ bits of margin ($23$ if you count $9 < 2^{3.17}$ more
tightly). The scalar layer breathes easier than the field layer's $17$
bits, which matches how the two codebases feel to verify. When you meet
the scalar Montgomery proofs in the companion repos, this margin
computation is the first \lean{have} of every multiplication lemma.

\begin{checkpoint}
You should now be able to: match a goal to its decision procedure by the
shape of its operators; execute the bound-then-omega pattern for nonlinear
bounds; explain why \lean{decide} is trustworthy and where it hits its
computational wall; and state the \lean{simp} discipline --- and the story of
why this book is unusually sincere about it.
\end{checkpoint}
