scs 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +42 -13
- data/lib/scs/ffi.rb +1 -7
- data/lib/scs/matrix.rb +72 -0
- data/lib/scs/solver.rb +19 -26
- data/lib/scs/version.rb +1 -1
- data/lib/scs.rb +1 -0
- data/vendor/scs/CITATION.cff +1 -1
- data/vendor/scs/CMakeLists.txt +55 -7
- data/vendor/scs/Makefile +9 -9
- data/vendor/scs/README.md +4 -1
- data/vendor/scs/include/aa.h +1 -1
- data/vendor/scs/include/cones.h +17 -12
- data/vendor/scs/include/glbopts.h +27 -66
- data/vendor/scs/include/linalg.h +2 -1
- data/vendor/scs/include/linsys.h +13 -13
- data/vendor/scs/include/normalize.h +7 -5
- data/vendor/scs/include/rw.h +3 -3
- data/vendor/scs/include/scs.h +85 -106
- data/vendor/scs/include/scs_types.h +34 -0
- data/vendor/scs/include/scs_work.h +80 -0
- data/vendor/scs/include/util.h +3 -1
- data/vendor/scs/linsys/cpu/direct/private.c +86 -73
- data/vendor/scs/linsys/cpu/direct/private.h +2 -2
- data/vendor/scs/linsys/cpu/indirect/private.c +42 -33
- data/vendor/scs/linsys/cpu/indirect/private.h +1 -2
- data/vendor/scs/linsys/csparse.c +3 -3
- data/vendor/scs/linsys/external/amd/LICENSE.txt +0 -897
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +9 -7
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +1 -1
- data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
- data/vendor/scs/linsys/gpu/gpu.h +8 -11
- data/vendor/scs/linsys/gpu/indirect/private.c +72 -49
- data/vendor/scs/linsys/gpu/indirect/private.h +14 -13
- data/vendor/scs/linsys/scs_matrix.c +55 -104
- data/vendor/scs/linsys/scs_matrix.h +5 -4
- data/vendor/scs/scs.mk +1 -5
- data/vendor/scs/src/aa.c +13 -8
- data/vendor/scs/src/cones.c +197 -108
- data/vendor/scs/src/linalg.c +25 -0
- data/vendor/scs/src/normalize.c +75 -26
- data/vendor/scs/src/rw.c +74 -30
- data/vendor/scs/src/scs.c +300 -264
- data/vendor/scs/src/scs_version.c +8 -6
- data/vendor/scs/src/util.c +27 -13
- data/vendor/scs/test/minunit.h +6 -1
- data/vendor/scs/test/problem_utils.h +28 -35
- data/vendor/scs/test/problems/degenerate.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +6 -2
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +5 -4
- data/vendor/scs/test/problems/random_prob.h +6 -2
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +9 -2
- data/vendor/scs/test/problems/small_lp.h +7 -2
- data/vendor/scs/test/problems/small_qp.h +387 -0
- data/vendor/scs/test/problems/{test_fails.h → test_validation.h} +7 -4
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +4 -4
- data/vendor/scs/test/random_socp_prob.c +4 -2
- data/vendor/scs/test/run_from_file.c +16 -4
- data/vendor/scs/test/run_tests.c +23 -14
- metadata +10 -35
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/csparse.o +0 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/scs_matrix.o +0 -0
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_indir.o +0 -0
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.o +0 -0
@@ -18,10 +18,11 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
18
18
|
if (p) {
|
19
19
|
SCS(cs_spfree)(p->L);
|
20
20
|
SCS(cs_spfree)(p->kkt);
|
21
|
+
scs_free(p->diag_p);
|
21
22
|
scs_free(p->perm);
|
22
23
|
scs_free(p->Dinv);
|
23
24
|
scs_free(p->bp);
|
24
|
-
scs_free(p->
|
25
|
+
scs_free(p->diag_r_idxs);
|
25
26
|
scs_free(p->Lnz);
|
26
27
|
scs_free(p->iwork);
|
27
28
|
scs_free(p->etree);
|
@@ -32,9 +33,8 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
32
33
|
}
|
33
34
|
}
|
34
35
|
|
35
|
-
static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
36
|
-
scs_float *
|
37
|
-
scs_float rho_x) {
|
36
|
+
static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P, scs_float *diag_p,
|
37
|
+
const scs_float *diag_r, scs_int *diag_r_idxs) {
|
38
38
|
/* ONLY UPPER TRIANGULAR PART IS STUFFED
|
39
39
|
* forms column compressed kkt matrix
|
40
40
|
* assumes column compressed form A matrix
|
@@ -42,7 +42,7 @@ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
42
42
|
* forms upper triangular part of [(I + P) A'; A -I]
|
43
43
|
* P : n x n, A: m x n.
|
44
44
|
*/
|
45
|
-
scs_int i, j,
|
45
|
+
scs_int h, i, j, count;
|
46
46
|
csc *Kcsc, *K;
|
47
47
|
scs_int n = A->n;
|
48
48
|
scs_int m = A->m;
|
@@ -65,72 +65,80 @@ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
65
65
|
return SCS_NULL;
|
66
66
|
}
|
67
67
|
|
68
|
-
|
68
|
+
count = 0; /* element counter */
|
69
69
|
if (P) {
|
70
|
-
/*
|
71
|
-
for (j = 0; j <
|
70
|
+
/* R_x + P in top left */
|
71
|
+
for (j = 0; j < n; j++) { /* cols */
|
72
|
+
diag_p[j] = 0.;
|
72
73
|
/* empty column, add diagonal */
|
73
74
|
if (P->p[j] == P->p[j + 1]) {
|
74
|
-
K->i[
|
75
|
-
K->p[
|
76
|
-
K->x[
|
77
|
-
|
75
|
+
K->i[count] = j;
|
76
|
+
K->p[count] = j;
|
77
|
+
K->x[count] = diag_r[j];
|
78
|
+
diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
|
79
|
+
count++;
|
78
80
|
}
|
79
|
-
for (
|
80
|
-
i = P->i[
|
81
|
+
for (h = P->p[j]; h < P->p[j + 1]; h++) {
|
82
|
+
i = P->i[h]; /* row */
|
81
83
|
if (i > j) { /* only upper triangular needed */
|
82
84
|
break;
|
83
85
|
}
|
84
|
-
K->i[
|
85
|
-
K->p[
|
86
|
-
K->x[
|
86
|
+
K->i[count] = i;
|
87
|
+
K->p[count] = j;
|
88
|
+
K->x[count] = P->x[h];
|
87
89
|
if (i == j) {
|
88
90
|
/* P has diagonal element */
|
89
|
-
|
91
|
+
diag_p[j] = P->x[h];
|
92
|
+
K->x[count] += diag_r[j];
|
93
|
+
diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
|
90
94
|
}
|
91
|
-
|
95
|
+
count++;
|
92
96
|
/* reached the end without adding diagonal, do it now */
|
93
|
-
if ((i < j) && (
|
94
|
-
K->i[
|
95
|
-
K->p[
|
96
|
-
K->x[
|
97
|
-
|
97
|
+
if ((i < j) && (h + 1 == P->p[j + 1] || P->i[h + 1] > j)) {
|
98
|
+
K->i[count] = j;
|
99
|
+
K->p[count] = j;
|
100
|
+
K->x[count] = diag_r[j];
|
101
|
+
diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
|
102
|
+
count++;
|
98
103
|
}
|
99
104
|
}
|
100
105
|
}
|
101
106
|
} else {
|
102
|
-
/*
|
103
|
-
for (
|
104
|
-
|
105
|
-
K->
|
106
|
-
K->
|
107
|
-
|
107
|
+
/* R_x in top left */
|
108
|
+
for (j = 0; j < n; j++) {
|
109
|
+
diag_p[j] = 0.;
|
110
|
+
K->i[count] = j;
|
111
|
+
K->p[count] = j;
|
112
|
+
K->x[count] = diag_r[j];
|
113
|
+
diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
|
114
|
+
count++;
|
108
115
|
}
|
109
116
|
}
|
110
117
|
|
111
118
|
/* A^T at top right */
|
112
119
|
for (j = 0; j < n; j++) {
|
113
|
-
for (
|
114
|
-
K->p[
|
115
|
-
K->i[
|
116
|
-
K->x[
|
117
|
-
|
120
|
+
for (h = A->p[j]; h < A->p[j + 1]; h++) {
|
121
|
+
K->p[count] = A->i[h] + n;
|
122
|
+
K->i[count] = j;
|
123
|
+
K->x[count] = A->x[h];
|
124
|
+
count++;
|
118
125
|
}
|
119
126
|
}
|
120
127
|
|
121
|
-
/* -
|
122
|
-
for (
|
123
|
-
K->i[
|
124
|
-
K->p[
|
125
|
-
K->x[
|
126
|
-
|
127
|
-
|
128
|
+
/* -R_y at bottom right */
|
129
|
+
for (j = 0; j < m; j++) {
|
130
|
+
K->i[count] = j + n;
|
131
|
+
K->p[count] = j + n;
|
132
|
+
K->x[count] = -diag_r[j + n];
|
133
|
+
diag_r_idxs[j + n] = count; /* store the indices where diag_r occurs */
|
134
|
+
count++;
|
128
135
|
}
|
129
|
-
|
130
|
-
|
136
|
+
|
137
|
+
K->nz = count;
|
138
|
+
idx_mapping = (scs_int *)scs_calloc(K->nz, sizeof(scs_int));
|
131
139
|
Kcsc = SCS(cs_compress)(K, idx_mapping);
|
132
|
-
for (i = 0; i <
|
133
|
-
|
140
|
+
for (i = 0; i < m + n; i++) {
|
141
|
+
diag_r_idxs[i] = idx_mapping[diag_r_idxs[i]];
|
134
142
|
}
|
135
143
|
SCS(cs_spfree)(K);
|
136
144
|
scs_free(idx_mapping);
|
@@ -138,7 +146,7 @@ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
138
146
|
}
|
139
147
|
|
140
148
|
static scs_int _ldl_init(csc *A, scs_int *P, scs_float **info) {
|
141
|
-
*info = (scs_float *)
|
149
|
+
*info = (scs_float *)scs_calloc(AMD_INFO, sizeof(scs_float));
|
142
150
|
return amd_order(A->n, A->p, A->i, P, (scs_float *)SCS_NULL, *info);
|
143
151
|
}
|
144
152
|
|
@@ -146,10 +154,10 @@ static scs_int _ldl_init(csc *A, scs_int *P, scs_float **info) {
|
|
146
154
|
static scs_int ldl_prepare(ScsLinSysWork *p) {
|
147
155
|
csc *kkt = p->kkt, *L = p->L;
|
148
156
|
scs_int n = kkt->n;
|
149
|
-
p->etree = (scs_int *)
|
150
|
-
p->Lnz = (scs_int *)
|
151
|
-
p->iwork = (scs_int *)
|
152
|
-
L->p = (scs_int *)
|
157
|
+
p->etree = (scs_int *)scs_calloc(n, sizeof(scs_int));
|
158
|
+
p->Lnz = (scs_int *)scs_calloc(n, sizeof(scs_int));
|
159
|
+
p->iwork = (scs_int *)scs_calloc(3 * n, sizeof(scs_int));
|
160
|
+
L->p = (scs_int *)scs_calloc((1 + n), sizeof(scs_int));
|
153
161
|
L->nzmax = QDLDL_etree(n, kkt->p, kkt->i, p->iwork, p->Lnz, p->etree);
|
154
162
|
if (L->nzmax < 0) {
|
155
163
|
scs_printf("Error in elimination tree calculation.\n");
|
@@ -161,12 +169,12 @@ static scs_int ldl_prepare(ScsLinSysWork *p) {
|
|
161
169
|
return L->nzmax;
|
162
170
|
}
|
163
171
|
|
164
|
-
L->x = (scs_float *)
|
165
|
-
L->i = (scs_int *)
|
166
|
-
p->Dinv = (scs_float *)
|
167
|
-
p->D = (scs_float *)
|
168
|
-
p->bwork = (scs_int *)
|
169
|
-
p->fwork = (scs_float *)
|
172
|
+
L->x = (scs_float *)scs_calloc(L->nzmax, sizeof(scs_float));
|
173
|
+
L->i = (scs_int *)scs_calloc(L->nzmax, sizeof(scs_int));
|
174
|
+
p->Dinv = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
175
|
+
p->D = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
176
|
+
p->bwork = (scs_int *)scs_calloc(n, sizeof(scs_int));
|
177
|
+
p->fwork = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
170
178
|
return L->nzmax;
|
171
179
|
}
|
172
180
|
|
@@ -223,7 +231,7 @@ static scs_int *cs_pinv(scs_int const *p, scs_int n) {
|
|
223
231
|
if (!p) {
|
224
232
|
return SCS_NULL;
|
225
233
|
} /* p = SCS_NULL denotes identity */
|
226
|
-
pinv = (scs_int *)
|
234
|
+
pinv = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* allocate result */
|
227
235
|
if (!pinv) {
|
228
236
|
return SCS_NULL;
|
229
237
|
} /* out of memory */
|
@@ -283,10 +291,10 @@ static csc *cs_symperm(const csc *A, const scs_int *pinv, scs_int *idx_mapping,
|
|
283
291
|
}
|
284
292
|
|
285
293
|
static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
286
|
-
ScsLinSysWork *p, scs_float *
|
294
|
+
ScsLinSysWork *p, const scs_float *diag_r) {
|
287
295
|
scs_float *info;
|
288
296
|
scs_int *Pinv, amd_status, *idx_mapping, i;
|
289
|
-
csc *kkt_perm, *kkt = form_kkt(A, P,
|
297
|
+
csc *kkt_perm, *kkt = form_kkt(A, P, p->diag_p, diag_r, p->diag_r_idxs);
|
290
298
|
if (!kkt) {
|
291
299
|
return SCS_NULL;
|
292
300
|
}
|
@@ -300,10 +308,10 @@ static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
300
308
|
amd_info(info);
|
301
309
|
#endif
|
302
310
|
Pinv = cs_pinv(p->perm, A->n + A->m);
|
303
|
-
idx_mapping = (scs_int *)
|
311
|
+
idx_mapping = (scs_int *)scs_calloc(kkt->nzmax, sizeof(scs_int));
|
304
312
|
kkt_perm = cs_symperm(kkt, Pinv, idx_mapping, 1);
|
305
|
-
for (i = 0; i < A->m; i++) {
|
306
|
-
p->
|
313
|
+
for (i = 0; i < A->n + A->m; i++) {
|
314
|
+
p->diag_r_idxs[i] = idx_mapping[p->diag_r_idxs[i]];
|
307
315
|
}
|
308
316
|
SCS(cs_spfree)(kkt);
|
309
317
|
scs_free(Pinv);
|
@@ -312,10 +320,15 @@ static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
|
|
312
320
|
return kkt_perm;
|
313
321
|
}
|
314
322
|
|
315
|
-
void SCS(
|
323
|
+
void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
|
316
324
|
scs_int i, ldl_status;
|
317
|
-
for (i = 0; i < p->
|
318
|
-
|
325
|
+
for (i = 0; i < p->n; ++i) {
|
326
|
+
/* top left is R_x + P, bottom right is -R_y */
|
327
|
+
p->kkt->x[p->diag_r_idxs[i]] = p->diag_p[i] + diag_r[i];
|
328
|
+
}
|
329
|
+
for (i = p->n; i < p->n + p->m; ++i) {
|
330
|
+
/* top left is R_x + P, bottom right is -R_y */
|
331
|
+
p->kkt->x[p->diag_r_idxs[i]] = -diag_r[i];
|
319
332
|
}
|
320
333
|
ldl_status = ldl_factor(p, p->n);
|
321
334
|
if (ldl_status < 0) {
|
@@ -327,21 +340,21 @@ void SCS(update_lin_sys_rho_y_vec)(ScsLinSysWork *p, scs_float *rho_y_vec) {
|
|
327
340
|
}
|
328
341
|
|
329
342
|
ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
|
330
|
-
scs_float *
|
343
|
+
const scs_float *diag_r) {
|
331
344
|
ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
|
332
345
|
scs_int n_plus_m = A->n + A->m, ldl_status, ldl_prepare_status;
|
333
346
|
p->m = A->m;
|
334
347
|
p->n = A->n;
|
335
|
-
p->
|
336
|
-
p->perm = (scs_int *)
|
337
|
-
p->L = (csc *)
|
338
|
-
p->bp = (scs_float *)
|
339
|
-
p->
|
348
|
+
p->diag_p = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
349
|
+
p->perm = (scs_int *)scs_calloc(sizeof(scs_int), n_plus_m);
|
350
|
+
p->L = (csc *)scs_calloc(1, sizeof(csc));
|
351
|
+
p->bp = (scs_float *)scs_calloc(n_plus_m, sizeof(scs_float));
|
352
|
+
p->diag_r_idxs = (scs_int *)scs_calloc(n_plus_m, sizeof(scs_int));
|
340
353
|
p->factorizations = 0;
|
341
354
|
p->L->m = n_plus_m;
|
342
355
|
p->L->n = n_plus_m;
|
343
356
|
p->L->nz = -1;
|
344
|
-
p->kkt = permute_kkt(A, P, p,
|
357
|
+
p->kkt = permute_kkt(A, P, p, diag_r);
|
345
358
|
ldl_prepare_status = ldl_prepare(p);
|
346
359
|
ldl_status = ldl_factor(p, A->n);
|
347
360
|
if (ldl_prepare_status < 0 || ldl_status < 0) {
|
@@ -18,12 +18,12 @@ struct SCS_LIN_SYS_WORK {
|
|
18
18
|
scs_float *Dinv; /* inverse diagonal matrix of factorization */
|
19
19
|
scs_int *perm; /* permutation of KKT matrix for factorization */
|
20
20
|
scs_float *bp; /* workspace memory for solves */
|
21
|
-
scs_int *
|
21
|
+
scs_int *diag_r_idxs;
|
22
22
|
scs_int factorizations;
|
23
23
|
/* ldl factorization workspace */
|
24
24
|
scs_float *D, *fwork;
|
25
25
|
scs_int *etree, *iwork, *Lnz, *bwork;
|
26
|
-
scs_float
|
26
|
+
scs_float *diag_p;
|
27
27
|
};
|
28
28
|
|
29
29
|
#ifdef __cplusplus
|
@@ -17,7 +17,8 @@ char *SCS(get_lin_sys_summary)(ScsLinSysWork *p, const ScsInfo *info) {
|
|
17
17
|
}
|
18
18
|
*/
|
19
19
|
|
20
|
-
/*
|
20
|
+
/* Not possible to do this on the fly due to M_ii += a_i' (R_y)^-1 a_i */
|
21
|
+
/* set M = inv ( diag ( R_x + P + A' R_y^{-1} A ) ) */
|
21
22
|
static void set_preconditioner(ScsLinSysWork *p) {
|
22
23
|
scs_int i, k;
|
23
24
|
scs_float *M = p->M;
|
@@ -28,22 +29,26 @@ static void set_preconditioner(ScsLinSysWork *p) {
|
|
28
29
|
scs_printf("getting pre-conditioner\n");
|
29
30
|
#endif
|
30
31
|
|
32
|
+
/* M_ii = (R_x)_i + P_ii + a_i' (R_y)^-1 a_i */
|
31
33
|
for (i = 0; i < A->n; ++i) { /* cols */
|
32
|
-
|
33
|
-
|
34
|
+
/* M_ii = (R_x)_i */
|
35
|
+
M[i] = p->diag_r[i];
|
36
|
+
/* M_ii += a_i' (R_y)^-1 a_i */
|
34
37
|
for (k = A->p[i]; k < A->p[i + 1]; ++k) {
|
35
38
|
/* A->i[k] is row of entry k with value A->x[k] */
|
36
|
-
M[i] += A->x[k] * A->x[k] / p->
|
39
|
+
M[i] += A->x[k] * A->x[k] / p->diag_r[A->n + A->i[k]];
|
37
40
|
}
|
38
41
|
if (P) {
|
39
42
|
for (k = P->p[i]; k < P->p[i + 1]; k++) {
|
40
43
|
/* diagonal element only */
|
41
44
|
if (P->i[k] == i) { /* row == col */
|
45
|
+
/* M_ii += P_ii */
|
42
46
|
M[i] += P->x[k];
|
43
47
|
break;
|
44
48
|
}
|
45
49
|
}
|
46
50
|
}
|
51
|
+
/* finally invert for pre-conditioner */
|
47
52
|
M[i] = 1. / M[i];
|
48
53
|
}
|
49
54
|
#if VERBOSITY > 0
|
@@ -111,10 +116,18 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
111
116
|
}
|
112
117
|
|
113
118
|
/* vec -> R_y^{-1} vec */
|
114
|
-
static void
|
119
|
+
static void scale_by_r_y_inv(scs_float *vec, ScsLinSysWork *p) {
|
115
120
|
scs_int i;
|
116
121
|
for (i = 0; i < p->m; ++i) {
|
117
|
-
vec[i] /= p->
|
122
|
+
vec[i] /= p->diag_r[p->n + i];
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
/* y += R_x * x */
|
127
|
+
static void accum_by_r_x(scs_float *y, const scs_float *x, ScsLinSysWork *p) {
|
128
|
+
scs_int i;
|
129
|
+
for (i = 0; i < p->n; ++i) {
|
130
|
+
y[i] += p->diag_r[i] * x[i];
|
118
131
|
}
|
119
132
|
}
|
120
133
|
|
@@ -123,7 +136,7 @@ static void accum_by_a(ScsLinSysWork *p, const scs_float *x, scs_float *y) {
|
|
123
136
|
SCS(accum_by_atrans)(p->At, x, y);
|
124
137
|
}
|
125
138
|
|
126
|
-
/* y = (
|
139
|
+
/* y = (R_x + P + A' R_y^{-1} A) x */
|
127
140
|
static void mat_vec(const ScsMatrix *A, const ScsMatrix *P, ScsLinSysWork *p,
|
128
141
|
const scs_float *x, scs_float *y) {
|
129
142
|
scs_float *z = p->tmp;
|
@@ -133,10 +146,10 @@ static void mat_vec(const ScsMatrix *A, const ScsMatrix *P, ScsLinSysWork *p,
|
|
133
146
|
SCS(accum_by_p)(P, x, y); /* y = Px */
|
134
147
|
}
|
135
148
|
accum_by_a(p, x, z); /* z = Ax */
|
136
|
-
|
149
|
+
scale_by_r_y_inv(z, p); /* z = R_y^{-1} A x */
|
137
150
|
SCS(accum_by_atrans)(A, z, y); /* y += A'z, y = Px + A' R_y^{-1} Ax */
|
138
|
-
/* y =
|
139
|
-
|
151
|
+
/* y = R_x * x + Px + A' R_y^{-1} A * x */
|
152
|
+
accum_by_r_x(y, x, p);
|
140
153
|
}
|
141
154
|
|
142
155
|
static void apply_pre_conditioner(scs_float *z, scs_float *r, scs_int n,
|
@@ -149,36 +162,35 @@ static void apply_pre_conditioner(scs_float *z, scs_float *r, scs_int n,
|
|
149
162
|
}
|
150
163
|
|
151
164
|
/* no need to update anything in this case */
|
152
|
-
void SCS(
|
153
|
-
p->
|
165
|
+
void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
|
166
|
+
p->diag_r = diag_r; /* this isn't needed but do it to be safe */
|
154
167
|
set_preconditioner(p);
|
155
168
|
}
|
156
169
|
|
157
170
|
ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
|
158
|
-
scs_float *
|
171
|
+
const scs_float *diag_r) {
|
159
172
|
ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
|
160
173
|
p->A = A;
|
161
174
|
p->P = P;
|
162
175
|
p->m = A->m;
|
163
176
|
p->n = A->n;
|
164
|
-
p->rho_x = rho_x;
|
165
177
|
|
166
|
-
p->p = (scs_float *)
|
167
|
-
p->r = (scs_float *)
|
168
|
-
p->Gp = (scs_float *)
|
169
|
-
p->tmp = (scs_float *)
|
178
|
+
p->p = (scs_float *)scs_calloc((A->n), sizeof(scs_float));
|
179
|
+
p->r = (scs_float *)scs_calloc((A->n), sizeof(scs_float));
|
180
|
+
p->Gp = (scs_float *)scs_calloc((A->n), sizeof(scs_float));
|
181
|
+
p->tmp = (scs_float *)scs_calloc((A->m), sizeof(scs_float));
|
170
182
|
|
171
183
|
/* memory for A transpose */
|
172
|
-
p->At = (ScsMatrix *)
|
184
|
+
p->At = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
173
185
|
p->At->m = A->n;
|
174
186
|
p->At->n = A->m;
|
175
|
-
p->At->i = (scs_int *)
|
176
|
-
p->At->p = (scs_int *)
|
177
|
-
p->At->x = (scs_float *)
|
187
|
+
p->At->i = (scs_int *)scs_calloc((A->p[A->n]), sizeof(scs_int));
|
188
|
+
p->At->p = (scs_int *)scs_calloc((A->m + 1), sizeof(scs_int));
|
189
|
+
p->At->x = (scs_float *)scs_calloc((A->p[A->n]), sizeof(scs_float));
|
178
190
|
transpose(A, p);
|
179
191
|
|
180
192
|
/* preconditioner memory */
|
181
|
-
p->
|
193
|
+
p->diag_r = diag_r;
|
182
194
|
p->z = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
183
195
|
p->M = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
184
196
|
set_preconditioner(p);
|
@@ -192,8 +204,7 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
|
|
192
204
|
return p;
|
193
205
|
}
|
194
206
|
|
195
|
-
/* solves (
|
196
|
-
* b */
|
207
|
+
/* solves (R_x * I + P + A' R_y^{-1} A)x = b, s warm start, solution in b */
|
197
208
|
static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *b,
|
198
209
|
scs_int max_its, scs_float tol) {
|
199
210
|
scs_int i, n = pr->n;
|
@@ -268,14 +279,12 @@ static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *b,
|
|
268
279
|
/* solves Mx = b, for x but stores result in b */
|
269
280
|
/* s contains warm-start (if available) */
|
270
281
|
/*
|
271
|
-
* [x] = [
|
272
|
-
* [y] [
|
273
|
-
*
|
274
|
-
* R_y = diag(rho_y_vec)
|
282
|
+
* [x] = [R_x + P A' ]^{-1} [rx]
|
283
|
+
* [y] [ A -R_y ] [ry]
|
275
284
|
*
|
276
285
|
* becomes:
|
277
286
|
*
|
278
|
-
* x = (
|
287
|
+
* x = (R_x + P + A' R_y^{-1} A)^{-1} (rx + A' R_y^{-1} ry)
|
279
288
|
* y = R_y^{-1} (Ax - ry)
|
280
289
|
*
|
281
290
|
*/
|
@@ -299,12 +308,12 @@ scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
|
|
299
308
|
/* tmp = ry */
|
300
309
|
memcpy(p->tmp, &(b[p->n]), p->m * sizeof(scs_float));
|
301
310
|
/* tmp = R_y^{-1} * ry */
|
302
|
-
|
311
|
+
scale_by_r_y_inv(p->tmp, p);
|
303
312
|
/* b[:n] = rx + A' R_y^{-1} ry */
|
304
313
|
SCS(accum_by_atrans)(p->A, p->tmp, b);
|
305
314
|
/* set max_iters to 10 * n (though in theory n is enough for any tol) */
|
306
315
|
max_iters = 10 * p->n;
|
307
|
-
/* solves (
|
316
|
+
/* solves (R_x + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
|
308
317
|
* b */
|
309
318
|
cg_its = pcg(p, s, b, max_iters, tol); /* b[:n] = x */
|
310
319
|
|
@@ -313,7 +322,7 @@ scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
|
|
313
322
|
/* b[n:] = Ax - ry */
|
314
323
|
accum_by_a(p, b, &(b[p->n]));
|
315
324
|
/* b[n:] = R_y^{-1} (Ax - ry) = y */
|
316
|
-
|
325
|
+
scale_by_r_y_inv(&(b[p->n]), p);
|
317
326
|
p->tot_cg_its += cg_its;
|
318
327
|
#if VERBOSITY > 1
|
319
328
|
scs_printf("tol %.3e\n", tol);
|
data/vendor/scs/linsys/csparse.c
CHANGED
@@ -12,9 +12,9 @@ csc *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values,
|
|
12
12
|
A->n = n;
|
13
13
|
A->nzmax = nzmax = MAX(nzmax, 1);
|
14
14
|
A->nz = triplet ? 0 : -1; /* allocate triplet or comp.col */
|
15
|
-
A->p = (scs_int *)
|
16
|
-
A->i = (scs_int *)
|
17
|
-
A->x = values ? (scs_float *)
|
15
|
+
A->p = (scs_int *)scs_calloc((triplet ? nzmax : n + 1), sizeof(scs_int));
|
16
|
+
A->i = (scs_int *)scs_calloc(nzmax, sizeof(scs_int));
|
17
|
+
A->x = values ? (scs_float *)scs_calloc(nzmax, sizeof(scs_float)) : SCS_NULL;
|
18
18
|
return (!A->p || !A->i || (values && !A->x)) ? SCS(cs_spfree)(A) : A;
|
19
19
|
}
|
20
20
|
|