Bound Propagator
The bound propagator orchestrates layer-by-layer formal verification through neural networks.
Propagateur de bornes à travers le réseau
- class abstractnn.bound_propagator.BoundPropagator(relaxation_type: str = 'linear', enable_reporting: bool = True)[source]
Bases:
objectPropage les expressions affines à travers le réseau
BoundPropagator
- class abstractnn.bound_propagator.BoundPropagator(relaxation_type: str = 'linear', enable_reporting: bool = True)[source]
Bases:
objectPropage les expressions affines à travers le réseau
Main class for propagating bounds through neural networks.
- propagate(input_expressions, layers, input_shape)[source]
Propagate affine expressions through network layers:
\[\mathbf{y} = f_L \circ f_{L-1} \circ \cdots \circ f_1(\mathbf{x})\]where each \(f_i\) is a layer transformation.
- Parameters:
input_expressions (List[AffineExpression]) – Input symbolic expressions
layers (List[Dict]) – Network layers from ONNX parser
input_shape (Tuple) – Shape of input (B, C, H, W)
- Returns:
Output expressions after full propagation
- Return type:
List[AffineExpression]
- _propagate_layer(expressions, layer, current_shape)
Propagate through a single layer.
Supports:
Linear: Conv, Gemm/Linear, BatchNorm
Non-linear: ReLU, MaxPool
Utility: Reshape, Flatten, Concat
Layer Handlers
Conv2d Handler
def _handle_conv(self, expressions, layer, input_shape):
"""
Handle convolutional layer.
Forward pass:
y[n, c_out, h, w] = bias[c_out] +
Σ weight[c_out, c_in, k_h, k_w] *
x[n, c_in, h*s_h + k_h, w*s_w + k_w]
Symbolic:
Each output neuron is a weighted sum of input expressions
"""
ReLU Handler
def _handle_relu(self, expressions):
"""
Handle ReLU activation with relaxation.
Cases:
1. l >= 0: y = x (active)
2. u <= 0: y = 0 (inactive)
3. l < 0 < u: y ∈ [0, max(|l|, u)] (ambiguous, needs relaxation)
"""
MaxPool Handler
def _handle_maxpool(self, expressions, layer, input_shape):
"""
Handle max pooling conservatively.
For region R: max(R) ≤ max(upper_bounds(R))
Takes union of all possible maxima in pooling window.
"""
Usage Examples
Basic Propagation
from abstractnn.affine_engine import AffineExpressionEngine
from abstractnn.bound_propagator import BoundPropagator
from abstractnn.onnx_parser import ONNXParser
# Load model
parser = ONNXParser('model.onnx')
layers = parser.parse()
# Create propagator
engine = AffineExpressionEngine()
propagator = BoundPropagator(engine, enable_reporting=True)
# Create input
import numpy as np
image = np.random.rand(3, 28, 28).astype(np.float32)
input_exprs = engine.create_input_expressions(image, noise_level=0.1)
# Propagate
output_exprs = propagator.propagate(
input_exprs,
layers,
input_shape=(1, 3, 28, 28)
)
# Get bounds
bounds = [expr.get_bounds() for expr in output_exprs]
print(f"Output bounds: {bounds[0]}")
With Checkpointing
# Enable checkpointing for large models
propagator = BoundPropagator(
engine,
enable_reporting=True,
checkpoint_frequency=5 # Save every 5 layers
)
output_exprs = propagator.propagate(
input_exprs,
layers,
input_shape=(1, 3, 224, 224)
)
# Access intermediate checkpoints
checkpoints = propagator.get_checkpoints()
for layer_idx, checkpoint in checkpoints.items():
print(f"Layer {layer_idx}: {len(checkpoint)} expressions")
Layer-by-Layer Analysis
# Analyze bound growth through layers
propagator = BoundPropagator(engine, enable_reporting=True)
current_exprs = input_exprs
bound_widths = []
for i, layer in enumerate(layers):
current_exprs = propagator._propagate_layer(
current_exprs,
layer,
current_shape
)
# Measure bound width
bounds = [e.get_bounds() for e in current_exprs[:10]]
avg_width = np.mean([u - l for l, u in bounds])
bound_widths.append(avg_width)
print(f"Layer {i} ({layer['type']}): avg width = {avg_width:.4f}")
# Plot bound growth
import matplotlib.pyplot as plt
plt.plot(bound_widths)
plt.xlabel('Layer')
plt.ylabel('Average Bound Width')
plt.title('Bound Relaxation Through Network')
plt.show()
Affine Engine: Affine expression management
relaxer: Non-linear relaxation techniques
../user_guide/propagation: Propagation user guide