#![allow(non_snake_case)]
use super::*;
use crate::algebra::*;
use crate::solver::core::{
cones::{CompositeCone, Cone},
traits::ProblemData,
};
pub struct DefaultProblemData<T> {
pub P: CscMatrix<T>,
pub q: Vec<T>,
pub A: CscMatrix<T>,
pub b: Vec<T>,
pub n: usize,
pub m: usize,
pub equilibration: DefaultEquilibrationData<T>,
pub normq: T,
pub normb: T,
}
impl<T> DefaultProblemData<T>
where
T: FloatT,
{
pub fn new(P: &CscMatrix<T>, q: &[T], A: &CscMatrix<T>, b: &[T]) -> Self {
let (m, n) = (A.nrows(), A.ncols());
let P = P.to_triu();
let q = q.to_vec();
let A = A.clone();
let b = b.to_vec();
let equilibration = DefaultEquilibrationData::<T>::new(n, m);
let normq = q.norm_inf();
let normb = b.norm_inf();
Self {
P,
q,
A,
b,
n,
m,
equilibration,
normq,
normb,
}
}
}
impl<T> ProblemData<T> for DefaultProblemData<T>
where
T: FloatT,
{
type V = DefaultVariables<T>;
type C = CompositeCone<T>;
type SE = DefaultSettings<T>;
fn equilibrate(&mut self, cones: &CompositeCone<T>, settings: &DefaultSettings<T>) {
let data = self;
let equil = &mut data.equilibration;
if !settings.equilibrate_enable {
return;
}
let (d, e) = (&mut equil.d, &mut equil.e);
let dwork = &mut equil.dinv;
let ework = &mut equil.einv;
let (P, A, q, b) = (&mut data.P, &mut data.A, &mut data.q, &mut data.b);
let scale_min = settings.equilibrate_min_scaling;
let scale_max = settings.equilibrate_max_scaling;
for _ in 0..settings.equilibrate_max_iter {
kkt_col_norms(P, A, dwork, ework);
dwork.scalarop(|x| limit_scaling(x, scale_min, scale_max));
ework.scalarop(|x| limit_scaling(x, scale_min, scale_max));
dwork.rsqrt();
ework.rsqrt();
scale_data(P, A, q, b, Some(dwork), ework);
d.hadamard(dwork);
e.hadamard(ework);
P.col_norms(dwork);
let mean_col_norm_P = dwork.mean();
let inf_norm_q = q.norm_inf();
if mean_col_norm_P != T::zero() && inf_norm_q != T::zero() {
let scale_cost = T::max(inf_norm_q, mean_col_norm_P);
let scale_cost = limit_scaling(scale_cost, scale_min, scale_max);
let ctmp = T::recip(scale_cost);
P.scale(ctmp);
q.scale(ctmp);
equil.c *= ctmp;
}
}
if cones.rectify_equilibration(ework, e) {
scale_data(P, A, q, b, None, ework);
e.hadamard(ework);
}
equil.dinv.scalarop_from(T::recip, d);
equil.einv.scalarop_from(T::recip, e);
}
}
fn kkt_col_norms<T: FloatT>(
P: &CscMatrix<T>,
A: &CscMatrix<T>,
norm_LHS: &mut [T],
norm_RHS: &mut [T],
) {
P.col_norms_sym(norm_LHS); A.col_norms_no_reset(norm_LHS); A.row_norms(norm_RHS); }
fn limit_scaling<T>(s: T, minval: T, maxval: T) -> T
where
T: FloatT + ScalarMath<T>,
{
s.clip(minval, maxval, T::one(), maxval)
}
fn scale_data<T: FloatT>(
P: &mut CscMatrix<T>,
A: &mut CscMatrix<T>,
q: &mut [T],
b: &mut [T],
d: Option<&[T]>,
e: &[T],
) {
match d {
Some(d) => {
P.lrscale(d, d); A.lrscale(e, d); q.hadamard(d);
}
None => {
A.lscale(e); }
}
b.hadamard(e);
}