scs 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/lib/scs/ffi.rb +2 -2
  6. data/lib/scs/version.rb +1 -1
  7. data/lib/scs.rb +3 -3
  8. data/vendor/scs/CITATION.cff +2 -2
  9. data/vendor/scs/CMakeLists.txt +305 -171
  10. data/vendor/scs/Makefile +44 -19
  11. data/vendor/scs/README.md +1 -1
  12. data/vendor/scs/include/glbopts.h +34 -14
  13. data/vendor/scs/include/linsys.h +8 -8
  14. data/vendor/scs/include/scs.h +6 -2
  15. data/vendor/scs/include/scs_blas.h +4 -0
  16. data/vendor/scs/include/scs_types.h +3 -1
  17. data/vendor/scs/include/scs_work.h +9 -8
  18. data/vendor/scs/include/util.h +1 -1
  19. data/vendor/scs/linsys/cpu/direct/private.c +32 -153
  20. data/vendor/scs/linsys/cpu/direct/private.h +6 -6
  21. data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
  22. data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
  23. data/vendor/scs/linsys/csparse.c +140 -12
  24. data/vendor/scs/linsys/csparse.h +10 -17
  25. data/vendor/scs/linsys/gpu/gpu.c +4 -4
  26. data/vendor/scs/linsys/gpu/gpu.h +1 -1
  27. data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
  28. data/vendor/scs/linsys/mkl/direct/private.c +182 -0
  29. data/vendor/scs/linsys/mkl/direct/private.h +38 -0
  30. data/vendor/scs/linsys/scs_matrix.c +11 -5
  31. data/vendor/scs/scs.mk +40 -27
  32. data/vendor/scs/src/cones.c +17 -161
  33. data/vendor/scs/src/exp_cone.c +399 -0
  34. data/vendor/scs/src/linalg.c +17 -3
  35. data/vendor/scs/src/normalize.c +4 -2
  36. data/vendor/scs/src/rw.c +107 -38
  37. data/vendor/scs/src/scs.c +103 -69
  38. data/vendor/scs/src/util.c +12 -3
  39. data/vendor/scs/test/minunit.h +2 -1
  40. data/vendor/scs/test/problem_utils.h +2 -1
  41. data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
  42. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +8 -3
  43. data/vendor/scs/test/problems/max_ent +0 -0
  44. data/vendor/scs/test/problems/max_ent.h +8 -0
  45. data/vendor/scs/test/problems/mpc_bug.h +19 -0
  46. data/vendor/scs/test/problems/mpc_bug1 +0 -0
  47. data/vendor/scs/test/problems/mpc_bug2 +0 -0
  48. data/vendor/scs/test/problems/mpc_bug3 +0 -0
  49. data/vendor/scs/test/problems/random_prob.h +2 -43
  50. data/vendor/scs/test/problems/rob_gauss_cov_est.h +7 -2
  51. data/vendor/scs/test/problems/test_exp_cone.h +84 -0
  52. data/vendor/scs/test/problems/test_prob_from_data_file.h +73 -0
  53. data/vendor/scs/test/run_from_file.c +7 -1
  54. data/vendor/scs/test/run_tests.c +25 -9
  55. 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
- static ScsCone *read_scs_cone(FILE *fin) {
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
- fread(&(k->z), sizeof(scs_int), 1, fin);
34
- fread(&(k->l), sizeof(scs_int), 1, fin);
35
- fread(&(k->bsize), sizeof(scs_int), 1, fin);
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
- fread(&(k->qsize), sizeof(scs_int), 1, fin);
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
- fread(k->q, sizeof(scs_int), k->qsize, fin);
96
+ read_int(k->q, file_int_sz, k->qsize, fin);
46
97
  }
47
- fread(&(k->ssize), sizeof(scs_int), 1, fin);
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
- fread(k->s, sizeof(scs_int), k->ssize, fin);
101
+ read_int(k->s, file_int_sz, k->ssize, fin);
51
102
  }
52
- fread(&(k->ep), sizeof(scs_int), 1, fin);
53
- fread(&(k->ed), sizeof(scs_int), 1, fin);
54
- fread(&(k->psize), sizeof(scs_int), 1, fin);
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
- fread(&(s->normalize), sizeof(scs_int), 1, fin);
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
- fread(&(s->max_iters), sizeof(scs_int), 1, fin);
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
- fread(&(s->verbose), sizeof(scs_int), 1, fin);
93
- fread(&(s->warm_start), sizeof(scs_int), 1, fin);
94
- fread(&(s->acceleration_lookback), sizeof(scs_int), 1, fin);
95
- fread(&(s->acceleration_interval), sizeof(scs_int), 1, fin);
96
- fread(&(s->adaptive_scale), sizeof(scs_int), 1, fin);
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
- fread(&(A->m), sizeof(scs_int), 1, fin);
113
- fread(&(A->n), sizeof(scs_int), 1, fin);
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
- fread(A->p, sizeof(scs_int), A->n + 1, fin);
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
- fread(A->i, sizeof(scs_int), Anz, fin);
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
- fread(&(d->m), sizeof(scs_int), 1, fin);
142
- fread(&(d->n), sizeof(scs_int), 1, fin);
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 &= fread(&has_p, sizeof(scs_int), 1, fin);
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
- "Error, sizeof(file int) is %lu, but scs expects sizeof(int) %lu, "
189
- "scs should be recompiled with correct flags.\n",
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 = SCS(get_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
- r->res_pri = SAFEDIV_POS(NORM(r->ax_s_btau, m), r->tau);
199
- r->res_dual = SAFEDIV_POS(NORM(r->px_aty_ctau, n), r->tau);
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 < 0) {
204
- r->res_unbdd_a = SAFEDIV_POS(NORM(r->ax_s, m), -r->ctx_tau);
205
- r->res_unbdd_p = SAFEDIV_POS(NORM(r->px, n), -r->ctx_tau);
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 < 0) {
208
- r->res_infeas = SAFEDIV_POS(NORM(r->aty, n), -r->bty_tau);
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
- return (-b + SQRTF(MAX(b * b - 4 * a * c, 0.))) / (2 * a);
364
+ rad = b * b - 4 * a * c;
365
+ return (-b + SQRTF(MAX(rad, 0.))) / (2 * a);
355
366
  }
