scs 0.2.2 → 0.3.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/LICENSE.txt +18 -18
  4. data/README.md +19 -14
  5. data/lib/scs/ffi.rb +31 -20
  6. data/lib/scs/solver.rb +32 -9
  7. data/lib/scs/version.rb +1 -1
  8. data/vendor/scs/CITATION.cff +39 -0
  9. data/vendor/scs/CMakeLists.txt +320 -0
  10. data/vendor/scs/Makefile +32 -23
  11. data/vendor/scs/README.md +9 -218
  12. data/vendor/scs/include/aa.h +67 -23
  13. data/vendor/scs/include/cones.h +22 -19
  14. data/vendor/scs/include/glbopts.h +107 -79
  15. data/vendor/scs/include/linalg.h +3 -4
  16. data/vendor/scs/include/linsys.h +58 -44
  17. data/vendor/scs/include/normalize.h +6 -5
  18. data/vendor/scs/include/rw.h +8 -2
  19. data/vendor/scs/include/scs.h +257 -141
  20. data/vendor/scs/include/scs_types.h +34 -0
  21. data/vendor/scs/include/scs_work.h +83 -0
  22. data/vendor/scs/include/util.h +3 -15
  23. data/vendor/scs/linsys/cpu/direct/private.c +241 -232
  24. data/vendor/scs/linsys/cpu/direct/private.h +13 -7
  25. data/vendor/scs/linsys/cpu/indirect/private.c +194 -118
  26. data/vendor/scs/linsys/cpu/indirect/private.h +7 -4
  27. data/vendor/scs/linsys/csparse.c +87 -0
  28. data/vendor/scs/linsys/csparse.h +34 -0
  29. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
  30. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
  31. data/vendor/scs/linsys/external/amd/amd_internal.h +1 -1
  32. data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
  33. data/vendor/scs/linsys/external/qdldl/changes +2 -0
  34. data/vendor/scs/linsys/external/qdldl/qdldl.c +29 -46
  35. data/vendor/scs/linsys/external/qdldl/qdldl.h +33 -41
  36. data/vendor/scs/linsys/external/qdldl/qdldl_types.h +11 -3
  37. data/vendor/scs/linsys/gpu/gpu.c +58 -21
  38. data/vendor/scs/linsys/gpu/gpu.h +70 -35
  39. data/vendor/scs/linsys/gpu/indirect/private.c +394 -157
  40. data/vendor/scs/linsys/gpu/indirect/private.h +27 -12
  41. data/vendor/scs/linsys/scs_matrix.c +478 -0
  42. data/vendor/scs/linsys/scs_matrix.h +70 -0
  43. data/vendor/scs/scs.mk +14 -10
  44. data/vendor/scs/src/aa.c +394 -110
  45. data/vendor/scs/src/cones.c +497 -359
  46. data/vendor/scs/src/ctrlc.c +15 -5
  47. data/vendor/scs/src/linalg.c +107 -26
  48. data/vendor/scs/src/normalize.c +30 -72
  49. data/vendor/scs/src/rw.c +202 -27
  50. data/vendor/scs/src/scs.c +769 -571
  51. data/vendor/scs/src/scs_version.c +11 -3
  52. data/vendor/scs/src/util.c +37 -106
  53. data/vendor/scs/test/minunit.h +22 -8
  54. data/vendor/scs/test/problem_utils.h +180 -25
  55. data/vendor/scs/test/problems/degenerate.h +130 -0
  56. data/vendor/scs/test/problems/hs21_tiny_qp.h +124 -0
  57. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +116 -0
  58. data/vendor/scs/test/problems/infeasible_tiny_qp.h +100 -0
  59. data/vendor/scs/test/problems/qafiro_tiny_qp.h +199 -0
  60. data/vendor/scs/test/problems/random_prob +0 -0
  61. data/vendor/scs/test/problems/random_prob.h +45 -0
  62. data/vendor/scs/test/problems/rob_gauss_cov_est.h +188 -31
  63. data/vendor/scs/test/problems/small_lp.h +14 -13
  64. data/vendor/scs/test/problems/small_qp.h +352 -0
  65. data/vendor/scs/test/problems/test_validation.h +43 -0
  66. data/vendor/scs/test/problems/unbounded_tiny_qp.h +82 -0
  67. data/vendor/scs/test/random_socp_prob.c +54 -53
  68. data/vendor/scs/test/rng.h +109 -0
  69. data/vendor/scs/test/run_from_file.c +20 -11
  70. data/vendor/scs/test/run_tests.c +35 -2
  71. metadata +29 -98
  72. data/vendor/scs/linsys/amatrix.c +0 -305
  73. data/vendor/scs/linsys/amatrix.h +0 -36
  74. data/vendor/scs/linsys/amatrix.o +0 -0
  75. data/vendor/scs/linsys/cpu/direct/private.o +0 -0
  76. data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
  77. data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
  78. data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
  79. data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
  80. data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
  81. data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
  82. data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
  83. data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
  84. data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
  85. data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
  86. data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
  87. data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
  88. data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
  89. data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
  90. data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
  91. data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
  92. data/vendor/scs/src/aa.o +0 -0
  93. data/vendor/scs/src/cones.o +0 -0
  94. data/vendor/scs/src/ctrlc.o +0 -0
  95. data/vendor/scs/src/linalg.o +0 -0
  96. data/vendor/scs/src/normalize.o +0 -0
  97. data/vendor/scs/src/rw.o +0 -0
  98. data/vendor/scs/src/scs.o +0 -0
  99. data/vendor/scs/src/scs_version.o +0 -0
  100. data/vendor/scs/src/util.o +0 -0
  101. data/vendor/scs/test/data/small_random_socp +0 -0
  102. data/vendor/scs/test/problems/small_random_socp.h +0 -33
  103. data/vendor/scs/test/run_tests +0 -2
