scs 0.3.1 → 0.3.2
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/README.md +8 -8
- data/lib/scs/ffi.rb +1 -7
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +1 -1
- data/vendor/scs/CMakeLists.txt +55 -7
- data/vendor/scs/Makefile +9 -9
- data/vendor/scs/README.md +2 -1
- data/vendor/scs/include/aa.h +1 -1
- data/vendor/scs/include/cones.h +14 -11
- data/vendor/scs/include/glbopts.h +26 -64
- data/vendor/scs/include/linalg.h +2 -1
- data/vendor/scs/include/linsys.h +13 -13
- data/vendor/scs/include/normalize.h +6 -5
- data/vendor/scs/include/scs.h +43 -87
- data/vendor/scs/include/scs_types.h +34 -0
- data/vendor/scs/include/scs_work.h +83 -0
- data/vendor/scs/linsys/cpu/direct/private.c +86 -73
- data/vendor/scs/linsys/cpu/direct/private.h +2 -2
- data/vendor/scs/linsys/cpu/indirect/private.c +42 -33
- data/vendor/scs/linsys/cpu/indirect/private.h +1 -2
- data/vendor/scs/linsys/csparse.c +3 -3
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
- data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
- data/vendor/scs/linsys/gpu/gpu.h +8 -11
- data/vendor/scs/linsys/gpu/indirect/private.c +72 -49
- data/vendor/scs/linsys/gpu/indirect/private.h +14 -13
- data/vendor/scs/linsys/scs_matrix.c +26 -46
- data/vendor/scs/linsys/scs_matrix.h +4 -4
- data/vendor/scs/scs.mk +1 -1
- data/vendor/scs/src/aa.c +13 -4
- data/vendor/scs/src/cones.c +143 -92
- data/vendor/scs/src/linalg.c +25 -0
- data/vendor/scs/src/normalize.c +26 -26
- data/vendor/scs/src/rw.c +48 -12
- data/vendor/scs/src/scs.c +104 -110
- data/vendor/scs/src/scs_version.c +8 -6
- data/vendor/scs/src/util.c +1 -1
- data/vendor/scs/test/minunit.h +6 -1
- data/vendor/scs/test/problem_utils.h +28 -35
- data/vendor/scs/test/problems/degenerate.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +1 -1
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +1 -1
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -3
- data/vendor/scs/test/problems/random_prob.h +1 -1
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +1 -1
- data/vendor/scs/test/problems/small_lp.h +3 -1
- data/vendor/scs/test/problems/small_qp.h +352 -0
- data/vendor/scs/test/problems/{test_fails.h → test_validation.h} +3 -3
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +1 -1
- data/vendor/scs/test/random_socp_prob.c +1 -1
- data/vendor/scs/test/run_from_file.c +1 -1
- data/vendor/scs/test/run_tests.c +23 -14
- metadata +8 -5
data/vendor/scs/src/cones.c
CHANGED
@@ -10,18 +10,15 @@
|
|
10
10
|
#define BOX_CONE_MAX_ITERS (25)
|
11
11
|
#define POW_CONE_MAX_ITERS (20)
|
12
12
|
|
13
|
-
/* In the box cone projection we penalize the `t` term additionally by this
|
14
|
-
* factor. This encourages the `t` term to stay close to the incoming `t` term,
|
15
|
-
* which should provide better convergence since typically the `t` term does
|
16
|
-
* not appear in the linear system other than `t = 1`. Setting to 1 is
|
17
|
-
* the vanilla projection.
|
18
|
-
*/
|
19
|
-
#define BOX_T_SCALE (1.)
|
20
|
-
|
21
13
|
/* Box cone limits (+ or -) taken to be INF */
|
22
14
|
#define MAX_BOX_VAL (1e15)
|
23
15
|
|
24
16
|
#ifdef USE_LAPACK
|
17
|
+
|
18
|
+
#ifdef __cplusplus
|
19
|
+
extern "C" {
|
20
|
+
#endif
|
21
|
+
|
25
22
|
void BLAS(syev)(const char *jobz, const char *uplo, blas_int *n, scs_float *a,
|
26
23
|
blas_int *lda, scs_float *w, scs_float *work, blas_int *lwork,
|
27
24
|
blas_int *info);
|
@@ -31,34 +28,43 @@ blas_int BLAS(syrk)(const char *uplo, const char *trans, const blas_int *n,
|
|
31
28
|
const scs_float *beta, scs_float *c, const blas_int *ldc);
|
32
29
|
void BLAS(scal)(const blas_int *n, const scs_float *sa, scs_float *sx,
|
33
30
|
const blas_int *incx);
|
31
|
+
|
32
|
+
#ifdef __cplusplus
|
33
|
+
}
|
34
|
+
#endif
|
35
|
+
|
34
36
|
#endif
|
35
37
|
|
36
38
|
/* set the vector of rho y terms, based on scale and cones */
|
37
|
-
void SCS(
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
for (i = 0; i < k->z; ++i) {
|
39
|
+
void SCS(set_r_y)(const ScsConeWork *c, scs_float scale, scs_float *r_y) {
|
40
|
+
scs_int i;
|
41
|
+
/* z cone */
|
42
|
+
for (i = 0; i < c->k->z; ++i) {
|
42
43
|
/* set rho_y small for z, similar to rho_x term, since z corresponds to
|
43
44
|
* dual free cone, this effectively decreases penalty on those entries
|
44
45
|
* and lets them be determined almost entirely by the linear system solve
|
45
46
|
*/
|
46
|
-
|
47
|
+
r_y[i] = 1.0 / (1000. * scale);
|
47
48
|
}
|
48
|
-
count += k->z;
|
49
49
|
/* others */
|
50
|
-
for (i =
|
51
|
-
|
50
|
+
for (i = c->k->z; i < c->m; ++i) {
|
51
|
+
r_y[i] = 1.0 / scale;
|
52
52
|
}
|
53
|
+
}
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
/* the function f aggregates the entries within each cone */
|
56
|
+
void SCS(enforce_cone_boundaries)(const ScsConeWork *c, scs_float *vec,
|
57
|
+
scs_float (*f)(const scs_float *, scs_int)) {
|
58
|
+
scs_int i, j, delta;
|
59
|
+
scs_int count = c->cone_boundaries[0];
|
60
|
+
scs_float wrk;
|
61
|
+
for (i = 1; i < c->cone_boundaries_len; ++i) {
|
62
|
+
delta = c->cone_boundaries[i];
|
63
|
+
wrk = f(&(vec[count]), delta);
|
64
|
+
for (j = count; j < count + delta; ++j) {
|
65
|
+
vec[j] = wrk;
|
66
|
+
}
|
67
|
+
count += delta;
|
62
68
|
}
|
63
69
|
}
|
64
70
|
|
@@ -71,7 +77,7 @@ static inline scs_int get_sd_cone_size(scs_int s) {
|
|
71
77
|
* cone boundaries, boundaries[0] is starting index for cones of size strictly
|
72
78
|
* larger than 1, boundaries malloc-ed here so should be freed.
|
73
79
|
*/
|
74
|
-
|
80
|
+
void set_cone_boundaries(const ScsCone *k, ScsConeWork *c) {
|
75
81
|
scs_int i, s_cone_sz, count = 0;
|
76
82
|
scs_int cone_boundaries_len =
|
77
83
|
1 + k->qsize + k->ssize + k->ed + k->ep + k->psize;
|
@@ -99,8 +105,8 @@ scs_int SCS(set_cone_boundaries)(const ScsCone *k, scs_int **cone_boundaries) {
|
|
99
105
|
}
|
100
106
|
count += k->psize;
|
101
107
|
/* other cones */
|
102
|
-
|
103
|
-
|
108
|
+
c->cone_boundaries = b;
|
109
|
+
c->cone_boundaries_len = cone_boundaries_len;
|
104
110
|
}
|
105
111
|
|
106
112
|
static scs_int get_full_cone_dims(const ScsCone *k) {
|
@@ -121,7 +127,7 @@ static scs_int get_full_cone_dims(const ScsCone *k) {
|
|
121
127
|
if (k->ep) {
|
122
128
|
c += 3 * k->ep;
|
123
129
|
}
|
124
|
-
if (k->
|
130
|
+
if (k->psize) {
|
125
131
|
c += 3 * k->psize;
|
126
132
|
}
|
127
133
|
return c;
|
@@ -216,6 +222,9 @@ void SCS(finish_cone)(ScsConeWork *c) {
|
|
216
222
|
scs_free(c->work);
|
217
223
|
}
|
218
224
|
#endif
|
225
|
+
if (c->cone_boundaries) {
|
226
|
+
scs_free(c->cone_boundaries);
|
227
|
+
}
|
219
228
|
if (c->s) {
|
220
229
|
scs_free(c->s);
|
221
230
|
}
|
@@ -484,7 +493,7 @@ static scs_int proj_semi_definite_cone(scs_float *X, const scs_int n,
|
|
484
493
|
/* Solve eigenproblem, reuse workspaces */
|
485
494
|
BLAS(syev)("Vectors", "Lower", &nb, Xs, &nb, e, work, &lwork, &info);
|
486
495
|
if (info != 0) {
|
487
|
-
scs_printf("WARN: LAPACK syev error, info = %i\n", info);
|
496
|
+
scs_printf("WARN: LAPACK syev error, info = %i\n", (int)info);
|
488
497
|
if (info < 0) {
|
489
498
|
return info;
|
490
499
|
}
|
@@ -587,36 +596,40 @@ static void normalize_box_cone(ScsConeWork *c, scs_float *D, scs_int bsize) {
|
|
587
596
|
}
|
588
597
|
}
|
589
598
|
|
590
|
-
/*
|
591
|
-
tx = [t; s], total length = bsize
|
592
|
-
uses Moreau since \Pi_K*(tx) = \Pi_K(-tx) + tx
|
599
|
+
/* Project onto { (t, s) | t * l <= s <= t * u, t >= 0 }, Newton's method on t
|
600
|
+
tx = [t; s], total length = bsize, under Euclidean metric 1/r_box.
|
593
601
|
*/
|
594
602
|
static scs_float proj_box_cone(scs_float *tx, const scs_float *bl,
|
595
603
|
const scs_float *bu, scs_int bsize,
|
596
|
-
scs_float t_warm_start) {
|
604
|
+
scs_float t_warm_start, scs_float *r_box) {
|
597
605
|
scs_float *x, gt, ht, t_prev, t = t_warm_start;
|
606
|
+
scs_float rho_t = 1, *rho = SCS_NULL, r;
|
598
607
|
scs_int iter, j;
|
599
608
|
|
600
609
|
if (bsize == 1) { /* special case */
|
601
610
|
tx[0] = MAX(tx[0], 0.0);
|
602
611
|
return tx[0];
|
603
612
|
}
|
604
|
-
|
605
613
|
x = &(tx[1]);
|
606
614
|
|
615
|
+
if (r_box) {
|
616
|
+
rho_t = 1.0 / r_box[0];
|
617
|
+
rho = &(r_box[1]);
|
618
|
+
}
|
619
|
+
|
607
620
|
/* should only require about 5 or so iterations, 1 or 2 if warm-started */
|
608
621
|
for (iter = 0; iter < BOX_CONE_MAX_ITERS; iter++) {
|
609
622
|
t_prev = t;
|
610
|
-
|
611
|
-
|
612
|
-
ht = BOX_T_SCALE; /* hessian */
|
623
|
+
gt = rho_t * (t - tx[0]); /* gradient */
|
624
|
+
ht = rho_t; /* hessian */
|
613
625
|
for (j = 0; j < bsize - 1; j++) {
|
626
|
+
r = rho ? 1.0 / rho[j] : 1.;
|
614
627
|
if (x[j] > t * bu[j]) {
|
615
|
-
gt += (t * bu[j] - x[j]) * bu[j]; /* gradient */
|
616
|
-
ht += bu[j] * bu[j]; /* hessian */
|
628
|
+
gt += r * (t * bu[j] - x[j]) * bu[j]; /* gradient */
|
629
|
+
ht += r * bu[j] * bu[j]; /* hessian */
|
617
630
|
} else if (x[j] < t * bl[j]) {
|
618
|
-
gt += (t * bl[j] - x[j]) * bl[j]; /* gradient */
|
619
|
-
ht += bl[j] * bl[j]; /* hessian */
|
631
|
+
gt += r * (t * bl[j] - x[j]) * bl[j]; /* gradient */
|
632
|
+
ht += r * bl[j] * bl[j]; /* hessian */
|
620
633
|
}
|
621
634
|
}
|
622
635
|
t = MAX(t - gt / MAX(ht, 1e-8), 0.); /* newton step */
|
@@ -647,6 +660,7 @@ static scs_float proj_box_cone(scs_float *tx, const scs_float *bl,
|
|
647
660
|
/* x[j] unchanged otherwise */
|
648
661
|
}
|
649
662
|
tx[0] = t;
|
663
|
+
|
650
664
|
#if VERBOSITY > 3
|
651
665
|
scs_printf("box cone iters %i\n", (int)iter + 1);
|
652
666
|
#endif
|
@@ -718,18 +732,23 @@ static void proj_power_cone(scs_float *v, scs_float a) {
|
|
718
732
|
}
|
719
733
|
|
720
734
|
/* project onto the primal K cone in the paper */
|
735
|
+
/* the r_y vector determines the INVERSE metric, ie, project under the
|
736
|
+
* diag(r_y)^-1 norm.
|
737
|
+
*/
|
721
738
|
static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
722
|
-
scs_int normalize) {
|
739
|
+
scs_int normalize, scs_float *r_y) {
|
723
740
|
scs_int i, status;
|
724
741
|
scs_int count = 0;
|
742
|
+
scs_float *r_box = SCS_NULL;
|
743
|
+
scs_float *bu, *bl;
|
725
744
|
|
726
|
-
if (k->z) {
|
745
|
+
if (k->z) { /* doesn't use r_y */
|
727
746
|
/* project onto primal zero / dual free cone */
|
728
747
|
memset(x, 0, k->z * sizeof(scs_float));
|
729
748
|
count += k->z;
|
730
749
|
}
|
731
750
|
|
732
|
-
if (k->l) {
|
751
|
+
if (k->l) { /* doesn't use r_y */
|
733
752
|
/* project onto positive orthant */
|
734
753
|
for (i = count; i < count + k->l; ++i) {
|
735
754
|
x[i] = MAX(x[i], 0.0);
|
@@ -737,19 +756,19 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
737
756
|
count += k->l;
|
738
757
|
}
|
739
758
|
|
740
|
-
if (k->bsize) {
|
741
|
-
|
742
|
-
|
743
|
-
c->box_t_warm_start = proj_box_cone(&(x[count]), c->bl, c->bu, k->bsize,
|
744
|
-
c->box_t_warm_start);
|
745
|
-
} else {
|
746
|
-
c->box_t_warm_start = proj_box_cone(&(x[count]), k->bl, k->bu, k->bsize,
|
747
|
-
c->box_t_warm_start);
|
759
|
+
if (k->bsize) { /* DOES use r_y */
|
760
|
+
if (r_y) {
|
761
|
+
r_box = &(r_y[count]);
|
748
762
|
}
|
763
|
+
/* project onto box cone */
|
764
|
+
bu = normalize ? c->bu : k->bu;
|
765
|
+
bl = normalize ? c->bl : k->bl;
|
766
|
+
c->box_t_warm_start = proj_box_cone(&(x[count]), bl, bu, k->bsize,
|
767
|
+
c->box_t_warm_start, r_box);
|
749
768
|
count += k->bsize; /* since b = (t,s), len(s) = bsize - 1 */
|
750
769
|
}
|
751
770
|
|
752
|
-
if (k->qsize && k->q) {
|
771
|
+
if (k->qsize && k->q) { /* doesn't use r_y */
|
753
772
|
/* project onto second-order cones */
|
754
773
|
for (i = 0; i < k->qsize; ++i) {
|
755
774
|
proj_soc(&(x[count]), k->q[i]);
|
@@ -757,7 +776,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
757
776
|
}
|
758
777
|
}
|
759
778
|
|
760
|
-
if (k->ssize && k->s) {
|
779
|
+
if (k->ssize && k->s) { /* doesn't use r_y */
|
761
780
|
/* project onto PSD cones */
|
762
781
|
for (i = 0; i < k->ssize; ++i) {
|
763
782
|
status = proj_semi_definite_cone(&(x[count]), k->s[i], c);
|
@@ -768,13 +787,13 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
768
787
|
}
|
769
788
|
}
|
770
789
|
|
771
|
-
if (k->ep) {
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
790
|
+
if (k->ep) { /* doesn't use r_y */
|
791
|
+
/*
|
792
|
+
* exponential cone is not self dual, if s \in K
|
793
|
+
* then y \in K^* and so if K is the primal cone
|
794
|
+
* here we project onto K^*, via Moreau
|
795
|
+
* \Pi_C^*(y) = y + \Pi_C(-y)
|
796
|
+
*/
|
778
797
|
#ifdef _OPENMP
|
779
798
|
#pragma omp parallel for
|
780
799
|
#endif
|
@@ -784,7 +803,8 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
784
803
|
count += 3 * k->ep;
|
785
804
|
}
|
786
805
|
|
787
|
-
|
806
|
+
/* dual exponential cone */
|
807
|
+
if (k->ed) { /* doesn't use r_y */
|
788
808
|
/*
|
789
809
|
* exponential cone is not self dual, if s \in K
|
790
810
|
* then y \in K^* and so if K is the primal cone
|
@@ -812,7 +832,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
812
832
|
count += 3 * k->ed;
|
813
833
|
}
|
814
834
|
|
815
|
-
if (k->psize && k->p) {
|
835
|
+
if (k->psize && k->p) { /* doesn't use r_y */
|
816
836
|
scs_float v[3];
|
817
837
|
scs_int idx;
|
818
838
|
/* don't use openmp for power cone
|
@@ -820,7 +840,7 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
820
840
|
pragma omp parallel for private(v, idx)
|
821
841
|
endif
|
822
842
|
*/
|
823
|
-
for (i = 0; i < k->psize; ++i) {
|
843
|
+
for (i = 0; i < k->psize; ++i) { /* doesn't use r_y */
|
824
844
|
idx = count + 3 * i;
|
825
845
|
if (k->p[i] >= 0) {
|
826
846
|
/* primal power cone */
|
@@ -844,11 +864,23 @@ static scs_int proj_cone(scs_float *x, const ScsCone *k, ScsConeWork *c,
|
|
844
864
|
return 0;
|
845
865
|
}
|
846
866
|
|
847
|
-
ScsConeWork *SCS(init_cone)(const ScsCone *k,
|
848
|
-
scs_int cone_len) {
|
867
|
+
ScsConeWork *SCS(init_cone)(const ScsCone *k, scs_int m) {
|
849
868
|
ScsConeWork *c = (ScsConeWork *)scs_calloc(1, sizeof(ScsConeWork));
|
850
|
-
c->
|
851
|
-
c->
|
869
|
+
c->k = k;
|
870
|
+
c->m = m;
|
871
|
+
c->scaled_cones = 0;
|
872
|
+
set_cone_boundaries(k, c);
|
873
|
+
c->s = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
874
|
+
if (k->ssize && k->s) {
|
875
|
+
if (set_up_sd_cone_work_space(c, k) < 0) {
|
876
|
+
SCS(finish_cone)(c);
|
877
|
+
return SCS_NULL;
|
878
|
+
}
|
879
|
+
}
|
880
|
+
return c;
|
881
|
+
}
|
882
|
+
|
883
|
+
void scale_box_cone(const ScsCone *k, ScsConeWork *c, ScsScaling *scal) {
|
852
884
|
if (k->bsize && k->bu && k->bl) {
|
853
885
|
c->box_t_warm_start = 1.;
|
854
886
|
if (scal) {
|
@@ -857,33 +889,52 @@ ScsConeWork *SCS(init_cone)(const ScsCone *k, const ScsScaling *scal,
|
|
857
889
|
memcpy(c->bu, k->bu, (k->bsize - 1) * sizeof(scs_float));
|
858
890
|
memcpy(c->bl, k->bl, (k->bsize - 1) * sizeof(scs_float));
|
859
891
|
/* also does some sanitizing */
|
860
|
-
normalize_box_cone(c,
|
861
|
-
k->bsize);
|
862
|
-
}
|
863
|
-
}
|
864
|
-
if (k->ssize && k->s) {
|
865
|
-
if (set_up_sd_cone_work_space(c, k) < 0) {
|
866
|
-
SCS(finish_cone)(c);
|
867
|
-
return SCS_NULL;
|
892
|
+
normalize_box_cone(c, &(scal->D[k->z + k->l]), k->bsize);
|
868
893
|
}
|
869
894
|
}
|
870
|
-
return c;
|
871
895
|
}
|
872
896
|
|
873
|
-
/*
|
874
|
-
|
875
|
-
|
897
|
+
/* Outward facing cone projection routine, performs projection in-place.
|
898
|
+
If normalize > 0 then will use normalized (equilibrated) cones if applicable.
|
899
|
+
|
900
|
+
Moreau decomposition for R-norm projections:
|
901
|
+
|
902
|
+
`x + R^{-1} \Pi_{C^*}^{R^{-1}} ( - R x ) = \Pi_C^R ( x )`
|
903
|
+
|
904
|
+
where \Pi^R_C is the projection onto C under the R-norm:
|
905
|
+
|
906
|
+
`||x||_R = \sqrt{x ' R x}`.
|
907
|
+
|
876
908
|
*/
|
877
|
-
scs_int SCS(proj_dual_cone)(scs_float *x,
|
878
|
-
|
879
|
-
scs_int status;
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
909
|
+
scs_int SCS(proj_dual_cone)(scs_float *x, ScsConeWork *c, ScsScaling *scal,
|
910
|
+
scs_float *r_y) {
|
911
|
+
scs_int status, i;
|
912
|
+
const ScsCone *k = c->k;
|
913
|
+
|
914
|
+
if (!c->scaled_cones) {
|
915
|
+
scale_box_cone(k, c, scal);
|
916
|
+
c->scaled_cones = 1;
|
917
|
+
}
|
918
|
+
|
919
|
+
/* copy s = x */
|
920
|
+
memcpy(c->s, x, c->m * sizeof(scs_float));
|
921
|
+
|
922
|
+
/* x -> - Rx */
|
923
|
+
for (i = 0; i < c->m; ++i) {
|
924
|
+
x[i] *= r_y ? -r_y[i] : -1;
|
925
|
+
}
|
926
|
+
|
927
|
+
/* project -x onto cone, x -> \Pi_{C^*}^{R^{-1}}(-x) under r_y metric */
|
928
|
+
status = proj_cone(x, k, c, scal ? 1 : 0, r_y);
|
929
|
+
|
930
|
+
/* return x + R^{-1} \Pi_{C^*}^{R^{-1}} ( -x ) */
|
931
|
+
for (i = 0; i < c->m; ++i) {
|
932
|
+
if (r_y) {
|
933
|
+
x[i] = x[i] / r_y[i] + c->s[i];
|
934
|
+
} else {
|
935
|
+
x[i] += c->s[i];
|
936
|
+
}
|
937
|
+
}
|
938
|
+
|
888
939
|
return status;
|
889
940
|
}
|
data/vendor/scs/src/linalg.c
CHANGED
@@ -83,9 +83,22 @@ void SCS(add_scaled_array)(scs_float *a, const scs_float *b, scs_int n,
|
|
83
83
|
}
|
84
84
|
}
|
85
85
|
|
86
|
+
scs_float SCS(mean)(const scs_float *x, scs_int n) {
|
87
|
+
scs_int i;
|
88
|
+
scs_float mean = 0.;
|
89
|
+
for (i = 0; i < n; ++i) {
|
90
|
+
mean += x[i];
|
91
|
+
}
|
92
|
+
return mean / n;
|
93
|
+
}
|
94
|
+
|
86
95
|
#else
|
87
96
|
/* If we have BLAS / LAPACK we may as well use them */
|
88
97
|
|
98
|
+
#ifdef __cplusplus
|
99
|
+
extern "C" {
|
100
|
+
#endif
|
101
|
+
|
89
102
|
scs_float BLAS(nrm2)(blas_int *n, const scs_float *x, blas_int *incx);
|
90
103
|
scs_float BLAS(dot)(const blas_int *n, const scs_float *x, const blas_int *incx,
|
91
104
|
const scs_float *y, const blas_int *incy);
|
@@ -96,6 +109,10 @@ void BLAS(axpy)(blas_int *n, const scs_float *a, const scs_float *x,
|
|
96
109
|
void BLAS(scal)(const blas_int *n, const scs_float *sa, scs_float *sx,
|
97
110
|
const blas_int *incx);
|
98
111
|
|
112
|
+
#ifdef __cplusplus
|
113
|
+
}
|
114
|
+
#endif
|
115
|
+
|
99
116
|
/* a *= b */
|
100
117
|
void SCS(scale_array)(scs_float *a, const scs_float b, scs_int len) {
|
101
118
|
blas_int bone = 1;
|
@@ -137,4 +154,12 @@ void SCS(add_scaled_array)(scs_float *a, const scs_float *b, scs_int len,
|
|
137
154
|
BLAS(axpy)(&blen, &sc, b, &bone, a, &bone);
|
138
155
|
}
|
139
156
|
|
157
|
+
scs_float SCS(mean)(const scs_float *x, scs_int n) {
|
158
|
+
blas_int bone = 1;
|
159
|
+
blas_int bzero = 0;
|
160
|
+
blas_int blen = (blas_int)n;
|
161
|
+
scs_float y = 1.0;
|
162
|
+
return BLAS(dot)(&blen, x, &bone, &y, &bzero) / n;
|
163
|
+
}
|
164
|
+
|
140
165
|
#endif
|
data/vendor/scs/src/normalize.c
CHANGED
@@ -4,48 +4,48 @@
|
|
4
4
|
#include "scs.h"
|
5
5
|
|
6
6
|
/* needed for normalizing the warm-start */
|
7
|
-
void SCS(normalize_sol)(
|
7
|
+
void SCS(normalize_sol)(ScsScaling *scal, ScsSolution *sol) {
|
8
8
|
scs_int i;
|
9
|
-
scs_float *D =
|
10
|
-
scs_float *E =
|
11
|
-
for (i = 0; i <
|
12
|
-
sol->x[i] /= (E[i] /
|
9
|
+
scs_float *D = scal->D;
|
10
|
+
scs_float *E = scal->E;
|
11
|
+
for (i = 0; i < scal->n; ++i) {
|
12
|
+
sol->x[i] /= (E[i] / scal->dual_scale);
|
13
13
|
}
|
14
|
-
for (i = 0; i <
|
15
|
-
sol->y[i] /= (D[i] /
|
14
|
+
for (i = 0; i < scal->m; ++i) {
|
15
|
+
sol->y[i] /= (D[i] / scal->primal_scale);
|
16
16
|
}
|
17
|
-
for (i = 0; i <
|
18
|
-
sol->s[i] *= (D[i] *
|
17
|
+
for (i = 0; i < scal->m; ++i) {
|
18
|
+
sol->s[i] *= (D[i] * scal->dual_scale);
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
22
|
-
void SCS(un_normalize_sol)(
|
22
|
+
void SCS(un_normalize_sol)(ScsScaling *scal, ScsSolution *sol) {
|
23
23
|
scs_int i;
|
24
|
-
scs_float *D =
|
25
|
-
scs_float *E =
|
26
|
-
for (i = 0; i <
|
27
|
-
sol->x[i] *= (E[i] /
|
24
|
+
scs_float *D = scal->D;
|
25
|
+
scs_float *E = scal->E;
|
26
|
+
for (i = 0; i < scal->n; ++i) {
|
27
|
+
sol->x[i] *= (E[i] / scal->dual_scale);
|
28
28
|
}
|
29
|
-
for (i = 0; i <
|
30
|
-
sol->y[i] *= (D[i] /
|
29
|
+
for (i = 0; i < scal->m; ++i) {
|
30
|
+
sol->y[i] *= (D[i] / scal->primal_scale);
|
31
31
|
}
|
32
|
-
for (i = 0; i <
|
33
|
-
sol->s[i] /= (D[i] *
|
32
|
+
for (i = 0; i < scal->m; ++i) {
|
33
|
+
sol->s[i] /= (D[i] * scal->dual_scale);
|
34
34
|
}
|
35
35
|
}
|
36
36
|
|
37
|
-
void SCS(un_normalize_primal)(
|
37
|
+
void SCS(un_normalize_primal)(ScsScaling *scal, scs_float *r) {
|
38
38
|
scs_int i;
|
39
|
-
scs_float *D =
|
40
|
-
for (i = 0; i <
|
41
|
-
r[i] /= (D[i] *
|
39
|
+
scs_float *D = scal->D;
|
40
|
+
for (i = 0; i < scal->m; ++i) {
|
41
|
+
r[i] /= (D[i] * scal->dual_scale);
|
42
42
|
}
|
43
43
|
}
|
44
44
|
|
45
|
-
void SCS(un_normalize_dual)(
|
45
|
+
void SCS(un_normalize_dual)(ScsScaling *scal, scs_float *r) {
|
46
46
|
scs_int i;
|
47
|
-
scs_float *E =
|
48
|
-
for (i = 0; i <
|
49
|
-
r[i] /= (E[i] *
|
47
|
+
scs_float *E = scal->E;
|
48
|
+
for (i = 0; i < scal->n; ++i) {
|
49
|
+
r[i] /= (E[i] * scal->primal_scale);
|
50
50
|
}
|
51
51
|
}
|
data/vendor/scs/src/rw.c
CHANGED
@@ -33,20 +33,20 @@ static ScsCone *read_scs_cone(FILE *fin) {
|
|
33
33
|
fread(&(k->z), sizeof(scs_int), 1, fin);
|
34
34
|
fread(&(k->l), sizeof(scs_int), 1, fin);
|
35
35
|
fread(&(k->bsize), sizeof(scs_int), 1, fin);
|
36
|
-
k->bl = scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
37
|
-
k->bu = scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
36
|
+
k->bl = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
37
|
+
k->bu = (scs_float *)scs_calloc(MAX(k->bsize - 1, 0), sizeof(scs_float));
|
38
38
|
fread(k->bl, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
|
39
39
|
fread(k->bu, sizeof(scs_float), MAX(k->bsize - 1, 0), fin);
|
40
40
|
fread(&(k->qsize), sizeof(scs_int), 1, fin);
|
41
|
-
k->q = scs_calloc(k->qsize, sizeof(scs_int));
|
41
|
+
k->q = (scs_int *)scs_calloc(k->qsize, sizeof(scs_int));
|
42
42
|
fread(k->q, sizeof(scs_int), k->qsize, fin);
|
43
43
|
fread(&(k->ssize), sizeof(scs_int), 1, fin);
|
44
|
-
k->s = scs_calloc(k->ssize, sizeof(scs_int));
|
44
|
+
k->s = (scs_int *)scs_calloc(k->ssize, sizeof(scs_int));
|
45
45
|
fread(k->s, sizeof(scs_int), k->ssize, fin);
|
46
46
|
fread(&(k->ep), sizeof(scs_int), 1, fin);
|
47
47
|
fread(&(k->ed), sizeof(scs_int), 1, fin);
|
48
48
|
fread(&(k->psize), sizeof(scs_int), 1, fin);
|
49
|
-
k->p = scs_calloc(k->psize, sizeof(scs_float));
|
49
|
+
k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
|
50
50
|
fread(k->p, sizeof(scs_float), k->psize, fin);
|
51
51
|
return k;
|
52
52
|
}
|
@@ -103,11 +103,11 @@ static ScsMatrix *read_amatrix(FILE *fin) {
|
|
103
103
|
ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
104
104
|
fread(&(A->m), sizeof(scs_int), 1, fin);
|
105
105
|
fread(&(A->n), sizeof(scs_int), 1, fin);
|
106
|
-
A->p = scs_calloc(A->n + 1, sizeof(scs_int));
|
106
|
+
A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
|
107
107
|
fread(A->p, sizeof(scs_int), A->n + 1, fin);
|
108
108
|
Anz = A->p[A->n];
|
109
|
-
A->x = scs_calloc(Anz, sizeof(scs_float));
|
110
|
-
A->i = scs_calloc(Anz, sizeof(scs_int));
|
109
|
+
A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
|
110
|
+
A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
|
111
111
|
fread(A->x, sizeof(scs_float), Anz, fin);
|
112
112
|
fread(A->i, sizeof(scs_int), Anz, fin);
|
113
113
|
return A;
|
@@ -132,8 +132,8 @@ static ScsData *read_scs_data(FILE *fin) {
|
|
132
132
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
133
133
|
fread(&(d->m), sizeof(scs_int), 1, fin);
|
134
134
|
fread(&(d->n), sizeof(scs_int), 1, fin);
|
135
|
-
d->b = scs_calloc(d->m, sizeof(scs_float));
|
136
|
-
d->c = scs_calloc(d->n, sizeof(scs_float));
|
135
|
+
d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
136
|
+
d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
137
137
|
fread(d->b, sizeof(scs_float), d->m, fin);
|
138
138
|
fread(d->c, sizeof(scs_float), d->n, fin);
|
139
139
|
d->A = read_amatrix(fin);
|
@@ -146,8 +146,8 @@ static ScsData *read_scs_data(FILE *fin) {
|
|
146
146
|
void SCS(write_data)(const ScsData *d, const ScsCone *k,
|
147
147
|
const ScsSettings *stgs) {
|
148
148
|
FILE *fout = fopen(stgs->write_data_filename, "wb");
|
149
|
-
uint32_t scs_int_sz = (uint32_t)
|
150
|
-
uint32_t scs_float_sz = (uint32_t)
|
149
|
+
uint32_t scs_int_sz = (uint32_t)sizeof(scs_int);
|
150
|
+
uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
|
151
151
|
const char *scs_version = SCS_VERSION;
|
152
152
|
uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
|
153
153
|
scs_printf("writing data to %s\n", stgs->write_data_filename);
|
@@ -213,6 +213,8 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
|
|
213
213
|
scs_int iter, SCS(timer) * solve_timer) {
|
214
214
|
ScsResiduals *r = w->r_orig;
|
215
215
|
ScsResiduals *r_n = w->r_normalized;
|
216
|
+
ScsSolution *sol = w->xys_orig;
|
217
|
+
ScsSolution *sol_n = w->xys_normalized;
|
216
218
|
/* if iter 0 open to write, else open to append */
|
217
219
|
FILE *fout = fopen(stgs->log_csv_filename, iter == 0 ? "w" : "a");
|
218
220
|
if (!fout) {
|
@@ -227,6 +229,18 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
|
|
227
229
|
"res_pri,"
|
228
230
|
"res_dual,"
|
229
231
|
"gap,"
|
232
|
+
"x_nrm_inf,"
|
233
|
+
"y_nrm_inf,"
|
234
|
+
"s_nrm_inf,"
|
235
|
+
"x_nrm_2,"
|
236
|
+
"y_nrm_2,"
|
237
|
+
"s_nrm_2,"
|
238
|
+
"x_nrm_inf_normalized,"
|
239
|
+
"y_nrm_inf_normalized,"
|
240
|
+
"s_nrm_inf_normalized,"
|
241
|
+
"x_nrm_2_normalized,"
|
242
|
+
"y_nrm_2_normalized,"
|
243
|
+
"s_nrm_2_normalized,"
|
230
244
|
"ax_s_btau_nrm_inf,"
|
231
245
|
"px_aty_ctau_nrm_inf,"
|
232
246
|
"ax_s_btau_nrm_2,"
|
@@ -252,6 +266,11 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
|
|
252
266
|
"dobj_normalized,"
|
253
267
|
"tau_normalized,"
|
254
268
|
"kap_normalized,"
|
269
|
+
"ax_nrm_inf,"
|
270
|
+
"px_nrm_inf,"
|
271
|
+
"aty_nrm_inf,"
|
272
|
+
"b_nrm_inf,"
|
273
|
+
"c_nrm_inf,"
|
255
274
|
"scale,"
|
256
275
|
"diff_u_ut_nrm_2,"
|
257
276
|
"diff_v_v_prev_nrm_2,"
|
@@ -267,6 +286,18 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
|
|
267
286
|
fprintf(fout, "%.16e,", r->res_pri);
|
268
287
|
fprintf(fout, "%.16e,", r->res_dual);
|
269
288
|
fprintf(fout, "%.16e,", r->gap);
|
289
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(sol->x, w->n));
|
290
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(sol->y, w->m));
|
291
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(sol->s, w->m));
|
292
|
+
fprintf(fout, "%.16e,", SCS(norm_2)(sol->x, w->n));
|
293
|
+
fprintf(fout, "%.16e,", SCS(norm_2)(sol->y, w->m));
|
294
|
+
fprintf(fout, "%.16e,", SCS(norm_2)(sol->s, w->m));
|
295
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(sol_n->x, w->n));
|
296
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(sol_n->y, w->m));
|
297
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(sol_n->s, w->m));
|
298
|
+
fprintf(fout, "%.16e,", SCS(norm_2)(sol_n->x, w->n));
|
299
|
+
fprintf(fout, "%.16e,", SCS(norm_2)(sol_n->y, w->m));
|
300
|
+
fprintf(fout, "%.16e,", SCS(norm_2)(sol_n->s, w->m));
|
270
301
|
fprintf(fout, "%.16e,", SCS(norm_inf)(r->ax_s_btau, w->m));
|
271
302
|
fprintf(fout, "%.16e,", SCS(norm_inf)(r->px_aty_ctau, w->n));
|
272
303
|
fprintf(fout, "%.16e,", SCS(norm_2)(r->ax_s_btau, w->m));
|
@@ -292,6 +323,11 @@ void SCS(log_data_to_csv)(const ScsData *d, const ScsCone *k,
|
|
292
323
|
fprintf(fout, "%.16e,", r_n->dobj);
|
293
324
|
fprintf(fout, "%.16e,", r_n->tau);
|
294
325
|
fprintf(fout, "%.16e,", r_n->kap);
|
326
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(r->ax, w->m));
|
327
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(r->px, w->n));
|
328
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(r->aty, w->n));
|
329
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(w->b_orig, w->m));
|
330
|
+
fprintf(fout, "%.16e,", SCS(norm_inf)(w->c_orig, w->n));
|
295
331
|
fprintf(fout, "%.16e,", w->scale);
|
296
332
|
fprintf(fout, "%.16e,", SCS(norm_diff)(w->u, w->u_t, l));
|
297
333
|
fprintf(fout, "%.16e,", SCS(norm_diff)(w->v, w->v_prev, l));
|