use super::Constraint;
use crate::matrix_operations;
#[derive(Clone, Copy)]
pub struct SecondOrderCone {
alpha: f64,
}
impl SecondOrderCone {
pub fn new(alpha: f64) -> SecondOrderCone {
assert!(alpha > 0.0); SecondOrderCone { alpha }
}
}
impl Constraint for SecondOrderCone {
fn project(&self, x: &mut [f64]) {
let n = x.len();
assert!(n >= 2, "x must be of dimension at least 2");
let z = &x[..n - 1];
let r = x[n - 1];
let norm_z = matrix_operations::norm2(z);
if self.alpha * norm_z <= -r {
x.iter_mut().for_each(|v| *v = 0.0);
} else if norm_z > self.alpha * r {
let beta = (self.alpha * norm_z + r) / (self.alpha.powi(2) + 1.0);
x[..n - 1]
.iter_mut()
.for_each(|v| *v *= self.alpha * beta / norm_z);
x[n - 1] = beta;
}
}
fn is_convex(&self) -> bool {
true
}
}