scs 0.2.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 (106) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +98 -0
  5. data/ext/scs/extconf.rb +29 -0
  6. data/lib/scs.rb +17 -0
  7. data/lib/scs/ffi.rb +117 -0
  8. data/lib/scs/solver.rb +173 -0
  9. data/lib/scs/version.rb +3 -0
  10. data/vendor/scs/LICENSE.txt +21 -0
  11. data/vendor/scs/Makefile +164 -0
  12. data/vendor/scs/README.md +222 -0
  13. data/vendor/scs/include/aa.h +56 -0
  14. data/vendor/scs/include/cones.h +46 -0
  15. data/vendor/scs/include/ctrlc.h +33 -0
  16. data/vendor/scs/include/glbopts.h +177 -0
  17. data/vendor/scs/include/linalg.h +26 -0
  18. data/vendor/scs/include/linsys.h +64 -0
  19. data/vendor/scs/include/normalize.h +18 -0
  20. data/vendor/scs/include/rw.h +17 -0
  21. data/vendor/scs/include/scs.h +161 -0
  22. data/vendor/scs/include/scs_blas.h +51 -0
  23. data/vendor/scs/include/util.h +65 -0
  24. data/vendor/scs/linsys/amatrix.c +305 -0
  25. data/vendor/scs/linsys/amatrix.h +36 -0
  26. data/vendor/scs/linsys/amatrix.o +0 -0
  27. data/vendor/scs/linsys/cpu/direct/private.c +366 -0
  28. data/vendor/scs/linsys/cpu/direct/private.h +26 -0
  29. data/vendor/scs/linsys/cpu/direct/private.o +0 -0
  30. data/vendor/scs/linsys/cpu/indirect/private.c +256 -0
  31. data/vendor/scs/linsys/cpu/indirect/private.h +31 -0
  32. data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
  33. data/vendor/scs/linsys/external/amd/LICENSE.txt +934 -0
  34. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +469 -0
  35. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +254 -0
  36. data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
  37. data/vendor/scs/linsys/external/amd/amd.h +400 -0
  38. data/vendor/scs/linsys/external/amd/amd_1.c +180 -0
  39. data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
  40. data/vendor/scs/linsys/external/amd/amd_2.c +1842 -0
  41. data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
  42. data/vendor/scs/linsys/external/amd/amd_aat.c +184 -0
  43. data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
  44. data/vendor/scs/linsys/external/amd/amd_control.c +64 -0
  45. data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
  46. data/vendor/scs/linsys/external/amd/amd_defaults.c +37 -0
  47. data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
  48. data/vendor/scs/linsys/external/amd/amd_dump.c +179 -0
  49. data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
  50. data/vendor/scs/linsys/external/amd/amd_global.c +16 -0
  51. data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
  52. data/vendor/scs/linsys/external/amd/amd_info.c +119 -0
  53. data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
  54. data/vendor/scs/linsys/external/amd/amd_internal.h +304 -0
  55. data/vendor/scs/linsys/external/amd/amd_order.c +199 -0
  56. data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
  57. data/vendor/scs/linsys/external/amd/amd_post_tree.c +120 -0
  58. data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
  59. data/vendor/scs/linsys/external/amd/amd_postorder.c +206 -0
  60. data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
  61. data/vendor/scs/linsys/external/amd/amd_preprocess.c +118 -0
  62. data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
  63. data/vendor/scs/linsys/external/amd/amd_valid.c +92 -0
  64. data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
  65. data/vendor/scs/linsys/external/amd/changes +11 -0
  66. data/vendor/scs/linsys/external/qdldl/LICENSE +201 -0
  67. data/vendor/scs/linsys/external/qdldl/README.md +120 -0
  68. data/vendor/scs/linsys/external/qdldl/changes +4 -0
  69. data/vendor/scs/linsys/external/qdldl/qdldl.c +298 -0
  70. data/vendor/scs/linsys/external/qdldl/qdldl.h +177 -0
  71. data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
  72. data/vendor/scs/linsys/external/qdldl/qdldl_types.h +21 -0
  73. data/vendor/scs/linsys/gpu/gpu.c +41 -0
  74. data/vendor/scs/linsys/gpu/gpu.h +85 -0
  75. data/vendor/scs/linsys/gpu/indirect/private.c +304 -0
  76. data/vendor/scs/linsys/gpu/indirect/private.h +36 -0
  77. data/vendor/scs/scs.mk +181 -0
  78. data/vendor/scs/src/aa.c +224 -0
  79. data/vendor/scs/src/aa.o +0 -0
  80. data/vendor/scs/src/cones.c +802 -0
  81. data/vendor/scs/src/cones.o +0 -0
  82. data/vendor/scs/src/ctrlc.c +77 -0
  83. data/vendor/scs/src/ctrlc.o +0 -0
  84. data/vendor/scs/src/linalg.c +84 -0
  85. data/vendor/scs/src/linalg.o +0 -0
  86. data/vendor/scs/src/normalize.c +93 -0
  87. data/vendor/scs/src/normalize.o +0 -0
  88. data/vendor/scs/src/rw.c +167 -0
  89. data/vendor/scs/src/rw.o +0 -0
  90. data/vendor/scs/src/scs.c +978 -0
  91. data/vendor/scs/src/scs.o +0 -0
  92. data/vendor/scs/src/scs_version.c +5 -0
  93. data/vendor/scs/src/scs_version.o +0 -0
  94. data/vendor/scs/src/util.c +196 -0
  95. data/vendor/scs/src/util.o +0 -0
  96. data/vendor/scs/test/data/small_random_socp +0 -0
  97. data/vendor/scs/test/minunit.h +13 -0
  98. data/vendor/scs/test/problem_utils.h +93 -0
  99. data/vendor/scs/test/problems/rob_gauss_cov_est.h +85 -0
  100. data/vendor/scs/test/problems/small_lp.h +50 -0
  101. data/vendor/scs/test/problems/small_random_socp.h +33 -0
  102. data/vendor/scs/test/random_socp_prob.c +171 -0
  103. data/vendor/scs/test/run_from_file.c +69 -0
  104. data/vendor/scs/test/run_tests +2 -0
  105. data/vendor/scs/test/run_tests.c +32 -0
  106. metadata +203 -0
