scs 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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