Affine Arithmetic Expression Evaluator #
This module provides expression evaluation using Affine Arithmetic (AA). Affine arithmetic tracks correlations between variables, solving the "dependency problem" that causes interval arithmetic to over-approximate.
Main definitions #
AffineConfig- Configuration for affine evaluationAffineEnv- Variable environment mapping indices to affine formsLeanCert.Internal.Affine.evalUnchecked- Main evaluator: Expr → AffineFormevalIntervalAffine?- Strict evaluator rejecting unsupported/domain-invalid cases
Performance #
For expressions with repeated variables:
- Interval:
x - xon [-1, 1] gives [-2, 2] - Affine:
x - xon [-1, 1] gives [0, 0] (exact!)
Affine arithmetic gives 50-90% tighter bounds for many real-world expressions, especially in neural network verification where the same inputs flow through multiple paths.
Limitations #
Some transcendental functions (sin, cos, atan) fall back to interval arithmetic because affine approximations aren't yet implemented.
Configuration #
Configuration for Affine evaluation.
taylorDepth- Number of Taylor terms for transcendental functionsmaxNoiseSymbols- Maximum noise symbols before consolidation (0 = unlimited)
- taylorDepth : ℕ
Number of Taylor series terms for transcendental functions
- maxNoiseSymbols : ℕ
Max noise symbols before consolidation (0 = no limit)
Instances For
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
Equations
- One or more equations did not get rendered due to their size.
Instances For
Variable Environment #
Variable assignment as Affine forms
Equations
Instances For
Create an affine environment from rational intervals.
Each variable gets a unique noise symbol to track correlations.
Equations
- LeanCert.Engine.toAffineEnv intervals = fun (i : ℕ) => have I := intervals.getD i (LeanCert.Core.IntervalRat.singleton 0); LeanCert.Engine.Affine.AffineForm.ofInterval I i intervals.length
Instances For
Main Evaluator #
Evaluate expression using Affine Arithmetic.
This function recursively evaluates an expression, using:
- Exact affine operations for linear functions (add, sub, neg, scale)
- Controlled approximations for nonlinear functions (mul, sq)
- Interval fallbacks for unsupported transcendentals (sin, cos, atan)
The result is an AffineForm that can be converted to an interval via
toInterval, typically giving tighter bounds than pure interval arithmetic.
Equations
- One or more equations did not get rendered due to their size.
- LeanCert.Internal.Affine.evalUnchecked (LeanCert.Core.Expr.const q) ρ cfg = LeanCert.Engine.Affine.AffineForm.const q
- LeanCert.Internal.Affine.evalUnchecked (LeanCert.Core.Expr.var idx) ρ cfg = ρ idx
- LeanCert.Internal.Affine.evalUnchecked (e₁.add e₂) ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e₁ ρ cfg).add (LeanCert.Internal.Affine.evalUnchecked e₂ ρ cfg)
- LeanCert.Internal.Affine.evalUnchecked (e₁.mul e₂) ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e₁ ρ cfg).mul (LeanCert.Internal.Affine.evalUnchecked e₂ ρ cfg)
- LeanCert.Internal.Affine.evalUnchecked e_2.neg ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).neg
- LeanCert.Internal.Affine.evalUnchecked e_2.inv ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).inv
- LeanCert.Internal.Affine.evalUnchecked e_2.exp ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).exp cfg.taylorDepth
- LeanCert.Internal.Affine.evalUnchecked e_2.sinh ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).sinh cfg.taylorDepth
- LeanCert.Internal.Affine.evalUnchecked e_2.cosh ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).cosh cfg.taylorDepth
- LeanCert.Internal.Affine.evalUnchecked e_2.tanh ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).tanh
- LeanCert.Internal.Affine.evalUnchecked e_2.sqrt ρ cfg = (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).sqrt
- LeanCert.Internal.Affine.evalUnchecked e_2.atan ρ cfg = { c0 := (-2 + 2) / 2, coeffs := [], r := (2 - -2) / 2, r_nonneg := LeanCert.Internal.Affine.evalUnchecked._proof_5 }
- LeanCert.Internal.Affine.evalUnchecked e_2.sinc ρ cfg = { c0 := 0, coeffs := [], r := 1, r_nonneg := LeanCert.Internal.Affine.evalUnchecked._proof_6 }
- LeanCert.Internal.Affine.evalUnchecked e_2.erf ρ cfg = { c0 := 0, coeffs := [], r := 1, r_nonneg := LeanCert.Internal.Affine.evalUnchecked._proof_6 }
Instances For
Strict affine evaluator.
This variant returns none for operations that the legacy evaluator handles by
returning default or a huge fallback interval. All expression constructors are
implemented here; none means that a partial operation's domain could not be
proved for the supplied interval.
Equations
- One or more equations did not get rendered due to their size.
- LeanCert.Engine.evalIntervalAffine? (LeanCert.Core.Expr.const q) ρ cfg = some (LeanCert.Engine.Affine.AffineForm.const q)
- LeanCert.Engine.evalIntervalAffine? (LeanCert.Core.Expr.var idx) ρ cfg = some (ρ idx)
- LeanCert.Engine.evalIntervalAffine? e_2.neg ρ cfg = match LeanCert.Engine.evalIntervalAffine? e_2 ρ cfg with | some a => some a.neg | none => none
- LeanCert.Engine.evalIntervalAffine? e_2.exp ρ cfg = match LeanCert.Engine.evalIntervalAffine? e_2 ρ cfg with | some a => some (a.exp cfg.taylorDepth) | none => none
- LeanCert.Engine.evalIntervalAffine? e_2.sinh ρ cfg = match LeanCert.Engine.evalIntervalAffine? e_2 ρ cfg with | some a => some (a.sinh cfg.taylorDepth) | none => none
- LeanCert.Engine.evalIntervalAffine? e_2.cosh ρ cfg = match LeanCert.Engine.evalIntervalAffine? e_2 ρ cfg with | some a => some (a.cosh cfg.taylorDepth) | none => none
- LeanCert.Engine.evalIntervalAffine? e_2.tanh ρ cfg = match LeanCert.Engine.evalIntervalAffine? e_2 ρ cfg with | some a => some a.tanh | none => none
- LeanCert.Engine.evalIntervalAffine? e_2.sqrt ρ cfg = match LeanCert.Engine.evalIntervalAffine? e_2 ρ cfg with | some a => some a.sqrt | none => none
- LeanCert.Engine.evalIntervalAffine? e_2.sinc ρ cfg = some { c0 := 0, coeffs := [], r := 1, r_nonneg := LeanCert.Internal.Affine.evalUnchecked._proof_6 }
- LeanCert.Engine.evalIntervalAffine? e_2.erf ρ cfg = some { c0 := 0, coeffs := [], r := 1, r_nonneg := LeanCert.Internal.Affine.evalUnchecked._proof_6 }
Instances For
Diagnose the first strict affine evaluation failure.
Equations
- One or more equations did not get rendered due to their size.
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.neg ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.exp ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.sin ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.cos ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.atan ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.arsinh ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.sinc ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.erf ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.sinh ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.cosh ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.tanh ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2.sqrt ρ cfg = LeanCert.Engine.EvalError.nestedFailure "unary operand" (LeanCert.Engine.diagnoseEvalIntervalAffineFailure e_2 ρ cfg)
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure (LeanCert.Core.Expr.const q) ρ cfg = LeanCert.Engine.EvalError.unsupportedBackend "internal: total affine expression unexpectedly failed"
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure (LeanCert.Core.Expr.var idx) ρ cfg = LeanCert.Engine.EvalError.unsupportedBackend "internal: total affine expression unexpectedly failed"
- LeanCert.Engine.diagnoseEvalIntervalAffineFailure (LeanCert.Core.Expr.namedConst c) ρ cfg = LeanCert.Engine.EvalError.unsupportedBackend "internal: total affine expression unexpectedly failed"
Instances For
Checked affine evaluator with structured domain errors.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Strictly evaluate and convert to an interval.
Equations
- LeanCert.Engine.evalAffineToInterval? e ρ cfg = match LeanCert.Engine.evalIntervalAffine? e ρ cfg with | some a => some a.toInterval | none => none
Instances For
Check if expression is bounded above
Equations
- LeanCert.Engine.checkUpperBoundAffine e ρ bound cfg = decide ((LeanCert.Internal.Affine.evalUnchecked e ρ cfg).toInterval.hi ≤ bound)
Instances For
Check if expression is bounded below
Equations
- LeanCert.Engine.checkLowerBoundAffine e ρ bound cfg = decide (bound ≤ (LeanCert.Internal.Affine.evalUnchecked e ρ cfg).toInterval.lo)
Instances For
Correctness Theorem #
Environment membership: real value is represented by the affine form
Equations
- LeanCert.Engine.envMemAffine ρ_real ρ_affine eps = ∀ (i : ℕ), (ρ_affine i).mem_affine eps (ρ_real i)
Instances For
A successful strict affine evaluation represents the true value.
Unlike the legacy total evaluator, success itself discharges every partial domain condition. Operations without a dedicated affine linearization use the proved interval fallback and therefore remain sound while losing correlation.
Successful checked affine evaluation is sound for every expression.
Domain validity for Affine evaluation. This is defined directly in terms of LeanCert.Internal.Affine.evalUnchecked to ensure compatibility. For log, we require the argument's toInterval to have positive lower bound.
Equations
- LeanCert.Engine.evalDomainValidAffine (LeanCert.Core.Expr.const q) ρ cfg = True
- LeanCert.Engine.evalDomainValidAffine (LeanCert.Core.Expr.var idx) ρ cfg = True
- LeanCert.Engine.evalDomainValidAffine (e₁.add e₂) ρ cfg = (LeanCert.Engine.evalDomainValidAffine e₁ ρ cfg ∧ LeanCert.Engine.evalDomainValidAffine e₂ ρ cfg)
- LeanCert.Engine.evalDomainValidAffine (e₁.mul e₂) ρ cfg = (LeanCert.Engine.evalDomainValidAffine e₁ ρ cfg ∧ LeanCert.Engine.evalDomainValidAffine e₂ ρ cfg)
- LeanCert.Engine.evalDomainValidAffine e_2.neg ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.inv ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.exp ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.sin ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.cos ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.log ρ cfg = (LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg ∧ (LeanCert.Internal.Affine.evalUnchecked e_2 ρ cfg).toInterval.lo > 0)
- LeanCert.Engine.evalDomainValidAffine e_2.atan ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.arsinh ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.atanh ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.sinc ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.erf ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.sinh ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.cosh ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.tanh ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine e_2.sqrt ρ cfg = LeanCert.Engine.evalDomainValidAffine e_2 ρ cfg
- LeanCert.Engine.evalDomainValidAffine (LeanCert.Core.Expr.namedConst c) ρ cfg = True
Instances For
Domain validity is trivially true for ADSupported expressions (which exclude log).
Correctness theorem for Affine interval evaluation.
If all input variables are represented by their affine forms (via noise assignment eps), then the real evaluation of the expression is represented by the affine result.
This proves soundness: the affine form always contains the true value.
Note: Requires valid noise assignment and domain validity for log. Some transcendental cases (sin, cos, pi) use interval fallback and have separate soundness via interval bounds.
Corollary: The interval produced by toInterval contains the true value.
This is the key result for optimization: if we compute an affine form and convert to an interval, the interval is guaranteed to contain the true value.