scs 0.2.2 → 0.3.2
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 +16 -0
- data/LICENSE.txt +18 -18
- data/README.md +19 -14
- data/lib/scs/ffi.rb +31 -20
- 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 +320 -0
- data/vendor/scs/Makefile +32 -23
- data/vendor/scs/README.md +9 -218
- data/vendor/scs/include/aa.h +67 -23
- data/vendor/scs/include/cones.h +22 -19
- data/vendor/scs/include/glbopts.h +107 -79
- data/vendor/scs/include/linalg.h +3 -4
- data/vendor/scs/include/linsys.h +58 -44
- data/vendor/scs/include/normalize.h +6 -5
- data/vendor/scs/include/rw.h +8 -2
- data/vendor/scs/include/scs.h +257 -141
- data/vendor/scs/include/scs_types.h +34 -0
- data/vendor/scs/include/scs_work.h +83 -0
- data/vendor/scs/include/util.h +3 -15
- data/vendor/scs/linsys/cpu/direct/private.c +241 -232
- data/vendor/scs/linsys/cpu/direct/private.h +13 -7
- data/vendor/scs/linsys/cpu/indirect/private.c +194 -118
- data/vendor/scs/linsys/cpu/indirect/private.h +7 -4
- data/vendor/scs/linsys/csparse.c +87 -0
- data/vendor/scs/linsys/csparse.h +34 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
- data/vendor/scs/linsys/external/amd/amd_internal.h +1 -1
- data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
- 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_types.h +11 -3
- data/vendor/scs/linsys/gpu/gpu.c +58 -21
- data/vendor/scs/linsys/gpu/gpu.h +70 -35
- data/vendor/scs/linsys/gpu/indirect/private.c +394 -157
- data/vendor/scs/linsys/gpu/indirect/private.h +27 -12
- data/vendor/scs/linsys/scs_matrix.c +478 -0
- data/vendor/scs/linsys/scs_matrix.h +70 -0
- data/vendor/scs/scs.mk +14 -10
- data/vendor/scs/src/aa.c +394 -110
- data/vendor/scs/src/cones.c +497 -359
- data/vendor/scs/src/ctrlc.c +15 -5
- data/vendor/scs/src/linalg.c +107 -26
- data/vendor/scs/src/normalize.c +30 -72
- data/vendor/scs/src/rw.c +202 -27
- data/vendor/scs/src/scs.c +769 -571
- data/vendor/scs/src/scs_version.c +11 -3
- data/vendor/scs/src/util.c +37 -106
- data/vendor/scs/test/minunit.h +22 -8
- data/vendor/scs/test/problem_utils.h +180 -25
- 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 +14 -13
- data/vendor/scs/test/problems/small_qp.h +352 -0
- data/vendor/scs/test/problems/test_validation.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 +20 -11
- data/vendor/scs/test/run_tests.c +35 -2
- metadata +29 -98
- 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/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.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/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_version.o +0 -0
- data/vendor/scs/src/util.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,57 @@
|
|
|
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
|
-
/*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
scs_int i;
|
|
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 ) ) */
|
|
22
|
+
static void set_preconditioner(ScsLinSysWork *p) {
|
|
23
|
+
scs_int i, k;
|
|
28
24
|
scs_float *M = p->M;
|
|
25
|
+
const ScsMatrix *A = p->A;
|
|
26
|
+
const ScsMatrix *P = p->P;
|
|
29
27
|
|
|
30
|
-
#if
|
|
28
|
+
#if VERBOSITY > 0
|
|
31
29
|
scs_printf("getting pre-conditioner\n");
|
|
32
30
|
#endif
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
/* M_ii = (R_x)_i + P_ii + a_i' (R_y)^-1 a_i */
|
|
33
|
+
for (i = 0; i < A->n; ++i) { /* cols */
|
|
34
|
+
/* M_ii = (R_x)_i */
|
|
35
|
+
M[i] = p->diag_r[i];
|
|
36
|
+
/* M_ii += a_i' (R_y)^-1 a_i */
|
|
37
|
+
for (k = A->p[i]; k < A->p[i + 1]; ++k) {
|
|
38
|
+
/* A->i[k] is row of entry k with value A->x[k] */
|
|
39
|
+
M[i] += A->x[k] * A->x[k] / p->diag_r[A->n + A->i[k]];
|
|
40
|
+
}
|
|
41
|
+
if (P) {
|
|
42
|
+
for (k = P->p[i]; k < P->p[i + 1]; k++) {
|
|
43
|
+
/* diagonal element only */
|
|
44
|
+
if (P->i[k] == i) { /* row == col */
|
|
45
|
+
/* M_ii += P_ii */
|
|
46
|
+
M[i] += P->x[k];
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/* finally invert for pre-conditioner */
|
|
52
|
+
M[i] = 1. / M[i];
|
|
38
53
|
}
|
|
39
|
-
|
|
40
|
-
#if EXTRA_VERBOSE > 0
|
|
54
|
+
#if VERBOSITY > 0
|
|
41
55
|
scs_printf("finished getting pre-conditioner\n");
|
|
42
56
|
#endif
|
|
43
57
|
}
|
|
@@ -54,15 +68,16 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
|
|
|
54
68
|
scs_float *Ax = A->x;
|
|
55
69
|
|
|
56
70
|
scs_int i, j, q, *z, c1, c2;
|
|
57
|
-
#if
|
|
71
|
+
#if VERBOSITY > 0
|
|
58
72
|
SCS(timer) transpose_timer;
|
|
59
73
|
scs_printf("transposing A\n");
|
|
60
74
|
SCS(tic)(&transpose_timer);
|
|
61
75
|
#endif
|
|
62
76
|
|
|
63
77
|
z = (scs_int *)scs_calloc(m, sizeof(scs_int));
|
|
64
|
-
for (i = 0; i < Ap[n]; i++)
|
|
65
|
-
|
|
78
|
+
for (i = 0; i < Ap[n]; i++)
|
|
79
|
+
z[Ai[i]]++; /* row counts */
|
|
80
|
+
SCS(cumsum)(Cp, z, m); /* row pointers */
|
|
66
81
|
|
|
67
82
|
for (j = 0; j < n; j++) {
|
|
68
83
|
c1 = Ap[j];
|
|
@@ -76,7 +91,7 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
|
|
|
76
91
|
}
|
|
77
92
|
scs_free(z);
|
|
78
93
|
|
|
79
|
-
#if
|
|
94
|
+
#if VERBOSITY > 0
|
|
80
95
|
scs_printf("finished transposing A, time: %1.2es\n",
|
|
81
96
|
SCS(tocq)(&transpose_timer) / 1e3);
|
|
82
97
|
#endif
|
|
@@ -100,60 +115,86 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
|
|
|
100
115
|
}
|
|
101
116
|
}
|
|
102
117
|
|
|
103
|
-
/*
|
|
104
|
-
static void
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
/* vec -> R_y^{-1} vec */
|
|
119
|
+
static void scale_by_r_y_inv(scs_float *vec, ScsLinSysWork *p) {
|
|
120
|
+
scs_int i;
|
|
121
|
+
for (i = 0; i < p->m; ++i) {
|
|
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];
|
|
131
|
+
}
|
|
112
132
|
}
|
|
113
133
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
SCS(
|
|
134
|
+
/* we use a different accum_by_a here for speed */
|
|
135
|
+
static void accum_by_a(ScsLinSysWork *p, const scs_float *x, scs_float *y) {
|
|
136
|
+
SCS(accum_by_atrans)(p->At, x, y);
|
|
117
137
|
}
|
|
118
138
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
/* y = (R_x + P + A' R_y^{-1} A) x */
|
|
140
|
+
static void mat_vec(const ScsMatrix *A, const ScsMatrix *P, ScsLinSysWork *p,
|
|
141
|
+
const scs_float *x, scs_float *y) {
|
|
142
|
+
scs_float *z = p->tmp;
|
|
143
|
+
memset(z, 0, A->m * sizeof(scs_float)); /* z = 0 */
|
|
144
|
+
memset(y, 0, A->n * sizeof(scs_float)); /* y = 0 */
|
|
145
|
+
if (P) {
|
|
146
|
+
SCS(accum_by_p)(P, x, y); /* y = Px */
|
|
147
|
+
}
|
|
148
|
+
accum_by_a(p, x, z); /* z = Ax */
|
|
149
|
+
scale_by_r_y_inv(z, p); /* z = R_y^{-1} A x */
|
|
150
|
+
SCS(accum_by_atrans)(A, z, y); /* y += A'z, y = Px + A' R_y^{-1} Ax */
|
|
151
|
+
/* y = R_x * x + Px + A' R_y^{-1} A * x */
|
|
152
|
+
accum_by_r_x(y, x, p);
|
|
122
153
|
}
|
|
123
154
|
|
|
124
|
-
static void apply_pre_conditioner(scs_float *
|
|
125
|
-
|
|
155
|
+
static void apply_pre_conditioner(scs_float *z, scs_float *r, scs_int n,
|
|
156
|
+
ScsLinSysWork *pr) {
|
|
126
157
|
scs_int i;
|
|
127
|
-
*
|
|
158
|
+
scs_float *M = pr->M;
|
|
128
159
|
for (i = 0; i < n; ++i) {
|
|
129
160
|
z[i] = r[i] * M[i];
|
|
130
|
-
*ipzr += z[i] * r[i];
|
|
131
161
|
}
|
|
132
162
|
}
|
|
133
163
|
|
|
134
|
-
|
|
135
|
-
|
|
164
|
+
/* no need to update anything in this case */
|
|
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 */
|
|
167
|
+
set_preconditioner(p);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
|
|
171
|
+
const scs_float *diag_r) {
|
|
136
172
|
ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
|
|
137
|
-
p->
|
|
138
|
-
p->
|
|
139
|
-
p->
|
|
140
|
-
p->
|
|
173
|
+
p->A = A;
|
|
174
|
+
p->P = P;
|
|
175
|
+
p->m = A->m;
|
|
176
|
+
p->n = A->n;
|
|
177
|
+
|
|
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));
|
|
141
182
|
|
|
142
183
|
/* memory for A transpose */
|
|
143
|
-
p->At = (ScsMatrix *)
|
|
184
|
+
p->At = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
144
185
|
p->At->m = A->n;
|
|
145
186
|
p->At->n = A->m;
|
|
146
|
-
p->At->i = (scs_int *)
|
|
147
|
-
p->At->p = (scs_int *)
|
|
148
|
-
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));
|
|
149
190
|
transpose(A, p);
|
|
150
191
|
|
|
151
192
|
/* preconditioner memory */
|
|
152
|
-
p->
|
|
153
|
-
p->
|
|
154
|
-
|
|
193
|
+
p->diag_r = diag_r;
|
|
194
|
+
p->z = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
|
195
|
+
p->M = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
|
|
196
|
+
set_preconditioner(p);
|
|
155
197
|
|
|
156
|
-
p->total_solve_time = 0;
|
|
157
198
|
p->tot_cg_its = 0;
|
|
158
199
|
if (!p->p || !p->r || !p->Gp || !p->tmp || !p->At || !p->At->i || !p->At->p ||
|
|
159
200
|
!p->At->x) {
|
|
@@ -163,94 +204,129 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
|
|
|
163
204
|
return p;
|
|
164
205
|
}
|
|
165
206
|
|
|
166
|
-
/* solves (I+A'A)x = b, s warm start, solution
|
|
167
|
-
static scs_int pcg(
|
|
168
|
-
ScsLinSysWork *pr, const scs_float *s, scs_float *b,
|
|
207
|
+
/* solves (R_x * I + P + A' R_y^{-1} A)x = b, s warm start, solution in b */
|
|
208
|
+
static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *b,
|
|
169
209
|
scs_int max_its, scs_float tol) {
|
|
170
|
-
scs_int i, n =
|
|
171
|
-
scs_float
|
|
210
|
+
scs_int i, n = pr->n;
|
|
211
|
+
scs_float ztr, ztr_prev, alpha;
|
|
172
212
|
scs_float *p = pr->p; /* cg direction */
|
|
173
213
|
scs_float *Gp = pr->Gp; /* updated CG direction */
|
|
174
214
|
scs_float *r = pr->r; /* cg residual */
|
|
175
215
|
scs_float *z = pr->z; /* for preconditioning */
|
|
176
|
-
scs_float *M = pr->M; /* inverse diagonal preconditioner */
|
|
177
216
|
|
|
178
|
-
|
|
217
|
+
const ScsMatrix *A = pr->A;
|
|
218
|
+
const ScsMatrix *P = pr->P;
|
|
219
|
+
|
|
220
|
+
if (!s) {
|
|
221
|
+
/* take s = 0 */
|
|
222
|
+
/* r = b */
|
|
179
223
|
memcpy(r, b, n * sizeof(scs_float));
|
|
224
|
+
/* b = 0 */
|
|
180
225
|
memset(b, 0, n * sizeof(scs_float));
|
|
181
226
|
} else {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
227
|
+
/* r = Mat * s */
|
|
228
|
+
mat_vec(A, P, pr, s, r);
|
|
229
|
+
/* r = Mat * s - b */
|
|
230
|
+
SCS(add_scaled_array)(r, b, n, -1.);
|
|
231
|
+
/* r = b - Mat * s */
|
|
232
|
+
SCS(scale_array)(r, -1., n);
|
|
233
|
+
/* b = s */
|
|
185
234
|
memcpy(b, s, n * sizeof(scs_float));
|
|
186
235
|
}
|
|
187
236
|
|
|
188
237
|
/* check to see if we need to run CG at all */
|
|
189
|
-
if (
|
|
238
|
+
if (CG_NORM(r, n) < MAX(tol, 1e-12)) {
|
|
190
239
|
return 0;
|
|
191
240
|
}
|
|
192
241
|
|
|
193
|
-
|
|
242
|
+
/* z = M r (M is inverse preconditioner) */
|
|
243
|
+
apply_pre_conditioner(z, r, n, pr);
|
|
244
|
+
/* ztr = z'r */
|
|
245
|
+
ztr = SCS(dot)(z, r, n);
|
|
246
|
+
/* p = z */
|
|
194
247
|
memcpy(p, z, n * sizeof(scs_float));
|
|
195
248
|
|
|
196
249
|
for (i = 0; i < max_its; ++i) {
|
|
197
|
-
|
|
198
|
-
|
|
250
|
+
/* Gp = Mat * p */
|
|
251
|
+
mat_vec(A, P, pr, p, Gp);
|
|
252
|
+
/* alpha = z'r / p'G p */
|
|
253
|
+
alpha = ztr / SCS(dot)(p, Gp, n);
|
|
254
|
+
/* b += alpha * p */
|
|
199
255
|
SCS(add_scaled_array)(b, p, n, alpha);
|
|
256
|
+
/* r -= alpha * G p */
|
|
200
257
|
SCS(add_scaled_array)(r, Gp, n, -alpha);
|
|
201
258
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
(long)i + 1);
|
|
259
|
+
#if VERBOSITY > 3
|
|
260
|
+
scs_printf("tol: %.4e, resid: %.4e, iters: %li\n", tol, CG_NORM(r, n),
|
|
261
|
+
(long)i + 1);
|
|
206
262
|
#endif
|
|
263
|
+
if (CG_NORM(r, n) < tol) {
|
|
207
264
|
return i + 1;
|
|
208
265
|
}
|
|
209
|
-
|
|
210
|
-
apply_pre_conditioner(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
SCS(
|
|
266
|
+
/* z = M r (M is inverse preconditioner) */
|
|
267
|
+
apply_pre_conditioner(z, r, n, pr);
|
|
268
|
+
ztr_prev = ztr;
|
|
269
|
+
/* ztr = z'r */
|
|
270
|
+
ztr = SCS(dot)(z, r, n);
|
|
271
|
+
/* p = beta * p, where beta = ztr / ztr_prev */
|
|
272
|
+
SCS(scale_array)(p, ztr / ztr_prev, n);
|
|
273
|
+
/* p = z + beta * p */
|
|
274
|
+
SCS(add_scaled_array)(p, z, n, 1.);
|
|
214
275
|
}
|
|
215
276
|
return i;
|
|
216
277
|
}
|
|
217
278
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
p->tot_cg_its += cg_its;
|
|
279
|
+
/* solves Mx = b, for x but stores result in b */
|
|
280
|
+
/* s contains warm-start (if available) */
|
|
281
|
+
/*
|
|
282
|
+
* [x] = [R_x + P A' ]^{-1} [rx]
|
|
283
|
+
* [y] [ A -R_y ] [ry]
|
|
284
|
+
*
|
|
285
|
+
* becomes:
|
|
286
|
+
*
|
|
287
|
+
* x = (R_x + P + A' R_y^{-1} A)^{-1} (rx + A' R_y^{-1} ry)
|
|
288
|
+
* y = R_y^{-1} (Ax - ry)
|
|
289
|
+
*
|
|
290
|
+
*/
|
|
291
|
+
scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
|
|
292
|
+
scs_float tol) {
|
|
293
|
+
scs_int cg_its, max_iters;
|
|
294
|
+
|
|
295
|
+
if (tol <= 0.) {
|
|
296
|
+
scs_printf("Warning: tol = %4f <= 0, likely compiled without setting "
|
|
297
|
+
"INDIRECT flag.\n",
|
|
298
|
+
tol);
|
|
239
299
|
}
|
|
240
300
|
|
|
241
|
-
p->
|
|
242
|
-
|
|
243
|
-
|
|
301
|
+
if (CG_NORM(b, p->n + p->m) <= 1e-12) {
|
|
302
|
+
memset(b, 0, (p->n + p->m) * sizeof(scs_float));
|
|
303
|
+
return 0;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* use p->tmp here, and in mat_vec, can do both since they don't overlap */
|
|
307
|
+
/* b = [rx; ry] */
|
|
308
|
+
/* tmp = ry */
|
|
309
|
+
memcpy(p->tmp, &(b[p->n]), p->m * sizeof(scs_float));
|
|
310
|
+
/* tmp = R_y^{-1} * ry */
|
|
311
|
+
scale_by_r_y_inv(p->tmp, p);
|
|
312
|
+
/* b[:n] = rx + A' R_y^{-1} ry */
|
|
313
|
+
SCS(accum_by_atrans)(p->A, p->tmp, b);
|
|
314
|
+
/* set max_iters to 10 * n (though in theory n is enough for any tol) */
|
|
315
|
+
max_iters = 10 * p->n;
|
|
316
|
+
/* solves (R_x + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
|
|
317
|
+
* b */
|
|
318
|
+
cg_its = pcg(p, s, b, max_iters, tol); /* b[:n] = x */
|
|
319
|
+
|
|
320
|
+
/* b[n:] = -ry */
|
|
321
|
+
SCS(scale_array)(&(b[p->n]), -1., p->m);
|
|
322
|
+
/* b[n:] = Ax - ry */
|
|
323
|
+
accum_by_a(p, b, &(b[p->n]));
|
|
324
|
+
/* b[n:] = R_y^{-1} (Ax - ry) = y */
|
|
325
|
+
scale_by_r_y_inv(&(b[p->n]), p);
|
|
326
|
+
p->tot_cg_its += cg_its;
|
|
327
|
+
#if VERBOSITY > 1
|
|
328
|
+
scs_printf("tol %.3e\n", tol);
|
|
329
|
+
scs_printf("cg_its %i\n", (int)cg_its);
|
|
244
330
|
#endif
|
|
245
331
|
return 0;
|
|
246
332
|
}
|
|
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,27 @@
|
|
|
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
|
+
const scs_float *diag_r;
|
|
26
29
|
};
|
|
27
30
|
|
|
28
31
|
#ifdef __cplusplus
|
|
@@ -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_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
|
+
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
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
#ifdef MATLAB_MEX_FILE
|
|
20
20
|
#include "mex.h"
|
|
21
|
-
#include "matrix.h"
|
|
22
21
|
#endif
|
|
23
22
|
|
|
24
23
|
#ifndef NULL
|
|
@@ -51,7 +50,7 @@
|
|
|
51
50
|
|
|
52
51
|
struct SuiteSparse_config_struct SuiteSparse_config =
|
|
53
52
|
{
|
|
54
|
-
|
|
53
|
+
scs_malloc, scs_calloc, scs_realloc, scs_free, _scs_printf,
|
|
55
54
|
SuiteSparse_hypot,
|
|
56
55
|
SuiteSparse_divcomplex
|
|
57
56
|
|
|
@@ -73,12 +72,13 @@ struct SuiteSparse_config_struct SuiteSparse_config =
|
|
|
73
72
|
SuiteSparse_start be called prior to calling any SuiteSparse function.
|
|
74
73
|
*/
|
|
75
74
|
|
|
75
|
+
|
|
76
76
|
void SuiteSparse_start ( void )
|
|
77
77
|
{
|
|
78
|
-
SuiteSparse_config.malloc_func =
|
|
79
|
-
SuiteSparse_config.calloc_func =
|
|
80
|
-
SuiteSparse_config.realloc_func =
|
|
81
|
-
SuiteSparse_config.free_func =
|
|
78
|
+
SuiteSparse_config.malloc_func = scs_malloc ;
|
|
79
|
+
SuiteSparse_config.calloc_func = scs_calloc ;
|
|
80
|
+
SuiteSparse_config.realloc_func = scs_realloc ;
|
|
81
|
+
SuiteSparse_config.free_func = scs_free ;
|
|
82
82
|
SuiteSparse_config.printf_func = _scs_printf ;
|
|
83
83
|
/* math functions */
|
|
84
84
|
SuiteSparse_config.hypot_func = SuiteSparse_hypot ;
|
|
@@ -44,7 +44,7 @@ extern "C" {
|
|
|
44
44
|
|
|
45
45
|
#include <limits.h>
|
|
46
46
|
#include <stdlib.h>
|
|
47
|
-
#include "
|
|
47
|
+
#include "glbopts.h"
|
|
48
48
|
#include "ctrlc.h"
|
|
49
49
|
|
|
50
50
|
/* ========================================================================== */
|
|
@@ -71,6 +71,11 @@ extern "C" {
|
|
|
71
71
|
#define SuiteSparse_long_id "%" SuiteSparse_long_idd
|
|
72
72
|
#endif
|
|
73
73
|
|
|
74
|
+
#ifndef _scs_printf
|
|
75
|
+
#define _scs_printf scs_printf
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
|
|
74
79
|
/* ========================================================================== */
|
|
75
80
|
/* === SuiteSparse_config parameters and functions ========================== */
|
|
76
81
|
/* ========================================================================== */
|
|
@@ -89,8 +89,8 @@ GLOBAL Int AMD_order
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/* allocate two size-n integer workspaces */
|
|
92
|
-
Len = SuiteSparse_malloc (n, sizeof (Int)) ;
|
|
93
|
-
Pinv = SuiteSparse_malloc (n, sizeof (Int)) ;
|
|
92
|
+
Len = (Int *)SuiteSparse_malloc (n, sizeof (Int)) ;
|
|
93
|
+
Pinv = (Int *)SuiteSparse_malloc (n, sizeof (Int)) ;
|
|
94
94
|
mem += n ;
|
|
95
95
|
mem += n ;
|
|
96
96
|
if (!Len || !Pinv)
|
|
@@ -106,8 +106,8 @@ GLOBAL Int AMD_order
|
|
|
106
106
|
{
|
|
107
107
|
/* sort the input matrix and remove duplicate entries */
|
|
108
108
|
AMD_DEBUG1 (("Matrix is jumbled\n")) ;
|
|
109
|
-
Rp = SuiteSparse_malloc (n+1, sizeof (Int)) ;
|
|
110
|
-
Ri = SuiteSparse_malloc (nz, sizeof (Int)) ;
|
|
109
|
+
Rp = (Int *)SuiteSparse_malloc (n+1, sizeof (Int)) ;
|
|
110
|
+
Ri = (Int *)SuiteSparse_malloc (nz, sizeof (Int)) ;
|
|
111
111
|
mem += (n+1) ;
|
|
112
112
|
mem += MAX (nz,1) ;
|
|
113
113
|
if (!Rp || !Ri)
|
|
@@ -160,7 +160,7 @@ GLOBAL Int AMD_order
|
|
|
160
160
|
ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
|
|
161
161
|
if (ok)
|
|
162
162
|
{
|
|
163
|
-
S = SuiteSparse_malloc (slen, sizeof (Int)) ;
|
|
163
|
+
S = (Int *)SuiteSparse_malloc (slen, sizeof (Int)) ;
|
|
164
164
|
}
|
|
165
165
|
AMD_DEBUG1 (("slen %g\n", (scs_float) slen)) ;
|
|
166
166
|
if (!S)
|