pub mod amd;
pub mod kkt_matching;
pub mod nested_dissection;
pub mod natural;
use crate::csc::CscMatrix;
#[derive(Debug, Clone, Copy)]
pub enum Ordering {
Amd,
Natural,
NestedDissection,
KktMatchingAmd,
}
pub fn compute_ordering(csc: &CscMatrix, ordering: Ordering) -> (Vec<usize>, Vec<usize>) {
compute_ordering_with_kkt(csc, ordering, None)
}
pub fn compute_ordering_with_kkt(
csc: &CscMatrix,
ordering: Ordering,
n_primal: Option<usize>,
) -> (Vec<usize>, Vec<usize>) {
match ordering {
Ordering::Amd => amd::amd_ordering(csc),
Ordering::Natural => natural::natural_ordering(csc.n),
Ordering::NestedDissection => nested_dissection::nd_ordering(csc),
Ordering::KktMatchingAmd => {
let np = n_primal.unwrap_or(0);
if np > 0 && np < csc.n {
kkt_matching::kkt_matching_ordering(csc, np)
} else {
amd::amd_ordering(csc)
}
}
}
}
pub fn permute_symmetric_csc(csc: &CscMatrix, _perm: &[usize], perm_inv: &[usize]) -> CscMatrix {
let n = csc.n;
let mut triplets: Vec<(usize, usize, f64)> = Vec::with_capacity(csc.nnz());
for old_col in 0..n {
let new_col = perm_inv[old_col];
for idx in csc.col_ptr[old_col]..csc.col_ptr[old_col + 1] {
let old_row = csc.row_idx[idx];
let new_row = perm_inv[old_row];
let val = csc.vals[idx];
let (r, c) = if new_row <= new_col {
(new_row, new_col)
} else {
(new_col, new_row)
};
triplets.push((r, c, val));
}
}
let mut col_count = vec![0usize; n];
for &(_, c, _) in &triplets {
col_count[c] += 1;
}
let mut col_ptr = vec![0usize; n + 1];
for j in 0..n {
col_ptr[j + 1] = col_ptr[j] + col_count[j];
}
let nnz = col_ptr[n];
let mut row_idx = vec![0usize; nnz];
let mut vals = vec![0.0; nnz];
let mut offset = col_ptr[..n].to_vec();
for &(r, c, v) in &triplets {
let pos = offset[c];
row_idx[pos] = r;
vals[pos] = v;
offset[c] += 1;
}
for j in 0..n {
let start = col_ptr[j];
let end = col_ptr[j + 1];
for i in (start + 1)..end {
let key_row = row_idx[i];
let key_val = vals[i];
let mut pos = i;
while pos > start && row_idx[pos - 1] > key_row {
row_idx[pos] = row_idx[pos - 1];
vals[pos] = vals[pos - 1];
pos -= 1;
}
row_idx[pos] = key_row;
vals[pos] = key_val;
}
}
CscMatrix { n, col_ptr, row_idx, vals }
}