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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/LICENSE.txt +1 -1
- data/README.md +35 -6
- data/lib/scs/matrix.rb +72 -0
- data/lib/scs/solver.rb +19 -26
- data/lib/scs/version.rb +1 -1
- data/lib/scs.rb +1 -0
- data/vendor/scs/CITATION.cff +2 -2
- data/vendor/scs/CMakeLists.txt +285 -169
- data/vendor/scs/Makefile +43 -18
- data/vendor/scs/README.md +3 -1
- data/vendor/scs/include/cones.h +5 -3
- data/vendor/scs/include/glbopts.h +35 -17
- data/vendor/scs/include/linsys.h +8 -8
- data/vendor/scs/include/normalize.h +1 -0
- data/vendor/scs/include/rw.h +3 -3
- data/vendor/scs/include/scs.h +51 -24
- data/vendor/scs/include/scs_types.h +3 -1
- data/vendor/scs/include/scs_work.h +13 -15
- data/vendor/scs/include/util.h +4 -2
- data/vendor/scs/linsys/cpu/direct/private.c +32 -153
- data/vendor/scs/linsys/cpu/direct/private.h +6 -6
- data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
- data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
- data/vendor/scs/linsys/csparse.c +140 -12
- data/vendor/scs/linsys/csparse.h +10 -17
- data/vendor/scs/linsys/external/amd/LICENSE.txt +0 -897
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +4 -2
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +0 -5
- data/vendor/scs/linsys/gpu/gpu.c +4 -4
- data/vendor/scs/linsys/gpu/gpu.h +1 -1
- data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
- data/vendor/scs/linsys/mkl/direct/private.c +182 -0
- data/vendor/scs/linsys/mkl/direct/private.h +38 -0
- data/vendor/scs/linsys/scs_matrix.c +49 -72
- data/vendor/scs/linsys/scs_matrix.h +4 -3
- data/vendor/scs/scs.mk +39 -30
- data/vendor/scs/src/aa.c +0 -4
- data/vendor/scs/src/cones.c +78 -184
- data/vendor/scs/src/exp_cone.c +399 -0
- data/vendor/scs/src/normalize.c +51 -0
- data/vendor/scs/src/rw.c +139 -76
- data/vendor/scs/src/scs.c +275 -202
- data/vendor/scs/src/util.c +36 -13
- data/vendor/scs/test/minunit.h +2 -1
- data/vendor/scs/test/problem_utils.h +5 -4
- data/vendor/scs/test/problems/degenerate.h +1 -0
- data/vendor/scs/test/problems/hs21_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +13 -4
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -0
- data/vendor/scs/test/problems/max_ent +0 -0
- data/vendor/scs/test/problems/max_ent.h +8 -0
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/random_prob.h +2 -39
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +15 -3
- data/vendor/scs/test/problems/small_lp.h +4 -1
- data/vendor/scs/test/problems/small_qp.h +42 -7
- data/vendor/scs/test/problems/test_exp_cone.h +84 -0
- data/vendor/scs/test/problems/test_prob_from_data_file.h +57 -0
- data/vendor/scs/test/problems/test_validation.h +4 -1
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +3 -3
- data/vendor/scs/test/random_socp_prob.c +3 -1
- data/vendor/scs/test/run_from_file.c +22 -4
- data/vendor/scs/test/run_tests.c +22 -9
- 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,
|
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
|
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
|
-
|
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
|
-
|
93
|
+
CUSTOM_FLAGS += -DDLONG=$(DLONG) # use longs rather than ints
|
93
94
|
endif
|
94
95
|
CTRLC = 1
|
95
96
|
ifneq ($(CTRLC), 0)
|
96
|
-
|
97
|
+
CUSTOM_FLAGS += -DCTRLC=$(CTRLC) # graceful interrupts with ctrl-c
|
97
98
|
endif
|
98
99
|
SFLOAT = 0
|
99
100
|
ifneq ($(SFLOAT), 0)
|
100
|
-
|
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
|
-
|
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
|
-
|
115
|
-
ifneq ($(
|
116
|
-
|
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
|
-
|
126
|
+
CUSTOM_FLAGS += -DVERBOSITY=$(VERBOSITY) # verbosity level
|
122
127
|
endif
|
123
128
|
COVERAGE = 0
|
124
129
|
ifneq ($(COVERAGE), 0)
|
125
|
-
|
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
|
149
|
-
|
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
|
-
|
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
|
-
|
168
|
+
CUSTOM_FLAGS += -DNOBLASSUFFIX=$(NOBLASSUFFIX) # hack to strip blas suffix
|
160
169
|
endif
|
161
170
|
|
162
171
|
BLASSUFFIX = "_"
|
163
172
|
ifneq ($(BLASSUFFIX), "_")
|
164
|
-
|
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
|
-
|
179
|
+
CUSTOM_FLAGS += -DMATLAB_MEX_FILE=$(MATLAB_MEX_FILE) # matlab mex
|
171
180
|
endif
|
172
181
|
PYTHON = 0
|
173
182
|
ifneq ($(PYTHON), 0)
|
174
|
-
|
183
|
+
CUSTOM_FLAGS += -DPYTHON=$(PYTHON) # python extension
|
175
184
|
endif
|
176
185
|
USING_R = 0
|
177
186
|
ifneq ($(USING_R), 0)
|
178
|
-
|
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 += $(
|
185
|
-
CUDAFLAGS += $(
|
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
|
data/vendor/scs/src/cones.c
CHANGED
@@ -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)
|
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(
|
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 (
|
587
|
-
|
522
|
+
if (k->bu[j] >= MAX_BOX_VAL) {
|
523
|
+
k->bu[j] = INFINITY;
|
588
524
|
} else {
|
589
|
-
|
525
|
+
k->bu[j] = D ? D[j + 1] * k->bu[j] / D[0] : k->bu[j];
|
590
526
|
}
|
591
|
-
if (
|
592
|
-
|
527
|
+
if (k->bl[j] <= -MAX_BOX_VAL) {
|
528
|
+
k->bl[j] = -INFINITY;
|
593
529
|
} else {
|
594
|
-
|
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
|
-
|
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
|
-
|
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) <
|
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
|
-
|
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
|
-
|
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)(
|
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(
|
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(
|
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
|
-
|
806
|
+
ScsCone *k = c->k;
|
913
807
|
|
914
808
|
if (!c->scaled_cones) {
|
915
809
|
scale_box_cone(k, c, scal);
|