scs 0.4.0 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|