Affine Engine

The affine engine is the core component for symbolic expression management and propagation.

Moteur d’expressions affines pour la propagation formelle

class abstractnn.affine_engine.AffineExpression(constant: float, coefficients: Dict[int, float], bounds: Dict[int, Tuple[float, float]])[source]

Bases: object

Représente une expression affine : y = a0 + sum(aj * xj) avec xj ∈ [lj, uj]

__init__(constant: float, coefficients: Dict[int, float], bounds: Dict[int, Tuple[float, float]])[source]
get_bounds() Tuple[float, float][source]

Calcule les bornes [min, max] de l’expression affine

__add__(other)[source]

Addition de deux expressions affines

__mul__(scalar)[source]

Multiplication par un scalaire

class abstractnn.affine_engine.AffineExpressionEngine[source]

Bases: object

Moteur de manipulation d’expressions affines

static create_input_expressions(input_data: ndarray, noise_level: float) List[AffineExpression][source]

Crée les expressions affines initiales pour l’entrée avec bruit Chaque pixel x_i devient: x_i = 0 + 1*ε_i où ε_i ∈ [value-noise, value+noise]

static linear_layer(expressions: List[AffineExpression], weight: ndarray, bias: ndarray = None) List[AffineExpression][source]

Propage à travers une couche linéaire (MatMul + bias)

static conv2d_layer(expressions: List[AffineExpression], weight: ndarray, bias: ndarray = None, input_shape: Tuple[int, int, int, int] = None, stride: Tuple[int, int] = (1, 1), padding: Tuple[int, int] = (0, 0), dilation: Tuple[int, int] = (1, 1)) Tuple[List[AffineExpression], Tuple[int, int, int, int]][source]

Propage à travers une couche convolutionnelle 2D

Parameters:
  • expressions – Liste d’expressions affines (input flattened)

  • weight – Poids de convolution de forme (out_channels, in_channels, kH, kW)

  • bias – Biais de forme (out_channels,)

  • input_shape – (batch, in_channels, height, width)

  • stride – (stride_h, stride_w)

  • padding – (pad_h, pad_w)

  • dilation – (dilation_h, dilation_w)

Returns:

(expressions de sortie, output_shape)

static maxpool2d_layer(expressions: List[AffineExpression], input_shape: Tuple[int, int, int, int], kernel_size: Tuple[int, int], stride: Tuple[int, int] = None, padding: Tuple[int, int] = (0, 0)) Tuple[List[AffineExpression], Tuple[int, int, int, int]][source]

Propage à travers une couche MaxPool2D

Pour MaxPool, on utilise une relaxation: on prend l’expression avec la borne supérieure maximale (approximation conservative)

Parameters:
  • expressions – Liste d’expressions affines

  • input_shape – (batch, channels, height, width)

  • kernel_size – (pool_h, pool_w)

  • stride – (stride_h, stride_w), par défaut = kernel_size

  • padding – (pad_h, pad_w)

Returns:

(expressions de sortie, output_shape)

static avgpool2d_layer(expressions: List[AffineExpression], input_shape: Tuple[int, int, int, int], kernel_size: Tuple[int, int], stride: Tuple[int, int] = None, padding: Tuple[int, int] = (0, 0)) Tuple[List[AffineExpression], Tuple[int, int, int, int]][source]

Propage à travers une couche AvgPool2D (opération linéaire)

Parameters:
  • expressions – Liste d’expressions affines

  • input_shape – (batch, channels, height, width)

  • kernel_size – (pool_h, pool_w)

  • stride – (stride_h, stride_w)

  • padding – (pad_h, pad_w)

Returns:

(expressions de sortie, output_shape)

AffineExpression

class abstractnn.affine_engine.AffineExpression(constant: float, coefficients: Dict[int, float], bounds: Dict[int, Tuple[float, float]])[source]

Bases: object

Représente une expression affine : y = a0 + sum(aj * xj) avec xj ∈ [lj, uj]

constant

The constant term \(c_0\) in the affine expression

coefficients

Dictionary mapping symbol indices to coefficients

bounds

Dictionary mapping symbol indices to their bounds \([\underline{\epsilon_i}, \overline{\epsilon_i}]\)

get_bounds()[source]

Compute interval bounds for this expression:

\[ \begin{align}\begin{aligned}\underline{y} = c_0 + \sum_{i: c_i \geq 0} c_i \cdot \underline{\epsilon_i} + \sum_{i: c_i < 0} c_i \cdot \overline{\epsilon_i}\\\overline{y} = c_0 + \sum_{i: c_i \geq 0} c_i \cdot \overline{\epsilon_i} + \sum_{i: c_i < 0} c_i \cdot \underline{\epsilon_i}\end{aligned}\end{align} \]
__init__(constant: float, coefficients: Dict[int, float], bounds: Dict[int, Tuple[float, float]])[source]
get_bounds() Tuple[float, float][source]

Calcule les bornes [min, max] de l’expression affine

__add__(other)[source]

