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
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Small QP with a fully dense A matrix.
|
|
3
|
+
* This is the regime where the dense direct backend (Gram + Cholesky)
|
|
4
|
+
* should outperform the sparse direct backend (QDLDL), because QDLDL
|
|
5
|
+
* fill-in destroys sparsity while the dense backend uses optimized BLAS.
|
|
6
|
+
*
|
|
7
|
+
* n = 20 variables, m = 200 constraints, A fully dense (col_nnz = m).
|
|
8
|
+
*/
|
|
9
|
+
#include "glbopts.h"
|
|
10
|
+
#include "minunit.h"
|
|
11
|
+
#include "problem_utils.h"
|
|
12
|
+
#include "scs.h"
|
|
13
|
+
#include "util.h"
|
|
14
|
+
|
|
15
|
+
static const char *dense_qp(void) {
|
|
16
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
17
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
18
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
19
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
20
|
+
ScsSolution *opt_sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
21
|
+
ScsInfo info = {0};
|
|
22
|
+
scs_float p_f = 0.1;
|
|
23
|
+
int seed = 5678;
|
|
24
|
+
scs_int n = 20;
|
|
25
|
+
scs_int m = 200;
|
|
26
|
+
/* col_nnz = m makes A fully dense */
|
|
27
|
+
scs_int col_nnz = m;
|
|
28
|
+
scs_int nnz = n * col_nnz;
|
|
29
|
+
scs_int exitflag;
|
|
30
|
+
scs_float perr, derr;
|
|
31
|
+
scs_int success;
|
|
32
|
+
const char *fail;
|
|
33
|
+
|
|
34
|
+
k->z = (scs_int)floor(m * p_f);
|
|
35
|
+
k->l = m - k->z;
|
|
36
|
+
|
|
37
|
+
d->m = m;
|
|
38
|
+
d->n = n;
|
|
39
|
+
d->P = SCS_NULL;
|
|
40
|
+
gen_random_prob_data(nnz, col_nnz, d, k, opt_sol, seed);
|
|
41
|
+
scs_set_default_settings(stgs);
|
|
42
|
+
stgs->eps_abs = 1e-5;
|
|
43
|
+
stgs->eps_rel = 1e-5;
|
|
44
|
+
|
|
45
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
46
|
+
|
|
47
|
+
perr = SCS(dot)(d->c, sol->x, d->n) - SCS(dot)(d->c, opt_sol->x, d->n);
|
|
48
|
+
derr = -SCS(dot)(d->b, sol->y, d->m) + SCS(dot)(d->b, opt_sol->y, d->m);
|
|
49
|
+
scs_printf("true obj %4e\n", SCS(dot)(d->c, opt_sol->x, d->n));
|
|
50
|
+
scs_printf("primal obj error %4e\n", perr);
|
|
51
|
+
scs_printf("dual obj error %4e\n", derr);
|
|
52
|
+
|
|
53
|
+
success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
|
|
54
|
+
|
|
55
|
+
mu_assert("dense_qp: SCS failed to produce outputflag SCS_SOLVED", success);
|
|
56
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
57
|
+
SCS(free_data)(d);
|
|
58
|
+
SCS(free_cone)(k);
|
|
59
|
+
SCS(free_sol)(sol);
|
|
60
|
+
SCS(free_sol)(opt_sol);
|
|
61
|
+
scs_free(stgs);
|
|
62
|
+
|
|
63
|
+
return fail;
|
|
64
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "util.h"
|
|
8
8
|
|
|
9
9
|
static const char *hs21_tiny_qp(void) {
|
|
10
|
+
scs_int cold_iter;
|
|
10
11
|
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
11
12
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
12
13
|
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
@@ -83,12 +84,15 @@ static const char *hs21_tiny_qp(void) {
|
|
|
83
84
|
mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED",
|
|
84
85
|
success);
|
|
85
86
|
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
87
|
+
cold_iter = info.iter;
|
|
86
88
|
|
|
87
89
|
/* test warm-starting */
|
|
88
90
|
stgs->warm_start = 1;
|
|
89
91
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
90
|
-
/*
|
|
91
|
-
|
|
92
|
+
/* relative to the cold solve: an absolute cap encodes the iteration
|
|
93
|
+
* count of one particular metric and breaks whenever the scaling
|
|
94
|
+
* changes, even though the warm solve is correct */
|
|
95
|
+
mu_assert("hs21_tiny_qp: warm-start failure", info.iter <= cold_iter / 2);
|
|
92
96
|
success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
|
|
93
97
|
|
|
94
98
|
mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
/* test read / write logic */
|
|
11
11
|
static const char *hs21_tiny_qp_rw(void) {
|
|
12
|
+
scs_int cold_iter;
|
|
12
13
|
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
13
14
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
14
15
|
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
@@ -74,6 +75,7 @@ static const char *hs21_tiny_qp_rw(void) {
|
|
|
74
75
|
|
|
75
76
|
stgs->write_data_filename = "hs21_tiny_qp";
|
|
76
77
|
stgs->max_iters = 1;
|
|
78
|
+
stgs->time_limit_secs = 123.;
|
|
77
79
|
|
|
78
80
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
79
81
|
|
|
@@ -90,6 +92,9 @@ static const char *hs21_tiny_qp_rw(void) {
|
|
|
90
92
|
return "Data read failure, exit.\n";
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
mu_assert("hs21_tiny_qp: time_limit_secs failed to round-trip",
|
|
96
|
+
ABS(stgs->time_limit_secs - 123.) < 1e-12);
|
|
97
|
+
|
|
93
98
|
stgs->max_iters = 1000;
|
|
94
99
|
/* solve with read data */
|
|
95
100
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
@@ -105,12 +110,15 @@ static const char *hs21_tiny_qp_rw(void) {
|
|
|
105
110
|
mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED",
|
|
106
111
|
success);
|
|
107
112
|
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
113
|
+
cold_iter = info.iter;
|
|
108
114
|
|
|
109
115
|
/* test warm-starting */
|
|
110
116
|
stgs->warm_start = 1;
|
|
111
117
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
112
|
-
/*
|
|
113
|
-
|
|
118
|
+
/* relative to the cold solve: an absolute cap encodes the iteration
|
|
119
|
+
* count of one particular metric and breaks whenever the scaling
|
|
120
|
+
* changes, even though the warm solve is correct */
|
|
121
|
+
mu_assert("hs21_tiny_qp_rw: warm-start failure", info.iter <= cold_iter / 2);
|
|
114
122
|
success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
|
|
115
123
|
|
|
116
124
|
mu_assert("hs21_tiny_qp: SCS failed to produce outputflag SCS_SOLVED",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#include "glbopts.h"
|
|
2
|
+
#include "linalg.h"
|
|
3
|
+
#include "minunit.h"
|
|
4
|
+
#include "problem_utils.h"
|
|
5
|
+
#include "scs.h"
|
|
6
|
+
#include "util.h"
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Infeasible LP: x >= 1 AND x <= 0 (contradictory).
|
|
10
|
+
*
|
|
11
|
+
* SCS form: min c'x, Ax + s = b, s in K_nn (l=2)
|
|
12
|
+
* row 0: -x + s0 = -1, s0 >= 0 => x >= 1
|
|
13
|
+
* row 1: x + s1 = 0, s1 >= 0 => x <= 0
|
|
14
|
+
*
|
|
15
|
+
* A = [[-1], [1]], b = [-1, 0], c = [1], k->l = 2.
|
|
16
|
+
*/
|
|
17
|
+
static const char *infeasible_lp(void) {
|
|
18
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
19
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
20
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
21
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
22
|
+
ScsInfo info = {0};
|
|
23
|
+
scs_int exitflag;
|
|
24
|
+
const char *fail;
|
|
25
|
+
|
|
26
|
+
scs_float Ax[] = {-1.0, 1.0};
|
|
27
|
+
scs_int Ai[] = {0, 1};
|
|
28
|
+
scs_int Ap[] = {0, 2};
|
|
29
|
+
|
|
30
|
+
scs_float b[] = {-1.0, 0.0};
|
|
31
|
+
scs_float c[] = {1.0};
|
|
32
|
+
|
|
33
|
+
scs_int m = 2, n = 1;
|
|
34
|
+
|
|
35
|
+
d->m = m;
|
|
36
|
+
d->n = n;
|
|
37
|
+
d->b = b;
|
|
38
|
+
d->c = c;
|
|
39
|
+
|
|
40
|
+
d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
41
|
+
d->A->m = m;
|
|
42
|
+
d->A->n = n;
|
|
43
|
+
d->A->x = Ax;
|
|
44
|
+
d->A->i = Ai;
|
|
45
|
+
d->A->p = Ap;
|
|
46
|
+
|
|
47
|
+
k->l = m;
|
|
48
|
+
|
|
49
|
+
scs_set_default_settings(stgs);
|
|
50
|
+
stgs->eps_abs = 1e-6;
|
|
51
|
+
stgs->eps_rel = 1e-6;
|
|
52
|
+
stgs->eps_infeas = 1e-9;
|
|
53
|
+
|
|
54
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
55
|
+
|
|
56
|
+
mu_assert("infeasible_lp: expected SCS_INFEASIBLE",
|
|
57
|
+
exitflag == SCS_INFEASIBLE);
|
|
58
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
59
|
+
|
|
60
|
+
SCS(free_sol)(sol);
|
|
61
|
+
scs_free(d->A);
|
|
62
|
+
scs_free(k);
|
|
63
|
+
scs_free(stgs);
|
|
64
|
+
scs_free(d);
|
|
65
|
+
return fail;
|
|
66
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#include "glbopts.h"
|
|
2
|
+
#include "linalg.h"
|
|
3
|
+
#include "minunit.h"
|
|
4
|
+
#include "problem_utils.h"
|
|
5
|
+
#include "scs.h"
|
|
6
|
+
#include "util.h"
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Infeasible SOCP: (t, x) in SOC_2 AND t <= -1.
|
|
10
|
+
* Since SOC_2 requires t >= |x| >= 0, t <= -1 is infeasible.
|
|
11
|
+
*
|
|
12
|
+
* Variables [t, x] (n=2), m=3.
|
|
13
|
+
* Cone order: l=1 first, then q=[2].
|
|
14
|
+
* Row 0 (l=1): t + s0 = -1, s0 >= 0 => t <= -1
|
|
15
|
+
* Row 1 (q[0]): -t + s1 = 0 => s1 = t
|
|
16
|
+
* Row 2 (q[1]): -x + s2 = 0 => s2 = x
|
|
17
|
+
* => (t, x) in SOC_2 AND t <= -1: infeasible since SOC_2 requires t >= 0.
|
|
18
|
+
*
|
|
19
|
+
* A cols (CSC):
|
|
20
|
+
* col 0 (t): row 0 -> +1, row 1 -> -1
|
|
21
|
+
* col 1 (x): row 2 -> -1
|
|
22
|
+
*/
|
|
23
|
+
static const char *infeasible_socp(void) {
|
|
24
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
25
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
26
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
27
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
28
|
+
ScsInfo info = {0};
|
|
29
|
+
scs_int exitflag;
|
|
30
|
+
const char *fail;
|
|
31
|
+
|
|
32
|
+
scs_float Ax[] = {1.0, -1.0, -1.0};
|
|
33
|
+
scs_int Ai[] = {0, 1, 2};
|
|
34
|
+
scs_int Ap[] = {0, 2, 3};
|
|
35
|
+
|
|
36
|
+
scs_float b[] = {-1.0, 0.0, 0.0};
|
|
37
|
+
scs_float c[] = {1.0, 0.0};
|
|
38
|
+
|
|
39
|
+
scs_int q[] = {2};
|
|
40
|
+
scs_int m = 3, n = 2;
|
|
41
|
+
|
|
42
|
+
d->m = m;
|
|
43
|
+
d->n = n;
|
|
44
|
+
d->b = b;
|
|
45
|
+
d->c = c;
|
|
46
|
+
|
|
47
|
+
d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
48
|
+
d->A->m = m;
|
|
49
|
+
d->A->n = n;
|
|
50
|
+
d->A->x = Ax;
|
|
51
|
+
d->A->i = Ai;
|
|
52
|
+
d->A->p = Ap;
|
|
53
|
+
|
|
54
|
+
k->l = 1;
|
|
55
|
+
k->qsize = 1;
|
|
56
|
+
k->q = q;
|
|
57
|
+
|
|
58
|
+
scs_set_default_settings(stgs);
|
|
59
|
+
stgs->eps_abs = 1e-6;
|
|
60
|
+
stgs->eps_rel = 1e-6;
|
|
61
|
+
stgs->eps_infeas = 1e-9;
|
|
62
|
+
|
|
63
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
64
|
+
|
|
65
|
+
mu_assert("infeasible_socp: expected SCS_INFEASIBLE",
|
|
66
|
+
exitflag == SCS_INFEASIBLE);
|
|
67
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
68
|
+
|
|
69
|
+
SCS(free_sol)(sol);
|
|
70
|
+
scs_free(d->A);
|
|
71
|
+
scs_free(k);
|
|
72
|
+
scs_free(stgs);
|
|
73
|
+
scs_free(d);
|
|
74
|
+
return fail;
|
|
75
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#include "glbopts.h"
|
|
2
|
+
#include "linalg.h"
|
|
3
|
+
#include "minunit.h"
|
|
4
|
+
#include "problem_utils.h"
|
|
5
|
+
#include "scs.h"
|
|
6
|
+
#include "util.h"
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Test scs_update (b and/or c) for a simple LP.
|
|
10
|
+
*
|
|
11
|
+
* Base problem: min x s.t. x >= 2
|
|
12
|
+
* row 0: -x + s = -2, s >= 0 => x >= 2
|
|
13
|
+
* n=1, m=1, k->l=1
|
|
14
|
+
* A=[[-1]], b=[-2], c=[1]
|
|
15
|
+
* Optimal: x=2, obj=2.
|
|
16
|
+
*
|
|
17
|
+
* After scs_update(b=[-3]): x >= 3, obj=3.
|
|
18
|
+
* After scs_update(c=[2]): min 2x s.t. x >= 3, obj=6.
|
|
19
|
+
* After scs_update(b=[-2], c=[1]): back to original, obj=2.
|
|
20
|
+
*/
|
|
21
|
+
static const char *lp_update(void) {
|
|
22
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
23
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
24
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
25
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
26
|
+
ScsInfo info = {0};
|
|
27
|
+
scs_int exitflag;
|
|
28
|
+
scs_int success;
|
|
29
|
+
const char *fail;
|
|
30
|
+
|
|
31
|
+
scs_float Ax[] = {-1.0};
|
|
32
|
+
scs_int Ai[] = {0};
|
|
33
|
+
scs_int Ap[] = {0, 1};
|
|
34
|
+
|
|
35
|
+
scs_float b[] = {-2.0};
|
|
36
|
+
scs_float c[] = {1.0};
|
|
37
|
+
|
|
38
|
+
scs_int m = 1, n = 1;
|
|
39
|
+
|
|
40
|
+
d->m = m;
|
|
41
|
+
d->n = n;
|
|
42
|
+
d->b = b;
|
|
43
|
+
d->c = c;
|
|
44
|
+
|
|
45
|
+
d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
46
|
+
d->A->m = m;
|
|
47
|
+
d->A->n = n;
|
|
48
|
+
d->A->x = Ax;
|
|
49
|
+
d->A->i = Ai;
|
|
50
|
+
d->A->p = Ap;
|
|
51
|
+
|
|
52
|
+
k->l = m;
|
|
53
|
+
|
|
54
|
+
scs_set_default_settings(stgs);
|
|
55
|
+
stgs->eps_abs = 1e-6;
|
|
56
|
+
stgs->eps_rel = 1e-6;
|
|
57
|
+
|
|
58
|
+
ScsWork *w = scs_init(d, k, stgs);
|
|
59
|
+
mu_assert("lp_update: scs_init returned NULL", w != SCS_NULL);
|
|
60
|
+
|
|
61
|
+
/* base solve: min x s.t. x >= 2, expected obj=2 */
|
|
62
|
+
exitflag = scs_solve(w, sol, &info, 0);
|
|
63
|
+
success = exitflag == SCS_SOLVED && ABS(info.pobj - 2.0) < 1e-4;
|
|
64
|
+
mu_assert("lp_update: base solve failed", success);
|
|
65
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
66
|
+
if (fail) return fail;
|
|
67
|
+
|
|
68
|
+
/* update b: x >= 3, expected obj=3 */
|
|
69
|
+
b[0] = -3.0;
|
|
70
|
+
scs_update(w, b, SCS_NULL);
|
|
71
|
+
exitflag = scs_solve(w, sol, &info, 1);
|
|
72
|
+
success = exitflag == SCS_SOLVED && ABS(info.pobj - 3.0) < 1e-4;
|
|
73
|
+
mu_assert("lp_update: b-update solve failed", success);
|
|
74
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
75
|
+
if (fail) return fail;
|
|
76
|
+
|
|
77
|
+
/* update c: min 2x s.t. x >= 3, expected obj=6 */
|
|
78
|
+
c[0] = 2.0;
|
|
79
|
+
scs_update(w, SCS_NULL, c);
|
|
80
|
+
exitflag = scs_solve(w, sol, &info, 1);
|
|
81
|
+
success = exitflag == SCS_SOLVED && ABS(info.pobj - 6.0) < 1e-4;
|
|
82
|
+
mu_assert("lp_update: c-update solve failed", success);
|
|
83
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
84
|
+
if (fail) return fail;
|
|
85
|
+
|
|
86
|
+
/* update both b and c back to original: min x s.t. x >= 2, expected obj=2 */
|
|
87
|
+
b[0] = -2.0;
|
|
88
|
+
c[0] = 1.0;
|
|
89
|
+
scs_update(w, b, c);
|
|
90
|
+
exitflag = scs_solve(w, sol, &info, 1);
|
|
91
|
+
success = exitflag == SCS_SOLVED && ABS(info.pobj - 2.0) < 1e-4;
|
|
92
|
+
mu_assert("lp_update: b+c-update solve failed", success);
|
|
93
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
94
|
+
if (fail) return fail;
|
|
95
|
+
|
|
96
|
+
/* null/null update: no change to problem, result must be identical */
|
|
97
|
+
scs_update(w, SCS_NULL, SCS_NULL);
|
|
98
|
+
exitflag = scs_solve(w, sol, &info, 1);
|
|
99
|
+
success = exitflag == SCS_SOLVED && ABS(info.pobj - 2.0) < 1e-4;
|
|
100
|
+
mu_assert("lp_update: null-null update changed result", success);
|
|
101
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
102
|
+
|
|
103
|
+
scs_finish(w);
|
|
104
|
+
SCS(free_sol)(sol);
|
|
105
|
+
scs_free(d->A);
|
|
106
|
+
scs_free(k);
|
|
107
|
+
scs_free(stgs);
|
|
108
|
+
scs_free(d);
|
|
109
|
+
return fail;
|
|
110
|
+
}
|
|
@@ -173,8 +173,10 @@ static const char *qafiro_tiny_qp(void) {
|
|
|
173
173
|
stgs->warm_start = 0;
|
|
174
174
|
stgs->normalize = 0;
|
|
175
175
|
stgs->adaptive_scale = 0;
|
|
176
|
-
stgs->acceleration_lookback =
|
|
176
|
+
stgs->acceleration_lookback = 10;
|
|
177
177
|
stgs->acceleration_interval = 10;
|
|
178
|
+
stgs->acceleration_type_1 = 0;
|
|
179
|
+
stgs->acceleration_regularization = 1e-12;
|
|
178
180
|
stgs->log_csv_filename = "qafiro_tiny_qp.csv";
|
|
179
181
|
|
|
180
182
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "util.h"
|
|
9
9
|
|
|
10
10
|
static const char *rob_gauss_cov_est(void) {
|
|
11
|
+
scs_int cold_iter;
|
|
11
12
|
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
12
13
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
13
14
|
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
@@ -163,6 +164,7 @@ static const char *rob_gauss_cov_est(void) {
|
|
|
163
164
|
stgs->eps_infeas = 1e-9;
|
|
164
165
|
|
|
165
166
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
167
|
+
cold_iter = info.iter;
|
|
166
168
|
|
|
167
169
|
perr = SCS(dot)(d->c, sol->x, d->n) - opt;
|
|
168
170
|
derr = -SCS(dot)(d->b, sol->y, d->m) - opt;
|
|
@@ -178,11 +180,12 @@ static const char *rob_gauss_cov_est(void) {
|
|
|
178
180
|
if (fail)
|
|
179
181
|
return fail;
|
|
180
182
|
|
|
181
|
-
/* test warm-starting
|
|
183
|
+
/* test warm-starting: relative to the cold solve, so the bound stays
|
|
184
|
+
* meaningful when the metric (and hence the iteration count) changes */
|
|
182
185
|
stgs->warm_start = 1;
|
|
183
186
|
exitflag = scs(d, k, stgs, sol, &info);
|
|
184
|
-
|
|
185
|
-
|
|
187
|
+
mu_assert("rob_gauss_cov_est: warm-start failure",
|
|
188
|
+
info.iter <= cold_iter / 2);
|
|
186
189
|
success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
|
|
187
190
|
|
|
188
191
|
mu_assert("rob_gauss_cov_est: SCS failed to produce outputflag SCS_SOLVED",
|
|
@@ -331,6 +331,11 @@ static const char *small_qp(void) {
|
|
|
331
331
|
stgs->eps_abs = 1e-6;
|
|
332
332
|
stgs->eps_rel = 1e-6;
|
|
333
333
|
stgs->eps_infeas = 1e-10;
|
|
334
|
+
/* fixed metric for reproducible trajectories across platforms, matching
|
|
335
|
+
* the suite convention (adaptive dynamics have dedicated tests); with
|
|
336
|
+
* adaptive scaling on, this instance stalls on some architectures in
|
|
337
|
+
* the no-acceleration builds */
|
|
338
|
+
stgs->adaptive_scale = 0;
|
|
334
339
|
|
|
335
340
|
ScsWork *w = scs_init(d, k, stgs);
|
|
336
341
|
exitflag = scs_solve(w, sol, &info, 0);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#include "glbopts.h"
|
|
2
|
+
#include "linalg.h"
|
|
3
|
+
#include "minunit.h"
|
|
4
|
+
#include "problem_utils.h"
|
|
5
|
+
#include "scs.h"
|
|
6
|
+
#include "util.h"
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Test box cone projection on a simple LP (no P matrix).
|
|
10
|
+
*
|
|
11
|
+
* K_box = {(t, s) : bl_i * t <= s_i <= bu_i * t, t >= 0}
|
|
12
|
+
*
|
|
13
|
+
* Problem: minimize x1 + x2
|
|
14
|
+
* subject to -1 <= x1 <= 1
|
|
15
|
+
* -2 <= x2 <= 2
|
|
16
|
+
* Solution: x1 = -1, x2 = -2, obj = -3.
|
|
17
|
+
*
|
|
18
|
+
* SCS formulation: Ax + s = b, s in K_box
|
|
19
|
+
* k->bsize = 3 (t + x1 + x2)
|
|
20
|
+
* k->bl = [-1, -2], k->bu = [1, 2]
|
|
21
|
+
* Row 0 (t-slot): 0*x1 + 0*x2 + s[0] = 1 => t = 1
|
|
22
|
+
* Row 1 (x1-slot): -x1 + s[1] = 0 => s[1] = x1
|
|
23
|
+
* Row 2 (x2-slot): -x2 + s[2] = 0 => s[2] = x2
|
|
24
|
+
*
|
|
25
|
+
* A (CSC, 3x2):
|
|
26
|
+
* col 0 (x1): row 1 -> -1
|
|
27
|
+
* col 1 (x2): row 2 -> -1
|
|
28
|
+
*/
|
|
29
|
+
static const char *test_box_cone_lp(void) {
|
|
30
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
31
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
32
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
33
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
34
|
+
ScsInfo info = {0};
|
|
35
|
+
scs_int exitflag;
|
|
36
|
+
scs_float perr, derr;
|
|
37
|
+
scs_int success;
|
|
38
|
+
const char *fail;
|
|
39
|
+
|
|
40
|
+
scs_float opt = -3.0;
|
|
41
|
+
|
|
42
|
+
scs_float Ax[] = {-1.0, -1.0};
|
|
43
|
+
scs_int Ai[] = {1, 2};
|
|
44
|
+
scs_int Ap[] = {0, 1, 2};
|
|
45
|
+
|
|
46
|
+
scs_float b[] = {1.0, 0.0, 0.0};
|
|
47
|
+
scs_float c[] = {1.0, 1.0};
|
|
48
|
+
|
|
49
|
+
scs_float bl[] = {-1.0, -2.0};
|
|
50
|
+
scs_float bu[] = {1.0, 2.0};
|
|
51
|
+
|
|
52
|
+
scs_int m = 3, n = 2;
|
|
53
|
+
|
|
54
|
+
d->m = m;
|
|
55
|
+
d->n = n;
|
|
56
|
+
d->b = b;
|
|
57
|
+
d->c = c;
|
|
58
|
+
|
|
59
|
+
d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
60
|
+
d->A->m = m;
|
|
61
|
+
d->A->n = n;
|
|
62
|
+
d->A->x = Ax;
|
|
63
|
+
d->A->i = Ai;
|
|
64
|
+
d->A->p = Ap;
|
|
65
|
+
|
|
66
|
+
k->bsize = 3;
|
|
67
|
+
k->bl = bl;
|
|
68
|
+
k->bu = bu;
|
|
69
|
+
|
|
70
|
+
scs_set_default_settings(stgs);
|
|
71
|
+
stgs->eps_abs = 1e-6;
|
|
72
|
+
stgs->eps_rel = 1e-6;
|
|
73
|
+
|
|
74
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
75
|
+
|
|
76
|
+
perr = info.pobj - opt;
|
|
77
|
+
derr = info.dobj - opt;
|
|
78
|
+
|
|
79
|
+
scs_printf("primal obj error %4e\n", perr);
|
|
80
|
+
scs_printf("dual obj error %4e\n", derr);
|
|
81
|
+
|
|
82
|
+
success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
|
|
83
|
+
mu_assert("test_box_cone_lp: SCS failed to produce SCS_SOLVED", success);
|
|
84
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
85
|
+
|
|
86
|
+
SCS(free_sol)(sol);
|
|
87
|
+
scs_free(d->A);
|
|
88
|
+
scs_free(k);
|
|
89
|
+
scs_free(stgs);
|
|
90
|
+
scs_free(d);
|
|
91
|
+
return fail;
|
|
92
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#include "glbopts.h"
|
|
2
|
+
#include "linalg.h"
|
|
3
|
+
#include "minunit.h"
|
|
4
|
+
#include "problem_utils.h"
|
|
5
|
+
#include "scs.h"
|
|
6
|
+
#include "util.h"
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Dual exponential cone test.
|
|
10
|
+
*
|
|
11
|
+
* K_exp* (dual exp cone) = {(u,v,w): u<=0, -u*exp(v/u - 1) <= w}
|
|
12
|
+
* U {u=0, v>=0, w>=0}
|
|
13
|
+
* (Friberg 2021 convention used by SCS.)
|
|
14
|
+
*
|
|
15
|
+
* Problem: minimize w s.t. (u, v, w) in K_exp*, u = -1, v = 1.
|
|
16
|
+
*
|
|
17
|
+
* With u=-1, v=1 (first branch, u<0):
|
|
18
|
+
* -(-1)*exp(1/(-1) - 1) = exp(-2) <= w
|
|
19
|
+
* Optimal: w* = exp(-2) ~= 0.13534, obj ~= 0.13534.
|
|
20
|
+
*
|
|
21
|
+
* Cone ordering: z=2 (equality rows 0-1), ed=1 (dual exp triple rows 2-4).
|
|
22
|
+
* Variables [u, v, w] (n=3), m=5.
|
|
23
|
+
*
|
|
24
|
+
* Constraints:
|
|
25
|
+
* Row 0 (z): u = -1 -> A[0,0]=1, b[0]=-1
|
|
26
|
+
* Row 1 (z): v = 1 -> A[1,1]=1, b[1]= 1
|
|
27
|
+
* Row 2 (ed): s[2] = u -> A[2,0]=-1, b[2]=0
|
|
28
|
+
* Row 3 (ed): s[3] = v -> A[3,1]=-1, b[3]=0
|
|
29
|
+
* Row 4 (ed): s[4] = w -> A[4,2]=-1, b[4]=0
|
|
30
|
+
*
|
|
31
|
+
* A cols (CSC):
|
|
32
|
+
* col 0 (u): row 0 -> +1, row 2 -> -1
|
|
33
|
+
* col 1 (v): row 1 -> +1, row 3 -> -1
|
|
34
|
+
* col 2 (w): row 4 -> -1
|
|
35
|
+
*/
|
|
36
|
+
static const char *test_dual_exp_cone(void) {
|
|
37
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
38
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
39
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
40
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
41
|
+
ScsInfo info = {0};
|
|
42
|
+
scs_int exitflag;
|
|
43
|
+
scs_float perr, derr;
|
|
44
|
+
scs_int success;
|
|
45
|
+
const char *fail;
|
|
46
|
+
|
|
47
|
+
/* exp(-2) = 0.13533528323661270... */
|
|
48
|
+
scs_float opt = 0.13533528323661270;
|
|
49
|
+
|
|
50
|
+
scs_float Ax[] = {1.0, -1.0, 1.0, -1.0, -1.0};
|
|
51
|
+
scs_int Ai[] = {0, 2, 1, 3, 4};
|
|
52
|
+
scs_int Ap[] = {0, 2, 4, 5};
|
|
53
|
+
|
|
54
|
+
scs_float b[] = {-1.0, 1.0, 0.0, 0.0, 0.0};
|
|
55
|
+
scs_float c[] = {0.0, 0.0, 1.0};
|
|
56
|
+
|
|
57
|
+
scs_int m = 5, n = 3;
|
|
58
|
+
|
|
59
|
+
d->m = m;
|
|
60
|
+
d->n = n;
|
|
61
|
+
d->b = b;
|
|
62
|
+
d->c = c;
|
|
63
|
+
|
|
64
|
+
d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
65
|
+
d->A->m = m;
|
|
66
|
+
d->A->n = n;
|
|
67
|
+
d->A->x = Ax;
|
|
68
|
+
d->A->i = Ai;
|
|
69
|
+
d->A->p = Ap;
|
|
70
|
+
|
|
71
|
+
k->z = 2;
|
|
72
|
+
k->ed = 1;
|
|
73
|
+
|
|
74
|
+
scs_set_default_settings(stgs);
|
|
75
|
+
stgs->eps_abs = 1e-6;
|
|
76
|
+
stgs->eps_rel = 1e-6;
|
|
77
|
+
|
|
78
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
79
|
+
|
|
80
|
+
perr = info.pobj - opt;
|
|
81
|
+
derr = info.dobj - opt;
|
|
82
|
+
|
|
83
|
+
scs_printf("primal obj error %4e\n", perr);
|
|
84
|
+
scs_printf("dual obj error %4e\n", derr);
|
|
85
|
+
|
|
86
|
+
success = ABS(perr) < 1e-4 && ABS(derr) < 1e-4 && exitflag == SCS_SOLVED;
|
|
87
|
+
mu_assert("test_dual_exp_cone: SCS failed to produce SCS_SOLVED", success);
|
|
88
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
89
|
+
|
|
90
|
+
SCS(free_sol)(sol);
|
|
91
|
+
scs_free(d->A);
|
|
92
|
+
scs_free(k);
|
|
93
|
+
scs_free(stgs);
|
|
94
|
+
scs_free(d);
|
|
95
|
+
return fail;
|
|
96
|
+
}
|