22#define LOBPCG_TOL 1e-5   
   25    #define M_PI 3.14159265358979323846 
   37        # ifdef QPALM_PRINTING 
   46            # ifdef QPALM_PRINTING 
   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;
 
   67            # ifdef QPALM_PRINTING 
   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++) {
 
  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 QPALM_NONCONVEX 
  334    lambda = lobpcg(work, NULL, c);
 
  346    #ifdef QPALM_PRINTING 
  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
 
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, .
 
Linear algebra with vectors.
 
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