22 ladel_int col, index, nnz_kkt, nnz_schur, n = work->
data->
n, m = work->
data->
m;
25 nnz_kkt = Q->nzmax + n + A->nzmax + m;
27 for (col = 1; col <= n; col++)
30 if (index >= 0 && Q->i[index] == col-1) nnz_kkt--;
34 nnz_schur = nnz_kkt - A->nzmax - m;
38 c->array_int_ncol1 = work->
index_L;
40 c->array_int_ncol1 = NULL;
42 ladel_int Atnz_col, Atnz_col_max = 0;
43 for (col = 0; col < m; col++) Atnz_col_max =
c_max(At->p[col+1] - At->p[col], Atnz_col_max);
44 for (col = 0; col < m; col++)
46 Atnz_col = At->p[col+1] - At->p[col];
47 if (Atnz_col + Atnz_col_max <= n)
48 nnz_schur += (Atnz_col*(Atnz_col-1))/2;
50 nnz_schur += (Atnz_col*(n - Atnz_col_max) - ((n - Atnz_col_max)*(n - Atnz_col_max + 1)) / 2);
52 if (2 * Atnz_col_max > n) nnz_schur += (Atnz_col_max*(Atnz_col_max - 1)) / 2 - (Atnz_col_max*(n - Atnz_col_max) - ((n - Atnz_col_max)*(n - Atnz_col_max + 1)) / 2);
53 nnz_schur =
c_max(
c_min(nnz_schur, (n*(n-1))/2), 1);
56 At = ladel_sparse_free(At);
59 if ((nnz_kkt*nnz_kkt)/(nnz_schur*nnz_schur)*n/(n+m) < 2)
76 ladel_int n = A->ncol;
78 if (A->symmetry == UNSYMMETRIC)
79 ladel_matvec(A, x, y,
TRUE);
81 ladel_symmetric_matvec(A, x, y,
TRUE);
83 ladel_double* x2 = ladel_malloc(n,
sizeof(
c_float));
84 ladel_double_vector_copy(x, n, x2);
85 if (A->symmetry == UNSYMMETRIC)
86 ladel_matvec(A, x2, y,
TRUE);
88 ladel_symmetric_matvec(A, x2, y,
TRUE);
96 ladel_int m = A->nrow;
98 if (A->symmetry == UNSYMMETRIC)
99 ladel_tpose_matvec(A, x, y,
TRUE);
101 ladel_symmetric_matvec(A, x, y,
TRUE);
103 ladel_double* x2 = ladel_malloc(m,
sizeof(
c_float));
104 ladel_double_vector_copy(x, m, x2);
105 if (A->symmetry == UNSYMMETRIC)
106 ladel_tpose_matvec(A, x2, y,
TRUE);
108 ladel_symmetric_matvec(A, x2, y,
TRUE);
117 ladel_int col, index, index_kkt, n = work->
data->
n, m = work->
data->
m, Qnz = Q->nzmax;
121 for (col = 0; col < n; col++)
123 kkt->p[col] = kkt_full->p[col] = Q->p[col];
124 kkt->nz[col] = Q->p[col+1] - Q->p[col];
126 kkt->p[col] = kkt_full->p[col] = Q->p[col];
127 for (index = 0; index < Qnz; index++)
129 kkt->i[index] = kkt_full->i[index] = Q->i[index];
130 kkt->x[index] = kkt_full->x[index] = Q->x[index];
135 for (; col < m+n; col++)
137 kkt_full->i[index_kkt] = first_row_A[col-n] = At->i[At->p[col-n]];
138 kkt_full->x[index_kkt] = first_elem_A[col-n] = At->x[At->p[col-n]];
142 kkt->nz[col] = At->p[col-n+1] - At->p[col-n] + 1;
143 kkt->i[index_kkt] = At->i[At->p[col-n]];
144 kkt->x[index_kkt] = At->x[At->p[col-n]];
149 kkt->i[index_kkt] = col;
150 kkt->x[index_kkt] = 1;
153 if (At->p[col-n+1]-At->p[col-n] != 0) index_kkt++;
155 for (index = At->p[col-n]+1; index < At->p[col-n+1]; index++)
157 kkt->i[index_kkt] = kkt_full->i[index_kkt] = At->i[index];
158 kkt->x[index_kkt] = kkt_full->x[index_kkt] = At->x[index];
162 kkt->i[index_kkt] = kkt_full->i[index_kkt] = col;
163 kkt->x[index_kkt] = kkt_full->x[index_kkt] = -sigma_inv[col-n];
164 if (At->p[col-n+1]-At->p[col-n] == 0) kkt->x[index_kkt] = 1;
167 kkt->p[col+1] = kkt_full->p[col+1] = Qnz + At->p[col+1-n] + 1 + col - n;
175 ladel_int col, n = work->
data->
n, m = work->
data->
m;
179 for (col = n; col < n+m; col++)
183 kkt->nz[col] = At->p[col-n+1] - At->p[col-n] + 1;
184 kkt->i[kkt->p[col]] = first_row_A[col-n];
185 kkt->x[kkt->p[col]] = first_elem_A[col-n];
186 kkt->x[kkt->p[col+1]-1] = -sigma_inv[col-n];
187 kkt->i[kkt->p[col+1]-1] = col;
191 kkt->i[kkt->p[col]] = col;
192 kkt->x[kkt->p[col]] = 1;
200 ladel_int col, index, n = work->
data->
n;
207 kkt->nz[col] = At->p[col-n+1] - At->p[col-n] + 1;
208 kkt->i[kkt->p[col]] = first_row_A[col-n];
209 kkt->x[kkt->p[col]] = first_elem_A[col-n];
210 kkt->x[kkt->p[col+1]-1] = -sigma_inv[col-n];
211 ladel_row_add(work->
solver->
LD, work->
solver->
sym, col, kkt, col, -sigma_inv[col-n], c);
217 ladel_int col, index, n = work->
data->
n;
218 ladel_double *sigma_inv = work->
sigma_inv;
228 kkt->i[kkt->p[col]] = col;
229 kkt->x[kkt->p[col]] = -sigma_inv[col-n];
248 d.diag_elem = 1.0/work->
gamma;
250 else d.diag_size = 0;
258 QAtA = ladel_add_matrices_pattern(work->
data->
Q, AtA, c);
259 QAtA->symmetry = UPPER;
262 ladel_factorize_advanced_with_diag(M, d, work->
solver->
sym, NO_ORDERING, &work->
solver->
LD, QAtA, c);
264 ladel_sparse_free(AtA);
265 ladel_sparse_free(QAtA);
270 ladel_factorize_with_prior_basis_with_diag(M, d, work->
solver->
sym, work->
solver->
LD, c);
277 size_t nb_active = 0;
278 for (
size_t i = 0; i < work->
data->
m; i++) {
286 AtsigmaA = ladel_mat_mat_transpose(At_sqrt_sigma, A_sqrt_sigma, c);
287 QAtsigmaA = ladel_add_matrices(1.0, work->
data->
Q, 1.0, AtsigmaA, c);
288 QAtsigmaA->symmetry = UPPER;
291 AtsigmaA = ladel_sparse_free(AtsigmaA);
292 QAtsigmaA = ladel_sparse_free(QAtsigmaA);
293 At_sqrt_sigma = ladel_sparse_free(At_sqrt_sigma);
294 A_sqrt_sigma = ladel_sparse_free(A_sqrt_sigma);
322 for (k = 0; k < nb_sigma_changed; k++) {
323 row = sigma_changed[k];
324 At_scalex[row] = At_scalex[row]*At_scalex[row];
326 At_scalex[row] =
c_sqrt(1-1/At_scalex[row]);
331 ladel_sparse_matrix *W = ladel_sparse_alloc(work->
data->
n + work->
data->
m, 1, 1, UNSYMMETRIC,
TRUE,
FALSE);
337 for (k = 0; k < nb_sigma_changed; k++)
339 row = sigma_changed[k];
342 factor = work->
sigma_inv[row]*(At_scalex[row] - 1.0);
344 ladel_rank1_update(work->
solver->
LD, work->
solver->
sym, W, 0, factor, UPDATE, c);
346 ladel_sparse_free(W);
350 for (k = 0; k < nb_sigma_changed; k++)
353 sigma_changed[k], At_scalex[sigma_changed[k]], UPDATE, c);
#define FACTORIZE_SCHUR
factorize the Schur complement
#define FACTORIZE_KKT_OR_SCHUR
select automatically between kkt system and schur complement
#define FACTORIZE_KKT
factorize the kkt system
#define c_sqrt
square root
ladel_int c_int
type for integer numbers
ladel_double c_float
type for floating point numbers
#define c_max(a, b)
maximum of two values
#define c_min(a, b)
minimum of two values
void vec_set_scalar(c_float *a, c_float sc, size_t n)
Fill float vector with a scalar value.
void vec_self_mult_scalar(c_float *a, c_float sc, size_t n)
Mulitply vector with a constant scale factor.
void prea_vec_copy(const c_float *a, c_float *b, size_t n)
Copy vector a into preallocated vector b.
Linear algebra with vectors.
void ldlsolveLD_neg_dphi(QPALMWorkspace *work, solver_common *c)
Solve the linear system .
void kkt_update_leaving_constraints(QPALMWorkspace *work, solver_common *c)
Perform a factorization update for the leaving constraints.
void qpalm_form_kkt(QPALMWorkspace *work)
Form the KKT system .
void mat_vec(solver_sparse *A, solver_dense *x, solver_dense *y, solver_common *c)
Matrix-vector multiplication.
void qpalm_set_factorization_method(QPALMWorkspace *work, solver_common *c)
Choose the linear systems solver method based on the problem data sizes.
void ldldowndate_leaving_constraints(QPALMWorkspace *work, solver_common *c)
Downdate the factorization given a set of leaving constraints.
void ldlupdate_sigma_changed(QPALMWorkspace *work, solver_common *c)
Update the factorization given a set of indexes where has been updated.
void kkt_update_entering_constraints(QPALMWorkspace *work, solver_common *c)
Perform a factorization update for the entering constraints.
void ldlcholQAtsigmaA(QPALMWorkspace *work, solver_common *c)
Calculate factorization of , with and the set of active constraints.
void mat_tpose_vec(solver_sparse *A, solver_dense *x, solver_dense *y, solver_common *c)
Matrix-transpose-vector multiplication.
void ldlchol(solver_sparse *M, QPALMWorkspace *work, solver_common *c)
Calculate factorization of a matrix .
void kkt_solve(QPALMWorkspace *work, solver_common *c)
Solve the KKT system .
void qpalm_reform_kkt(QPALMWorkspace *work)
Reform the KKT system (i.e.
void ldlupdate_entering_constraints(QPALMWorkspace *work, solver_common *c)
Update the factorization given a set of entering constraints.
Interface and wrapper to matrix/factorization (ladel) functions.
size_t m
number of constraints m
size_t n
number of variables n
solver_sparse * A
sparse linear constraints matrix A (size m x n)
solver_sparse * Q
sparse quadratic part of the cost Q (size n x n)
c_int proximal
boolean, use proximal method of multipliers or not
c_int factorization_method
factorize KKT or Schur complement
solver_sparse * At_sqrt_sigma
A' * sqrt(sigma)
c_int * first_row_A
row index of the first element in each column of A'
c_int * active_constraints
index set of active constraints
c_int reset_newton
boolean, after sigma is updated perform a new factorization
c_int * leave
index set of leaving constraints
solver_dense * rhs_kkt
[-dphi; zeros(m,1)]
solver_factor * LD
LD factor (part of LDL' factorization)
c_int factorization_method
factorize KKT or Schur complement
c_int * enter
index set of entering constraints
c_int first_factorization
boolean, indicate we have not factorized previously
solver_dense * At_scale
running vector of sqrt(sigma), used to scale At_sqrt_sigma
solver_dense * sol_kkt
sol_kkt = kkt \ rhs_kkt
c_float * first_elem_A
value of the first element in each column of A'
c_int nb_leave
number of leaving constraints
solver_symbolics * sym
symbolics for kkt (only used in LADEL)
solver_sparse * kkt_full
KKT matrix if all constraints would be active.
solver_sparse * kkt
KKT matrix.
c_int nb_enter
number of entering constraints
c_int nb_sigma_changed
number of sigma-components that changed in an outer iteration (relevant for factorization update)
c_float * neg_dphi
-dphi, required as the rhs in SCHUR
QPALMSettings * settings
problem settings
c_float * sigma_inv
1./sigma
c_float gamma
proximal penalty factor
c_float * dphi
gradient of the Lagrangian
QPALMSolver * solver
linsys variables
QPALMData * data
problem data to work on (possibly scaled)
c_int * index_L
index set L (where s>0)
c_float * d
primal update step
ladel_double solver_dense
ladel_sparse_matrix solver_sparse