scs 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +35 -6
  5. data/lib/scs/matrix.rb +72 -0
  6. data/lib/scs/solver.rb +19 -26
  7. data/lib/scs/version.rb +1 -1
  8. data/lib/scs.rb +1 -0
  9. data/vendor/scs/CITATION.cff +2 -2
  10. data/vendor/scs/CMakeLists.txt +285 -169
  11. data/vendor/scs/Makefile +43 -18
  12. data/vendor/scs/README.md +3 -1
  13. data/vendor/scs/include/cones.h +5 -3
  14. data/vendor/scs/include/glbopts.h +35 -17
  15. data/vendor/scs/include/linsys.h +8 -8
  16. data/vendor/scs/include/normalize.h +1 -0
  17. data/vendor/scs/include/rw.h +3 -3
  18. data/vendor/scs/include/scs.h +51 -24
  19. data/vendor/scs/include/scs_types.h +3 -1
  20. data/vendor/scs/include/scs_work.h +13 -15
  21. data/vendor/scs/include/util.h +4 -2
  22. data/vendor/scs/linsys/cpu/direct/private.c +32 -153
  23. data/vendor/scs/linsys/cpu/direct/private.h +6 -6
  24. data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
  25. data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
  26. data/vendor/scs/linsys/csparse.c +140 -12
  27. data/vendor/scs/linsys/csparse.h +10 -17
  28. data/vendor/scs/linsys/external/amd/LICENSE.txt +0 -897
  29. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +4 -2
  30. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +0 -5
  31. data/vendor/scs/linsys/gpu/gpu.c +4 -4
  32. data/vendor/scs/linsys/gpu/gpu.h +1 -1
  33. data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
  34. data/vendor/scs/linsys/mkl/direct/private.c +182 -0
  35. data/vendor/scs/linsys/mkl/direct/private.h +38 -0
  36. data/vendor/scs/linsys/scs_matrix.c +49 -72
  37. data/vendor/scs/linsys/scs_matrix.h +4 -3
  38. data/vendor/scs/scs.mk +39 -30
  39. data/vendor/scs/src/aa.c +0 -4
  40. data/vendor/scs/src/cones.c +78 -184
  41. data/vendor/scs/src/exp_cone.c +399 -0
  42. data/vendor/scs/src/normalize.c +51 -0
  43. data/vendor/scs/src/rw.c +139 -76
  44. data/vendor/scs/src/scs.c +275 -202
  45. data/vendor/scs/src/util.c +36 -13
  46. data/vendor/scs/test/minunit.h +2 -1
  47. data/vendor/scs/test/problem_utils.h +5 -4
  48. data/vendor/scs/test/problems/degenerate.h +1 -0
  49. data/vendor/scs/test/problems/hs21_tiny_qp.h +2 -1
  50. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +13 -4
  51. data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -0
  52. data/vendor/scs/test/problems/max_ent +0 -0
  53. data/vendor/scs/test/problems/max_ent.h +8 -0
  54. data/vendor/scs/test/problems/qafiro_tiny_qp.h +2 -1
  55. data/vendor/scs/test/problems/random_prob.h +2 -39
  56. data/vendor/scs/test/problems/rob_gauss_cov_est.h +15 -3
  57. data/vendor/scs/test/problems/small_lp.h +4 -1
  58. data/vendor/scs/test/problems/small_qp.h +42 -7
  59. data/vendor/scs/test/problems/test_exp_cone.h +84 -0
  60. data/vendor/scs/test/problems/test_prob_from_data_file.h +57 -0
  61. data/vendor/scs/test/problems/test_validation.h +4 -1
  62. data/vendor/scs/test/problems/unbounded_tiny_qp.h +3 -3
  63. data/vendor/scs/test/random_socp_prob.c +3 -1
  64. data/vendor/scs/test/run_from_file.c +22 -4
  65. data/vendor/scs/test/run_tests.c +22 -9
  66. metadata +12 -4
