scs 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +1 -1
  5. data/lib/scs/version.rb +1 -1
  6. data/vendor/scs/CITATION.cff +2 -2
  7. data/vendor/scs/CMakeLists.txt +284 -168
  8. data/vendor/scs/Makefile +43 -18
  9. data/vendor/scs/README.md +1 -1
  10. data/vendor/scs/include/glbopts.h +32 -13
  11. data/vendor/scs/include/linsys.h +8 -8
  12. data/vendor/scs/include/scs.h +6 -2
  13. data/vendor/scs/include/scs_types.h +3 -1
  14. data/vendor/scs/include/scs_work.h +9 -8
  15. data/vendor/scs/include/util.h +1 -1
  16. data/vendor/scs/linsys/cpu/direct/private.c +32 -153
  17. data/vendor/scs/linsys/cpu/direct/private.h +6 -6
  18. data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
  19. data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
  20. data/vendor/scs/linsys/csparse.c +140 -12
  21. data/vendor/scs/linsys/csparse.h +10 -17
  22. data/vendor/scs/linsys/gpu/gpu.c +4 -4
  23. data/vendor/scs/linsys/gpu/gpu.h +1 -1
  24. data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
  25. data/vendor/scs/linsys/mkl/direct/private.c +182 -0
  26. data/vendor/scs/linsys/mkl/direct/private.h +38 -0
  27. data/vendor/scs/linsys/scs_matrix.c +11 -5
  28. data/vendor/scs/scs.mk +39 -26
  29. data/vendor/scs/src/cones.c +15 -159
  30. data/vendor/scs/src/exp_cone.c +399 -0
  31. data/vendor/scs/src/normalize.c +4 -2
  32. data/vendor/scs/src/rw.c +93 -38
  33. data/vendor/scs/src/scs.c +83 -52
  34. data/vendor/scs/src/util.c +12 -3
  35. data/vendor/scs/test/minunit.h +2 -1
  36. data/vendor/scs/test/problem_utils.h +2 -1
  37. data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
  38. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +8 -3
  39. data/vendor/scs/test/problems/max_ent +0 -0
  40. data/vendor/scs/test/problems/max_ent.h +8 -0
  41. data/vendor/scs/test/problems/random_prob.h +2 -43
  42. data/vendor/scs/test/problems/rob_gauss_cov_est.h +7 -2
  43. data/vendor/scs/test/problems/test_exp_cone.h +84 -0
  44. data/vendor/scs/test/problems/test_prob_from_data_file.h +57 -0
  45. data/vendor/scs/test/run_from_file.c +7 -1
  46. data/vendor/scs/test/run_tests.c +22 -9
  47. metadata +10 -3
