scs 0.2.3 → 0.3.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 +4 -0
- data/README.md +11 -6
- data/lib/scs/ffi.rb +30 -13
- data/lib/scs/solver.rb +32 -9
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +39 -0
- data/vendor/scs/CMakeLists.txt +7 -8
- data/vendor/scs/Makefile +24 -15
- data/vendor/scs/README.md +5 -263
- data/vendor/scs/include/aa.h +67 -23
- data/vendor/scs/include/cones.h +17 -17
- data/vendor/scs/include/glbopts.h +98 -32
- data/vendor/scs/include/linalg.h +2 -4
- data/vendor/scs/include/linsys.h +58 -44
- data/vendor/scs/include/normalize.h +3 -3
- data/vendor/scs/include/rw.h +8 -2
- data/vendor/scs/include/scs.h +293 -133
- data/vendor/scs/include/util.h +3 -15
- data/vendor/scs/linsys/cpu/direct/private.c +220 -224
- data/vendor/scs/linsys/cpu/direct/private.h +13 -7
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.c +177 -110
- data/vendor/scs/linsys/cpu/indirect/private.h +8 -4
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/csparse.c +87 -0
- data/vendor/scs/linsys/csparse.h +34 -0
- data/vendor/scs/linsys/csparse.o +0 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +1 -1
- 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_internal.h +1 -1
- 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/changes +2 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.c +29 -46
- data/vendor/scs/linsys/external/qdldl/qdldl.h +33 -41
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl_types.h +11 -3
- data/vendor/scs/linsys/gpu/gpu.c +31 -33
- data/vendor/scs/linsys/gpu/gpu.h +48 -31
- data/vendor/scs/linsys/gpu/indirect/private.c +338 -232
- data/vendor/scs/linsys/gpu/indirect/private.h +23 -14
- data/vendor/scs/linsys/scs_matrix.c +498 -0
- data/vendor/scs/linsys/scs_matrix.h +70 -0
- data/vendor/scs/linsys/scs_matrix.o +0 -0
- data/vendor/scs/scs.mk +13 -9
- data/vendor/scs/src/aa.c +384 -109
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.c +440 -353
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.c +15 -5
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.c +84 -28
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.c +22 -64
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.c +160 -21
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.c +767 -563
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_indir.o +0 -0
- data/vendor/scs/src/scs_version.c +9 -3
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.c +37 -106
- data/vendor/scs/src/util.o +0 -0
- data/vendor/scs/test/minunit.h +17 -8
- data/vendor/scs/test/problem_utils.h +176 -14
- data/vendor/scs/test/problems/degenerate.h +130 -0
- data/vendor/scs/test/problems/hs21_tiny_qp.h +124 -0
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +116 -0
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +100 -0
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +199 -0
- data/vendor/scs/test/problems/random_prob +0 -0
- data/vendor/scs/test/problems/random_prob.h +45 -0
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +188 -31
- data/vendor/scs/test/problems/small_lp.h +13 -14
- data/vendor/scs/test/problems/test_fails.h +43 -0
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +82 -0
- data/vendor/scs/test/random_socp_prob.c +54 -53
- data/vendor/scs/test/rng.h +109 -0
- data/vendor/scs/test/run_from_file.c +19 -10
- data/vendor/scs/test/run_tests.c +27 -3
- metadata +20 -8
- data/vendor/scs/linsys/amatrix.c +0 -305
- data/vendor/scs/linsys/amatrix.h +0 -36
- data/vendor/scs/linsys/amatrix.o +0 -0
- data/vendor/scs/test/data/small_random_socp +0 -0
- data/vendor/scs/test/problems/small_random_socp.h +0 -33
- data/vendor/scs/test/run_tests +0 -2
|
@@ -1,43 +1,52 @@
|
|
|
1
1
|
#include "private.h"
|
|
2
|
+
#include "linsys.h"
|
|
3
|
+
#include "util.h"
|
|
4
|
+
#include <limits.h>
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
char *SCS(get_lin_sys_method)(const ScsMatrix *A, const ScsSettings *stgs) {
|
|
7
|
-
char *str = (char *)scs_malloc(sizeof(char) * 128);
|
|
8
|
-
sprintf(str, "sparse-indirect, nnz in A = %li, CG tol ~ 1/iter^(%2.2f)",
|
|
9
|
-
(long)A->p[A->n], stgs->cg_rate);
|
|
10
|
-
return str;
|
|
6
|
+
const char *SCS(get_lin_sys_method)() {
|
|
7
|
+
return "sparse-indirect";
|
|
11
8
|
}
|
|
12
9
|
|
|
10
|
+
/*
|
|
13
11
|
char *SCS(get_lin_sys_summary)(ScsLinSysWork *p, const ScsInfo *info) {
|
|
14
12
|
char *str = (char *)scs_malloc(sizeof(char) * 128);
|
|
15
|
-
sprintf(str,
|
|
16
|
-
|
|
17
|
-
(scs_float)p->tot_cg_its / (info->iter + 1),
|
|
18
|
-
p->total_solve_time / (info->iter + 1) / 1e3);
|
|
13
|
+
sprintf(str, "lin-sys: avg cg its: %2.2f\n",
|
|
14
|
+
(scs_float)p->tot_cg_its / (info->iter + 1));
|
|
19
15
|
p->tot_cg_its = 0;
|
|
20
|
-
p->total_solve_time = 0;
|
|
21
16
|
return str;
|
|
22
17
|
}
|
|
18
|
+
*/
|
|
23
19
|
|
|
24
|
-
/* M = inv ( diag (
|
|
25
|
-
static void
|
|
26
|
-
|
|
27
|
-
scs_int i;
|
|
20
|
+
/* set M = inv ( diag ( rho_x * I + P + A' R_y^{-1} A ) ) */
|
|
21
|
+
static void set_preconditioner(ScsLinSysWork *p) {
|
|
22
|
+
scs_int i, k;
|
|
28
23
|
scs_float *M = p->M;
|
|
24
|
+
const ScsMatrix *A = p->A;
|
|
25
|
+
const ScsMatrix *P = p->P;
|
|
29
26
|
|
|
30
|
-
#if
|
|
27
|
+
#if VERBOSITY > 0
|
|
31
28
|
scs_printf("getting pre-conditioner\n");
|
|
32
29
|
#endif
|
|
33
30
|
|
|
34
|
-
for (i = 0; i < A->n; ++i) {
|
|
35
|
-
M[i] =
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
for (i = 0; i < A->n; ++i) { /* cols */
|
|
32
|
+
M[i] = p->rho_x;
|
|
33
|
+
/* diag(A' R_y^{-1} A) */
|
|
34
|
+
for (k = A->p[i]; k < A->p[i + 1]; ++k) {
|
|
35
|
+
/* A->i[k] is row of entry k with value A->x[k] */
|
|
36
|
+
M[i] += A->x[k] * A->x[k] / p->rho_y_vec[A->i[k]];
|
|
37
|
+
}
|
|
38
|
+
if (P) {
|
|
39
|
+
for (k = P->p[i]; k < P->p[i + 1]; k++) {
|
|
40
|
+
/* diagonal element only */
|
|
41
|
+
if (P->i[k] == i) { /* row == col */
|
|
42
|
+
M[i] += P->x[k];
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
M[i] = 1. / M[i];
|
|
38
48
|
}
|
|
39
|
-
|
|
40
|
-
#if EXTRA_VERBOSE > 0
|
|
49
|
+
#if VERBOSITY > 0
|
|
41
50
|
scs_printf("finished getting pre-conditioner\n");
|
|
42
51
|
#endif
|
|
43
52
|
}
|
|
@@ -54,15 +63,16 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
|
|
|
54
63
|
scs_float *Ax = A->x;
|
|
55
64
|
|
|
56
65
|
scs_int i, j, q, *z, c1, c2;
|
|
57
|
-
#if
|
|
66
|
+
#if VERBOSITY > 0
|
|
58
67
|
SCS(timer) transpose_timer;
|
|
59
68
|
scs_printf("transposing A\n");
|
|
60
69
|
SCS(tic)(&transpose_timer);
|
|
61
70
|
#endif
|
|
62
71
|
|
|
63
72
|
z = (scs_int *)scs_calloc(m, sizeof(scs_int));
|
|
64
|
-
for (i = 0; i < Ap[n]; i++)
|
|
65
|
-
|
|
73
|
+
for (i = 0; i < Ap[n]; i++)
|
|
74
|
+
z[Ai[i]]++; /* row counts */
|
|
75
|
+
SCS(cumsum)(Cp, z, m); /* row pointers */
|
|
66
76
|
|
|
67
77
|
for (j = 0; j < n; j++) {
|
|
68
78
|
c1 = Ap[j];
|
|
@@ -76,7 +86,7 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
|
|
|
76
86
|
}
|
|
77
87
|
scs_free(z);
|
|
78
88
|
|
|
79
|
-
#if
|
|
89
|
+
#if VERBOSITY > 0
|
|
80
90
|
scs_printf("finished transposing A, time: %1.2es\n",
|
|
81
91
|
SCS(tocq)(&transpose_timer) / 1e3);
|
|
82
92
|
#endif
|
|
@@ -100,40 +110,59 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
|
100
110
|
}
|
|
101
111
|
}
|
|
102
112
|
|
|
103
|
-
/*
|
|
104
|
-
static void
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
memset(y, 0, A->n * sizeof(scs_float));
|
|
110
|
-
SCS(accum_by_atrans)(A, p, tmp, y);
|
|
111
|
-
SCS(add_scaled_array)(y, x, A->n, s->rho_x);
|
|
113
|
+
/* vec -> R_y^{-1} vec */
|
|
114
|
+
static void scale_by_diag_r(scs_float *vec, ScsLinSysWork *p) {
|
|
115
|
+
scs_int i;
|
|
116
|
+
for (i = 0; i < p->m; ++i) {
|
|
117
|
+
vec[i] /= p->rho_y_vec[i];
|
|
118
|
+
}
|
|
112
119
|
}
|
|
113
120
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
SCS(
|
|
121
|
+
/* we use a different accum_by_a here for speed */
|
|
122
|
+
static void accum_by_a(ScsLinSysWork *p, const scs_float *x, scs_float *y) {
|
|
123
|
+
SCS(accum_by_atrans)(p->At, x, y);
|
|
117
124
|
}
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
126
|
+
/* y = (rho_x * I + P + A' R_y^{-1} A) x */
|
|
127
|
+
static void mat_vec(const ScsMatrix *A, const ScsMatrix *P, ScsLinSysWork *p,
|
|
128
|
+
const scs_float *x, scs_float *y) {
|
|
129
|
+
scs_float *z = p->tmp;
|
|
130
|
+
memset(z, 0, A->m * sizeof(scs_float)); /* z = 0 */
|
|
131
|
+
memset(y, 0, A->n * sizeof(scs_float)); /* y = 0 */
|
|
132
|
+
if (P) {
|
|
133
|
+
SCS(accum_by_p)(P, x, y); /* y = Px */
|
|
134
|
+
}
|
|
135
|
+
accum_by_a(p, x, z); /* z = Ax */
|
|
136
|
+
scale_by_diag_r(z, p); /* z = R_y^{-1} A x */
|
|
137
|
+
SCS(accum_by_atrans)(A, z, y); /* y += A'z, y = Px + A' R_y^{-1} Ax */
|
|
138
|
+
/* y = rho_x * x + Px + A' R_y^{-1} A x */
|
|
139
|
+
SCS(add_scaled_array)(y, x, A->n, p->rho_x);
|
|
122
140
|
}
|
|
123
141
|
|
|
124
|
-
static void apply_pre_conditioner(scs_float *
|
|
125
|
-
|
|
142
|
+
static void apply_pre_conditioner(scs_float *z, scs_float *r, scs_int n,
|
|
143
|
+
ScsLinSysWork *pr) {
|
|
126
144
|
scs_int i;
|
|
127
|
-
*
|
|
145
|
+
scs_float *M = pr->M;
|
|
128
146
|
for (i = 0; i < n; ++i) {
|
|
129
147
|
z[i] = r[i] * M[i];
|
|
130
|
-
*ipzr += z[i] * r[i];
|
|
131
148
|
}
|
|
132
149
|
}
|
|
133
150
|
|
|
134
|
-
|
|
135
|
-
|
|
151
|
+
/* no need to update anything in this case */
|
|
152
|
+
void SCS(update_lin_sys_rho_y_vec)(ScsLinSysWork *p, scs_float *rho_y_vec) {
|
|
153
|
+
p->rho_y_vec = rho_y_vec; /* this isn't needed but do it to be safe */
|
|
154
|
+
set_preconditioner(p);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
|
|
158
|
+
scs_float *rho_y_vec, scs_float rho_x) {
|
|
136
159
|
ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
|
|
160
|
+
p->A = A;
|
|
161
|
+
p->P = P;
|
|
162
|
+
p->m = A->m;
|
|
163
|
+
p->n = A->n;
|
|
164
|
+
p->rho_x = rho_x;
|
|
165
|
+
|
|
137
166
|
p->p = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
|
|
138
167
|
p->r = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
|
|
139
168
|
p->Gp = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
|
|
@@ -149,11 +178,11 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
|
|
|
149
178
|
transpose(A, p);
|
|
150
179
|
|
|
151
180
|
/* preconditioner memory */
|
|
152
|
-
p->
|
|
153
|
-
p->
|
|
154
|
-
|
|
181
|
+
p->rho_y_vec = rho_y_vec;
|
|
182
|
+
p->z = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
|
183
|
+
p->M = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
|
184
|
+
set_preconditioner(p);
|
|
155
185
|
|
|
156
|
-
p->total_solve_time = 0;
|
|
157
186
|
p->tot_cg_its = 0;
|
|
158
187
|
if (!p->p || !p->r || !p->Gp || !p->tmp || !p->At || !p->At->i || !p->At->p ||
|
|
159
188
|
!p->At->x) {
|
|
@@ -163,94 +192,132 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
|
|
|
163
192
|
return p;
|
|
164
193
|
}
|
|
165
194
|
|
|
166
|
-
/* solves (I+A'A)x = b, s warm start, solution stored in
|
|
167
|
-
|
|
168
|
-
|
|
195
|
+
/* solves (rho_x * I + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
|
|
196
|
+
* b */
|
|
197
|
+
static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *b,
|
|
169
198
|
scs_int max_its, scs_float tol) {
|
|
170
|
-
scs_int i, n =
|
|
171
|
-
scs_float
|
|
199
|
+
scs_int i, n = pr->n;
|
|
200
|
+
scs_float ztr, ztr_prev, alpha;
|
|
172
201
|
scs_float *p = pr->p; /* cg direction */
|
|
173
202
|
scs_float *Gp = pr->Gp; /* updated CG direction */
|
|
174
203
|
scs_float *r = pr->r; /* cg residual */
|
|
175
204
|
scs_float *z = pr->z; /* for preconditioning */
|
|
176
|
-
scs_float *M = pr->M; /* inverse diagonal preconditioner */
|
|
177
205
|
|
|
178
|
-
|
|
206
|
+
const ScsMatrix *A = pr->A;
|
|
207
|
+
const ScsMatrix *P = pr->P;
|
|
208
|
+
|
|
209
|
+
if (!s) {
|
|
210
|
+
/* take s = 0 */
|
|
211
|
+
/* r = b */
|
|
179
212
|
memcpy(r, b, n * sizeof(scs_float));
|
|
213
|
+
/* b = 0 */
|
|
180
214
|
memset(b, 0, n * sizeof(scs_float));
|
|
181
215
|
} else {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
216
|
+
/* r = Mat * s */
|
|
217
|
+
mat_vec(A, P, pr, s, r);
|
|
218
|
+
/* r = Mat * s - b */
|
|
219
|
+
SCS(add_scaled_array)(r, b, n, -1.);
|
|
220
|
+
/* r = b - Mat * s */
|
|
221
|
+
SCS(scale_array)(r, -1., n);
|
|
222
|
+
/* b = s */
|
|
185
223
|
memcpy(b, s, n * sizeof(scs_float));
|
|
186
224
|
}
|
|
187
225
|
|
|
188
226
|
/* check to see if we need to run CG at all */
|
|
189
|
-
if (
|
|
227
|
+
if (CG_NORM(r, n) < MAX(tol, 1e-12)) {
|
|
190
228
|
return 0;
|
|
191
229
|
}
|
|
192
230
|
|
|
193
|
-
|
|
231
|
+
/* z = M r (M is inverse preconditioner) */
|
|
232
|
+
apply_pre_conditioner(z, r, n, pr);
|
|
233
|
+
/* ztr = z'r */
|
|
234
|
+
ztr = SCS(dot)(z, r, n);
|
|
235
|
+
/* p = z */
|
|
194
236
|
memcpy(p, z, n * sizeof(scs_float));
|
|
195
237
|
|
|
196
238
|
for (i = 0; i < max_its; ++i) {
|
|
197
|
-
|
|
198
|
-
|
|
239
|
+
/* Gp = Mat * p */
|
|
240
|
+
mat_vec(A, P, pr, p, Gp);
|
|
241
|
+
/* alpha = z'r / p'G p */
|
|
242
|
+
alpha = ztr / SCS(dot)(p, Gp, n);
|
|
243
|
+
/* b += alpha * p */
|
|
199
244
|
SCS(add_scaled_array)(b, p, n, alpha);
|
|
245
|
+
/* r -= alpha * G p */
|
|
200
246
|
SCS(add_scaled_array)(r, Gp, n, -alpha);
|
|
201
247
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
(long)i + 1);
|
|
248
|
+
#if VERBOSITY > 3
|
|
249
|
+
scs_printf("tol: %.4e, resid: %.4e, iters: %li\n", tol, CG_NORM(r, n),
|
|
250
|
+
(long)i + 1);
|
|
206
251
|
#endif
|
|
252
|
+
if (CG_NORM(r, n) < tol) {
|
|
207
253
|
return i + 1;
|
|
208
254
|
}
|
|
209
|
-
|
|
210
|
-
apply_pre_conditioner(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
SCS(
|
|
255
|
+
/* z = M r (M is inverse preconditioner) */
|
|
256
|
+
apply_pre_conditioner(z, r, n, pr);
|
|
257
|
+
ztr_prev = ztr;
|
|
258
|
+
/* ztr = z'r */
|
|
259
|
+
ztr = SCS(dot)(z, r, n);
|
|
260
|
+
/* p = beta * p, where beta = ztr / ztr_prev */
|
|
261
|
+
SCS(scale_array)(p, ztr / ztr_prev, n);
|
|
262
|
+
/* p = z + beta * p */
|
|
263
|
+
SCS(add_scaled_array)(p, z, n, 1.);
|
|
214
264
|
}
|
|
215
265
|
return i;
|
|
216
266
|
}
|
|
217
267
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
268
|
+
/* solves Mx = b, for x but stores result in b */
|
|
269
|
+
/* s contains warm-start (if available) */
|
|
270
|
+
/*
|
|
271
|
+
* [x] = [rho_x I + P A' ]^{-1} [rx]
|
|
272
|
+
* [y] [ A -R_y ] [ry]
|
|
273
|
+
*
|
|
274
|
+
* R_y = diag(rho_y_vec)
|
|
275
|
+
*
|
|
276
|
+
* becomes:
|
|
277
|
+
*
|
|
278
|
+
* x = (rho_x I + P + A' R_y^{-1} A)^{-1} (rx + A' R_y^{-1} ry)
|
|
279
|
+
* y = R_y^{-1} (Ax - ry)
|
|
280
|
+
*
|
|
281
|
+
*/
|
|
282
|
+
scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
|
|
283
|
+
scs_float tol) {
|
|
284
|
+
scs_int cg_its, max_iters;
|
|
285
|
+
|
|
286
|
+
if (tol <= 0.) {
|
|
287
|
+
scs_printf("Warning: tol = %4f <= 0, likely compiled without setting "
|
|
288
|
+
"INDIRECT flag.\n",
|
|
289
|
+
tol);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (CG_NORM(b, p->n + p->m) <= 1e-12) {
|
|
293
|
+
memset(b, 0, (p->n + p->m) * sizeof(scs_float));
|
|
294
|
+
return 0;
|
|
239
295
|
}
|
|
240
296
|
|
|
241
|
-
p->
|
|
242
|
-
|
|
243
|
-
|
|
297
|
+
/* use p->tmp here, and in mat_vec, can do both since they don't overlap */
|
|
298
|
+
/* b = [rx; ry] */
|
|
299
|
+
/* tmp = ry */
|
|
300
|
+
memcpy(p->tmp, &(b[p->n]), p->m * sizeof(scs_float));
|
|
301
|
+
/* tmp = R_y^{-1} * ry */
|
|
302
|
+
scale_by_diag_r(p->tmp, p);
|
|
303
|
+
/* b[:n] = rx + A' R_y^{-1} ry */
|
|
304
|
+
SCS(accum_by_atrans)(p->A, p->tmp, b);
|
|
305
|
+
/* set max_iters to 10 * n (though in theory n is enough for any tol) */
|
|
306
|
+
max_iters = 10 * p->n;
|
|
307
|
+
/* solves (rho_x I + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
|
|
308
|
+
* b */
|
|
309
|
+
cg_its = pcg(p, s, b, max_iters, tol); /* b[:n] = x */
|
|
310
|
+
|
|
311
|
+
/* b[n:] = -ry */
|
|
312
|
+
SCS(scale_array)(&(b[p->n]), -1., p->m);
|
|
313
|
+
/* b[n:] = Ax - ry */
|
|
314
|
+
accum_by_a(p, b, &(b[p->n]));
|
|
315
|
+
/* b[n:] = R_y^{-1} (Ax - ry) = y */
|
|
316
|
+
scale_by_diag_r(&(b[p->n]), p);
|
|
317
|
+
p->tot_cg_its += cg_its;
|
|
318
|
+
#if VERBOSITY > 1
|
|
319
|
+
scs_printf("tol %.3e\n", tol);
|
|
320
|
+
scs_printf("cg_its %i\n", (int)cg_its);
|
|
244
321
|
#endif
|
|
245
322
|
return 0;
|
|
246
323
|
}
|
|
247
|
-
|
|
248
|
-
void SCS(normalize_a)(ScsMatrix *A, const ScsSettings *stgs, const ScsCone *k,
|
|
249
|
-
ScsScaling *scal) {
|
|
250
|
-
SCS(_normalize_a)(A, stgs, k, scal);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
void SCS(un_normalize_a)(ScsMatrix *A, const ScsSettings *stgs,
|
|
254
|
-
const ScsScaling *scal) {
|
|
255
|
-
SCS(_un_normalize_a)(A, stgs, scal);
|
|
256
|
-
}
|
|
@@ -5,24 +5,28 @@
|
|
|
5
5
|
extern "C" {
|
|
6
6
|
#endif
|
|
7
7
|
|
|
8
|
-
#include <math.h>
|
|
9
|
-
#include "amatrix.h"
|
|
10
8
|
#include "glbopts.h"
|
|
11
9
|
#include "linalg.h"
|
|
12
10
|
#include "scs.h"
|
|
11
|
+
#include "scs_matrix.h"
|
|
12
|
+
#include <math.h>
|
|
13
13
|
|
|
14
14
|
struct SCS_LIN_SYS_WORK {
|
|
15
|
+
scs_int n, m; /* linear system dimensions */
|
|
15
16
|
scs_float *p; /* cg iterate */
|
|
16
17
|
scs_float *r; /* cg residual */
|
|
17
18
|
scs_float *Gp;
|
|
18
19
|
scs_float *tmp;
|
|
19
|
-
ScsMatrix *
|
|
20
|
+
const ScsMatrix *A; /* does *not* own this memory */
|
|
21
|
+
const ScsMatrix *P; /* does *not* own this memory */
|
|
22
|
+
ScsMatrix *At; /* does own this memory */
|
|
20
23
|
/* preconditioning */
|
|
21
24
|
scs_float *z;
|
|
22
25
|
scs_float *M;
|
|
23
26
|
/* reporting */
|
|
24
27
|
scs_int tot_cg_its;
|
|
25
|
-
scs_float
|
|
28
|
+
scs_float *rho_y_vec;
|
|
29
|
+
scs_float rho_x;
|
|
26
30
|
};
|
|
27
31
|
|
|
28
32
|
#ifdef __cplusplus
|
|
Binary file
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* Routines modified from CSparse, T. Davis et al */
|
|
2
|
+
|
|
3
|
+
#include "csparse.h"
|
|
4
|
+
|
|
5
|
+
csc *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values,
|
|
6
|
+
scs_int triplet) {
|
|
7
|
+
csc *A = (csc *)scs_calloc(1, sizeof(csc)); /* allocate the csc struct */
|
|
8
|
+
if (!A) {
|
|
9
|
+
return SCS_NULL;
|
|
10
|
+
} /* out of memory */
|
|
11
|
+
A->m = m; /* define dimensions and nzmax */
|
|
12
|
+
A->n = n;
|
|
13
|
+
A->nzmax = nzmax = MAX(nzmax, 1);
|
|
14
|
+
A->nz = triplet ? 0 : -1; /* allocate triplet or comp.col */
|
|
15
|
+
A->p = (scs_int *)scs_malloc((triplet ? nzmax : n + 1) * sizeof(scs_int));
|
|
16
|
+
A->i = (scs_int *)scs_malloc(nzmax * sizeof(scs_int));
|
|
17
|
+
A->x = values ? (scs_float *)scs_malloc(nzmax * sizeof(scs_float)) : SCS_NULL;
|
|
18
|
+
return (!A->p || !A->i || (values && !A->x)) ? SCS(cs_spfree)(A) : A;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
csc *SCS(cs_done)(csc *C, void *w, void *x, scs_int ok) {
|
|
22
|
+
scs_free(w); /* free workspace */
|
|
23
|
+
scs_free(x);
|
|
24
|
+
return ok ? C : SCS(cs_spfree)(C); /* return result if OK, else free it */
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* C = compressed-column form of a triplet matrix T */
|
|
28
|
+
csc *SCS(cs_compress)(const csc *T, scs_int *idx_mapping) {
|
|
29
|
+
scs_int m, n, nz, p, k, *Cp, *Ci, *w, *Ti, *Tj;
|
|
30
|
+
scs_float *Cx, *Tx;
|
|
31
|
+
csc *C;
|
|
32
|
+
m = T->m;
|
|
33
|
+
n = T->n;
|
|
34
|
+
Ti = T->i;
|
|
35
|
+
Tj = T->p;
|
|
36
|
+
Tx = T->x;
|
|
37
|
+
nz = T->nz;
|
|
38
|
+
C = SCS(cs_spalloc)(m, n, nz, Tx != SCS_NULL, 0); /* allocate result */
|
|
39
|
+
w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */
|
|
40
|
+
if (!C || !w) {
|
|
41
|
+
return SCS(cs_done)(C, w, SCS_NULL, 0);
|
|
42
|
+
} /* out of memory */
|
|
43
|
+
Cp = C->p;
|
|
44
|
+
Ci = C->i;
|
|
45
|
+
Cx = C->x;
|
|
46
|
+
for (k = 0; k < nz; k++) {
|
|
47
|
+
w[Tj[k]]++; /* column counts */
|
|
48
|
+
}
|
|
49
|
+
SCS(cumsum)(Cp, w, n); /* column pointers */
|
|
50
|
+
for (k = 0; k < nz; k++) {
|
|
51
|
+
Ci[p = w[Tj[k]]++] = Ti[k]; /* A(i,j) is the pth entry in C */
|
|
52
|
+
if (idx_mapping) {
|
|
53
|
+
idx_mapping[k] = p;
|
|
54
|
+
} /* old to new indices */
|
|
55
|
+
if (Cx) {
|
|
56
|
+
Cx[p] = Tx[k];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return SCS(cs_done)(C, w, SCS_NULL, 1); /* success; free w and return C */
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n) {
|
|
63
|
+
scs_int i, nz = 0;
|
|
64
|
+
scs_float nz2 = 0;
|
|
65
|
+
if (!p || !c) {
|
|
66
|
+
return (-1);
|
|
67
|
+
} /* check inputs */
|
|
68
|
+
for (i = 0; i < n; i++) {
|
|
69
|
+
p[i] = nz;
|
|
70
|
+
nz += c[i];
|
|
71
|
+
nz2 += c[i]; /* also in scs_float to avoid scs_int overflow */
|
|
72
|
+
c[i] = p[i]; /* also copy p[0..n-1] back into c[0..n-1]*/
|
|
73
|
+
}
|
|
74
|
+
p[n] = nz;
|
|
75
|
+
return nz2; /* return sum (c [0..n-1]) */
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
csc *SCS(cs_spfree)(csc *A) {
|
|
79
|
+
if (!A) {
|
|
80
|
+
return SCS_NULL;
|
|
81
|
+
} /* do nothing if A already SCS_NULL */
|
|
82
|
+
scs_free(A->p);
|
|
83
|
+
scs_free(A->i);
|
|
84
|
+
scs_free(A->x);
|
|
85
|
+
scs_free(A);
|
|
86
|
+
return (csc *)SCS_NULL; /* free the csc struct and return SCS_NULL */
|
|
87
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Routines modified from CSparse, T. Davis et al */
|
|
2
|
+
|
|
3
|
+
#ifndef CS_H_GUARD
|
|
4
|
+
#define CS_H_GUARD
|
|
5
|
+
|
|
6
|
+
#ifdef __cplusplus
|
|
7
|
+
extern "C" {
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
#include "glbopts.h"
|
|
11
|
+
#include "scs.h"
|
|
12
|
+
|
|
13
|
+
/* matrix in compressed-column or triplet form */
|
|
14
|
+
typedef struct SPARSE_MATRIX {
|
|
15
|
+
scs_int nzmax; /* maximum number of entries */
|
|
16
|
+
scs_int m; /* number of rows */
|
|
17
|
+
scs_int n; /* number of columns */
|
|
18
|
+
scs_int *p; /* column pointers (size n+1) or col indices (size nzmax) */
|
|
19
|
+
scs_int *i; /* row indices, size nzmax */
|
|
20
|
+
scs_float *x; /* numerical values, size nzmax */
|
|
21
|
+
scs_int nz; /* # of entries in triplet matrix, -1 for compressed-col */
|
|
22
|
+
} csc;
|
|
23
|
+
|
|
24
|
+
csc *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values,
|
|
25
|
+
scs_int triplet);
|
|
26
|
+
csc *SCS(cs_done)(csc *C, void *w, void *x, scs_int ok);
|
|
27
|
+
csc *SCS(cs_compress)(const csc *T, scs_int *idx_mapping);
|
|
28
|
+
scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n);
|
|
29
|
+
csc *SCS(cs_spfree)(csc *A);
|
|
30
|
+
|
|
31
|
+
#ifdef __cplusplus
|
|
32
|
+
}
|
|
33
|
+
#endif
|
|
34
|
+
#endif
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|