@@ -1,5 +1,13 @@
1
+ #ifdef __cplusplus
2
+ extern "C" {
3
+ #endif
4
+
1
5
  #include "glbopts.h"
2
6
 
3
- const char *SCS(version)(void) { return SCS_VERSION; }
4
- size_t SCS(sizeof_int)(void) { return sizeof(scs_int); }
5
- size_t SCS(sizeof_float)(void) { return sizeof(scs_float); }
7
+ const char *scs_version(void) {
8
+ return SCS_VERSION;
9
+ }
10
+
11
+ #ifdef __cplusplus
12
+ }
13
+ #endif
@@ -2,12 +2,16 @@
2
2
 
3
3
  #include "glbopts.h"
4
4
  #include "linsys.h"
5
+ #include "scs_matrix.h"
5
6
 
6
7
  /* return milli-seconds */
7
8
  #if (defined NOTIMER)
8
9
 
9
- void SCS(tic)(SCS(timer) * t) {}
10
- scs_float SCS(tocq)(SCS(timer) * t) { return NAN; }
10
+ void SCS(tic)(SCS(timer) * t) {
11
+ }
12
+ scs_float SCS(tocq)(SCS(timer) * t) {
13
+ return NAN;
14
+ }
11
15
 
12
16
  #elif (defined _WIN32 || _WIN64 || defined _WINDLL)
13
17
 