@@ -13,11 +13,12 @@ extern "C" {
13
13
  /* normalizes A matrix, sets scal->E and scal->D diagonal scaling matrices,
14
14
  * A -> D*A*E. D and E must be all positive entries, D must satisfy cone
15
15
  * boundaries */
16
- ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, scs_float *b,
17
- scs_float *c, ScsConeWork *cone);
16
+ ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, ScsConeWork *cone);
18
17
 
19
18
  /* unnormalizes A matrix, unnormalizes by w->D and w->E */
20
- void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling *scal);
19
+ /* void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling
20
+ * *scal);
21
+ */
21
22
 
22
23
  /* to free the memory allocated in a ScsMatrix (called on A and P at finish) */
23
24
  void SCS(free_scs_matrix)(ScsMatrix *A);
data/vendor/scs/scs.mk CHANGED
@@ -69,6 +69,7 @@ DIRSRC = $(LINSYS)/cpu/direct
69
69
  INDIRSRC = $(LINSYS)/cpu/indirect
70
70
  GPUDIR = $(LINSYS)/gpu/direct
71
71
  GPUINDIR = $(LINSYS)/gpu/indirect
72
+ MKLSRC = $(LINSYS)/mkl/direct
72
73
 
73
74
  EXTSRC = $(LINSYS)/external
74
75
 
@@ -83,48 +84,56 @@ ifeq ($(PREFIX),)
83
84
  PREFIX = /usr/local
84
85
  endif
85
86
 
86
- OPT_FLAGS =
87
- ########### OPTIONAL FLAGS ##########
87
+ ########### CUSTOM FLAGS ##########
88
88
  # these can all be override from the command line
89
+ CUSTOM_FLAGS =
89
90
  # e.g. make DLONG=1 will override the setting below
90
91
  DLONG = 0
91
92
  ifneq ($(DLONG), 0)
92
- OPT_FLAGS += -DDLONG=$(DLONG) # use longs rather than ints
93
+ CUSTOM_FLAGS += -DDLONG=$(DLONG) # use longs rather than ints
93
94
  endif
94
95
  CTRLC = 1
95
96
  ifneq ($(CTRLC), 0)
96
- OPT_FLAGS += -DCTRLC=$(CTRLC) # graceful interrupts with ctrl-c
97
+ CUSTOM_FLAGS += -DCTRLC=$(CTRLC) # graceful interrupts with ctrl-c
97
98
  endif
98
99
  SFLOAT = 0
99
100
  ifneq ($(SFLOAT), 0)
100
- OPT_FLAGS += -DSFLOAT=$(SFLOAT) # use floats rather than doubles
101
- endif
102
- NOTIMER = 0
103
- ifneq ($(NOTIMER), 0)
104
- OPT_FLAGS += -DNOTIMER=$(NOTIMER) # no timing, times reported as nan
105
- endif
106
- COPYAMATRIX = 1
107
- ifneq ($(COPYAMATRIX), 0)
108
- OPT_FLAGS += -DCOPYAMATRIX=$(COPYAMATRIX) # if normalize, copy A
101
+ CUSTOM_FLAGS += -DSFLOAT=$(SFLOAT) # use floats rather than doubles
109
102
  endif
110
103
  GPU_TRANSPOSE_MAT = 1
111
104
  ifneq ($(GPU_TRANSPOSE_MAT), 0)
112
- OPT_FLAGS += -DGPU_TRANSPOSE_MAT=$(GPU_TRANSPOSE_MAT) # tranpose A mat in GPU memory
105
+ CUSTOM_FLAGS += -DGPU_TRANSPOSE_MAT=$(GPU_TRANSPOSE_MAT) # transpose A mat in GPU memory
106
+ endif
107
+ NO_TIMER = 0
108
+ ifneq ($(NO_TIMER), 0)
109
+ CUSTOM_FLAGS += -DNO_TIMER=$(NO_TIMER) # no timing, times reported as nan
110
+ endif
111
+ NO_VALIDATE = 0
112
+ ifneq ($(NO_VALIDATE), 0)
113
+ CUSTOM_FLAGS += -DNO_VALIDATE=$(NO_VALIDATE) # perform problem validation or skip
114
+ endif
115
+ NO_PRINTING = 0
116
+ ifneq ($(NO_PRINTING), 0)
117
+ CUSTOM_FLAGS += -DNO_PRINTING=$(NO_PRINTING) # disable printing
113
118
  endif
