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