18#ifdef COMPILE_NONCONVEX
22#define LOBPCG_TOL 1e-5
25 #define M_PI 3.14159265358979323846
47 qpalm_eprint(
"Imaginary roots. This should not happen.");
51 r[0] = (-b-di_sqrt)/(2*a);
52 r[1] = (-b+di_sqrt)/(2*a);
56 c_float temp, q, p, re, an, r13;
61 q = (3.0*c - (b*b))/9.0;
62 p = (-(27.0*d) + b*(9.0*c - 2.0*(b*b)))/54.0;
68 qpalm_eprint(
"Imaginary roots. This should not happen.");
77 r[0] = -re + r13*
c_cos(an/3.0);
78 r[1] = -re + r13*
c_cos((an + 2.0*
M_PI)/3.0);
79 r[2] = -re + r13*
c_cos((an + 4.0*
M_PI)/3.0);
83 if (r[0] <= r[1] && r[0] <= r[2])
return r[0];
84 else return c_min(r[1], r[2]);
88static int custom_rref(
c_float D[3][3])
94 if (a[0] < a[1] || a[0] < a[2])
100 temp[0] = D[0][0]; temp[1] = D[0][1]; temp[2] = D[0][2];
101 D[0][0] = D[1][0]; D[0][1] = D[1][1]; D[0][2] = D[1][2];
102 D[1][0] = temp[0]; D[1][1] = temp[1]; D[1][2] = temp[2];
108 temp[0] = D[0][0]; temp[1] = D[0][1]; temp[2] = D[0][2];
109 D[0][0] = D[2][0]; D[0][1] = D[2][1]; D[0][2] = D[2][2];
110 D[2][0] = temp[0]; D[2][1] = temp[1]; D[2][2] = temp[2];
119 D[0][1] *= p; D[0][2] *= p; D[0][0] = 1.0;
120 D[1][1] -= D[1][0]*D[0][1]; D[1][2] -= D[1][0]*D[0][2]; D[1][0] = 0;
121 D[2][1] -= D[2][0]*D[0][1]; D[2][2] -= D[2][0]*D[0][2]; D[2][0] = 0;
129 D[1][1] = D[2][1]; D[1][2] = D[2][2];
130 D[2][2] = temp[2]; D[2][1] = 0;
138 D[1][2] *= p; D[1][1] = 1.0;
139 D[0][2] -= D[0][1]*D[1][2]; D[0][1] = 0;
140 D[2][2] -= D[2][1]*D[1][2]; D[2][1] = 0;
148 c_float xqx = B[0][0], xqw = B[0][1], xqp = B[0][2], wqw = B[1][1], wqp = B[1][2], pqp = B[2][2], xp = C[0][2], wp = C[1][2];
149 a = wp*wp + xp*xp - 1;
150 b = (-xqx*wp*wp + 2*xqw*wp*xp - 2*wqp*wp - wqw*xp*xp - 2*xqp*xp + pqp + wqw + xqx);
151 c = (wqp*wqp - 2*xp*wqp*xqw + 2*wp*xqx*wqp + xqp*xqp - 2*wp*xqp*xqw + 2*wqw*xp*xqp + xqw*xqw - pqp*wqw - pqp*xqx - wqw*xqx);
152 d = - xqx*wqp*wqp + 2*wqp*xqp*xqw - wqw*xqp*xqp - pqp*xqw*xqw + pqp*wqw*xqx;
153 c_float lam = min_root_third_order(a, b, c, d);
157 D[0][0] = B[0][0] - lam*C[0][0];
159 D[0][2] = B[0][2] - lam*C[0][2];
161 D[1][1] = B[1][1] - lam*C[1][1];
162 D[1][2] = B[1][2] - lam*C[1][2];
163 D[2][0] = B[2][0] - lam*C[2][0];
164 D[2][1] = B[2][1] - lam*C[2][1];
165 D[2][2] = B[2][2] - lam*C[2][2];
167 int ind = custom_rref(D);
171 x[0] = 1; x[1] = 0; x[2] = 0;
176 x[0] = 0; x[1] = 1; x[2] = 0;
180 c_float temp = 1/
c_sqrt(1 + D[0][2]*D[0][2] - 2*D[0][2]*C[0][2] + D[1][2]*D[1][2] - 2*D[1][2]*C[1][2]);
182 x[0] = -D[0][2]*temp;
183 x[1] = -D[1][2]*temp;
195 size_t n = work->
data->
n;
202 for (i = 0; i < n; i++) {
203 x[i] = (
c_float) rand()/RAND_MAX;
215 mat_vec(A, x_chol , Ax_chol, c);
231 c_float C[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
233 c_float xAw, wAw, xAp, wAp, pAp, xp, wp;
239 mat_vec(A, w_chol, Aw_chol, c);
244 c_float B_init[2][2] = {{lambda, xAw}, {xAw, wAw}};
249 cc = lambda*wAw - xAw*xAw;
251 lambda = (-b-
c_sqrt(di))/2;
252 B_init[0][0] -= lambda;
253 B_init[1][1] -= lambda;
260 B_init[0][1] /= B_init[0][0];
261 b = 1/
c_sqrt(1 + B_init[0][1]*B_init[0][1]);
262 y[0] = -B_init[0][1]*b;
272 size_t max_iter = 10000;
273 for (i = 0; i < max_iter; i++) {
280 lambda -=
c_sqrt(2)*norm_w + 1e-6;
281 if (n <= 3) lambda -= 1e-6;
286 mat_vec(A, w_chol, Aw_chol, c);
302 B[0][0] = lambda; B[0][1] = xAw; B[0][2] = xAp;
303 B[1][0] = xAw; B[1][1] = wAw; B[1][2] = wAp;
304 B[2][0] = xAp; B[2][1] = wAp; B[2][2] = pAp;
306 C[0][2] = xp; C[1][2] = wp; C[2][0] = xp; C[2][1] = wp;
309 lambda = custom_eig(B, C, y);
332 #ifdef COMPILE_NONCONVEX
334 lambda = lobpcg(work, NULL, c);
347 qpalm_print(
"Warning: nonconvex is not supported in this version of QPALM. Setting it to false.\n");
359 for (i=0; i < ncol; i++) {
362 for (j = Mp[i]; j < Mp[i+1]; j++) {
371 ub_eig = center[i] + radius[i];
373 ub_eig =
c_max(ub_eig, (center[i] + radius[i]));
Custom memory allocation, print and utility functions, and data types for floats and ints.
#define c_sqrt
square root
ladel_int c_int
type for integer numbers
#define mod(a, b)
modulo operation (positive result for all values)
ladel_double c_float
type for floating point numbers
#define c_max(a, b)
maximum of two values
#define qpalm_eprint(...)
#define c_absval(x)
absolute value
#define c_min(a, b)
minimum of two values
Linear algebra with vectors.
void vec_add_scaled(const c_float *a, const c_float *b, c_float *c, c_float sc, size_t n)
Scaled addition of one vector to another vector, .
void vec_mult_scalar(const c_float *a, c_float sc, c_float *b, size_t n)
Mulitply vector with a constant scale factor and store in a different vector.
void vec_mult_add_scaled(c_float *a, const c_float *b, c_float sc1, c_float sc2, size_t n)
Scaled addition of one vector to another vector, both being scaled, .
void vec_self_mult_scalar(c_float *a, c_float sc, size_t n)
Mulitply vector with a constant scale factor.
c_float vec_prod(const c_float *a, const c_float *b, size_t n)
Inner product between two vectors, .
c_float vec_norm_two(const c_float *a, size_t n)
2-norm of a vector, .
void prea_vec_copy(const c_float *a, c_float *b, size_t n)
Copy vector a into preallocated vector b.
c_float vec_norm_inf(const c_float *a, size_t n)
Infinity norm of a vector, .
void set_settings_nonconvex(QPALMWorkspace *work, solver_common *c)
Set the proximal parameters for nonconvex QPs.
c_float gershgorin_max(solver_sparse *M, c_float *center, c_float *radius)
Calculate the Gershgorin upper bound for the eigenvalues of a symmetric matrix.
#define LOBPCG_TOL
Tolerance on the infinity norm of the residual in lobpcg.
Routines to deal with nonconvex QPs.
void mat_vec(solver_sparse *A, solver_dense *x, solver_dense *y, solver_common *c)
Matrix-vector multiplication.
size_t n
number of variables n
solver_sparse * Q
sparse quadratic part of the cost Q (size n x n)
c_float gamma_max
proximal penalty parameter cap
c_int proximal
boolean, use proximal method of multipliers or not
c_float gamma_init
initial proximal penalty parameter
c_int nonconvex
boolean, indicates whether the QP is nonconvex
solver_dense * neg_dphi
-gradient of the Lagrangian
solver_dense * d
primal update step
solver_dense * Atyh
A' * yh.
c_float * neg_dphi
-dphi, required as the rhs in SCHUR
c_int gamma_maxed
flag to indicate whether gamma has been maximized when the primal residual was low
QPALMSettings * settings
problem settings
c_float gamma
proximal penalty factor
QPALMSolver * solver
linsys variables
QPALMData * data
problem data to work on (possibly scaled)
c_float * temp_n
placeholder for vector of size n
c_float * d
primal update step
Internal data structures used in QPALM.
ladel_double solver_dense
ladel_sparse_matrix solver_sparse