114
- NOVALIDATE = 0
115
- ifneq ($(NOVALIDATE), 0)
116
- OPT_FLAGS += -DNOVALIDATE=$(NOVALIDATE) # perform problem validation or skip
119
+ NO_READ_WRITE = 0
120
+ ifneq ($(NO_READ_WRITE), 0)
121
+ CUSTOM_FLAGS += -DNO_READ_WRITE=$(NO_READ_WRITE) # disable printing
117
122
  endif
118
123
  ### VERBOSITY LEVELS: 0,1,2,...
119
124
  VERBOSITY = 0
120
125
  ifneq ($(VERBOSITY), 0)
121
- OPT_FLAGS += -DVERBOSITY=$(VERBOSITY) # verbosity level
126
+ CUSTOM_FLAGS += -DVERBOSITY=$(VERBOSITY) # verbosity level
122
127
  endif
123
128
  COVERAGE = 0
124
129
  ifneq ($(COVERAGE), 0)
125
- override CFLAGS += --coverage # generate test coverage data
130
+ CUSTOM_FLAGS += --coverage # generate test coverage data
126
131
  endif
127
132
 
133
+ # See: https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl-link-line-advisor.html
134
+ # This is probably not correct for other systems. TODO: update this
135
+ # to work for all combinations of platform / compiler / threading options.
136
+ MKLFLAGS = -L$(MKLROOT) -L$(MKLROOT)/lib -Wl,--no-as-needed -lmkl_rt -lmkl_gnu_thread -lmkl_core -lgomp -lpthread -ldl
128
137
 
129
138
  ############ OPENMP: ############
130
139
  # set USE_OPENMP = 1 to allow openmp (multi-threaded matrix multiplies):
@@ -142,44 +151,44 @@ endif
142
151
  # NB: point the libraries to the locations where
143
152
  # you have blas and lapack installed
144
153
 
154
+ BLASLDFLAGS =
145
155
  USE_LAPACK = 1
146
156
  ifneq ($(USE_LAPACK), 0)
147
157
  # edit these for your setup:
148
- BLASLDFLAGS = -llapack -lblas # -lgfortran
149
- LDFLAGS += $(BLASLDFLAGS)
150
- OPT_FLAGS += -DUSE_LAPACK
158
+ BLASLDFLAGS += -llapack -lblas # -lgfortran
159
+ CUSTOM_FLAGS += -DUSE_LAPACK
151
160
 
152
161
  BLAS64 = 0
153
162
  ifneq ($(BLAS64), 0)
154
- OPT_FLAGS += -DBLAS64=$(BLAS64) # if blas/lapack lib uses 64 bit ints
163
+ CUSTOM_FLAGS += -DBLAS64=$(BLAS64) # if blas/lapack lib uses 64 bit ints
155
164
  endif
156
165
 
157
166
  NOBLASSUFFIX = 0
158
167
  ifneq ($(NOBLASSUFFIX), 0)
159
- OPT_FLAGS += -DNOBLASSUFFIX=$(NOBLASSUFFIX) # hack to strip blas suffix
168
+ CUSTOM_FLAGS += -DNOBLASSUFFIX=$(NOBLASSUFFIX) # hack to strip blas suffix
160
169
  endif
161
170
 
162
171
  BLASSUFFIX = "_"
163
172
  ifneq ($(BLASSUFFIX), "_")
164
- OPT_FLAGS += -DBLASSUFFIX=$(BLASSUFFIX) # blas suffix (underscore usually)
173
+ CUSTOM_FLAGS += -DBLASSUFFIX=$(BLASSUFFIX) # blas suffix (underscore usually)
165
174
  endif
166
175
  endif
167
176
 
168
177
  MATLAB_MEX_FILE = 0
169
178
  ifneq ($(MATLAB_MEX_FILE), 0)
170
- OPT_FLAGS += -DMATLAB_MEX_FILE=$(MATLAB_MEX_FILE) # matlab mex
179
+ CUSTOM_FLAGS += -DMATLAB_MEX_FILE=$(MATLAB_MEX_FILE) # matlab mex
171
180
  endif
