scs 0.3.2 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|