Configuration
LeanCert supports multiple arithmetic backends for different performance/precision tradeoffs.
Backend Selection
import leancert as lc
# Default: Exact rational arithmetic
result = lc.find_bounds(expr, domain)
# Dyadic: 10-100x faster for deep expressions
result = lc.find_bounds(expr, domain, config=lc.Config.dyadic())
# Affine: 50-90% tighter bounds for correlated variables
result = lc.find_bounds(expr, domain, config=lc.Config.affine())
Backend Enum
leancert.config.Backend
Bases: Enum
Backend selection for interval arithmetic.
- RATIONAL: Standard rational arithmetic. Exact but can suffer from denominator explosion on deep expressions.
- DYADIC: High-performance dyadic arithmetic (n * 2^e). Avoids denominator explosion by using fixed-precision outward rounding. 10-100x faster for complex expressions like neural networks.
- AFFINE: Affine arithmetic that tracks correlations between variables. Solves the "dependency problem" (e.g., x-x gives [0,0] not [-2,2]). 50-90% tighter bounds for expressions with repeated variables.
Source code in python/leancert/config.py
Comparison
| Backend | Speed | Precision | Best For |
|---|---|---|---|
RATIONAL |
Baseline | Exact | Small expressions, proofs |
DYADIC |
10-100x faster | ~15 decimal digits | Neural networks, deep expressions |
AFFINE |
Similar to Rational | Tighter bounds | Repeated variables, LayerNorm |
Config Class
leancert.config.Config
dataclass
Configuration for verification requests.
Attributes:
| Name | Type | Description |
|---|---|---|
taylor_depth |
int
|
Depth of Taylor expansion for interval arithmetic. Higher values give tighter bounds but are slower. |
max_iters |
int
|
Maximum iterations for optimization/root finding. |
tolerance |
Fraction
|
Desired precision (as a fraction). |
use_monotonicity |
bool
|
Use monotonicity pruning in optimization. |
timeout_sec |
float
|
Timeout in seconds. |
backend |
Backend
|
Interval arithmetic backend (RATIONAL, DYADIC, or AFFINE). |
dyadic_config |
Optional[DyadicConfig]
|
Configuration for Dyadic backend (if backend is DYADIC). |
affine_config |
Optional[AffineConfig]
|
Configuration for Affine backend (if backend is AFFINE). |
Source code in python/leancert/config.py
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | |
taylor_depth = 10
class-attribute
instance-attribute
max_iters = 1000
class-attribute
instance-attribute
tolerance = Fraction(1, 1000)
class-attribute
instance-attribute
use_monotonicity = True
class-attribute
instance-attribute
timeout_sec = 60.0
class-attribute
instance-attribute
backend = Backend.RATIONAL
class-attribute
instance-attribute
dyadic_config = None
class-attribute
instance-attribute
affine_config = None
class-attribute
instance-attribute
low_precision()
classmethod
medium_precision()
classmethod
high_precision()
classmethod
dyadic(precision=-53)
classmethod
Configuration using Dyadic backend for high performance.
Recommended for deep expressions, neural networks, or when rational arithmetic is too slow.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
precision
|
int
|
Dyadic precision (default -53, IEEE double-like). |
-53
|
Source code in python/leancert/config.py
dyadic_fast()
classmethod
Fast Dyadic configuration with lower precision.
Source code in python/leancert/config.py
dyadic_high_precision()
classmethod
High precision Dyadic configuration.
Source code in python/leancert/config.py
affine()
classmethod
Configuration using Affine backend for tight bounds.
Recommended for expressions with repeated variables where the dependency problem causes interval over-approximation.
Example
x - x on [-1, 1]: - Interval gives [-2, 2] - Affine gives [0, 0] (exact!)
Source code in python/leancert/config.py
affine_compact()
classmethod
Affine configuration with noise symbol consolidation.
Factory Methods
# Precision presets
lc.Config.low_precision() # Fast, ~2 decimal places
lc.Config.medium_precision() # Default, ~3 decimal places
lc.Config.high_precision() # Slow, ~5 decimal places
# Backend presets
lc.Config.dyadic() # IEEE double-like precision
lc.Config.dyadic_fast() # Lower precision, faster
lc.Config.dyadic_high_precision() # ~30 decimal digits
lc.Config.affine() # Affine arithmetic (tight bounds)
lc.Config.affine_compact() # With noise symbol consolidation
DyadicConfig
leancert.config.DyadicConfig
dataclass
Configuration for Dyadic arithmetic backend.
Attributes:
| Name | Type | Description |
|---|---|---|
precision |
int
|
Minimum exponent for outward rounding. -53 gives IEEE double-like precision (~15 decimal digits). Use -100 for higher precision, -30 for faster computation. |
round_after_ops |
int
|
Round after this many operations. 0 means round after every operation (most sound, slightly slower). |
Source code in python/leancert/config.py
fast()
classmethod
high_precision()
classmethod
Precision Levels
| Precision | Decimal Digits | Use Case |
|---|---|---|
-30 |
~9 | Fast prototyping |
-53 |
~15 | Default (IEEE double-like) |
-100 |
~30 | High-precision verification |
# Custom Dyadic configuration
config = lc.Config(
backend=lc.Backend.DYADIC,
dyadic_config=lc.DyadicConfig(precision=-100)
)
AffineConfig
leancert.config.AffineConfig
dataclass
Configuration for Affine arithmetic backend.
Affine arithmetic tracks correlations between variables, solving the "dependency problem" in interval arithmetic. For example: - Interval: x - x on [-1, 1] gives [-2, 2] - Affine: x - x on [-1, 1] gives [0, 0] (exact!)
Attributes:
| Name | Type | Description |
|---|---|---|
max_noise_symbols |
int
|
Maximum noise symbols before consolidation. 0 means no limit. Higher limits give tighter bounds but use more memory. |
Source code in python/leancert/config.py
compact()
classmethod
The Dependency Problem
Standard interval arithmetic loses correlations between variables:
x = lc.var('x')
# Interval arithmetic: x - x on [-1, 1] gives [-2, 2]
result_interval = lc.find_bounds(x - x, {'x': (-1, 1)})
print(result_interval.max_hi) # 2.0 (overapproximation!)
# Affine arithmetic: x - x on [-1, 1] gives [0, 0]
result_affine = lc.find_bounds(x - x, {'x': (-1, 1)}, config=lc.Config.affine())
print(result_affine.max_hi) # 0.0 (exact!)
Affine arithmetic tracks linear correlations, giving tighter bounds for:
- Expressions with repeated variables (
x*x - x*x) - LayerNorm in transformers (mean/variance correlation)
- Control systems with rotation matrices
# Custom Affine configuration
config = lc.Config(
backend=lc.Backend.AFFINE,
affine_config=lc.AffineConfig(max_noise_symbols=100)
)
Examples
Neural Network Verification
For neural networks, use Dyadic for speed:
import leancert as lc
# Neural network expression (deep computation graph)
net_output = build_network_expr(weights, biases)
# Dyadic is 10-100x faster than rational for deep expressions
config = lc.Config.dyadic()
result = lc.find_bounds(net_output, input_domain, config=config)
Transformer LayerNorm
For transformers with LayerNorm, use Affine for tight bounds:
import leancert as lc
# LayerNorm has correlated mean/variance computation
layernorm_expr = build_layernorm_expr(x, gamma, beta)
# Affine arithmetic tracks correlations
config = lc.Config.affine()
result = lc.find_bounds(layernorm_expr, input_domain, config=config)
High-Precision Proofs
For formal proofs requiring maximum precision:
import leancert as lc
config = lc.Config.high_precision()
result = lc.find_bounds(expr, domain, config=config)
# Export certificate for Lean verification
result.certificate.save("proof.json")
Custom Configuration
from fractions import Fraction
import leancert as lc
config = lc.Config(
taylor_depth=15, # More Taylor terms
max_iters=2000, # More optimization iterations
tolerance=Fraction(1, 10000), # Tighter tolerance
use_monotonicity=True, # Enable monotonicity pruning
timeout_sec=120.0, # 2 minute timeout
backend=lc.Backend.DYADIC,
dyadic_config=lc.DyadicConfig(precision=-80),
)
result = lc.find_bounds(expr, domain, config=config)