scs 0.5.5 → 0.6.0

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/scs/ffi.rb +18 -0
  5. data/lib/scs/solver.rb +11 -7
  6. data/lib/scs/version.rb +1 -1
  7. data/vendor/scs/CITATION.cff +2 -3
  8. data/vendor/scs/CLAUDE.md +115 -0
  9. data/vendor/scs/CMakeLists.txt +330 -201
  10. data/vendor/scs/CONTRIBUTING.md +49 -0
  11. data/vendor/scs/Makefile +90 -43
  12. data/vendor/scs/README.md +96 -2
  13. data/vendor/scs/include/aa.h +59 -11
  14. data/vendor/scs/include/aa_stats.h +47 -0
  15. data/vendor/scs/include/cones.h +16 -7
  16. data/vendor/scs/include/glbopts.h +113 -26
  17. data/vendor/scs/include/linalg.h +5 -1
  18. data/vendor/scs/include/linsys.h +1 -2
  19. data/vendor/scs/include/normalize.h +6 -2
  20. data/vendor/scs/include/rw.h +9 -3
  21. data/vendor/scs/include/scs.h +17 -1
  22. data/vendor/scs/include/scs_blas.h +8 -0
  23. data/vendor/scs/include/scs_types.h +2 -2
  24. data/vendor/scs/include/scs_work.h +22 -1
  25. data/vendor/scs/include/util.h +3 -6
  26. data/vendor/scs/include/util_spectral_cones.h +3 -3
  27. data/vendor/scs/linsys/accelerate/direct/private.c +126 -0
  28. data/vendor/scs/linsys/accelerate/direct/private.h +34 -0
  29. data/vendor/scs/linsys/cpu/dense/private.c +250 -0
  30. data/vendor/scs/linsys/cpu/dense/private.h +31 -0
  31. data/vendor/scs/linsys/cpu/direct/private.c +86 -44
  32. data/vendor/scs/linsys/cpu/indirect/private.c +647 -113
  33. data/vendor/scs/linsys/cpu/indirect/private.h +28 -0
  34. data/vendor/scs/linsys/csparse.c +9 -3
  35. data/vendor/scs/linsys/csparse.h +4 -2
  36. data/vendor/scs/linsys/cudss/direct/private.c +77 -43
  37. data/vendor/scs/linsys/cudss/direct/private.h +33 -7
  38. data/vendor/scs/linsys/gpu/indirect/private.c +6 -2
  39. data/vendor/scs/linsys/mkl/direct/private.c +63 -31
  40. data/vendor/scs/linsys/mkl/direct/private.h +0 -1
  41. data/vendor/scs/linsys/scs_matrix.c +291 -165
  42. data/vendor/scs/linsys/scs_matrix.h +7 -9
  43. data/vendor/scs/scs.mk +35 -13
  44. data/vendor/scs/src/aa.c +673 -166
  45. data/vendor/scs/src/cones.c +545 -223
  46. data/vendor/scs/src/ctrlc.c +59 -16
  47. data/vendor/scs/src/exp_cone.c +70 -50
  48. data/vendor/scs/src/linalg.c +21 -2
  49. data/vendor/scs/src/normalize.c +24 -26
  50. data/vendor/scs/src/rw.c +596 -124
  51. data/vendor/scs/src/scs.c +990 -513
  52. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_IPM.c +240 -187
  53. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_Newton.c +108 -85
  54. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_wrapper.c +62 -63
  55. data/vendor/scs/src/spectral_cones/logdeterminant/logdet_cone.c +85 -78
  56. data/vendor/scs/src/spectral_cones/nuclear/ell1_cone.c +92 -97
  57. data/vendor/scs/src/spectral_cones/nuclear/nuclear_cone.c +39 -28
  58. data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_cone.c +59 -40
  59. data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_eval_cone.c +37 -29
  60. data/vendor/scs/src/spectral_cones/util_spectral_cones.c +12 -6
  61. data/vendor/scs/src/util.c +37 -7
  62. data/vendor/scs/test/mkl_interface_mismatch.c +97 -0
  63. data/vendor/scs/test/packaging/CMakeLists.txt +21 -0
  64. data/vendor/scs/test/packaging/consume.c +50 -0
  65. data/vendor/scs/test/problem_utils.h +9 -2
  66. data/vendor/scs/test/problems/dense_qp.h +64 -0
  67. data/vendor/scs/test/problems/hs21_tiny_qp.h +6 -2
  68. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +10 -2
  69. data/vendor/scs/test/problems/infeasible_lp.h +66 -0
  70. data/vendor/scs/test/problems/infeasible_socp.h +75 -0
  71. data/vendor/scs/test/problems/lp_update.h +110 -0
  72. data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -1
  73. data/vendor/scs/test/problems/rob_gauss_cov_est.h +6 -3
  74. data/vendor/scs/test/problems/small_qp.h +5 -0
  75. data/vendor/scs/test/problems/test_box_cone.h +92 -0
  76. data/vendor/scs/test/problems/test_dual_exp_cone.h +96 -0
  77. data/vendor/scs/test/problems/test_inaccurate.h +212 -0
  78. data/vendor/scs/test/problems/test_mixed_cones.h +113 -0
  79. data/vendor/scs/test/problems/test_normalize_roundtrip.h +279 -0
  80. data/vendor/scs/test/problems/test_power_cone.h +414 -0
  81. data/vendor/scs/test/problems/test_psd_metric.h +109 -0
  82. data/vendor/scs/test/problems/test_psd_n1.h +84 -0
  83. data/vendor/scs/test/problems/test_root_plus.h +191 -0
  84. data/vendor/scs/test/problems/test_rw_settings.h +112 -0
  85. data/vendor/scs/test/problems/test_soc_sizes.h +393 -0
  86. data/vendor/scs/test/problems/test_solver_options.h +558 -0
  87. data/vendor/scs/test/problems/test_validation.h +263 -24
  88. data/vendor/scs/test/problems/test_zero_cone.h +81 -0
  89. data/vendor/scs/test/problems/unbounded_lp.h +66 -0
  90. data/vendor/scs/test/problems/unbounded_socp.h +71 -0
  91. data/vendor/scs/test/run_from_file.c +6 -0
  92. data/vendor/scs/test/run_tests.c +71 -0
  93. data/vendor/scs/test/rw_settings.c +7 -0
  94. data/vendor/scs/test/spectral_cones_problems/test_ell1_and_nuc.h +128 -0
  95. data/vendor/scs/test/spectral_cones_problems/test_ell1_cone.h +115 -0
  96. metadata +35 -3
