scs 0.5.6 → 0.6.0
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 +5 -0
- data/LICENSE.txt +1 -1
- data/lib/scs/ffi.rb +18 -0
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +2 -3
- data/vendor/scs/CLAUDE.md +115 -0
- data/vendor/scs/CMakeLists.txt +330 -201
- data/vendor/scs/CONTRIBUTING.md +49 -0
- data/vendor/scs/Makefile +90 -43
- data/vendor/scs/README.md +96 -2
- data/vendor/scs/include/aa.h +59 -11
- data/vendor/scs/include/aa_stats.h +47 -0
- data/vendor/scs/include/cones.h +16 -7
- data/vendor/scs/include/glbopts.h +113 -26
- data/vendor/scs/include/linalg.h +5 -1
- data/vendor/scs/include/linsys.h +1 -2
- data/vendor/scs/include/normalize.h +6 -2
- data/vendor/scs/include/rw.h +9 -3
- data/vendor/scs/include/scs.h +17 -1
- data/vendor/scs/include/scs_blas.h +8 -0
- data/vendor/scs/include/scs_types.h +2 -2
- data/vendor/scs/include/scs_work.h +22 -1
- data/vendor/scs/include/util.h +3 -6
- data/vendor/scs/include/util_spectral_cones.h +3 -3
- data/vendor/scs/linsys/accelerate/direct/private.c +126 -0
- data/vendor/scs/linsys/accelerate/direct/private.h +34 -0
- data/vendor/scs/linsys/cpu/dense/private.c +250 -0
- data/vendor/scs/linsys/cpu/dense/private.h +31 -0
- data/vendor/scs/linsys/cpu/direct/private.c +86 -44
- data/vendor/scs/linsys/cpu/indirect/private.c +647 -113
- data/vendor/scs/linsys/cpu/indirect/private.h +28 -0
- data/vendor/scs/linsys/csparse.c +9 -3
- data/vendor/scs/linsys/csparse.h +4 -2
- data/vendor/scs/linsys/cudss/direct/private.c +77 -43
- data/vendor/scs/linsys/cudss/direct/private.h +33 -7
- data/vendor/scs/linsys/gpu/indirect/private.c +6 -2
- data/vendor/scs/linsys/mkl/direct/private.c +63 -31
- data/vendor/scs/linsys/mkl/direct/private.h +0 -1
- data/vendor/scs/linsys/scs_matrix.c +291 -165
- data/vendor/scs/linsys/scs_matrix.h +7 -9
- data/vendor/scs/scs.mk +35 -13
- data/vendor/scs/src/aa.c +673 -166
- data/vendor/scs/src/cones.c +545 -223
- data/vendor/scs/src/ctrlc.c +59 -16
- data/vendor/scs/src/exp_cone.c +70 -50
- data/vendor/scs/src/linalg.c +21 -2
- data/vendor/scs/src/normalize.c +24 -26
- data/vendor/scs/src/rw.c +596 -124
- data/vendor/scs/src/scs.c +990 -513
- data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_IPM.c +240 -187
- data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_Newton.c +108 -85
- data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_wrapper.c +62 -63
- data/vendor/scs/src/spectral_cones/logdeterminant/logdet_cone.c +85 -78
- data/vendor/scs/src/spectral_cones/nuclear/ell1_cone.c +92 -97
- data/vendor/scs/src/spectral_cones/nuclear/nuclear_cone.c +39 -28
- data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_cone.c +59 -40
- data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_eval_cone.c +37 -29
- data/vendor/scs/src/spectral_cones/util_spectral_cones.c +12 -6
- data/vendor/scs/src/util.c +37 -7
- data/vendor/scs/test/mkl_interface_mismatch.c +97 -0
- data/vendor/scs/test/packaging/CMakeLists.txt +21 -0
- data/vendor/scs/test/packaging/consume.c +50 -0
- data/vendor/scs/test/problem_utils.h +9 -2
- data/vendor/scs/test/problems/dense_qp.h +64 -0
- data/vendor/scs/test/problems/hs21_tiny_qp.h +6 -2
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +10 -2
- data/vendor/scs/test/problems/infeasible_lp.h +66 -0
- data/vendor/scs/test/problems/infeasible_socp.h +75 -0
- data/vendor/scs/test/problems/lp_update.h +110 -0
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -1
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +6 -3
- data/vendor/scs/test/problems/small_qp.h +5 -0
- data/vendor/scs/test/problems/test_box_cone.h +92 -0
- data/vendor/scs/test/problems/test_dual_exp_cone.h +96 -0
- data/vendor/scs/test/problems/test_inaccurate.h +212 -0
- data/vendor/scs/test/problems/test_mixed_cones.h +113 -0
- data/vendor/scs/test/problems/test_normalize_roundtrip.h +279 -0
- data/vendor/scs/test/problems/test_power_cone.h +414 -0
- data/vendor/scs/test/problems/test_psd_metric.h +109 -0
- data/vendor/scs/test/problems/test_psd_n1.h +84 -0
- data/vendor/scs/test/problems/test_root_plus.h +191 -0
- data/vendor/scs/test/problems/test_rw_settings.h +112 -0
- data/vendor/scs/test/problems/test_soc_sizes.h +393 -0
- data/vendor/scs/test/problems/test_solver_options.h +558 -0
- data/vendor/scs/test/problems/test_validation.h +263 -24
- data/vendor/scs/test/problems/test_zero_cone.h +81 -0
- data/vendor/scs/test/problems/unbounded_lp.h +66 -0
- data/vendor/scs/test/problems/unbounded_socp.h +71 -0
- data/vendor/scs/test/run_from_file.c +6 -0
- data/vendor/scs/test/run_tests.c +71 -0
- data/vendor/scs/test/rw_settings.c +7 -0
- data/vendor/scs/test/spectral_cones_problems/test_ell1_and_nuc.h +128 -0
- data/vendor/scs/test/spectral_cones_problems/test_ell1_cone.h +115 -0
- metadata +35 -3
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#include "cones.h"
|
|
2
|
-
|
|
2
|
+
/* #include "scs.h" */
|
|
3
3
|
#include "linalg.h"
|
|
4
4
|
#include "scs_blas.h"
|
|
5
5
|
#include "scs_types.h"
|
|
6
6
|
#include "util_spectral_cones.h"
|
|
7
|
-
#include <stdlib.h>
|
|
7
|
+
#include <stdlib.h> /* qsort */
|
|
8
8
|
|
|
9
9
|
#define TOL_LARGEST_CONE 1e-9
|
|
10
10
|
|
|
@@ -30,7 +30,8 @@ static void compute_cone_residuals(scs_float t, const scs_float *x,
|
|
|
30
30
|
#endif
|
|
31
31
|
|
|
32
32
|
scs_int assert_sorted(scs_float *x, scs_int n) {
|
|
33
|
-
|
|
33
|
+
scs_int i;
|
|
34
|
+
for (i = 0; i < n - 1; ++i) {
|
|
34
35
|
if (x[i] < x[i + 1]) {
|
|
35
36
|
return -1;
|
|
36
37
|
}
|
|
@@ -40,53 +41,64 @@ scs_int assert_sorted(scs_float *x, scs_int n) {
|
|
|
40
41
|
|
|
41
42
|
scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
|
|
42
43
|
scs_int k) {
|
|
44
|
+
scs_int nu, nt;
|
|
45
|
+
scs_float eta;
|
|
46
|
+
scs_float t0;
|
|
47
|
+
scs_float S;
|
|
48
|
+
scs_float a_u, a_t;
|
|
49
|
+
scs_float ratio, s1, s3, s;
|
|
50
|
+
scs_float val;
|
|
51
|
+
scs_int i;
|
|
52
|
+
|
|
43
53
|
#ifdef SPECTRAL_DEBUG
|
|
44
54
|
scs_float t00 = *t;
|
|
45
55
|
scs_float *x0 = scs_malloc(n * sizeof(*x0));
|
|
56
|
+
scs_int status;
|
|
46
57
|
memcpy(x0, x, n * sizeof(*x0));
|
|
47
|
-
|
|
58
|
+
status = assert_sorted(x, n);
|
|
48
59
|
if (status < 0) {
|
|
49
60
|
scs_printf("NOT SORTED! \n");
|
|
50
61
|
return status;
|
|
51
62
|
}
|
|
52
63
|
#endif
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
/* -------------------------------
|
|
66
|
+
* Initialize state variables
|
|
67
|
+
* ------------------------------- */
|
|
57
68
|
assert(k < n && k > 0);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
nu = k;
|
|
70
|
+
nt = 0;
|
|
71
|
+
eta = 0.0;
|
|
72
|
+
t0 = *t;
|
|
73
|
+
S = x[0];
|
|
74
|
+
for (i = 1; i < k; ++i) {
|
|
63
75
|
S += x[i];
|
|
64
76
|
}
|
|
65
77
|
|
|
66
|
-
|
|
78
|
+
a_u = x[nu - 1];
|
|
79
|
+
a_t = x[nu];
|
|
67
80
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
scs_float ratio, s1, s3, s;
|
|
81
|
+
/* ---------------------------------
|
|
82
|
+
* main loop
|
|
83
|
+
* --------------------------------- */
|
|
72
84
|
while (S > *t + TOL_LARGEST_CONE) {
|
|
73
85
|
ratio = (nu == k) ? 1.0 : (scs_float)(nt) / (k - nu);
|
|
74
86
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
/* ------------------------------------------------------
|
|
88
|
+
* compute step size
|
|
89
|
+
* ------------------------------------------------------ */
|
|
78
90
|
s1 = (nu == k) ? a_u - a_t : (a_u - a_t) / (ratio - 1);
|
|
79
91
|
s3 = (S - *t) / (ratio * (nu + 1) + (k - nu));
|
|
80
92
|
s = (nu == 0) ? s3 : MIN(s3, s1);
|
|
81
93
|
|
|
82
94
|
if (!(nu + nt == n || nt == 0)) {
|
|
83
|
-
|
|
95
|
+
val = a_t - x[nu + nt];
|
|
84
96
|
s = MIN(s, val);
|
|
85
97
|
}
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
99
|
+
/* --------------------------
|
|
100
|
+
* update state
|
|
101
|
+
* -------------------------- */
|
|
90
102
|
eta += s * ratio;
|
|
91
103
|
S -= s * (ratio * nu + k - nu);
|
|
92
104
|
*t = t0 + eta;
|
|
@@ -110,8 +122,7 @@ scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
|
|
|
110
122
|
|
|
111
123
|
nt -= 1;
|
|
112
124
|
|
|
113
|
-
|
|
114
|
-
scs_int i;
|
|
125
|
+
/* update projection */
|
|
115
126
|
for (i = 0; i < nu; ++i) {
|
|
116
127
|
x[i] -= eta;
|
|
117
128
|
}
|
|
@@ -121,12 +132,14 @@ scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
|
|
|
121
132
|
}
|
|
122
133
|
|
|
123
134
|
#ifdef SPECTRAL_DEBUG
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
135
|
+
{
|
|
136
|
+
scs_float residuals[3];
|
|
137
|
+
compute_cone_residuals(*t, x, t00, x0, residuals, n, k);
|
|
138
|
+
scs_free(x0);
|
|
139
|
+
if (residuals[0] > 1e-10 || residuals[1] > 1e-10 ||
|
|
140
|
+
fabs(residuals[2]) > 1e-10) {
|
|
141
|
+
return -1;
|
|
142
|
+
}
|
|
130
143
|
}
|
|
131
144
|
#endif
|
|
132
145
|
|
|
@@ -144,14 +157,15 @@ scs_int cmp_desc(const void *a, const void *b) {
|
|
|
144
157
|
}
|
|
145
158
|
|
|
146
159
|
#ifdef SPECTRAL_DEBUG
|
|
147
|
-
|
|
160
|
+
/* this function is not used in production so fine to allocate memory */
|
|
148
161
|
static scs_float sum_largest_val(const scs_float *x, scs_int n, scs_int k) {
|
|
149
162
|
scs_float *x_temp = scs_malloc(n * sizeof(*x));
|
|
163
|
+
scs_float val = 0.0;
|
|
164
|
+
scs_int i;
|
|
150
165
|
memcpy(x_temp, x, n * sizeof(*x));
|
|
151
166
|
qsort(x_temp, n, sizeof(*x_temp), cmp_desc);
|
|
152
167
|
|
|
153
|
-
|
|
154
|
-
for (scs_int i = 0; i < k; ++i) {
|
|
168
|
+
for (i = 0; i < k; ++i) {
|
|
155
169
|
val += x_temp[i];
|
|
156
170
|
}
|
|
157
171
|
scs_free(x_temp);
|
|
@@ -165,18 +179,23 @@ static void compute_cone_residuals(scs_float t, const scs_float *x,
|
|
|
165
179
|
scs_float lmbda_t = t - t0;
|
|
166
180
|
scs_float *lmbda_x = scs_malloc(n * sizeof(*x));
|
|
167
181
|
scs_float sum_lmbda_x = 0.0;
|
|
168
|
-
|
|
182
|
+
scs_int i;
|
|
183
|
+
scs_float comp;
|
|
184
|
+
scs_float pri_res;
|
|
185
|
+
scs_float dual_res;
|
|
186
|
+
|
|
187
|
+
for (i = 0; i < n; ++i) {
|
|
169
188
|
lmbda_x[i] = x[i] - x0[i];
|
|
170
189
|
sum_lmbda_x += lmbda_x[i];
|
|
171
190
|
}
|
|
172
191
|
|
|
173
|
-
|
|
174
|
-
|
|
192
|
+
comp = lmbda_t * t + SCS(dot)(lmbda_x, x, n);
|
|
193
|
+
pri_res = sum_largest_val(x, n, k) - t;
|
|
175
194
|
|
|
176
|
-
|
|
195
|
+
dual_res = fabs(sum_lmbda_x + lmbda_t * k);
|
|
177
196
|
dual_res *= dual_res;
|
|
178
197
|
|
|
179
|
-
for (
|
|
198
|
+
for (i = 0; i < n; ++i) {
|
|
180
199
|
if (lmbda_x[i] > 0) {
|
|
181
200
|
dual_res += lmbda_x[i] * lmbda_x[i];
|
|
182
201
|
}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
#include "linalg.h"
|
|
3
3
|
#include "scs_blas.h"
|
|
4
4
|
#include "scs_types.h"
|
|
5
|
-
#include "util.h"
|
|
5
|
+
#include "util.h"
|
|
6
|
+
|
|
7
|
+
#include <string.h>
|
|
6
8
|
|
|
7
9
|
/*
|
|
8
10
|
* Spectral matrix cone projections, from "Projection onto Spectral Matrix
|
|
@@ -37,13 +39,14 @@ void BLAS(gemm)(const char *transa, const char *transb, blas_int *m,
|
|
|
37
39
|
}
|
|
38
40
|
#endif
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
/* forward declaration */
|
|
41
43
|
scs_int proj_sum_largest_cone_sorted(scs_float *t, scs_float *x, scs_int n,
|
|
42
44
|
scs_int k);
|
|
43
45
|
|
|
44
46
|
void flip(scs_float *x, int n) {
|
|
45
47
|
scs_float temp;
|
|
46
|
-
|
|
48
|
+
int i;
|
|
49
|
+
for (i = 0; i < n / 2; i++) {
|
|
47
50
|
temp = x[i];
|
|
48
51
|
x[i] = x[n - i - 1];
|
|
49
52
|
x[n - i - 1] = temp;
|
|
@@ -52,19 +55,19 @@ void flip(scs_float *x, int n) {
|
|
|
52
55
|
|
|
53
56
|
scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
|
|
54
57
|
ScsConeWork *c) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
/*
|
|
59
|
+
* tvX = [t, X], where X represents the lower triangular part of a matrix
|
|
60
|
+
* stored in a compact form and off-diagonal elements have been scaled by
|
|
61
|
+
* sqrt(2)
|
|
62
|
+
*/
|
|
58
63
|
scs_float *X = tX + 1;
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
// compute eigendecomposition
|
|
62
|
-
// ----------------------------------------------------------------------
|
|
65
|
+
/* compute eigendecomposition */
|
|
63
66
|
scs_int i;
|
|
64
67
|
blas_int nb = (blas_int)n;
|
|
65
68
|
blas_int nb_plus_one = (blas_int)(n + 1);
|
|
66
69
|
blas_int one_int = 1;
|
|
67
|
-
scs_float sqrt2 =
|
|
70
|
+
scs_float sqrt2 = SQRTF(2.0);
|
|
68
71
|
scs_float sqrt2_inv = 1.0 / sqrt2;
|
|
69
72
|
scs_float *Xs = c->Xs;
|
|
70
73
|
scs_float *e = c->e;
|
|
@@ -72,19 +75,26 @@ scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
|
|
|
72
75
|
scs_float *work = c->work;
|
|
73
76
|
blas_int lwork = c->lwork;
|
|
74
77
|
blas_int info = 0;
|
|
78
|
+
scs_int status;
|
|
79
|
+
char transN;
|
|
80
|
+
char transY;
|
|
81
|
+
scs_float one;
|
|
82
|
+
scs_float zero;
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
/* copy lower triangular matrix into full matrix */
|
|
77
85
|
for (i = 0; i < n; ++i) {
|
|
78
86
|
memcpy(&(Xs[i * (n + 1)]), &(X[i * n - ((i - 1) * i) / 2]),
|
|
79
87
|
(n - i) * sizeof(scs_float));
|
|
80
88
|
}
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
/* rescale diags by sqrt(2) */
|
|
83
91
|
BLAS(scal)(&nb, &sqrt2, Xs, &nb_plus_one);
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
/*
|
|
94
|
+
* Eigendecomposition. On exit, the lower triangular part of Xs stores
|
|
95
|
+
* the eigenvectors. The vector e stores the eigenvalues in ascending
|
|
96
|
+
* order (smallest eigenvalue first)
|
|
97
|
+
*/
|
|
88
98
|
BLAS(syev)("Vectors", "Lower", &nb, Xs, &nb, e, work, &lwork, &info);
|
|
89
99
|
if (info != 0) {
|
|
90
100
|
scs_printf("WARN: LAPACK syev error, info = %i\n", (int)info);
|
|
@@ -93,15 +103,15 @@ scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
|
|
|
93
103
|
}
|
|
94
104
|
}
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
/*
|
|
107
|
+
* Project onto spectral *vector* cone. Note that e is sqrt(2) times
|
|
108
|
+
* the eigenvalue vector we want to project. We therefore multiply
|
|
109
|
+
* tvX[0] by sqrt(2).
|
|
110
|
+
*/
|
|
101
111
|
tX[0] *= sqrt2;
|
|
102
112
|
SPECTRAL_TIMING(SCS(timer) _timer; SCS(tic)(&_timer);)
|
|
103
113
|
flip(e, n);
|
|
104
|
-
|
|
114
|
+
status = proj_sum_largest_cone_sorted(&tX[0], e, n, k);
|
|
105
115
|
flip(e, n);
|
|
106
116
|
SPECTRAL_TIMING(c->tot_time_vec_cone_proj += SCS(tocq)(&_timer);)
|
|
107
117
|
|
|
@@ -109,20 +119,18 @@ scs_int SCS(proj_sum_largest_evals)(scs_float *tX, scs_int n, scs_int k,
|
|
|
109
119
|
return status;
|
|
110
120
|
}
|
|
111
121
|
|
|
112
|
-
|
|
113
|
-
// recover projection onto spectral *matrix* cone
|
|
114
|
-
// ----------------------------------------------------------------------
|
|
122
|
+
/* recover projection onto spectral *matrix* cone */
|
|
115
123
|
memcpy(c->work_sum_of_largest, Xs, n * n * sizeof(*Xs));
|
|
116
124
|
for (i = 0; i < n; ++i) {
|
|
117
125
|
BLAS(scal)(&nb, &e[i], &Xs[i * n], &one_int);
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
transN = 'N';
|
|
129
|
+
transY = 'T';
|
|
130
|
+
one = 1.0;
|
|
131
|
+
zero = 0.0;
|
|
124
132
|
|
|
125
|
-
|
|
133
|
+
/* it is not safe to have overlapping matrices for dgemm_. */
|
|
126
134
|
BLAS(gemm)(&transN, &transY, &nb, &nb, &nb, &one, Xs, &nb,
|
|
127
135
|
c->work_sum_of_largest, &nb, &zero, Z, &nb);
|
|
128
136
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#include "util_spectral_cones.h"
|
|
2
2
|
|
|
3
3
|
bool is_pos(const scs_float *x, scs_int n) {
|
|
4
|
-
|
|
4
|
+
scs_int i;
|
|
5
|
+
for (i = 0; i < n; ++i) {
|
|
5
6
|
if (x[i] <= 0.0) {
|
|
6
7
|
return false;
|
|
7
8
|
}
|
|
@@ -10,7 +11,8 @@ bool is_pos(const scs_float *x, scs_int n) {
|
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
bool is_negative(const scs_float *x, scs_int n) {
|
|
13
|
-
|
|
14
|
+
scs_int i;
|
|
15
|
+
for (i = 0; i < n; ++i) {
|
|
14
16
|
if (x[i] >= 0.0) {
|
|
15
17
|
return false;
|
|
16
18
|
}
|
|
@@ -19,13 +21,15 @@ bool is_negative(const scs_float *x, scs_int n) {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
void non_neg_proj(const scs_float *src, scs_float *dst, scs_int n) {
|
|
22
|
-
|
|
24
|
+
scs_int i;
|
|
25
|
+
for (i = 0; i < n; ++i) {
|
|
23
26
|
dst[i] = (src[i] > 0.0) ? src[i] : 0.0;
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
void print_vector(const scs_float *x, scs_int n) {
|
|
28
|
-
|
|
31
|
+
scs_int i;
|
|
32
|
+
for (i = 0; i < n; ++i) {
|
|
29
33
|
printf("%f ", x[i]);
|
|
30
34
|
}
|
|
31
35
|
printf("\n");
|
|
@@ -33,8 +37,9 @@ void print_vector(const scs_float *x, scs_int n) {
|
|
|
33
37
|
|
|
34
38
|
scs_float min_vec(const scs_float *vec, scs_int n) {
|
|
35
39
|
scs_float minVal = vec[0];
|
|
40
|
+
scs_int i;
|
|
36
41
|
|
|
37
|
-
for (
|
|
42
|
+
for (i = 1; i < n; ++i) {
|
|
38
43
|
if (vec[i] < minVal) {
|
|
39
44
|
minVal = vec[i];
|
|
40
45
|
}
|
|
@@ -45,7 +50,8 @@ scs_float min_vec(const scs_float *vec, scs_int n) {
|
|
|
45
50
|
|
|
46
51
|
scs_float sum_log(const scs_float *x, scs_int n) {
|
|
47
52
|
scs_float sum = 0.0;
|
|
48
|
-
|
|
53
|
+
scs_int i;
|
|
54
|
+
for (i = 0; i < n; ++i) {
|
|
49
55
|
sum += log(x[i]);
|
|
50
56
|
}
|
|
51
57
|
return sum;
|
data/vendor/scs/src/util.c
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Utility functions: platform-specific timers, deep copy helpers for
|
|
3
|
+
* ScsData/ScsSettings, memory deallocation, and default settings.
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
#include "util.h"
|
|
2
7
|
|
|
3
8
|
#include "glbopts.h"
|
|
9
|
+
#include <string.h>
|
|
4
10
|
#include "linsys.h"
|
|
5
11
|
#include "scs_matrix.h"
|
|
6
12
|
|
|
@@ -71,25 +77,38 @@ scs_float SCS(tocq)(SCS(timer) * t) {
|
|
|
71
77
|
|
|
72
78
|
#endif
|
|
73
79
|
|
|
74
|
-
|
|
80
|
+
scs_int SCS(deep_copy_data)(ScsData *dest, const ScsData *src) {
|
|
81
|
+
memset(dest, 0, sizeof(*dest));
|
|
75
82
|
dest->n = src->n;
|
|
76
83
|
dest->m = src->m;
|
|
77
|
-
SCS(copy_matrix)(&(dest->A), src->A)
|
|
78
|
-
|
|
84
|
+
if (!SCS(copy_matrix)(&(dest->A), src->A) ||
|
|
85
|
+
!SCS(copy_matrix)(&(dest->P), src->P)) {
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
79
88
|
dest->b = (scs_float *)scs_calloc(dest->m, sizeof(scs_float));
|
|
80
|
-
memcpy(dest->b, src->b, dest->m * sizeof(scs_float));
|
|
81
89
|
dest->c = (scs_float *)scs_calloc(dest->n, sizeof(scs_float));
|
|
90
|
+
if (!dest->b || !dest->c) {
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
memcpy(dest->b, src->b, dest->m * sizeof(scs_float));
|
|
82
94
|
memcpy(dest->c, src->c, dest->n * sizeof(scs_float));
|
|
95
|
+
return 1;
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
|
|
98
|
+
scs_int SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
|
|
86
99
|
memcpy(dest, src, sizeof(ScsSettings));
|
|
87
100
|
/* MATLAB does something weird with strdup, so use strcpy instead */
|
|
88
101
|
char *tmp;
|
|
89
102
|
if (src->write_data_filename) {
|
|
90
103
|
/* sizeof(char) = 1 */
|
|
91
104
|
tmp = (char *)scs_malloc(strlen(src->write_data_filename) + 1);
|
|
92
|
-
|
|
105
|
+
if (tmp) {
|
|
106
|
+
strcpy(tmp, src->write_data_filename);
|
|
107
|
+
}
|
|
108
|
+
if (!tmp) {
|
|
109
|
+
dest->write_data_filename = SCS_NULL;
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
93
112
|
dest->write_data_filename = tmp;
|
|
94
113
|
} else {
|
|
95
114
|
dest->write_data_filename = SCS_NULL;
|
|
@@ -98,11 +117,18 @@ void SCS(deep_copy_stgs)(ScsSettings *dest, const ScsSettings *src) {
|
|
|
98
117
|
if (src->log_csv_filename) {
|
|
99
118
|
/* sizeof(char) = 1 */
|
|
100
119
|
tmp = (char *)scs_malloc(strlen(src->log_csv_filename) + 1);
|
|
101
|
-
|
|
120
|
+
if (tmp) {
|
|
121
|
+
strcpy(tmp, src->log_csv_filename);
|
|
122
|
+
}
|
|
123
|
+
if (!tmp) {
|
|
124
|
+
dest->log_csv_filename = SCS_NULL;
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
102
127
|
dest->log_csv_filename = tmp;
|
|
103
128
|
} else {
|
|
104
129
|
dest->log_csv_filename = SCS_NULL;
|
|
105
130
|
}
|
|
131
|
+
return 1;
|
|
106
132
|
}
|
|
107
133
|
|
|
108
134
|
void SCS(free_data)(ScsData *d) {
|
|
@@ -143,7 +169,11 @@ void scs_set_default_settings(ScsSettings *stgs) {
|
|
|
143
169
|
stgs->warm_start = WARM_START;
|
|
144
170
|
stgs->acceleration_lookback = ACCELERATION_LOOKBACK;
|
|
145
171
|
stgs->acceleration_interval = ACCELERATION_INTERVAL;
|
|
172
|
+
stgs->acceleration_type_1 = ACCELERATION_TYPE_1;
|
|
173
|
+
stgs->acceleration_regularization = AA_REGULARIZATION;
|
|
174
|
+
stgs->acceleration_relaxation = AA_RELAXATION;
|
|
146
175
|
stgs->adaptive_scale = ADAPTIVE_SCALE;
|
|
176
|
+
stgs->adaptive_diag_scale = ADAPTIVE_DIAG_SCALE;
|
|
147
177
|
stgs->write_data_filename = WRITE_DATA_FILENAME;
|
|
148
178
|
stgs->log_csv_filename = LOG_CSV_FILENAME;
|
|
149
179
|
stgs->time_limit_secs = TIME_LIMIT_SECS;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#include "scs.h"
|
|
2
|
+
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include <string.h>
|
|
6
|
+
|
|
7
|
+
/* Two modes, selected by argv[1]:
|
|
8
|
+
*
|
|
9
|
+
* mismatch (default): preset the WRONG integer width before scs_init;
|
|
10
|
+
* initialization must fail fast with the interface-layer diagnostic.
|
|
11
|
+
*
|
|
12
|
+
* gnu: preset the GNU Fortran calling-convention flag together with the
|
|
13
|
+
* CORRECT integer width (values 2 = LP64|GNU or 3 = ILP64|GNU, as an
|
|
14
|
+
* MKL-backed NumPy does when it initializes MKL first); initialization
|
|
15
|
+
* and a full solve must succeed, proving the runtime guard compares
|
|
16
|
+
* only the width bit. */
|
|
17
|
+
|
|
18
|
+
#define MKL_INTERFACE_LP64 0
|
|
19
|
+
#define MKL_INTERFACE_ILP64 1
|
|
20
|
+
#define MKL_INTERFACE_GNU 2
|
|
21
|
+
|
|
22
|
+
int MKL_Set_Interface_Layer(int);
|
|
23
|
+
|
|
24
|
+
int main(int argc, char **argv) {
|
|
25
|
+
scs_float P_x[3] = {3., -1., 2.};
|
|
26
|
+
scs_int P_i[3] = {0, 0, 1};
|
|
27
|
+
scs_int P_p[3] = {0, 1, 3};
|
|
28
|
+
scs_float A_x[4] = {-1., 1., 1., 1.};
|
|
29
|
+
scs_int A_i[4] = {0, 1, 0, 2};
|
|
30
|
+
scs_int A_p[3] = {0, 2, 4};
|
|
31
|
+
scs_float b[3] = {-1., 0.3, -0.5};
|
|
32
|
+
scs_float c[2] = {-1., -1.};
|
|
33
|
+
ScsCone k = {0};
|
|
34
|
+
ScsData d = {0};
|
|
35
|
+
ScsSettings stgs = {0};
|
|
36
|
+
ScsSolution sol = {0};
|
|
37
|
+
ScsInfo info;
|
|
38
|
+
ScsWork *w;
|
|
39
|
+
int gnu_mode = argc > 1 && strcmp(argv[1], "gnu") == 0;
|
|
40
|
+
int layer;
|
|
41
|
+
int actual;
|
|
42
|
+
scs_int exitflag;
|
|
43
|
+
|
|
44
|
+
#ifdef BLAS64
|
|
45
|
+
layer = gnu_mode ? (MKL_INTERFACE_ILP64 | MKL_INTERFACE_GNU)
|
|
46
|
+
: MKL_INTERFACE_LP64;
|
|
47
|
+
#else
|
|
48
|
+
layer = gnu_mode ? (MKL_INTERFACE_LP64 | MKL_INTERFACE_GNU)
|
|
49
|
+
: MKL_INTERFACE_ILP64;
|
|
50
|
+
#endif
|
|
51
|
+
|
|
52
|
+
actual = MKL_Set_Interface_Layer(layer);
|
|
53
|
+
if (actual != layer) {
|
|
54
|
+
fprintf(stderr,
|
|
55
|
+
"failed to pre-set MKL interface layer to %d, actual layer is %d\n",
|
|
56
|
+
layer, actual);
|
|
57
|
+
return 2;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
d.m = 3;
|
|
61
|
+
d.n = 2;
|
|
62
|
+
d.b = b;
|
|
63
|
+
d.c = c;
|
|
64
|
+
d.A = &(ScsMatrix){A_x, A_i, A_p, 3, 2};
|
|
65
|
+
d.P = &(ScsMatrix){P_x, P_i, P_p, 2, 2};
|
|
66
|
+
|
|
67
|
+
k.z = 1;
|
|
68
|
+
k.l = 2;
|
|
69
|
+
|
|
70
|
+
scs_set_default_settings(&stgs);
|
|
71
|
+
stgs.verbose = 1;
|
|
72
|
+
|
|
73
|
+
if (gnu_mode) {
|
|
74
|
+
exitflag = scs(&d, &k, &stgs, &sol, &info);
|
|
75
|
+
if (exitflag != SCS_SOLVED) {
|
|
76
|
+
fprintf(stderr, "gnu-layer solve failed with exitflag %d\n",
|
|
77
|
+
(int)exitflag);
|
|
78
|
+
return 4;
|
|
79
|
+
}
|
|
80
|
+
printf("gnu-layer solve succeeded (layer %d)\n", layer);
|
|
81
|
+
free(sol.x);
|
|
82
|
+
free(sol.y);
|
|
83
|
+
free(sol.s);
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
w = scs_init(&d, &k, &stgs);
|
|
88
|
+
if (w != SCS_NULL) {
|
|
89
|
+
fprintf(stderr,
|
|
90
|
+
"expected scs_init to fail after forcing the wrong MKL interface "
|
|
91
|
+
"layer\n");
|
|
92
|
+
scs_finish(w);
|
|
93
|
+
return 3;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Consumes an INSTALLED scs package (see .github/workflows/cmake_consume.yml).
|
|
2
|
+
# The installed package, not this fixture, must enforce its consumer floor.
|
|
3
|
+
cmake_minimum_required(VERSION 3.18)
|
|
4
|
+
project(scs_consume C)
|
|
5
|
+
|
|
6
|
+
set(SCS_COMPONENT scsdir CACHE STRING "scs library to consume (scsdir, scsmkl, ...)")
|
|
7
|
+
|
|
8
|
+
# CI: a consumer that resolved LAPACK at the wrong integer width before scs
|
|
9
|
+
# must be refused by a static package.
|
|
10
|
+
option(PREFIND_LAPACK_WRONG_WIDTH "find LAPACK with 4-byte integers first" OFF)
|
|
11
|
+
if(PREFIND_LAPACK_WRONG_WIDTH)
|
|
12
|
+
set(BLA_SIZEOF_INTEGER 4)
|
|
13
|
+
find_package(LAPACK REQUIRED)
|
|
14
|
+
endif()
|
|
15
|
+
|
|
16
|
+
find_package(scs CONFIG REQUIRED)
|
|
17
|
+
if(NOT scs::${SCS_COMPONENT} IN_LIST scs_LIBRARIES)
|
|
18
|
+
message(FATAL_ERROR "scs_LIBRARIES=${scs_LIBRARIES} lacks scs::${SCS_COMPONENT}")
|
|
19
|
+
endif()
|
|
20
|
+
add_executable(consume consume.c)
|
|
21
|
+
target_link_libraries(consume PRIVATE scs::${SCS_COMPONENT})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/* Minimal consumer of an *installed* SCS package: links scs::scsdir via
|
|
2
|
+
* find_package(scs) and solves a tiny QP. Used by the cmake_consume CI
|
|
3
|
+
* workflow to prove installed packages are usable for both shared and
|
|
4
|
+
* static builds (and that shared installs demand no private build deps). */
|
|
5
|
+
#include "scs.h"
|
|
6
|
+
|
|
7
|
+
#include <stdio.h>
|
|
8
|
+
#include <stdlib.h>
|
|
9
|
+
|
|
10
|
+
int main(void) {
|
|
11
|
+
scs_float P_x[3] = {3., -1., 2.};
|
|
12
|
+
scs_int P_i[3] = {0, 0, 1};
|
|
13
|
+
scs_int P_p[3] = {0, 1, 3};
|
|
14
|
+
scs_float A_x[4] = {-1., 1., 1., 1.};
|
|
15
|
+
scs_int A_i[4] = {0, 1, 0, 2};
|
|
16
|
+
scs_int A_p[3] = {0, 2, 4};
|
|
17
|
+
scs_float b[3] = {-1., 0.3, -0.5};
|
|
18
|
+
scs_float c[2] = {-1., -1.};
|
|
19
|
+
ScsCone k = {0};
|
|
20
|
+
ScsData d = {0};
|
|
21
|
+
ScsSettings stgs = {0};
|
|
22
|
+
ScsSolution sol = {0};
|
|
23
|
+
ScsInfo info;
|
|
24
|
+
scs_int exitflag;
|
|
25
|
+
|
|
26
|
+
printf("consuming scs %s\n", scs_version());
|
|
27
|
+
|
|
28
|
+
d.m = 3;
|
|
29
|
+
d.n = 2;
|
|
30
|
+
d.b = b;
|
|
31
|
+
d.c = c;
|
|
32
|
+
d.A = &(ScsMatrix){A_x, A_i, A_p, 3, 2};
|
|
33
|
+
d.P = &(ScsMatrix){P_x, P_i, P_p, 2, 2};
|
|
34
|
+
k.z = 1;
|
|
35
|
+
k.l = 2;
|
|
36
|
+
|
|
37
|
+
scs_set_default_settings(&stgs);
|
|
38
|
+
stgs.verbose = 1;
|
|
39
|
+
|
|
40
|
+
exitflag = scs(&d, &k, &stgs, &sol, &info);
|
|
41
|
+
if (exitflag != SCS_SOLVED) {
|
|
42
|
+
fprintf(stderr, "consume: solve failed with exitflag %d\n", (int)exitflag);
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
printf("consume: solved, objective %f\n", info.pobj);
|
|
46
|
+
free(sol.x);
|
|
47
|
+
free(sol.y);
|
|
48
|
+
free(sol.s);
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
#include "scs_matrix.h"
|
|
11
11
|
#include "util.h"
|
|
12
12
|
|
|
13
|
+
#include <string.h>
|
|
14
|
+
|
|
13
15
|
#define _MAX_RAND_VAL (1073741823) /* 2^30 - 1 */
|
|
14
16
|
|
|
15
17
|
/* uniform random number in [-1,1] */
|
|
@@ -205,10 +207,15 @@ const char *verify_solution_correct(ScsData *d, ScsCone *k, ScsSettings *stgs,
|
|
|
205
207
|
|
|
206
208
|
/**************** ASSERTS *****************/
|
|
207
209
|
if (status == SCS_SOLVED) {
|
|
210
|
+
/* reported-vs-recomputed consistency: the recomputation here uses a
|
|
211
|
+
* different BLAS summation order than the solver's internal pipeline,
|
|
212
|
+
* so the discrepancy scales with the magnitude of the accumulated
|
|
213
|
+
* quantities (~ the objective scale), like the gap and objective
|
|
214
|
+
* checks below already do */
|
|
208
215
|
mu_assert_less("Primal residual ERROR", ABS(res_pri - info->res_pri),
|
|
209
|
-
1e-10);
|
|
216
|
+
1e-10 * (1 + ABS(pobj)));
|
|
210
217
|
mu_assert_less("Dual residual ERROR", ABS(res_dual - info->res_dual),
|
|
211
|
-
1e-10);
|
|
218
|
+
1e-10 * (1 + ABS(pobj)));
|
|
212
219
|
mu_assert_less("Gap ERROR", ABS(gap - info->gap), 1e-7 * (1 + ABS(gap)));
|
|
213
220
|
mu_assert_less("Primal obj ERROR", ABS(pobj - info->pobj),
|
|
214
221
|
1e-9 * (1 + ABS(pobj)));
|