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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +2 -2
- data/vendor/scs/CMakeLists.txt +284 -168
- data/vendor/scs/Makefile +43 -18
- data/vendor/scs/README.md +1 -1
- data/vendor/scs/include/glbopts.h +32 -13
- data/vendor/scs/include/linsys.h +8 -8
- data/vendor/scs/include/scs.h +6 -2
- data/vendor/scs/include/scs_types.h +3 -1
- data/vendor/scs/include/scs_work.h +9 -8
- data/vendor/scs/include/util.h +1 -1
- data/vendor/scs/linsys/cpu/direct/private.c +32 -153
- data/vendor/scs/linsys/cpu/direct/private.h +6 -6
- data/vendor/scs/linsys/cpu/indirect/private.c +9 -22
- data/vendor/scs/linsys/cpu/indirect/private.h +4 -2
- data/vendor/scs/linsys/csparse.c +140 -12
- data/vendor/scs/linsys/csparse.h +10 -17
- data/vendor/scs/linsys/gpu/gpu.c +4 -4
- data/vendor/scs/linsys/gpu/gpu.h +1 -1
- data/vendor/scs/linsys/gpu/indirect/private.c +15 -26
- data/vendor/scs/linsys/mkl/direct/private.c +182 -0
- data/vendor/scs/linsys/mkl/direct/private.h +38 -0
- data/vendor/scs/linsys/scs_matrix.c +11 -5
- data/vendor/scs/scs.mk +39 -26
- data/vendor/scs/src/cones.c +15 -159
- data/vendor/scs/src/exp_cone.c +399 -0
- data/vendor/scs/src/normalize.c +4 -2
- data/vendor/scs/src/rw.c +93 -38
- data/vendor/scs/src/scs.c +83 -52
- data/vendor/scs/src/util.c +12 -3
- data/vendor/scs/test/minunit.h +2 -1
- data/vendor/scs/test/problem_utils.h +2 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +8 -3
- data/vendor/scs/test/problems/max_ent +0 -0
- data/vendor/scs/test/problems/max_ent.h +8 -0
- data/vendor/scs/test/problems/random_prob.h +2 -43
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +7 -2
- data/vendor/scs/test/problems/test_exp_cone.h +84 -0
- data/vendor/scs/test/problems/test_prob_from_data_file.h +57 -0
- data/vendor/scs/test/run_from_file.c +7 -1
- data/vendor/scs/test/run_tests.c +22 -9
- 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 =
|
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
|
-
|
199
|
-
|
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
|
-
|
205
|
-
|
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
|
-
|
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
|
-
|
361
|
+
rad = b * b - 4 * a * c;
|
362
|
+
return (-b + SQRTF(MAX(rad, 0.))) / (2 * a);
|
355
363
|
}
|
356
364
|
|
357
|
-
/* status
|
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
|
-
|
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(
|
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
|
-
|
379
|
-
|
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 =
|
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(
|
534
|
-
if (info->comp_slack > 1e-5 * MAX(
|
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
|
-
|
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(
|
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(
|
667
|
-
|
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
|
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(
|
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 =
|
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
|
-
|
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
|
-
|
941
|
-
scs_float
|
942
|
-
scs_float
|
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
|
-
|
947
|
-
|
948
|
-
|
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
|
-
|
952
|
-
|
953
|
-
|
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
|
-
|
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,
|
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)
|
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
|
-
|
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
|
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);
|
data/vendor/scs/src/util.c
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
#include "scs_matrix.h"
|
6
6
|
|
7
7
|
/* return milli-seconds */
|
8
|
-
#if (defined
|
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
|
-
|
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
|
-
|
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
|
}
|
data/vendor/scs/test/minunit.h
CHANGED
@@ -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
|
-
|
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 =
|
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 =
|
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
|
@@ -1,49 +1,8 @@
|
|
1
1
|
#include "glbopts.h"
|
2
|
-
#include "
|
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
|