scs 0.4.0 → 0.4.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 +8 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/scs/ffi.rb +2 -2
- data/lib/scs/version.rb +1 -1
- data/lib/scs.rb +3 -3
- data/vendor/scs/CITATION.cff +2 -2
- data/vendor/scs/CMakeLists.txt +305 -171
- data/vendor/scs/Makefile +44 -19
- data/vendor/scs/README.md +1 -1
- data/vendor/scs/include/glbopts.h +34 -14
- data/vendor/scs/include/linsys.h +8 -8
- data/vendor/scs/include/scs.h +6 -2
- data/vendor/scs/include/scs_blas.h +4 -0
- data/vendor/scs/include/scs_types.h +3 -1
- data/vendor/scs/include/scs_work.h +9 -8
- data/vendor/scs/include/util.h +1 -1
- data/vendor/scs/linsys/cpu/direct/private.c +32 -153
- data/vendor/scs/linsys/cpu/direct/private.h +6 -6
- data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
- data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
- data/vendor/scs/linsys/csparse.c +140 -12
- data/vendor/scs/linsys/csparse.h +10 -17
- data/vendor/scs/linsys/gpu/gpu.c +4 -4
- data/vendor/scs/linsys/gpu/gpu.h +1 -1
- data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
- data/vendor/scs/linsys/mkl/direct/private.c +182 -0
- data/vendor/scs/linsys/mkl/direct/private.h +38 -0
- data/vendor/scs/linsys/scs_matrix.c +11 -5
- data/vendor/scs/scs.mk +40 -27
- data/vendor/scs/src/cones.c +17 -161
- data/vendor/scs/src/exp_cone.c +399 -0
- data/vendor/scs/src/linalg.c +17 -3
- data/vendor/scs/src/normalize.c +4 -2
- data/vendor/scs/src/rw.c +107 -38
- data/vendor/scs/src/scs.c +103 -69
- data/vendor/scs/src/util.c +12 -3
- data/vendor/scs/test/minunit.h +2 -1
- data/vendor/scs/test/problem_utils.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +8 -3
- data/vendor/scs/test/problems/max_ent +0 -0
- data/vendor/scs/test/problems/max_ent.h +8 -0
- data/vendor/scs/test/problems/mpc_bug.h +19 -0
- data/vendor/scs/test/problems/mpc_bug1 +0 -0
- data/vendor/scs/test/problems/mpc_bug2 +0 -0
- data/vendor/scs/test/problems/mpc_bug3 +0 -0
- data/vendor/scs/test/problems/random_prob.h +2 -43
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +7 -2
- data/vendor/scs/test/problems/test_exp_cone.h +84 -0
- data/vendor/scs/test/problems/test_prob_from_data_file.h +73 -0
- data/vendor/scs/test/run_from_file.c +7 -1
- data/vendor/scs/test/run_tests.c +25 -9
- metadata +14 -3
data/vendor/scs/src/rw.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "rw.h"
|
2
2
|
|
3
|
+
#include <errno.h>
|
3
4
|
#include <stdint.h>
|
4
5
|
#include <stdio.h>
|
5
6
|
#include <stdlib.h>
|
@@ -9,6 +10,25 @@
|
|
9
10
|
#include "scs_matrix.h"
|
10
11
|
#include "util.h"
|
11
12
|
|
13
|
+
#if NO_READ_WRITE > 0 /* Disables all read / write functionality */
|
14
|
+
|
15
|
+
void SCS(write_data)(const ScsData *d, const ScsCone *k,
|
16
|
+
const ScsSettings *stgs) {
|
17
|
+
/* Do nothing */
|
18
|
+
}
|
19
|
+
scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
20
|
+
ScsSettings **stgs) {
|
21
|
+
/* Failure */
|
22
|
+
return -1;
|
23
|
+
}
|
24
|
+
void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
25
|
+
const ScsWork *w, scs_int iter,
|
26
|
+
SCS(timer) * solve_timer) {
|
27
|
+
/* Do nothing */
|
28
|
+
}
|
29
|
+
|
30
|
+
#else
|
31
|
+
|
12
32
|
/* writes/reads problem data to/from filename */
|
13
33
|
/* This is a VERY naive implementation, doesn't care about portability etc */
|
14
34
|
|
@@ -28,30 +48,61 @@ static void write_scs_cone(const ScsCone *k, FILE *fout) {
|
|
28
48
|
fwrite(k->p, sizeof(scs_float), k->psize, fout);
|
29
49
|
}
|
30
50
|
|
31
|
-
|
51
|
+
/*
|
52
|
+
* Read integer data from file. If the integer width on file is
|
53
|
+
* different to scs_int then it will cast the ints after reading
|
54
|
+
* to be compatible with the SCS data types.
|
55
|
+
*/
|
56
|
+
static size_t read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
|
57
|
+
FILE *fin) {
|
58
|
+
if (file_int_sz == sizeof(scs_int)) {
|
59
|
+
return fread(dest, sizeof(scs_int), nitems, fin);
|
60
|
+
}
|
61
|
+
void *ptr = scs_calloc(nitems, file_int_sz);
|
62
|
+
size_t val = fread(ptr, file_int_sz, nitems, fin);
|
63
|
+
size_t i;
|
64
|
+
switch (file_int_sz) {
|
65
|
+
case 4:
|
66
|
+
for (i = 0; i < nitems; ++i) {
|
67
|
+
dest[i] = (scs_int)(((int *)ptr)[i]);
|
68
|
+
}
|
69
|
+
break;
|
70
|
+
case 8:
|
71
|
+
for (i = 0; i < nitems; ++i) {
|
72
|
+
dest[i] = (scs_int)(((long long *)ptr)[i]);
|
73
|
+
}
|
74
|
+
break;
|
75
|
+
}
|
76
|
+
if (ptr) {
|
77
|
+
scs_free(ptr);
|
78
|
+
}
|
79
|
+
return val;
|
80
|
+
}
|
81
|
+
|
82
|
+
static ScsCone *read_scs_cone(FILE *fin, size_t file_int_sz) {
|
32
83
|
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
33
|
-
|
34
|
-
|
35
|
-
|
84
|
+
read_int(&(k->z), file_int_sz, 1, fin);
|
85
|
+
read_int(&(k->l), file_int_sz, 1, fin);
|
86
|
+
read_int(&(k->bsize), file_int_sz, 1, fin);
|
36
87
|
if (k->bsize > 1) {
|
37
88
|
k->bl = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
38
89
|
k->bu = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
39
90
|
fread(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
|
40
91
|
fread(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
|
41
92
|
}
|
42
|
-
|
93
|
+
read_int(&(k->qsize), file_int_sz, 1, fin);
|
43
94
|
if (k->qsize) {
|
44
95
|
k->q = (scs_int *)scs_calloc(k->qsize, sizeof(scs_int));
|
45
|
-
|
96
|
+
read_int(k->q, file_int_sz, k->qsize, fin);
|
46
97
|
}
|
47
|
-
|
98
|
+
read_int(&(k->ssize), file_int_sz, 1, fin);
|
48
99
|
if (k->ssize) {
|
49
100
|
k->s = (scs_int *)scs_calloc(k->ssize, sizeof(scs_int));
|
50
|
-
|
101
|
+
read_int(k->s, file_int_sz, k->ssize, fin);
|
51
102
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
103
|
+
read_int(&(k->ep), file_int_sz, 1, fin);
|
104
|
+
read_int(&(k->ed), file_int_sz, 1, fin);
|
105
|
+
read_int(&(k->psize), file_int_sz, 1, fin);
|
55
106
|
if (k->psize) {
|
56
107
|
k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
|
57
108
|
fread(k->p, sizeof(scs_float), k->psize, fin);
|
@@ -79,21 +130,21 @@ static void write_scs_stgs(const ScsSettings *s, FILE *fout) {
|
|
79
130
|
/* Do not write the log_csv_filename */
|
80
131
|
}
|
81
132
|
|
82
|
-
static ScsSettings *read_scs_stgs(FILE *fin) {
|
133
|
+
static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz) {
|
83
134
|
ScsSettings *s = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
84
|
-
|
135
|
+
read_int(&(s->normalize), file_int_sz, 1, fin);
|
85
136
|
fread(&(s->scale), sizeof(scs_float), 1, fin);
|
86
137
|
fread(&(s->rho_x), sizeof(scs_float), 1, fin);
|
87
|
-
|
138
|
+
read_int(&(s->max_iters), file_int_sz, 1, fin);
|
88
139
|
fread(&(s->eps_abs), sizeof(scs_float), 1, fin);
|
89
140
|
fread(&(s->eps_rel), sizeof(scs_float), 1, fin);
|
90
141
|
fread(&(s->eps_infeas), sizeof(scs_float), 1, fin);
|
91
142
|
fread(&(s->alpha), sizeof(scs_float), 1, fin);
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
143
|
+
read_int(&(s->verbose), file_int_sz, 1, fin);
|
144
|
+
read_int(&(s->warm_start), file_int_sz, 1, fin);
|
145
|
+
read_int(&(s->acceleration_lookback), file_int_sz, 1, fin);
|
146
|
+
read_int(&(s->acceleration_interval), file_int_sz, 1, fin);
|
147
|
+
read_int(&(s->adaptive_scale), file_int_sz, 1, fin);
|
97
148
|
return s;
|
98
149
|
}
|
99
150
|
|
@@ -106,18 +157,18 @@ static void write_amatrix(const ScsMatrix *A, FILE *fout) {
|
|
106
157
|
fwrite(A->i, sizeof(scs_int), Anz, fout);
|
107
158
|
}
|
108
159
|
|
109
|
-
static ScsMatrix *read_amatrix(FILE *fin) {
|
160
|
+
static ScsMatrix *read_amatrix(FILE *fin, size_t file_int_sz) {
|
110
161
|
scs_int Anz;
|
111
162
|
ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
112
|
-
|
113
|
-
|
163
|
+
read_int(&(A->m), file_int_sz, 1, fin);
|
164
|
+
read_int(&(A->n), file_int_sz, 1, fin);
|
114
165
|
A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
|
115
|
-
|
166
|
+
read_int(A->p, file_int_sz, A->n + 1, fin);
|
116
167
|
Anz = A->p[A->n];
|
117
168
|
A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
|
118
169
|
A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
|
119
170
|
fread(A->x, sizeof(scs_float), Anz, fin);
|
120
|
-
|
171
|
+
read_int(A->i, file_int_sz, Anz, fin);
|
121
172
|
return A;
|
122
173
|
}
|
123
174
|
|
@@ -135,19 +186,20 @@ static void write_scs_data(const ScsData *d, FILE *fout) {
|
|
135
186
|
}
|
136
187
|
}
|
137
188
|
|
138
|
-
static ScsData *read_scs_data(FILE *fin) {
|
189
|
+
static ScsData *read_scs_data(FILE *fin, size_t file_int_sz) {
|
139
190
|
scs_int has_p = 0;
|
140
191
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
141
|
-
|
142
|
-
|
192
|
+
|
193
|
+
read_int(&(d->m), file_int_sz, 1, fin);
|
194
|
+
read_int(&(d->n), file_int_sz, 1, fin);
|
143
195
|
d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
144
196
|
d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
145
197
|
fread(d->b, sizeof(scs_float), d->m, fin);
|
146
198
|
fread(d->c, sizeof(scs_float), d->n, fin);
|
147
|
-
d->A = read_amatrix(fin);
|
199
|
+
d->A = read_amatrix(fin, file_int_sz);
|
148
200
|
/* If has_p bit is not set or this hits end of file then has_p = 0 */
|
149
|
-
has_p &=
|
150
|
-
d->P = has_p ? read_amatrix(fin) : SCS_NULL;
|
201
|
+
has_p &= read_int(&has_p, file_int_sz, 1, fin);
|
202
|
+
d->P = has_p ? read_amatrix(fin, file_int_sz) : SCS_NULL;
|
151
203
|
return d;
|
152
204
|
}
|
153
205
|
|
@@ -158,7 +210,6 @@ void SCS(write_data)(const ScsData *d, const ScsCone *k,
|
|
158
210
|
uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
|
159
211
|
const char *scs_version = SCS_VERSION;
|
160
212
|
uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
|
161
|
-
scs_printf("writing data to %s\n", stgs->write_data_filename);
|
162
213
|
fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout);
|
163
214
|
fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout);
|
164
215
|
fwrite(&(scs_version_sz), sizeof(uint32_t), 1, fout);
|
@@ -175,9 +226,11 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
175
226
|
uint32_t file_float_sz;
|
176
227
|
uint32_t file_version_sz;
|
177
228
|
char file_version[16];
|
229
|
+
errno = 0;
|
178
230
|
FILE *fin = fopen(filename, "rb");
|
179
231
|
if (!fin) {
|
180
232
|
scs_printf("Error reading file %s\n", filename);
|
233
|
+
scs_printf("errno:%i:%s\n", errno, strerror(errno));
|
181
234
|
return -1;
|
182
235
|
}
|
183
236
|
scs_printf("Reading data from %s\n", filename);
|
@@ -185,11 +238,10 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
185
238
|
fread(&(file_float_sz), sizeof(uint32_t), 1, fin);
|
186
239
|
if (file_int_sz != (uint32_t)sizeof(scs_int)) {
|
187
240
|
scs_printf(
|
188
|
-
"
|
189
|
-
"
|
241
|
+
"Warning, sizeof(file int) is %lu, but scs expects sizeof(int) %lu. "
|
242
|
+
"SCS will attempt to cast the data, which may be slow. "
|
243
|
+
"This message can be avoided by recompiling with the correct flags.\n",
|
190
244
|
(unsigned long)file_int_sz, (unsigned long)sizeof(scs_int));
|
191
|
-
fclose(fin);
|
192
|
-
return -1;
|
193
245
|
}
|
194
246
|
if (file_float_sz != (uint32_t)sizeof(scs_float)) {
|
195
247
|
scs_printf(
|
@@ -209,9 +261,10 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
209
261
|
"************************************************************\n",
|
210
262
|
file_version, SCS_VERSION);
|
211
263
|
}
|
212
|
-
*k = read_scs_cone(fin);
|
213
|
-
*d = read_scs_data(fin);
|
214
|
-
*stgs = read_scs_stgs(fin);
|
264
|
+
*k = read_scs_cone(fin, file_int_sz);
|
265
|
+
*d = read_scs_data(fin, file_int_sz);
|
266
|
+
*stgs = read_scs_stgs(fin, file_int_sz);
|
267
|
+
scs_printf("Finished reading data.\n");
|
215
268
|
fclose(fin);
|
216
269
|
return 0;
|
217
270
|
}
|
@@ -275,8 +328,15 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
|
275
328
|
"tau_normalized,"
|
276
329
|
"kap_normalized,"
|
277
330
|
"ax_nrm_inf,"
|
331
|
+
"ax_s_nrm_inf"
|
278
332
|
"px_nrm_inf,"
|
279
333
|
"aty_nrm_inf,"
|
334
|
+
"xt_p_x,"
|
335
|
+
"xt_p_x_tau,"
|
336
|
+
"ctx,"
|
337
|
+
"ctx_tau,"
|
338
|
+
"bty,"
|
339
|
+
"bty_tau,"
|
280
340
|
"b_nrm_inf,"
|
281
341
|
"c_nrm_inf,"
|
282
342
|
"scale,"
|
@@ -332,8 +392,15 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
|
332
392
|
fprintf(fout, "%.16e,", r_n->tau);
|
333
393
|
fprintf(fout, "%.16e,", r_n->kap);
|
334
394
|
fprintf(fout, "%.16e,", SCS(norm_inf)(r->ax, w->d->m));
|
395
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(r->ax_s, w->d->m));
|
335
396
|
fprintf(fout, "%.16e,", SCS(norm_inf)(r->px, w->d->n));
|
336
397
|
fprintf(fout, "%.16e,", SCS(norm_inf)(r->aty, w->d->n));
|
398
|
+
fprintf(fout, "%.16e,", r->xt_p_x);
|
399
|
+
fprintf(fout, "%.16e,", r->xt_p_x_tau);
|
400
|
+
fprintf(fout, "%.16e,", r->ctx);
|
401
|
+
fprintf(fout, "%.16e,", r->ctx_tau);
|
402
|
+
fprintf(fout, "%.16e,", r->bty);
|
403
|
+
fprintf(fout, "%.16e,", r->bty_tau);
|
337
404
|
fprintf(fout, "%.16e,", SCS(norm_inf)(w->b_orig, w->d->m));
|
338
405
|
fprintf(fout, "%.16e,", SCS(norm_inf)(w->c_orig, w->d->n));
|
339
406
|
fprintf(fout, "%.16e,", w->stgs->scale);
|
@@ -348,3 +415,5 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
|
348
415
|
fprintf(fout, "\n");
|
349
416
|
fclose(fout);
|
350
417
|
}
|
418
|
+
|
419
|
+
#endif
|
data/vendor/scs/src/scs.c
CHANGED
@@ -76,7 +76,7 @@ static void print_init_header(const ScsData *d, const ScsCone *k,
|
|
76
76
|
const ScsSettings *stgs) {
|
77
77
|
scs_int i;
|
78
78
|
char *cone_str = SCS(get_cone_header)(k);
|
79
|
-
const char *lin_sys_method =
|
79
|
+
const char *lin_sys_method = scs_get_lin_sys_method();
|
80
80
|
#ifdef USE_LAPACK
|
81
81
|
scs_int acceleration_lookback = stgs->acceleration_lookback;
|
82
82
|
scs_int acceleration_interval = stgs->acceleration_interval;
|
@@ -112,6 +112,9 @@ static void print_init_header(const ScsData *d, const ScsCone *k,
|
|
112
112
|
if (stgs->time_limit_secs) {
|
113
113
|
scs_printf("\t time_limit_secs: %.2e\n", stgs->time_limit_secs);
|
114
114
|
}
|
115
|
+
#ifdef _OPENMP
|
116
|
+
scs_printf("\t compiled with openmp parallelization enabled\n");
|
117
|
+
#endif
|
115
118
|
if (lin_sys_method) {
|
116
119
|
scs_printf("lin-sys: %s\n\t nnz(A): %li, nnz(P): %li\n", lin_sys_method,
|
117
120
|
(long)d->A->p[d->A->n], d->P ? (long)d->P->p[d->P->n] : 0l);
|
@@ -195,17 +198,24 @@ static void warm_start_vars(ScsWork *w, ScsSolution *sol) {
|
|
195
198
|
}
|
196
199
|
|
197
200
|
static void compute_residuals(ScsResiduals *r, scs_int m, scs_int n) {
|
198
|
-
|
199
|
-
|
201
|
+
scs_float nm_ax_s, nm_px, nm_aty;
|
202
|
+
scs_float nm_ax_s_btau = NORM(r->ax_s_btau, m);
|
203
|
+
scs_float nm_px_aty_ctau = NORM(r->px_aty_ctau, n);
|
204
|
+
|
205
|
+
r->res_pri = SAFEDIV_POS(nm_ax_s_btau, r->tau);
|
206
|
+
r->res_dual = SAFEDIV_POS(nm_px_aty_ctau, r->tau);
|
200
207
|
r->res_unbdd_a = NAN;
|
201
208
|
r->res_unbdd_p = NAN;
|
202
209
|
r->res_infeas = NAN;
|
203
|
-
if (r->ctx_tau <
|
204
|
-
|
205
|
-
|
210
|
+
if (r->ctx_tau < -INFEAS_NEGATIVITY_TOL) {
|
211
|
+
nm_ax_s = NORM(r->ax_s, m);
|
212
|
+
nm_px = NORM(r->px, n);
|
213
|
+
r->res_unbdd_a = SAFEDIV_POS(nm_ax_s, -r->ctx_tau);
|
214
|
+
r->res_unbdd_p = SAFEDIV_POS(nm_px, -r->ctx_tau);
|
206
215
|
}
|
207
|
-
if (r->bty_tau <
|
208
|
-
|
216
|
+
if (r->bty_tau < -INFEAS_NEGATIVITY_TOL) {
|
217
|
+
nm_aty = NORM(r->aty, n);
|
218
|
+
r->res_infeas = SAFEDIV_POS(nm_aty, -r->bty_tau);
|
209
219
|
}
|
210
220
|
}
|
211
221
|
|
@@ -347,14 +357,15 @@ static inline scs_float dot_r(ScsWork *w, const scs_float *x,
|
|
347
357
|
|
348
358
|
static scs_float root_plus(ScsWork *w, scs_float *p, scs_float *mu,
|
349
359
|
scs_float eta) {
|
350
|
-
scs_float a, b, c, tau_scale = w->diag_r[w->d->n + w->d->m];
|
360
|
+
scs_float a, b, c, rad, tau_scale = w->diag_r[w->d->n + w->d->m];
|
351
361
|
a = tau_scale + dot_r(w, w->g, w->g);
|
352
362
|
b = dot_r(w, mu, w->g) - 2 * dot_r(w, p, w->g) - eta * tau_scale;
|
353
363
|
c = dot_r(w, p, p) - dot_r(w, p, mu);
|
354
|
-
|
364
|
+
rad = b * b - 4 * a * c;
|
365
|
+
return (-b + SQRTF(MAX(rad, 0.))) / (2 * a);
|
355
366
|
}
|
356
367
|
|
357
|
-
/* status
|
368
|
+
/* status != 0 indicates failure */
|
358
369
|
static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
359
370
|
scs_int n = w->d->n, m = w->d->m, l = n + m + 1, status, i;
|
360
371
|
scs_float *warm_start = SCS_NULL;
|
@@ -364,22 +375,24 @@ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
|
364
375
|
w->u_t[i] *= (i < n ? 1 : -1) * w->diag_r[i];
|
365
376
|
}
|
366
377
|
#if INDIRECT > 0
|
378
|
+
scs_float nm_ax_s_btau, nm_px_aty_ctau, nm_ws;
|
367
379
|
/* compute warm start using the cone projection output */
|
380
|
+
nm_ax_s_btau = CG_NORM(w->r_normalized->ax_s_btau, m);
|
381
|
+
nm_px_aty_ctau = CG_NORM(w->r_normalized->px_aty_ctau, n);
|
368
382
|
warm_start = w->lin_sys_warm_start;
|
369
|
-
memcpy(warm_start, w->u, (l - 1) * sizeof(scs_float));
|
370
383
|
/* warm_start = u[:n] + tau * g[:n] */
|
371
|
-
|
384
|
+
memcpy(warm_start, w->u, n * sizeof(scs_float));
|
385
|
+
SCS(add_scaled_array)(warm_start, w->g, n, w->u[l - 1]);
|
372
386
|
/* use normalized residuals to compute tolerance */
|
373
|
-
tol = MIN(
|
374
|
-
CG_NORM(w->r_normalized->px_aty_ctau, w->d->n));
|
387
|
+
tol = MIN(nm_ax_s_btau, nm_px_aty_ctau);
|
375
388
|
/* tol ~ O(1/k^(1+eps)) guarantees convergence */
|
376
389
|
/* use warm-start to calculate tolerance rather than w->u_t, since warm_start
|
377
390
|
* should be approximately equal to the true solution */
|
378
|
-
|
379
|
-
|
391
|
+
nm_ws = CG_NORM(warm_start, n) / POWF((scs_float)iter + 1, CG_RATE);
|
392
|
+
tol = CG_TOL_FACTOR * MIN(tol, nm_ws);
|
380
393
|
tol = MAX(CG_BEST_TOL, tol);
|
381
394
|
#endif
|
382
|
-
status =
|
395
|
+
status = scs_solve_lin_sys(w->p, w->u_t, warm_start, tol);
|
383
396
|
if (iter < FEASIBLE_ITERS) {
|
384
397
|
w->u_t[l - 1] = 1.;
|
385
398
|
} else {
|
@@ -514,6 +527,7 @@ static void set_unfinished(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
514
527
|
/* sets solutions, re-scales by inner prods if infeasible or unbounded */
|
515
528
|
static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
516
529
|
scs_int iter) {
|
530
|
+
scs_float nm_s, nm_y, sty;
|
517
531
|
setx(w, sol);
|
518
532
|
sety(w, sol);
|
519
533
|
sets(w, sol);
|
@@ -521,6 +535,11 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
521
535
|
SCS(un_normalize_sol)(w->scal, sol);
|
522
536
|
}
|
523
537
|
populate_residual_struct(w, iter);
|
538
|
+
|
539
|
+
nm_s = SCS(norm_inf)(sol->s, w->d->m);
|
540
|
+
nm_y = SCS(norm_inf)(sol->y, w->d->m);
|
541
|
+
sty = SCS(dot)(sol->s, sol->y, w->d->m);
|
542
|
+
|
524
543
|
info->setup_time = w->setup_time;
|
525
544
|
info->iter = iter;
|
526
545
|
info->res_infeas = w->r_orig->res_infeas;
|
@@ -530,9 +549,8 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
530
549
|
info->scale_updates = w->scale_updates;
|
531
550
|
info->rejected_accel_steps = w->rejected_accel_steps;
|
532
551
|
info->accepted_accel_steps = w->accepted_accel_steps;
|
533
|
-
info->comp_slack = ABS(
|
534
|
-
if (info->comp_slack > 1e-5 * MAX(
|
535
|
-
SCS(norm_inf)(sol->y, w->d->m))) {
|
552
|
+
info->comp_slack = ABS(sty);
|
553
|
+
if (info->comp_slack > 1e-5 * MAX(nm_s, nm_y)) {
|
536
554
|
scs_printf("WARNING - large complementary slackness residual: %f\n",
|
537
555
|
info->comp_slack);
|
538
556
|
}
|
@@ -563,26 +581,28 @@ static void print_summary(ScsWork *w, scs_int i, SCS(timer) * solve_timer) {
|
|
563
581
|
/* report mid point of primal and dual objective values */
|
564
582
|
scs_printf("%*.2e ", (int)HSPACE, 0.5 * (r->pobj + r->dobj));
|
565
583
|
scs_printf("%*.2e ", (int)HSPACE, w->stgs->scale);
|
566
|
-
|
584
|
+
/* Report TOTAL time, including setup */
|
585
|
+
scs_printf("%*.2e ", (int)HSPACE,
|
586
|
+
(SCS(tocq)(solve_timer) + w->setup_time) / 1e3);
|
567
587
|
scs_printf("\n");
|
568
588
|
|
569
589
|
#if VERBOSITY > 0
|
570
|
-
scs_printf("Norm u = %
|
571
|
-
scs_printf("Norm u_t = %
|
572
|
-
scs_printf("Norm v = %
|
573
|
-
scs_printf("Norm rsk = %
|
574
|
-
scs_printf("Norm x = %
|
575
|
-
scs_printf("Norm y = %
|
576
|
-
scs_printf("Norm s = %
|
577
|
-
scs_printf("Norm |Ax + s| = %1.
|
578
|
-
scs_printf("tau = %
|
579
|
-
scs_printf("kappa = %
|
580
|
-
scs_printf("|u - u_t| = %1.
|
590
|
+
scs_printf("Norm u = %1.6e, ", SCS(norm_2)(w->u, w->d->n + w->d->m + 1));
|
591
|
+
scs_printf("Norm u_t = %1.6e, ", SCS(norm_2)(w->u_t, w->d->n + w->d->m + 1));
|
592
|
+
scs_printf("Norm v = %1.6e, ", SCS(norm_2)(w->v, w->d->n + w->d->m + 1));
|
593
|
+
scs_printf("Norm rsk = %1.6e, ", SCS(norm_2)(w->rsk, w->d->n + w->d->m + 1));
|
594
|
+
scs_printf("Norm x = %1.6e, ", SCS(norm_2)(w->xys_orig->x, w->d->n));
|
595
|
+
scs_printf("Norm y = %1.6e, ", SCS(norm_2)(w->xys_orig->y, w->d->m));
|
596
|
+
scs_printf("Norm s = %1.6e, ", SCS(norm_2)(w->xys_orig->s, w->d->m));
|
597
|
+
scs_printf("Norm |Ax + s| = %1.6e, ", SCS(norm_2)(r->ax_s, w->d->m));
|
598
|
+
scs_printf("tau = %1.6e, ", w->u[w->d->n + w->d->m]);
|
599
|
+
scs_printf("kappa = %1.6e, ", w->rsk[w->d->n + w->d->m]);
|
600
|
+
scs_printf("|u - u_t| = %1.6e, ",
|
581
601
|
SCS(norm_diff)(w->u, w->u_t, w->d->n + w->d->m + 1));
|
582
|
-
scs_printf("res_infeas = %1.
|
583
|
-
scs_printf("res_unbdd_a = %1.
|
584
|
-
scs_printf("res_unbdd_p = %1.
|
585
|
-
scs_printf("ctx_tau = %1.
|
602
|
+
scs_printf("res_infeas = %1.6e, ", r->res_infeas);
|
603
|
+
scs_printf("res_unbdd_a = %1.6e, ", r->res_unbdd_a);
|
604
|
+
scs_printf("res_unbdd_p = %1.6e, ", r->res_unbdd_p);
|
605
|
+
scs_printf("ctx_tau = %1.6e, ", r->ctx_tau);
|
586
606
|
scs_printf("bty_tau = %1.2e\n", r->bty_tau);
|
587
607
|
#endif
|
588
608
|
|
@@ -649,26 +669,29 @@ static void print_footer(ScsInfo *info) {
|
|
649
669
|
}
|
650
670
|
|
651
671
|
static scs_int has_converged(ScsWork *w, scs_int iter) {
|
672
|
+
scs_float abs_xt_p_x, abs_ctx, abs_bty;
|
673
|
+
scs_float nm_s, nm_px, nm_aty, nm_ax;
|
674
|
+
scs_float grl, prl, drl;
|
652
675
|
scs_float eps_abs = w->stgs->eps_abs;
|
653
676
|
scs_float eps_rel = w->stgs->eps_rel;
|
654
677
|
scs_float eps_infeas = w->stgs->eps_infeas;
|
655
|
-
scs_float grl, prl, drl;
|
656
678
|
|
657
679
|
ScsResiduals *r = w->r_orig;
|
658
|
-
scs_float *b = w->b_orig;
|
659
|
-
scs_float *c = w->c_orig;
|
660
|
-
scs_float *s = w->xys_orig->s;
|
661
680
|
|
662
681
|
if (r->tau > 0.) {
|
682
|
+
abs_xt_p_x = ABS(r->xt_p_x);
|
683
|
+
abs_ctx = ABS(r->ctx);
|
684
|
+
abs_bty = ABS(r->bty);
|
685
|
+
|
686
|
+
nm_s = NORM(w->xys_orig->s, w->d->m);
|
687
|
+
nm_px = NORM(r->px, w->d->n);
|
688
|
+
nm_aty = NORM(r->aty, w->d->n);
|
689
|
+
nm_ax = NORM(r->ax, w->d->m);
|
663
690
|
/* xt_p_x, ctx, bty already have tau divided out */
|
664
|
-
grl = MAX(MAX(
|
691
|
+
grl = MAX(MAX(abs_xt_p_x, abs_ctx), abs_bty);
|
665
692
|
/* s, ax, px, aty do *not* have tau divided out, so need to divide */
|
666
|
-
prl = MAX(MAX(
|
667
|
-
|
668
|
-
r->tau;
|
669
|
-
drl = MAX(MAX(NORM(c, w->d->n) * r->tau, NORM(r->px, w->d->n)),
|
670
|
-
NORM(r->aty, w->d->n)) /
|
671
|
-
r->tau;
|
693
|
+
prl = MAX(MAX(w->nm_b_orig * r->tau, nm_s), nm_ax) / r->tau;
|
694
|
+
drl = MAX(MAX(w->nm_c_orig * r->tau, nm_px), nm_aty) / r->tau;
|
672
695
|
if (isless(r->res_pri, eps_abs + eps_rel * prl) &&
|
673
696
|
isless(r->res_dual, eps_abs + eps_rel * drl) &&
|
674
697
|
isless(r->gap, eps_abs + eps_rel * grl)) {
|
@@ -685,7 +708,7 @@ static scs_int has_converged(ScsWork *w, scs_int iter) {
|
|
685
708
|
return 0;
|
686
709
|
}
|
687
710
|
|
688
|
-
#if
|
711
|
+
#if NO_VALIDATE == 0
|
689
712
|
static scs_int validate(const ScsData *d, const ScsCone *k,
|
690
713
|
const ScsSettings *stgs) {
|
691
714
|
if (d->m <= 0 || d->n <= 0) {
|
@@ -762,12 +785,15 @@ scs_int scs_update(ScsWork *w, scs_float *b, scs_float *c) {
|
|
762
785
|
} else {
|
763
786
|
memcpy(w->d->b, w->b_orig, w->d->m * sizeof(scs_float));
|
764
787
|
}
|
788
|
+
w->nm_b_orig = NORM(w->b_orig, w->d->m);
|
789
|
+
|
765
790
|
if (c) {
|
766
791
|
memcpy(w->c_orig, c, w->d->n * sizeof(scs_float));
|
767
792
|
memcpy(w->d->c, c, w->d->n * sizeof(scs_float));
|
768
793
|
} else {
|
769
794
|
memcpy(w->d->c, w->c_orig, w->d->n * sizeof(scs_float));
|
770
795
|
}
|
796
|
+
w->nm_c_orig = NORM(w->c_orig, w->d->n);
|
771
797
|
|
772
798
|
/* normalize */
|
773
799
|
if (w->scal) {
|
@@ -826,7 +852,7 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
826
852
|
w->rsk = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
827
853
|
w->h = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
|
828
854
|
w->g = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
|
829
|
-
w->lin_sys_warm_start = (scs_float *)scs_calloc(
|
855
|
+
w->lin_sys_warm_start = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
|
830
856
|
w->diag_r = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
831
857
|
/* x,y,s struct */
|
832
858
|
w->xys_orig = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
@@ -864,7 +890,7 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
864
890
|
/* set w->*_orig and performs normalization if appropriate */
|
865
891
|
scs_update(w, w->d->b, w->d->c);
|
866
892
|
|
867
|
-
if (!(w->p =
|
893
|
+
if (!(w->p = scs_init_lin_sys_work(w->d->A, w->d->P, w->diag_r))) {
|
868
894
|
scs_printf("ERROR: init_lin_sys_work failure\n");
|
869
895
|
return SCS_NULL;
|
870
896
|
}
|
@@ -891,7 +917,7 @@ static void update_work_cache(ScsWork *w) {
|
|
891
917
|
/* g = (I + M)^{-1} h */
|
892
918
|
memcpy(w->g, w->h, (w->d->n + w->d->m) * sizeof(scs_float));
|
893
919
|
SCS(scale_array)(&(w->g[w->d->n]), -1., w->d->m);
|
894
|
-
|
920
|
+
scs_solve_lin_sys(w->p, w->g, SCS_NULL, CG_BEST_TOL);
|
895
921
|
return;
|
896
922
|
}
|
897
923
|
|
@@ -934,24 +960,27 @@ scs_int should_update_r(scs_float factor, scs_int iter) {
|
|
934
960
|
|
935
961
|
static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
936
962
|
scs_int i;
|
937
|
-
scs_float factor, new_scale;
|
963
|
+
scs_float factor, new_scale, relative_res_pri, relative_res_dual;
|
964
|
+
scs_float denom_pri, denom_dual;
|
938
965
|
|
939
966
|
ScsResiduals *r = w->r_orig;
|
940
|
-
|
941
|
-
scs_float
|
942
|
-
scs_float
|
967
|
+
|
968
|
+
scs_float nm_ax = SCALE_NORM(r->ax, w->d->m);
|
969
|
+
scs_float nm_s = SCALE_NORM(w->xys_orig->s, w->d->m);
|
970
|
+
scs_float nm_px_aty_ctau = SCALE_NORM(r->px_aty_ctau, w->d->n);
|
971
|
+
scs_float nm_px = SCALE_NORM(r->px, w->d->n);
|
972
|
+
scs_float nm_aty = SCALE_NORM(r->aty, w->d->n);
|
973
|
+
scs_float nm_ax_s_btau = SCALE_NORM(r->ax_s_btau, w->d->m);
|
943
974
|
|
944
975
|
scs_int iters_since_last_update = iter - w->last_scale_update_iter;
|
945
976
|
/* ||Ax + s - b * tau|| */
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
SCALE_NORM(b, w->d->m) * r->tau));
|
977
|
+
denom_pri = MAX(nm_ax, nm_s);
|
978
|
+
denom_pri = MAX(denom_pri, w->nm_b_orig * r->tau);
|
979
|
+
relative_res_pri = SAFEDIV_POS(nm_ax_s_btau, denom_pri);
|
950
980
|
/* ||Px + A'y + c * tau|| */
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
SCALE_NORM(c, w->d->n) * r->tau));
|
981
|
+
denom_dual = MAX(nm_px, nm_aty);
|
982
|
+
denom_dual = MAX(denom_dual, w->nm_c_orig * r->tau);
|
983
|
+
relative_res_dual = SAFEDIV_POS(nm_px_aty_ctau, denom_dual);
|
955
984
|
|
956
985
|
/* higher scale makes res_pri go down faster, so increase if res_pri larger */
|
957
986
|
w->sum_log_scale_factor += log(relative_res_pri) - log(relative_res_dual);
|
@@ -981,7 +1010,7 @@ static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
981
1010
|
set_diag_r(w);
|
982
1011
|
|
983
1012
|
/* update linear systems */
|
984
|
-
|
1013
|
+
scs_update_lin_sys_diag_r(w->p, w->diag_r);
|
985
1014
|
|
986
1015
|
/* update pre-solved quantities */
|
987
1016
|
update_work_cache(w);
|
@@ -1025,7 +1054,7 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
1025
1054
|
/* initialize ctrl-c support */
|
1026
1055
|
scs_start_interrupt_listener();
|
1027
1056
|
SCS(tic)(&solve_timer);
|
1028
|
-
strcpy(info->lin_sys_solver,
|
1057
|
+
strcpy(info->lin_sys_solver, scs_get_lin_sys_method());
|
1029
1058
|
info->status_val = SCS_UNFINISHED; /* not yet converged */
|
1030
1059
|
update_work(w, sol);
|
1031
1060
|
|
@@ -1057,7 +1086,7 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
1057
1086
|
|
1058
1087
|
/******************* linear system solve ********************/
|
1059
1088
|
SCS(tic)(&lin_sys_timer);
|
1060
|
-
if (project_lin_sys(w, i)
|
1089
|
+
if (project_lin_sys(w, i) != 0) {
|
1061
1090
|
return failure(w, w->d->m, w->d->n, sol, info, SCS_FAILED,
|
1062
1091
|
"error in project_lin_sys", "failure");
|
1063
1092
|
}
|
@@ -1162,7 +1191,7 @@ void scs_finish(ScsWork *w) {
|
|
1162
1191
|
if (w) {
|
1163
1192
|
SCS(finish_cone)(w->cone_work);
|
1164
1193
|
if (w->p) {
|
1165
|
-
|
1194
|
+
scs_free_lin_sys_work(w->p);
|
1166
1195
|
}
|
1167
1196
|
if (w->accel) {
|
1168
1197
|
aa_finish(w->accel);
|
@@ -1179,7 +1208,7 @@ ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) {
|
|
1179
1208
|
scs_printf("ERROR: Missing ScsData or ScsCone input\n");
|
1180
1209
|
return SCS_NULL;
|
1181
1210
|
}
|
1182
|
-
#if
|
1211
|
+
#if NO_VALIDATE == 0
|
1183
1212
|
if (validate(d, k, stgs) < 0) {
|
1184
1213
|
scs_printf("ERROR: Validation returned failure\n");
|
1185
1214
|
return SCS_NULL;
|
@@ -1191,8 +1220,13 @@ ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) {
|
|
1191
1220
|
#endif
|
1192
1221
|
SCS(tic)(&init_timer);
|
1193
1222
|
if (stgs->write_data_filename) {
|
1223
|
+
scs_printf("Writing raw problem data to %s\n", stgs->write_data_filename);
|
1194
1224
|
SCS(write_data)(d, k, stgs);
|
1195
1225
|
}
|
1226
|
+
if (stgs->log_csv_filename) {
|
1227
|
+
scs_printf("Logging run data to %s\n", stgs->log_csv_filename);
|
1228
|
+
/* logging done every iteration */
|
1229
|
+
}
|
1196
1230
|
w = init_work(d, k, stgs);
|
1197
1231
|
if (w) {
|
1198
1232
|
w->setup_time = SCS(tocq)(&init_timer);
|
data/vendor/scs/src/util.c
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
#include "scs_matrix.h"
|
6
6
|
|
7
7
|
/* return milli-seconds */
|
8
|
-
#if (defined
|
8
|
+
#if (defined NO_TIMER)
|
9
9
|
|
10
10
|
void SCS(tic)(SCS(timer) * t) {
|
11
11
|
}
|
@@ -84,13 +84,22 @@ void SCS(deep_copy_data)(ScsData *dest, const ScsData *src) {
|
|
84
84
|
|
85
85
|
void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
|
86
86
|
memcpy(dest, src, sizeof(ScsSettings));
|
87
|
+
/* MATLAB does something weird with strdup, so use strcpy instead */
|
88
|
+
char *tmp;
|
87
89
|
if (src->write_data_filename) {
|
88
|
-
|
90
|
+
/* sizeof(char) = 1 */
|
91
|
+
tmp = (char *)scs_malloc(strlen(src->write_data_filename) + 1);
|
92
|
+
strcpy(tmp, src->write_data_filename);
|
93
|
+
dest->write_data_filename = tmp;
|
89
94
|
} else {
|
90
95
|
dest->write_data_filename = SCS_NULL;
|
91
96
|
}
|
97
|
+
/* MATLAB does something weird with strdup, so use strcpy instead */
|
92
98
|
if (src->log_csv_filename) {
|
93
|
-
|
99
|
+
/* sizeof(char) = 1 */
|
100
|
+
tmp = (char *)scs_malloc(strlen(src->log_csv_filename) + 1);
|
101
|
+
strcpy(tmp, src->log_csv_filename);
|
102
|
+
dest->log_csv_filename = tmp;
|
94
103
|
} else {
|
95
104
|
dest->log_csv_filename = SCS_NULL;
|
96
105
|
}
|