172
181
  PYTHON = 0
173
182
  ifneq ($(PYTHON), 0)
174
- OPT_FLAGS += -DPYTHON=$(PYTHON) # python extension
183
+ CUSTOM_FLAGS += -DPYTHON=$(PYTHON) # python extension
175
184
  endif
176
185
  USING_R = 0
177
186
  ifneq ($(USING_R), 0)
178
- OPT_FLAGS += -DUSING_R=$(USING_R) # R extension
187
+ CUSTOM_FLAGS += -DUSING_R=$(USING_R) # R extension
179
188
  endif
180
189
 
181
190
  # debug to see var values, e.g. 'make print-OBJECTS' shows OBJECTS value
182
191
  print-%: ; @echo $*=$($*)
183
192
 
184
- override CFLAGS += $(OPT_FLAGS)
185
- CUDAFLAGS += $(OPT_FLAGS)
193
+ override CFLAGS += $(CUSTOM_FLAGS)
194
+ CUDAFLAGS += $(CUSTOM_FLAGS)
data/vendor/scs/src/aa.c CHANGED
@@ -199,7 +199,6 @@ static void set_m(AaWork *a, aa_int len) {
199
199
  }
200
200
  }
201
201
  TIME_TOC
202
- return;
203
202
  }
204
203
 
205
204
  /* initialize accel params, in particular x_prev, f_prev, g_prev */
@@ -278,7 +277,6 @@ static void update_accel_params(const aa_float *x, const aa_float *f, AaWork *a,
278
277
  a->norm_g = BLAS(nrm2)(&bdim, a->g, &one);
279
278
 
280
279
  TIME_TOC
281
- return;
282
280
  }
283
281
 
284
282
  /* f = (1-relaxation) * \sum_i a_i x_i + relaxation * \sum_i a_i f_i */
@@ -493,7 +491,6 @@ void aa_finish(AaWork *a) {
493
491
  }
494
492
  free(a);
495
493
  }
496
- return;
497
494
  }
498
495
 
499
496
  void aa_reset(AaWork *a) {
@@ -502,7 +499,6 @@ void aa_reset(AaWork *a) {
502
499
  printf("AA reset.\n");
503
500
  }
504
501
  a->iter = 0;
505
- return;
506
502
  }
507
503
 
508
504
  #endif
@@ -4,10 +4,8 @@
4
4
  #include "scs_blas.h" /* contains BLAS(X) macros and type info */
5
5
  #include "util.h"
6
6
 
7
- #define CONE_TOL (1e-9)
8
- #define CONE_THRESH (1e-8)
9
- #define EXP_CONE_MAX_ITERS (100)
10
7
  #define BOX_CONE_MAX_ITERS (25)
8
+ #define POW_CONE_TOL (1e-9)
11
9
  #define POW_CONE_MAX_ITERS (20)
12
10
 
13
11
  /* Box cone limits (+ or -) taken to be INF */
