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.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +1 -1
  4. data/lib/scs/ffi.rb +18 -0
  5. data/lib/scs/version.rb +1 -1
  6. data/vendor/scs/CITATION.cff +2 -3
  7. data/vendor/scs/CLAUDE.md +115 -0
  8. data/vendor/scs/CMakeLists.txt +330 -201
  9. data/vendor/scs/CONTRIBUTING.md +49 -0
  10. data/vendor/scs/Makefile +90 -43
  11. data/vendor/scs/README.md +96 -2
  12. data/vendor/scs/include/aa.h +59 -11
  13. data/vendor/scs/include/aa_stats.h +47 -0
  14. data/vendor/scs/include/cones.h +16 -7
  15. data/vendor/scs/include/glbopts.h +113 -26
  16. data/vendor/scs/include/linalg.h +5 -1
  17. data/vendor/scs/include/linsys.h +1 -2
  18. data/vendor/scs/include/normalize.h +6 -2
  19. data/vendor/scs/include/rw.h +9 -3
  20. data/vendor/scs/include/scs.h +17 -1
  21. data/vendor/scs/include/scs_blas.h +8 -0
  22. data/vendor/scs/include/scs_types.h +2 -2
  23. data/vendor/scs/include/scs_work.h +22 -1
  24. data/vendor/scs/include/util.h +3 -6
  25. data/vendor/scs/include/util_spectral_cones.h +3 -3
  26. data/vendor/scs/linsys/accelerate/direct/private.c +126 -0
  27. data/vendor/scs/linsys/accelerate/direct/private.h +34 -0
  28. data/vendor/scs/linsys/cpu/dense/private.c +250 -0
  29. data/vendor/scs/linsys/cpu/dense/private.h +31 -0
  30. data/vendor/scs/linsys/cpu/direct/private.c +86 -44
  31. data/vendor/scs/linsys/cpu/indirect/private.c +647 -113
  32. data/vendor/scs/linsys/cpu/indirect/private.h +28 -0
  33. data/vendor/scs/linsys/csparse.c +9 -3
  34. data/vendor/scs/linsys/csparse.h +4 -2
  35. data/vendor/scs/linsys/cudss/direct/private.c +77 -43
  36. data/vendor/scs/linsys/cudss/direct/private.h +33 -7
  37. data/vendor/scs/linsys/gpu/indirect/private.c +6 -2
  38. data/vendor/scs/linsys/mkl/direct/private.c +63 -31
  39. data/vendor/scs/linsys/mkl/direct/private.h +0 -1
  40. data/vendor/scs/linsys/scs_matrix.c +291 -165
  41. data/vendor/scs/linsys/scs_matrix.h +7 -9
  42. data/vendor/scs/scs.mk +35 -13
  43. data/vendor/scs/src/aa.c +673 -166
  44. data/vendor/scs/src/cones.c +545 -223
  45. data/vendor/scs/src/ctrlc.c +59 -16
  46. data/vendor/scs/src/exp_cone.c +70 -50
  47. data/vendor/scs/src/linalg.c +21 -2
  48. data/vendor/scs/src/normalize.c +24 -26
  49. data/vendor/scs/src/rw.c +596 -124
  50. data/vendor/scs/src/scs.c +990 -513
  51. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_IPM.c +240 -187
  52. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_Newton.c +108 -85
  53. data/vendor/scs/src/spectral_cones/logdeterminant/log_cone_wrapper.c +62 -63
  54. data/vendor/scs/src/spectral_cones/logdeterminant/logdet_cone.c +85 -78
  55. data/vendor/scs/src/spectral_cones/nuclear/ell1_cone.c +92 -97
  56. data/vendor/scs/src/spectral_cones/nuclear/nuclear_cone.c +39 -28
  57. data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_cone.c +59 -40
  58. data/vendor/scs/src/spectral_cones/sum-largest/sum_largest_eval_cone.c +37 -29
  59. data/vendor/scs/src/spectral_cones/util_spectral_cones.c +12 -6
  60. data/vendor/scs/src/util.c +37 -7
  61. data/vendor/scs/test/mkl_interface_mismatch.c +97 -0
  62. data/vendor/scs/test/packaging/CMakeLists.txt +21 -0
  63. data/vendor/scs/test/packaging/consume.c +50 -0
  64. data/vendor/scs/test/problem_utils.h +9 -2
  65. data/vendor/scs/test/problems/dense_qp.h +64 -0
  66. data/vendor/scs/test/problems/hs21_tiny_qp.h +6 -2
  67. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +10 -2
  68. data/vendor/scs/test/problems/infeasible_lp.h +66 -0
  69. data/vendor/scs/test/problems/infeasible_socp.h +75 -0
  70. data/vendor/scs/test/problems/lp_update.h +110 -0
  71. data/vendor/scs/test/problems/qafiro_tiny_qp.h +3 -1
  72. data/vendor/scs/test/problems/rob_gauss_cov_est.h +6 -3
  73. data/vendor/scs/test/problems/small_qp.h +5 -0
  74. data/vendor/scs/test/problems/test_box_cone.h +92 -0
  75. data/vendor/scs/test/problems/test_dual_exp_cone.h +96 -0
  76. data/vendor/scs/test/problems/test_inaccurate.h +212 -0
  77. data/vendor/scs/test/problems/test_mixed_cones.h +113 -0
  78. data/vendor/scs/test/problems/test_normalize_roundtrip.h +279 -0
  79. data/vendor/scs/test/problems/test_power_cone.h +414 -0
  80. data/vendor/scs/test/problems/test_psd_metric.h +109 -0
  81. data/vendor/scs/test/problems/test_psd_n1.h +84 -0
  82. data/vendor/scs/test/problems/test_root_plus.h +191 -0
  83. data/vendor/scs/test/problems/test_rw_settings.h +112 -0
  84. data/vendor/scs/test/problems/test_soc_sizes.h +393 -0
  85. data/vendor/scs/test/problems/test_solver_options.h +558 -0
  86. data/vendor/scs/test/problems/test_validation.h +263 -24
  87. data/vendor/scs/test/problems/test_zero_cone.h +81 -0
  88. data/vendor/scs/test/problems/unbounded_lp.h +66 -0
  89. data/vendor/scs/test/problems/unbounded_socp.h +71 -0
  90. data/vendor/scs/test/run_from_file.c +6 -0
  91. data/vendor/scs/test/run_tests.c +71 -0
  92. data/vendor/scs/test/rw_settings.c +7 -0
  93. data/vendor/scs/test/spectral_cones_problems/test_ell1_and_nuc.h +128 -0
  94. data/vendor/scs/test/spectral_cones_problems/test_ell1_cone.h +115 -0
  95. 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
- /* 25 iters should be enough if warm-started */
91
- mu_assert("hs21_tiny_qp: warm-start failure", info.iter <= 25);
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
- /* 25 iters should be enough if warm-started */
113
- mu_assert("hs21_tiny_qp: warm-start failure", info.iter <= 25);
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 = -10;
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
- /* 100 iters should be enough if warm-started */
185
- mu_assert("rob_gauss_cov_est: warm-start failure", info.iter <= 100);
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
+ }