data/vendor/scs/src/scs.c CHANGED
@@ -76,7 +76,7 @@ static void print_init_header(const ScsData *d, const ScsCone *k,
76
76
  const ScsSettings *stgs) {
77
77
  scs_int i;
78
78
  char *cone_str = SCS(get_cone_header)(k);
79
- const char *lin_sys_method = SCS(get_lin_sys_method)();
79
+ const char *lin_sys_method = scs_get_lin_sys_method();
80
80
  #ifdef USE_LAPACK
81
81
  scs_int acceleration_lookback = stgs->acceleration_lookback;
82
82
  scs_int acceleration_interval = stgs->acceleration_interval;
@@ -195,17 +195,24 @@ static void warm_start_vars(ScsWork *w, ScsSolution *sol) {
195
195
  }
196
196
 
197
197
  static void compute_residuals(ScsResiduals *r, scs_int m, scs_int n) {
198
- r->res_pri = SAFEDIV_POS(NORM(r->ax_s_btau, m), r->tau);
199
- r->res_dual = SAFEDIV_POS(NORM(r->px_aty_ctau, n), r->tau);
198
+ scs_float nm_ax_s, nm_px, nm_aty;
199
+ scs_float nm_ax_s_btau = NORM(r->ax_s_btau, m);
200
+ scs_float nm_px_aty_ctau = NORM(r->px_aty_ctau, n);
201
+
202
+ r->res_pri = SAFEDIV_POS(nm_ax_s_btau, r->tau);
203
+ r->res_dual = SAFEDIV_POS(nm_px_aty_ctau, r->tau);
200
204
  r->res_unbdd_a = NAN;
201
205
  r->res_unbdd_p = NAN;
202
206
  r->res_infeas = NAN;
203
207
  if (r->ctx_tau < 0) {
204
- r->res_unbdd_a = SAFEDIV_POS(NORM(r->ax_s, m), -r->ctx_tau);
205
- r->res_unbdd_p = SAFEDIV_POS(NORM(r->px, n), -r->ctx_tau);
208
+ nm_ax_s = NORM(r->ax_s, m);
209
+ nm_px = NORM(r->px, n);
210
+ r->res_unbdd_a = SAFEDIV_POS(nm_ax_s, -r->ctx_tau);
211
+ r->res_unbdd_p = SAFEDIV_POS(nm_px, -r->ctx_tau);
206
212
  }
207
213
  if (r->bty_tau < 0) {
208
- r->res_infeas = SAFEDIV_POS(NORM(r->aty, n), -r->bty_tau);
214
+ nm_aty = NORM(r->aty, n);
215
+ r->res_infeas = SAFEDIV_POS(nm_aty, -r->bty_tau);
209
216
  }
210
217
  }
211
218
 
@@ -347,14 +354,15 @@ static inline scs_float dot_r(ScsWork *w, const scs_float *x,
347
354
 
348
355
  static scs_float root_plus(ScsWork *w, scs_float *p, scs_float *mu,
349
356
  scs_float eta) {
350
- scs_float a, b, c, tau_scale = w->diag_r[w->d->n + w->d->m];
357
+ scs_float a, b, c, rad, tau_scale = w->diag_r[w->d->n + w->d->m];
351
358
  a = tau_scale + dot_r(w, w->g, w->g);
352
359
  b = dot_r(w, mu, w->g) - 2 * dot_r(w, p, w->g) - eta * tau_scale;
353
360
  c = dot_r(w, p, p) - dot_r(w, p, mu);
354
- return (-b + SQRTF(MAX(b * b - 4 * a * c, 0.))) / (2 * a);
361
+ rad = b * b - 4 * a * c;
362
+ return (-b + SQRTF(MAX(rad, 0.))) / (2 * a);
355
363
  }
356
364
 
357
- /* status < 0 indicates failure */
365
+ /* status != 0 indicates failure */
358
366
  static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
359
367
  scs_int n = w->d->n, m = w->d->m, l = n + m + 1, status, i;
360
368
  scs_float *warm_start = SCS_NULL;
@@ -364,22 +372,24 @@ static scs_int project_lin_sys(ScsWork *w, scs_int iter) {
364
372
  w->u_t[i] *= (i < n ? 1 : -1) * w->diag_r[i];
365
373
  }
366
374
  #if INDIRECT > 0
375
+ scs_float nm_ax_s_btau, nm_px_aty_ctau, nm_ws;
367
376
  /* compute warm start using the cone projection output */
377
+ nm_ax_s_btau = CG_NORM(w->r_normalized->ax_s_btau, m);
378
+ nm_px_aty_ctau = CG_NORM(w->r_normalized->px_aty_ctau, n);
368
379
  warm_start = w->lin_sys_warm_start;
369
- memcpy(warm_start, w->u, (l - 1) * sizeof(scs_float));
370
380
  /* warm_start = u[:n] + tau * g[:n] */
371
- SCS(add_scaled_array)(warm_start, w->g, l - 1, w->u[l - 1]);
381
+ memcpy(warm_start, w->u, n * sizeof(scs_float));
382
+ SCS(add_scaled_array)(warm_start, w->g, n, w->u[l - 1]);
372
383
  /* use normalized residuals to compute tolerance */
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));
384
+ tol = MIN(nm_ax_s_btau, nm_px_aty_ctau);
375
385
  /* tol ~ O(1/k^(1+eps)) guarantees convergence */
376
386
  /* use warm-start to calculate tolerance rather than w->u_t, since warm_start
377
387
  * should be approximately equal to the true solution */
378
- tol = CG_TOL_FACTOR * MIN(tol, CG_NORM(warm_start, w->d->n) /
379
- POWF((scs_float)iter + 1, CG_RATE));
388
+ nm_ws = CG_NORM(warm_start, n) / POWF((scs_float)iter + 1, CG_RATE);
389
+ tol = CG_TOL_FACTOR * MIN(tol, nm_ws);
380
390
  tol = MAX(CG_BEST_TOL, tol);
381
391
  #endif
