torch_pfaffian.kernels package¶
Submodules¶
torch_pfaffian.kernels.det_magnitude module¶
- class torch_pfaffian.kernels.det_magnitude.LogMagnitudePfaffian(*args, **kwargs)¶
Bases:
FunctionDifferentiable
log|Pf(A)| = 0.5 * log|det(A)|using a single factorization in each direction.The forward computes one
torch.linalg.slogdet(); the backward supplies the analytic gradient0.5 * (A^{-1})^T(Wirtinger-conjugated for complex inputs) through a single non-raisingtorch.linalg.inv_ex(), instead of differentiating throughslogdet. Differentiating throughslogdetformsgrad * A^{-T}, which is infinite at an exactly-singular input, so even the correct upstream multiplier of0would give0 * inf = NaN. Here exactly-singular elements (det(A) == 0, soslogdetreturns sign0) keep the correct-infvalue and receive a zero gradient: the identity is substituted before the inverse so the factorization stays finite, and the gradient is masked to zero there. Numerically singular elements (a round-offdetwith nonzero sign) are already finite and left unchanged. No host synchronization happens in either direction.- static backward(ctx: BackwardCFunction, grad_output: Tensor) Tensor | None¶
- static forward(ctx: FunctionCtx, matrix: Tensor) Tensor¶
- torch_pfaffian.kernels.det_magnitude.log_magnitude_pfaffian(matrix: Tensor) Tensor¶
Log-magnitude
log|Pf(A)| = 0.5 * log|det(A)|of a batch of skew-symmetric matrices.The value is computed through
torch.linalg.slogdet(), so it works in the log domain and stays finite (and keeps its gradient alive) even for tiny Pfaffians such as probabilities of order2^{-k}that would underflow the linear-domainsqrt(|det|). The gradient uses the analyticLogMagnitudePfaffian, a single factorization each direction that isNaN-free at exactly-singular inputs (see that class). Odd-dimensional inputs are singular, so the log-magnitude is-inf(returned with an autograd connection so a backward through it yields a zero gradient rather than raising, and without reading the entries soinf/naninputs stay-inf).- Parameters:
matrix – Skew-symmetric matrices of shape
(..., m, m), real or complex floating point.- Returns:
The log-magnitude of shape
(...,)in the input’s real floating dtype (real for complex inputs, since a magnitude is real-valued).- Return type:
torch.Tensor
- torch_pfaffian.kernels.det_magnitude.magnitude_pfaffian(matrix: Tensor, *, epsilon: float = 0.0) Tensor¶
Magnitude
|Pf(A)|of a batch of skew-symmetric matrices, real-valued and differentiable.The magnitude is obtained by exponentiating
log_magnitude_pfaffian(). Whenepsilonis positive the log-magnitude is floored at0.5 * log(epsilon)before exponentiation, reproducing the historicalsqrt(clamp(|det|, epsilon))floor as a function argument rather than a mutable global. Prefer the default0.0together withlog_magnitude_pfaffian()for gradient-safe small probabilities.- Parameters:
matrix – Skew-symmetric matrices of shape
(..., m, m), real or complex floating point.epsilon – When positive, floors the result at
sqrt(epsilon). The default0.0applies no floor.
- Returns:
The magnitude
|Pf(A)|of shape(...,)in the input’s real floating dtype.- Return type:
torch.Tensor
torch_pfaffian.kernels.parlett_reid_slog module¶
- torch_pfaffian.kernels.parlett_reid_slog.parlett_reid_slog(matrix: Tensor) tuple[torch.Tensor, torch.Tensor]¶
Log-domain signed Pfaffian of a batch of skew-symmetric matrices via Parlett-Reid elimination.
The batched skew-tridiagonalization with partial pivoting is run device-side with no host synchronization (no
.item(),.any()orisfinite().all()), and the result is accumulated as(phase, log|Pf|)rather than a raw product. The log domain removes both the overflow at large dimensions and the underflow for tiny Pfaffians (probabilities of order2^{-k}). Real and complex inputs share the single code path:phaseis+-1(or0) for real inputs and a unit-modulus complex number for complex inputs. An exact zero pivot column terminates that batch element cleanly with(0, -inf), since its remaining rank-2 updates vanish, so no epsilon threshold is needed.- Parameters:
matrix – Skew-symmetric matrices of shape
(..., m, m), real or complex floating point.- Returns:
A pair
(phase, log_abs)wherephasehas shape(...,)and matches the input dtype (withPf = phase * exp(log_abs), andphase = 0whenPf = 0), andlog_abshas shape(...,)in the matching real dtype (-infwhenPf = 0). Oddmgives(0, -inf)andm = 0gives(1, 0).- Return type:
tuple[torch.Tensor, torch.Tensor]
torch_pfaffian.kernels.small_n module¶
- torch_pfaffian.kernels.small_n.small_pfaffian(matrix: Tensor) Tensor¶
Signed/complex Pfaffian of a batch
(..., m, m)for evenm <= SMALL_N_MAXvia unrolled matchings.This is the compile-time form of the recursive expansion: the perfect matchings are enumerated once per dimension and evaluated as one batched gather followed by unrolled elementwise products and a matvec with the sign vector, with no elimination loop or data-dependent control flow. The factor product is unrolled (rather than
torch.prod()) so that zero entries still get correct product-rule gradients, making the kernel exact and autograd-friendly for the supported sizes.- Parameters:
matrix – Skew-symmetric matrices of shape
(..., m, m)with evenm <= SMALL_N_MAX.- Returns:
The signed Pfaffian of shape
(...,), sharing the input backend, dtype and device.- Return type:
torch.Tensor