Addition de deux expressions affines

__mul__(scalar)[source]

Multiplication par un scalaire

AffineExpressionEngine

class abstractnn.affine_engine.AffineExpressionEngine[source]

Bases: object

Moteur de manipulation d’expressions affines

create_input_expressions(image, noise_level)[source]

Create affine expressions for perturbed input:

\[x_i = \text{image}_i + \epsilon \cdot \delta_i, \quad \delta_i \in [-1, 1]\]
Parameters:
  • image (numpy.ndarray) – Input image

  • noise_level (float) – Perturbation radius \(\epsilon\)

Returns:

List of affine expressions

Return type:

List[AffineExpression]

conv2d_layer(expressions, weights, bias, input_shape, stride, padding, dilation)[source]

Propagate through convolutional layer:

\[y_{out}[n, c_{out}, h, w] = \text{bias}[c_{out}] + \sum_{c_{in}=0}^{C_{in}-1} \sum_{k_h, k_w} \text{weight}[c_{out}, c_{in}, k_h, k_w] \cdot x_{in}[n, c_{in}, h \cdot s_h + k_h, w \cdot s_w + k_w]\]
linear_layer(expressions, weights, bias)[source]

Propagate through fully-connected layer:

\[y = Wx + b\]
static create_input_expressions(input_data: ndarray, noise_level: float) List[AffineExpression][source]

Crée les expressions affines initiales pour l’entrée avec bruit Chaque pixel x_i devient: x_i = 0 + 1*ε_i où ε_i ∈ [value-noise, value+noise]

static linear_layer(expressions: List[AffineExpression], weight: ndarray, bias: ndarray = None) List[AffineExpression][source]

Propage à travers une couche linéaire (MatMul + bias)

static conv2d_layer(expressions: List[AffineExpression], weight: ndarray, bias: ndarray = None, input_shape: Tuple[int, int, int, int] = None, stride: Tuple[int, int] = (1, 1), padding: Tuple[int, int] = (0, 0), dilation: Tuple[int, int] = (1, 1)) Tuple[List[AffineExpression], Tuple[int, int, int, int]][source]

Propage à travers une couche convolutionnelle 2D

Parameters:
  • expressions – Liste d’expressions affines (input flattened)

  • weight – Poids de convolution de forme (out_channels, in_channels, kH, kW)

  • bias – Biais de forme (out_channels,)

  • input_shape – (batch, in_channels, height, width)

  • stride – (stride_h, stride_w)

  • padding – (pad_h, pad_w)

  • dilation – (dilation_h, dilation_w)

Returns:

(expressions de sortie, output_shape)

static maxpool2d_layer(expressions: List[AffineExpression], input_shape: Tuple[int, int, int, int], kernel_size: Tuple[int, int], stride: Tuple[int, int] = None, padding: Tuple[int, int] = (0, 0)) Tuple[List[AffineExpression], Tuple[int, int, int, int]][source]

Propage à travers une couche MaxPool2D

Pour MaxPool, on utilise une relaxation: on prend l’expression avec la borne supérieure maximale (approximation conservative)

Parameters:
  • expressions – Liste d’expressions affines

  • input_shape – (batch, channels, height, width)

  • kernel_size – (pool_h, pool_w)

  • stride – (stride_h, stride_w), par défaut = kernel_size

  • padding – (pad_h, pad_w)

Returns:

(expressions de sortie, output_shape)

static avgpool2d_layer(expressions: List[AffineExpression], input_shape: Tuple[int, int, int, int], kernel_size: Tuple[int, int], stride: Tuple[int, int] = None, padding: Tuple[int, int] = (0, 0)) Tuple[List[AffineExpression], Tuple[int, int, int, int]][source]

Propage à travers une couche AvgPool2D (opération linéaire)

Parameters:
  • expressions – Liste d’expressions affines

  • input_shape – (batch, channels, height, width)

  • kernel_size – (pool_h, pool_w)

  • stride – (stride_h, stride_w)

  • padding – (pad_h, pad_w)

Returns:

(expressions de sortie, output_shape)

Examples

Basic Usage

from abstractnn..affine_engine import AffineExpressionEngine
import numpy as np

engine = AffineExpressionEngine()

# Create perturbed input
image = np.random.rand(3, 28, 28).astype(np.float32)
expressions = engine.create_input_expressions(image, noise_level=0.1)

print(f"Created {len(expressions)} expressions")
print(f"First expression bounds: {expressions[0].get_bounds()}")

Convolution Example

# Define conv layer
weights = np.random.randn(64, 3, 3, 3).astype(np.float32)
bias = np.random.randn(64).astype(np.float32)

# Propagate
output_exprs, output_shape = engine.conv2d_layer(
    expressions,
    weights,
    bias,
    input_shape=(1, 3, 28, 28),
    stride=(1, 1),
    padding=(1, 1),
    dilation=(1, 1)
)

print(f"Output shape: {output_shape}")
print(f"Output expressions: {len(output_exprs)}")