pounce_algorithm/sqp/
qp_assembly.rs1use pounce_common::types::{Index, NLP_LOWER_BOUND_INF, NLP_UPPER_BOUND_INF, Number};
22use pounce_linalg::triplet::{GenTMatrix, GenTMatrixSpace, SymTMatrix, SymTMatrixSpace};
23use pounce_qp::{HessianInertia, QpProblem};
24use std::rc::Rc;
25
26pub struct SqpQpData {
28 pub n: usize,
29 pub m: usize,
30
31 pub h: SymTMatrix,
32 pub g: Vec<Number>,
33 pub a: GenTMatrix,
34 pub bl: Vec<Number>,
35 pub bu: Vec<Number>,
36 pub xl: Vec<Number>,
37 pub xu: Vec<Number>,
38 pub hessian_inertia: HessianInertia,
39}
40
41#[derive(Clone)]
44pub struct Triplet {
45 pub n_rows: usize,
46 pub n_cols: usize,
47 pub irow: Vec<Index>,
48 pub jcol: Vec<Index>,
49 pub vals: Vec<Number>,
50}
51
52impl SqpQpData {
53 pub fn build(
63 x: &[Number],
64 grad_f: &[Number],
65 c_vals: &[Number],
66 bl_c: &[Number],
67 bu_c: &[Number],
68 xl_orig: &[Number],
69 xu_orig: &[Number],
70 jac_c: Triplet,
71 hess_lag: Triplet,
72 hessian_inertia: HessianInertia,
73 ) -> Self {
74 let n = grad_f.len();
75 let m = c_vals.len();
76 assert_eq!(x.len(), n);
77 assert_eq!(bl_c.len(), m);
78 assert_eq!(bu_c.len(), m);
79 assert_eq!(xl_orig.len(), n);
80 assert_eq!(xu_orig.len(), n);
81 assert_eq!(jac_c.n_rows, m);
82 assert_eq!(jac_c.n_cols, n);
83 assert_eq!(hess_lag.n_rows, n);
84 assert_eq!(hess_lag.n_cols, n);
85
86 let h_space = SymTMatrixSpace::new(n as Index, hess_lag.irow, hess_lag.jcol);
87 let mut h = SymTMatrix::new(Rc::clone(&h_space));
88 h.set_values(&hess_lag.vals);
89
90 let a_space = GenTMatrixSpace::new(m as Index, n as Index, jac_c.irow, jac_c.jcol);
91 let mut a = GenTMatrix::new(Rc::clone(&a_space));
92 a.set_values(&jac_c.vals);
93
94 let mut bl = Vec::with_capacity(m);
98 let mut bu = Vec::with_capacity(m);
99 for i in 0..m {
100 bl.push(shift_bound(bl_c[i], c_vals[i], true));
101 bu.push(shift_bound(bu_c[i], c_vals[i], false));
102 }
103
104 let mut xl = Vec::with_capacity(n);
106 let mut xu = Vec::with_capacity(n);
107 for i in 0..n {
108 xl.push(shift_bound(xl_orig[i], x[i], true));
109 xu.push(shift_bound(xu_orig[i], x[i], false));
110 }
111
112 Self {
113 n,
114 m,
115 h,
116 g: grad_f.to_vec(),
117 a,
118 bl,
119 bu,
120 xl,
121 xu,
122 hessian_inertia,
123 }
124 }
125
126 pub fn as_qp(&self) -> QpProblem<'_> {
129 QpProblem {
130 n: self.n,
131 m: self.m,
132 h: &self.h,
133 g: &self.g,
134 a: &self.a,
135 bl: &self.bl,
136 bu: &self.bu,
137 xl: &self.xl,
138 xu: &self.xu,
139 hessian_inertia: self.hessian_inertia,
140 }
141 }
142}
143
144fn shift_bound(bound: Number, current: Number, is_lower: bool) -> Number {
148 if is_lower {
149 if bound <= NLP_LOWER_BOUND_INF {
150 NLP_LOWER_BOUND_INF
151 } else {
152 bound - current
153 }
154 } else if bound >= NLP_UPPER_BOUND_INF {
155 NLP_UPPER_BOUND_INF
156 } else {
157 bound - current
158 }
159}