@@ -46,7 +50,9 @@ scs_float SCS(tocq)(SCS(timer) * t) {
46
50
 
47
51
  #else
48
52
 
49
- void SCS(tic)(SCS(timer) * t) { clock_gettime(CLOCK_MONOTONIC, &t->tic); }
53
+ void SCS(tic)(SCS(timer) * t) {
54
+ clock_gettime(CLOCK_MONOTONIC, &t->tic);
55
+ }
50
56
 
51
57
  scs_float SCS(tocq)(SCS(timer) * t) {
52
58
  struct timespec temp;
@@ -65,109 +71,29 @@ scs_float SCS(tocq)(SCS(timer) * t) {
65
71
 
66
72
  #endif
67
73
 
68
- scs_float SCS(toc)(SCS(timer) * t) {
69
- scs_float time = SCS(tocq)(t);
70
- scs_printf("time: %8.4f milli-seconds.\n", time);
71
- return time;
72
- }
73
-
74
- scs_float SCS(str_toc)(char *str, SCS(timer) * t) {
75
- scs_float time = SCS(tocq)(t);
76
- scs_printf("%s - time: %8.4f milli-seconds.\n", str, time);
77
- return time;
78
- }
79
-
80
- void SCS(print_cone_data)(const ScsCone *k) {
81
- scs_int i;
82
- scs_printf("num zeros = %i\n", (int)k->f);
83
- scs_printf("num LP = %i\n", (int)k->l);
84
- scs_printf("num SOCs = %i\n", (int)k->qsize);
85
- scs_printf("soc array:\n");
86
- for (i = 0; i < k->qsize; i++) {
87
- scs_printf("%i\n", (int)k->q[i]);
88
- }
89
- scs_printf("num SDCs = %i\n", (int)k->ssize);
90
- scs_printf("sdc array:\n");
91
- for (i = 0; i < k->ssize; i++) {
92
- scs_printf("%i\n", (int)k->s[i]);
93
- }
94
- scs_printf("num ep = %i\n", (int)k->ep);
95
- scs_printf("num ed = %i\n", (int)k->ed);
96
- scs_printf("num PCs = %i\n", (int)k->psize);
97
- scs_printf("pow array:\n");
98
- for (i = 0; i < k->psize; i++) {
99
- scs_printf("%4f\n", (double)k->p[i]);
100
- }
101
- }
102
-
103
- void SCS(print_work)(const ScsWork *w) {
104
- scs_int i, l = w->n + w->m;
105
- scs_printf("\n u_t is \n");
106
- for (i = 0; i < l; i++) {
107
- scs_printf("%f\n", w->u_t[i]);
108
- }
109
- scs_printf("\n u is \n");
110
- for (i = 0; i < l; i++) {
111
- scs_printf("%f\n", w->u[i]);
112
- }
113
- scs_printf("\n v is \n");
114
- for (i = 0; i < l; i++) {
115
- scs_printf("%f\n", w->v[i]);
116
- }
117
- }
118
-
119
- void SCS(print_data)(const ScsData *d) {
120
- scs_printf("m = %i\n", (int)d->m);
121
- scs_printf("n = %i\n", (int)d->n);
122
-
123
- scs_printf("max_iters = %i\n", (int)d->stgs->max_iters);
124
- scs_printf("verbose = %i\n", (int)d->stgs->verbose);
125
- scs_printf("normalize = %i\n", (int)d->stgs->normalize);
126
- scs_printf("warm_start = %i\n", (int)d->stgs->warm_start);
127
- scs_printf("acceleration_lookback = %i\n",
128
- (int)d->stgs->acceleration_lookback);
129
- scs_printf("eps = %4f\n", d->stgs->eps);
130
- scs_printf("alpha = %4f\n", d->stgs->alpha);
131
- scs_printf("rho_x = %4f\n", d->stgs->rho_x);
132
- scs_printf("cg_rate = %4f\n", d->stgs->cg_rate);
133
- scs_printf("scale = %4f\n", d->stgs->scale);
134
- scs_printf("write_data_filename = %s\n",
135
- (char *)d->stgs->write_data_filename);
136
- }
137
-
138
- void SCS(print_array)(const scs_float *arr, scs_int n, const char *name) {
139
- scs_int i, j, k = 0;
140
- scs_int num_on_one_line = 10;
141
- scs_printf("\n");
142
- for (i = 0; i < n / num_on_one_line; ++i) {
143
- for (j = 0; j < num_on_one_line; ++j) {
144
- scs_printf("%s[%li] = %4f, ", name, (long)k, arr[k]);
145
- k++;
146
- }
147
- scs_printf("\n");
148
- }
149
- for (j = k; j < n; ++j) {
150
- scs_printf("%s[%li] = %4f, ", name, (long)j, arr[j]);
151
- }
152
- scs_printf("\n");
153
- }
154
-
155
- void SCS(free_data)(ScsData *d, ScsCone *k) {
74
+ void SCS(free_data)(ScsData *d, ScsCone *k, ScsSettings *stgs) {
156
75
  if (d) {
157
76
  scs_free(d->b);
158
77
  scs_free(d->c);
159
- scs_free(d->stgs);
160
78
  if (d->A) {
161
- SCS(free_a_matrix)(d->A);
79
+ SCS(free_scs_matrix)(d->A);
80
+ }
81
+ if (d->P) {
82
+ SCS(free_scs_matrix)(d->P);
162
83
  }
163
84
  scs_free(d);
164
85
  }
165
86
  if (k) {
87
+ scs_free(k->bu);
88
+ scs_free(k->bl);
166
89
  scs_free(k->q);
167
90
  scs_free(k->s);
168
91
  scs_free(k->p);
169
92
  scs_free(k);
170
93
  }
94
+ if (stgs) {
95
+ scs_free(stgs);
96
+ }
171
97
  }
172
98
 
173
99
  void SCS(free_sol)(ScsSolution *sol) {
@@ -179,18 +105,23 @@ void SCS(free_sol)(ScsSolution *sol) {
179
105
  }
180
106
  }
181
107
 
182
- /* assumes d->stgs already allocated memory */
183
- void SCS(set_default_settings)(ScsData *d) {
108
+ /* assumes stgs already allocated memory */
109
+ void scs_set_default_settings(ScsSettings *stgs) {
184
110
  /* These constants are defined in include/glbopts.h */
185
- d->stgs->max_iters = MAX_ITERS;
186
- d->stgs->eps = EPS;
187
- d->stgs->alpha = ALPHA;
188
- d->stgs->rho_x = RHO_X;
189
- d->stgs->scale = SCALE;
190
- d->stgs->cg_rate = CG_RATE;
191
- d->stgs->verbose = VERBOSE;
192
- d->stgs->normalize = NORMALIZE;
193
- d->stgs->warm_start = WARM_START;
194
- d->stgs->acceleration_lookback = ACCELERATION_LOOKBACK;
195
- d->stgs->write_data_filename = WRITE_DATA_FILENAME;
111
+ stgs->max_iters = MAX_ITERS;
112
+ stgs->eps_abs = EPS_ABS;
113
+ stgs->eps_rel = EPS_REL;
114
+ stgs->eps_infeas = EPS_INFEAS;
115
+ stgs->alpha = ALPHA;
116
+ stgs->rho_x = RHO_X;
117
+ stgs->scale = SCALE;
118
+ stgs->verbose = VERBOSE;
119
+ stgs->normalize = NORMALIZE;
120
+ stgs->warm_start = WARM_START;
121
+ stgs->acceleration_lookback = ACCELERATION_LOOKBACK;
122
+ stgs->acceleration_interval = ACCELERATION_INTERVAL;
123
+ stgs->adaptive_scale = ADAPTIVE_SCALE;
124
+ stgs->write_data_filename = WRITE_DATA_FILENAME;
125
+ stgs->log_csv_filename = LOG_CSV_FILENAME;
126
+ stgs->time_limit_secs = TIME_LIMIT_SECS;
196
127
  }
@@ -1,13 +1,27 @@
1
1
  /* Taken from http://www.jera.com/techinfo/jtns/jtn002.html */
2
2
 
3
3
  /* Simple Macros for testing */
4
- #define mu_assert(message, test) \
5
- do { \
6
- if (!(test)) return message; \
4
+ #define mu_assert_less(message, a, b) \
5
+ do { \
6
+ if (a > b) { \
7
+ scs_printf("%s: %1.3e > %1.3e\n", message, a, b); \
8
+ return message; \
9
+ } \
7
10
  } while (0)
8
- #define mu_run_test(test) \
9
- do { \
10
- const char *message = test(); \
11
- tests_run++; \
12
- if (message) return message; \
11
+ #define mu_assert(message, test) \
12
+ do { \
13
+ if (!(test)) \
14
+ return message; \
15
+ } while (0)
16
+ #define mu_run_test(test) _mu_run_test(#test, test)
17
+
18
+ #define _mu_run_test(name, test) \
19
+ do { \
20
+ scs_printf("*********************************************************\n"); \
21
+ scs_printf("Running test: %s\n", name); \
22
+ const char *message = test(); \
23
+ tests_run++; \
24
+ scs_printf("*********************************************************\n"); \
25
+ if (message) \
26
+ return message; \
13
27
  } while (0)
@@ -1,34 +1,24 @@
1
1
  #ifndef PUTILS_H_GUARD
2
2
  #define PUTILS_H_GUARD
3
3
 
4
- #include "amatrix.h"
5
4
  #include "cones.h"
6
5
  #include "linalg.h"
6
+ #include "linsys.h"
7
+ #include "minunit.h"
8
+ #include "rng.h"
7
9
  #include "scs.h"
10
+ #include "scs_matrix.h"
8
11
  #include "util.h"
9
12
 
10
- #define PI (3.141592654)
11
- #ifdef DLONG
12
- #ifdef _WIN64
13
- /* this is a Microsoft extension, but also works with min_g_w-w64 */
14
- #define INTRW "%I64d"
15
- #else
16
- #define INTRW "%ld"
17
- #endif
18
- #else
19
- #define INTRW "%i"
20
- #endif
21
-
22
- void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
23
- ScsSolution *opt_sol);
13
+ #define _MAX_RAND_VAL (1073741823) /* 2^30 - 1 */
24
14
 
25
15
  /* uniform random number in [-1,1] */
26
16
  static scs_float rand_scs_float(void) {
27
- return 2 * (((scs_float)rand()) / RAND_MAX) - 1;
17
+ return 2 * (((scs_float)ran_arr_next()) / _MAX_RAND_VAL) - 1; /* in [-1, 1] */
28
18
  }
29
19
 
30
20
  void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
31
- ScsSolution *opt_sol) {
21
+ ScsSolution *opt_sol, scs_int seed) {
32
22
  scs_int n = d->n;
33
23
  scs_int m = d->m;
34
24
  ScsMatrix *A = d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
@@ -39,6 +29,7 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
39
29
  scs_float *s = opt_sol->s = (scs_float *)scs_calloc(m, sizeof(scs_float));
40
30
  /* temporary variables */
41
31
  scs_float *z = (scs_float *)scs_calloc(m, sizeof(scs_float));
32
+ ScsConeWork *tmp_cone_work;
42
33
  scs_int i, j, r, rn, rm;
43
34
 
44
35
  A->i = (scs_int *)scs_calloc(nnz, sizeof(scs_int));
@@ -50,8 +41,9 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
50
41
  for (i = 0; i < m; i++) {
51
42
  y[i] = z[i] = rand_scs_float();
52
43
  }
53
-
54
- SCS(proj_dual_cone)(y, k, SCS_NULL, SCS_NULL, -1);
44
+ tmp_cone_work = SCS(init_cone)(k, m);
45
+ SCS(proj_dual_cone)(y, tmp_cone_work, SCS_NULL, SCS_NULL);
46
+ SCS(finish_cone(tmp_cone_work));
55
47
 
56
48
  for (i = 0; i < m; i++) {
57
49
  b[i] = s[i] = y[i] - z[i];
@@ -65,18 +57,15 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
65
57
  c = -A'*y
66
58
  b = A*x + s
67
59
  */
60
+ ran_start(seed);
68
61
  A->p[0] = 0;
69
- scs_printf("Generating random matrix:\n");
70
62
  for (j = 0; j < n; j++) { /* column */
71
- if (j * 100 % n == 0 && (j * 100 / n) % 10 == 0) {
72
- scs_printf("%ld%%\n", (long)(j * 100 / n));
73
- }
74
63
  r = 0;
75
64
  for (i = 0; i < m && r < col_nnz; ++i) {
76
65
  /* generate a unique sorted array via Knuths alg */
77
66
  rn = m - i;
78
67
  rm = col_nnz - r;
79
- if ((rand() % rn) < rm) {
68
+ if ((ran_arr_next() % rn) < rm) {
80
69
  A->x[r + j * col_nnz] = rand_scs_float();
81
70
  A->i[r + j * col_nnz] = i;
82
71
  b[i] += A->x[r + j * col_nnz] * x[j];
@@ -86,8 +75,174 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
86
75
  }
87
76
  A->p[j + 1] = (j + 1) * col_nnz;
88
77
  }
89
- scs_printf("done\n");
90
78
  scs_free(z);
91
79
  }
92
80
 
81
+ static scs_float get_dual_cone_dist(const scs_float *y, ScsConeWork *c,
82
+ scs_int m) {
83
+ scs_float dist;
84
+ scs_float *t = (scs_float *)scs_calloc(m, sizeof(scs_float));
85
+ memcpy(t, y, m * sizeof(scs_float));
86
+ SCS(proj_dual_cone)(t, c, SCS_NULL, SCS_NULL);
87
+ dist = SCS(norm_inf_diff)(t, y, m);
88
+ scs_free(t);
89
+ return dist;
90
+ }
91
+
92
+ /* via moreau */
93
+ static scs_float get_pri_cone_dist(const scs_float *s, ScsConeWork *c,
94
+ scs_int m) {
95
+ scs_float dist;
96
+ scs_float *t = (scs_float *)scs_calloc(m, sizeof(scs_float));
97
+ memcpy(t, s, m * sizeof(scs_float));
98
+ SCS(scale_array)(t, -1.0, m);
99
+ SCS(proj_dual_cone)(t, c, SCS_NULL, SCS_NULL);
100
+ dist = SCS(norm_inf)(t, m); /* ||s - Pi_c(s)|| = ||Pi_c*(-s)|| */
101
+ scs_free(t);
102
+ return dist;
103
+ }
104
+
105
+ const char *verify_solution_correct(ScsData *d, ScsCone *k, ScsSettings *stgs,
106
+ ScsInfo *info, ScsSolution *sol,
107
+ scs_int status) {
108
+ scs_int n = d->n, m = d->m;
109
+ scs_float *x = sol->x;
110
+ scs_float *y = sol->y;
111
+ scs_float *s = sol->s;
112
+
113
+ scs_float *c = d->c;
114
+ scs_float *b = d->b;
115
+
116
+ scs_float *primal = (scs_float *)scs_calloc(m, sizeof(scs_float));
117
+ scs_float *ax = (scs_float *)scs_calloc(m, sizeof(scs_float));
118
+ scs_float *dual = (scs_float *)scs_calloc(n, sizeof(scs_float));
119
+ scs_float *px = (scs_float *)scs_calloc(n, sizeof(scs_float));
120
+ scs_float *aty = (scs_float *)scs_calloc(n, sizeof(scs_float));
121
+
122
+ scs_float res_pri, res_dual, res_infeas, res_unbdd_a, res_unbdd_p;
123
+ scs_float ctx, bty, xt_p_x, gap, pobj, dobj, sty;
124
+ scs_float grl, prl, drl;
125
+
126
+ scs_float sdist = NAN, ydist = NAN;
127
+
128
+ ScsConeWork *cone_work = SCS(init_cone)(k, m);
129
+
130
+ /**************** PRIMAL *********************/
131
+ memset(ax, 0, m * sizeof(scs_float));
132
+ /* Ax */
133
+ SCS(accum_by_a)(d->A, x, ax);
134
+
135
+ memcpy(primal, ax, m * sizeof(scs_float));
136
+ /* Ax + s */
137
+ SCS(add_scaled_array)(primal, s, m, 1.);
138
+
139
+ /* unbounded residual |Ax + s| */
140
+ res_unbdd_a = NORM(primal, m);
141
+
142
+ /* Ax + s - b */
143
+ SCS(add_scaled_array)(primal, b, m, -1.0);
144
+
145
+ res_pri = NORM(primal, m);
146
+
147
+ /**************** DUAL *********************/
148
+ memset(px, 0, n * sizeof(scs_float));
149
+ if (d->P) {
150
+ /* px = Px */
151
+ SCS(accum_by_p)(d->P, x, px);
152
+ xt_p_x = SCS(dot)(px, x, n);
153
+ res_unbdd_p = NORM(px, n);
154
+ } else {
155
+ xt_p_x = 0;
156
+ res_unbdd_p = 0;
157
+ }
158
+
159
+ memset(aty, 0, n * sizeof(scs_float));
160
+ /* aty = A'y */
161
+ SCS(accum_by_atrans)(d->A, y, aty);
162
+ res_infeas = NORM(aty, n);
163
+
164
+ memcpy(dual, aty, n * sizeof(scs_float));
165
+ /* Px + A'y */
166
+ SCS(add_scaled_array)(dual, px, n, 1.);
167
+ /* Px + A'y + c */
168
+ SCS(add_scaled_array)(dual, c, n, 1.0);
169
+
170
+ res_dual = NORM(dual, n);
171
+
172
+ /**************** CONES *****************/
173
+
174
+ if (status == SCS_SOLVED || status == SCS_UNBOUNDED) {
175
+ sdist = get_pri_cone_dist(sol->s, cone_work, m);
176
+ }
177
+ if (status == SCS_SOLVED || status == SCS_INFEASIBLE) {
178
+ ydist = get_dual_cone_dist(sol->y, cone_work, m);
179
+ }
180
+
181
+ /**************** OTHERS *****************/
182
+ sty = SCS(dot)(y, s, m);
183
+
184
+ bty = SCS(dot)(y, b, m);
185
+ ctx = SCS(dot)(x, c, n);
186
+
187
+ gap = ABS(xt_p_x + ctx + bty);
188
+ pobj = xt_p_x / 2. + ctx;
189
+ dobj = -xt_p_x / 2. - bty;
190
+
191
+ /************** OPTIMALITY ****************/
192
+
193
+ grl = MAX(MAX(ABS(xt_p_x), ABS(ctx)), ABS(bty));
194
+ prl = MAX(MAX(NORM(b, m), NORM(s, m)), NORM(ax, m));
195
+ drl = MAX(MAX(NORM(c, n), NORM(px, n)), NORM(aty, n));
196
+
197
+ /**************** CLEANUP *****************/
198
+ scs_free(primal);
199
+ scs_free(dual);
200
+ scs_free(px);
201
+ scs_free(ax);
202
+ scs_free(aty);
203
+ SCS(finish_cone)(cone_work);
204
+
205
+ /**************** ASSERTS *****************/
206
+ if (status == SCS_SOLVED) {
207
+ mu_assert_less("Primal residual ERROR", ABS(res_pri - info->res_pri),
208
+ 1e-11);
209
+ mu_assert_less("Dual residual ERROR", ABS(res_dual - info->res_dual),
210
+ 1e-11);
211
+ mu_assert_less("Gap ERROR", ABS(gap - info->gap), 1e-8 * (1 + ABS(gap)));
212
+ mu_assert_less("Primal obj ERROR", ABS(pobj - info->pobj),
213
+ 1e-9 * (1 + ABS(pobj)));
214
+ mu_assert_less("Dual obj ERROR", ABS(dobj - info->dobj),
215
+ 1e-9 * (1 + ABS(dobj)));
216
+ /* slightly looser tol */
217
+ mu_assert_less("Complementary slackness ERROR", ABS(sty),
218
+ 1e-8 * MAX(NORM(s, m), NORM(y, m)));
219
+ mu_assert_less("s cone dist ERROR", ABS(sdist), 1e-5);
220
+ mu_assert_less("y cone dist ERROR", ABS(ydist), 1e-5);
221
+
222
+ mu_assert_less("Primal feas ERROR", res_pri,
223
+ stgs->eps_abs + stgs->eps_rel * prl);
224
+ mu_assert_less("Dual feas ERROR", res_dual,
225
+ stgs->eps_abs + stgs->eps_rel * drl);
226
+ mu_assert_less("Gap feas ERROR", gap, stgs->eps_abs + stgs->eps_rel * grl);
227
+
228
+ } else if (status == SCS_INFEASIBLE) {
229
+ mu_assert_less("Infeas ERROR", ABS(res_infeas - info->res_infeas), 1e-8);
230
+ mu_assert_less("bty ERROR", ABS(bty + 1), 1e-12);
231
+ mu_assert_less("y cone dist ERROR", ABS(ydist), 1e-5);
232
+ mu_assert_less("Infeas invalid ERROR", res_infeas, stgs->eps_infeas);
233
+
234
+ } else if (status == SCS_UNBOUNDED) {
235
+ mu_assert_less("Unbdd_a ERROR", ABS(res_unbdd_a - info->res_unbdd_a), 1e-8);
236
+ mu_assert_less("Unbdd_p ERROR", ABS(res_unbdd_p - info->res_unbdd_p), 1e-8);
237
+ mu_assert_less("ctx ERROR", ABS(ctx + 1), 1e-12);
238
+ mu_assert_less("s cone dist ERROR", ABS(sdist), 1e-5);
239
+ mu_assert_less("Unbounded P invalid ERROR", res_unbdd_p, stgs->eps_infeas);
240
+ mu_assert_less("Unbounded A invalid ERROR", res_unbdd_a, stgs->eps_infeas);
241
+
242
+ } else {
243
+ return "INVALID STATUS";
244
+ }
245
+ return 0;
246
+ }
247
+
93
248
  #endif
@@ -0,0 +1,130 @@
1
+ #include "glbopts.h"
2
+ #include "linalg.h"
3
+ #include "minunit.h"
4
+ #include "scs.h"
5
+ #include "scs_matrix.h"
6
+ #include "util.h"
7
+
8
+ /* test degenerate cones */
9
+ static const char *degenerate(void) {
10
+ ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
11
+ ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
12
+ ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
13
+ ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
14
+ ScsInfo info = {0};
15
+ scs_int exitflag, success;
16
+ scs_float tpobj, tdobj, perr, derr;
17
+ const char *fail;
18
+
19
+ /* data */
20
+ scs_float Ax[] = {-10., -1., 1., -1.};
21
+ scs_int Ai[] = {1, 2, 1, 3};
22
+ scs_int Ap[] = {0, 2, 4};
23
+
24
+ scs_float Px[] = {0.02, 2.};
25
+ scs_int Pi[] = {0, 1};
26
+ scs_int Pp[] = {0, 1, 2};
27
+
28
+ scs_float b[] = {1., -1., 2., -0.5};
29
+ scs_float c[] = {1., 2.};
30
+
31
+ scs_int m = 4;
32
+ scs_int n = 2;
33
+
34
+ /* used later: */
35
+ scs_int sq[] = {1};
36
+
37
+ /* end data */
38
+
39
+ d->m = m;
40
+ d->n = n;
41
+ d->b = b;
42
+ d->c = c;
43
+
44
+ d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
45
+ d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
46
+
47
+ d->A->m = m;
48
+ d->A->n = n;
49
+
50
+ d->A->x = Ax;
51
+ d->A->i = Ai;
52
+ d->A->p = Ap;
53
+
54
+ d->P->m = n;
55
+ d->P->n = n;
56
+
57
+ d->P->x = Px;
58
+ d->P->i = Pi;
59
+ d->P->p = Pp;
60
+
61
+ scs_set_default_settings(stgs);
62
+ stgs->eps_abs = 1e-6;
63
+ stgs->eps_rel = 1e-6;
64
+ stgs->eps_infeas = 1e-9;
65
+
66
+ /* positive orthants */
67
+ k->l = 4;
68
+ exitflag = scs(d, k, stgs, sol, &info);
69
+ fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
70
+ if (fail) {
71
+ return fail;
72
+ }
73
+ mu_assert("bsize: SCS failed to produce outputflag SCS_SOLVED",
74
+ exitflag == SCS_SOLVED);
75
+
76
+ tpobj = info.pobj;
77
+ tdobj = info.dobj;
78
+
79
+ /* degenerate box cone */
80
+ k->bsize = 1;
81
+ k->l = 3;
82
+ exitflag = scs(d, k, stgs, sol, &info);
83
+ fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
84
+ if (fail) {
85
+ return fail;
86
+ }
87
+ perr = info.pobj - tpobj;
88
+ derr = info.dobj - tdobj;
89
+ success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED;
90
+ mu_assert("degenerate box cone failure", success);
91
+
92
+ /* degenerate SOC cone */
93
+ k->bsize = 0;
94
+ k->q = sq;
95
+ k->qsize = 1;
96
+ k->l = 3;
97
+ exitflag = scs(d, k, stgs, sol, &info);
98
+ fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
99
+ if (fail) {
100
+ return fail;
101
+ }
102
+ perr = info.pobj - tpobj;
103
+ derr = info.dobj - tdobj;
104
+ success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED;
105
+ mu_assert("degenerate SOC cone failure", success);
106
+
107
+ /* degenerate PSD cone */
108
+ k->q = 0;
109
+ k->qsize = 0;
110
+ k->s = sq;
111
+ k->ssize = 1;
112
+ k->l = 3;
113
+ exitflag = scs(d, k, stgs, sol, &info);
114
+ fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
115
+ if (fail) {
116
+ return fail;
117
+ }
118
+ perr = info.pobj - tpobj;
119
+ derr = info.dobj - tdobj;
120
+ success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED;
121
+ mu_assert("degenerate PSD cone failure", success);
122
+
123
+ SCS(free_sol)(sol);
124
+ scs_free(d->A);
125
+ scs_free(d->P);
126
+ scs_free(k);
127
+ scs_free(stgs);
128
+ scs_free(d);
129
+ return fail;
130
+ }