scs 0.3.2 → 0.4.0
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 +6 -0
- data/README.md +34 -5
- 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 +1 -1
- data/vendor/scs/CMakeLists.txt +2 -2
- data/vendor/scs/README.md +3 -1
- data/vendor/scs/include/cones.h +5 -3
- data/vendor/scs/include/glbopts.h +4 -5
- data/vendor/scs/include/normalize.h +1 -0
- data/vendor/scs/include/rw.h +3 -3
- data/vendor/scs/include/scs.h +45 -22
- data/vendor/scs/include/scs_work.h +15 -18
- data/vendor/scs/include/util.h +3 -1
- 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/scs_matrix.c +38 -67
- data/vendor/scs/linsys/scs_matrix.h +4 -3
- data/vendor/scs/scs.mk +0 -4
- data/vendor/scs/src/aa.c +0 -4
- data/vendor/scs/src/cones.c +63 -25
- data/vendor/scs/src/normalize.c +49 -0
- data/vendor/scs/src/rw.c +48 -40
- data/vendor/scs/src/scs.c +212 -170
- data/vendor/scs/src/util.c +26 -12
- data/vendor/scs/test/problem_utils.h +3 -3
- data/vendor/scs/test/problems/degenerate.h +1 -0
- data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -0
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +5 -1
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -0
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/random_prob.h +5 -1
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +8 -1
- 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_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 +15 -3
- metadata +5 -4
data/vendor/scs/src/scs.c
CHANGED
@@ -40,21 +40,34 @@ static void free_work(ScsWork *w) {
|
|
40
40
|
scs_free(w->rsk);
|
41
41
|
scs_free(w->h);
|
42
42
|
scs_free(w->g);
|
43
|
-
scs_free(w->
|
44
|
-
scs_free(w->
|
43
|
+
scs_free(w->b_orig);
|
44
|
+
scs_free(w->c_orig);
|
45
45
|
scs_free(w->lin_sys_warm_start);
|
46
46
|
scs_free(w->diag_r);
|
47
|
+
SCS(free_sol)(w->xys_orig);
|
47
48
|
if (w->scal) {
|
48
49
|
scs_free(w->scal->D);
|
49
50
|
scs_free(w->scal->E);
|
50
51
|
scs_free(w->scal);
|
51
52
|
}
|
52
|
-
SCS(free_sol)(w->xys_orig);
|
53
53
|
free_residuals(w->r_orig);
|
54
54
|
if (w->stgs && w->stgs->normalize) {
|
55
55
|
SCS(free_sol)(w->xys_normalized);
|
56
56
|
free_residuals(w->r_normalized);
|
57
57
|
}
|
58
|
+
if (w->stgs) {
|
59
|
+
if (w->stgs->log_csv_filename)
|
60
|
+
scs_free((char *)w->stgs->log_csv_filename);
|
61
|
+
if (w->stgs->write_data_filename)
|
62
|
+
scs_free((char *)w->stgs->write_data_filename);
|
63
|
+
scs_free(w->stgs);
|
64
|
+
}
|
65
|
+
if (w->k) { /* deep copy */
|
66
|
+
SCS(free_cone)(w->k);
|
67
|
+
}
|
68
|
+
if (w->d) { /* deep copy */
|
69
|
+
SCS(free_data)(w->d);
|
70
|
+
}
|
58
71
|
scs_free(w);
|
59
72
|
}
|
60
73
|
}
|
@@ -87,12 +100,11 @@ static void print_init_header(const ScsData *d, const ScsCone *k,
|
|
87
100
|
scs_free(cone_str);
|
88
101
|
scs_printf("settings: eps_abs: %.1e, eps_rel: %.1e, eps_infeas: %.1e\n"
|
89
102
|
"\t alpha: %.2f, scale: %.2e, adaptive_scale: %i\n"
|
90
|
-
"\t max_iters: %i, normalize: %i,
|
91
|
-
/*, rho_x: %.2e\n", */
|
103
|
+
"\t max_iters: %i, normalize: %i, rho_x: %.2e\n",
|
92
104
|
stgs->eps_abs, stgs->eps_rel, stgs->eps_infeas, stgs->alpha,
|
93
105
|
stgs->scale, (int)stgs->adaptive_scale, (int)stgs->max_iters,
|
94
|
-
(int)stgs->normalize,
|
95
|
-
/*
|
106
|
+
(int)stgs->normalize, stgs->rho_x);
|
107
|
+
/* (int)stgs->warm_start); */
|
96
108
|
if (stgs->acceleration_lookback != 0) {
|
97
109
|
scs_printf("\t acceleration_lookback: %i, acceleration_interval: %i\n",
|
98
110
|
(int)acceleration_lookback, (int)acceleration_interval);
|
@@ -154,18 +166,26 @@ static scs_int failure(ScsWork *w, scs_int m, scs_int n, ScsSolution *sol,
|
|
154
166
|
return status;
|
155
167
|
}
|
156
168
|
|
169
|
+
static inline scs_int _is_nan(scs_float x) {
|
170
|
+
return x != x;
|
171
|
+
}
|
172
|
+
|
157
173
|
/* given x,y,s warm start, set v = [x; s / R + y; 1]
|
174
|
+
* check for nans and set to zero if present
|
158
175
|
*/
|
159
176
|
static void warm_start_vars(ScsWork *w, ScsSolution *sol) {
|
160
|
-
scs_int n = w->n, m = w->m, i;
|
177
|
+
scs_int n = w->d->n, m = w->d->m, i;
|
161
178
|
scs_float *v = w->v;
|
162
179
|
/* normalize the warm-start */
|
163
180
|
if (w->stgs->normalize) {
|
164
181
|
SCS(normalize_sol)(w->scal, sol);
|
165
182
|
}
|
166
|
-
|
183
|
+
for (i = 0; i < n; ++i) {
|
184
|
+
v[i] = _is_nan(sol->x[i]) ? 0. : sol->x[i];
|
185
|
+
}
|
167
186
|
for (i = 0; i < m; ++i) {
|
168
187
|
v[i + n] = sol->y[i] + sol->s[i] / w->diag_r[i + n];
|
188
|
+
v[i + n] = _is_nan(v[i + n]) ? 0. : v[i + n];
|
169
189
|
}
|
170
190
|
v[n + m] = 1.0; /* tau = 1 */
|
171
191
|
/* un-normalize so sol unchanged */
|
@@ -199,12 +219,12 @@ static void unnormalize_residuals(ScsWork *w) {
|
|
199
219
|
r->tau = r_n->tau;
|
200
220
|
|
201
221
|
/* mem copy arrays */
|
202
|
-
memcpy(r->ax, r_n->ax, w->m * sizeof(scs_float));
|
203
|
-
memcpy(r->ax_s, r_n->ax_s, w->m * sizeof(scs_float));
|
204
|
-
memcpy(r->ax_s_btau, r_n->ax_s_btau, w->m * sizeof(scs_float));
|
205
|
-
memcpy(r->aty, r_n->aty, w->n * sizeof(scs_float));
|
206
|
-
memcpy(r->px, r_n->px, w->n * sizeof(scs_float));
|
207
|
-
memcpy(r->px_aty_ctau, r_n->px_aty_ctau, w->n * sizeof(scs_float));
|
222
|
+
memcpy(r->ax, r_n->ax, w->d->m * sizeof(scs_float));
|
223
|
+
memcpy(r->ax_s, r_n->ax_s, w->d->m * sizeof(scs_float));
|
224
|
+
memcpy(r->ax_s_btau, r_n->ax_s_btau, w->d->m * sizeof(scs_float));
|
225
|
+
memcpy(r->aty, r_n->aty, w->d->n * sizeof(scs_float));
|
226
|
+
memcpy(r->px, r_n->px, w->d->n * sizeof(scs_float));
|
227
|
+
memcpy(r->px_aty_ctau, r_n->px_aty_ctau, w->d->n * sizeof(scs_float));
|
208
228
|
|
209
229
|
/* unnormalize */
|
210
230
|
r->kap = r_n->kap / pd;
|
@@ -225,13 +245,13 @@ static void unnormalize_residuals(ScsWork *w) {
|
|
225
245
|
SCS(un_normalize_dual)(w->scal, r->px);
|
226
246
|
SCS(un_normalize_dual)(w->scal, r->px_aty_ctau);
|
227
247
|
|
228
|
-
compute_residuals(r, w->m, w->n);
|
248
|
+
compute_residuals(r, w->d->m, w->d->n);
|
229
249
|
}
|
230
250
|
|
231
251
|
/* calculates un-normalized residual quantities */
|
232
252
|
/* this is somewhat slow but not a bottleneck */
|
233
253
|
static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
234
|
-
scs_int n = w->n, m = w->m;
|
254
|
+
scs_int n = w->d->n, m = w->d->m;
|
235
255
|
/* normalized x,y,s terms */
|
236
256
|
scs_float *x = w->xys_normalized->x;
|
237
257
|
scs_float *y = w->xys_normalized->y;
|
@@ -254,7 +274,7 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
254
274
|
/**************** PRIMAL *********************/
|
255
275
|
memset(r->ax, 0, m * sizeof(scs_float));
|
256
276
|
/* ax = Ax */
|
257
|
-
SCS(accum_by_a)(w->A, x, r->ax);
|
277
|
+
SCS(accum_by_a)(w->d->A, x, r->ax);
|
258
278
|
|
259
279
|
memcpy(r->ax_s, r->ax, m * sizeof(scs_float));
|
260
280
|
/* ax_s = Ax + s */
|
@@ -262,13 +282,13 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
262
282
|
|
263
283
|
memcpy(r->ax_s_btau, r->ax_s, m * sizeof(scs_float));
|
264
284
|
/* ax_s_btau = Ax + s - b * tau */
|
265
|
-
SCS(add_scaled_array)(r->ax_s_btau, w->
|
285
|
+
SCS(add_scaled_array)(r->ax_s_btau, w->d->b, m, -r->tau);
|
266
286
|
|
267
287
|
/**************** DUAL *********************/
|
268
288
|
memset(r->px, 0, n * sizeof(scs_float));
|
269
|
-
if (w->P) {
|
289
|
+
if (w->d->P) {
|
270
290
|
/* px = Px */
|
271
|
-
SCS(accum_by_p)(w->P, x, r->px);
|
291
|
+
SCS(accum_by_p)(w->d->P, x, r->px);
|
272
292
|
r->xt_p_x_tau = SCS(dot)(r->px, x, n);
|
273
293
|
} else {
|
274
294
|
r->xt_p_x_tau = 0.;
|
@@ -276,18 +296,18 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
276
296
|
|
277
297
|
memset(r->aty, 0, n * sizeof(scs_float));
|
278
298
|
/* aty = A'y */
|
279
|
-
SCS(accum_by_atrans)(w->A, y, r->aty);
|
299
|
+
SCS(accum_by_atrans)(w->d->A, y, r->aty);
|
280
300
|
|
281
301
|
/* r->px_aty_ctau = Px */
|
282
302
|
memcpy(r->px_aty_ctau, r->px, n * sizeof(scs_float));
|
283
303
|
/* r->px_aty_ctau = Px + A'y */
|
284
304
|
SCS(add_scaled_array)(r->px_aty_ctau, r->aty, n, 1.);
|
285
305
|
/* r->px_aty_ctau = Px + A'y + c * tau */
|
286
|
-
SCS(add_scaled_array)(r->px_aty_ctau, w->
|
306
|
+
SCS(add_scaled_array)(r->px_aty_ctau, w->d->c, n, r->tau);
|
287
307
|
|
288
308
|
/**************** OTHERS *****************/
|
289
|
-
r->bty_tau = SCS(dot)(y, w->
|
290
|
-
r->ctx_tau = SCS(dot)(x, w->
|
309
|
+
r->bty_tau = SCS(dot)(y, w->d->b, m);
|
310
|
+
r->ctx_tau = SCS(dot)(x, w->d->c, n);
|
291
311
|
|
292
312
|
r->bty = SAFEDIV_POS(r->bty_tau, r->tau);
|
293
313
|
r->ctx = SAFEDIV_POS(r->ctx_tau, r->tau);
|
@@ -309,7 +329,7 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
309
329
|
}
|
310
330
|
|
311
331
|
static void cold_start_vars(ScsWork *w) {
|
312
|
-
scs_int l = w->n + w->m + 1;
|
332
|
+
scs_int l = w->d->n + w->d->m + 1;
|
313
333
|
memset(w->v, 0, l * sizeof(scs_float));
|
314
334
|
w->v[l - 1] = 1.;
|
315
335
|
}
|
@@ -319,7 +339,7 @@ static inline scs_float dot_r(ScsWork *w, const scs_float *x,
|
|
319
339
|
const scs_float *y) {
|
320
340
|
scs_int i;
|
321
341
|
scs_float ip = 0.0;
|
322
|
-
for (i = 0; i < w->n + w->m; ++i) {
|
342
|
+
for (i = 0; i < w->d->n + w->d->m; ++i) {
|
323
343
|
ip += x[i] * y[i] * w->diag_r[i];
|
324
344
|
}
|
325
345
|
return ip;
|
@@ -327,7 +347,7 @@ static inline scs_float dot_r(ScsWork *w, const scs_float *x,
|
|
327
347
|
|
328
348
|
static scs_float root_plus(ScsWork *w, scs_float *p, scs_float *mu,
|
329
349
|
scs_float eta) {
|
330
|
-
scs_float a, b, c, tau_scale = w->diag_r[w->n + w->m];
|
350
|
+
scs_float a, b, c, tau_scale = w->diag_r[w->d->n + w->d->m];
|
331
351
|
a = tau_scale + dot_r(w, w->g, w->g);
|
332
352
|
b = dot_r(w, mu, w->g) - 2 * dot_r(w, p, w->g) - eta * tau_scale;
|
333
353
|
c = dot_r(w, p, p) - dot_r(w, p, mu);
|
@@ -336,7 +356,7 @@ static scs_float root_plus(ScsWork *w, scs_float *p, scs_float *mu,
|
|
336
356
|
|
337
357
|
/* status < 0 indicates failure */
|
338
358
|
static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
339
|
-
scs_int n = w->n, m = w->m, l = n + m + 1, status, i;
|
359
|
+
scs_int n = w->d->n, m = w->d->m, l = n + m + 1, status, i;
|
340
360
|
scs_float *warm_start = SCS_NULL;
|
341
361
|
scs_float tol = -1.0; /* only used for indirect methods, overridden later */
|
342
362
|
memcpy(w->u_t, w->v, l * sizeof(scs_float));
|
@@ -350,12 +370,12 @@ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
|
350
370
|
/* warm_start = u[:n] + tau * g[:n] */
|
351
371
|
SCS(add_scaled_array)(warm_start, w->g, l - 1, w->u[l - 1]);
|
352
372
|
/* use normalized residuals to compute tolerance */
|
353
|
-
tol = MIN(CG_NORM(w->r_normalized->ax_s_btau, w->m),
|
354
|
-
CG_NORM(w->r_normalized->px_aty_ctau, w->n));
|
373
|
+
tol = MIN(CG_NORM(w->r_normalized->ax_s_btau, w->d->m),
|
374
|
+
CG_NORM(w->r_normalized->px_aty_ctau, w->d->n));
|
355
375
|
/* tol ~ O(1/k^(1+eps)) guarantees convergence */
|
356
376
|
/* use warm-start to calculate tolerance rather than w->u_t, since warm_start
|
357
377
|
* should be approximately equal to the true solution */
|
358
|
-
tol = CG_TOL_FACTOR * MIN(tol, CG_NORM(warm_start, w->n) /
|
378
|
+
tol = CG_TOL_FACTOR * MIN(tol, CG_NORM(warm_start, w->d->n) /
|
359
379
|
POWF((scs_float)iter + 1, CG_RATE));
|
360
380
|
tol = MAX(CG_BEST_TOL, tol);
|
361
381
|
#endif
|
@@ -378,14 +398,14 @@ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
|
378
398
|
* (no effect of w->stgs->alpha here).
|
379
399
|
*/
|
380
400
|
static void compute_rsk(ScsWork *w) {
|
381
|
-
scs_int i, l = w->m + w->n + 1;
|
401
|
+
scs_int i, l = w->d->m + w->d->n + 1;
|
382
402
|
for (i = 0; i < l; ++i) {
|
383
403
|
w->rsk[i] = (w->v[i] + w->u[i] - 2 * w->u_t[i]) * w->diag_r[i];
|
384
404
|
}
|
385
405
|
}
|
386
406
|
|
387
407
|
static void update_dual_vars(ScsWork *w) {
|
388
|
-
scs_int i, l = w->n + w->m + 1;
|
408
|
+
scs_int i, l = w->d->n + w->d->m + 1;
|
389
409
|
for (i = 0; i < l; ++i) {
|
390
410
|
w->v[i] += w->stgs->alpha * (w->u[i] - w->u_t[i]);
|
391
411
|
}
|
@@ -393,7 +413,7 @@ static void update_dual_vars(ScsWork *w) {
|
|
393
413
|
|
394
414
|
/* status < 0 indicates failure */
|
395
415
|
static scs_int project_cones(ScsWork *w, const ScsCone *k, scs_int iter) {
|
396
|
-
scs_int i, n = w->n, l = w->n + w->m + 1, status;
|
416
|
+
scs_int i, n = w->d->n, l = w->d->n + w->d->m + 1, status;
|
397
417
|
for (i = 0; i < l; ++i) {
|
398
418
|
w->u[i] = 2 * w->u_t[i] - w->v[i];
|
399
419
|
}
|
@@ -410,30 +430,30 @@ static scs_int project_cones(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
410
430
|
|
411
431
|
static void sety(const ScsWork *w, ScsSolution *sol) {
|
412
432
|
if (!sol->y) {
|
413
|
-
sol->y = (scs_float *)scs_calloc(w->m, sizeof(scs_float));
|
433
|
+
sol->y = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
414
434
|
}
|
415
|
-
memcpy(sol->y, &(w->u[w->n]), w->m * sizeof(scs_float));
|
435
|
+
memcpy(sol->y, &(w->u[w->d->n]), w->d->m * sizeof(scs_float));
|
416
436
|
}
|
417
437
|
|
418
438
|
/* s is contained in rsk */
|
419
439
|
static void sets(const ScsWork *w, ScsSolution *sol) {
|
420
440
|
if (!sol->s) {
|
421
|
-
sol->s = (scs_float *)scs_calloc(w->m, sizeof(scs_float));
|
441
|
+
sol->s = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
422
442
|
}
|
423
|
-
memcpy(sol->s, &(w->rsk[w->n]), w->m * sizeof(scs_float));
|
443
|
+
memcpy(sol->s, &(w->rsk[w->d->n]), w->d->m * sizeof(scs_float));
|
424
444
|
}
|
425
445
|
|
426
446
|
static void setx(const ScsWork *w, ScsSolution *sol) {
|
427
447
|
if (!sol->x) {
|
428
|
-
sol->x = (scs_float *)scs_calloc(w->n, sizeof(scs_float));
|
448
|
+
sol->x = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
|
429
449
|
}
|
430
|
-
memcpy(sol->x, w->u, w->n * sizeof(scs_float));
|
450
|
+
memcpy(sol->x, w->u, w->d->n * sizeof(scs_float));
|
431
451
|
}
|
432
452
|
|
433
453
|
static void set_solved(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
434
|
-
SCS(scale_array)(sol->x, SAFEDIV_POS(1.0, w->r_orig->tau), w->n);
|
435
|
-
SCS(scale_array)(sol->y, SAFEDIV_POS(1.0, w->r_orig->tau), w->m);
|
436
|
-
SCS(scale_array)(sol->s, SAFEDIV_POS(1.0, w->r_orig->tau), w->m);
|
454
|
+
SCS(scale_array)(sol->x, SAFEDIV_POS(1.0, w->r_orig->tau), w->d->n);
|
455
|
+
SCS(scale_array)(sol->y, SAFEDIV_POS(1.0, w->r_orig->tau), w->d->m);
|
456
|
+
SCS(scale_array)(sol->s, SAFEDIV_POS(1.0, w->r_orig->tau), w->d->m);
|
437
457
|
info->gap = w->r_orig->gap;
|
438
458
|
info->res_pri = w->r_orig->res_pri;
|
439
459
|
info->res_dual = w->r_orig->res_dual;
|
@@ -444,9 +464,9 @@ static void set_solved(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
444
464
|
}
|
445
465
|
|
446
466
|
static void set_infeasible(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
447
|
-
SCS(scale_array)(sol->y, -1 / w->r_orig->bty_tau, w->m);
|
448
|
-
SCS(scale_array)(sol->x, NAN, w->n);
|
449
|
-
SCS(scale_array)(sol->s, NAN, w->m);
|
467
|
+
SCS(scale_array)(sol->y, -1 / w->r_orig->bty_tau, w->d->m);
|
468
|
+
SCS(scale_array)(sol->x, NAN, w->d->n);
|
469
|
+
SCS(scale_array)(sol->s, NAN, w->d->m);
|
450
470
|
info->gap = NAN;
|
451
471
|
info->res_pri = NAN;
|
452
472
|
info->res_dual = NAN;
|
@@ -457,9 +477,9 @@ static void set_infeasible(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
457
477
|
}
|
458
478
|
|
459
479
|
static void set_unbounded(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
460
|
-
SCS(scale_array)(sol->x, -1 / w->r_orig->ctx_tau, w->n);
|
461
|
-
SCS(scale_array)(sol->s, -1 / w->r_orig->ctx_tau, w->m);
|
462
|
-
SCS(scale_array)(sol->y, NAN, w->m);
|
480
|
+
SCS(scale_array)(sol->x, -1 / w->r_orig->ctx_tau, w->d->n);
|
481
|
+
SCS(scale_array)(sol->s, -1 / w->r_orig->ctx_tau, w->d->m);
|
482
|
+
SCS(scale_array)(sol->y, NAN, w->d->m);
|
463
483
|
info->gap = NAN;
|
464
484
|
info->res_pri = NAN;
|
465
485
|
info->res_dual = NAN;
|
@@ -506,13 +526,13 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
506
526
|
info->res_infeas = w->r_orig->res_infeas;
|
507
527
|
info->res_unbdd_a = w->r_orig->res_unbdd_a;
|
508
528
|
info->res_unbdd_p = w->r_orig->res_unbdd_p;
|
509
|
-
info->scale = w->scale;
|
529
|
+
info->scale = w->stgs->scale;
|
510
530
|
info->scale_updates = w->scale_updates;
|
511
531
|
info->rejected_accel_steps = w->rejected_accel_steps;
|
512
532
|
info->accepted_accel_steps = w->accepted_accel_steps;
|
513
|
-
info->comp_slack = ABS(SCS(dot)(sol->s, sol->y, w->m));
|
514
|
-
if (info->comp_slack >
|
515
|
-
|
533
|
+
info->comp_slack = ABS(SCS(dot)(sol->s, sol->y, w->d->m));
|
534
|
+
if (info->comp_slack > 1e-5 * MAX(SCS(norm_inf)(sol->s, w->d->m),
|
535
|
+
SCS(norm_inf)(sol->y, w->d->m))) {
|
516
536
|
scs_printf("WARNING - large complementary slackness residual: %f\n",
|
517
537
|
info->comp_slack);
|
518
538
|
}
|
@@ -542,23 +562,23 @@ static void print_summary(ScsWork *w, scs_int i, SCS(timer) * solve_timer) {
|
|
542
562
|
scs_printf("%*.2e ", (int)HSPACE, r->gap);
|
543
563
|
/* report mid point of primal and dual objective values */
|
544
564
|
scs_printf("%*.2e ", (int)HSPACE, 0.5 * (r->pobj + r->dobj));
|
545
|
-
scs_printf("%*.2e ", (int)HSPACE, w->scale);
|
565
|
+
scs_printf("%*.2e ", (int)HSPACE, w->stgs->scale);
|
546
566
|
scs_printf("%*.2e ", (int)HSPACE, SCS(tocq)(solve_timer) / 1e3);
|
547
567
|
scs_printf("\n");
|
548
568
|
|
549
569
|
#if VERBOSITY > 0
|
550
|
-
scs_printf("Norm u = %4f, ", SCS(norm_2)(w->u, w->n + w->m + 1));
|
551
|
-
scs_printf("Norm u_t = %4f, ", SCS(norm_2)(w->u_t, w->n + w->m + 1));
|
552
|
-
scs_printf("Norm v = %4f, ", SCS(norm_2)(w->v, w->n + w->m + 1));
|
553
|
-
scs_printf("Norm rsk = %4f, ", SCS(norm_2)(w->rsk, w->n + w->m + 1));
|
554
|
-
scs_printf("Norm x = %4f, ", SCS(norm_2)(w->xys_orig->x, w->n));
|
555
|
-
scs_printf("Norm y = %4f, ", SCS(norm_2)(w->xys_orig->y, w->m));
|
556
|
-
scs_printf("Norm s = %4f, ", SCS(norm_2)(w->xys_orig->s, w->m));
|
557
|
-
scs_printf("Norm |Ax + s| = %1.2e, ", SCS(norm_2)(r->ax_s, w->m));
|
558
|
-
scs_printf("tau = %4f, ", w->u[w->n + w->m]);
|
559
|
-
scs_printf("kappa = %4f, ", w->rsk[w->n + w->m]);
|
570
|
+
scs_printf("Norm u = %4f, ", SCS(norm_2)(w->u, w->d->n + w->d->m + 1));
|
571
|
+
scs_printf("Norm u_t = %4f, ", SCS(norm_2)(w->u_t, w->d->n + w->d->m + 1));
|
572
|
+
scs_printf("Norm v = %4f, ", SCS(norm_2)(w->v, w->d->n + w->d->m + 1));
|
573
|
+
scs_printf("Norm rsk = %4f, ", SCS(norm_2)(w->rsk, w->d->n + w->d->m + 1));
|
574
|
+
scs_printf("Norm x = %4f, ", SCS(norm_2)(w->xys_orig->x, w->d->n));
|
575
|
+
scs_printf("Norm y = %4f, ", SCS(norm_2)(w->xys_orig->y, w->d->m));
|
576
|
+
scs_printf("Norm s = %4f, ", SCS(norm_2)(w->xys_orig->s, w->d->m));
|
577
|
+
scs_printf("Norm |Ax + s| = %1.2e, ", SCS(norm_2)(r->ax_s, w->d->m));
|
578
|
+
scs_printf("tau = %4f, ", w->u[w->d->n + w->d->m]);
|
579
|
+
scs_printf("kappa = %4f, ", w->rsk[w->d->n + w->d->m]);
|
560
580
|
scs_printf("|u - u_t| = %1.2e, ",
|
561
|
-
SCS(norm_diff)(w->u, w->u_t, w->n + w->m + 1));
|
581
|
+
SCS(norm_diff)(w->u, w->u_t, w->d->n + w->d->m + 1));
|
562
582
|
scs_printf("res_infeas = %1.2e, ", r->res_infeas);
|
563
583
|
scs_printf("res_unbdd_a = %1.2e, ", r->res_unbdd_a);
|
564
584
|
scs_printf("res_unbdd_p = %1.2e, ", r->res_unbdd_p);
|
@@ -643,10 +663,11 @@ static scs_int has_converged(ScsWork *w, scs_int iter) {
|
|
643
663
|
/* xt_p_x, ctx, bty already have tau divided out */
|
644
664
|
grl = MAX(MAX(ABS(r->xt_p_x), ABS(r->ctx)), ABS(r->bty));
|
645
665
|
/* s, ax, px, aty do *not* have tau divided out, so need to divide */
|
646
|
-
prl = MAX(MAX(NORM(b, w->m) * r->tau, NORM(s, w->m)),
|
666
|
+
prl = MAX(MAX(NORM(b, w->d->m) * r->tau, NORM(s, w->d->m)),
|
667
|
+
NORM(r->ax, w->d->m)) /
|
647
668
|
r->tau;
|
648
|
-
drl = MAX(MAX(NORM(c, w->n) * r->tau, NORM(r->px, w->n)),
|
649
|
-
NORM(r->aty, w->n)) /
|
669
|
+
drl = MAX(MAX(NORM(c, w->d->n) * r->tau, NORM(r->px, w->d->n)),
|
670
|
+
NORM(r->aty, w->d->n)) /
|
650
671
|
r->tau;
|
651
672
|
if (isless(r->res_pri, eps_abs + eps_rel * prl) &&
|
652
673
|
isless(r->res_dual, eps_abs + eps_rel * drl) &&
|
@@ -722,7 +743,6 @@ static scs_int validate(const ScsData *d, const ScsCone *k,
|
|
722
743
|
|
723
744
|
static ScsResiduals *init_residuals(const ScsData *d) {
|
724
745
|
ScsResiduals *r = (ScsResiduals *)scs_calloc(1, sizeof(ScsResiduals));
|
725
|
-
r->last_iter = -1;
|
726
746
|
r->ax = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
727
747
|
r->ax_s = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
728
748
|
r->ax_s_btau = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
@@ -732,16 +752,44 @@ static ScsResiduals *init_residuals(const ScsData *d) {
|
|
732
752
|
return r;
|
733
753
|
}
|
734
754
|
|
755
|
+
scs_int scs_update(ScsWork *w, scs_float *b, scs_float *c) {
|
756
|
+
SCS(timer) update_timer;
|
757
|
+
SCS(tic)(&update_timer);
|
758
|
+
|
759
|
+
if (b) {
|
760
|
+
memcpy(w->b_orig, b, w->d->m * sizeof(scs_float));
|
761
|
+
memcpy(w->d->b, b, w->d->m * sizeof(scs_float));
|
762
|
+
} else {
|
763
|
+
memcpy(w->d->b, w->b_orig, w->d->m * sizeof(scs_float));
|
764
|
+
}
|
765
|
+
if (c) {
|
766
|
+
memcpy(w->c_orig, c, w->d->n * sizeof(scs_float));
|
767
|
+
memcpy(w->d->c, c, w->d->n * sizeof(scs_float));
|
768
|
+
} else {
|
769
|
+
memcpy(w->d->c, w->c_orig, w->d->n * sizeof(scs_float));
|
770
|
+
}
|
771
|
+
|
772
|
+
/* normalize */
|
773
|
+
if (w->scal) {
|
774
|
+
SCS(normalize_b_c)(w->scal, w->d->b, w->d->c);
|
775
|
+
}
|
776
|
+
|
777
|
+
/* override setup time with update time, since the update is the 'setup' */
|
778
|
+
w->setup_time = SCS(tocq)(&update_timer);
|
779
|
+
return 0;
|
780
|
+
}
|
781
|
+
|
735
782
|
/* Sets the diag_r vector, given the scale parameters in work */
|
736
783
|
static void set_diag_r(ScsWork *w) {
|
737
784
|
scs_int i;
|
738
|
-
for (i = 0; i < w->n; ++i) {
|
785
|
+
for (i = 0; i < w->d->n; ++i) {
|
739
786
|
w->diag_r[i] = w->stgs->rho_x;
|
740
787
|
}
|
741
788
|
/* use cone information to set R_y */
|
742
|
-
SCS(set_r_y)(w->cone_work, w->scale, &(w->diag_r[w->n]));
|
789
|
+
SCS(set_r_y)(w->cone_work, w->stgs->scale, &(w->diag_r[w->d->n]));
|
743
790
|
/* if modified need to SCS(enforce_cone_boundaries)(...) */
|
744
|
-
w->diag_r[w->n + w->m] =
|
791
|
+
w->diag_r[w->d->n + w->d->m] =
|
792
|
+
TAU_FACTOR; /* TODO: is this the best choice? */
|
745
793
|
}
|
746
794
|
|
747
795
|
static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
@@ -755,18 +803,21 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
755
803
|
scs_printf("ERROR: allocating work failure\n");
|
756
804
|
return SCS_NULL;
|
757
805
|
}
|
758
|
-
/*
|
759
|
-
w->d =
|
760
|
-
w->
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
w->
|
765
|
-
w->
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
w->
|
806
|
+
/* deep copy data */
|
807
|
+
w->d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
808
|
+
SCS(deep_copy_data)(w->d, d);
|
809
|
+
d = SCS_NULL; /* for safety */
|
810
|
+
|
811
|
+
/* deep copy cone */
|
812
|
+
w->k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
813
|
+
SCS(deep_copy_cone)(w->k, k);
|
814
|
+
k = SCS_NULL; /* for safety */
|
815
|
+
|
816
|
+
/* deep copy settings */
|
817
|
+
w->stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
818
|
+
SCS(deep_copy_stgs)(w->stgs, stgs);
|
819
|
+
stgs = SCS_NULL; /* for safety */
|
820
|
+
|
770
821
|
/* allocate workspace: */
|
771
822
|
w->u = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
772
823
|
w->u_t = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
@@ -779,64 +830,44 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
779
830
|
w->diag_r = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
780
831
|
/* x,y,s struct */
|
781
832
|
w->xys_orig = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
782
|
-
w->xys_orig->x = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
783
|
-
w->xys_orig->s = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
784
|
-
w->xys_orig->y = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
785
|
-
w->r_orig = init_residuals(d);
|
786
|
-
|
787
|
-
w->
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
w->c_orig = d->c;
|
792
|
-
w->b_normalized = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
793
|
-
w->c_normalized = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
794
|
-
memcpy(w->b_normalized, w->b_orig, w->m * sizeof(scs_float));
|
795
|
-
memcpy(w->c_normalized, w->c_orig, w->n * sizeof(scs_float));
|
796
|
-
|
797
|
-
if (!(w->cone_work = SCS(init_cone)(k, w->m))) {
|
798
|
-
scs_printf("ERROR: init_cone failure\n");
|
833
|
+
w->xys_orig->x = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
|
834
|
+
w->xys_orig->s = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
835
|
+
w->xys_orig->y = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
836
|
+
w->r_orig = init_residuals(w->d);
|
837
|
+
w->b_orig = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
838
|
+
w->c_orig = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
|
839
|
+
|
840
|
+
if (!w->c_orig) {
|
841
|
+
scs_printf("ERROR: work memory allocation failure\n");
|
799
842
|
return SCS_NULL;
|
800
843
|
}
|
801
|
-
set_diag_r(w);
|
802
844
|
|
803
|
-
if (!w->
|
804
|
-
scs_printf("ERROR:
|
845
|
+
if (!(w->cone_work = SCS(init_cone)(w->k, w->d->m))) {
|
846
|
+
scs_printf("ERROR: init_cone failure\n");
|
805
847
|
return SCS_NULL;
|
806
848
|
}
|
849
|
+
set_diag_r(w);
|
807
850
|
|
808
851
|
if (w->stgs->normalize) {
|
809
852
|
w->xys_normalized = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
810
|
-
w->xys_normalized->x = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
811
|
-
w->xys_normalized->s = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
812
|
-
w->xys_normalized->y = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
813
|
-
w->r_normalized = init_residuals(d);
|
814
|
-
|
815
|
-
#ifdef COPYAMATRIX
|
816
|
-
if (!SCS(copy_matrix)(&(w->A), d->A)) {
|
817
|
-
scs_printf("ERROR: copy A matrix failed\n");
|
818
|
-
return SCS_NULL;
|
819
|
-
}
|
820
|
-
if (w->P && !SCS(copy_matrix)(&(w->P), d->P)) {
|
821
|
-
scs_printf("ERROR: copy P matrix failed\n");
|
822
|
-
return SCS_NULL;
|
823
|
-
}
|
824
|
-
#endif
|
853
|
+
w->xys_normalized->x = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
|
854
|
+
w->xys_normalized->s = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
855
|
+
w->xys_normalized->y = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
856
|
+
w->r_normalized = init_residuals(w->d);
|
825
857
|
/* this allocates memory that must be freed */
|
826
|
-
w->scal = SCS(normalize_a_p)(w->P, w->A, w->
|
827
|
-
w->cone_work);
|
858
|
+
w->scal = SCS(normalize_a_p)(w->d->P, w->d->A, w->cone_work);
|
828
859
|
} else {
|
829
860
|
w->xys_normalized = w->xys_orig;
|
830
861
|
w->r_normalized = w->r_orig;
|
831
862
|
w->scal = SCS_NULL;
|
832
863
|
}
|
833
|
-
|
864
|
+
/* set w->*_orig and performs normalization if appropriate */
|
865
|
+
scs_update(w, w->d->b, w->d->c);
|
866
|
+
|
867
|
+
if (!(w->p = SCS(init_lin_sys_work)(w->d->A, w->d->P, w->diag_r))) {
|
834
868
|
scs_printf("ERROR: init_lin_sys_work failure\n");
|
835
869
|
return SCS_NULL;
|
836
870
|
}
|
837
|
-
/* Acceleration */
|
838
|
-
w->rejected_accel_steps = 0;
|
839
|
-
w->accepted_accel_steps = 0;
|
840
871
|
if (w->stgs->acceleration_lookback) {
|
841
872
|
/* TODO(HACK!) negative acceleration_lookback interpreted as type-II */
|
842
873
|
if (!(w->accel = aa_init(l, ABS(w->stgs->acceleration_lookback),
|
@@ -858,16 +889,31 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
858
889
|
|
859
890
|
static void update_work_cache(ScsWork *w) {
|
860
891
|
/* g = (I + M)^{-1} h */
|
861
|
-
memcpy(w->g, w->h, (w->n + w->m) * sizeof(scs_float));
|
862
|
-
SCS(scale_array)(&(w->g[w->n]), -1., w->m);
|
892
|
+
memcpy(w->g, w->h, (w->d->n + w->d->m) * sizeof(scs_float));
|
893
|
+
SCS(scale_array)(&(w->g[w->d->n]), -1., w->d->m);
|
863
894
|
SCS(solve_lin_sys)(w->p, w->g, SCS_NULL, CG_BEST_TOL);
|
864
895
|
return;
|
865
896
|
}
|
866
897
|
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
|
898
|
+
/* Reset quantities specific to current solve */
|
899
|
+
static void reset_tracking(ScsWork *w) {
|
900
|
+
w->last_scale_update_iter = 0;
|
901
|
+
w->sum_log_scale_factor = 0.;
|
902
|
+
w->n_log_scale_factor = 0;
|
903
|
+
w->scale_updates = 0;
|
904
|
+
w->time_limit_reached = 0;
|
905
|
+
/* Acceleration */
|
906
|
+
w->rejected_accel_steps = 0;
|
907
|
+
w->accepted_accel_steps = 0;
|
908
|
+
w->aa_norm = 0.;
|
909
|
+
/* Need this to force residual calc if previous solve solved at iter 0 */
|
910
|
+
w->r_normalized->last_iter = -1;
|
911
|
+
w->r_orig->last_iter = -1;
|
912
|
+
}
|
913
|
+
|
914
|
+
static scs_int update_work(ScsWork *w, ScsSolution *sol) {
|
915
|
+
reset_tracking(w);
|
916
|
+
|
871
917
|
if (w->stgs->warm_start) {
|
872
918
|
warm_start_vars(w, sol);
|
873
919
|
} else {
|
@@ -875,8 +921,8 @@ static scs_int update_work(const ScsData *d, ScsWork *w, ScsSolution *sol) {
|
|
875
921
|
}
|
876
922
|
|
877
923
|
/* h = [c;b] */
|
878
|
-
memcpy(w->h, w->
|
879
|
-
memcpy(&(w->h[n]), w->
|
924
|
+
memcpy(w->h, w->d->c, w->d->n * sizeof(scs_float));
|
925
|
+
memcpy(&(w->h[w->d->n]), w->d->b, w->d->m * sizeof(scs_float));
|
880
926
|
update_work_cache(w);
|
881
927
|
return 0;
|
882
928
|
}
|
@@ -897,15 +943,15 @@ static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
897
943
|
|
898
944
|
scs_int iters_since_last_update = iter - w->last_scale_update_iter;
|
899
945
|
/* ||Ax + s - b * tau|| */
|
900
|
-
scs_float relative_res_pri =
|
901
|
-
|
902
|
-
|
903
|
-
|
946
|
+
scs_float relative_res_pri = SAFEDIV_POS(
|
947
|
+
SCALE_NORM(r->ax_s_btau, w->d->m),
|
948
|
+
MAX(MAX(SCALE_NORM(r->ax, w->d->m), SCALE_NORM(xys->s, w->d->m)),
|
949
|
+
SCALE_NORM(b, w->d->m) * r->tau));
|
904
950
|
/* ||Px + A'y + c * tau|| */
|
905
|
-
scs_float relative_res_dual =
|
906
|
-
|
907
|
-
|
908
|
-
|
951
|
+
scs_float relative_res_dual = SAFEDIV_POS(
|
952
|
+
SCALE_NORM(r->px_aty_ctau, w->d->n),
|
953
|
+
MAX(MAX(SCALE_NORM(r->px, w->d->n), SCALE_NORM(r->aty, w->d->n)),
|
954
|
+
SCALE_NORM(c, w->d->n) * r->tau));
|
909
955
|
|
910
956
|
/* higher scale makes res_pri go down faster, so increase if res_pri larger */
|
911
957
|
w->sum_log_scale_factor += log(relative_res_pri) - log(relative_res_dual);
|
@@ -919,8 +965,9 @@ static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
919
965
|
if (iters_since_last_update < RESCALING_MIN_ITERS) {
|
920
966
|
return;
|
921
967
|
}
|
922
|
-
new_scale =
|
923
|
-
|
968
|
+
new_scale =
|
969
|
+
MIN(MAX(w->stgs->scale * factor, MIN_SCALE_VALUE), MAX_SCALE_VALUE);
|
970
|
+
if (new_scale == w->stgs->scale) {
|
924
971
|
return;
|
925
972
|
}
|
926
973
|
if (should_update_r(factor, iters_since_last_update)) {
|
@@ -928,7 +975,7 @@ static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
928
975
|
w->sum_log_scale_factor = 0;
|
929
976
|
w->n_log_scale_factor = 0;
|
930
977
|
w->last_scale_update_iter = iter;
|
931
|
-
w->scale = new_scale;
|
978
|
+
w->stgs->scale = new_scale;
|
932
979
|
|
933
980
|
/* update diag r vector */
|
934
981
|
set_diag_r(w);
|
@@ -947,7 +994,7 @@ static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
947
994
|
/* solve: R^+ (v^+ + u - 2u_t) = rsk = R(v + u - 2u_t)
|
948
995
|
* => v^+ = R+^-1 rsk + 2u_t - u
|
949
996
|
*/
|
950
|
-
for (i = 0; i < w->n + w->m + 1; i++) {
|
997
|
+
for (i = 0; i < w->d->n + w->d->m + 1; i++) {
|
951
998
|
w->v[i] = w->rsk[i] / w->diag_r[i] + 2 * w->u_t[i] - w->u[i];
|
952
999
|
}
|
953
1000
|
}
|
@@ -959,7 +1006,8 @@ static inline void normalize_v(scs_float *v, scs_int len) {
|
|
959
1006
|
SCS(scale_array)(v, SQRTF((scs_float)len) * ITERATE_NORM / v_norm, len);
|
960
1007
|
}
|
961
1008
|
|
962
|
-
scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info
|
1009
|
+
scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
1010
|
+
scs_int warm_start) {
|
963
1011
|
scs_int i;
|
964
1012
|
SCS(timer) solve_timer, lin_sys_timer, cone_timer, accel_timer;
|
965
1013
|
scs_float total_accel_time = 0.0, total_cone_time = 0.0,
|
@@ -968,16 +1016,18 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
968
1016
|
scs_printf("ERROR: missing ScsWork, ScsSolution or ScsInfo input\n");
|
969
1017
|
return SCS_FAILED;
|
970
1018
|
}
|
971
|
-
scs_int l = w->m + w->n + 1;
|
972
|
-
const ScsData *d = w->d;
|
1019
|
+
scs_int l = w->d->m + w->d->n + 1;
|
973
1020
|
const ScsCone *k = w->k;
|
974
|
-
|
1021
|
+
ScsSettings *stgs = w->stgs;
|
1022
|
+
/* set warm start */
|
1023
|
+
stgs->warm_start = warm_start;
|
1024
|
+
|
975
1025
|
/* initialize ctrl-c support */
|
976
1026
|
scs_start_interrupt_listener();
|
977
1027
|
SCS(tic)(&solve_timer);
|
978
1028
|
strcpy(info->lin_sys_solver, SCS(get_lin_sys_method)());
|
979
1029
|
info->status_val = SCS_UNFINISHED; /* not yet converged */
|
980
|
-
update_work(
|
1030
|
+
update_work(w, sol);
|
981
1031
|
|
982
1032
|
if (w->stgs->verbose) {
|
983
1033
|
print_header(w, k);
|
@@ -1008,7 +1058,7 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
1008
1058
|
/******************* linear system solve ********************/
|
1009
1059
|
SCS(tic)(&lin_sys_timer);
|
1010
1060
|
if (project_lin_sys(w, i) < 0) {
|
1011
|
-
return failure(w, w->m, w->n, sol, info, SCS_FAILED,
|
1061
|
+
return failure(w, w->d->m, w->d->n, sol, info, SCS_FAILED,
|
1012
1062
|
"error in project_lin_sys", "failure");
|
1013
1063
|
}
|
1014
1064
|
total_lin_sys_time += SCS(tocq)(&lin_sys_timer);
|
@@ -1016,7 +1066,7 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
1016
1066
|
/****************** project onto the cones ******************/
|
1017
1067
|
SCS(tic)(&cone_timer);
|
1018
1068
|
if (project_cones(w, k, i) < 0) {
|
1019
|
-
return failure(w, w->m, w->n, sol, info, SCS_FAILED,
|
1069
|
+
return failure(w, w->d->m, w->d->n, sol, info, SCS_FAILED,
|
1020
1070
|
"error in project_cones", "failure");
|
1021
1071
|
}
|
1022
1072
|
total_cone_time += SCS(tocq)(&cone_timer);
|
@@ -1027,8 +1077,8 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
1027
1077
|
|
1028
1078
|
if (i % CONVERGED_INTERVAL == 0) {
|
1029
1079
|
if (scs_is_interrupted()) {
|
1030
|
-
return failure(w, w->m, w->n, sol, info, SCS_SIGINT,
|
1031
|
-
"interrupted");
|
1080
|
+
return failure(w, w->d->m, w->d->n, sol, info, SCS_SIGINT,
|
1081
|
+
"interrupted", "interrupted");
|
1032
1082
|
}
|
1033
1083
|
populate_residual_struct(w, i);
|
1034
1084
|
if ((info->status_val = has_converged(w, i)) != 0) {
|
@@ -1076,14 +1126,14 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
1076
1126
|
if (w->stgs->log_csv_filename) {
|
1077
1127
|
/* calc residuals every iter if logging to csv */
|
1078
1128
|
populate_residual_struct(w, i);
|
1079
|
-
SCS(log_data_to_csv)(
|
1129
|
+
SCS(log_data_to_csv)(k, stgs, w, i, &solve_timer);
|
1080
1130
|
}
|
1081
1131
|
}
|
1082
1132
|
|
1083
1133
|
/* Final logging after full run */
|
1084
1134
|
if (w->stgs->log_csv_filename) {
|
1085
1135
|
populate_residual_struct(w, i);
|
1086
|
-
SCS(log_data_to_csv)(
|
1136
|
+
SCS(log_data_to_csv)(k, stgs, w, i, &solve_timer);
|
1087
1137
|
}
|
1088
1138
|
|
1089
1139
|
if (w->stgs->verbose) {
|
@@ -1111,14 +1161,6 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
1111
1161
|
void scs_finish(ScsWork *w) {
|
1112
1162
|
if (w) {
|
1113
1163
|
SCS(finish_cone)(w->cone_work);
|
1114
|
-
if (w->stgs && w->stgs->normalize) {
|
1115
|
-
#ifndef COPYAMATRIX
|
1116
|
-
SCS(un_normalize_a_p)(w->A, w->P, w->scal);
|
1117
|
-
#else
|
1118
|
-
SCS(free_scs_matrix)(w->A);
|
1119
|
-
SCS(free_scs_matrix)(w->P);
|
1120
|
-
#endif
|
1121
|
-
}
|
1122
1164
|
if (w->p) {
|
1123
1165
|
SCS(free_lin_sys_work)(w->p);
|
1124
1166
|
}
|
@@ -1142,6 +1184,10 @@ ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) {
|
|
1142
1184
|
scs_printf("ERROR: Validation returned failure\n");
|
1143
1185
|
return SCS_NULL;
|
1144
1186
|
}
|
1187
|
+
#endif
|
1188
|
+
#if VERBOSITY > 0
|
1189
|
+
scs_printf("size of scs_int = %lu, size of scs_float = %lu\n",
|
1190
|
+
sizeof(scs_int), sizeof(scs_float));
|
1145
1191
|
#endif
|
1146
1192
|
SCS(tic)(&init_timer);
|
1147
1193
|
if (stgs->write_data_filename) {
|
@@ -1160,12 +1206,8 @@ scs_int scs(const ScsData *d, const ScsCone *k, const ScsSettings *stgs,
|
|
1160
1206
|
ScsSolution *sol, ScsInfo *info) {
|
1161
1207
|
scs_int status;
|
1162
1208
|
ScsWork *w = scs_init(d, k, stgs);
|
1163
|
-
#if VERBOSITY > 0
|
1164
|
-
scs_printf("size of scs_int = %lu, size of scs_float = %lu\n",
|
1165
|
-
sizeof(scs_int), sizeof(scs_float));
|
1166
|
-
#endif
|
1167
1209
|
if (w) {
|
1168
|
-
scs_solve(w, sol, info);
|
1210
|
+
scs_solve(w, sol, info, stgs->warm_start);
|
1169
1211
|
status = info->status_val;
|
1170
1212
|
} else {
|
1171
1213
|
status = failure(SCS_NULL, d ? d->m : -1, d ? d->n : -1, sol, info,
|