@@ -35,6 +33,62 @@ void BLAS(scal)(const blas_int *n, const scs_float *sa, scs_float *sx,
35
33
 
36
34
  #endif
37
35
 
36
+ /* Forward declare exponential cone projection routine.
37
+ * Implemented in exp_cone.c.
38
+ */
39
+ scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal);
40
+
41
+ void SCS(free_cone)(ScsCone *k) {
42
+ if (k) {
43
+ if (k->bu)
44
+ scs_free(k->bu);
45
+ if (k->bl)
46
+ scs_free(k->bl);
47
+ if (k->q)
48
+ scs_free(k->q);
49
+ if (k->s)
50
+ scs_free(k->s);
51
+ if (k->p)
52
+ scs_free(k->p);
53
+ scs_free(k);
54
+ }
55
+ }
56
+
57
+ void SCS(deep_copy_cone)(ScsCone *dest, const ScsCone *src) {
58
+ memcpy(dest, src, sizeof(ScsCone));
59
+ /* copy bu, bl */
60
+ if (src->bsize > 1) {
61
+ dest->bu = (scs_float *)scs_calloc(src->bsize - 1, sizeof(scs_float));
62
+ memcpy(dest->bu, src->bu, (src->bsize - 1) * sizeof(scs_float));
63
+ dest->bl = (scs_float *)scs_calloc(src->bsize - 1, sizeof(scs_float));
64
+ memcpy(dest->bl, src->bl, (src->bsize - 1) * sizeof(scs_float));
65
+ } else {
66
+ dest->bu = SCS_NULL;
67
+ dest->bl = SCS_NULL;
68
+ }
69
+ /* copy SOC */
70
+ if (src->qsize > 0) {
71
+ dest->q = (scs_int *)scs_calloc(src->qsize, sizeof(scs_int));
72
+ memcpy(dest->q, src->q, src->qsize * sizeof(scs_int));
73
+ } else {
74
+ dest->q = SCS_NULL;
75
+ }
76
+ /* copy PSD cone */
77
+ if (src->ssize > 0) {
78
+ dest->s = (scs_int *)scs_calloc(src->ssize, sizeof(scs_int));
79
+ memcpy(dest->s, src->s, src->ssize * sizeof(scs_int));
80
+ } else {
81
+ dest->s = SCS_NULL;
82
+ }
83
+ /* copy power cone */
84
+ if (src->psize > 0) {
85
+ dest->p = (scs_float *)scs_calloc(src->psize, sizeof(scs_float));
86
+ memcpy(dest->p, src->p, src->psize * sizeof(scs_float));
87
+ } else {
88
+ dest->p = SCS_NULL;
89
+ }
90
+ }
91
+
38
92
  /* set the vector of rho y terms, based on scale and cones */