Binary file
@@ -0,0 +1,77 @@
1
+ /*
2
+ * Implements signal handling (ctrl-c) for SCS.
3
+ *
4
+ * Under Windows, we use SetConsoleCtrlHandler.
5
+ * Under Unix systems, we use sigaction.
6
+ * For Mex files, we use utSetInterruptEnabled/utIsInterruptPending.
7
+ *
8
+ */
9
+
10
+ #include "ctrlc.h"
11
+
12
+ #if CTRLC > 0
13
+
14
+ #ifdef MATLAB_MEX_FILE
15
+ #include <stdbool.h>
16
+
17
+ extern bool utIsInterruptPending(void);
18
+ extern bool utSetInterruptEnabled(bool);
19
+
20
+ static int istate;
21
+ void scs_start_interrupt_listener(void) {
22
+ istate = (int)utSetInterruptEnabled(true);
23
+ }
24
+
25
+ void scs_end_interrupt_listener(void) { utSetInterruptEnabled((bool)istate); }
26
+
27
+ int scs_is_interrupted(void) { return (int)utIsInterruptPending(); }
28
+
29
+ #elif (defined _WIN32 || _WIN64 || defined _WINDLL)
30
+ #include <windows.h>
31
+
32
+ static int int_detected;
33
+ static BOOL WINAPI scs_handle_ctrlc(DWORD dwCtrlType) {
34
+ if (dwCtrlType != CTRL_C_EVENT) {
35
+ return FALSE;
36
+ }
37
+ int_detected = 1;
38
+ return TRUE;
39
+ }
40
+
41
+ void scs_start_interrupt_listener(void) {
42
+ int_detected = 0;
43
+ SetConsoleCtrlHandler(scs_handle_ctrlc, TRUE);
44
+ }
45
+
46
+ void scs_end_interrupt_listener(void) {
47
+ SetConsoleCtrlHandler(scs_handle_ctrlc, FALSE);
48
+ }
49
+
50
+ int scs_is_interrupted(void) { return int_detected; }
51
+
52
+ #else /* Unix */
53
+
54
+ #include <signal.h>
55
+ static int int_detected;
56
+ struct sigaction oact;
57
+ static void scs_handle_ctrlc(int dummy) { int_detected = dummy ? dummy : -1; }
58
+
59
+ void scs_start_interrupt_listener(void) {
60
+ struct sigaction act;
61
+ int_detected = 0;
62
+ act.sa_flags = 0;
63
+ sigemptyset(&act.sa_mask);
64
+ act.sa_handler = scs_handle_ctrlc;
65
+ sigaction(SIGINT, &act, &oact);
66
+ }
67
+
68
+ void scs_end_interrupt_listener(void) {
69
+ struct sigaction act;
70
+ sigaction(SIGINT, &oact, &act);
71
+ }
72
+
73
+ int scs_is_interrupted(void) { return int_detected; }
74
+
75
+ #endif /* END IF MATLAB_MEX_FILE / WIN32 */
76
+
77
+ #endif /* END IF CTRLC > 0 */
Binary file
@@ -0,0 +1,84 @@
1
+ #include "linalg.h"
2
+ #include <math.h>
3
+
4
+ /* x = b*a */
5
+ void SCS(set_as_scaled_array)(scs_float *x, const scs_float *a,
6
+ const scs_float b, scs_int len) {
7
+ scs_int i;
8
+ for (i = 0; i < len; ++i) x[i] = b * a[i];
9
+ }
10
+
11
+ /* a *= b */
12
+ void SCS(scale_array)(scs_float *a, const scs_float b, scs_int len) {
13
+ scs_int i;
14
+ for (i = 0; i < len; ++i) a[i] *= b;
15
+ }
16
+
17
+ /* x'*y */
18
+ scs_float SCS(dot)(const scs_float *x, const scs_float *y, scs_int len) {
19
+ scs_int i;
20
+ scs_float ip = 0.0;
21
+ for (i = 0; i < len; ++i) {
22
+ ip += x[i] * y[i];
23
+ }
24
+ return ip;
25
+ }
26
+
27
+ /* ||v||_2^2 */
28
+ scs_float SCS(norm_sq)(const scs_float *v, scs_int len) {
29
+ scs_int i;
30
+ scs_float nmsq = 0.0;
31
+ for (i = 0; i < len; ++i) {
32
+ nmsq += v[i] * v[i];
33
+ }
34
+ return nmsq;
35
+ }
36
+
37
+ /* ||v||_2 */
38
+ scs_float SCS(norm)(const scs_float *v, scs_int len) {
39
+ return SQRTF(SCS(norm_sq)(v, len));
40
+ }
41
+
42
+ scs_float SCS(norm_inf)(const scs_float *a, scs_int l) {
43
+ scs_float tmp, max = 0.0;
44
+ scs_int i;
45
+ for (i = 0; i < l; ++i) {
46
+ tmp = ABS(a[i]);
47
+ if (tmp > max) {
48
+ max = tmp;
49
+ }
50
+ }
51
+ return max;
52
+ }
53
+
54
+ /* saxpy a += sc*b */
55
+ void SCS(add_scaled_array)(scs_float *a, const scs_float *b, scs_int n,
56
+ const scs_float sc) {
57
+ scs_int i;
58
+ for (i = 0; i < n; ++i) {
59
+ a[i] += sc * b[i];
60
+ }
61
+ }
62
+
63
+ scs_float SCS(norm_diff)(const scs_float *a, const scs_float *b, scs_int l) {
64
+ scs_float nm_diff = 0.0, tmp;
65
+ scs_int i;
66
+ for (i = 0; i < l; ++i) {
67
+ tmp = (a[i] - b[i]);
68
+ nm_diff += tmp * tmp;
69
+ }
70
+ return SQRTF(nm_diff);
71
+ }
72
+
73
+ scs_float SCS(norm_inf_diff)(const scs_float *a, const scs_float *b,
74
+ scs_int l) {
75
+ scs_float tmp, max = 0.0;
76
+ scs_int i;
77
+ for (i = 0; i < l; ++i) {
78
+ tmp = ABS(a[i] - b[i]);
79
+ if (tmp > max) {
80
+ max = tmp;
81
+ }
82
+ }
83
+ return max;
84
+ }
Binary file
@@ -0,0 +1,93 @@
1
+ #include "normalize.h"
2
+ #include "linalg.h"
3
+ #include "scs.h"
4
+
5
+ #define MIN_SCALE (1e-6)
6
+
7
+ void SCS(normalize_b_c)(ScsWork *w) {
8
+ scs_int i;
9
+ scs_float nm, *D = w->scal->D, *E = w->scal->E, *b = w->b, *c = w->c;
10
+ /* scale b */
11
+ for (i = 0; i < w->m; ++i) {
12
+ b[i] /= D[i];
13
+ }
14
+ nm = SCS(norm)(b, w->m);
15
+ w->sc_b = w->scal->mean_norm_col_a / MAX(nm, MIN_SCALE);
16
+ /* scale c */
17
+ for (i = 0; i < w->n; ++i) {
18
+ c[i] /= E[i];
19
+ }
20
+ nm = SCS(norm)(c, w->n);
21
+ w->sc_c = w->scal->mean_norm_row_a / MAX(nm, MIN_SCALE);
22
+ SCS(scale_array)(b, w->sc_b * w->stgs->scale, w->m);
23
+ SCS(scale_array)(c, w->sc_c * w->stgs->scale, w->n);
24
+ }
25
+
26
+ void SCS(calc_scaled_resids)(ScsWork *w, ScsResiduals *r) {
27
+ scs_float *D = w->scal->D;
28
+ scs_float *E = w->scal->E;
29
+ scs_float *u = w->u;
30
+ scs_float *u_t = w->u_t;
31
+ scs_float *u_prev = w->u_prev;
32
+ scs_float tmp;
33
+ scs_int i, n = w->n, m = w->m;
34
+
35
+ r->res_pri = 0;
36
+ for (i = 0; i < n; ++i) {
37
+ tmp = (u[i] - u_t[i]) / (E[i] * w->sc_b);
38
+ r->res_pri += tmp * tmp;
39
+ }
40
+ for (i = 0; i < m; ++i) {
41
+ tmp = (u[i + n] - u_t[i + n]) / (D[i] * w->sc_c);
42
+ r->res_pri += tmp * tmp;
43
+ }
44
+ tmp = u[n + m] - u_t[n + m];
45
+ r->res_pri += tmp * tmp;
46
+ r->res_pri = sqrt(r->res_pri);
47
+
48
+ r->res_dual = 0;
49
+ for (i = 0; i < n; ++i) {
50
+ tmp = (u[i] - u_prev[i]) * E[i] / w->sc_b;
51
+ r->res_dual += tmp * tmp;
52
+ }
53
+ for (i = 0; i < m; ++i) {
54
+ tmp = (u[i + n] - u_prev[i + n]) * D[i] / w->sc_c;
55
+ r->res_dual += tmp * tmp;
56
+ }
57
+ tmp = u[n + m] - u_t[n + m];
58
+ r->res_dual += tmp * tmp;
59
+ r->res_dual = sqrt(r->res_dual);
60
+ }
61
+
62
+ void SCS(normalize_warm_start)(ScsWork *w) {
63
+ scs_int i;
64
+ scs_float *D = w->scal->D;
65
+ scs_float *E = w->scal->E;
66
+ scs_float *x = w->u;
67
+ scs_float *y = &(w->u[w->n]);
68
+ scs_float *s = &(w->v[w->n]);
69
+ for (i = 0; i < w->n; ++i) {
70
+ x[i] *= (E[i] * w->sc_b);
71
+ }
72
+ for (i = 0; i < w->m; ++i) {
73
+ y[i] *= (D[i] * w->sc_c);
74
+ }
75
+ for (i = 0; i < w->m; ++i) {
76
+ s[i] /= (D[i] / (w->sc_b * w->stgs->scale));
77
+ }
78
+ }
79
+
80
+ void SCS(un_normalize_sol)(ScsWork *w, ScsSolution *sol) {
81
+ scs_int i;
82
+ scs_float *D = w->scal->D;
83
+ scs_float *E = w->scal->E;
84
+ for (i = 0; i < w->n; ++i) {
85
+ sol->x[i] /= (E[i] * w->sc_b);
86
+ }
87
+ for (i = 0; i < w->m; ++i) {
88
+ sol->y[i] /= (D[i] * w->sc_c);
89
+ }
90
+ for (i = 0; i < w->m; ++i) {
91
+ sol->s[i] *= D[i] / (w->sc_b * w->stgs->scale);
92
+ }
93
+ }
@@ -0,0 +1,167 @@
1
+ #include "rw.h"
2
+
3
+ #include <stdint.h>
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+
7
+ #include "amatrix.h"
8
+ #include "scs.h"
9
+ #include "util.h"
10
+
11
+ /* writes/reads problem data to/from filename */
12
+ /* This is a VERY naive implementation, doesn't care about portability etc */
13
+
14
+ static void write_scs_cone(const ScsCone *k, FILE *fout) {
15
+ fwrite(&(k->f), sizeof(scs_int), 1, fout);
16
+ fwrite(&(k->l), sizeof(scs_int), 1, fout);
17
+ fwrite(&(k->qsize), sizeof(scs_int), 1, fout);
18
+ fwrite(k->q, sizeof(scs_int), k->qsize, fout);
19
+ fwrite(&(k->ssize), sizeof(scs_int), 1, fout);
20
+ fwrite(k->s, sizeof(scs_int), k->ssize, fout);
21
+ fwrite(&(k->ep), sizeof(scs_int), 1, fout);
22
+ fwrite(&(k->ed), sizeof(scs_int), 1, fout);
23
+ fwrite(&(k->psize), sizeof(scs_int), 1, fout);
24
+ fwrite(k->p, sizeof(scs_float), k->psize, fout);
25
+ }
26
+
27
+ static ScsCone *read_scs_cone(FILE *fin) {
28
+ ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
29
+ fread(&(k->f), sizeof(scs_int), 1, fin);
30
+ fread(&(k->l), sizeof(scs_int), 1, fin);
31
+ fread(&(k->qsize), sizeof(scs_int), 1, fin);
32
+ k->q = scs_calloc(k->qsize, sizeof(scs_int));
33
+ fread(k->q, sizeof(scs_int), k->qsize, fin);
34
+ fread(&(k->ssize), sizeof(scs_int), 1, fin);
35
+ k->s = scs_calloc(k->ssize, sizeof(scs_int));
36
+ fread(k->s, sizeof(scs_int), k->ssize, fin);
37
+ fread(&(k->ep), sizeof(scs_int), 1, fin);
38
+ fread(&(k->ed), sizeof(scs_int), 1, fin);
39
+ fread(&(k->psize), sizeof(scs_int), 1, fin);
40
+ k->p = scs_calloc(k->psize, sizeof(scs_int));
41
+ fread(k->p, sizeof(scs_float), k->psize, fin);
42
+ return k;
43
+ }
44
+
45
+ static void write_scs_stgs(const ScsSettings *s, FILE *fout) {
46
+ /* Warm start to false for now */
47
+ scs_int warm_start = 0;
48
+ fwrite(&(s->normalize), sizeof(scs_int), 1, fout);
49
+ fwrite(&(s->scale), sizeof(scs_float), 1, fout);
50
+ fwrite(&(s->rho_x), sizeof(scs_float), 1, fout);
51
+ fwrite(&(s->max_iters), sizeof(scs_int), 1, fout);
52
+ fwrite(&(s->eps), sizeof(scs_float), 1, fout);
53
+ fwrite(&(s->alpha), sizeof(scs_float), 1, fout);
54
+ fwrite(&(s->cg_rate), sizeof(scs_float), 1, fout);
55
+ fwrite(&(s->verbose), sizeof(scs_int), 1, fout);
56
+ fwrite(&warm_start, sizeof(scs_int), 1, fout);
57
+ fwrite(&(s->acceleration_lookback), sizeof(scs_int), 1, fout);
58
+ /* Do not write the write_data_filename */
59
+ }
60
+
61
+ static ScsSettings *read_scs_stgs(FILE *fin) {
62
+ ScsSettings *s = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
63
+ fread(&(s->normalize), sizeof(scs_int), 1, fin);
64
+ fread(&(s->scale), sizeof(scs_float), 1, fin);
65
+ fread(&(s->rho_x), sizeof(scs_float), 1, fin);
66
+ fread(&(s->max_iters), sizeof(scs_int), 1, fin);
67
+ fread(&(s->eps), sizeof(scs_float), 1, fin);
68
+ fread(&(s->alpha), sizeof(scs_float), 1, fin);
69
+ fread(&(s->cg_rate), sizeof(scs_float), 1, fin);
70
+ fread(&(s->verbose), sizeof(scs_int), 1, fin);
71
+ fread(&(s->warm_start), sizeof(scs_int), 1, fin);
72
+ fread(&(s->acceleration_lookback), sizeof(scs_int), 1, fin);
73
+ return s;
74
+ }
75
+
76
+ static void write_amatrix(const ScsMatrix *A, FILE *fout) {
77
+ scs_int Anz = A->p[A->n];
78
+ fwrite(&(A->m), sizeof(scs_int), 1, fout);
79
+ fwrite(&(A->n), sizeof(scs_int), 1, fout);
80
+ fwrite(A->p, sizeof(scs_int), A->n + 1, fout);
81
+ fwrite(A->x, sizeof(scs_float), Anz, fout);
82
+ fwrite(A->i, sizeof(scs_int), Anz, fout);
83
+ }
84
+
85
+ static ScsMatrix *read_amatrix(FILE *fin) {
86
+ scs_int Anz;
87
+ ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
88
+ fread(&(A->m), sizeof(scs_int), 1, fin);
89
+ fread(&(A->n), sizeof(scs_int), 1, fin);
90
+ A->p = scs_calloc(A->n + 1, sizeof(scs_int));
91
+ fread(A->p, sizeof(scs_int), A->n + 1, fin);
92
+ Anz = A->p[A->n];
93
+ A->x = scs_calloc(Anz, sizeof(scs_float));
94
+ A->i = scs_calloc(Anz, sizeof(scs_int));
95
+ fread(A->x, sizeof(scs_float), Anz, fin);
96
+ fread(A->i, sizeof(scs_int), Anz, fin);
97
+ return A;
98
+ }
99
+
100
+ static void write_scs_data(const ScsData *d, FILE *fout) {
101
+ fwrite(&(d->m), sizeof(scs_int), 1, fout);
102
+ fwrite(&(d->n), sizeof(scs_int), 1, fout);
103
+ fwrite(d->b, sizeof(scs_float), d->m, fout);
104
+ fwrite(d->c, sizeof(scs_float), d->n, fout);
105
+ write_scs_stgs(d->stgs, fout);
106
+ write_amatrix(d->A, fout);
107
+ }
108
+
109
+ static ScsData *read_scs_data(FILE *fin) {
110
+ ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
111
+ fread(&(d->m), sizeof(scs_int), 1, fin);
112
+ fread(&(d->n), sizeof(scs_int), 1, fin);
113
+ d->b = scs_calloc(d->m, sizeof(scs_float));
114
+ d->c = scs_calloc(d->n, sizeof(scs_float));
115
+ fread(d->b, sizeof(scs_float), d->m, fin);
116
+ fread(d->c, sizeof(scs_float), d->n, fin);
117
+ d->stgs = read_scs_stgs(fin);
118
+ d->A = read_amatrix(fin);
119
+ return d;
120
+ }
121
+
122
+ void SCS(write_data)(const ScsData *d, const ScsCone *k) {
123
+ FILE *fout = fopen(d->stgs->write_data_filename, "wb");
124
+ uint32_t scs_int_sz = (uint32_t)sizeof(scs_int);
125
+ uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
126
+ scs_printf("writing data to %s\n", d->stgs->write_data_filename);
127
+ fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout);
128
+ fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout);
129
+ write_scs_cone(k, fout);
130
+ write_scs_data(d, fout);
131
+ fclose(fout);
132
+ }
133
+
134
+ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k) {
135
+ uint32_t file_int_sz;
136
+ uint32_t file_float_sz;
137
+ FILE *fin = fopen(filename, "rb");
138
+ if (!fin) {
139
+ scs_printf("Error reading file %s\n", filename);
140
+ return -1;
141
+ }
142
+ scs_printf("Reading data from %s\n", filename);
143
+ fread(&(file_int_sz), sizeof(uint32_t), 1, fin);
144
+ fread(&(file_float_sz), sizeof(uint32_t), 1, fin);
145
+
146
+ if (file_int_sz != (uint32_t)sizeof(scs_int)) {
147
+ scs_printf(
148
+ "Error, sizeof(file int) is %lu, but scs expects sizeof(int) "
149
+ "%lu, scs should be recompiled with correct flags.\n",
150
+ (unsigned long)file_int_sz, (unsigned long)sizeof(scs_int));
151
+ fclose(fin);
152
+ return -1;
153
+ }
154
+ if (file_float_sz != (uint32_t)sizeof(scs_float)) {
155
+ scs_printf(
156
+ "Error, sizeof(file float) is %lu, but scs expects "
157
+ "sizeof(float) %lu, scs should be recompiled with the correct flags.\n",
158
+ (unsigned long)file_float_sz, (unsigned long)sizeof(scs_float));
159
+ fclose(fin);
160
+ return -1;
161
+ }
162
+
163
+ *k = read_scs_cone(fin);
164
+ *d = read_scs_data(fin);
165
+ fclose(fin);
166
+ return 0;
167
+ }
Binary file
@@ -0,0 +1,978 @@
1
+ #include "scs.h"
2
+
3
+ #include "aa.h"
4
+ #include "ctrlc.h"
5
+ #include "glbopts.h"
6
+ #include "linalg.h"
7
+ #include "linsys.h"
8
+ #include "normalize.h"
9
+ #include "rw.h"
10
+ #include "util.h"
11
+
12
+ SCS(timer) global_timer;
13
+
14
+ /* printing header */
15
+ static const char *HEADER[] = {
16
+ " Iter ", " pri res ", " dua res ", " rel gap ",
17
+ " pri obj ", " dua obj ", " kap/tau ", " time (s)",
18
+ };
19
+ static const scs_int HSPACE = 9;
20
+ static const scs_int HEADER_LEN = 8;
21
+ static const scs_int LINE_LEN = 76;
22
+
23
+ static scs_int scs_isnan(scs_float x) { return (x == NAN || x != x); }
24
+
25
+ static void free_work(ScsWork *w) {
26
+ if (w) {
27
+ scs_free(w->u);
28
+ scs_free(w->u_best);
29
+ scs_free(w->u_t);
30
+ scs_free(w->u_prev);
31
+ /* Don't need these because u*, v* are contiguous in mem
32
+ scs_free(w->v);
33
+ scs_free(w->v_best);
34
+ scs_free(w->v_prev);
35
+ */
36
+ scs_free(w->h);
37
+ scs_free(w->g);
38
+ scs_free(w->b);
39
+ scs_free(w->c);
40
+ scs_free(w->pr);
41
+ scs_free(w->dr);
42
+ if (w->scal) {
43
+ scs_free(w->scal->D);
44
+ scs_free(w->scal->E);
45
+ scs_free(w->scal);
46
+ }
47
+ scs_free(w);
48
+ }
49
+ }
50
+
51
+ static void print_init_header(const ScsData *d, const ScsCone *k) {
52
+ scs_int i;
53
+ ScsSettings *stgs = d->stgs;
54
+ char *cone_str = SCS(get_cone_header)(k);
55
+ char *lin_sys_method = SCS(get_lin_sys_method)(d->A, d->stgs);
56
+ #ifdef USE_LAPACK
57
+ scs_int acceleration_lookback = stgs->acceleration_lookback;
58
+ #else
59
+ scs_int acceleration_lookback = 0;
60
+ #endif
61
+ for (i = 0; i < LINE_LEN; ++i) {
62
+ scs_printf("-");
63
+ }
64
+ scs_printf(
65
+ "\n\tSCS v%s - Splitting Conic Solver\n\t(c) Brendan "
66
+ "O'Donoghue, Stanford University, 2012\n",
67
+ SCS(version)());
68
+ for (i = 0; i < LINE_LEN; ++i) {
69
+ scs_printf("-");
70
+ }
71
+ scs_printf("\n");
72
+ if (lin_sys_method) {
73
+ scs_printf("Lin-sys: %s\n", lin_sys_method);
74
+ scs_free(lin_sys_method);
75
+ }
76
+ if (stgs->normalize) {
77
+ scs_printf(
78
+ "eps = %.2e, alpha = %.2f, max_iters = %i, normalize = %i, "
79
+ "scale = %2.2f\nacceleration_lookback = %i, rho_x = %.2e\n",
80
+ stgs->eps, stgs->alpha, (int)stgs->max_iters, (int)stgs->normalize,
81
+ stgs->scale, (int)acceleration_lookback, stgs->rho_x);
82
+ } else {
83
+ scs_printf(
84
+ "eps = %.2e, alpha = %.2f, max_iters = %i, normalize = %i\n"
85
+ "acceleration_lookback = %i, rho_x = %.2e\n",
86
+ stgs->eps, stgs->alpha, (int)stgs->max_iters, (int)stgs->normalize,
87
+ (int)acceleration_lookback, stgs->rho_x);
88
+ }
89
+ scs_printf("Variables n = %i, constraints m = %i\n", (int)d->n, (int)d->m);
90
+ scs_printf("%s", cone_str);
91
+ scs_free(cone_str);
92
+ #ifdef MATLAB_MEX_FILE
93
+ mexEvalString("drawnow;");
94
+ #endif
95
+ }
96
+
97
+ static void populate_on_failure(scs_int m, scs_int n, ScsSolution *sol,
98
+ ScsInfo *info, scs_int status_val,
99
+ const char *msg) {
100
+ if (info) {
101
+ info->rel_gap = NAN;
102
+ info->res_pri = NAN;
103
+ info->res_dual = NAN;
104
+ info->pobj = NAN;
105
+ info->dobj = NAN;
106
+ info->iter = -1;
107
+ info->status_val = status_val;
108
+ info->solve_time = NAN;
109
+ strcpy(info->status, msg);
110
+ }
111
+ if (sol) {
112
+ if (n > 0) {
113
+ if (!sol->x) {
114
+ sol->x = (scs_float *)scs_malloc(sizeof(scs_float) * n);
115
+ }
116
+ SCS(scale_array)(sol->x, NAN, n);
117
+ }
118
+ if (m > 0) {
119
+ if (!sol->y) {
120
+ sol->y = (scs_float *)scs_malloc(sizeof(scs_float) * m);
121
+ }
122
+ SCS(scale_array)(sol->y, NAN, m);
123
+ if (!sol->s) {
124
+ sol->s = (scs_float *)scs_malloc(sizeof(scs_float) * m);
125
+ }
126
+ SCS(scale_array)(sol->s, NAN, m);
127
+ }
128
+ }
129
+ }
130
+
131
+ static scs_int failure(ScsWork *w, scs_int m, scs_int n, ScsSolution *sol,
132
+ ScsInfo *info, scs_int stint, const char *msg,
133
+ const char *ststr) {
134
+ scs_int status = stint;
135
+ populate_on_failure(m, n, sol, info, status, ststr);
136
+ scs_printf("Failure:%s\n", msg);
137
+ scs_end_interrupt_listener();
138
+ return status;
139
+ }
140
+
141
+ static void warm_start_vars(ScsWork *w, const ScsSolution *sol) {
142
+ scs_int i, n = w->n, m = w->m;
143
+ memset(w->v, 0, n * sizeof(scs_float));
144
+ memcpy(w->u, sol->x, n * sizeof(scs_float));
145
+ memcpy(&(w->u[n]), sol->y, m * sizeof(scs_float));
146
+ memcpy(&(w->v[n]), sol->s, m * sizeof(scs_float));
147
+ w->u[n + m] = 1.0;
148
+ w->v[n + m] = 0.0;
149
+ #ifndef NOVALIDATE
150
+ for (i = 0; i < n + m + 1; ++i) {
151
+ if (scs_isnan(w->u[i])) {
152
+ w->u[i] = 0;
153
+ }
154
+ if (scs_isnan(w->v[i])) {
155
+ w->v[i] = 0;
156
+ }
157
+ }
158
+ #endif
159
+ if (w->stgs->normalize) {
160
+ SCS(normalize_warm_start)(w);
161
+ }
162
+ }
163
+
164
+ static scs_float calc_primal_resid(ScsWork *w, const scs_float *x,
165
+ const scs_float *s, const scs_float tau,
166
+ scs_float *nm_axs) {
167
+ scs_int i;
168
+ scs_float pres = 0, scale, *pr = w->pr;
169
+ *nm_axs = 0;
170
+ memset(pr, 0, w->m * sizeof(scs_float));
171
+ SCS(accum_by_a)(w->A, w->p, x, pr);
172
+ SCS(add_scaled_array)(pr, s, w->m, 1.0); /* pr = Ax + s */
173
+ for (i = 0; i < w->m; ++i) {
174
+ scale = w->stgs->normalize ? w->scal->D[i] / (w->sc_b * w->stgs->scale) : 1;
175
+ scale = scale * scale;
176
+ *nm_axs += (pr[i] * pr[i]) * scale;
177
+ pres += (pr[i] - w->b[i] * tau) * (pr[i] - w->b[i] * tau) * scale;
178
+ }
179
+ *nm_axs = SQRTF(*nm_axs);
180
+ return SQRTF(pres); /* SCS(norm)(Ax + s - b * tau) */
181
+ }
182
+
183
+ static scs_float calc_dual_resid(ScsWork *w, const scs_float *y,
184
+ const scs_float tau, scs_float *nm_a_ty) {
185
+ scs_int i;
186
+ scs_float dres = 0, scale, *dr = w->dr;
187
+ *nm_a_ty = 0;
188
+ memset(dr, 0, w->n * sizeof(scs_float));
189
+ SCS(accum_by_atrans)(w->A, w->p, y, dr); /* dr = A'y */
190
+ for (i = 0; i < w->n; ++i) {
191
+ scale = w->stgs->normalize ? w->scal->E[i] / (w->sc_c * w->stgs->scale) : 1;
192
+ scale = scale * scale;
193
+ *nm_a_ty += (dr[i] * dr[i]) * scale;
194
+ dres += (dr[i] + w->c[i] * tau) * (dr[i] + w->c[i] * tau) * scale;
195
+ }
196
+ *nm_a_ty = SQRTF(*nm_a_ty);
197
+ return SQRTF(dres); /* SCS(norm)(A'y + c * tau) */
198
+ }
199
+
200
+ /* calculates un-normalized quantities */
201
+ static void calc_residuals(ScsWork *w, ScsResiduals *r, scs_int iter) {
202
+ scs_float *x = w->u, *y = &(w->u[w->n]), *s = &(w->v[w->n]);
203
+ scs_float nmpr_tau, nmdr_tau, nm_axs_tau, nm_a_ty_tau, ct_x, bt_y;
204
+ scs_int n = w->n, m = w->m;
205
+
206
+ /* checks if the residuals are unchanged by checking iteration */
207
+ if (r->last_iter == iter) {
208
+ return;
209
+ }
210
+ r->last_iter = iter;
211
+
212
+ r->tau = ABS(w->u[n + m]);
213
+ r->kap = ABS(w->v[n + m]) /
214
+ (w->stgs->normalize ? (w->stgs->scale * w->sc_c * w->sc_b) : 1);
215
+
216
+ nmpr_tau = calc_primal_resid(w, x, s, r->tau, &nm_axs_tau);
217
+ nmdr_tau = calc_dual_resid(w, y, r->tau, &nm_a_ty_tau);
218
+
219
+ r->bt_y_by_tau =
220
+ SCS(dot)(y, w->b, m) /
221
+ (w->stgs->normalize ? (w->stgs->scale * w->sc_c * w->sc_b) : 1);
222
+ r->ct_x_by_tau =
223
+ SCS(dot)(x, w->c, n) /
224
+ (w->stgs->normalize ? (w->stgs->scale * w->sc_c * w->sc_b) : 1);
225
+
226
+ r->res_infeas =
227
+ r->bt_y_by_tau < 0 ? w->nm_b * nm_a_ty_tau / -r->bt_y_by_tau : NAN;
228
+ r->res_unbdd =
229
+ r->ct_x_by_tau < 0 ? w->nm_c * nm_axs_tau / -r->ct_x_by_tau : NAN;
230
+
231
+ bt_y = SAFEDIV_POS(r->bt_y_by_tau, r->tau);
232
+ ct_x = SAFEDIV_POS(r->ct_x_by_tau, r->tau);
233
+
234
+ r->res_pri = SAFEDIV_POS(nmpr_tau / (1 + w->nm_b), r->tau);
235
+ r->res_dual = SAFEDIV_POS(nmdr_tau / (1 + w->nm_c), r->tau);
236
+ r->rel_gap = ABS(ct_x + bt_y) / (1 + ABS(ct_x) + ABS(bt_y));
237
+ }
238
+
239
+ static void cold_start_vars(ScsWork *w) {
240
+ scs_int l = w->n + w->m + 1;
241
+ memset(w->u, 0, l * sizeof(scs_float));
242
+ memset(w->v, 0, l * sizeof(scs_float));
243
+ w->u[l - 1] = SQRTF((scs_float)l);
244
+ w->v[l - 1] = SQRTF((scs_float)l);
245
+ }
246
+
247
+ /* status < 0 indicates failure */
248
+ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
249
+ /* ut = u + v */
250
+
251
+ scs_int n = w->n, m = w->m, l = n + m + 1, status;
252
+ memcpy(w->u_t, w->u, l * sizeof(scs_float));
253
+ SCS(add_scaled_array)(w->u_t, w->v, l, 1.0);
254
+
255
+ SCS(scale_array)(w->u_t, w->stgs->rho_x, n);
256
+
257
+ SCS(add_scaled_array)(w->u_t, w->h, l - 1, -w->u_t[l - 1]);
258
+ SCS(add_scaled_array)
259
+ (w->u_t, w->h, l - 1, -SCS(dot)(w->u_t, w->g, l - 1) / (w->g_th + 1));
260
+ SCS(scale_array)(&(w->u_t[n]), -1, m);
261
+
262
+ status = SCS(solve_lin_sys)(w->A, w->stgs, w->p, w->u_t, w->u, iter);
263
+
264
+ w->u_t[l - 1] += SCS(dot)(w->u_t, w->h, l - 1);
265
+
266
+ return status;
267
+ }
268
+
269
+ static void update_dual_vars(ScsWork *w) {
270
+ scs_int i, n = w->n, l = n + w->m + 1;
271
+ /* this does not relax 'x' variable */
272
+ for (i = n; i < l; ++i) {
273
+ w->v[i] += (w->u[i] - w->stgs->alpha * w->u_t[i] -
274
+ (1.0 - w->stgs->alpha) * w->u_prev[i]);
275
+ }
276
+ }
277
+
278
+ /* status < 0 indicates failure */
279
+ static scs_int project_cones(ScsWork *w, const ScsCone *k, scs_int iter) {
280
+ scs_int i, n = w->n, l = n + w->m + 1, status;
281
+ /* this does not relax 'x' variable */
282
+ for (i = 0; i < n; ++i) {
283
+ w->u[i] = w->u_t[i] - w->v[i];
284
+ }
285
+ for (i = n; i < l; ++i) {
286
+ w->u[i] = w->stgs->alpha * w->u_t[i] + (1 - w->stgs->alpha) * w->u_prev[i] -
287
+ w->v[i];
288
+ }
289
+ /* u = [x;y;tau] */
290
+ status =
291
+ SCS(proj_dual_cone)(&(w->u[n]), k, w->cone_work, &(w->u_prev[n]), iter);
292
+ if (w->u[l - 1] < 0.0) {
293
+ w->u[l - 1] = 0.0;
294
+ }
295
+
296
+ return status;
297
+ }
298
+
299
+ static scs_int indeterminate(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
300
+ strcpy(info->status, "Indeterminate");
301
+ SCS(scale_array)(sol->x, NAN, w->n);
302
+ SCS(scale_array)(sol->y, NAN, w->m);
303
+ SCS(scale_array)(sol->s, NAN, w->m);
304
+ return SCS_INDETERMINATE;
305
+ }
306
+
307
+ static void sety(ScsWork *w, ScsSolution *sol) {
308
+ if (!sol->y) {
309
+ sol->y = (scs_float *)scs_malloc(sizeof(scs_float) * w->m);
310
+ }
311
+ memcpy(sol->y, &(w->u[w->n]), w->m * sizeof(scs_float));
312
+ }
313
+
314
+ static void sets(ScsWork *w, ScsSolution *sol) {
315
+ if (!sol->s) {
316
+ sol->s = (scs_float *)scs_malloc(sizeof(scs_float) * w->m);
317
+ }
318
+ memcpy(sol->s, &(w->v[w->n]), w->m * sizeof(scs_float));
319
+ }
320
+
321
+ static void setx(ScsWork *w, ScsSolution *sol) {
322
+ if (!sol->x) {
323
+ sol->x = (scs_float *)scs_malloc(sizeof(scs_float) * w->n);
324
+ }
325
+ memcpy(sol->x, w->u, w->n * sizeof(scs_float));
326
+ }
327
+
328
+ static scs_float get_max_residual(ScsResiduals *r) {
329
+ return MAX(r->rel_gap, MAX(r->res_pri, r->res_dual));
330
+ }
331
+
332
+ static void copy_from_best_iterate(ScsWork *w) {
333
+ memcpy(w->u, w->u_best, (w->m + w->n + 1) * sizeof(scs_float));
334
+ memcpy(w->v, w->v_best, (w->m + w->n + 1) * sizeof(scs_float));
335
+ }
336
+
337
+ static scs_int solved(ScsWork *w, ScsSolution *sol, ScsInfo *info,
338
+ ScsResiduals *r, scs_int iter) {
339
+ if (w->best_max_residual < get_max_residual(r)) {
340
+ r->last_iter = -1; /* Forces residual recomputation. */
341
+ copy_from_best_iterate(w);
342
+ calc_residuals(w, r, iter);
343
+ setx(w, sol);
344
+ sety(w, sol);
345
+ sets(w, sol);
346
+ }
347
+ SCS(scale_array)(sol->x, SAFEDIV_POS(1.0, r->tau), w->n);
348
+ SCS(scale_array)(sol->y, SAFEDIV_POS(1.0, r->tau), w->m);
349
+ SCS(scale_array)(sol->s, SAFEDIV_POS(1.0, r->tau), w->m);
350
+ if (info->status_val == 0) {
351
+ strcpy(info->status, "Solved/Inaccurate");
352
+ return SCS_SOLVED_INACCURATE;
353
+ }
354
+ strcpy(info->status, "Solved");
355
+ return SCS_SOLVED;
356
+ }
357
+
358
+ static scs_int infeasible(ScsWork *w, ScsSolution *sol, ScsInfo *info,
359
+ scs_float bt_y) {
360
+ SCS(scale_array)(sol->y, -1 / bt_y, w->m);
361
+ SCS(scale_array)(sol->x, NAN, w->n);
362
+ SCS(scale_array)(sol->s, NAN, w->m);
363
+ if (info->status_val == 0) {
364
+ strcpy(info->status, "Infeasible/Inaccurate");
365
+ return SCS_INFEASIBLE_INACCURATE;
366
+ }
367
+ strcpy(info->status, "Infeasible");
368
+ return SCS_INFEASIBLE;
369
+ }
370
+
371
+ static scs_int unbounded(ScsWork *w, ScsSolution *sol, ScsInfo *info,
372
+ scs_float ct_x) {
373
+ SCS(scale_array)(sol->x, -1 / ct_x, w->n);
374
+ SCS(scale_array)(sol->s, -1 / ct_x, w->m);
375
+ SCS(scale_array)(sol->y, NAN, w->m);
376
+ if (info->status_val == 0) {
377
+ strcpy(info->status, "Unbounded/Inaccurate");
378
+ return SCS_UNBOUNDED_INACCURATE;
379
+ }
380
+ strcpy(info->status, "Unbounded");
381
+ return SCS_UNBOUNDED;
382
+ }
383
+
384
+ static scs_int is_solved_status(scs_int status) {
385
+ return status == SCS_SOLVED || status == SCS_SOLVED_INACCURATE;
386
+ }
387
+
388
+ static scs_int is_infeasible_status(scs_int status) {
389
+ return status == SCS_INFEASIBLE || status == SCS_INFEASIBLE_INACCURATE;
390
+ }
391
+
392
+ static scs_int is_unbounded_status(scs_int status) {
393
+ return status == SCS_UNBOUNDED || status == SCS_UNBOUNDED_INACCURATE;
394
+ }
395
+
396
+ static void get_info(ScsWork *w, ScsSolution *sol, ScsInfo *info,
397
+ ScsResiduals *r, scs_int iter) {
398
+ info->iter = iter;
399
+ info->res_infeas = r->res_infeas;
400
+ info->res_unbdd = r->res_unbdd;
401
+ if (is_solved_status(info->status_val)) {
402
+ info->rel_gap = r->rel_gap;
403
+ info->res_pri = r->res_pri;
404
+ info->res_dual = r->res_dual;
405
+ info->pobj = r->ct_x_by_tau / r->tau;
406
+ info->dobj = -r->bt_y_by_tau / r->tau;
407
+ } else if (is_unbounded_status(info->status_val)) {
408
+ info->rel_gap = NAN;
409
+ info->res_pri = NAN;
410
+ info->res_dual = NAN;
411
+ info->pobj = -INFINITY;
412
+ info->dobj = -INFINITY;
413
+ } else if (is_infeasible_status(info->status_val)) {
414
+ info->rel_gap = NAN;
415
+ info->res_pri = NAN;
416
+ info->res_dual = NAN;
417
+ info->pobj = INFINITY;
418
+ info->dobj = INFINITY;
419
+ }
420
+ }
421
+
422
+ /* sets solutions, re-scales by inner prods if infeasible or unbounded */
423
+ static void get_solution(ScsWork *w, ScsSolution *sol, ScsInfo *info,
424
+ ScsResiduals *r, scs_int iter) {
425
+ scs_int l = w->n + w->m + 1;
426
+ calc_residuals(w, r, iter);
427
+ setx(w, sol);
428
+ sety(w, sol);
429
+ sets(w, sol);
430
+ if (info->status_val == SCS_UNFINISHED) {
431
+ /* not yet converged, take best guess */
432
+ if (r->tau > INDETERMINATE_TOL && r->tau > r->kap) {
433
+ info->status_val = solved(w, sol, info, r, iter);
434
+ } else if (SCS(norm)(w->u, l) < INDETERMINATE_TOL * SQRTF((scs_float)l)) {
435
+ info->status_val = indeterminate(w, sol, info);
436
+ } else if (r->bt_y_by_tau < r->ct_x_by_tau) {
437
+ info->status_val = infeasible(w, sol, info, r->bt_y_by_tau);
438
+ } else {
439
+ info->status_val = unbounded(w, sol, info, r->ct_x_by_tau);
440
+ }
441
+ } else if (is_solved_status(info->status_val)) {
442
+ info->status_val = solved(w, sol, info, r, iter);
443
+ } else if (is_infeasible_status(info->status_val)) {
444
+ info->status_val = infeasible(w, sol, info, r->bt_y_by_tau);
445
+ } else {
446
+ info->status_val = unbounded(w, sol, info, r->ct_x_by_tau);
447
+ }
448
+ if (w->stgs->normalize) {
449
+ SCS(un_normalize_sol)(w, sol);
450
+ }
451
+ get_info(w, sol, info, r, iter);
452
+ }
453
+
454
+ static void print_summary(ScsWork *w, scs_int i, ScsResiduals *r,
455
+ SCS(timer) * solve_timer) {
456
+ scs_printf("%*i|", (int)strlen(HEADER[0]), (int)i);
457
+ scs_printf("%*.2e ", (int)HSPACE, r->res_pri);
458
+ scs_printf("%*.2e ", (int)HSPACE, r->res_dual);
459
+ scs_printf("%*.2e ", (int)HSPACE, r->rel_gap);
460
+ scs_printf("%*.2e ", (int)HSPACE, SAFEDIV_POS(r->ct_x_by_tau, r->tau));
461
+ scs_printf("%*.2e ", (int)HSPACE, SAFEDIV_POS(-r->bt_y_by_tau, r->tau));
462
+ scs_printf("%*.2e ", (int)HSPACE, SAFEDIV_POS(r->kap, r->tau));
463
+ scs_printf("%*.2e ", (int)HSPACE, SCS(tocq)(solve_timer) / 1e3);
464
+ scs_printf("\n");
465
+
466
+ #if EXTRA_VERBOSE > 0
467
+ scs_printf("Norm u = %4f, ", SCS(norm)(w->u, w->n + w->m + 1));
468
+ scs_printf("Norm u_t = %4f, ", SCS(norm)(w->u_t, w->n + w->m + 1));
469
+ scs_printf("Norm v = %4f, ", SCS(norm)(w->v, w->n + w->m + 1));
470
+ scs_printf("tau = %4f, ", w->u[w->n + w->m]);
471
+ scs_printf("kappa = %4f, ", w->v[w->n + w->m]);
472
+ scs_printf("|u - u_prev| = %1.2e, ",
473
+ SCS(norm_diff)(w->u, w->u_prev, w->n + w->m + 1));
474
+ scs_printf("|u - u_t| = %1.2e, ",
475
+ SCS(norm_diff)(w->u, w->u_t, w->n + w->m + 1));
476
+ scs_printf("res_infeas = %1.2e, ", r->res_infeas);
477
+ scs_printf("res_unbdd = %1.2e\n", r->res_unbdd);
478
+ #endif
479
+
480
+ #ifdef MATLAB_MEX_FILE
481
+ mexEvalString("drawnow;");
482
+ #endif
483
+ }
484
+
485
+ static void print_header(ScsWork *w, const ScsCone *k) {
486
+ scs_int i;
487
+ if (w->stgs->warm_start) {
488
+ scs_printf("SCS using variable warm-starting\n");
489
+ }
490
+ for (i = 0; i < LINE_LEN; ++i) {
491
+ scs_printf("-");
492
+ }
493
+ scs_printf("\n");
494
+ for (i = 0; i < HEADER_LEN - 1; ++i) {
495
+ scs_printf("%s|", HEADER[i]);
496
+ }
497
+ scs_printf("%s\n", HEADER[HEADER_LEN - 1]);
498
+ for (i = 0; i < LINE_LEN; ++i) {
499
+ scs_printf("-");
500
+ }
501
+ scs_printf("\n");
502
+ #ifdef MATLAB_MEX_FILE
503
+ mexEvalString("drawnow;");
504
+ #endif
505
+ }
506
+
507
+ static scs_float get_dual_cone_dist(const scs_float *y, const ScsCone *k,
508
+ ScsConeWork *c, scs_int m) {
509
+ scs_float dist;
510
+ scs_float *t = (scs_float *)scs_malloc(sizeof(scs_float) * m);
511
+ memcpy(t, y, m * sizeof(scs_float));
512
+ SCS(proj_dual_cone)(t, k, c, SCS_NULL, -1);
513
+ dist = SCS(norm_inf_diff)(t, y, m);
514
+ #if EXTRA_VERBOSE > 0
515
+ SCS(print_array)(y, m, "y");
516
+ SCS(print_array)(t, m, "proj_y");
517
+ scs_printf("dist = %4f\n", dist);
518
+ #endif
519
+ scs_free(t);
520
+ return dist;
521
+ }
522
+
523
+ /* via moreau */
524
+ static scs_float get_pri_cone_dist(const scs_float *s, const ScsCone *k,
525
+ ScsConeWork *c, scs_int m) {
526
+ scs_float dist;
527
+ scs_float *t = (scs_float *)scs_malloc(sizeof(scs_float) * m);
528
+ memcpy(t, s, m * sizeof(scs_float));
529
+ SCS(scale_array)(t, -1.0, m);
530
+ SCS(proj_dual_cone)(t, k, c, SCS_NULL, -1);
531
+ dist = SCS(norm_inf)(t, m); /* ||s - Pi_c(s)|| = ||Pi_c*(-s)|| */
532
+ #if EXTRA_VERBOSE > 0
533
+ SCS(print_array)(s, m, "s");
534
+ SCS(print_array)(t, m, "(s - proj_s)");
535
+ scs_printf("dist = %4f\n", dist);
536
+ #endif
537
+ scs_free(t);
538
+ return dist;
539
+ }
540
+
541
+ static char *get_accel_summary(ScsInfo *info, scs_float total_accel_time) {
542
+ char *str = (char *)scs_malloc(sizeof(char) * 64);
543
+ sprintf(str, "\tAcceleration: avg step time: %1.2es\n",
544
+ total_accel_time / (info->iter + 1) / 1e3);
545
+ return str;
546
+ }
547
+
548
+ static void print_footer(const ScsData *d, const ScsCone *k, ScsSolution *sol,
549
+ ScsWork *w, ScsInfo *info,
550
+ scs_float total_accel_time) {
551
+ scs_int i;
552
+ char *lin_sys_str = SCS(get_lin_sys_summary)(w->p, info);
553
+ char *cone_str = SCS(get_cone_summary)(info, w->cone_work);
554
+ char *accel_str = get_accel_summary(info, total_accel_time);
555
+ for (i = 0; i < LINE_LEN; ++i) {
556
+ scs_printf("-");
557
+ }
558
+ scs_printf("\nStatus: %s\n", info->status);
559
+ if (info->iter == w->stgs->max_iters) {
560
+ scs_printf(
561
+ "Hit max_iters, solution may be inaccurate, returning best found "
562
+ "solution.\n");
563
+ }
564
+ scs_printf("Timing: Solve time: %1.2es\n", info->solve_time / 1e3);
565
+
566
+ if (lin_sys_str) {
567
+ scs_printf("%s", lin_sys_str);
568
+ scs_free(lin_sys_str);
569
+ }
570
+
571
+ if (cone_str) {
572
+ scs_printf("%s", cone_str);
573
+ scs_free(cone_str);
574
+ }
575
+
576
+ if (accel_str) {
577
+ scs_printf("%s", accel_str);
578
+ scs_free(accel_str);
579
+ }
580
+
581
+ for (i = 0; i < LINE_LEN; ++i) {
582
+ scs_printf("-");
583
+ }
584
+ scs_printf("\n");
585
+
586
+ if (is_infeasible_status(info->status_val)) {
587
+ scs_printf("Certificate of primal infeasibility:\n");
588
+ scs_printf("dist(y, K*) = %.4e\n",
589
+ get_dual_cone_dist(sol->y, k, w->cone_work, d->m));
590
+ scs_printf("|A'y|_2 * |b|_2 = %.4e\n", info->res_infeas);
591
+ scs_printf("b'y = %.4f\n", SCS(dot)(d->b, sol->y, d->m));
592
+ } else if (is_unbounded_status(info->status_val)) {
593
+ scs_printf("Certificate of dual infeasibility:\n");
594
+ scs_printf("dist(s, K) = %.4e\n",
595
+ get_pri_cone_dist(sol->s, k, w->cone_work, d->m));
596
+ scs_printf("|Ax + s|_2 * |c|_2 = %.4e\n", info->res_unbdd);
597
+ scs_printf("c'x = %.4f\n", SCS(dot)(d->c, sol->x, d->n));
598
+ } else {
599
+ scs_printf("Error metrics:\n");
600
+ scs_printf("dist(s, K) = %.4e, dist(y, K*) = %.4e, s'y/|s||y| = %.4e\n",
601
+ get_pri_cone_dist(sol->s, k, w->cone_work, d->m),
602
+ get_dual_cone_dist(sol->y, k, w->cone_work, d->m),
603
+ SCS(dot)(sol->s, sol->y, d->m) / SCS(norm)(sol->s, d->m) /
604
+ SCS(norm)(sol->y, d->m));
605
+ scs_printf("primal res: |Ax + s - b|_2 / (1 + |b|_2) = %.4e\n",
606
+ info->res_pri);
607
+ scs_printf("dual res: |A'y + c|_2 / (1 + |c|_2) = %.4e\n",
608
+ info->res_dual);
609
+ scs_printf("rel gap: |c'x + b'y| / (1 + |c'x| + |b'y|) = %.4e\n",
610
+ info->rel_gap);
611
+ for (i = 0; i < LINE_LEN; ++i) {
612
+ scs_printf("-");
613
+ }
614
+ scs_printf("\n");
615
+ scs_printf("c'x = %.4f, -b'y = %.4f\n", info->pobj, info->dobj);
616
+ }
617
+ for (i = 0; i < LINE_LEN; ++i) {
618
+ scs_printf("=");
619
+ }
620
+ scs_printf("\n");
621
+ #ifdef MATLAB_MEX_FILE
622
+ mexEvalString("drawnow;");
623
+ #endif
624
+ }
625
+
626
+ static scs_int has_converged(ScsWork *w, ScsResiduals *r, scs_int iter) {
627
+ scs_float eps = w->stgs->eps;
628
+ if (isless(r->res_pri, eps) && isless(r->res_dual, eps) &&
629
+ isless(r->rel_gap, eps)) {
630
+ return SCS_SOLVED;
631
+ }
632
+ /* Add iter > 0 to avoid strange edge case where infeasible point found
633
+ * right at start of run `out/demo_SOCP_indirect 2 0.1 0.3 1506264403` */
634
+ if (isless(r->res_unbdd, eps) && iter > 0) {
635
+ return SCS_UNBOUNDED;
636
+ }
637
+ if (isless(r->res_infeas, eps) && iter > 0) {
638
+ return SCS_INFEASIBLE;
639
+ }
640
+ return 0;
641
+ }
642
+
643
+ static scs_int validate(const ScsData *d, const ScsCone *k) {
644
+ ScsSettings *stgs = d->stgs;
645
+ if (d->m <= 0 || d->n <= 0) {
646
+ scs_printf("m and n must both be greater than 0; m = %li, n = %li\n",
647
+ (long)d->m, (long)d->n);
648
+ return -1;
649
+ }
650
+ if (d->m < d->n) {
651
+ scs_printf("WARN: m less than n, problem likely degenerate\n");
652
+ /* return -1; */
653
+ }
654
+ if (SCS(validate_lin_sys)(d->A) < 0) {
655
+ scs_printf("invalid linear system input data\n");
656
+ return -1;
657
+ }
658
+ if (SCS(validate_cones)(d, k) < 0) {
659
+ scs_printf("cone validation error\n");
660
+ return -1;
661
+ }
662
+ if (stgs->max_iters <= 0) {
663
+ scs_printf("max_iters must be positive\n");
664
+ return -1;
665
+ }
666
+ if (stgs->eps <= 0) {
667
+ scs_printf("eps tolerance must be positive\n");
668
+ return -1;
669
+ }
670
+ if (stgs->alpha <= 0 || stgs->alpha >= 2) {
671
+ scs_printf("alpha must be in (0,2)\n");
672
+ return -1;
673
+ }
674
+ if (stgs->rho_x <= 0) {
675
+ scs_printf("rho_x must be positive (1e-3 works well).\n");
676
+ return -1;
677
+ }
678
+ if (stgs->scale <= 0) {
679
+ scs_printf("scale must be positive (1 works well).\n");
680
+ return -1;
681
+ }
682
+ return 0;
683
+ }
684
+
685
+ static ScsWork *init_work(const ScsData *d, const ScsCone *k) {
686
+ ScsWork *w = (ScsWork *)scs_calloc(1, sizeof(ScsWork));
687
+ scs_int l = d->n + d->m + 1;
688
+ if (d->stgs->verbose) {
689
+ print_init_header(d, k);
690
+ }
691
+ if (!w) {
692
+ scs_printf("ERROR: allocating work failure\n");
693
+ return SCS_NULL;
694
+ }
695
+ /* get settings and dims from data struct */
696
+ w->stgs = d->stgs;
697
+ w->m = d->m;
698
+ w->n = d->n;
699
+ w->best_max_residual = INFINITY;
700
+ /* allocate workspace: */
701
+ /* u* include v* values */
702
+ w->u = (scs_float *)scs_malloc(2 * l * sizeof(scs_float));
703
+ w->u_best = (scs_float *)scs_malloc(2 * l * sizeof(scs_float));
704
+ w->u_t = (scs_float *)scs_malloc(l * sizeof(scs_float));
705
+ w->u_prev = (scs_float *)scs_malloc(2 * l * sizeof(scs_float));
706
+ w->h = (scs_float *)scs_malloc((l - 1) * sizeof(scs_float));
707
+ w->g = (scs_float *)scs_malloc((l - 1) * sizeof(scs_float));
708
+ w->pr = (scs_float *)scs_malloc(d->m * sizeof(scs_float));
709
+ w->dr = (scs_float *)scs_malloc(d->n * sizeof(scs_float));
710
+ w->b = (scs_float *)scs_malloc(d->m * sizeof(scs_float));
711
+ w->c = (scs_float *)scs_malloc(d->n * sizeof(scs_float));
712
+ if (!w->u || !w->u_t || !w->u_prev || !w->h || !w->g || !w->pr || !w->dr ||
713
+ !w->b || !w->c) {
714
+ scs_printf("ERROR: work memory allocation failure\n");
715
+ return SCS_NULL;
716
+ }
717
+ /* make u,v and u_prev,v_prev contiguous in memory */
718
+ w->v = &(w->u[l]);
719
+ w->v_best = &(w->u_best[l]);
720
+ w->v_prev = &(w->u_prev[l]);
721
+ w->A = d->A;
722
+ if (w->stgs->normalize) {
723
+ #ifdef COPYAMATRIX
724
+ if (!SCS(copy_a_matrix)(&(w->A), d->A)) {
725
+ scs_printf("ERROR: copy A matrix failed\n");
726
+ return SCS_NULL;
727
+ }
728
+ #endif
729
+ w->scal = (ScsScaling *)scs_malloc(sizeof(ScsScaling));
730
+ SCS(normalize_a)(w->A, w->stgs, k, w->scal);
731
+ #if EXTRA_VERBOSE > 0
732
+ SCS(print_array)(w->scal->D, d->m, "D");
733
+ scs_printf("SCS(norm) D = %4f\n", SCS(norm)(w->scal->D, d->m));
734
+ SCS(print_array)(w->scal->E, d->n, "E");
735
+ scs_printf("SCS(norm) E = %4f\n", SCS(norm)(w->scal->E, d->n));
736
+ #endif
737
+ } else {
738
+ w->scal = SCS_NULL;
739
+ }
740
+ if (!(w->cone_work = SCS(init_cone)(k))) {
741
+ scs_printf("ERROR: init_cone failure\n");
742
+ return SCS_NULL;
743
+ }
744
+ if (!(w->p = SCS(init_lin_sys_work)(w->A, w->stgs))) {
745
+ scs_printf("ERROR: init_lin_sys_work failure\n");
746
+ return SCS_NULL;
747
+ }
748
+ if (!(w->accel =
749
+ aa_init(2 * (w->m + w->n + 1), ABS(w->stgs->acceleration_lookback),
750
+ w->stgs->acceleration_lookback >= 0))) {
751
+ if (w->stgs->verbose) {
752
+ scs_printf("WARN: aa_init returned NULL, no acceleration applied.\n");
753
+ }
754
+ }
755
+ return w;
756
+ }
757
+
758
+ static scs_int update_work(const ScsData *d, ScsWork *w,
759
+ const ScsSolution *sol) {
760
+ /* before normalization */
761
+ scs_int n = d->n;
762
+ scs_int m = d->m;
763
+
764
+ w->nm_b = SCS(norm)(d->b, m);
765
+ w->nm_c = SCS(norm)(d->c, n);
766
+ memcpy(w->b, d->b, d->m * sizeof(scs_float));
767
+ memcpy(w->c, d->c, d->n * sizeof(scs_float));
768
+
769
+ #if EXTRA_VERBOSE > 0
770
+ SCS(print_array)(w->b, m, "b");
771
+ scs_printf("pre-normalized norm b = %4f\n", SCS(norm)(w->b, m));
772
+ SCS(print_array)(w->c, n, "c");
773
+ scs_printf("pre-normalized norm c = %4f\n", SCS(norm)(w->c, n));
774
+ #endif
775
+ if (w->stgs->normalize) {
776
+ SCS(normalize_b_c)(w);
777
+ #if EXTRA_VERBOSE > 0
778
+ SCS(print_array)(w->b, m, "bn");
779
+ scs_printf("sc_b = %4f\n", w->sc_b);
780
+ scs_printf("post-normalized norm b = %4f\n", SCS(norm)(w->b, m));
781
+ SCS(print_array)(w->c, n, "cn");
782
+ scs_printf("sc_c = %4f\n", w->sc_c);
783
+ scs_printf("post-normalized norm c = %4f\n", SCS(norm)(w->c, n));
784
+ #endif
785
+ }
786
+ if (w->stgs->warm_start) {
787
+ warm_start_vars(w, sol);
788
+ } else {
789
+ cold_start_vars(w);
790
+ }
791
+ memcpy(w->h, w->c, n * sizeof(scs_float));
792
+ memcpy(&(w->h[n]), w->b, m * sizeof(scs_float));
793
+ memcpy(w->g, w->h, (n + m) * sizeof(scs_float));
794
+ SCS(solve_lin_sys)(w->A, w->stgs, w->p, w->g, SCS_NULL, -1);
795
+ SCS(scale_array)(&(w->g[n]), -1, m);
796
+ w->g_th = SCS(dot)(w->h, w->g, n + m);
797
+ return 0;
798
+ }
799
+
800
+ static scs_float iterate_norm_diff(ScsWork *w) {
801
+ scs_int l = w->m + w->n + 1;
802
+ scs_float u_norm_difference = SCS(norm_diff)(w->u, w->u_prev, l);
803
+ scs_float v_norm_difference = SCS(norm_diff)(w->v, w->v_prev, l);
804
+ scs_float norm = SQRTF(SCS(norm_sq)(w->u, l) + SCS(norm_sq)(w->v, l));
805
+ scs_float norm_diff = SQRTF(u_norm_difference * u_norm_difference +
806
+ v_norm_difference * v_norm_difference);
807
+ return norm_diff / norm;
808
+ }
809
+
810
+ static void update_best_iterate(ScsWork *w, ScsResiduals *r) {
811
+ scs_float max_residual = get_max_residual(r);
812
+ if (w->best_max_residual > max_residual) {
813
+ w->best_max_residual = max_residual;
814
+ memcpy(w->u_best, w->u, (w->m + w->n + 1) * sizeof(scs_float));
815
+ memcpy(w->v_best, w->v, (w->m + w->n + 1) * sizeof(scs_float));
816
+ }
817
+ }
818
+
819
+ scs_int SCS(solve)(ScsWork *w, const ScsData *d, const ScsCone *k,
820
+ ScsSolution *sol, ScsInfo *info) {
821
+ scs_int i;
822
+ SCS(timer) solve_timer, accel_timer;
823
+ scs_float total_accel_time = 0.0, total_norm;
824
+ ScsResiduals r;
825
+ scs_int l = w->m + w->n + 1;
826
+ if (!d || !k || !sol || !info || !w || !d->b || !d->c) {
827
+ scs_printf("ERROR: SCS_NULL input\n");
828
+ return SCS_FAILED;
829
+ }
830
+ /* initialize ctrl-c support */
831
+ scs_start_interrupt_listener();
832
+ SCS(tic)(&solve_timer);
833
+ info->status_val = SCS_UNFINISHED; /* not yet converged */
834
+ r.last_iter = -1;
835
+ update_work(d, w, sol);
836
+
837
+ if (w->stgs->verbose) {
838
+ print_header(w, k);
839
+ }
840
+ /* scs: */
841
+ for (i = 0; i < w->stgs->max_iters; ++i) {
842
+ /* accelerate here so that last step always projection onto cone */
843
+ /* this ensures the returned iterates always satisfy conic constraints */
844
+ /* this relies on the fact that u and v are contiguous in memory */
845
+ SCS(tic)(&accel_timer);
846
+ if (i > 0 && aa_apply(w->u, w->u_prev, w->accel) != 0) {
847
+ /*
848
+ return failure(w, w->m, w->n, sol, info, SCS_FAILED,
849
+ "error in accelerate", "Failure");
850
+ */
851
+ }
852
+ total_accel_time += SCS(tocq)(&accel_timer);
853
+
854
+ /* scs is homogeneous so scale the iterates to keep norm reasonable */
855
+ total_norm = SQRTF(SCS(norm_sq)(w->u, l) + SCS(norm_sq)(w->v, l));
856
+ SCS(scale_array)(w->u, SQRTF((scs_float)l) * ITERATE_NORM / total_norm, l);
857
+ SCS(scale_array)(w->v, SQRTF((scs_float)l) * ITERATE_NORM / total_norm, l);
858
+
859
+ memcpy(w->u_prev, w->u, l * sizeof(scs_float));
860
+ memcpy(w->v_prev, w->v, l * sizeof(scs_float));
861
+
862
+ if (project_lin_sys(w, i) < 0) {
863
+ return failure(w, w->m, w->n, sol, info, SCS_FAILED,
864
+ "error in project_lin_sys", "Failure");
865
+ }
866
+ if (project_cones(w, k, i) < 0) {
867
+ return failure(w, w->m, w->n, sol, info, SCS_FAILED,
868
+ "error in project_cones", "Failure");
869
+ }
870
+
871
+ update_dual_vars(w);
872
+
873
+ if (scs_is_interrupted()) {
874
+ return failure(w, w->m, w->n, sol, info, SCS_SIGINT, "Interrupted",
875
+ "Interrupted");
876
+ }
877
+ if (i % CONVERGED_INTERVAL == 0 || iterate_norm_diff(w) < 1e-10) {
878
+ calc_residuals(w, &r, i);
879
+ if ((info->status_val = has_converged(w, &r, i)) != 0) {
880
+ break;
881
+ }
882
+ update_best_iterate(w, &r);
883
+ }
884
+
885
+ if (w->stgs->verbose && i % PRINT_INTERVAL == 0) {
886
+ calc_residuals(w, &r, i);
887
+ update_best_iterate(w, &r);
888
+ print_summary(w, i, &r, &solve_timer);
889
+ }
890
+ }
891
+ if (w->stgs->verbose) {
892
+ calc_residuals(w, &r, i);
893
+ print_summary(w, i, &r, &solve_timer);
894
+ }
895
+ /* populate solution vectors (unnormalized) and info */
896
+ get_solution(w, sol, info, &r, i);
897
+ info->solve_time = SCS(tocq)(&solve_timer);
898
+
899
+ if (w->stgs->verbose) {
900
+ print_footer(d, k, sol, w, info, total_accel_time);
901
+ }
902
+ scs_end_interrupt_listener();
903
+ return info->status_val;
904
+ }
905
+
906
+ void SCS(finish)(ScsWork *w) {
907
+ if (w) {
908
+ SCS(finish_cone)(w->cone_work);
909
+ if (w->stgs && w->stgs->normalize) {
910
+ #ifndef COPYAMATRIX
911
+ SCS(un_normalize_a)(w->A, w->stgs, w->scal);
912
+ #else
913
+ SCS(free_a_matrix)(w->A);
914
+ #endif
915
+ }
916
+ if (w->p) {
917
+ SCS(free_lin_sys_work)(w->p);
918
+ }
919
+ if (w->accel) {
920
+ aa_finish(w->accel);
921
+ }
922
+ free_work(w);
923
+ }
924
+ }
925
+
926
+ ScsWork *SCS(init)(const ScsData *d, const ScsCone *k, ScsInfo *info) {
927
+ #if EXTRA_VERBOSE > 1
928
+ SCS(tic)(&global_timer);
929
+ #endif
930
+ ScsWork *w;
931
+ SCS(timer) init_timer;
932
+ scs_start_interrupt_listener();
933
+ if (!d || !k || !info) {
934
+ scs_printf("ERROR: Missing ScsData, ScsCone or ScsInfo input\n");
935
+ return SCS_NULL;
936
+ }
937
+ #if EXTRA_VERBOSE > 0
938
+ SCS(print_data)(d);
939
+ SCS(print_cone_data)(k);
940
+ #endif
941
+ #ifndef NOVALIDATE
942
+ if (validate(d, k) < 0) {
943
+ scs_printf("ERROR: Validation returned failure\n");
944
+ return SCS_NULL;
945
+ }
946
+ #endif
947
+ SCS(tic)(&init_timer);
948
+ if (d->stgs->write_data_filename) {
949
+ SCS(write_data)(d, k);
950
+ }
951
+ w = init_work(d, k);
952
+ info->setup_time = SCS(tocq)(&init_timer);
953
+ if (d->stgs->verbose) {
954
+ scs_printf("Setup time: %1.2es\n", info->setup_time / 1e3);
955
+ }
956
+ scs_end_interrupt_listener();
957
+ return w;
958
+ }
959
+
960
+ /* this just calls SCS(init), SCS(solve), and SCS(finish) */
961
+ scs_int scs(const ScsData *d, const ScsCone *k, ScsSolution *sol,
962
+ ScsInfo *info) {
963
+ scs_int status;
964
+ ScsWork *w = SCS(init)(d, k, info);
965
+ #if EXTRA_VERBOSE > 0
966
+ scs_printf("size of scs_int = %lu, size of scs_float = %lu\n",
967
+ sizeof(scs_int), sizeof(scs_float));
968
+ #endif
969
+ if (w) {
970
+ SCS(solve)(w, d, k, sol, info);
971
+ status = info->status_val;
972
+ } else {
973
+ status = failure(SCS_NULL, d ? d->m : -1, d ? d->n : -1, sol, info,
974
+ SCS_FAILED, "could not initialize work", "Failure");
975
+ }
976
+ SCS(finish)(w);
977
+ return status;
978
+ }