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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +34 -5
  4. data/lib/scs/matrix.rb +72 -0
  5. data/lib/scs/solver.rb +19 -26
  6. data/lib/scs/version.rb +1 -1
  7. data/lib/scs.rb +1 -0
  8. data/vendor/scs/CITATION.cff +1 -1
  9. data/vendor/scs/CMakeLists.txt +2 -2
  10. data/vendor/scs/README.md +3 -1
  11. data/vendor/scs/include/cones.h +5 -3
  12. data/vendor/scs/include/glbopts.h +4 -5
  13. data/vendor/scs/include/normalize.h +1 -0
  14. data/vendor/scs/include/rw.h +3 -3
  15. data/vendor/scs/include/scs.h +45 -22
  16. data/vendor/scs/include/scs_work.h +15 -18
  17. data/vendor/scs/include/util.h +3 -1
  18. data/vendor/scs/linsys/external/amd/LICENSE.txt +0 -897
  19. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +4 -2
  20. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +0 -5
  21. data/vendor/scs/linsys/scs_matrix.c +38 -67
  22. data/vendor/scs/linsys/scs_matrix.h +4 -3
  23. data/vendor/scs/scs.mk +0 -4
  24. data/vendor/scs/src/aa.c +0 -4
  25. data/vendor/scs/src/cones.c +63 -25
  26. data/vendor/scs/src/normalize.c +49 -0
  27. data/vendor/scs/src/rw.c +48 -40
  28. data/vendor/scs/src/scs.c +212 -170
  29. data/vendor/scs/src/util.c +26 -12
  30. data/vendor/scs/test/problem_utils.h +3 -3
  31. data/vendor/scs/test/problems/degenerate.h +1 -0
  32. data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -0
  33. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +5 -1
  34. data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -0
  35. data/vendor/scs/test/problems/qafiro_tiny_qp.h +2 -1
  36. data/vendor/scs/test/problems/random_prob.h +5 -1
  37. data/vendor/scs/test/problems/rob_gauss_cov_est.h +8 -1
  38. data/vendor/scs/test/problems/small_lp.h +4 -1
  39. data/vendor/scs/test/problems/small_qp.h +42 -7
  40. data/vendor/scs/test/problems/test_validation.h +4 -1
  41. data/vendor/scs/test/problems/unbounded_tiny_qp.h +3 -3
  42. data/vendor/scs/test/random_socp_prob.c +3 -1
  43. data/vendor/scs/test/run_from_file.c +15 -3
  44. 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->b_normalized);
44
- scs_free(w->c_normalized);
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, warm_start: %i\n",
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, (int)stgs->warm_start);
95
- /* , stgs->rho_x); */
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
- memcpy(v, sol->x, n * sizeof(scs_float));
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->b_normalized, m, -r->tau);
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->c_normalized, n, r->tau);
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->b_normalized, m);
290
- r->ctx_tau = SCS(dot)(x, w->c_normalized, n);
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
- 1e-5 * MAX(SCS(norm_inf)(sol->s, w->m), SCS(norm_inf)(sol->y, w->m))) {
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)), NORM(r->ax, 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] = TAU_FACTOR; /* TODO: is this the best choice? */
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
- /* get settings and dims from data struct */
759
- w->d = d;
760
- w->k = k;
761
- w->stgs = stgs;
762
- w->scale = stgs->scale; /* initial scale, may be updated */
763
- w->m = d->m;
764
- w->n = d->n;
765
- w->last_scale_update_iter = 0;
766
- w->sum_log_scale_factor = 0.;
767
- w->n_log_scale_factor = 0;
768
- w->scale_updates = 0;
769
- w->time_limit_reached = 0;
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->A = d->A;
788
- w->P = d->P;
789
-
790
- w->b_orig = d->b;
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->c_normalized) {
804
- scs_printf("ERROR: work memory allocation failure\n");
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->b_normalized, w->c_normalized,
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
- if (!(w->p = SCS(init_lin_sys_work)(w->A, w->P, w->diag_r))) {
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
- static scs_int update_work(const ScsData *d, ScsWork *w, ScsSolution *sol) {
868
- /* before normalization */
869
- scs_int n = d->n;
870
- scs_int m = d->m;
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->c_normalized, n * sizeof(scs_float));
879
- memcpy(&(w->h[n]), w->b_normalized, m * sizeof(scs_float));
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
- SAFEDIV_POS(SCALE_NORM(r->ax_s_btau, w->m),
902
- MAX(MAX(SCALE_NORM(r->ax, w->m), SCALE_NORM(xys->s, w->m)),
903
- SCALE_NORM(b, w->m) * r->tau));
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
- SAFEDIV_POS(SCALE_NORM(r->px_aty_ctau, w->n),
907
- MAX(MAX(SCALE_NORM(r->px, w->n), SCALE_NORM(r->aty, w->n)),
908
- SCALE_NORM(c, w->n) * r->tau));
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 = MIN(MAX(w->scale * factor, MIN_SCALE_VALUE), MAX_SCALE_VALUE);
923
- if (new_scale == w->scale) {
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
- const ScsSettings *stgs = w->stgs;
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(d, w, sol);
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, "interrupted",
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)(d, k, stgs, w, i, &solve_timer);
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)(d, k, stgs, w, i, &solve_timer);
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,