use crate::algebra::*;
use crate::solver::chordal::ChordalInfo;
use crate::solver::chordal::SparsityPattern;
use crate::solver::core::cones::*;
use crate::solver::DefaultVariables;
impl<T> ChordalInfo<T>
where
T: FloatT,
{
pub(crate) fn psd_completion(&self, variables: &mut DefaultVariables<T>) {
let cones = &self.init_cones;
let row_ranges: Vec<_> = cones.rng_cones_iter().collect();
for pattern in self.spatterns.iter() {
let row_range = row_ranges[pattern.orig_index].clone();
let z = &mut variables.z[row_range];
complete(z, pattern);
}
}
}
fn complete<T>(z: &mut [T], pattern: &SparsityPattern)
where
T: FloatT,
{
let n = pattern.ordering.len();
let mut Z = Matrix::zeros((n, n));
svec_to_mat(&mut Z, z);
psd_complete(&mut Z, pattern);
mat_to_svec(z, &Z);
}
fn psd_complete<T>(A: &mut Matrix<T>, pattern: &SparsityPattern)
where
T: FloatT,
{
let sntree = &pattern.sntree;
let p = &pattern.ordering;
let ip = invperm(p);
let N = A.ncols();
let mut W = Matrix::zeros((N, N));
W.subsref(A, p, p);
let mut Wαα = Matrix::<T>::zeros((0, 0));
let mut Wαν = Matrix::<T>::zeros((0, 0));
let mut Wηα = Matrix::<T>::zeros((0, 0));
let mut Wηα_times_Y = Matrix::<T>::zeros((0, 0));
let mut chol = CholeskyEngine::new(0);
let mut svd = SVDEngine::new((0, 0));
for j in (0..(sntree.n_cliques - 1)).rev() {
let ν = sntree.get_snode(j);
let α = sntree.get_separators(j);
let i = ν[0];
let η: Vec<usize> = ((i + 1)..N)
.filter(|&x| !α.contains(&x) && !ν.contains(&x))
.collect();
Wαα.resize((α.len(), α.len()));
Wαν.resize((α.len(), ν.len()));
Wηα.resize((η.len(), α.len()));
Wαα.subsref(&W, α, α);
Wαν.subsref(&W, α, ν);
Wηα.subsref(&W, &η, α);
chol.resize(α.len());
match chol.factor(&mut Wαα) {
Ok(()) => {
chol.solve(&mut Wαν);
}
Err(_) => {
svd.resize((α.len(), α.len()));
svd.factor(&mut Wαα).unwrap();
svd.solve(&mut Wαν); }
}
let Y = &Wαν; Wηα_times_Y.resize((η.len(), ν.len()));
Wηα_times_Y.mul(&Wηα, Y, T::one(), T::zero());
W.subsasgn(&η, ν, &Wηα_times_Y);
W.subsasgn(ν, &η, &Wηα_times_Y.t());
}
A.subsref(&W, &ip, &ip);
}