@@ -1,8 +1,8 @@
1
- #include "glbopts.h" // for scs_printf
1
+ #include "glbopts.h" /* for scs_printf */
2
2
  #include "linalg.h"
3
3
  #include "scs_blas.h"
4
- #include "util_spectral_cones.h" // for Newton structs
5
- #include <string.h> // for memcpy
4
+ #include "util_spectral_cones.h" /* for Newton structs */
5
+ #include <string.h> /* for memcpy */
6
6
 
7
7
  /*
8
8
  * Spectral matrix cone projections, from "Projection onto Spectral Matrix
@@ -56,24 +56,29 @@ static void f_oracle(const scs_float *u1, scs_float r, scs_float t0,
56
56
  scs_float v0, const scs_float *x0, const scs_float *x_inv,
57
57
  scs_int n, scs_float *f_u, scs_float *grad_f0,
58
58
  scs_float *grad_f1) {
59
- // compute grad_f0[0, 1] = t - t0, v - v0, grad_f1[2:-1] = x - x0
59
+ scs_float sum_log_xv;
60
+ scs_float norm_2;
61
+
62
+ /* compute grad_f0[0, 1] = t - t0, v - v0, grad_f1[2:-1] = x - x0 */
60
63
  grad_f0[0] = u1[0] - t0;
61
64
  grad_f0[1] = u1[1] - v0;
62
65
  memcpy(grad_f0 + 2, u1 + 2, n * sizeof(*grad_f0));
63
66
  SCS(add_scaled_array)(grad_f0 + 2, x0, n, -1.0);
64
67
  grad_f0[n + 2] = -1.0;
65
68
 
66
- // compute f_u
67
- scs_float sum_log_xv = sum_log(u1 + 2, n) - n * log(u1[1]);
68
- scs_float norm_2 = SCS(norm_2)(grad_f0 + 2, n);
69
+ /* compute f_u */
70
+ sum_log_xv = sum_log(u1 + 2, n) - n * log(u1[1]);
71
+ norm_2 = SCS(norm_2)(grad_f0 + 2, n);
69
72
  f_u[0] = 0.5 * (grad_f0[0] * grad_f0[0] + grad_f0[1] * grad_f0[1] +
70
73
  norm_2 * norm_2) -
71
74
  r;
72
75
  f_u[1] = -u1[1] * sum_log_xv - u1[0];
73
76
  f_u[2] = -u1[1];
74
77
 
75
- // compute grad_f1[0] = -1, grad_f1[1] = n - sum(log(x/v)),
76
- // grad[2:-1] = - v / x, grad[-1] = 0
78
+ /*
79
+ * compute grad_f1[0] = -1, grad_f1[1] = n - sum(log(x/v)),
80
+ * grad[2:-1] = - v / x, grad[-1] = 0
81
+ */
77
82
  grad_f1[0] = -1.0;
78
83
  grad_f1[1] = n - sum_log_xv;
79
84
  memcpy(grad_f1 + 2, x_inv, n * sizeof(*x_inv));
@@ -81,15 +86,17 @@ static void f_oracle(const scs_float *u1, scs_float r, scs_float t0,
81
86
  grad_f1[n + 2] = 0.0;
82
87
  }
83
88
 
