scs 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|