382
- status = SCS(solve_lin_sys)(w->p, w->u_t, warm_start, tol);
392
+ status = scs_solve_lin_sys(w->p, w->u_t, warm_start, tol);
383
393
  if (iter < FEASIBLE_ITERS) {
384
394
  w->u_t[l - 1] = 1.;
385
395
  } else {
@@ -514,6 +524,7 @@ static void set_unfinished(const ScsWork *w, ScsSolution *sol, ScsInfo *info) {
514
524
  /* sets solutions, re-scales by inner prods if infeasible or unbounded */
515
525
  static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
516
526
  scs_int iter) {
527
+ scs_float nm_s, nm_y, sty;
517
528
  setx(w, sol);
518
529
  sety(w, sol);
519
530
  sets(w, sol);
@@ -521,6 +532,11 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
521
532
  SCS(un_normalize_sol)(w->scal, sol);
522
533
  }
523
534
  populate_residual_struct(w, iter);
535
+
536
+ nm_s = SCS(norm_inf)(sol->s, w->d->m);
537
+ nm_y = SCS(norm_inf)(sol->y, w->d->m);
538
+ sty = SCS(dot)(sol->s, sol->y, w->d->m);
539
+
524
540
  info->setup_time = w->setup_time;
525
541
  info->iter = iter;
526
542
  info->res_infeas = w->r_orig->res_infeas;
@@ -530,9 +546,8 @@ static void finalize(ScsWork *w, ScsSolution *sol, ScsInfo *info,
530
546
  info->scale_updates = w->scale_updates;
531
547
  info->rejected_accel_steps = w->rejected_accel_steps;
532
548
  info->accepted_accel_steps = w->accepted_accel_steps;
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))) {
549
+ info->comp_slack = ABS(sty);
550
+ if (info->comp_slack > 1e-5 * MAX(nm_s, nm_y)) {
536
551
  scs_printf("WARNING - large complementary slackness residual: %f\n",
537
552
  info->comp_slack);
538
553
  }
@@ -563,7 +578,9 @@ static void print_summary(ScsWork *w, scs_int i, SCS(timer) * solve_timer) {
563
578
  /* report mid point of primal and dual objective values */
564
579
  scs_printf("%*.2e ", (int)HSPACE, 0.5 * (r->pobj + r->dobj));
565
580
  scs_printf("%*.2e ", (int)HSPACE, w->stgs->scale);
566
- scs_printf("%*.2e ", (int)HSPACE, SCS(tocq)(solve_timer) / 1e3);
581
+ /* Report TOTAL time, including setup */
582
+ scs_printf("%*.2e ", (int)HSPACE,
583
+ (SCS(tocq)(solve_timer) + w->setup_time) / 1e3);
567
584
  scs_printf("\n");
568
585
 
569
586
  #if VERBOSITY > 0
@@ -649,26 +666,29 @@ static void print_footer(ScsInfo *info) {
649
666
  }
650
667
 
651
668
  static scs_int has_converged(ScsWork *w, scs_int iter) {
669
+ scs_float abs_xt_p_x, abs_ctx, abs_bty;
670
+ scs_float nm_s, nm_px, nm_aty, nm_ax;
671
+ scs_float grl, prl, drl;
652
672
  scs_float eps_abs = w->stgs->eps_abs;
653
673
  scs_float eps_rel = w->stgs->eps_rel;
654
674
  scs_float eps_infeas = w->stgs->eps_infeas;
655
- scs_float grl, prl, drl;
656
675
 
657
676
  ScsResiduals *r = w->r_orig;
658
- scs_float *b = w->b_orig;
659
- scs_float *c = w->c_orig;
660
- scs_float *s = w->xys_orig->s;
661
677
 
662
678
  if (r->tau > 0.) {
679
+ abs_xt_p_x = ABS(r->xt_p_x);
680
+ abs_ctx = ABS(r->ctx);
681
+ abs_bty = ABS(r->bty);
682
+
683
+ nm_s = NORM(w->xys_orig->s, w->d->m);
684
+ nm_px = NORM(r->px, w->d->n);
685
+ nm_aty = NORM(r->aty, w->d->n);
686
+ nm_ax = NORM(r->ax, w->d->m);
663
687
  /* xt_p_x, ctx, bty already have tau divided out */
664
- grl = MAX(MAX(ABS(r->xt_p_x), ABS(r->ctx)), ABS(r->bty));
688
+ grl = MAX(MAX(abs_xt_p_x, abs_ctx), abs_bty);
665
689
  /* s, ax, px, aty do *not* have tau divided out, so need to divide */
666
- prl = MAX(MAX(NORM(b, w->d->m) * r->tau, NORM(s, w->d->m)),
667
- NORM(r->ax, w->d->m)) /
668
- r->tau;
669
- drl = MAX(MAX(NORM(c, w->d->n) * r->tau, NORM(r->px, w->d->n)),
670
- NORM(r->aty, w->d->n)) /
671
- r->tau;
690
+ prl = MAX(MAX(w->nm_b_orig * r->tau, nm_s), nm_ax) / r->tau;
691
+ drl = MAX(MAX(w->nm_c_orig * r->tau, nm_px), nm_aty) / r->tau;
672
692
  if (isless(r->res_pri, eps_abs + eps_rel * prl) &&
673
693
  isless(r->res_dual, eps_abs + eps_rel * drl) &&
674
694
  isless(r->gap, eps_abs + eps_rel * grl)) {
@@ -685,7 +705,7 @@ static scs_int has_converged(ScsWork *w, scs_int iter) {
685
705
  return 0;
686
706
  }
687
707
 
688
- #if NOVALIDATE == 0
708
+ #if NO_VALIDATE == 0
689
709
  static scs_int validate(const ScsData *d, const ScsCone *k,
690
710
  const ScsSettings *stgs) {
691
711
  if (d->m <= 0 || d->n <= 0) {
@@ -762,12 +782,15 @@ scs_int scs_update(ScsWork *w, scs_float *b, scs_float *c) {
762
782
  } else {
763
783
  memcpy(w->d->b, w->b_orig, w->d->m * sizeof(scs_float));
764
784
  }
785
+ w->nm_b_orig = NORM(w->b_orig, w->d->m);
786
+
765
787
  if (c) {
766
788
  memcpy(w->c_orig, c, w->d->n * sizeof(scs_float));
767
789
  memcpy(w->d->c, c, w->d->n * sizeof(scs_float));
768
790
  } else {
769
791
  memcpy(w->d->c, w->c_orig, w->d->n * sizeof(scs_float));
770
792
  }
793
+ w->nm_c_orig = NORM(w->c_orig, w->d->n);
771
794
 
772
795
  /* normalize */
773
796
  if (w->scal) {
@@ -826,7 +849,7 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
826
849
  w->rsk = (scs_float *)scs_calloc(l, sizeof(scs_float));
827
850
  w->h = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
828
851
  w->g = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
829
- w->lin_sys_warm_start = (scs_float *)scs_calloc((l - 1), sizeof(scs_float));
852
+ w->lin_sys_warm_start = (scs_float *)scs_calloc(w->d->n, sizeof(scs_float));
830
853
  w->diag_r = (scs_float *)scs_calloc(l, sizeof(scs_float));
831
854
  /* x,y,s struct */
832
855
  w->xys_orig = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
@@ -864,7 +887,7 @@ static ScsWork *init_work(const ScsData *d, const ScsCone *k,
864
887
  /* set w->*_orig and performs normalization if appropriate */
865
888
  scs_update(w, w->d->b, w->d->c);
866
889
 
867
- if (!(w->p = SCS(init_lin_sys_work)(w->d->A, w->d->P, w->diag_r))) {
890
+ if (!(w->p = scs_init_lin_sys_work(w->d->A, w->d->P, w->diag_r))) {
868
891
  scs_printf("ERROR: init_lin_sys_work failure\n");
869
892
  return SCS_NULL;
870
893
  }
@@ -891,7 +914,7 @@ static void update_work_cache(ScsWork *w) {
891
914
  /* g = (I + M)^{-1} h */
892
915
  memcpy(w->g, w->h, (w->d->n + w->d->m) * sizeof(scs_float));
893
916
  SCS(scale_array)(&(w->g[w->d->n]), -1., w->d->m);
894
- SCS(solve_lin_sys)(w->p, w->g, SCS_NULL, CG_BEST_TOL);
917
+ scs_solve_lin_sys(w->p, w->g, SCS_NULL, CG_BEST_TOL);
895
918
  return;
896
919
  }
897
920
 
@@ -934,24 +957,27 @@ scs_int should_update_r(scs_float factor, scs_int iter) {
934
957
 
935
958
  static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
936
959
  scs_int i;
937
- scs_float factor, new_scale;
960
+ scs_float factor, new_scale, relative_res_pri, relative_res_dual;
961
+ scs_float denom_pri, denom_dual;
938
962
 
939
963
  ScsResiduals *r = w->r_orig;
940
- ScsSolution *xys = w->xys_orig;
941
- scs_float *b = w->b_orig;
942
- scs_float *c = w->c_orig;
964
+
965
+ scs_float nm_ax = SCALE_NORM(r->ax, w->d->m);
966
+ scs_float nm_s = SCALE_NORM(w->xys_orig->s, w->d->m);
967
+ scs_float nm_px_aty_ctau = SCALE_NORM(r->px_aty_ctau, w->d->n);
968
+ scs_float nm_px = SCALE_NORM(r->px, w->d->n);
969
+ scs_float nm_aty = SCALE_NORM(r->aty, w->d->n);
970
+ scs_float nm_ax_s_btau = SCALE_NORM(r->ax_s_btau, w->d->m);
943
971
 
944
972
  scs_int iters_since_last_update = iter - w->last_scale_update_iter;
945
973
  /* ||Ax + s - b * 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));
974
+ denom_pri = MAX(nm_ax, nm_s);
975
+ denom_pri = MAX(denom_pri, w->nm_b_orig * r->tau);
976
+ relative_res_pri = SAFEDIV_POS(nm_ax_s_btau, denom_pri);
950
977
  /* ||Px + A'y + c * 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));
978
+ denom_dual = MAX(nm_px, nm_aty);
979
+ denom_dual = MAX(denom_dual, w->nm_c_orig * r->tau);
980
+ relative_res_dual = SAFEDIV_POS(nm_px_aty_ctau, denom_dual);
955
981
 
956
982
  /* higher scale makes res_pri go down faster, so increase if res_pri larger */
957
983
  w->sum_log_scale_factor += log(relative_res_pri) - log(relative_res_dual);
@@ -981,7 +1007,7 @@ static void update_scale(ScsWork *w, const ScsCone *k, scs_int iter) {
981
1007
  set_diag_r(w);
982
1008
 
983
1009
  /* update linear systems */
984
- SCS(update_lin_sys_diag_r)(w->p, w->diag_r);
1010
+ scs_update_lin_sys_diag_r(w->p, w->diag_r);
985
1011
 
986
1012
  /* update pre-solved quantities */
987
1013
  update_work_cache(w);
@@ -1025,7 +1051,7 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info,
1025
1051
  /* initialize ctrl-c support */
1026
1052
  scs_start_interrupt_listener();
1027
1053
  SCS(tic)(&solve_timer);
1028
- strcpy(info->lin_sys_solver, SCS(get_lin_sys_method)());
1054
+ strcpy(info->lin_sys_solver, scs_get_lin_sys_method());
1029
1055
  info->status_val = SCS_UNFINISHED; /* not yet converged */
1030
1056
  update_work(w, sol);
1031
1057
 
@@ -1057,7 +1083,7 @@ scs_int scs_solve(ScsWork *w, ScsSolution *sol, ScsInfo *info,
1057
1083
 
1058
1084
  /******************* linear system solve ********************/
1059
1085
  SCS(tic)(&lin_sys_timer);
1060
- if (project_lin_sys(w, i) < 0) {
1086
+ if (project_lin_sys(w, i) != 0) {
1061
1087
  return failure(w, w->d->m, w->d->n, sol, info, SCS_FAILED,
1062
1088
  "error in project_lin_sys", "failure");
1063
1089
  }
@@ -1162,7 +1188,7 @@ void scs_finish(ScsWork *w) {
1162
1188
  if (w) {
1163
1189
  SCS(finish_cone)(w->cone_work);
1164
1190
  if (w->p) {
1165
- SCS(free_lin_sys_work)(w->p);
1191
+ scs_free_lin_sys_work(w->p);
1166
1192
  }
1167
1193
  if (w->accel) {
1168
1194
  aa_finish(w->accel);
@@ -1179,7 +1205,7 @@ ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) {
1179
1205
  scs_printf("ERROR: Missing ScsData or ScsCone input\n");
1180
1206
  return SCS_NULL;
1181
1207
  }
1182
- #if NOVALIDATE == 0
1208
+ #if NO_VALIDATE == 0
1183
1209
  if (validate(d, k, stgs) < 0) {
1184
1210
  scs_printf("ERROR: Validation returned failure\n");
1185
1211
  return SCS_NULL;
@@ -1191,8 +1217,13 @@ ScsWork *scs_init(const ScsData *d, const ScsCone *k, const ScsSettings *stgs) {
1191
1217
  #endif
1192
1218
  SCS(tic)(&init_timer);
1193
1219
  if (stgs->write_data_filename) {
1220
+ scs_printf("Writing raw problem data to %s\n", stgs->write_data_filename);
1194
1221
  SCS(write_data)(d, k, stgs);
1195
1222
  }
1223
+ if (stgs->log_csv_filename) {
1224
+ scs_printf("Logging run data to %s\n", stgs->log_csv_filename);
1225
+ /* logging done every iteration */
1226
+ }
1196
1227
  w = init_work(d, k, stgs);
1197
1228
  if (w) {
1198
1229
  w->setup_time = SCS(tocq)(&init_timer);
@@ -5,7 +5,7 @@
5
5
  #include "scs_matrix.h"
6
6
 
7
7
  /* return milli-seconds */
8
- #if (defined NOTIMER)
8
+ #if (defined NO_TIMER)
9
9
 
10
10
  void SCS(tic)(SCS(timer) * t) {
11
11
  }
@@ -84,13 +84,22 @@ void SCS(deep_copy_data)(ScsData *dest, const ScsData *src) {
84
84
 
85
85
  void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
86
86
  memcpy(dest, src, sizeof(ScsSettings));
87
+ /* MATLAB does something weird with strdup, so use strcpy instead */
88
+ char *tmp;
87
89
  if (src->write_data_filename) {
88
- dest->write_data_filename = strdup(src->write_data_filename);
90
+ /* sizeof(char) = 1 */
91
+ tmp = (char *)scs_malloc(strlen(src->write_data_filename) + 1);
92
+ strcpy(tmp, src->write_data_filename);
93
+ dest->write_data_filename = tmp;
89
94
  } else {
90
95
  dest->write_data_filename = SCS_NULL;
91
96
  }
97
+ /* MATLAB does something weird with strdup, so use strcpy instead */
92
98
  if (src->log_csv_filename) {
93
- dest->log_csv_filename = strdup(src->log_csv_filename);
99
+ /* sizeof(char) = 1 */
100
+ tmp = (char *)scs_malloc(strlen(src->log_csv_filename) + 1);
101
+ strcpy(tmp, src->log_csv_filename);
102
+ dest->log_csv_filename = tmp;
94
103
  } else {
95
104
  dest->log_csv_filename = SCS_NULL;
96
105
  }
@@ -8,11 +8,13 @@
8
8
  return message; \
9
9
  } \
10
10
  } while (0)
11
+
11
12
  #define mu_assert(message, test) \
12
13
  do { \
13
14
  if (!(test)) \
14
15
  return message; \
15
16
  } while (0)
17
+
16
18
  #define mu_run_test(test) _mu_run_test(#test, test)
17
19
 
18
20
  #define _mu_run_test(name, test) \
@@ -21,7 +23,6 @@
21
23
  scs_printf("Running test: %s\n", name); \
22
24
  const char *message = test(); \
23
25
  tests_run++; \
24
- scs_printf("*********************************************************\n"); \
25
26
  if (message) \
26
27
  return message; \
27
28
  } while (0)
@@ -190,6 +190,7 @@ const char *verify_solution_correct(ScsData *d, ScsCone *k, ScsSettings *stgs,
190
190
 
191
191
  /************** OPTIMALITY ****************/
192
192
 
193
+ /* TODO: the MAX expansion computes these norms many times */
193
194
  grl = MAX(MAX(ABS(xt_p_x), ABS(ctx)), ABS(bty));
194
195
  prl = MAX(MAX(NORM(b, m), NORM(s, m)), NORM(ax, m));
195
196
  drl = MAX(MAX(NORM(c, n), NORM(px, n)), NORM(aty, n));
@@ -215,7 +216,7 @@ const char *verify_solution_correct(ScsData *d, ScsCone *k, ScsSettings *stgs,
215
216
  1e-9 * (1 + ABS(dobj)));
216
217
  /* slightly looser tol */
217
218
  mu_assert_less("Complementary slackness ERROR", ABS(sty),
218
- 1e-8 * MAX(NORM(s, m), NORM(y, m)));
219
+ 5e-8 * MAX(NORM(s, m), NORM(y, m)));
219
220
  mu_assert_less("s cone dist ERROR", ABS(sdist), 1e-5);
220
221
  mu_assert_less("y cone dist ERROR", ABS(ydist), 1e-5);
221
222
 
@@ -68,7 +68,7 @@ static const char *hs21_tiny_qp(void) {
68
68
  scs_set_default_settings(stgs);
69
69
  stgs->eps_abs = 1e-6;
70
70
  stgs->eps_rel = 1e-6;
71
- stgs->eps_infeas = 1e-9;
71
+ stgs->eps_infeas = 0.; /* disable due to gpu test finding cert */
72
72
 
73
73
  exitflag = scs(d, k, stgs, sol, &info);
74
74
 
@@ -16,7 +16,7 @@ static const char *hs21_tiny_qp_rw(void) {
16
16
  ScsInfo info = {0};
17
17
  scs_int exitflag;
18
18
  scs_float perr, derr;
19
- scs_int success;
19
+ scs_int success, read_status;
20
20
  const char *fail;
21
21
 
22
22
  /* data */
@@ -70,7 +70,7 @@ static const char *hs21_tiny_qp_rw(void) {
70
70
  scs_set_default_settings(stgs);
71
71
  stgs->eps_abs = 1e-6;
72
72
  stgs->eps_rel = 1e-6;
73
- stgs->eps_infeas = 1e-9;
73
+ stgs->eps_infeas = 0.; /* disable due to gpu test finding cert */
74
74
 
75
75
  stgs->write_data_filename = "hs21_tiny_qp";
76
76
  stgs->max_iters = 1;
@@ -84,7 +84,12 @@ static const char *hs21_tiny_qp_rw(void) {
84
84
  scs_free(stgs);
85
85
  scs_free(d);
86
86
 
87
- SCS(read_data)("hs21_tiny_qp", &d, &k, &stgs);
87
+ read_status = SCS(read_data)("hs21_tiny_qp", &d, &k, &stgs);
88
+
89
+ if (read_status < 0) {
90
+ return "Data read failure, exit.\n";
91
+ }
92
+
88
93
  stgs->max_iters = 1000;
89
94
  /* solve with read data */
90
95
  exitflag = scs(d, k, stgs, sol, &info);
Binary file
@@ -0,0 +1,8 @@
1
+ #include "glbopts.h"
2
+ #include "problems/test_prob_from_data_file.h"
3
+ #include "scs.h"
4
+
5
+ static const char *max_ent(void) {
6
+ scs_float OPT = -6.067087663361563; /* from ecos */
7
+ return _test_prob_from_data("test/problems/max_ent", OPT);
8
+ }
@@ -1,49 +1,8 @@
1
1
  #include "glbopts.h"
2
- #include "minunit.h"
3
- #include "problem_utils.h"
4
- #include "rw.h"
2
+ #include "problems/test_prob_from_data_file.h"
5
3
  #include "scs.h"
6
- #include "util.h"
7
4
 
8
5
  static const char *random_prob(void) {
9
- scs_int read_status;
10
- ScsData *d;
11
- ScsCone *k;
12
- ScsSettings *stgs;
13
- ScsSolution *sol;
14
- ScsInfo info = {0};
15
- scs_int exitflag;
16
- scs_float perr, derr;
17
- scs_int success;
18
- const char *fail;
19
-
20
6
  scs_float OPT = 5.751458006385587;
21
-
22
- read_status = SCS(read_data)("test/problems/random_prob", &d, &k, &stgs);
23
-
24
- if (read_status < 0) {
25
- return "Data read failure, exit.\n";
26
- }
27
-
28
- stgs->eps_abs = 1e-6;
29
- stgs->eps_rel = 1e-6;
30
-
31
- sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
32
- exitflag = scs(d, k, stgs, sol, &info);
33
-
34
- perr = SCS(dot)(d->c, sol->x, d->n) - OPT;
35
- derr = -SCS(dot)(d->b, sol->y, d->m) - OPT;
36
- scs_printf("primal obj error %4e\n", perr);
37
- scs_printf("dual obj error %4e\n", derr);
38
-
39
- success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
40
-
41
- mu_assert("random_prob: SCS failed to produce SCS_SOLVED", success);
42
- fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
43
- SCS(free_data)(d);
44
- SCS(free_cone)(k);
45
- SCS(free_sol)(sol);
46
- scs_free(stgs);
47
-
48
- return fail;
7
+ return _test_prob_from_data("test/problems/random_prob", OPT);
49
8
  }
@@ -15,7 +15,7 @@ static const char *rob_gauss_cov_est(void) {
15
15
  ScsInfo info = {0};
16
16
  scs_int exitflag;
17
17
  scs_float perr, derr;
18
- scs_int success;
18
+ scs_int success, read_status;
19
19
  const char *fail;
20
20
 
21
21
  /* data */
@@ -200,7 +200,12 @@ static const char *rob_gauss_cov_est(void) {
200
200
  scs_free(stgs);
201
201
  scs_free(d);
202
202
 
203
- SCS(read_data)("rob_gauss_cov_est", &d, &k, &stgs);
203
+ read_status = SCS(read_data)("rob_gauss_cov_est", &d, &k, &stgs);
204
+
205
+ if (read_status < 0) {
206
+ return "Data read failure, exit.\n";
207
+ }
208
+
204
209
  stgs->max_iters = 1000;
205
210
  /* solve with read data */
206
211
  exitflag = scs(d, k, stgs, sol, &info);
@@ -0,0 +1,84 @@
1
+ #include "glbopts.h"
2
+ #include "linalg.h"
3
+ #include "minunit.h"
4
+ #include "scs.h"
5
+
6
+ /* Forward declare exponential cone projection routine.
7
+ * Implemented in exp_cone.c.
8
+ */
9
+ scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal);
10
+
11
+ static scs_int _run_exp_cone_test(scs_float *v0, scs_float *vp_true,
12
+ scs_float *vd_true) {
13
+ scs_int success = 1;
14
+ scs_float vp[3], vd[3];
15
+ const scs_float TOL = 1e-6;
16
+
17
+ memcpy(vp, v0, 3 * sizeof(scs_float));
18
+ memcpy(vd, v0, 3 * sizeof(scs_float));
19
+
20
+ /* inefficient, but just for testing */
21
+ SCS(proj_pd_exp_cone)(vp, 1);
22
+ SCS(proj_pd_exp_cone)(vd, 0);
23
+
24
+ scs_printf("*******************************\n");
25
+ scs_printf("v0: (%f, %f, %f)\n", v0[0], v0[1], v0[2]);
26
+ scs_printf("vp: (%f, %f, %f)\n", vp[0], vp[1], vp[2]);
27
+ scs_printf("vp_true: (%f, %f, %f)\n", vp_true[0], vp_true[1], vp_true[2]);
28
+ scs_printf("vd: (%f, %f, %f)\n", vd[0], vd[1], vd[2]);
29
+ scs_printf("vd_true: (%f, %f, %f)\n", vd_true[0], vd_true[1], vd_true[2]);
30
+
31
+ success &= (SCS(norm_diff)(vp, vp_true, 3) <= TOL);
32
+ success &= (SCS(norm_diff)(vd, vd_true, 3) <= TOL);
33
+ /* Moreau decomposition holds only for polar */
34
+ /*
35
+ success &= (SCS(dot)(vp, vd, 3) <= TOL);
36
+ success &= (ABS(v0[0] - vp[0] + vd[0]) <= TOL);
37
+ success &= (ABS(v0[1] - vp[1] + vd[1]) <= TOL);
38
+ success &= (ABS(v0[2] - vp[2] + vd[2]) <= TOL);
39
+ */
40
+
41
+ if (!success) {
42
+ scs_printf("Failed.\n");
43
+ }
44
+
45
+ return success;
46
+ }
47
+
48
+ static const char *test_exp_cone(void) {
49
+ scs_int success = 1;
50
+ scs_int i;
51
+ /* test points */
52
+ scs_float v0[6][3] = {
53
+ {1, 2, 3},
54
+ {0.14814832, 1.04294573, 0.67905585},
55
+ {-0.78301134, 1.82790084, -1.05417044},
56
+ {1.3282585, -0.43277314, 1.7468072},
57
+ {0.67905585, 0.14814832, 1.04294573},
58
+ {0.50210027, 0.12314491, -1.77568921},
59
+ };
60
+ /* primal projections */
61
+ scs_float vp[6][3] = {
62
+ {0.8899428, 1.94041881, 3.06957226},
63
+ {-0.02001571, 0.8709169, 0.85112944},
64
+ {-1.17415616, 0.9567094, 0.280399},
65
+ {0.53160512, 0.2804836, 1.86652094},
66
+ {0.38322814, 0.27086569, 1.11482228},
67
+ {0., 0., 0.},
68
+ };
69
+ /* dual projections */
70
+ scs_float vd[6][3] = {
71
+ {-0., 2., 3.},
72
+ {-0., 1.04294573, 0.67905585},
73
+ {-0.68541419, 1.85424082, 0.01685653},
74
+ {-0.02277033, -0.12164823, 1.75085347},
75
+ {-0., 0.14814832, 1.04294573},
76
+ {-0., 0.12314491, -0.},
77
+ };
78
+
79
+ for (i = 0; i < 6; ++i) {
80
+ success &= _run_exp_cone_test(v0[i], vp[i], vd[i]);
81
+ }
82
+ mu_assert("test_exp_cone: Failure", success);
83
+ return 0;
84
+ }
@@ -0,0 +1,57 @@
1
+ #ifndef _SCS_FILE_TEST_CHASSIS
2
+ #define _SCS_FILE_TEST_CHASSIS
3
+
4
+ #include "glbopts.h"
5
+ #include "minunit.h"
6
+ #include "problem_utils.h"
7
+ #include "rw.h"
8
+ #include "scs.h"
9
+ #include "util.h"
10
+
11
+ static const char *_test_prob_from_data(const char *file, scs_float OPT) {
12
+ scs_int read_status;
13
+ ScsData *d;
14
+ ScsCone *k;
15
+ ScsSettings *stgs;
16
+ ScsSolution *sol;
17
+ ScsInfo info = {0};
18
+ scs_int exitflag;
19
+ scs_float perr, derr;
20
+ scs_int success;
21
+ const char *fail;
22
+
23
+ read_status = SCS(read_data)(file, &d, &k, &stgs);
24
+
25
+ if (read_status < 0) {
26
+ return "Data read failure, exit.\n";
27
+ }
28
+
29
+ stgs->eps_abs = 1e-6;
30
+ stgs->eps_rel = 1e-6;
31
+
32
+ sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
33
+ exitflag = scs(d, k, stgs, sol, &info);
34
+
35
+ perr = SCS(dot)(d->c, sol->x, d->n) - OPT;
36
+ derr = -SCS(dot)(d->b, sol->y, d->m) - OPT;
37
+ scs_printf("primal obj error %4e\n", perr);
38
+ scs_printf("dual obj error %4e\n", derr);
39
+
40
+ success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
41
+ if (!success) {
42
+ scs_printf("%s: FAILED\n", file);
43
+ }
44
+ mu_assert(file, success);
45
+ fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
46
+ SCS(free_data)(d);
47
+ SCS(free_cone)(k);
48
+ SCS(free_sol)(sol);
49
+ scs_free(stgs);
50
+
51
+ if (fail) {
52
+ scs_printf("%s: FAILED\n", file);
53
+ }
54
+ return fail;
55
+ }
56
+
57
+ #endif