84
- // u1 = [t, v, x]
89
+ /* u1 = [t, v, x] */
85
90
  static scs_float find_max_step_size(const scs_float *u1, const scs_float *z,
86
91
  const scs_float *s, const scs_float *du1,
87
92
  const scs_float *dz, const scs_float *ds,
88
93
  scs_int n) {
89
94
  scs_float step_max = 10.0;
90
95
  scs_int i;
96
+ scs_float step_max_dom;
97
+ scs_float step_size;
91
98
 
92
- // find maximum step size with respect to z and s
99
+ /* find maximum step size with respect to z and s */
93
100
  for (i = 0; i < 3; ++i) {
94
101
  if (dz[i] < 0) {
95
102
  step_max = MIN(step_max, -z[i] / dz[i]);
@@ -100,16 +107,16 @@ static scs_float find_max_step_size(const scs_float *u1, const scs_float *z,
100
107
  }
101
108
  }
102
109
 
103
- scs_float step_max_dom = 10;
110
+ step_max_dom = 10;
104
111
 
105
- // find maximum step size with respect to the domain of f
112
+ /* find maximum step size with respect to the domain of f */
106
113
  for (i = 1; i < n + 2; i++) {
107
114
  if (du1[i] < 0) {
108
115
  step_max_dom = MIN(step_max_dom, -u1[i] / du1[i]);
109
116
  }
110
117
  }
111
118
 
112
- scs_float step_size = MIN(1.0, STEP_IPM * step_max);
119
+ step_size = MIN(1.0, STEP_IPM * step_max);
113
120
 
114
121
  while (step_size > step_max_dom) {
115
122
  step_size *= BETA_IPM;
@@ -135,8 +142,10 @@ typedef struct {
135
142
 
136
143
  } KKT_solver_workspace;
137
144
 
138
- // Precomputations before solving the KKT system. You can think of this
139
- // as factoring the KKT matrix.
145
+ /*
146
+ * Precomputations before solving the KKT system. You can think of this
147
+ * as factoring the KKT matrix.
148
+ */
140
149
  static void KKT_precompute(scs_float v, const scs_float *x_inv,
141
150
  const scs_float *z, const scs_float *w, scs_int n,
142
151
  KKT_solver_workspace *KKT_work) {
@@ -146,10 +155,11 @@ static void KKT_precompute(scs_float v, const scs_float *x_inv,
146
155
  scs_float *GinvC = KKT_work->GinvC;
147
156
  scs_float *g0g1 = KKT_work->g0g1;
148
157
  scs_float *R = KKT_work->R;
158
+ scs_int i;
149
159
 
150
160
  scs_float a = z[0] + 1 / (w[2] * w[2]) + z[1] * n / v;
151
161
  scs_float coeff = 0.0;
152
- for (scs_int i = 0; i < n; i++) {
162
+ for (i = 0; i < n; i++) {
153
163
  temp1[i] = z[0] + (z[1] * v) * (x_inv[i] * x_inv[i]);
154
164
  temp2[i] = x_inv[i] / temp1[i];
155
165
  coeff += (x_inv[i] * x_inv[i]) / temp1[i];
@@ -157,34 +167,30 @@ static void KKT_precompute(scs_float v, const scs_float *x_inv,
157
167
  coeff = a - z[1] * z[1] * coeff;
158
168
  KKT_work->coeff = coeff;
159
169
 
160
- // --------------------------------------------------------------------
161
- // compute G \ g0
162
- // --------------------------------------------------------------------
170
+ /* compute G \ g0 */
163
171
  GinvC[0] = g0g1[0] / z[0];
164
172
  GinvC[1] = (g0g1[1] + z[1] * SCS(dot)(g0g1 + 2, temp2, n)) / coeff;
165
- for (scs_int i = 2; i < n + 2; i++) {
173
+ for (i = 2; i < n + 2; i++) {
166
174
  GinvC[i] = (g0g1[i] + (z[1] * GinvC[1]) * x_inv[i - 2]) / temp1[i - 2];
167
175
  }
168
176
  GinvC[n + 2] = -g0g1[n + 2];
169
177
 
170
- // --------------------------------------------------------------------
171
- // compute G \ g1
172
- // --------------------------------------------------------------------
178
+ /* compute G \ g1 */
173
179
  GinvC[n + 3] = g0g1[n + 3] / z[0];
174
180
  GinvC[n + 4] =
175
181
  (g0g1[n + 4] + z[1] * SCS(dot)(g0g1 + n + 5, temp2, n)) / coeff;
176
- for (scs_int i = n + 5; i < 2 * n + 5; i++) {
182
+ for (i = n + 5; i < 2 * n + 5; i++) {
177
183
  GinvC[i] =
178
184
  (g0g1[i] + (z[1] * GinvC[n + 4]) * x_inv[i - n - 5]) / temp1[i - n - 5];
179
185
  }
180
186
  GinvC[2 * n + 5] = -g0g1[2 * n + 5];
181
187
 
182
- // compute G \ ([0, 0, ..., 0, 1])
188
+ /* compute G \ ([0, 0, ..., 0, 1]) */
183
189
  GinvC[3 * n + 8] = -1.0;
184
190
 
185
- // ------------------------------------------------------------------------
186
- // compute R = I + C.T @ GinvC. This matrix is always reverse triangular.
187
- // ------------------------------------------------------------------------
191
+ /*
192
+ * compute R = I + C.T @ GinvC. This matrix is always reverse triangular.
193
+ */
188
194
  R[0] = 1 + SCS(dot)(g0g1, GinvC, u_dim);
189
195
  R[3] = SCS(dot)(g0g1, GinvC + u_dim, u_dim);
190
196
  R[6] = SCS(dot)(g0g1, GinvC + 2 * u_dim, u_dim);
@@ -215,38 +221,39 @@ static void KKT_solve(const scs_float *z, const scs_float *w,
215
221
  scs_float *bnew = KKT_work->bnew;
216
222
  scs_float *g0g1 = KKT_work->g0g1;
217
223
  scs_float *CCTdu = KKT_work->CCTdu;
224
+ scs_float scale;
225
+
226
+ const scs_int num_ref = 3;
227
+ scs_int i;
228
+ scs_int ii;
218
229
 
219
- // -------------------------------------------------------------------------
220
- // prepare RHS
221
- // -------------------------------------------------------------------------
230
+ /* prepare RHS */
222
231
  memcpy(rhs_reduced, rhs1, (n + 6) * sizeof(*rhs1));
223
232
  rhs_reduced[u_dim] -= w[0] * (rhs2[0] / lmbda[0]);
224
233
  rhs_reduced[u_dim + 1] -= w[1] * (rhs2[1] / lmbda[1]);
225
234
  rhs_reduced[u_dim + 2] -= w[2] * (rhs2[2] / lmbda[2]);
226
235
  memcpy(bnew, rhs_reduced, u_dim * sizeof(*rhs_reduced));
227
- scs_float scale = rhs_reduced[n + 3] / w[0];
236
+ scale = rhs_reduced[n + 3] / w[0];
228
237
  SCS(add_scaled_array)(bnew, g0g1, u_dim, scale);
229
238
  scale = rhs_reduced[n + 4] / w[1];
230
239
  SCS(add_scaled_array)(bnew, g0g1 + u_dim, u_dim, scale);
231
240
  bnew[1] -= (rhs_reduced[n + 5] / (w[2] * w[2]));
232
241
 
233
- // -------------------------------------------------------------------------
234
- // solve system and apply iterative refinement
235
- // -------------------------------------------------------------------------
242
+ /* solve system and apply iterative refinement */
236
243
  memcpy(residual, bnew, u_dim * sizeof(*bnew));
237
244
  memset(du1, 0, u1_dim * sizeof(*du1));
238
245
  *dr = 0;
239
- const scs_int num_ref = 3;
240
- for (scs_int i = 0; i < num_ref; ++i) {
241
- // --------------------------------
242
- // solve (G + C @ C.T) d = residual
243
- // --------------------------------
246
+ for (i = 0; i < num_ref; ++i) {
247
+ char trans;
248
+ scs_float *Gdu;
249
+
250
+ /* solve (G + C @ C.T) d = residual */
244
251
  GinvRes[0] = residual[0] / z[0];
245
252
  GinvRes[1] =
246
253
  (residual[1] + z[1] * SCS(dot)(residual + 2, temp2, n)) / coeff;
247
- for (scs_int i = 2; i < n + 2; ++i) {
248
- GinvRes[i] =
249
- (residual[i] + (z[1] * GinvRes[1]) * x_inv[i - 2]) / temp1[i - 2];
254
+ for (ii = 2; ii < n + 2; ++ii) {
255
+ GinvRes[ii] =
256
+ (residual[ii] + (z[1] * GinvRes[1]) * x_inv[ii - 2]) / temp1[ii - 2];
250
257
  }
251
258
 
252
259
  GinvRes[n + 2] = -residual[n + 2];
@@ -259,42 +266,42 @@ static void KKT_solve(const scs_float *z, const scs_float *w,
259
266
  (CTGinvRes[0] - R[0] * RinvCTGinvRes[0] - R[3] * RinvCTGinvRes[1]) /
260
267
  R[6];
261
268
 
262
- // --------------------------------------------------------------------
263
- // Here we want to apply the correction d: du = du + d, where
264
- // d = GinvRes - GinvC @ RinvCTGinvRes. Note that we expect the
265
- // correction d to be very small, so we *must* compute d first and
266
- // then add it to du, instead of computing it as
267
- // du = du + GinvRes, du = du - GinvC @ RinvCTGinvRes.
268
- // In other words, the following code will result in bugs due to
269
- // numerics:
270
- // daxpy_(&u_dim, &d_one, GinvRes, &bi_one, du, &bi_one);
271
- // char trans = 'N';
272
- // dgemv_(&trans, &u_dim, &i_three, &d_minus_one, GinvC, &u_dim,
273
- // RinvCTGinvRes, &bi_one, &d_one, du, &bi_one);
274
- // --------------------------------------------------------------------
275
-
276
- char trans = 'N';
269
+ /*
270
+ * Here we want to apply the correction d: du = du + d, where
271
+ * d = GinvRes - GinvC @ RinvCTGinvRes. Note that we expect the
272
+ * correction d to be very small, so we *must* compute d first and
273
+ * then add it to du, instead of computing it as
274
+ * du = du + GinvRes, du = du - GinvC @ RinvCTGinvRes.
275
+ * In other words, the following code will result in bugs due to
276
+ * numerics:
277
+ * daxpy_(&u_dim, &d_one, GinvRes, &bi_one, du, &bi_one);
278
+ * char trans = 'N';
279
+ * dgemv_(&trans, &u_dim, &i_three, &d_minus_one, GinvC, &u_dim,
280
+ * RinvCTGinvRes, &bi_one, &d_one, du, &bi_one);
281
+ */
282
+
283
+ trans = 'N';
277
284
  BLAS(gemv)(&trans, &u_dim, &bi_three, &d_minus_one, GinvC, &u_dim,
278
285
  RinvCTGinvRes, &bi_one, &d_one, GinvRes, &bi_one);
279
286
  SCS(add_scaled_array)(du1, GinvRes, u1_dim, 1.0);
280
287
  *dr += GinvRes[n + 2];
281
288
 
282
- // -----------------------------------
283
- // compute new residual
284
- // -----------------------------------
285
- scs_float *Gdu = GinvRes;
289
+ /* compute new residual */
290
+ Gdu = GinvRes;
286
291
  if (i != num_ref - 1) {
292
+ scs_float coeff0;
293
+ scs_float coeff1;
287
294
  Gdu[0] = z[0] * du1[0];
288
295
  Gdu[1] = ((z[0] + 1 / (w[2] * w[2])) * du1[1] +
289
296
  z[1] * (n / v * du1[1] - SCS(dot)(x_inv, du1 + 2, n)));
290
- for (scs_int ii = 2; ii < n + 2; ++ii) {
297
+ for (ii = 2; ii < n + 2; ++ii) {
291
298
  Gdu[ii] = (z[0] * du1[ii] +
292
299
  z[1] * (-du1[1] * x_inv[ii - 2] +
293
300
  v * du1[ii] * x_inv[ii - 2] * x_inv[ii - 2]));
294
301
  }
295
302
  Gdu[n + 2] = -(*dr);
296
- scs_float coeff0 = SCS(dot)(g0g1, du1, u1_dim) + g0g1[n + 2] * (*dr);
297
- scs_float coeff1 =
303
+ coeff0 = SCS(dot)(g0g1, du1, u1_dim) + g0g1[n + 2] * (*dr);
304
+ coeff1 =
298
305
  SCS(dot)(g0g1 + u_dim, du1, u1_dim) + g0g1[2 * n + 5] * (*dr);
299
306
  memcpy(CCTdu, g0g1, u_dim * sizeof(*g0g1));
300
307
  SCS(scale_array)(CCTdu, coeff0, u_dim);
@@ -302,22 +309,22 @@ static void KKT_solve(const scs_float *z, const scs_float *w,
302
309
  CCTdu[n + 2] += (*dr);
303
310
  memcpy(residual, bnew, u_dim * sizeof(*bnew));
304
311
 
305
- // important to compute the residual as residual = bnew - (Gdu +
306
- // CCTdu) and not as residual = (bnew - Gdu) - CCTdu
312
+ /*
313
+ * important to compute the residual as residual = bnew - (Gdu +
314
+ * CCTdu) and not as residual = (bnew - Gdu) - CCTdu
315
+ */
307
316
  SCS(add_scaled_array)(Gdu, CCTdu, u_dim, 1.0);
308
317
  SCS(add_scaled_array)(residual, Gdu, u_dim, -1.0);
309
318
  }
310
319
  }
311
320
 
312
- // -------------------------------------------------------------------------
313
- // recover substituted variables
314
- // -------------------------------------------------------------------------
321
+ /* recover substituted variables */
315
322
  memcpy(dz, rhs_reduced + u_dim, 3 * sizeof(*rhs_reduced));
316
323
  dz[0] -= w[0] * (SCS(dot)(g0g1, du1, u1_dim) + g0g1[n + 2] * (*dr));
317
324
  dz[1] -=
318
325
  w[1] * (SCS(dot)(g0g1 + u_dim, du1, u1_dim) + g0g1[2 * n + 5] * (*dr));
319
326
  dz[2] += du1[1];
320
- for (scs_int ii = 0; ii < 3; ++ii) {
327
+ for (ii = 0; ii < 3; ++ii) {
321
328
  dz[ii] = -dz[ii] / (w[ii] * w[ii]);
322
329
  ds[ii] = w[ii] * (rhs2[ii] / lmbda[ii] - w[ii] * dz[ii]);
323
330
  }
@@ -334,11 +341,54 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
334
341
  scs_int m = 3;
335
342
  scs_int u_dim = n + 3;
336
343
  scs_int u1_dim = n + 2;
344
+ scs_int i;
337
345
 
338
- // -----------------------------------------------------------------
339
- // scale (t0, v0, x0)
340
- // -----------------------------------------------------------------
346
+ /* scale (t0, v0, x0) */
341
347
  scs_float scale1 = SCS(norm_inf)(x0, n);
348
+
349
+ scs_float *x_inv;
350
+ scs_float *z;
351
+ scs_float *s;
352
+ scs_float *f_u;
353
+ scs_float *grad_f0;
354
+ scs_float *grad_f1;
355
+ scs_float *rx;
356
+ scs_float *rznl;
357
+ scs_float *w;
358
+ scs_float *lmbda;
359
+ scs_float *du1;
360
+ scs_float *dz;
361
+ scs_float *ds;
362
+ scs_float *u1_new;
363
+ scs_float *z_new;
364
+ scs_float *s_new;
365
+ scs_float *x_inv_new;
366
+ scs_float *f_u_new;
367
+ scs_float *grad_f0_new;
368
+ scs_float *grad_f1_new;
369
+ scs_float *rx_new;
370
+ scs_float *rznl_new;
371
+ scs_float *u1_0;
372
+ scs_float *du1_0;
373
+ scs_float *z0;
374
+ scs_float *dz0;
375
+ scs_float *s0;
376
+ scs_float *ds0;
377
+
378
+ scs_float r;
379
+ scs_float dr;
380
+ scs_float rnew;
381
+ scs_float r0;
382
+ scs_float dr0;
383
+
384
+ KKT_solver_workspace KKT_work;
385
+
386
+ scs_int relaxed_iters;
387
+ size_t iter;
388
+ scs_float theta1, theta2, theta3;
389
+ scs_float pres0, dres0;
390
+ scs_float phi0, dphi0, step_size0;
391
+
342
392
  scale1 = MAX(t0, scale1);
343
393
  scale1 = MAX(v0, scale1);
344
394
  scale1 = 1 / scale1;
@@ -346,45 +396,42 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
346
396
  v0 = v0 * scale1;
347
397
  SCS(scale_array)(x0, scale1, n);
348
398
 
349
- // ----------------------------------------------------------------------
350
- // Parse workspace
351
- // ----------------------------------------------------------------------
352
- scs_float *x_inv = workspace;
353
- scs_float *z = workspace + n;
354
- scs_float *s = z + m;
355
- scs_float *f_u = s + m;
356
- scs_float *grad_f0 = f_u + m;
357
- scs_float *grad_f1 = grad_f0 + u_dim;
358
- scs_float *rx = grad_f1 + u_dim;
359
- scs_float *rznl = rx + u_dim;
360
- scs_float *w = rznl + m;
361
- scs_float *lmbda = w + m;
362
- scs_float *du1 = lmbda + m;
363
- scs_float *dz = du1 + u1_dim;
364
- scs_float *ds = dz + m;
365
-
366
- // for evaluating the new residuals in the line search
367
- scs_float *u1_new = ds + m;
368
- scs_float *z_new = u1_new + u1_dim;
369
- scs_float *s_new = z_new + m;
370
- scs_float *x_inv_new = s_new + m;
371
- scs_float *f_u_new = x_inv_new + n;
372
- scs_float *grad_f0_new = f_u_new + m;
373
- scs_float *grad_f1_new = grad_f0_new + u_dim;
374
- scs_float *rx_new = grad_f1_new + u_dim;
375
- scs_float *rznl_new = rx_new + u_dim;
376
-
377
- // for storing the state for the line search
378
- scs_float *u1_0 = rznl_new + m;
379
- scs_float *du1_0 = u1_0 + u1_dim;
380
- scs_float *z0 = du1_0 + u1_dim;
381
- scs_float *dz0 = z0 + m;
382
- scs_float *s0 = dz0 + m;
383
- scs_float *ds0 = s0 + m;
384
- scs_float r0 = 0.0;
385
- scs_float dr0 = 0.0;
399
+ /* Parse workspace */
400
+ x_inv = workspace;
401
+ z = workspace + n;
402
+ s = z + m;
403
+ f_u = s + m;
404
+ grad_f0 = f_u + m;
405
+ grad_f1 = grad_f0 + u_dim;
406
+ rx = grad_f1 + u_dim;
407
+ rznl = rx + u_dim;
408
+ w = rznl + m;
409
+ lmbda = w + m;
410
+ du1 = lmbda + m;
411
+ dz = du1 + u1_dim;
412
+ ds = dz + m;
413
+
414
+ /* for evaluating the new residuals in the line search */
415
+ u1_new = ds + m;
416
+ z_new = u1_new + u1_dim;
417
+ s_new = z_new + m;
418
+ x_inv_new = s_new + m;
419
+ f_u_new = x_inv_new + n;
420
+ grad_f0_new = f_u_new + m;
421
+ grad_f1_new = grad_f0_new + u_dim;
422
+ rx_new = grad_f1_new + u_dim;
423
+ rznl_new = rx_new + u_dim;
424
+
425
+ /* for storing the state for the line search */
426
+ u1_0 = rznl_new + m;
427
+ du1_0 = u1_0 + u1_dim;
428
+ z0 = du1_0 + u1_dim;
429
+ dz0 = z0 + m;
430
+ s0 = dz0 + m;
431
+ ds0 = s0 + m;
432
+ r0 = 0.0;
433
+ dr0 = 0.0;
386
434
 
387
- KKT_solver_workspace KKT_work;
388
435
  KKT_work.g0g1 = grad_f0;
389
436
  KKT_work.temp1 = ds0 + m;
390
437
  KKT_work.temp2 = KKT_work.temp1 + u_dim;
@@ -398,29 +445,28 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
398
445
  KKT_work.bnew = KKT_work.rhs_reduced + u_dim + 3;
399
446
  KKT_work.CCTdu = KKT_work.bnew + u_dim;
400
447
 
401
- // ---------------------------------------------------------------------
402
- // initialize primal variable u1 = [t, v, x], epigraph variable r and
403
- // primal slack variable s and Lagrange multipliers z
404
- // ---------------------------------------------------------------------
405
- for (scs_int i = 0; i < n + 2; ++i) {
448
+ /*
449
+ * initialize primal variable u1 = [t, v, x], epigraph variable r and
450
+ * primal slack variable s and Lagrange multipliers z
451
+ */
452
+ for (i = 0; i < n + 2; ++i) {
406
453
  u1[i] = 1.0;
407
454
  }
408
455
 
409
- scs_float r = 0.0;
410
- scs_float dr = 0.0;
411
- scs_float rnew = 0.0;
456
+ r = 0.0;
457
+ dr = 0.0;
458
+ rnew = 0.0;
412
459
 
413
- for (scs_int i = 0; i < m; ++i) {
460
+ for (i = 0; i < m; ++i) {
414
461
  z[i] = 1.0;
415
462
  s[i] = 1.0;
416
463
  }
417
464
 
418
- scs_int relaxed_iters = 0;
419
- size_t iter = 0;
420
- scs_float theta1, theta2, theta3;
421
- scs_float pres0, dres0;
422
- scs_float phi0 = 0.0, dphi0 = 0.0, step_size0 = 0.0;
423
- // scs_int small_consecutive_steps_counter = 0;
465
+ relaxed_iters = 0;
466
+ iter = 0;
467
+ phi0 = 0.0;
468
+ dphi0 = 0.0;
469
+ step_size0 = 0.0;
424
470
 
425
471
  #ifdef SPECTRAL_DEBUG
426
472
  printf("%-3s%-15s%-15s%-15s%-10s%-10s\n", "", "gap", "pres", "dres", "sig",
@@ -430,18 +476,27 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
430
476
  for (iter = 0; iter < MAX_ITER_IPM; ++iter) {
431
477
  scs_float gap = z[0] * s[0] + z[1] * s[1] + z[2] * s[2];
432
478
  scs_float mu = gap / m;
433
-
434
- // --------------------------------------------------------
435
- // evaluate oracle
436
- // --------------------------------------------------------
437
- for (scs_int i = 0; i < n; i++) {
479
+ scs_float dres;
480
+ scs_float pres;
481
+ scs_float norm_rx;
482
+ scs_float norm_rznl;
483
+ scs_float relgap;
484
+ scs_float scale2;
485
+ scs_float rhs2_aff[3];
486
+ scs_float *rhs1_aff;
487
+ scs_float sigma;
488
+ scs_float phi;
489
+ scs_float dphi;
490
+ scs_float step_size;
491
+ scs_int j;
492
+
493
+ /* evaluate oracle */
494
+ for (i = 0; i < n; i++) {
438
495
  x_inv[i] = 1 / u1[i + 2];
439
496
  }
440
497
  f_oracle(u1, r, t0, v0, x0, x_inv, n, f_u, grad_f0, grad_f1);
441
498
 
442
- // --------------------------------------------------------
443
- // compute residuals and check termination criteria
444
- // --------------------------------------------------------
499
+ /* compute residuals and check termination criteria */
445
500
  memcpy(rx, grad_f0, u_dim * sizeof(*grad_f0));
446
501
  SCS(scale_array)(rx, z[0], u_dim);
447
502
  SCS(add_scaled_array)(rx, grad_f1, u_dim, z[1]);
@@ -451,11 +506,11 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
451
506
  rznl[1] = f_u[1] + s[1];
452
507
  rznl[2] = f_u[2] + s[2];
453
508
 
454
- scs_float dres = SCS(norm_2)(rx, u_dim);
455
- scs_float pres =
509
+ dres = SCS(norm_2)(rx, u_dim);
510
+ pres =
456
511
  sqrt(rznl[0] * rznl[0] + rznl[1] * rznl[1] + rznl[2] * rznl[2]);
457
- scs_float norm_rx = dres;
458
- scs_float norm_rznl = pres;
512
+ norm_rx = dres;
513
+ norm_rznl = pres;
459
514
 
460
515
  if (iter == 0) {
461
516
  pres0 = MAX(pres, 1.0);
@@ -467,7 +522,7 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
467
522
 
468
523
  pres = pres / pres0;
469
524
  dres = dres / dres0;
470
- scs_float relgap = gap / MAX(r, 1.0);
525
+ relgap = gap / MAX(r, 1.0);
471
526
 
472
527
  if (dres < FEASTOL_IPM && pres < FEASTOL_IPM &&
473
528
  (gap < ABSTOL_IPM || relgap <= RELTOL_IPM)) {
@@ -478,45 +533,44 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
478
533
  break;
479
534
  }
480
535
 
481
- // ----------------------------------------------------
482
- // compute scaling matrix and scaling point
483
- // ----------------------------------------------------
484
- for (scs_int i = 0; i < m; i++) {
536
+ /* compute scaling matrix and scaling point */
537
+ for (i = 0; i < m; i++) {
485
538
  w[i] = sqrt(s[i] / z[i]);
486
539
  lmbda[i] = sqrt(s[i] * z[i]);
487
540
  }
488
541
 
489
- // -----------------------------------------------------------------
490
- // precomputations for KKT system
491
- // -----------------------------------------------------------------
492
- scs_float scale2 = 1 / w[0];
542
+ /* precomputations for KKT system */
543
+ scale2 = 1 / w[0];
493
544
  SCS(scale_array)(grad_f0, scale2, u_dim);
494
545
  scale2 = 1 / w[1];
495
546
  SCS(scale_array)(grad_f1, scale2, u_dim);
496
547
  KKT_precompute(u1[1], x_inv, z, w, n, &KKT_work);
497
548
 
498
- scs_float rhs2_aff[] = {-lmbda[0] * lmbda[0], -lmbda[1] * lmbda[1],
499
- -lmbda[2] * lmbda[2]};
549
+ rhs2_aff[0] = -lmbda[0] * lmbda[0];
550
+ rhs2_aff[1] = -lmbda[1] * lmbda[1];
551
+ rhs2_aff[2] = -lmbda[2] * lmbda[2];
500
552
 
501
- // upper bound on loop is chosen so it also iterates over rznl
502
- for (scs_int i = 0; i < u_dim + 3; ++i) {
553
+ /* upper bound on loop is chosen so it also iterates over rznl */
554
+ for (i = 0; i < u_dim + 3; ++i) {
503
555
  rx[i] = -rx[i];
504
556
  }
505
- scs_float *rhs1_aff = rx;
557
+ rhs1_aff = rx;
506
558
 
507
- scs_float sigma = 0.0;
508
- scs_float phi = 0.0;
509
- scs_float dphi = 0.0;
510
- scs_float step_size = 0.0;
559
+ sigma = 0.0;
560
+ phi = 0.0;
561
+ dphi = 0.0;
562
+ step_size = 0.0;
511
563
  phi = theta1 * gap + theta2 * norm_rx + theta3 * norm_rznl;
512
564
  dphi = -theta1 * (1 - sigma) * gap - theta2 * norm_rx - theta3 * norm_rznl;
513
565
 
514
- for (scs_int i = 0; i < 2; ++i) {
515
- // ------------------------------------------------------------
516
- // For i = 0 we compute the affine-scaling direction.
517
- // For i = 1 we compute the actual search direction.
518
- // ------------------------------------------------------------
519
- if (i == 1 && variant == 0) {
566
+ for (j = 0; j < 2; ++j) {
567
+ bool backtrack;
568
+
569
+ /*
570
+ * For j = 0 we compute the affine-scaling direction.
571
+ * For j = 1 we compute the actual search direction.
572
+ */
573
+ if (j == 1 && variant == 0) {
520
574
  SCS(scale_array)(rhs1_aff, 1 - sigma, u_dim + 3);
521
575
  rhs2_aff[0] += (sigma * mu - ds[0] * dz[0]);
522
576
  rhs2_aff[1] += (sigma * mu - ds[1] * dz[1]);
@@ -526,16 +580,19 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
526
580
  KKT_solve(z, w, x_inv, u1[1], lmbda, n, rhs1_aff, rhs2_aff, &KKT_work,
527
581
  du1, &dr, dz, ds);
528
582
 
529
- // --------------------------------------------------------------
530
- // For i = 0 we determine the centering parameter.
531
- // For i = 1 we do a nonmonotone line search.
532
- // --------------------------------------------------------------
583
+ /*
584
+ * For j = 0 we determine the centering parameter.
585
+ * For j = 1 we do a nonmonotone line search.
586
+ */
533
587
  step_size = find_max_step_size(u1, z, s, du1, dz, ds, n);
534
588
 
535
- bool backtrack = true;
589
+ backtrack = true;
536
590
 
537
591
  while (backtrack) {
538
- // u_new = u + step * du, z_new = z + step * dz, s_new = s + step
592
+ scs_float gap_new;
593
+ scs_float phi_new;
594
+
595
+ /* u_new = u + step * du, z_new = z + step * dz, s_new = s + step */
539
596
  memcpy(u1_new, u1, u1_dim * sizeof(*u1));
540
597
  SCS(add_scaled_array)(u1_new, du1, u1_dim, step_size);
541
598
  rnew = r + step_size * dr;
@@ -544,14 +601,14 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
544
601
  memcpy(s_new, s, 3 * sizeof(*s));
545
602
  SCS(add_scaled_array)(s_new, ds, m, step_size);
546
603
 
547
- // evaluate oracle in u_new
548
- for (scs_int i = 0; i < n; i++) {
604
+ /* evaluate oracle in u_new */
605
+ for (i = 0; i < n; i++) {
549
606
  x_inv_new[i] = 1 / u1_new[i + 2];
550
607
  }
551
608
  f_oracle(u1_new, rnew, t0, v0, x0, x_inv_new, n, f_u_new, grad_f0_new,
552
609
  grad_f1_new);
553
610
 
554
- // compute residuals and merit function
611
+ /* compute residuals and merit function */
555
612
  memcpy(rx_new, grad_f0_new, u_dim * sizeof(*grad_f0_new));
556
613
  SCS(scale_array)(rx_new, z_new[0], u_dim);
557
614
  SCS(add_scaled_array)(rx_new, grad_f1_new, u_dim, z_new[1]);
@@ -560,14 +617,12 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
560
617
  rznl_new[0] = f_u_new[0] + s_new[0];
561
618
  rznl_new[1] = f_u_new[1] + s_new[1];
562
619
  rznl_new[2] = f_u_new[2] + s_new[2];
563
- scs_float gap_new = SCS(dot)(z_new, s_new, m);
564
- scs_float phi_new = theta1 * gap_new +
620
+ gap_new = SCS(dot)(z_new, s_new, m);
621
+ phi_new = theta1 * gap_new +
565
622
  theta2 * SCS(norm_2)(rx_new, u_dim) +
566
623
  theta3 * SCS(norm_2)(rznl_new, m);
567
- // ----------------------------------------------------------
568
- // For i == 0 we determine the centering parameter
569
- // ----------------------------------------------------------
570
- if (i == 0) {
624
+ /* For j == 0 we determine the centering parameter */
625
+ if (j == 0) {
571
626
  if (phi_new <= (1 - ALPHA_IPM * step_size) * phi) {
572
627
  backtrack = false;
573
628
  sigma = (gap_new / gap);
@@ -578,14 +633,13 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
578
633
  step_size *= BETA_IPM;
579
634
  }
580
635
  }
581
- // ------------------------------------------------------------
582
- // For i == 1 we do a nonmonotone line search with the actual
583
- // search direction
584
- // ------------------------------------------------------------
636
+ /*
637
+ * For j == 1 we do a nonmonotone line search with the actual
638
+ * search direction
639
+ */
585
640
  else {
586
641
  if (relaxed_iters == -1 || MAX_RELAXED_ITERS == 0) {
587
642
  if (phi_new <= phi + ALPHA_IPM * step_size * dphi) {
588
- // relaxed_iters = 0;
589
643
  backtrack = false;
590
644
  } else {
591
645
  step_size *= BETA_IPM;
@@ -611,7 +665,6 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
611
665
  backtrack = false;
612
666
  } else if (relaxed_iters == MAX_RELAXED_ITERS) {
613
667
  if (phi_new <= phi0 + ALPHA_IPM * step_size0 * dphi0) {
614
- // relaxed_iters = 0;
615
668
  backtrack = false;
616
669
  } else {
617
670
  relaxed_iters = -1;
@@ -640,7 +693,7 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
640
693
  }
641
694
  }
642
695
 
643
- // update iterates
696
+ /* update iterates */
644
697
  memcpy(u1, u1_new, u1_dim * sizeof(*u1));
645
698
  r = rnew;
646
699
  memcpy(z, z_new, 3 * sizeof(*z));
@@ -651,7 +704,7 @@ scs_int log_cone_IPM(scs_float t0, scs_float v0, scs_float *x0, scs_float *u1,
651
704
  #endif
652
705
  }
653
706
 
654
- // unscale solution
707
+ /* unscale solution */
655
708
  scale1 = 1 / scale1;
656
709
  SCS(scale_array)(x0, scale1, n);
657
710
  SCS(scale_array)(u1, scale1, u1_dim);