39
93
  void SCS(set_r_y)(const ScsConeWork *c, scs_float scale, scs_float *r_y) {
40
94
  scs_int i;
@@ -228,19 +282,13 @@ void SCS(finish_cone)(ScsConeWork *c) {
228
282
  if (c->s) {
229
283
  scs_free(c->s);
230
284
  }
231
- if (c->bu) {
232
- scs_free(c->bu);
233
- }
234
- if (c->bl) {
235
- scs_free(c->bl);
236
- }
237
285
  if (c) {
238
286
  scs_free(c);
239
287
  }
240
288
  }
241
289
 
242
290
  char *SCS(get_cone_header)(const ScsCone *k) {
243
- char *tmp = (char *)scs_malloc(sizeof(char) * 512);
291
+ char *tmp = (char *)scs_malloc(512); /* sizeof(char) = 1 */
244
292
  scs_int i, soc_vars, sd_vars;
245
293
  sprintf(tmp, "cones: ");
246
294
  if (k->z) {
@@ -280,118 +328,6 @@ char *SCS(get_cone_header)(const ScsCone *k) {
280
328
  return tmp;
281
329
  }
282
330
 
283
- static scs_float exp_newton_one_d(scs_float rho, scs_float y_hat,
284
- scs_float z_hat, scs_float w) {
285
- scs_float t_prev, t = MAX(w - z_hat, MAX(-z_hat, 1e-9));
286
- scs_float f = 1., fp = 1.;
287
- scs_int i;
288
- for (i = 0; i < EXP_CONE_MAX_ITERS; ++i) {
289
- t_prev = t;
290
- f = t * (t + z_hat) / rho / rho - y_hat / rho + log(t / rho) + 1;
291
- fp = (2 * t + z_hat) / rho / rho + 1 / t;
292
-
293
- t = t - f / fp;
294
-
295
- if (t <= -z_hat) {
296
- t = -z_hat;
297
- break;
298
- } else if (t <= 0) {
299
- t = 0;
300
- break;
301
- } else if (ABS(t - t_prev) < CONE_TOL) {
302
- break;
303
- } else if (SQRTF(f * f / fp) < CONE_TOL) {
304
- break;
305
- }
306
- }
307
- if (i == EXP_CONE_MAX_ITERS) {
308
- scs_printf("warning: exp cone newton step hit maximum %i iters\n", (int)i);
309
- scs_printf("rho=%1.5e; y_hat=%1.5e; z_hat=%1.5e; w=%1.5e; f=%1.5e, "
310
- "fp=%1.5e, t=%1.5e, t_prev= %1.5e\n",
311
- rho, y_hat, z_hat, w, f, fp, t, t_prev);
312
- }
313
- return t + z_hat;
314
- }
315
-
316
- static void exp_solve_for_x_with_rho(const scs_float *v, scs_float *x,
317
- scs_float rho, scs_float w) {
318
- x[2] = exp_newton_one_d(rho, v[1], v[2], w);
319
- x[1] = (x[2] - v[2]) * x[2] / rho;
320
- x[0] = v[0] - rho;
321
- }
322
-
323
- static scs_float exp_calc_grad(const scs_float *v, scs_float *x, scs_float rho,
324
- scs_float w) {
325
- exp_solve_for_x_with_rho(v, x, rho, w);
326
- if (x[1] <= 1e-12) {
327
- return x[0];
328
- }
329
- return x[0] + x[1] * log(x[1] / x[2]);
330
- }
331
-
332
- static void exp_get_rho_ub(const scs_float *v, scs_float *x, scs_float *ub,
333
- scs_float *lb) {
334
- *lb = 0;
335
- *ub = 0.125;
336
- while (exp_calc_grad(v, x, *ub, v[1]) > 0) {
337
- *lb = *ub;
338
- (*ub) *= 2;
339
- }
340
- }
341
-
342
- /* project onto the exponential cone, v has dimension *exactly* 3 */
343
- static scs_int proj_exp_cone(scs_float *v) {
344
- scs_int i;
345
- scs_float ub, lb, rho, g, x[3];
346
- scs_float r = v[0], s = v[1], t = v[2];
347
-
348
- /* v in cl(Kexp) */
349
- if ((s * exp(r / s) - t <= CONE_THRESH && s > 0) ||
350
- (r <= 0 && s == 0 && t >= 0)) {
351
- return 0;
352
- }
353
-
354
- /* -v in Kexp^* */
355
- if ((r > 0 && r * exp(s / r) + exp(1) * t <= CONE_THRESH) ||
356
- (r == 0 && s <= 0 && t <= 0)) {
357
- memset(v, 0, 3 * sizeof(scs_float));
358
- return 0;
359
- }
360
-
361
- /* special case with analytical solution */
362
- if (r < 0 && s < 0) {
363
- v[1] = 0.0;
364
- v[2] = MAX(v[2], 0);
365
- return 0;
366
- }
367
-
368
- /* iterative procedure to find projection, bisects on dual variable: */
369
- exp_get_rho_ub(v, x, &ub, &lb); /* get starting upper and lower bounds */
370
- for (i = 0; i < EXP_CONE_MAX_ITERS; ++i) {
371
- rho = (ub + lb) / 2; /* halfway between upper and lower bounds */
372
- g = exp_calc_grad(v, x, rho, x[1]); /* calculates gradient wrt dual var */
373
- if (g > 0) {
374
- lb = rho;
375
- } else {
376
- ub = rho;
377
- }
378
- if (ub - lb < CONE_TOL) {
379
- break;
380
- }
381
- }
382
- #if VERBOSITY > 10
383
- scs_printf("exponential cone proj iters %i\n", (int)i);
384
- #endif
385
- if (i == EXP_CONE_MAX_ITERS) {
386
- scs_printf("warning: exp cone outer step hit maximum %i iters\n", (int)i);
387
- scs_printf("r=%1.5e; s=%1.5e; t=%1.5e\n", r, s, t);
388
- }
389
- v[0] = x[0];
390
- v[1] = x[1];
391
- v[2] = x[2];
392
- return 0;
393
- }
394
-
395
331
  static scs_int set_up_sd_cone_work_space(ScsConeWork *c, const ScsCone *k) {
396
332
  scs_int i;
397
333
  #ifdef USE_LAPACK
@@ -580,18 +516,18 @@ static scs_float pow_calc_fp(scs_float x, scs_float y, scs_float dxdr,
580
516
  * { (t', s') | t' * l' <= s' <= t' u', t >= 0 } = K'
581
517
  * where l' = D l / d0, u' = D u / d0.
582
518
  */
583
- static void normalize_box_cone(ScsConeWork *c, scs_float *D, scs_int bsize) {
519
+ static void normalize_box_cone(ScsCone *k, scs_float *D, scs_int bsize) {
584
520
  scs_int j;
585
521
  for (j = 0; j < bsize - 1; j++) {
586
- if (c->bu[j] >= MAX_BOX_VAL) {
587
- c->bu[j] = INFINITY;
522
+ if (k->bu[j] >= MAX_BOX_VAL) {
523
+ k->bu[j] = INFINITY;
588
524
  } else {
589
- c->bu[j] = D ? D[j + 1] * c->bu[j] / D[0] : c->bu[j];
525
+ k->bu[j] = D ? D[j + 1] * k->bu[j] / D[0] : k->bu[j];
590
526
  }
591
- if (c->bl[j] <= -MAX_BOX_VAL) {
592
- c->bl[j] = -INFINITY;
527
+ if (k->bl[j] <= -MAX_BOX_VAL) {
528
+ k->bl[j] = -INFINITY;
593
529
  } else {
594
- c->bl[j] = D ? D[j + 1] * c->bl[j] / D[0] : c->bl[j];
530
+ k->bl[j] = D ? D[j + 1] * k->bl[j] / D[0] : k->bl[j];
595
531
  }
596
532
  }
597
533
  }
@@ -696,13 +632,13 @@ static void proj_power_cone(scs_float *v, scs_float a) {
696
632
  scs_int i;
697
633
  /* v in K_a */
698
634
  if (xh >= 0 && yh >= 0 &&
699
- CONE_THRESH + POWF(xh, a) * POWF(yh, (1 - a)) >= rh) {
635
+ POW_CONE_TOL + POWF(xh, a) * POWF(yh, (1 - a)) >= rh) {
700
636
  return;
701
637
  }
702
638
 
703
639
  /* -v in K_a^* */
704
640
  if (xh <= 0 && yh <= 0 &&
705
- CONE_THRESH + POWF(-xh, a) * POWF(-yh, 1 - a) >=
641
+ POW_CONE_TOL + POWF(-xh, a) * POWF(-yh, 1 - a) >=
706
642
  rh * POWF(a, a) * POWF(1 - a, 1 - a)) {
707
643
  v[0] = v[1] = v[2] = 0;
708
644
  return;
@@ -715,7 +651,7 @@ static void proj_power_cone(scs_float *v, scs_float a) {
715
651
  y = pow_calc_x(r, yh, rh, 1 - a);
716
652
 
717
653
  f = pow_calc_f(x, y, r, a);
718
- if (ABS(f) < CONE_TOL) {
654
+ if (ABS(f) < POW_CONE_TOL) {
719
655
  break;
720
656
  }
721
657
 
@@ -740,7 +676,6 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
740
676
  scs_int i, status;
741
677
  scs_int count = 0;
742
678
  scs_float *r_box = SCS_NULL;
743
- scs_float *bu, *bl;
744
679
 
745
680
  if (k->z) { /* doesn't use r_y */
746
681
  /* project onto primal zero / dual free cone */
@@ -761,9 +696,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
761
696
  r_box = &(r_y[count]);
762
697
  }
763
698
  /* project onto box cone */
764
- bu = normalize ? c->bu : k->bu;
765
- bl = normalize ? c->bl : k->bl;
766
- c->box_t_warm_start = proj_box_cone(&(x[count]), bl, bu, k->bsize,
699
+ c->box_t_warm_start = proj_box_cone(&(x[count]), k->bl, k->bu, k->bsize,
767
700
  c->box_t_warm_start, r_box);
768
701
  count += k->bsize; /* since b = (t,s), len(s) = bsize - 1 */
769
702
  }
@@ -787,51 +720,16 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
787
720
  }
788
721
  }
789
722
 
790
- if (k->ep) { /* doesn't use r_y */
791
- /*
792
- * exponential cone is not self dual, if s \in K
793
- * then y \in K^* and so if K is the primal cone
794
- * here we project onto K^*, via Moreau
795
- * \Pi_C^*(y) = y + \Pi_C(-y)
796
- */
723
+ if (k->ep || k->ed) { /* doesn't use r_y */
797
724
  #ifdef _OPENMP
798
725
  #pragma omp parallel for
799
726
  #endif
800
- for (i = 0; i < k->ep; ++i) {
801
- proj_exp_cone(&(x[count + 3 * i]));
727
+ for (i = 0; i < k->ep + k->ed; ++i) {
728
+ /* provided in exp_cone.c */
729
+ SCS(proj_pd_exp_cone)(&(x[count + 3 * i]), i < k->ep);
802
730
  }
803
- count += 3 * k->ep;
731
+ count += 3 * (k->ep + k->ed);
804
732
  }
805
-
806
- /* dual exponential cone */
807
- if (k->ed) { /* doesn't use r_y */
808
- /*
809
- * exponential cone is not self dual, if s \in K
810
- * then y \in K^* and so if K is the primal cone
811
- * here we project onto K^*, via Moreau
812
- * \Pi_C^*(y) = y + \Pi_C(-y)
813
- */
814
- scs_int idx;
815
- scs_float r, s, t;
816
- SCS(scale_array)(&(x[count]), -1, 3 * k->ed); /* x = -x; */
817
- #ifdef _OPENMP
818
- #pragma omp parallel for private(r, s, t, idx)
819
- #endif
820
- for (i = 0; i < k->ed; ++i) {
821
- idx = count + 3 * i;
822
- r = x[idx];
823
- s = x[idx + 1];
824
- t = x[idx + 2];
825
-
826
- proj_exp_cone(&(x[idx]));
827
-
828
- x[idx] -= r;
829
- x[idx + 1] -= s;
830
- x[idx + 2] -= t;
831
- }
832
- count += 3 * k->ed;
833
- }
834
-
835
733
  if (k->psize && k->p) { /* doesn't use r_y */
836
734
  scs_float v[3];
837
735
  scs_int idx;
@@ -864,7 +762,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
864
762
  return 0;
865
763
  }
866
764
 
867
- ScsConeWork *SCS(init_cone)(const ScsCone *k, scs_int m) {
765
+ ScsConeWork *SCS(init_cone)(ScsCone *k, scs_int m) {
868
766
  ScsConeWork *c = (ScsConeWork *)scs_calloc(1, sizeof(ScsConeWork));
869
767
  c->k = k;
870
768
  c->m = m;
@@ -880,16 +778,12 @@ ScsConeWork *SCS(init_cone)(const ScsCone *k, scs_int m) {
880
778
  return c;
881
779
  }
882
780
 
883
- void scale_box_cone(const ScsCone *k, ScsConeWork *c, ScsScaling *scal) {
781
+ void scale_box_cone(ScsCone *k, ScsConeWork *c, ScsScaling *scal) {
884
782
  if (k->bsize && k->bu && k->bl) {
885
783
  c->box_t_warm_start = 1.;
886
784
  if (scal) {
887
- c->bu = (scs_float *)scs_calloc(k->bsize - 1, sizeof(scs_float));
888
- c->bl = (scs_float *)scs_calloc(k->bsize - 1, sizeof(scs_float));
889
- memcpy(c->bu, k->bu, (k->bsize - 1) * sizeof(scs_float));
890
- memcpy(c->bl, k->bl, (k->bsize - 1) * sizeof(scs_float));
891
785
  /* also does some sanitizing */
892
- normalize_box_cone(c, &(scal->D[k->z + k->l]), k->bsize);
786
+ normalize_box_cone(k, &(scal->D[k->z + k->l]), k->bsize);
893
787
  }
894
788
  }
895
789
  }
@@ -909,7 +803,7 @@ void scale_box_cone(const ScsCone *k, ScsConeWork *c, ScsScaling *scal) {
909
803
  scs_int SCS(proj_dual_cone)(scs_float *x, ScsConeWork *c, ScsScaling *scal,
910
804
  scs_float *r_y) {
911
805
  scs_int status, i;
912
- const ScsCone *k = c->k;
806
+ ScsCone *k = c->k;
913
807
 
914
808
  if (!c->scaled_cones) {
915
809
  scale_box_cone(k, c, scal);