Skip to main content

signed_permutation

Function signed_permutation 

Source
pub fn signed_permutation(
    a: MatRef<'_, f64>,
    reference: MatRef<'_, f64>,
    check_finite: bool,
) -> Result<SignedPermutationAlignment, ProcrustesError>
Expand description

Solve min_{P ∈ S_K, s ∈ {±1}^K} ‖a · P · diag(s) − reference‖_F exactly.

§Algorithm

For K ≤ 3: brute-force enumeration of K! permutations (cost-per-cell nb[p[k]] − 2·|dot[p[k], k]| + nr[k], optimal sign per permutation closed-form). For K ≥ 4: Jonker-Volgenant linear assignment on -|aᵀ·reference|, O(K³). Both paths return the global optimum; permutation at exact cost ties is implementation-defined and may differ between the two paths.

§Errors

Same as crate::orthogonal.

§Examples

use procrustes::Mat;
// a is the 4×2 identity columns swapped, with column 1 sign-flipped.
let a = Mat::<f64>::from_fn(4, 2, |i, j| match (i, j) {
    (0, 1) => 1.0,
    (1, 0) => -1.0,
    _ => 0.0,
});
let reference = Mat::<f64>::from_fn(4, 2, |i, j| if i == j { 1.0 } else { 0.0 });
let aln = procrustes::signed_permutation(a.as_ref(), reference.as_ref(), true).unwrap();
assert_eq!(aln.assigned, vec![1, 0]);
assert_eq!(aln.signs, vec![1.0, -1.0]);
assert!(aln.residual_frobenius < 1e-10);