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
data/vendor/scs/src/ctrlc.c
CHANGED
|
@@ -33,49 +33,92 @@ int scs_is_interrupted(void) {
|
|
|
33
33
|
#elif (defined _WIN32 || _WIN64 || defined _WINDLL)
|
|
34
34
|
#include <windows.h>
|
|
35
35
|
|
|
36
|
-
static
|
|
36
|
+
static volatile LONG int_detected;
|
|
37
|
+
static INIT_ONCE ctrlc_init_once = INIT_ONCE_STATIC_INIT;
|
|
38
|
+
static CRITICAL_SECTION ctrlc_cs;
|
|
39
|
+
static int listener_count = 0;
|
|
40
|
+
|
|
41
|
+
static BOOL CALLBACK init_ctrlc_cs(PINIT_ONCE once, PVOID param, PVOID *ctx) {
|
|
42
|
+
(void)once;
|
|
43
|
+
(void)param;
|
|
44
|
+
(void)ctx;
|
|
45
|
+
InitializeCriticalSection(&ctrlc_cs);
|
|
46
|
+
return TRUE;
|
|
47
|
+
}
|
|
48
|
+
|
|
37
49
|
static BOOL WINAPI scs_handle_ctrlc(DWORD dwCtrlType) {
|
|
38
50
|
if (dwCtrlType != CTRL_C_EVENT) {
|
|
39
51
|
return FALSE;
|
|
40
52
|
}
|
|
41
|
-
int_detected
|
|
53
|
+
InterlockedExchange(&int_detected, 1);
|
|
42
54
|
return TRUE;
|
|
43
55
|
}
|
|
44
56
|
|
|
45
57
|
void scs_start_interrupt_listener(void) {
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
InitOnceExecuteOnce(&ctrlc_init_once, init_ctrlc_cs, NULL, NULL);
|
|
59
|
+
EnterCriticalSection(&ctrlc_cs);
|
|
60
|
+
if (listener_count == 0) {
|
|
61
|
+
InterlockedExchange(&int_detected, 0);
|
|
62
|
+
SetConsoleCtrlHandler(scs_handle_ctrlc, TRUE);
|
|
63
|
+
}
|
|
64
|
+
listener_count++;
|
|
65
|
+
LeaveCriticalSection(&ctrlc_cs);
|
|
48
66
|
}
|
|
49
67
|
|
|
50
68
|
void scs_end_interrupt_listener(void) {
|
|
51
|
-
|
|
69
|
+
InitOnceExecuteOnce(&ctrlc_init_once, init_ctrlc_cs, NULL, NULL);
|
|
70
|
+
EnterCriticalSection(&ctrlc_cs);
|
|
71
|
+
if (listener_count > 0) {
|
|
72
|
+
listener_count--;
|
|
73
|
+
if (listener_count == 0) {
|
|
74
|
+
SetConsoleCtrlHandler(scs_handle_ctrlc, FALSE);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
LeaveCriticalSection(&ctrlc_cs);
|
|
52
78
|
}
|
|
53
79
|
|
|
54
80
|
int scs_is_interrupted(void) {
|
|
55
|
-
return int_detected;
|
|
81
|
+
return (int)InterlockedCompareExchange(&int_detected, 0, 0);
|
|
56
82
|
}
|
|
57
83
|
|
|
58
84
|
#else /* Unix */
|
|
59
85
|
|
|
60
86
|
#include <signal.h>
|
|
61
|
-
|
|
62
|
-
|
|
87
|
+
#include <pthread.h>
|
|
88
|
+
|
|
89
|
+
static volatile sig_atomic_t int_detected;
|
|
90
|
+
static struct sigaction oact;
|
|
91
|
+
static pthread_mutex_t ctrlc_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
92
|
+
static int listener_count = 0;
|
|
93
|
+
|
|
63
94
|
static void scs_handle_ctrlc(int dummy) {
|
|
64
95
|
int_detected = dummy ? dummy : -1;
|
|
65
96
|
}
|
|
66
97
|
|
|
67
98
|
void scs_start_interrupt_listener(void) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
99
|
+
pthread_mutex_lock(&ctrlc_mutex);
|
|
100
|
+
if (listener_count == 0) {
|
|
101
|
+
struct sigaction act;
|
|
102
|
+
int_detected = 0;
|
|
103
|
+
act.sa_flags = 0;
|
|
104
|
+
sigemptyset(&act.sa_mask);
|
|
105
|
+
act.sa_handler = scs_handle_ctrlc;
|
|
106
|
+
sigaction(SIGINT, &act, &oact);
|
|
107
|
+
}
|
|
108
|
+
listener_count++;
|
|
109
|
+
pthread_mutex_unlock(&ctrlc_mutex);
|
|
74
110
|
}
|
|
75
111
|
|
|
76
112
|
void scs_end_interrupt_listener(void) {
|
|
77
|
-
|
|
78
|
-
|
|
113
|
+
pthread_mutex_lock(&ctrlc_mutex);
|
|
114
|
+
if (listener_count > 0) {
|
|
115
|
+
listener_count--;
|
|
116
|
+
if (listener_count == 0) {
|
|
117
|
+
struct sigaction act;
|
|
118
|
+
sigaction(SIGINT, &oact, &act);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
pthread_mutex_unlock(&ctrlc_mutex);
|
|
79
122
|
}
|
|
80
123
|
|
|
81
124
|
int scs_is_interrupted(void) {
|
data/vendor/scs/src/exp_cone.c
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Exponential cone projection via Newton's method.
|
|
3
|
+
* Handles both primal and dual exponential cones using Moreau decomposition.
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
#include "cones.h"
|
|
2
7
|
#include "glbopts.h"
|
|
3
8
|
#include "linalg.h"
|
|
@@ -25,14 +30,29 @@ static inline void _copy(scs_float *dest, const scs_float *src) {
|
|
|
25
30
|
dest[2] = src[2];
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
static inline scs_float norm_diff_sq_3(const scs_float *a, const scs_float *b) {
|
|
34
|
+
scs_float d0 = a[0] - b[0];
|
|
35
|
+
scs_float d1 = a[1] - b[1];
|
|
36
|
+
scs_float d2 = a[2] - b[2];
|
|
37
|
+
return d0 * d0 + d1 * d1 + d2 * d2;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* As defined in Friberg, 2021 (multiplied by positive polynomial). */
|
|
41
|
+
static scs_float hfun_f(const scs_float *v0, scs_float rho) {
|
|
42
|
+
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
|
43
|
+
scs_float exprho = EXPF(rho);
|
|
44
|
+
scs_float expnegrho = 1.0 / exprho; /* EXPF(-rho) == 1/EXPF(rho) */
|
|
45
|
+
|
|
46
|
+
return ((rho - 1) * r0 + s0) * exprho - (r0 - rho * s0) * expnegrho -
|
|
47
|
+
(rho * (rho - 1) + 1) * t0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static void hfun_fd(const scs_float *v0, scs_float rho, scs_float *f,
|
|
51
|
+
scs_float *df) {
|
|
31
52
|
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
|
32
53
|
scs_float exprho = EXPF(rho);
|
|
33
|
-
scs_float expnegrho = EXPF(-rho)
|
|
54
|
+
scs_float expnegrho = 1.0 / exprho; /* EXPF(-rho) == 1/EXPF(rho) */
|
|
34
55
|
|
|
35
|
-
/* Function value at v0 */
|
|
36
56
|
*f = ((rho - 1) * r0 + s0) * exprho - (r0 - rho * s0) * expnegrho -
|
|
37
57
|
(rho * (rho - 1) + 1) * t0;
|
|
38
58
|
|
|
@@ -47,14 +67,14 @@ static scs_float root_search_binary(const scs_float *v0, scs_float xl,
|
|
|
47
67
|
const scs_float EPS = 1e-12; /* looser tolerance for binary search */
|
|
48
68
|
const scs_int MAXITER = 40;
|
|
49
69
|
scs_int i;
|
|
50
|
-
scs_float x_plus = x, f
|
|
70
|
+
scs_float x_plus = x, f;
|
|
51
71
|
|
|
52
72
|
#if VERBOSITY > 0
|
|
53
73
|
scs_printf("Exp cone: Newton method failed, resorting to binary search.\n");
|
|
54
74
|
#endif
|
|
55
75
|
|
|
56
76
|
for (i = 0; i < MAXITER; i++) {
|
|
57
|
-
|
|
77
|
+
f = hfun_f(v0, x);
|
|
58
78
|
|
|
59
79
|
if (f < 0.0) {
|
|
60
80
|
xl = x;
|
|
@@ -88,7 +108,7 @@ static scs_float root_search_newton(const scs_float *v0, scs_float xl,
|
|
|
88
108
|
scs_int i;
|
|
89
109
|
|
|
90
110
|
for (i = 0; i < MAXITER; i++) {
|
|
91
|
-
|
|
111
|
+
hfun_fd(v0, x, &f, &df);
|
|
92
112
|
|
|
93
113
|
if (ABS(f) <= EPS) { /* root found */
|
|
94
114
|
break;
|
|
@@ -145,52 +165,52 @@ static scs_float root_search_newton(const scs_float *v0, scs_float xl,
|
|
|
145
165
|
static scs_float proj_primal_exp_cone_heuristic(const scs_float *v0,
|
|
146
166
|
scs_float *vp) {
|
|
147
167
|
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
|
148
|
-
scs_float
|
|
168
|
+
scs_float dist_sq, tp, newdist_sq;
|
|
149
169
|
|
|
150
170
|
/* Perspective boundary */
|
|
151
171
|
vp[2] = MAX(t0, 0.0);
|
|
152
172
|
vp[1] = 0.0;
|
|
153
173
|
vp[0] = MIN(r0, 0.0);
|
|
154
|
-
|
|
174
|
+
dist_sq = norm_diff_sq_3(v0, vp);
|
|
155
175
|
|
|
156
176
|
/* Perspective interior */
|
|
157
177
|
if (s0 > 0.0) {
|
|
158
178
|
tp = MAX(t0, s0 * EXPF(r0 / s0));
|
|
159
|
-
|
|
160
|
-
if (
|
|
179
|
+
newdist_sq = (tp - t0) * (tp - t0);
|
|
180
|
+
if (newdist_sq < dist_sq) {
|
|
161
181
|
vp[2] = tp;
|
|
162
182
|
vp[1] = s0;
|
|
163
183
|
vp[0] = r0;
|
|
164
|
-
|
|
184
|
+
dist_sq = newdist_sq;
|
|
165
185
|
}
|
|
166
186
|
}
|
|
167
|
-
return
|
|
187
|
+
return dist_sq;
|
|
168
188
|
}
|
|
169
189
|
|
|
170
190
|
/* Try heuristic (cheap) projection for polar cone */
|
|
171
191
|
static scs_float proj_polar_exp_cone_heuristic(const scs_float *v0,
|
|
172
192
|
scs_float *vd) {
|
|
173
193
|
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
|
174
|
-
scs_float
|
|
194
|
+
scs_float dist_sq, td, newdist_sq;
|
|
175
195
|
|
|
176
196
|
/* Perspective boundary */
|
|
177
197
|
vd[2] = MIN(t0, 0.0);
|
|
178
198
|
vd[1] = MIN(s0, 0.0);
|
|
179
199
|
vd[0] = 0.0;
|
|
180
|
-
|
|
200
|
+
dist_sq = norm_diff_sq_3(v0, vd);
|
|
181
201
|
|
|
182
202
|
/* Perspective interior */
|
|
183
203
|
if (r0 > 0.0) {
|
|
184
204
|
td = MIN(t0, -r0 * EXPF(s0 / r0 - 1.0));
|
|
185
|
-
|
|
186
|
-
if (
|
|
205
|
+
newdist_sq = (t0 - td) * (t0 - td);
|
|
206
|
+
if (newdist_sq < dist_sq) {
|
|
187
207
|
vd[2] = td;
|
|
188
208
|
vd[1] = s0;
|
|
189
209
|
vd[0] = r0;
|
|
190
|
-
|
|
210
|
+
dist_sq = newdist_sq;
|
|
191
211
|
}
|
|
192
212
|
}
|
|
193
|
-
return
|
|
213
|
+
return dist_sq;
|
|
194
214
|
}
|
|
195
215
|
|
|
196
216
|
static scs_float ppsi(const scs_float *v0) {
|
|
@@ -238,18 +258,18 @@ static scs_float domega(scs_float rho) {
|
|
|
238
258
|
}
|
|
239
259
|
|
|
240
260
|
/* Generate upper and lower search bounds for root of hfun */
|
|
241
|
-
static void exp_search_bracket(const scs_float *v0, scs_float
|
|
242
|
-
scs_float
|
|
261
|
+
static void exp_search_bracket(const scs_float *v0, scs_float pdist_sq,
|
|
262
|
+
scs_float ddist_sq, scs_float *low_out,
|
|
243
263
|
scs_float *upr_out) {
|
|
244
264
|
scs_float t0 = v0[2], s0 = v0[1], r0 = v0[0];
|
|
245
265
|
scs_float baselow = -EXP_CONE_INFINITY_VALUE;
|
|
246
266
|
scs_float baseupr = EXP_CONE_INFINITY_VALUE;
|
|
247
267
|
scs_float low = -EXP_CONE_INFINITY_VALUE;
|
|
248
268
|
scs_float upr = EXP_CONE_INFINITY_VALUE;
|
|
249
|
-
scs_float Dp, Dd, curbnd, fl, fu,
|
|
269
|
+
scs_float Dp, Dd, curbnd, fl, fu, tpu, tdl, sgn, val;
|
|
250
270
|
|
|
251
|
-
Dp = SQRTF(
|
|
252
|
-
Dd = SQRTF(
|
|
271
|
+
Dp = SQRTF(MAX(pdist_sq - MIN(s0, 0.0) * MIN(s0, 0.0), 0.0));
|
|
272
|
+
Dd = SQRTF(MAX(ddist_sq - MIN(r0, 0.0) * MIN(r0, 0.0), 0.0));
|
|
253
273
|
|
|
254
274
|
if (t0 > 0.0) {
|
|
255
275
|
curbnd = LOGF(t0 / ppsi(v0));
|
|
@@ -286,8 +306,8 @@ static void exp_search_bracket(const scs_float *v0, scs_float pdist,
|
|
|
286
306
|
upr = _clip(MAX(low, upr), baselow, baseupr);
|
|
287
307
|
|
|
288
308
|
if (low != upr) {
|
|
289
|
-
|
|
290
|
-
|
|
309
|
+
fl = hfun_f(v0, low);
|
|
310
|
+
fu = hfun_f(v0, upr);
|
|
291
311
|
|
|
292
312
|
if (fl * fu > 0.0) {
|
|
293
313
|
if (ABS(fl) < ABS(fu)) {
|
|
@@ -307,21 +327,21 @@ static scs_float proj_sol_primal_exp_cone(const scs_float *v0, scs_float rho,
|
|
|
307
327
|
scs_float *vp) {
|
|
308
328
|
scs_float linrho = (rho - 1.0) * v0[0] + v0[1];
|
|
309
329
|
scs_float exprho = EXPF(rho);
|
|
310
|
-
scs_float quadrho,
|
|
330
|
+
scs_float quadrho, dist_sq;
|
|
311
331
|
|
|
312
332
|
if (linrho > 0.0 && _isfinite(exprho)) {
|
|
313
333
|
quadrho = rho * (rho - 1.0) + 1.0;
|
|
314
334
|
vp[2] = exprho * linrho / quadrho;
|
|
315
335
|
vp[1] = linrho / quadrho;
|
|
316
336
|
vp[0] = rho * linrho / quadrho;
|
|
317
|
-
|
|
337
|
+
dist_sq = norm_diff_sq_3(vp, v0);
|
|
318
338
|
} else {
|
|
319
339
|
vp[2] = EXP_CONE_INFINITY_VALUE;
|
|
320
340
|
vp[1] = 0.0;
|
|
321
341
|
vp[0] = 0.0;
|
|
322
|
-
|
|
342
|
+
dist_sq = EXP_CONE_INFINITY_VALUE;
|
|
323
343
|
}
|
|
324
|
-
return
|
|
344
|
+
return dist_sq;
|
|
325
345
|
}
|
|
326
346
|
|
|
327
347
|
/* convert from rho to polar projection */
|
|
@@ -329,21 +349,21 @@ static scs_float proj_sol_polar_exp_cone(const scs_float *v0, scs_float rho,
|
|
|
329
349
|
scs_float *vd) {
|
|
330
350
|
scs_float linrho = v0[0] - rho * v0[1];
|
|
331
351
|
scs_float exprho = EXPF(-rho);
|
|
332
|
-
scs_float quadrho,
|
|
352
|
+
scs_float quadrho, dist_sq;
|
|
333
353
|
|
|
334
354
|
if (linrho > 0.0 && _isfinite(exprho)) {
|
|
335
355
|
quadrho = rho * (rho - 1.0) + 1.0;
|
|
336
356
|
vd[2] = -exprho * linrho / quadrho;
|
|
337
357
|
vd[1] = (1.0 - rho) * linrho / quadrho;
|
|
338
358
|
vd[0] = linrho / quadrho;
|
|
339
|
-
|
|
359
|
+
dist_sq = norm_diff_sq_3(v0, vd);
|
|
340
360
|
} else {
|
|
341
361
|
vd[2] = -EXP_CONE_INFINITY_VALUE;
|
|
342
362
|
vd[1] = 0.0;
|
|
343
363
|
vd[0] = 0.0;
|
|
344
|
-
|
|
364
|
+
dist_sq = EXP_CONE_INFINITY_VALUE;
|
|
345
365
|
}
|
|
346
|
-
return
|
|
366
|
+
return dist_sq;
|
|
347
367
|
}
|
|
348
368
|
|
|
349
369
|
/* Project onto primal or dual exponential cone, performed in-place.
|
|
@@ -352,7 +372,7 @@ static scs_float proj_sol_polar_exp_cone(const scs_float *v0, scs_float rho,
|
|
|
352
372
|
*/
|
|
353
373
|
scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal) {
|
|
354
374
|
scs_float TOL = 1e-8; /* pow(1e-10, 2.0 / 3.0); */
|
|
355
|
-
scs_float xl, xh,
|
|
375
|
+
scs_float xl, xh, pdist_sq, ddist_sq, err, rho, dist_hat_sq;
|
|
356
376
|
scs_float vp[3], vd[3], v_hat[3];
|
|
357
377
|
scs_int opt;
|
|
358
378
|
|
|
@@ -366,8 +386,8 @@ scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal) {
|
|
|
366
386
|
v0[2] *= -1.0;
|
|
367
387
|
}
|
|
368
388
|
|
|
369
|
-
|
|
370
|
-
|
|
389
|
+
pdist_sq = proj_primal_exp_cone_heuristic(v0, vp);
|
|
390
|
+
ddist_sq = proj_polar_exp_cone_heuristic(v0, vd);
|
|
371
391
|
|
|
372
392
|
err = ABS(vp[0] + vd[0] - v0[0]);
|
|
373
393
|
err = MAX(err, ABS(vp[1] + vd[1] - v0[1]));
|
|
@@ -377,45 +397,45 @@ scs_float SCS(proj_pd_exp_cone)(scs_float *v0, scs_int primal) {
|
|
|
377
397
|
* or optimality conditions are satisfied
|
|
378
398
|
*/
|
|
379
399
|
opt = (v0[1] <= 0.0 && v0[0] <= 0.0);
|
|
380
|
-
opt |= (MIN(
|
|
400
|
+
opt |= (MIN(pdist_sq, ddist_sq) <= TOL * TOL);
|
|
381
401
|
opt |= (err <= TOL && SCS(dot)(vp, vd, 3) <= TOL);
|
|
382
402
|
|
|
383
403
|
if (opt) {
|
|
384
404
|
if (primal) {
|
|
385
405
|
_copy(v0, vp);
|
|
386
|
-
return
|
|
406
|
+
return SQRTF(pdist_sq);
|
|
387
407
|
}
|
|
388
408
|
/* Polar cone -> dual cone. */
|
|
389
409
|
v0[0] = -vd[0];
|
|
390
410
|
v0[1] = -vd[1];
|
|
391
411
|
v0[2] = -vd[2];
|
|
392
|
-
return
|
|
412
|
+
return SQRTF(ddist_sq);
|
|
393
413
|
}
|
|
394
414
|
|
|
395
|
-
exp_search_bracket(v0,
|
|
415
|
+
exp_search_bracket(v0, pdist_sq, ddist_sq, &xl, &xh);
|
|
396
416
|
rho = root_search_newton(v0, xl, xh, 0.5 * (xl + xh));
|
|
397
417
|
|
|
398
418
|
if (primal) {
|
|
399
419
|
/* Primal cone projection. */
|
|
400
|
-
|
|
401
|
-
if (
|
|
420
|
+
dist_hat_sq = proj_sol_primal_exp_cone(v0, rho, v_hat);
|
|
421
|
+
if (dist_hat_sq <= pdist_sq) {
|
|
402
422
|
_copy(vp, v_hat);
|
|
403
|
-
|
|
423
|
+
pdist_sq = dist_hat_sq;
|
|
404
424
|
}
|
|
405
425
|
_copy(v0, vp);
|
|
406
|
-
return
|
|
426
|
+
return SQRTF(pdist_sq);
|
|
407
427
|
}
|
|
408
428
|
|
|
409
429
|
/* Polar cone projection. */
|
|
410
|
-
|
|
411
|
-
if (
|
|
430
|
+
dist_hat_sq = proj_sol_polar_exp_cone(v0, rho, v_hat);
|
|
431
|
+
if (dist_hat_sq <= ddist_sq) {
|
|
412
432
|
_copy(vd, v_hat);
|
|
413
|
-
|
|
433
|
+
ddist_sq = dist_hat_sq;
|
|
414
434
|
}
|
|
415
435
|
|
|
416
436
|
/* Polar cone -> dual cone. */
|
|
417
437
|
v0[0] = -vd[0];
|
|
418
438
|
v0[1] = -vd[1];
|
|
419
439
|
v0[2] = -vd[2];
|
|
420
|
-
return
|
|
440
|
+
return SQRTF(ddist_sq);
|
|
421
441
|
}
|
data/vendor/scs/src/linalg.c
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Dense linear algebra operations: norms, dot products, scaling, axpy.
|
|
3
|
+
* Has two implementations: a plain C fallback and an optimized BLAS version
|
|
4
|
+
* (selected at compile time via USE_LAPACK).
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
#include "linalg.h"
|
|
2
8
|
#include "scs_blas.h"
|
|
3
9
|
#include <math.h>
|
|
@@ -136,8 +142,9 @@ scs_float SCS(dot)(const scs_float *x, const scs_float *y, scs_int len) {
|
|
|
136
142
|
|
|
137
143
|
/* ||v||_2^2 */
|
|
138
144
|
scs_float SCS(norm_sq)(const scs_float *v, scs_int len) {
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
blas_int bone = 1;
|
|
146
|
+
blas_int blen = (blas_int)len;
|
|
147
|
+
return BLAS(dot)(&blen, v, &bone, v, &bone);
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
/* ||v||_2 */
|
|
@@ -163,6 +170,18 @@ scs_float SCS(norm_inf)(const scs_float *a, scs_int len) {
|
|
|
163
170
|
if (len <= 0) {
|
|
164
171
|
return 0.0;
|
|
165
172
|
}
|
|
173
|
+
/* For short vectors the BLAS function-call overhead (pointer args,
|
|
174
|
+
* Fortran ABI, 1-based index return) exceeds the arithmetic cost.
|
|
175
|
+
* Use a scalar loop below a threshold. */
|
|
176
|
+
if (len <= 16) {
|
|
177
|
+
scs_float mx = 0.0, tmp;
|
|
178
|
+
scs_int i;
|
|
179
|
+
for (i = 0; i < len; ++i) {
|
|
180
|
+
tmp = ABS(a[i]);
|
|
181
|
+
if (tmp > mx) mx = tmp;
|
|
182
|
+
}
|
|
183
|
+
return mx;
|
|
184
|
+
}
|
|
166
185
|
idx = (scs_int)BLASI(amax)(&blen, a, &bone);
|
|
167
186
|
/* Returned idx is 1-based. */
|
|
168
187
|
return ABS(a[idx - 1]);
|
data/vendor/scs/src/normalize.c
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Problem data normalization (equilibration) of b and c vectors,
|
|
3
|
+
* and solution normalization/un-normalization routines.
|
|
4
|
+
* Matrix normalization (A, P) is in linsys/scs_matrix.c.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
#include "normalize.h"
|
|
2
8
|
|
|
3
9
|
#include "linalg.h"
|
|
@@ -37,13 +43,22 @@ void SCS(normalize_b_c)(ScsScaling *scal, scs_float *b, scs_float *c) {
|
|
|
37
43
|
b[i] *= scal->D[i];
|
|
38
44
|
}
|
|
39
45
|
|
|
40
|
-
/*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
/* sigma comes from the stacked-operator equilibration (the tau-slot
|
|
47
|
+
* scaling computed jointly with D, E by normalize_a_p), replacing the
|
|
48
|
+
* old one-shot clamped max-norm heuristic which left problems with
|
|
49
|
+
* extreme cost/rhs magnitudes badly imbalanced. Fall back to the
|
|
50
|
+
* heuristic if unset (defensive; normalize_a_p always sets it). */
|
|
51
|
+
if (scal->tau_scale > 0.) {
|
|
52
|
+
sigma = scal->tau_scale;
|
|
53
|
+
} else {
|
|
54
|
+
nm_c = SCS(norm_inf)(c, scal->n);
|
|
55
|
+
nm_b = SCS(norm_inf)(b, scal->m);
|
|
56
|
+
sigma = MAX(nm_c, nm_b);
|
|
57
|
+
sigma = sigma < MIN_NORMALIZATION_FACTOR ? 1.0 : sigma;
|
|
58
|
+
sigma =
|
|
59
|
+
sigma > MAX_NORMALIZATION_FACTOR ? MAX_NORMALIZATION_FACTOR : sigma;
|
|
60
|
+
sigma = SAFEDIV_POS(1.0, sigma);
|
|
61
|
+
}
|
|
47
62
|
|
|
48
63
|
/* Scale b, c */
|
|
49
64
|
SCS(scale_array)(c, sigma, scal->n);
|
|
@@ -62,10 +77,9 @@ void SCS(normalize_sol)(ScsScaling *scal, ScsSolution *sol) {
|
|
|
62
77
|
for (i = 0; i < scal->n; ++i) {
|
|
63
78
|
sol->x[i] /= (E[i] / scal->dual_scale);
|
|
64
79
|
}
|
|
80
|
+
/* Fuse the y and s loops: both index D[i], halving D reads. */
|
|
65
81
|
for (i = 0; i < scal->m; ++i) {
|
|
66
82
|
sol->y[i] /= (D[i] / scal->primal_scale);
|
|
67
|
-
}
|
|
68
|
-
for (i = 0; i < scal->m; ++i) {
|
|
69
83
|
sol->s[i] *= (D[i] * scal->dual_scale);
|
|
70
84
|
}
|
|
71
85
|
}
|
|
@@ -77,26 +91,10 @@ void SCS(un_normalize_sol)(ScsScaling *scal, ScsSolution *sol) {
|
|
|
77
91
|
for (i = 0; i < scal->n; ++i) {
|
|
78
92
|
sol->x[i] *= (E[i] / scal->dual_scale);
|
|
79
93
|
}
|
|
94
|
+
/* Fuse the y and s loops: both index D[i], halving D reads. */
|
|
80
95
|
for (i = 0; i < scal->m; ++i) {
|
|
81
96
|
sol->y[i] *= (D[i] / scal->primal_scale);
|
|
82
|
-
}
|
|
83
|
-
for (i = 0; i < scal->m; ++i) {
|
|
84
97
|
sol->s[i] /= (D[i] * scal->dual_scale);
|
|
85
98
|
}
|
|
86
99
|
}
|
|
87
100
|
|
|
88
|
-
void SCS(un_normalize_primal)(ScsScaling *scal, scs_float *r) {
|
|
89
|
-
scs_int i;
|
|
90
|
-
scs_float *D = scal->D;
|
|
91
|
-
for (i = 0; i < scal->m; ++i) {
|
|
92
|
-
r[i] /= (D[i] * scal->dual_scale);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
void SCS(un_normalize_dual)(ScsScaling *scal, scs_float *r) {
|
|
97
|
-
scs_int i;
|
|
98
|
-
scs_float *E = scal->E;
|
|
99
|
-
for (i = 0; i < scal->n; ++i) {
|
|
100
|
-
r[i] /= (E[i] * scal->primal_scale);
|
|
101
|
-
}
|
|
102
|
-
}
|