scs 0.4.0 → 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 +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +2 -2
- data/vendor/scs/CMakeLists.txt +284 -168
- data/vendor/scs/Makefile +43 -18
- data/vendor/scs/README.md +1 -1
- data/vendor/scs/include/glbopts.h +32 -13
- data/vendor/scs/include/linsys.h +8 -8
- data/vendor/scs/include/scs.h +6 -2
- data/vendor/scs/include/scs_types.h +3 -1
- data/vendor/scs/include/scs_work.h +9 -8
- data/vendor/scs/include/util.h +1 -1
- 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/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 +11 -5
- data/vendor/scs/scs.mk +39 -26
- data/vendor/scs/src/cones.c +15 -159
- data/vendor/scs/src/exp_cone.c +399 -0
- data/vendor/scs/src/normalize.c +4 -2
- data/vendor/scs/src/rw.c +93 -38
- data/vendor/scs/src/scs.c +83 -52
- data/vendor/scs/src/util.c +12 -3
- data/vendor/scs/test/minunit.h +2 -1
- data/vendor/scs/test/problem_utils.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +8 -3
- data/vendor/scs/test/problems/max_ent +0 -0
- data/vendor/scs/test/problems/max_ent.h +8 -0
- data/vendor/scs/test/problems/random_prob.h +2 -43
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +7 -2
- 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/run_from_file.c +7 -1
- data/vendor/scs/test/run_tests.c +22 -9
- metadata +10 -3
@@ -0,0 +1,399 @@
|
|
1
|
+
#include "cones.h"
|
2
|
+
#include "glbopts.h"
|
3
|
+
#include "linalg.h"
|
4
|
+
#include "scs.h"
|
5
|
+
|
6
|
+
#define EXP_CONE_INFINITY_VALUE (1E15)
|
7
|
+
|
8
|
+
/*
|
9
|
+
* Exponential cone projection routines, from:
|
10
|
+
*
|
11
|
+
* Projection onto the exponential cone: a univariate root-finding problem,
|
12
|
+
* by Henrik A. Friberg, 2021.
|
13
|
+
*
|
14
|
+
*/
|
15
|
+
|
16
|
+
static inline scs_int _isfinite(scs_float x) {
|
17
|
+
return ABS(x) < EXP_CONE_INFINITY_VALUE;
|
18
|
+
}
|
19
|
+
|
20
|
+
static inline scs_float _clip(scs_float x, scs_float l, scs_float u) {
|
21
|
+
return MAX(l, MIN(u, x));
|
22
|
+
}
|
23
|
+
|
24
|
+
/* As defined in Friberg, 2021 (multiplied by positive polynomial) */
|
25
|
+
static void hfun(const scs_float *v0, scs_float rho, scs_float *f,
|
26
|
+
scs_float *df) {
|
27
|
+
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
28
|
+
scs_float exprho = exp(rho);
|
29
|
+
scs_float expnegrho = exp(-rho);
|
30
|
+
/* function value at v0 */
|
31
|
+
*f = ((rho - 1) * r0 + s0) * exprho - (r0 - rho * s0) * expnegrho -
|
32
|
+
(rho * (rho - 1) + 1) * t0;
|
33
|
+
/* gradient of function at v0 */
|
34
|
+
*df = (rho * r0 + s0) * exprho + (r0 - (rho - 1) * s0) * expnegrho -
|
35
|
+
(2 * rho - 1) * t0;
|
36
|
+
}
|
37
|
+
|
38
|
+
/* Binary search for the root of the hfun function */
|
39
|
+
static scs_float root_search_binary(const scs_float *v0, scs_float xl,
|
40
|
+
scs_float xu, scs_float x) {
|
41
|
+
#if VERBOSITY > 0
|
42
|
+
scs_printf("Exp cone: Newton method failed, resorting to binary search.\n");
|
43
|
+
#endif
|
44
|
+
const scs_float EPS = 1e-12; /* expensive so loosen tol */
|
45
|
+
const scs_int MAXITER = 40;
|
46
|
+
scs_int i;
|
47
|
+
scs_float x_plus = x, f, df;
|
48
|
+
for (i = 0; i < MAXITER; i++) {
|
49
|
+
hfun(v0, x, &f, &df);
|
50
|
+
if (f < 0.0) {
|
51
|
+
xl = x;
|
52
|
+
} else {
|
53
|
+
xu = x;
|
54
|
+
}
|
55
|
+
/* binary search step */
|
56
|
+
x_plus = 0.5 * (xl + xu);
|
57
|
+
if (ABS(x_plus - x) <= EPS * MAX(1., ABS(x_plus)) || (x_plus == xl) ||
|
58
|
+
(x_plus == xu)) {
|
59
|
+
break;
|
60
|
+
}
|
61
|
+
x = x_plus;
|
62
|
+
}
|
63
|
+
return x_plus;
|
64
|
+
}
|
65
|
+
|
66
|
+
/* Use damped Newton's to find the root of the hfun function */
|
67
|
+
static scs_float root_search_newton(const scs_float *v0, scs_float xl,
|
68
|
+
scs_float xu, scs_float x) {
|
69
|
+
/* params taken from Friberg code */
|
70
|
+
const scs_float EPS = 1e-15;
|
71
|
+
const scs_float DFTOL = 1e-13; /* pow(EPS, 6.0 / 7.0) */
|
72
|
+
const scs_int MAXITER = 20;
|
73
|
+
const scs_float LODAMP = 0.05;
|
74
|
+
const scs_float HIDAMP = 0.95;
|
75
|
+
|
76
|
+
scs_float x_plus, f, df;
|
77
|
+
scs_int i;
|
78
|
+
|
79
|
+
for (i = 0; i < MAXITER; i++) {
|
80
|
+
hfun(v0, x, &f, &df);
|
81
|
+
|
82
|
+
if (ABS(f) <= EPS) { /* root found */
|
83
|
+
break;
|
84
|
+
}
|
85
|
+
|
86
|
+
if (f < 0.0) {
|
87
|
+
xl = x;
|
88
|
+
} else {
|
89
|
+
xu = x;
|
90
|
+
}
|
91
|
+
|
92
|
+
if (xu <= xl) {
|
93
|
+
xu = 0.5 * (xu + xl);
|
94
|
+
xl = xu;
|
95
|
+
break;
|
96
|
+
}
|
97
|
+
|
98
|
+
if (!_isfinite(f) || df < DFTOL) {
|
99
|
+
break;
|
100
|
+
}
|
101
|
+
|
102
|
+
/* Newton step */
|
103
|
+
x_plus = x - f / df;
|
104
|
+
|
105
|
+
if (ABS(x_plus - x) <= EPS * MAX(1., ABS(x_plus))) {
|
106
|
+
break;
|
107
|
+
}
|
108
|
+
|
109
|
+
if (x_plus >= xu) {
|
110
|
+
x = MIN(LODAMP * x + HIDAMP * xu, xu);
|
111
|
+
} else if (x_plus <= xl) {
|
112
|
+
x = MAX(LODAMP * x + HIDAMP * xl, xl);
|
113
|
+
} else {
|
114
|
+
x = x_plus;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
if (i < MAXITER) { /* Newton's method converged */
|
118
|
+
#if VERBOSITY > 0
|
119
|
+
scs_printf("Exp cone: Newton iters:%i, f:%.4e, df:%.4e\n", (int)i, f, df);
|
120
|
+
#endif
|
121
|
+
return _clip(x, xl, xu);
|
122
|
+
}
|
123
|
+
/* Fall back to binary search if Newton failed */
|
124
|
+
return root_search_binary(v0, xl, xu, x);
|
125
|
+
}
|
126
|
+
|
127
|
+
/* try heuristic (cheap) projection */
|
128
|
+
static scs_float proj_primal_exp_cone_heuristic(const scs_float *v0,
|
129
|
+
scs_float *vp) {
|
130
|
+
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
131
|
+
scs_float dist, tp, newdist;
|
132
|
+
/* perspective boundary */
|
133
|
+
vp[2] = MAX(t0, 0);
|
134
|
+
vp[1] = 0.0;
|
135
|
+
vp[0] = MIN(r0, 0);
|
136
|
+
dist = SCS(norm_diff)(v0, vp, 3);
|
137
|
+
|
138
|
+
/* perspective interior */
|
139
|
+
if (s0 > 0.0) {
|
140
|
+
tp = MAX(t0, s0 * exp(r0 / s0));
|
141
|
+
newdist = tp - t0;
|
142
|
+
if (newdist < dist) {
|
143
|
+
vp[2] = tp;
|
144
|
+
vp[1] = s0;
|
145
|
+
vp[0] = r0;
|
146
|
+
dist = newdist;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
return dist;
|
150
|
+
}
|
151
|
+
|
152
|
+
/* try heuristic (cheap) projection */
|
153
|
+
static scs_float proj_polar_exp_cone_heuristic(const scs_float *v0,
|
154
|
+
scs_float *vd) {
|
155
|
+
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
156
|
+
scs_float dist, td, newdist;
|
157
|
+
/* perspective boundary */
|
158
|
+
vd[2] = MIN(t0, 0);
|
159
|
+
vd[1] = MIN(s0, 0);
|
160
|
+
vd[0] = 0.0;
|
161
|
+
dist = SCS(norm_diff)(v0, vd, 3);
|
162
|
+
|
163
|
+
/* perspective interior */
|
164
|
+
if (r0 > 0.0) {
|
165
|
+
td = MIN(t0, -r0 * exp(s0 / r0 - 1));
|
166
|
+
newdist = t0 - td;
|
167
|
+
if (newdist < dist) {
|
168
|
+
vd[2] = td;
|
169
|
+
vd[1] = s0;
|
170
|
+
vd[0] = r0;
|
171
|
+
dist = newdist;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
return dist;
|
175
|
+
}
|
176
|
+
|
177
|
+
static scs_float ppsi(const scs_float *v0) {
|
178
|
+
scs_float s0 = v0[1], r0 = v0[0];
|
179
|
+
scs_float psi;
|
180
|
+
|
181
|
+
if (r0 > s0) {
|
182
|
+
psi = (r0 - s0 + sqrt(r0 * r0 + s0 * s0 - r0 * s0)) / r0;
|
183
|
+
} else {
|
184
|
+
psi = -s0 / (r0 - s0 - sqrt(r0 * r0 + s0 * s0 - r0 * s0));
|
185
|
+
}
|
186
|
+
|
187
|
+
return ((psi - 1) * r0 + s0) / (psi * (psi - 1) + 1);
|
188
|
+
}
|
189
|
+
|
190
|
+
static scs_float pomega(scs_float rho) {
|
191
|
+
scs_float val = exp(rho) / (rho * (rho - 1) + 1);
|
192
|
+
|
193
|
+
if (rho < 2.0) {
|
194
|
+
val = MIN(val, exp(2.0) / 3);
|
195
|
+
}
|
196
|
+
|
197
|
+
return val;
|
198
|
+
}
|
199
|
+
|
200
|
+
static scs_float dpsi(const scs_float *v0) {
|
201
|
+
scs_float s0 = v0[1], r0 = v0[0];
|
202
|
+
scs_float psi;
|
203
|
+
|
204
|
+
if (s0 > r0) {
|
205
|
+
psi = (r0 - sqrt(r0 * r0 + s0 * s0 - r0 * s0)) / s0;
|
206
|
+
} else {
|
207
|
+
psi = (r0 - s0) / (r0 + sqrt(r0 * r0 + s0 * s0 - r0 * s0));
|
208
|
+
}
|
209
|
+
|
210
|
+
return (r0 - psi * s0) / (psi * (psi - 1) + 1);
|
211
|
+
}
|
212
|
+
|
213
|
+
static scs_float domega(scs_float rho) {
|
214
|
+
scs_float val = -exp(-rho) / (rho * (rho - 1) + 1);
|
215
|
+
|
216
|
+
if (rho > -1.0) {
|
217
|
+
val = MAX(val, -exp(1.0) / 3);
|
218
|
+
}
|
219
|
+
|
220
|
+
return val;
|
221
|
+
}
|
222
|
+
|
223
|
+
/* Generate upper and lower search bounds for root of hfun */
|
224
|
+
static void exp_search_bracket(const scs_float *v0, scs_float pdist,
|
225
|
+
scs_float ddist, scs_float *low_out,
|
226
|
+
scs_float *upr_out) {
|
227
|
+
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
228
|
+
scs_float baselow = -EXP_CONE_INFINITY_VALUE,
|
229
|
+
baseupr = EXP_CONE_INFINITY_VALUE;
|
230
|
+
scs_float low = -EXP_CONE_INFINITY_VALUE, upr = EXP_CONE_INFINITY_VALUE;
|
231
|
+
|
232
|
+
scs_float Dp = SQRTF(pdist * pdist - MIN(s0, 0) * MIN(s0, 0));
|
233
|
+
scs_float Dd = SQRTF(ddist * ddist - MIN(r0, 0) * MIN(r0, 0));
|
234
|
+
|
235
|
+
scs_float curbnd, fl, fu, df, tpu, tdl;
|
236
|
+
|
237
|
+
if (t0 > 0) {
|
238
|
+
curbnd = log(t0 / ppsi(v0));
|
239
|
+
low = MAX(low, curbnd);
|
240
|
+
} else if (t0 < 0) {
|
241
|
+
curbnd = -log(-t0 / dpsi(v0));
|
242
|
+
upr = MIN(upr, curbnd);
|
243
|
+
}
|
244
|
+
|
245
|
+
if (r0 > 0) {
|
246
|
+
baselow = 1 - s0 / r0;
|
247
|
+
low = MAX(low, baselow);
|
248
|
+
tpu = MAX(1e-12, MIN(Dd, Dp + t0));
|
249
|
+
curbnd = MAX(low, baselow + tpu / r0 / pomega(low));
|
250
|
+
upr = MIN(upr, curbnd);
|
251
|
+
}
|
252
|
+
|
253
|
+
if (s0 > 0) {
|
254
|
+
baseupr = r0 / s0;
|
255
|
+
upr = MIN(upr, baseupr);
|
256
|
+
tdl = -MAX(1e-12, MIN(Dp, Dd - t0));
|
257
|
+
curbnd = MIN(upr, baseupr - tdl / s0 / domega(upr));
|
258
|
+
low = MAX(low, curbnd);
|
259
|
+
}
|
260
|
+
|
261
|
+
/* Guarantee valid bracket */
|
262
|
+
/* TODO do we need these 2 lines? */
|
263
|
+
low = _clip(MIN(low, upr), baselow, baseupr);
|
264
|
+
upr = _clip(MAX(low, upr), baselow, baseupr);
|
265
|
+
|
266
|
+
if (low != upr) {
|
267
|
+
hfun(v0, low, &fl, &df);
|
268
|
+
hfun(v0, upr, &fu, &df);
|
269
|
+
|
270
|
+
if (fl * fu > 0) {
|
271
|
+
if (ABS(fl) < ABS(fu)) {
|
272
|
+
upr = low;
|
273
|
+
} else {
|
274
|
+
low = upr;
|
275
|
+
}
|
276
|
+
}
|
277
|
+
}
|
278
|
+
|
279
|
+
*low_out = low;
|
280
|
+
*upr_out = upr;
|
281
|
+
}
|
282
|
+
|
283
|
+
/* convert from rho to primal projection */
|
284
|
+
static scs_float proj_sol_primal_exp_cone(const scs_float *v0, scs_float rho,
|
285
|
+
scs_float *vp) {
|
286
|
+
scs_float linrho = (rho - 1) * v0[0] + v0[1];
|
287
|
+
scs_float exprho = exp(rho);
|
288
|
+
scs_float quadrho, dist;
|
289
|
+
if (linrho > 0 && _isfinite(exprho)) {
|
290
|
+
quadrho = rho * (rho - 1) + 1;
|
291
|
+
vp[2] = exprho * linrho / quadrho;
|
292
|
+
vp[1] = linrho / quadrho;
|
293
|
+
vp[0] = rho * linrho / quadrho;
|
294
|
+
dist = SCS(norm_diff)(vp, v0, 3);
|
295
|
+
} else {
|
296
|
+
vp[2] = EXP_CONE_INFINITY_VALUE;
|
297
|
+
vp[1] = 0.0;
|
298
|
+
vp[0] = 0.0;
|
299
|
+
dist = EXP_CONE_INFINITY_VALUE;
|
300
|
+
}
|
301
|
+
return dist;
|
302
|
+
}
|
303
|
+
|
304
|
+
/* convert from rho to polar projection */
|
305
|
+
static scs_float proj_sol_polar_exp_cone(const scs_float *v0, scs_float rho,
|
306
|
+
scs_float *vd) {
|
307
|
+
scs_float linrho = v0[0] - rho * v0[1];
|
308
|
+
scs_float exprho = exp(-rho);
|
309
|
+
scs_float quadrho, dist;
|
310
|
+
if (linrho > 0 && _isfinite(exprho)) {
|
311
|
+
quadrho = rho * (rho - 1) + 1;
|
312
|
+
vd[2] = -exprho * linrho / quadrho;
|
313
|
+
vd[1] = (1 - rho) * linrho / quadrho;
|
314
|
+
vd[0] = linrho / quadrho;
|
315
|
+
dist = SCS(norm_diff)(v0, vd, 3);
|
316
|
+
} else {
|
317
|
+
vd[2] = -EXP_CONE_INFINITY_VALUE;
|
318
|
+
vd[1] = 0.0;
|
319
|
+
vd[0] = 0.0;
|
320
|
+
dist = EXP_CONE_INFINITY_VALUE;
|
321
|
+
}
|
322
|
+
return dist;
|
323
|
+
}
|
324
|
+
|
325
|
+
static inline void _copy(scs_float *dest, scs_float *src) {
|
326
|
+
dest[0] = src[0];
|
327
|
+
dest[1] = src[1];
|
328
|
+
dest[2] = src[2];
|
329
|
+
}
|
330
|
+
|
331
|
+
/* Project onto primal or dual exponential cone, performed in-place.
|
332
|
+
* If `primal=0` then project on the dual cone, otherwise project
|
333
|
+
* onto primal. Taken from algorithm in Friberg, 2021.
|
334
|
+
*/
|
335
|
+
scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal) {
|
336
|
+
scs_float TOL = 1e-8; /* pow(1e-10, 2.0 / 3.0); */
|
337
|
+
scs_float xl, xh, pdist, ddist, err, rho, dist_hat;
|
338
|
+
scs_float vp[3], vd[3], v_hat[3];
|
339
|
+
scs_int opt;
|
340
|
+
if (!primal) {
|
341
|
+
/* This routine actually projects onto primal and polar cones
|
342
|
+
* simultaneously. So to make it project onto dual, use this:
|
343
|
+
* Pi_{C^*}(v0) = -Pi_{C^polar}(-v0)
|
344
|
+
*/
|
345
|
+
v0[0] *= -1.;
|
346
|
+
v0[1] *= -1.;
|
347
|
+
v0[2] *= -1.;
|
348
|
+
}
|
349
|
+
|
350
|
+
pdist = proj_primal_exp_cone_heuristic(v0, vp);
|
351
|
+
ddist = proj_polar_exp_cone_heuristic(v0, vd);
|
352
|
+
|
353
|
+
err = ABS(vp[0] + vd[0] - v0[0]);
|
354
|
+
err = MAX(err, ABS(vp[1] + vd[1] - v0[1]));
|
355
|
+
err = MAX(err, ABS(vp[2] + vd[2] - v0[2]));
|
356
|
+
|
357
|
+
/* Skip root search if presolve rules apply
|
358
|
+
* or optimality conditions are satisfied
|
359
|
+
*/
|
360
|
+
opt = (v0[1] <= 0 && v0[0] <= 0);
|
361
|
+
opt |= (MIN(pdist, ddist) <= TOL);
|
362
|
+
opt |= (err <= TOL && SCS(dot)(vp, vd, 3) <= TOL);
|
363
|
+
if (opt) {
|
364
|
+
if (primal) {
|
365
|
+
_copy(v0, vp);
|
366
|
+
return pdist;
|
367
|
+
}
|
368
|
+
/* polar cone -> dual cone */
|
369
|
+
v0[0] = -vd[0];
|
370
|
+
v0[1] = -vd[1];
|
371
|
+
v0[2] = -vd[2];
|
372
|
+
return ddist;
|
373
|
+
}
|
374
|
+
|
375
|
+
exp_search_bracket(v0, pdist, ddist, &xl, &xh);
|
376
|
+
rho = root_search_newton(v0, xl, xh, 0.5 * (xl + xh));
|
377
|
+
|
378
|
+
if (primal) {
|
379
|
+
/* primal cone projection */
|
380
|
+
dist_hat = proj_sol_primal_exp_cone(v0, rho, v_hat);
|
381
|
+
if (dist_hat <= pdist) {
|
382
|
+
_copy(vp, v_hat);
|
383
|
+
pdist = dist_hat;
|
384
|
+
}
|
385
|
+
_copy(v0, vp);
|
386
|
+
return pdist;
|
387
|
+
}
|
388
|
+
/* polar cone projection */
|
389
|
+
dist_hat = proj_sol_polar_exp_cone(v0, rho, v_hat);
|
390
|
+
if (dist_hat <= ddist) {
|
391
|
+
_copy(vd, v_hat);
|
392
|
+
ddist = dist_hat;
|
393
|
+
}
|
394
|
+
/* polar cone -> dual cone */
|
395
|
+
v0[0] = -vd[0];
|
396
|
+
v0[1] = -vd[1];
|
397
|
+
v0[2] = -vd[2];
|
398
|
+
return ddist;
|
399
|
+
}
|
data/vendor/scs/src/normalize.c
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
*/
|
27
27
|
void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c) {
|
28
28
|
scs_int i;
|
29
|
-
scs_float sigma;
|
29
|
+
scs_float sigma, nm_c, nm_b;
|
30
30
|
|
31
31
|
/* scale c */
|
32
32
|
for (i = 0; i < scal->n; ++i) {
|
@@ -38,7 +38,9 @@ void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c) {
|
|
38
38
|
}
|
39
39
|
|
40
40
|
/* calculate primal and dual scales */
|
41
|
-
|
41
|
+
nm_c = SCS(norm_inf)(c, scal->n);
|
42
|
+
nm_b = SCS(norm_inf)(b, scal->m);
|
43
|
+
sigma = MAX(nm_c, nm_b);
|
42
44
|
sigma = sigma < MIN_NORMALIZATION_FACTOR ? 1.0 : sigma;
|
43
45
|
sigma = sigma > MAX_NORMALIZATION_FACTOR ? MAX_NORMALIZATION_FACTOR : sigma;
|
44
46
|
sigma = SAFEDIV_POS(1.0, sigma);
|
data/vendor/scs/src/rw.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include "rw.h"
|
2
2
|
|
3
|
+
#include <errno.h>
|
3
4
|
#include <stdint.h>
|
4
5
|
#include <stdio.h>
|
5
6
|
#include <stdlib.h>
|
@@ -9,6 +10,25 @@
|
|
9
10
|
#include "scs_matrix.h"
|
10
11
|
#include "util.h"
|
11
12
|
|
13
|
+
#if NO_READ_WRITE > 0 /* Disables all read / write functionality */
|
14
|
+
|
15
|
+
void SCS(write_data)(const ScsData *d, const ScsCone *k,
|
16
|
+
const ScsSettings *stgs) {
|
17
|
+
/* Do nothing */
|
18
|
+
}
|
19
|
+
scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
20
|
+
ScsSettings **stgs) {
|
21
|
+
/* Failure */
|
22
|
+
return -1;
|
23
|
+
}
|
24
|
+
void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
25
|
+
const ScsWork *w, scs_int iter,
|
26
|
+
SCS(timer) * solve_timer) {
|
27
|
+
/* Do nothing */
|
28
|
+
}
|
29
|
+
|
30
|
+
#else
|
31
|
+
|
12
32
|
/* writes/reads problem data to/from filename */
|
13
33
|
/* This is a VERY naive implementation, doesn't care about portability etc */
|
14
34
|
|
@@ -28,30 +48,61 @@ static void write_scs_cone(const ScsCone *k, FILE *fout) {
|
|
28
48
|
fwrite(k->p, sizeof(scs_float), k->psize, fout);
|
29
49
|
}
|
30
50
|
|
31
|
-
|
51
|
+
/*
|
52
|
+
* Read integer data from file. If the integer width on file is
|
53
|
+
* different to scs_int then it will cast the ints after reading
|
54
|
+
* to be compatible with the SCS data types.
|
55
|
+
*/
|
56
|
+
static size_t read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
|
57
|
+
FILE *fin) {
|
58
|
+
if (file_int_sz == sizeof(scs_int)) {
|
59
|
+
return fread(dest, sizeof(scs_int), nitems, fin);
|
60
|
+
}
|
61
|
+
void *ptr = scs_calloc(nitems, file_int_sz);
|
62
|
+
size_t val = fread(ptr, file_int_sz, nitems, fin);
|
63
|
+
scs_int i;
|
64
|
+
switch (file_int_sz) {
|
65
|
+
case 4:
|
66
|
+
for (i = 0; i < nitems; ++i) {
|
67
|
+
dest[i] = (scs_int)(((int *)ptr)[i]);
|
68
|
+
}
|
69
|
+
break;
|
70
|
+
case 8:
|
71
|
+
for (i = 0; i < nitems; ++i) {
|
72
|
+
dest[i] = (scs_int)(((long long *)ptr)[i]);
|
73
|
+
}
|
74
|
+
break;
|
75
|
+
}
|
76
|
+
if (ptr) {
|
77
|
+
scs_free(ptr);
|
78
|
+
}
|
79
|
+
return val;
|
80
|
+
}
|
81
|
+
|
82
|
+
static ScsCone *read_scs_cone(FILE *fin, size_t file_int_sz) {
|
32
83
|
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
33
|
-
|
34
|
-
|
35
|
-
|
84
|
+
read_int(&(k->z), file_int_sz, 1, fin);
|
85
|
+
read_int(&(k->l), file_int_sz, 1, fin);
|
86
|
+
read_int(&(k->bsize), file_int_sz, 1, fin);
|
36
87
|
if (k->bsize > 1) {
|
37
88
|
k->bl = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
38
89
|
k->bu = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
39
90
|
fread(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
|
40
91
|
fread(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
|
41
92
|
}
|
42
|
-
|
93
|
+
read_int(&(k->qsize), file_int_sz, 1, fin);
|
43
94
|
if (k->qsize) {
|
44
95
|
k->q = (scs_int *)scs_calloc(k->qsize, sizeof(scs_int));
|
45
|
-
|
96
|
+
read_int(k->q, file_int_sz, k->qsize, fin);
|
46
97
|
}
|
47
|
-
|
98
|
+
read_int(&(k->ssize), file_int_sz, 1, fin);
|
48
99
|
if (k->ssize) {
|
49
100
|
k->s = (scs_int *)scs_calloc(k->ssize, sizeof(scs_int));
|
50
|
-
|
101
|
+
read_int(k->s, file_int_sz, k->ssize, fin);
|
51
102
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
103
|
+
read_int(&(k->ep), file_int_sz, 1, fin);
|
104
|
+
read_int(&(k->ed), file_int_sz, 1, fin);
|
105
|
+
read_int(&(k->psize), file_int_sz, 1, fin);
|
55
106
|
if (k->psize) {
|
56
107
|
k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
|
57
108
|
fread(k->p, sizeof(scs_float), k->psize, fin);
|
@@ -79,21 +130,21 @@ static void write_scs_stgs(const ScsSettings *s, FILE *fout) {
|
|
79
130
|
/* Do not write the log_csv_filename */
|
80
131
|
}
|
81
132
|
|
82
|
-
static ScsSettings *read_scs_stgs(FILE *fin) {
|
133
|
+
static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz) {
|
83
134
|
ScsSettings *s = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
84
|
-
|
135
|
+
read_int(&(s->normalize), file_int_sz, 1, fin);
|
85
136
|
fread(&(s->scale), sizeof(scs_float), 1, fin);
|
86
137
|
fread(&(s->rho_x), sizeof(scs_float), 1, fin);
|
87
|
-
|
138
|
+
read_int(&(s->max_iters), file_int_sz, 1, fin);
|
88
139
|
fread(&(s->eps_abs), sizeof(scs_float), 1, fin);
|
89
140
|
fread(&(s->eps_rel), sizeof(scs_float), 1, fin);
|
90
141
|
fread(&(s->eps_infeas), sizeof(scs_float), 1, fin);
|
91
142
|
fread(&(s->alpha), sizeof(scs_float), 1, fin);
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
143
|
+
read_int(&(s->verbose), file_int_sz, 1, fin);
|
144
|
+
read_int(&(s->warm_start), file_int_sz, 1, fin);
|
145
|
+
read_int(&(s->acceleration_lookback), file_int_sz, 1, fin);
|
146
|
+
read_int(&(s->acceleration_interval), file_int_sz, 1, fin);
|
147
|
+
read_int(&(s->adaptive_scale), file_int_sz, 1, fin);
|
97
148
|
return s;
|
98
149
|
}
|
99
150
|
|
@@ -106,18 +157,18 @@ static void write_amatrix(const ScsMatrix *A, FILE *fout) {
|
|
106
157
|
fwrite(A->i, sizeof(scs_int), Anz, fout);
|
107
158
|
}
|
108
159
|
|
109
|
-
static ScsMatrix *read_amatrix(FILE *fin) {
|
160
|
+
static ScsMatrix *read_amatrix(FILE *fin, size_t file_int_sz) {
|
110
161
|
scs_int Anz;
|
111
162
|
ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
112
|
-
|
113
|
-
|
163
|
+
read_int(&(A->m), file_int_sz, 1, fin);
|
164
|
+
read_int(&(A->n), file_int_sz, 1, fin);
|
114
165
|
A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
|
115
|
-
|
166
|
+
read_int(A->p, file_int_sz, A->n + 1, fin);
|
116
167
|
Anz = A->p[A->n];
|
117
168
|
A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
|
118
169
|
A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
|
119
170
|
fread(A->x, sizeof(scs_float), Anz, fin);
|
120
|
-
|
171
|
+
read_int(A->i, file_int_sz, Anz, fin);
|
121
172
|
return A;
|
122
173
|
}
|
123
174
|
|
@@ -135,19 +186,20 @@ static void write_scs_data(const ScsData *d, FILE *fout) {
|
|
135
186
|
}
|
136
187
|
}
|
137
188
|
|
138
|
-
static ScsData *read_scs_data(FILE *fin) {
|
189
|
+
static ScsData *read_scs_data(FILE *fin, size_t file_int_sz) {
|
139
190
|
scs_int has_p = 0;
|
140
191
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
141
|
-
|
142
|
-
|
192
|
+
|
193
|
+
read_int(&(d->m), file_int_sz, 1, fin);
|
194
|
+
read_int(&(d->n), file_int_sz, 1, fin);
|
143
195
|
d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
144
196
|
d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
145
197
|
fread(d->b, sizeof(scs_float), d->m, fin);
|
146
198
|
fread(d->c, sizeof(scs_float), d->n, fin);
|
147
|
-
d->A = read_amatrix(fin);
|
199
|
+
d->A = read_amatrix(fin, file_int_sz);
|
148
200
|
/* If has_p bit is not set or this hits end of file then has_p = 0 */
|
149
|
-
has_p &=
|
150
|
-
d->P = has_p ? read_amatrix(fin) : SCS_NULL;
|
201
|
+
has_p &= read_int(&has_p, file_int_sz, 1, fin);
|
202
|
+
d->P = has_p ? read_amatrix(fin, file_int_sz) : SCS_NULL;
|
151
203
|
return d;
|
152
204
|
}
|
153
205
|
|
@@ -158,7 +210,6 @@ void SCS(write_data)(const ScsData *d, const ScsCone *k,
|
|
158
210
|
uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
|
159
211
|
const char *scs_version = SCS_VERSION;
|
160
212
|
uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
|
161
|
-
scs_printf("writing data to %s\n", stgs->write_data_filename);
|
162
213
|
fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout);
|
163
214
|
fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout);
|
164
215
|
fwrite(&(scs_version_sz), sizeof(uint32_t), 1, fout);
|
@@ -175,9 +226,11 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
175
226
|
uint32_t file_float_sz;
|
176
227
|
uint32_t file_version_sz;
|
177
228
|
char file_version[16];
|
229
|
+
errno = 0;
|
178
230
|
FILE *fin = fopen(filename, "rb");
|
179
231
|
if (!fin) {
|
180
232
|
scs_printf("Error reading file %s\n", filename);
|
233
|
+
scs_printf("errno:%i:%s\n", errno, strerror(errno));
|
181
234
|
return -1;
|
182
235
|
}
|
183
236
|
scs_printf("Reading data from %s\n", filename);
|
@@ -185,11 +238,10 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
185
238
|
fread(&(file_float_sz), sizeof(uint32_t), 1, fin);
|
186
239
|
if (file_int_sz != (uint32_t)sizeof(scs_int)) {
|
187
240
|
scs_printf(
|
188
|
-
"
|
189
|
-
"
|
241
|
+
"Warning, sizeof(file int) is %lu, but scs expects sizeof(int) %lu. "
|
242
|
+
"SCS will attempt to cast the data, which may be slow. "
|
243
|
+
"This message can be avoided by recompiling with the correct flags.\n",
|
190
244
|
(unsigned long)file_int_sz, (unsigned long)sizeof(scs_int));
|
191
|
-
fclose(fin);
|
192
|
-
return -1;
|
193
245
|
}
|
194
246
|
if (file_float_sz != (uint32_t)sizeof(scs_float)) {
|
195
247
|
scs_printf(
|
@@ -209,9 +261,10 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
209
261
|
"************************************************************\n",
|
210
262
|
file_version, SCS_VERSION);
|
211
263
|
}
|
212
|
-
*k = read_scs_cone(fin);
|
213
|
-
*d = read_scs_data(fin);
|
214
|
-
*stgs = read_scs_stgs(fin);
|
264
|
+
*k = read_scs_cone(fin, file_int_sz);
|
265
|
+
*d = read_scs_data(fin, file_int_sz);
|
266
|
+
*stgs = read_scs_stgs(fin, file_int_sz);
|
267
|
+
scs_printf("Finished reading data.\n");
|
215
268
|
fclose(fin);
|
216
269
|
return 0;
|
217
270
|
}
|
@@ -348,3 +401,5 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
|
348
401
|
fprintf(fout, "\n");
|
349
402
|
fclose(fout);
|
350
403
|
}
|
404
|
+
|
405
|
+
#endif
|