scs 0.3.2 → 0.4.1

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 (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);