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.
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
  }