scs 0.3.0 → 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 +14 -0
- data/README.md +42 -13
- data/lib/scs/ffi.rb +1 -7
- 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 +55 -7
- data/vendor/scs/Makefile +9 -9
- data/vendor/scs/README.md +4 -1
- data/vendor/scs/include/aa.h +1 -1
- data/vendor/scs/include/cones.h +17 -12
- data/vendor/scs/include/glbopts.h +27 -66
- data/vendor/scs/include/linalg.h +2 -1
- data/vendor/scs/include/linsys.h +13 -13
- data/vendor/scs/include/normalize.h +7 -5
- data/vendor/scs/include/rw.h +3 -3
- data/vendor/scs/include/scs.h +85 -106
- data/vendor/scs/include/scs_types.h +34 -0
- data/vendor/scs/include/scs_work.h +80 -0
- data/vendor/scs/include/util.h +3 -1
- data/vendor/scs/linsys/cpu/direct/private.c +86 -73
- data/vendor/scs/linsys/cpu/direct/private.h +2 -2
- data/vendor/scs/linsys/cpu/indirect/private.c +42 -33
- data/vendor/scs/linsys/cpu/indirect/private.h +1 -2
- data/vendor/scs/linsys/csparse.c +3 -3
- data/vendor/scs/linsys/external/amd/LICENSE.txt +0 -897
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +9 -7
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +1 -1
- data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
- data/vendor/scs/linsys/gpu/gpu.h +8 -11
- data/vendor/scs/linsys/gpu/indirect/private.c +72 -49
- data/vendor/scs/linsys/gpu/indirect/private.h +14 -13
- data/vendor/scs/linsys/scs_matrix.c +55 -104
- data/vendor/scs/linsys/scs_matrix.h +5 -4
- data/vendor/scs/scs.mk +1 -5
- data/vendor/scs/src/aa.c +13 -8
- data/vendor/scs/src/cones.c +197 -108
- data/vendor/scs/src/linalg.c +25 -0
- data/vendor/scs/src/normalize.c +75 -26
- data/vendor/scs/src/rw.c +74 -30
- data/vendor/scs/src/scs.c +300 -264
- data/vendor/scs/src/scs_version.c +8 -6
- data/vendor/scs/src/util.c +27 -13
- data/vendor/scs/test/minunit.h +6 -1
- data/vendor/scs/test/problem_utils.h +28 -35
- data/vendor/scs/test/problems/degenerate.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +6 -2
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +2 -1
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +5 -4
- data/vendor/scs/test/problems/random_prob.h +6 -2
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +9 -2
- data/vendor/scs/test/problems/small_lp.h +7 -2
- data/vendor/scs/test/problems/small_qp.h +387 -0
- data/vendor/scs/test/problems/{test_fails.h → test_validation.h} +7 -4
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +4 -4
- data/vendor/scs/test/random_socp_prob.c +4 -2
- data/vendor/scs/test/run_from_file.c +16 -4
- data/vendor/scs/test/run_tests.c +23 -14
- metadata +10 -35
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/csparse.o +0 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/scs_matrix.o +0 -0
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_indir.o +0 -0
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.o +0 -0
data/vendor/scs/src/scs.c
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "normalize.h"
|
|
8
8
|
#include "rw.h"
|
|
9
9
|
#include "scs_matrix.h"
|
|
10
|
+
#include "scs_work.h"
|
|
10
11
|
#include "util.h"
|
|
11
12
|
|
|
12
13
|
/* printing header */
|
|
@@ -39,24 +40,34 @@ static void free_work(ScsWork *w) {
|
|
|
39
40
|
scs_free(w->rsk);
|
|
40
41
|
scs_free(w->h);
|
|
41
42
|
scs_free(w->g);
|
|
42
|
-
scs_free(w->
|
|
43
|
-
scs_free(w->
|
|
44
|
-
scs_free(w->rho_y_vec);
|
|
43
|
+
scs_free(w->b_orig);
|
|
44
|
+
scs_free(w->c_orig);
|
|
45
45
|
scs_free(w->lin_sys_warm_start);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
46
|
+
scs_free(w->diag_r);
|
|
47
|
+
SCS(free_sol)(w->xys_orig);
|
|
49
48
|
if (w->scal) {
|
|
50
49
|
scs_free(w->scal->D);
|
|
51
50
|
scs_free(w->scal->E);
|
|
52
51
|
scs_free(w->scal);
|
|
53
52
|
}
|
|
54
|
-
SCS(free_sol)(w->xys_orig);
|
|
55
53
|
free_residuals(w->r_orig);
|
|
56
|
-
if (w->stgs->normalize) {
|
|
54
|
+
if (w->stgs && w->stgs->normalize) {
|
|
57
55
|
SCS(free_sol)(w->xys_normalized);
|
|
58
56
|
free_residuals(w->r_normalized);
|
|
59
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
|
+
}
|
|
60
71
|
scs_free(w);
|
|
61
72
|
}
|
|
62
73
|
}
|
|
@@ -78,7 +89,7 @@ static void print_init_header(const ScsData *d, const ScsCone *k,
|
|
|
78
89
|
}
|
|
79
90
|
scs_printf("\n\t SCS v%s - Splitting Conic Solver\n\t(c) Brendan "
|
|
80
91
|
"O'Donoghue, Stanford University, 2012\n",
|
|
81
|
-
|
|
92
|
+
scs_version());
|
|
82
93
|
for (i = 0; i < LINE_LEN; ++i) {
|
|
83
94
|
scs_printf("-");
|
|
84
95
|
}
|
|
@@ -89,12 +100,11 @@ static void print_init_header(const ScsData *d, const ScsCone *k,
|
|
|
89
100
|
scs_free(cone_str);
|
|
90
101
|
scs_printf("settings: eps_abs: %.1e, eps_rel: %.1e, eps_infeas: %.1e\n"
|
|
91
102
|
"\t alpha: %.2f, scale: %.2e, adaptive_scale: %i\n"
|
|
92
|
-
"\t max_iters: %i, normalize: %i,
|
|
93
|
-
/*, rho_x: %.2e\n", */
|
|
103
|
+
"\t max_iters: %i, normalize: %i, rho_x: %.2e\n",
|
|
94
104
|
stgs->eps_abs, stgs->eps_rel, stgs->eps_infeas, stgs->alpha,
|
|
95
105
|
stgs->scale, (int)stgs->adaptive_scale, (int)stgs->max_iters,
|
|
96
|
-
(int)stgs->normalize,
|
|
97
|
-
/*
|
|
106
|
+
(int)stgs->normalize, stgs->rho_x);
|
|
107
|
+
/* (int)stgs->warm_start); */
|
|
98
108
|
if (stgs->acceleration_lookback != 0) {
|
|
99
109
|
scs_printf("\t acceleration_lookback: %i, acceleration_interval: %i\n",
|
|
100
110
|
(int)acceleration_lookback, (int)acceleration_interval);
|
|
@@ -156,24 +166,31 @@ static scs_int failure(ScsWork *w, scs_int m, scs_int n, ScsSolution *sol,
|
|
|
156
166
|
return status;
|
|
157
167
|
}
|
|
158
168
|
|
|
169
|
+
static inline scs_int _is_nan(scs_float x) {
|
|
170
|
+
return x != x;
|
|
171
|
+
}
|
|
172
|
+
|
|
159
173
|
/* given x,y,s warm start, set v = [x; s / R + y; 1]
|
|
160
|
-
*
|
|
174
|
+
* check for nans and set to zero if present
|
|
161
175
|
*/
|
|
162
176
|
static void warm_start_vars(ScsWork *w, ScsSolution *sol) {
|
|
163
|
-
scs_int n = w->n, m = w->m, i;
|
|
177
|
+
scs_int n = w->d->n, m = w->d->m, i;
|
|
164
178
|
scs_float *v = w->v;
|
|
165
179
|
/* normalize the warm-start */
|
|
166
180
|
if (w->stgs->normalize) {
|
|
167
|
-
SCS(normalize_sol)(w, sol);
|
|
181
|
+
SCS(normalize_sol)(w->scal, sol);
|
|
182
|
+
}
|
|
183
|
+
for (i = 0; i < n; ++i) {
|
|
184
|
+
v[i] = _is_nan(sol->x[i]) ? 0. : sol->x[i];
|
|
168
185
|
}
|
|
169
|
-
memcpy(v, sol->x, n * sizeof(scs_float));
|
|
170
186
|
for (i = 0; i < m; ++i) {
|
|
171
|
-
v[i + n] = sol->y[i] + sol->s[i] / w->
|
|
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];
|
|
172
189
|
}
|
|
173
190
|
v[n + m] = 1.0; /* tau = 1 */
|
|
174
191
|
/* un-normalize so sol unchanged */
|
|
175
192
|
if (w->stgs->normalize) {
|
|
176
|
-
SCS(un_normalize_sol)(w, sol);
|
|
193
|
+
SCS(un_normalize_sol)(w->scal, sol);
|
|
177
194
|
}
|
|
178
195
|
}
|
|
179
196
|
|
|
@@ -202,12 +219,12 @@ static void unnormalize_residuals(ScsWork *w) {
|
|
|
202
219
|
r->tau = r_n->tau;
|
|
203
220
|
|
|
204
221
|
/* mem copy arrays */
|
|
205
|
-
memcpy(r->ax, r_n->ax, w->m * sizeof(scs_float));
|
|
206
|
-
memcpy(r->ax_s, r_n->ax_s, w->m * sizeof(scs_float));
|
|
207
|
-
memcpy(r->ax_s_btau, r_n->ax_s_btau, w->m * sizeof(scs_float));
|
|
208
|
-
memcpy(r->aty, r_n->aty, w->n * sizeof(scs_float));
|
|
209
|
-
memcpy(r->px, r_n->px, w->n * sizeof(scs_float));
|
|
210
|
-
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));
|
|
211
228
|
|
|
212
229
|
/* unnormalize */
|
|
213
230
|
r->kap = r_n->kap / pd;
|
|
@@ -221,20 +238,20 @@ static void unnormalize_residuals(ScsWork *w) {
|
|
|
221
238
|
r->dobj = r_n->dobj / pd;
|
|
222
239
|
r->gap = r_n->gap / pd;
|
|
223
240
|
|
|
224
|
-
SCS(un_normalize_primal)(w, r->ax);
|
|
225
|
-
SCS(un_normalize_primal)(w, r->ax_s);
|
|
226
|
-
SCS(un_normalize_primal)(w, r->ax_s_btau);
|
|
227
|
-
SCS(un_normalize_dual)(w, r->aty);
|
|
228
|
-
SCS(un_normalize_dual)(w, r->px);
|
|
229
|
-
SCS(un_normalize_dual)(w, r->px_aty_ctau);
|
|
241
|
+
SCS(un_normalize_primal)(w->scal, r->ax);
|
|
242
|
+
SCS(un_normalize_primal)(w->scal, r->ax_s);
|
|
243
|
+
SCS(un_normalize_primal)(w->scal, r->ax_s_btau);
|
|
244
|
+
SCS(un_normalize_dual)(w->scal, r->aty);
|
|
245
|
+
SCS(un_normalize_dual)(w->scal, r->px);
|
|
246
|
+
SCS(un_normalize_dual)(w->scal, r->px_aty_ctau);
|
|
230
247
|
|
|
231
|
-
compute_residuals(r, w->m, w->n);
|
|
248
|
+
compute_residuals(r, w->d->m, w->d->n);
|
|
232
249
|
}
|
|
233
250
|
|
|
234
251
|
/* calculates un-normalized residual quantities */
|
|
235
252
|
/* this is somewhat slow but not a bottleneck */
|
|
236
253
|
static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
237
|
-
scs_int n = w->n, m = w->m;
|
|
254
|
+
scs_int n = w->d->n, m = w->d->m;
|
|
238
255
|
/* normalized x,y,s terms */
|
|
239
256
|
scs_float *x = w->xys_normalized->x;
|
|
240
257
|
scs_float *y = w->xys_normalized->y;
|
|
@@ -257,7 +274,7 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
|
257
274
|
/**************** PRIMAL *********************/
|
|
258
275
|
memset(r->ax, 0, m * sizeof(scs_float));
|
|
259
276
|
/* ax = Ax */
|
|
260
|
-
SCS(accum_by_a)(w->A, x, r->ax);
|
|
277
|
+
SCS(accum_by_a)(w->d->A, x, r->ax);
|
|
261
278
|
|
|
262
279
|
memcpy(r->ax_s, r->ax, m * sizeof(scs_float));
|
|
263
280
|
/* ax_s = Ax + s */
|
|
@@ -265,13 +282,13 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
|
265
282
|
|
|
266
283
|
memcpy(r->ax_s_btau, r->ax_s, m * sizeof(scs_float));
|
|
267
284
|
/* ax_s_btau = Ax + s - b * tau */
|
|
268
|
-
SCS(add_scaled_array)(r->ax_s_btau, w->
|
|
285
|
+
SCS(add_scaled_array)(r->ax_s_btau, w->d->b, m, -r->tau);
|
|
269
286
|
|
|
270
287
|
/**************** DUAL *********************/
|
|
271
288
|
memset(r->px, 0, n * sizeof(scs_float));
|
|
272
|
-
if (w->P) {
|
|
289
|
+
if (w->d->P) {
|
|
273
290
|
/* px = Px */
|
|
274
|
-
SCS(accum_by_p)(w->P, x, r->px);
|
|
291
|
+
SCS(accum_by_p)(w->d->P, x, r->px);
|
|
275
292
|
r->xt_p_x_tau = SCS(dot)(r->px, x, n);
|
|
276
293
|
} else {
|
|
277
294
|
r->xt_p_x_tau = 0.;
|
|
@@ -279,18 +296,18 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
|
279
296
|
|
|
280
297
|
memset(r->aty, 0, n * sizeof(scs_float));
|
|
281
298
|
/* aty = A'y */
|
|
282
|
-
SCS(accum_by_atrans)(w->A, y, r->aty);
|
|
299
|
+
SCS(accum_by_atrans)(w->d->A, y, r->aty);
|
|
283
300
|
|
|
284
301
|
/* r->px_aty_ctau = Px */
|
|
285
302
|
memcpy(r->px_aty_ctau, r->px, n * sizeof(scs_float));
|
|
286
303
|
/* r->px_aty_ctau = Px + A'y */
|
|
287
304
|
SCS(add_scaled_array)(r->px_aty_ctau, r->aty, n, 1.);
|
|
288
305
|
/* r->px_aty_ctau = Px + A'y + c * tau */
|
|
289
|
-
SCS(add_scaled_array)(r->px_aty_ctau, w->
|
|
306
|
+
SCS(add_scaled_array)(r->px_aty_ctau, w->d->c, n, r->tau);
|
|
290
307
|
|
|
291
308
|
/**************** OTHERS *****************/
|
|
292
|
-
r->bty_tau = SCS(dot)(y, w->
|
|
293
|
-
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);
|
|
294
311
|
|
|
295
312
|
r->bty = SAFEDIV_POS(r->bty_tau, r->tau);
|
|
296
313
|
r->ctx = SAFEDIV_POS(r->ctx_tau, r->tau);
|
|
@@ -306,58 +323,45 @@ static void populate_residual_struct(ScsWork *w, scs_int iter) {
|
|
|
306
323
|
memcpy(w->xys_orig->x, w->xys_normalized->x, n * sizeof(scs_float));
|
|
307
324
|
memcpy(w->xys_orig->y, w->xys_normalized->y, m * sizeof(scs_float));
|
|
308
325
|
memcpy(w->xys_orig->s, w->xys_normalized->s, m * sizeof(scs_float));
|
|
309
|
-
SCS(un_normalize_sol)(w, w->xys_orig);
|
|
326
|
+
SCS(un_normalize_sol)(w->scal, w->xys_orig);
|
|
310
327
|
unnormalize_residuals(w);
|
|
311
328
|
}
|
|
312
329
|
}
|
|
313
330
|
|
|
314
331
|
static void cold_start_vars(ScsWork *w) {
|
|
315
|
-
scs_int l = w->n + w->m + 1;
|
|
332
|
+
scs_int l = w->d->n + w->d->m + 1;
|
|
316
333
|
memset(w->v, 0, l * sizeof(scs_float));
|
|
317
334
|
w->v[l - 1] = 1.;
|
|
318
335
|
}
|
|
319
336
|
|
|
320
|
-
/* utility function that
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const scs_float *y) {
|
|
325
|
-
scs_int i, n = w->n, len = w->n + w->m;
|
|
337
|
+
/* utility function that computes x'Ry */
|
|
338
|
+
static inline scs_float dot_r(ScsWork *w, const scs_float *x,
|
|
339
|
+
const scs_float *y) {
|
|
340
|
+
scs_int i;
|
|
326
341
|
scs_float ip = 0.0;
|
|
327
|
-
for (i = 0; i < n; ++i) {
|
|
328
|
-
ip +=
|
|
329
|
-
}
|
|
330
|
-
for (i = n; i < len; ++i) {
|
|
331
|
-
ip += x[i] * y[i] * w->rho_y_vec[i - n];
|
|
342
|
+
for (i = 0; i < w->d->n + w->d->m; ++i) {
|
|
343
|
+
ip += x[i] * y[i] * w->diag_r[i];
|
|
332
344
|
}
|
|
333
345
|
return ip;
|
|
334
346
|
}
|
|
335
347
|
|
|
336
|
-
static inline scs_float get_tau_scale(ScsWork *w) {
|
|
337
|
-
return TAU_FACTOR; /* TAU_FACTOR * w->scale; */
|
|
338
|
-
}
|
|
339
|
-
|
|
340
348
|
static scs_float root_plus(ScsWork *w, scs_float *p, scs_float *mu,
|
|
341
349
|
scs_float eta) {
|
|
342
|
-
scs_float b, c,
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
c = dot_with_diag_scaling(w, p, p) - dot_with_diag_scaling(w, p, mu);
|
|
348
|
-
tau = (-b + SQRTF(MAX(b * b - 4 * a * c, 0.))) / (2 * a);
|
|
349
|
-
return tau;
|
|
350
|
+
scs_float a, b, c, tau_scale = w->diag_r[w->d->n + w->d->m];
|
|
351
|
+
a = tau_scale + dot_r(w, w->g, w->g);
|
|
352
|
+
b = dot_r(w, mu, w->g) - 2 * dot_r(w, p, w->g) - eta * tau_scale;
|
|
353
|
+
c = dot_r(w, p, p) - dot_r(w, p, mu);
|
|
354
|
+
return (-b + SQRTF(MAX(b * b - 4 * a * c, 0.))) / (2 * a);
|
|
350
355
|
}
|
|
351
356
|
|
|
352
357
|
/* status < 0 indicates failure */
|
|
353
358
|
static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
|
354
|
-
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;
|
|
355
360
|
scs_float *warm_start = SCS_NULL;
|
|
356
|
-
scs_float tol = -1.0; /* only used for indirect methods,
|
|
361
|
+
scs_float tol = -1.0; /* only used for indirect methods, overridden later */
|
|
357
362
|
memcpy(w->u_t, w->v, l * sizeof(scs_float));
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
w->u_t[i] *= -w->rho_y_vec[i - n];
|
|
363
|
+
for (i = 0; i < l - 1; ++i) {
|
|
364
|
+
w->u_t[i] *= (i < n ? 1 : -1) * w->diag_r[i];
|
|
361
365
|
}
|
|
362
366
|
#if INDIRECT > 0
|
|
363
367
|
/* compute warm start using the cone projection output */
|
|
@@ -366,12 +370,12 @@ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
|
|
366
370
|
/* warm_start = u[:n] + tau * g[:n] */
|
|
367
371
|
SCS(add_scaled_array)(warm_start, w->g, l - 1, w->u[l - 1]);
|
|
368
372
|
/* use normalized residuals to compute tolerance */
|
|
369
|
-
tol = MIN(CG_NORM(w->r_normalized->ax_s_btau, w->m),
|
|
370
|
-
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));
|
|
371
375
|
/* tol ~ O(1/k^(1+eps)) guarantees convergence */
|
|
372
376
|
/* use warm-start to calculate tolerance rather than w->u_t, since warm_start
|
|
373
377
|
* should be approximately equal to the true solution */
|
|
374
|
-
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) /
|
|
375
379
|
POWF((scs_float)iter + 1, CG_RATE));
|
|
376
380
|
tol = MAX(CG_BEST_TOL, tol);
|
|
377
381
|
#endif
|
|
@@ -394,40 +398,28 @@ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
|
|
|
394
398
|
* (no effect of w->stgs->alpha here).
|
|
395
399
|
*/
|
|
396
400
|
static void compute_rsk(ScsWork *w) {
|
|
397
|
-
scs_int i, l = w->m + w->n + 1;
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
w->rsk[i] = w->stgs->rho_x * (w->v[i] + w->u[i] - 2 * w->u_t[i]);
|
|
402
|
-
}
|
|
403
|
-
*/
|
|
404
|
-
/* s */
|
|
405
|
-
for (i = w->n; i < l - 1; ++i) {
|
|
406
|
-
w->rsk[i] = (w->v[i] + w->u[i] - 2 * w->u_t[i]) * w->rho_y_vec[i - w->n];
|
|
407
|
-
}
|
|
408
|
-
/* kappa, incorporates tau scaling parameter */
|
|
409
|
-
w->rsk[l - 1] =
|
|
410
|
-
get_tau_scale(w) * (w->v[l - 1] + w->u[l - 1] - 2 * w->u_t[l - 1]);
|
|
401
|
+
scs_int i, l = w->d->m + w->d->n + 1;
|
|
402
|
+
for (i = 0; i < l; ++i) {
|
|
403
|
+
w->rsk[i] = (w->v[i] + w->u[i] - 2 * w->u_t[i]) * w->diag_r[i];
|
|
404
|
+
}
|
|
411
405
|
}
|
|
412
406
|
|
|
413
407
|
static void update_dual_vars(ScsWork *w) {
|
|
414
|
-
scs_int i, l = w->n + w->m + 1;
|
|
415
|
-
scs_float a = w->stgs->alpha;
|
|
416
|
-
/* compute and store [r;s;kappa] */
|
|
417
|
-
compute_rsk(w);
|
|
408
|
+
scs_int i, l = w->d->n + w->d->m + 1;
|
|
418
409
|
for (i = 0; i < l; ++i) {
|
|
419
|
-
w->v[i] +=
|
|
410
|
+
w->v[i] += w->stgs->alpha * (w->u[i] - w->u_t[i]);
|
|
420
411
|
}
|
|
421
412
|
}
|
|
422
413
|
|
|
423
414
|
/* status < 0 indicates failure */
|
|
424
415
|
static scs_int project_cones(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
425
|
-
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;
|
|
426
417
|
for (i = 0; i < l; ++i) {
|
|
427
418
|
w->u[i] = 2 * w->u_t[i] - w->v[i];
|
|
428
419
|
}
|
|
429
420
|
/* u = [x;y;tau] */
|
|
430
|
-
status =
|
|
421
|
+
status =
|
|
422
|
+
SCS(proj_dual_cone)(&(w->u[n]), w->cone_work, w->scal, &(w->diag_r[n]));
|
|
431
423
|
if (iter < FEASIBLE_ITERS) {
|
|
432
424
|
w->u[l - 1] = 1.0;
|
|
433
425
|
} else {
|
|
@@ -438,30 +430,30 @@ static scs_int project_cones(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
|
438
430
|
|
|
439
431
|
static void sety(const ScsWork *w, ScsSolution *sol) {
|
|
440
432
|
if (!sol->y) {
|
|
441
|
-
sol->y = (scs_float *)scs_calloc(w->m, sizeof(scs_float));
|
|
433
|
+
sol->y = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
|
442
434
|
}
|
|
443
|
-
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));
|
|
444
436
|
}
|
|
445
437
|
|
|
446
438
|
/* s is contained in rsk */
|
|
447
439
|
static void sets(const ScsWork *w, ScsSolution *sol) {
|
|
448
440
|
if (!sol->s) {
|
|
449
|
-
sol->s = (scs_float *)scs_calloc(w->m, sizeof(scs_float));
|
|
441
|
+
sol->s = (scs_float *)scs_calloc(w->d->m, sizeof(scs_float));
|
|
450
442
|
}
|
|
451
|
-
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));
|
|
452
444
|
}
|
|
453
445
|
|
|
454
446
|
static void setx(const ScsWork *w, ScsSolution *sol) {
|
|
455
447
|
if (!sol->x) {
|
|
456
|
-
sol->x = (scs_float *)scs_calloc(w->n, sizeof(scs_float));
|
|
448
|
+
sol->x = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
|
|
457
449
|
}
|
|
458
|
-
memcpy(sol->x, w->u, w->n * sizeof(scs_float));
|
|
450
|
+
memcpy(sol->x, w->u, w->d->n * sizeof(scs_float));
|
|
459
451
|
}
|
|
460
452
|
|
|
461
453
|
static void set_solved(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
462
|
-
SCS(scale_array)(sol->x, SAFEDIV_POS(1.0, w->r_orig->tau), w->n);
|
|
463
|
-
SCS(scale_array)(sol->y, SAFEDIV_POS(1.0, w->r_orig->tau), w->m);
|
|
464
|
-
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);
|
|
465
457
|
info->gap = w->r_orig->gap;
|
|
466
458
|
info->res_pri = w->r_orig->res_pri;
|
|
467
459
|
info->res_dual = w->r_orig->res_dual;
|
|
@@ -472,9 +464,9 @@ static void set_solved(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
472
464
|
}
|
|
473
465
|
|
|
474
466
|
static void set_infeasible(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
475
|
-
SCS(scale_array)(sol->y, -1 / w->r_orig->bty_tau, w->m);
|
|
476
|
-
SCS(scale_array)(sol->x, NAN, w->n);
|
|
477
|
-
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);
|
|
478
470
|
info->gap = NAN;
|
|
479
471
|
info->res_pri = NAN;
|
|
480
472
|
info->res_dual = NAN;
|
|
@@ -485,9 +477,9 @@ static void set_infeasible(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
485
477
|
}
|
|
486
478
|
|
|
487
479
|
static void set_unbounded(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
488
|
-
SCS(scale_array)(sol->x, -1 / w->r_orig->ctx_tau, w->n);
|
|
489
|
-
SCS(scale_array)(sol->s, -1 / w->r_orig->ctx_tau, w->m);
|
|
490
|
-
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);
|
|
491
483
|
info->gap = NAN;
|
|
492
484
|
info->res_pri = NAN;
|
|
493
485
|
info->res_dual = NAN;
|
|
@@ -526,7 +518,7 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
|
526
518
|
sety(w, sol);
|
|
527
519
|
sets(w, sol);
|
|
528
520
|
if (w->stgs->normalize) {
|
|
529
|
-
SCS(un_normalize_sol)(w, sol);
|
|
521
|
+
SCS(un_normalize_sol)(w->scal, sol);
|
|
530
522
|
}
|
|
531
523
|
populate_residual_struct(w, iter);
|
|
532
524
|
info->setup_time = w->setup_time;
|
|
@@ -534,13 +526,13 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
|
534
526
|
info->res_infeas = w->r_orig->res_infeas;
|
|
535
527
|
info->res_unbdd_a = w->r_orig->res_unbdd_a;
|
|
536
528
|
info->res_unbdd_p = w->r_orig->res_unbdd_p;
|
|
537
|
-
info->scale = w->scale;
|
|
529
|
+
info->scale = w->stgs->scale;
|
|
538
530
|
info->scale_updates = w->scale_updates;
|
|
539
531
|
info->rejected_accel_steps = w->rejected_accel_steps;
|
|
540
532
|
info->accepted_accel_steps = w->accepted_accel_steps;
|
|
541
|
-
info->comp_slack = ABS(SCS(dot)(sol->s, sol->y, w->m));
|
|
542
|
-
if (info->comp_slack >
|
|
543
|
-
|
|
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))) {
|
|
544
536
|
scs_printf("WARNING - large complementary slackness residual: %f\n",
|
|
545
537
|
info->comp_slack);
|
|
546
538
|
}
|
|
@@ -570,22 +562,23 @@ static void print_summary(ScsWork *w, scs_int i, SCS(timer) * solve_timer) {
|
|
|
570
562
|
scs_printf("%*.2e ", (int)HSPACE, r->gap);
|
|
571
563
|
/* report mid point of primal and dual objective values */
|
|
572
564
|
scs_printf("%*.2e ", (int)HSPACE, 0.5 * (r->pobj + r->dobj));
|
|
573
|
-
scs_printf("%*.2e ", (int)HSPACE, w->scale);
|
|
565
|
+
scs_printf("%*.2e ", (int)HSPACE, w->stgs->scale);
|
|
574
566
|
scs_printf("%*.2e ", (int)HSPACE, SCS(tocq)(solve_timer) / 1e3);
|
|
575
567
|
scs_printf("\n");
|
|
576
568
|
|
|
577
569
|
#if VERBOSITY > 0
|
|
578
|
-
scs_printf("Norm u = %4f, ", SCS(norm_2)(w->u, w->n + w->m + 1));
|
|
579
|
-
scs_printf("Norm u_t = %4f, ", SCS(norm_2)(w->u_t, w->n + w->m + 1));
|
|
580
|
-
scs_printf("Norm v = %4f, ", SCS(norm_2)(w->v, w->n + w->m + 1));
|
|
581
|
-
scs_printf("Norm
|
|
582
|
-
scs_printf("Norm
|
|
583
|
-
scs_printf("Norm
|
|
584
|
-
scs_printf("Norm
|
|
585
|
-
scs_printf("
|
|
586
|
-
scs_printf("
|
|
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]);
|
|
587
580
|
scs_printf("|u - u_t| = %1.2e, ",
|
|
588
|
-
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));
|
|
589
582
|
scs_printf("res_infeas = %1.2e, ", r->res_infeas);
|
|
590
583
|
scs_printf("res_unbdd_a = %1.2e, ", r->res_unbdd_a);
|
|
591
584
|
scs_printf("res_unbdd_p = %1.2e, ", r->res_unbdd_p);
|
|
@@ -670,10 +663,11 @@ static scs_int has_converged(ScsWork *w, scs_int iter) {
|
|
|
670
663
|
/* xt_p_x, ctx, bty already have tau divided out */
|
|
671
664
|
grl = MAX(MAX(ABS(r->xt_p_x), ABS(r->ctx)), ABS(r->bty));
|
|
672
665
|
/* s, ax, px, aty do *not* have tau divided out, so need to divide */
|
|
673
|
-
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)) /
|
|
674
668
|
r->tau;
|
|
675
|
-
drl = MAX(MAX(NORM(c, w->n) * r->tau, NORM(r->px, w->n)),
|
|
676
|
-
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)) /
|
|
677
671
|
r->tau;
|
|
678
672
|
if (isless(r->res_pri, eps_abs + eps_rel * prl) &&
|
|
679
673
|
isless(r->res_dual, eps_abs + eps_rel * drl) &&
|
|
@@ -739,13 +733,16 @@ static scs_int validate(const ScsData *d, const ScsCone *k,
|
|
|
739
733
|
scs_printf("scale must be positive (1 works well).\n");
|
|
740
734
|
return -1;
|
|
741
735
|
}
|
|
736
|
+
if (stgs->acceleration_interval <= 0) {
|
|
737
|
+
scs_printf("acceleration_interval must be positive (10 works well).\n");
|
|
738
|
+
return -1;
|
|
739
|
+
}
|
|
742
740
|
return 0;
|
|
743
741
|
}
|
|
744
742
|
#endif
|
|
745
743
|
|
|
746
744
|
static ScsResiduals *init_residuals(const ScsData *d) {
|
|
747
745
|
ScsResiduals *r = (ScsResiduals *)scs_calloc(1, sizeof(ScsResiduals));
|
|
748
|
-
r->last_iter = -1;
|
|
749
746
|
r->ax = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
750
747
|
r->ax_s = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
751
748
|
r->ax_s_btau = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
@@ -755,6 +752,46 @@ static ScsResiduals *init_residuals(const ScsData *d) {
|
|
|
755
752
|
return r;
|
|
756
753
|
}
|
|
757
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
|
+
|
|
782
|
+
/* Sets the diag_r vector, given the scale parameters in work */
|
|
783
|
+
static void set_diag_r(ScsWork *w) {
|
|
784
|
+
scs_int i;
|
|
785
|
+
for (i = 0; i < w->d->n; ++i) {
|
|
786
|
+
w->diag_r[i] = w->stgs->rho_x;
|
|
787
|
+
}
|
|
788
|
+
/* use cone information to set R_y */
|
|
789
|
+
SCS(set_r_y)(w->cone_work, w->stgs->scale, &(w->diag_r[w->d->n]));
|
|
790
|
+
/* if modified need to SCS(enforce_cone_boundaries)(...) */
|
|
791
|
+
w->diag_r[w->d->n + w->d->m] =
|
|
792
|
+
TAU_FACTOR; /* TODO: is this the best choice? */
|
|
793
|
+
}
|
|
794
|
+
|
|
758
795
|
static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
759
796
|
const ScsSettings *stgs) {
|
|
760
797
|
ScsWork *w = (ScsWork *)scs_calloc(1, sizeof(ScsWork));
|
|
@@ -766,18 +803,21 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
|
766
803
|
scs_printf("ERROR: allocating work failure\n");
|
|
767
804
|
return SCS_NULL;
|
|
768
805
|
}
|
|
769
|
-
/*
|
|
770
|
-
w->d =
|
|
771
|
-
w->
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
w->
|
|
776
|
-
w->
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
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
|
+
|
|
781
821
|
/* allocate workspace: */
|
|
782
822
|
w->u = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
|
783
823
|
w->u_t = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
|
@@ -787,72 +827,47 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
|
787
827
|
w->h = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
|
|
788
828
|
w->g = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
|
|
789
829
|
w->lin_sys_warm_start = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
|
|
790
|
-
w->
|
|
830
|
+
w->diag_r = (scs_float *)scs_calloc(l, sizeof(scs_float));
|
|
791
831
|
/* x,y,s struct */
|
|
792
832
|
w->xys_orig = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
793
|
-
w->xys_orig->x = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
|
794
|
-
w->xys_orig->s = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
795
|
-
w->xys_orig->y = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
796
|
-
w->r_orig = init_residuals(d);
|
|
797
|
-
|
|
798
|
-
w->
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
w->b_orig = d->b;
|
|
802
|
-
w->c_orig = d->c;
|
|
803
|
-
w->b_normalized = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
804
|
-
w->c_normalized = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
|
805
|
-
memcpy(w->b_normalized, w->b_orig, w->m * sizeof(scs_float));
|
|
806
|
-
memcpy(w->c_normalized, w->c_orig, w->n * sizeof(scs_float));
|
|
807
|
-
SCS(set_rho_y_vec)(k, w->scale, w->rho_y_vec, w->m);
|
|
808
|
-
|
|
809
|
-
if (!w->c_normalized) {
|
|
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) {
|
|
810
841
|
scs_printf("ERROR: work memory allocation failure\n");
|
|
811
842
|
return SCS_NULL;
|
|
812
843
|
}
|
|
813
844
|
|
|
845
|
+
if (!(w->cone_work = SCS(init_cone)(w->k, w->d->m))) {
|
|
846
|
+
scs_printf("ERROR: init_cone failure\n");
|
|
847
|
+
return SCS_NULL;
|
|
848
|
+
}
|
|
849
|
+
set_diag_r(w);
|
|
850
|
+
|
|
814
851
|
if (w->stgs->normalize) {
|
|
815
852
|
w->xys_normalized = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
816
|
-
w->xys_normalized->x = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
|
817
|
-
w->xys_normalized->s = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
818
|
-
w->xys_normalized->y = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
819
|
-
w->r_normalized = init_residuals(d);
|
|
820
|
-
|
|
821
|
-
#ifdef COPYAMATRIX
|
|
822
|
-
if (!SCS(copy_matrix)(&(w->A), d->A)) {
|
|
823
|
-
scs_printf("ERROR: copy A matrix failed\n");
|
|
824
|
-
return SCS_NULL;
|
|
825
|
-
}
|
|
826
|
-
if (w->P && !SCS(copy_matrix)(&(w->P), d->P)) {
|
|
827
|
-
scs_printf("ERROR: copy P matrix failed\n");
|
|
828
|
-
return SCS_NULL;
|
|
829
|
-
}
|
|
830
|
-
#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);
|
|
831
857
|
/* this allocates memory that must be freed */
|
|
832
|
-
w->
|
|
833
|
-
w->scal = (ScsScaling *)scs_calloc(1, sizeof(ScsScaling));
|
|
834
|
-
SCS(normalize)
|
|
835
|
-
(w->P, w->A, w->b_normalized, w->c_normalized, w->scal, w->cone_boundaries,
|
|
836
|
-
w->cone_boundaries_len);
|
|
858
|
+
w->scal = SCS(normalize_a_p)(w->d->P, w->d->A, w->cone_work);
|
|
837
859
|
} else {
|
|
838
860
|
w->xys_normalized = w->xys_orig;
|
|
839
861
|
w->r_normalized = w->r_orig;
|
|
840
|
-
w->cone_boundaries_len = 0;
|
|
841
|
-
w->cone_boundaries = SCS_NULL;
|
|
842
862
|
w->scal = SCS_NULL;
|
|
843
863
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
if (!(w->p =
|
|
849
|
-
SCS(init_lin_sys_work)(w->A, w->P, w->rho_y_vec, w->stgs->rho_x))) {
|
|
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))) {
|
|
850
868
|
scs_printf("ERROR: init_lin_sys_work failure\n");
|
|
851
869
|
return SCS_NULL;
|
|
852
870
|
}
|
|
853
|
-
/* Acceleration */
|
|
854
|
-
w->rejected_accel_steps = 0;
|
|
855
|
-
w->accepted_accel_steps = 0;
|
|
856
871
|
if (w->stgs->acceleration_lookback) {
|
|
857
872
|
/* TODO(HACK!) negative acceleration_lookback interpreted as type-II */
|
|
858
873
|
if (!(w->accel = aa_init(l, ABS(w->stgs->acceleration_lookback),
|
|
@@ -874,16 +889,31 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
|
|
|
874
889
|
|
|
875
890
|
static void update_work_cache(ScsWork *w) {
|
|
876
891
|
/* g = (I + M)^{-1} h */
|
|
877
|
-
memcpy(w->g, w->h, (w->n + w->m) * sizeof(scs_float));
|
|
878
|
-
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);
|
|
879
894
|
SCS(solve_lin_sys)(w->p, w->g, SCS_NULL, CG_BEST_TOL);
|
|
880
895
|
return;
|
|
881
896
|
}
|
|
882
897
|
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
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
|
+
|
|
887
917
|
if (w->stgs->warm_start) {
|
|
888
918
|
warm_start_vars(w, sol);
|
|
889
919
|
} else {
|
|
@@ -891,18 +921,18 @@ static scs_int update_work(const ScsData *d, ScsWork *w, ScsSolution *sol) {
|
|
|
891
921
|
}
|
|
892
922
|
|
|
893
923
|
/* h = [c;b] */
|
|
894
|
-
memcpy(w->h, w->
|
|
895
|
-
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));
|
|
896
926
|
update_work_cache(w);
|
|
897
927
|
return 0;
|
|
898
928
|
}
|
|
899
929
|
|
|
900
930
|
/* will update if the factor is outside of range */
|
|
901
|
-
scs_int
|
|
931
|
+
scs_int should_update_r(scs_float factor, scs_int iter) {
|
|
902
932
|
return (factor > SQRTF(10.) || factor < 1. / SQRTF(10.));
|
|
903
933
|
}
|
|
904
934
|
|
|
905
|
-
static void
|
|
935
|
+
static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
906
936
|
scs_int i;
|
|
907
937
|
scs_float factor, new_scale;
|
|
908
938
|
|
|
@@ -913,15 +943,15 @@ static void maybe_update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
|
913
943
|
|
|
914
944
|
scs_int iters_since_last_update = iter - w->last_scale_update_iter;
|
|
915
945
|
/* ||Ax + s - b * tau|| */
|
|
916
|
-
scs_float relative_res_pri =
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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));
|
|
920
950
|
/* ||Px + A'y + c * tau|| */
|
|
921
|
-
scs_float relative_res_dual =
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
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));
|
|
925
955
|
|
|
926
956
|
/* higher scale makes res_pri go down faster, so increase if res_pri larger */
|
|
927
957
|
w->sum_log_scale_factor += log(relative_res_pri) - log(relative_res_dual);
|
|
@@ -935,18 +965,23 @@ static void maybe_update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
|
935
965
|
if (iters_since_last_update < RESCALING_MIN_ITERS) {
|
|
936
966
|
return;
|
|
937
967
|
}
|
|
938
|
-
new_scale =
|
|
939
|
-
|
|
968
|
+
new_scale =
|
|
969
|
+
MIN(MAX(w->stgs->scale * factor, MIN_SCALE_VALUE), MAX_SCALE_VALUE);
|
|
970
|
+
if (new_scale == w->stgs->scale) {
|
|
940
971
|
return;
|
|
941
972
|
}
|
|
942
|
-
if (
|
|
973
|
+
if (should_update_r(factor, iters_since_last_update)) {
|
|
943
974
|
w->scale_updates++;
|
|
944
975
|
w->sum_log_scale_factor = 0;
|
|
945
976
|
w->n_log_scale_factor = 0;
|
|
946
977
|
w->last_scale_update_iter = iter;
|
|
947
|
-
w->scale = new_scale;
|
|
948
|
-
|
|
949
|
-
|
|
978
|
+
w->stgs->scale = new_scale;
|
|
979
|
+
|
|
980
|
+
/* update diag r vector */
|
|
981
|
+
set_diag_r(w);
|
|
982
|
+
|
|
983
|
+
/* update linear systems */
|
|
984
|
+
SCS(update_lin_sys_diag_r)(w->p, w->diag_r);
|
|
950
985
|
|
|
951
986
|
/* update pre-solved quantities */
|
|
952
987
|
update_work_cache(w);
|
|
@@ -956,10 +991,11 @@ static void maybe_update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
|
|
|
956
991
|
aa_reset(w->accel);
|
|
957
992
|
}
|
|
958
993
|
/* update v, using fact that rsk, u, u_t vectors should be the same */
|
|
959
|
-
/* solve: R (v^+ + u - 2u_t) = rsk
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
994
|
+
/* solve: R^+ (v^+ + u - 2u_t) = rsk = R(v + u - 2u_t)
|
|
995
|
+
* => v^+ = R+^-1 rsk + 2u_t - u
|
|
996
|
+
*/
|
|
997
|
+
for (i = 0; i < w->d->n + w->d->m + 1; i++) {
|
|
998
|
+
w->v[i] = w->rsk[i] / w->diag_r[i] + 2 * w->u_t[i] - w->u[i];
|
|
963
999
|
}
|
|
964
1000
|
}
|
|
965
1001
|
}
|
|
@@ -970,7 +1006,8 @@ static inline void normalize_v(scs_float *v, scs_int len) {
|
|
|
970
1006
|
SCS(scale_array)(v, SQRTF((scs_float)len) * ITERATE_NORM / v_norm, len);
|
|
971
1007
|
}
|
|
972
1008
|
|
|
973
|
-
scs_int
|
|
1009
|
+
scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info,
|
|
1010
|
+
scs_int warm_start) {
|
|
974
1011
|
scs_int i;
|
|
975
1012
|
SCS(timer) solve_timer, lin_sys_timer, cone_timer, accel_timer;
|
|
976
1013
|
scs_float total_accel_time = 0.0, total_cone_time = 0.0,
|
|
@@ -979,15 +1016,18 @@ scs_int SCS(solve)(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
979
1016
|
scs_printf("ERROR: missing ScsWork, ScsSolution or ScsInfo input\n");
|
|
980
1017
|
return SCS_FAILED;
|
|
981
1018
|
}
|
|
982
|
-
scs_int l = w->m + w->n + 1;
|
|
983
|
-
const ScsData *d = w->d;
|
|
1019
|
+
scs_int l = w->d->m + w->d->n + 1;
|
|
984
1020
|
const ScsCone *k = w->k;
|
|
985
|
-
|
|
1021
|
+
ScsSettings *stgs = w->stgs;
|
|
1022
|
+
/* set warm start */
|
|
1023
|
+
stgs->warm_start = warm_start;
|
|
1024
|
+
|
|
986
1025
|
/* initialize ctrl-c support */
|
|
987
1026
|
scs_start_interrupt_listener();
|
|
988
1027
|
SCS(tic)(&solve_timer);
|
|
1028
|
+
strcpy(info->lin_sys_solver, SCS(get_lin_sys_method)());
|
|
989
1029
|
info->status_val = SCS_UNFINISHED; /* not yet converged */
|
|
990
|
-
update_work(
|
|
1030
|
+
update_work(w, sol);
|
|
991
1031
|
|
|
992
1032
|
if (w->stgs->verbose) {
|
|
993
1033
|
print_header(w, k);
|
|
@@ -1015,29 +1055,30 @@ scs_int SCS(solve)(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
1015
1055
|
/* store v_prev = v, *after* normalizing */
|
|
1016
1056
|
memcpy(w->v_prev, w->v, l * sizeof(scs_float));
|
|
1017
1057
|
|
|
1018
|
-
|
|
1058
|
+
/******************* linear system solve ********************/
|
|
1019
1059
|
SCS(tic)(&lin_sys_timer);
|
|
1020
1060
|
if (project_lin_sys(w, i) < 0) {
|
|
1021
|
-
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,
|
|
1022
1062
|
"error in project_lin_sys", "failure");
|
|
1023
1063
|
}
|
|
1024
1064
|
total_lin_sys_time += SCS(tocq)(&lin_sys_timer);
|
|
1025
1065
|
|
|
1026
|
-
|
|
1066
|
+
/****************** project onto the cones ******************/
|
|
1027
1067
|
SCS(tic)(&cone_timer);
|
|
1028
1068
|
if (project_cones(w, k, i) < 0) {
|
|
1029
|
-
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,
|
|
1030
1070
|
"error in project_cones", "failure");
|
|
1031
1071
|
}
|
|
1032
1072
|
total_cone_time += SCS(tocq)(&cone_timer);
|
|
1033
1073
|
|
|
1034
|
-
/* dual
|
|
1035
|
-
|
|
1074
|
+
/* compute [r;s;kappa], must be before dual var update */
|
|
1075
|
+
/* since Moreau decomp logic relies on v at start */
|
|
1076
|
+
compute_rsk(w);
|
|
1036
1077
|
|
|
1037
1078
|
if (i % CONVERGED_INTERVAL == 0) {
|
|
1038
1079
|
if (scs_is_interrupted()) {
|
|
1039
|
-
return failure(w, w->m, w->n, sol, info, SCS_SIGINT,
|
|
1040
|
-
"interrupted");
|
|
1080
|
+
return failure(w, w->d->m, w->d->n, sol, info, SCS_SIGINT,
|
|
1081
|
+
"interrupted", "interrupted");
|
|
1041
1082
|
}
|
|
1042
1083
|
populate_residual_struct(w, i);
|
|
1043
1084
|
if ((info->status_val = has_converged(w, i)) != 0) {
|
|
@@ -1051,6 +1092,21 @@ scs_int SCS(solve)(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
1051
1092
|
}
|
|
1052
1093
|
}
|
|
1053
1094
|
|
|
1095
|
+
/* Compute residuals. */
|
|
1096
|
+
if (w->stgs->verbose && i % PRINT_INTERVAL == 0) {
|
|
1097
|
+
populate_residual_struct(w, i);
|
|
1098
|
+
print_summary(w, i, &solve_timer);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/* If residuals are fresh then maybe compute new scale. */
|
|
1102
|
+
if (w->stgs->adaptive_scale && i == w->r_orig->last_iter) {
|
|
1103
|
+
update_scale(w, k, i);
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/****************** dual variable step **********************/
|
|
1107
|
+
/* do this after update_scale due to remapping that happens there */
|
|
1108
|
+
update_dual_vars(w);
|
|
1109
|
+
|
|
1054
1110
|
/* AA safeguard check.
|
|
1055
1111
|
* Perform safeguarding *after* convergence check to prevent safeguard
|
|
1056
1112
|
* overwriting converged iterate, since safeguard is on `v` and convergence
|
|
@@ -1066,29 +1122,18 @@ scs_int SCS(solve)(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
1066
1122
|
}
|
|
1067
1123
|
}
|
|
1068
1124
|
|
|
1069
|
-
/* Compute residuals. */
|
|
1070
|
-
if (w->stgs->verbose && i % PRINT_INTERVAL == 0) {
|
|
1071
|
-
populate_residual_struct(w, i);
|
|
1072
|
-
print_summary(w, i, &solve_timer);
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
/* If residuals are fresh then maybe compute new scale. */
|
|
1076
|
-
if (w->stgs->adaptive_scale && i == w->r_orig->last_iter) {
|
|
1077
|
-
maybe_update_scale(w, k, i);
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
1125
|
/* Log *after* updating scale so residual recalc does not affect alg */
|
|
1081
1126
|
if (w->stgs->log_csv_filename) {
|
|
1082
1127
|
/* calc residuals every iter if logging to csv */
|
|
1083
1128
|
populate_residual_struct(w, i);
|
|
1084
|
-
SCS(log_data_to_csv)(
|
|
1129
|
+
SCS(log_data_to_csv)(k, stgs, w, i, &solve_timer);
|
|
1085
1130
|
}
|
|
1086
1131
|
}
|
|
1087
1132
|
|
|
1088
1133
|
/* Final logging after full run */
|
|
1089
1134
|
if (w->stgs->log_csv_filename) {
|
|
1090
1135
|
populate_residual_struct(w, i);
|
|
1091
|
-
SCS(log_data_to_csv)(
|
|
1136
|
+
SCS(log_data_to_csv)(k, stgs, w, i, &solve_timer);
|
|
1092
1137
|
}
|
|
1093
1138
|
|
|
1094
1139
|
if (w->stgs->verbose) {
|
|
@@ -1113,17 +1158,9 @@ scs_int SCS(solve)(ScsWork *w, ScsSolution *sol, ScsInfo *info) {
|
|
|
1113
1158
|
return info->status_val;
|
|
1114
1159
|
}
|
|
1115
1160
|
|
|
1116
|
-
void
|
|
1161
|
+
void scs_finish(ScsWork *w) {
|
|
1117
1162
|
if (w) {
|
|
1118
1163
|
SCS(finish_cone)(w->cone_work);
|
|
1119
|
-
if (w->stgs && w->stgs->normalize) {
|
|
1120
|
-
#ifndef COPYAMATRIX
|
|
1121
|
-
SCS(un_normalize)(w->A, w->P, w->scal);
|
|
1122
|
-
#else
|
|
1123
|
-
SCS(free_scs_matrix)(w->A);
|
|
1124
|
-
SCS(free_scs_matrix)(w->P);
|
|
1125
|
-
#endif
|
|
1126
|
-
}
|
|
1127
1164
|
if (w->p) {
|
|
1128
1165
|
SCS(free_lin_sys_work)(w->p);
|
|
1129
1166
|
}
|
|
@@ -1134,8 +1171,7 @@ void SCS(finish)(ScsWork *w) {
|
|
|
1134
1171
|
}
|
|
1135
1172
|
}
|
|
1136
1173
|
|
|
1137
|
-
ScsWork *
|
|
1138
|
-
const ScsSettings *stgs) {
|
|
1174
|
+
ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) {
|
|
1139
1175
|
ScsWork *w;
|
|
1140
1176
|
SCS(timer) init_timer;
|
|
1141
1177
|
scs_start_interrupt_listener();
|
|
@@ -1148,6 +1184,10 @@ ScsWork *SCS(init)(const ScsData *d, const ScsCone *k,
|
|
|
1148
1184
|
scs_printf("ERROR: Validation returned failure\n");
|
|
1149
1185
|
return SCS_NULL;
|
|
1150
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));
|
|
1151
1191
|
#endif
|
|
1152
1192
|
SCS(tic)(&init_timer);
|
|
1153
1193
|
if (stgs->write_data_filename) {
|
|
@@ -1161,22 +1201,18 @@ ScsWork *SCS(init)(const ScsData *d, const ScsCone *k,
|
|
|
1161
1201
|
return w;
|
|
1162
1202
|
}
|
|
1163
1203
|
|
|
1164
|
-
/* this just calls
|
|
1204
|
+
/* this just calls scs_init, scs_solve, and scs_finish */
|
|
1165
1205
|
scs_int scs(const ScsData *d, const ScsCone *k, const ScsSettings *stgs,
|
|
1166
1206
|
ScsSolution *sol, ScsInfo *info) {
|
|
1167
1207
|
scs_int status;
|
|
1168
|
-
ScsWork *w =
|
|
1169
|
-
#if VERBOSITY > 0
|
|
1170
|
-
scs_printf("size of scs_int = %lu, size of scs_float = %lu\n",
|
|
1171
|
-
sizeof(scs_int), sizeof(scs_float));
|
|
1172
|
-
#endif
|
|
1208
|
+
ScsWork *w = scs_init(d, k, stgs);
|
|
1173
1209
|
if (w) {
|
|
1174
|
-
|
|
1210
|
+
scs_solve(w, sol, info, stgs->warm_start);
|
|
1175
1211
|
status = info->status_val;
|
|
1176
1212
|
} else {
|
|
1177
1213
|
status = failure(SCS_NULL, d ? d->m : -1, d ? d->n : -1, sol, info,
|
|
1178
1214
|
SCS_FAILED, "could not initialize work", "failure");
|
|
1179
1215
|
}
|
|
1180
|
-
|
|
1216
|
+
scs_finish(w);
|
|
1181
1217
|
return status;
|
|
1182
1218
|
}
|