356
367
 
357
- /* status < 0 indicates failure */
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
- SCS(add_scaled_array)(warm_start, w->g, l - 1, w->u[l - 1]);
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(CG_NORM(w->r_normalized->ax_s_btau, w->d->m),
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
- tol = CG_TOL_FACTOR * MIN(tol, CG_NORM(warm_start, w->d->n) /
379
- POWF((scs_float)iter + 1, CG_RATE));
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 = SCS(solve_lin_sys)(w->p, w->u_t, warm_start, tol);
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(SCS(dot)(sol->s, sol->y, w->d->m));
534
- if (info->comp_slack > 1e-5 * MAX(SCS(norm_inf)(sol->s, w->d->m),
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
- scs_printf("%*.2e ", (int)HSPACE, SCS(tocq)(solve_timer) / 1e3);
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 = %4f, ", SCS(norm_2)(w->u, w->d->n + w->d->m + 1));
571
- scs_printf("Norm u_t = %4f, ", SCS(norm_2)(w->u_t, w->d->n + w->d->m + 1));
572
- scs_printf("Norm v = %4f, ", SCS(norm_2)(w->v, w->d->n + w->d->m + 1));
573
- scs_printf("Norm rsk = %4f, ", SCS(norm_2)(w->rsk, w->d->n + w->d->m + 1));
574
- scs_printf("Norm x = %4f, ", SCS(norm_2)(w->xys_orig->x, w->d->n));
575
- scs_printf("Norm y = %4f, ", SCS(norm_2)(w->xys_orig->y, w->d->m));
576
- scs_printf("Norm s = %4f, ", SCS(norm_2)(w->xys_orig->s, w->d->m));
577
- scs_printf("Norm |Ax + s| = %1.2e, ", SCS(norm_2)(r->ax_s, w->d->m));
578
- scs_printf("tau = %4f, ", w->u[w->d->n + w->d->m]);
579
- scs_printf("kappa = %4f, ", w->rsk[w->d->n + w->d->m]);
580
- scs_printf("|u - u_t| = %1.2e, ",
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.2e, ", r->res_infeas);
583
- scs_printf("res_unbdd_a = %1.2e, ", r->res_unbdd_a);
584
- scs_printf("res_unbdd_p = %1.2e, ", r->res_unbdd_p);
585
- scs_printf("ctx_tau = %1.2e, ", r->ctx_tau);
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(ABS(r->xt_p_x), ABS(r->ctx)), ABS(r->bty));
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(NORM(b, w->d->m) * r->tau, NORM(s, w->d->m)),
667
- NORM(r->ax, w->d->m)) /
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 NOVALIDATE == 0
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((l - 1), sizeof(scs_float));
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 = SCS(init_lin_sys_work)(w->d->A, w->d->P, w->diag_r))) {
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
- SCS(solve_lin_sys)(w->p, w->g, SCS_NULL, CG_BEST_TOL);
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
- ScsSolution *xys = w->xys_orig;
941
- scs_float *b = w->b_orig;
942
- scs_float *c = w->c_orig;
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
- scs_float relative_res_pri = SAFEDIV_POS(
947
- SCALE_NORM(r->ax_s_btau, w->d->m),
948
- MAX(MAX(SCALE_NORM(r->ax, w->d->m), SCALE_NORM(xys->s, w->d->m)),
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
- scs_float relative_res_dual = SAFEDIV_POS(
952
- SCALE_NORM(r->px_aty_ctau, w->d->n),
953
- MAX(MAX(SCALE_NORM(r->px, w->d->n), SCALE_NORM(r->aty, w->d->n)),
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
- SCS(update_lin_sys_diag_r)(w->p, w->diag_r);
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, SCS(get_lin_sys_method)());
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) < 0) {
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
- SCS(free_lin_sys_work)(w->p);
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 NOVALIDATE == 0
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);
@@ -5,7 +5,7 @@
5
5
  #include "scs_matrix.h"
6
6
 
7
7
  /* return milli-seconds */
8
- #if (defined NOTIMER)
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
- dest->write_data_filename = strdup(src->write_data_filename);
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
- dest->log_csv_filename = strdup(src->log_csv_filename);
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
  }