scs 0.2.2 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/LICENSE.txt +18 -18
- data/README.md +19 -14
- data/lib/scs/ffi.rb +31 -20
- data/lib/scs/solver.rb +32 -9
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +39 -0
- data/vendor/scs/CMakeLists.txt +320 -0
- data/vendor/scs/Makefile +32 -23
- data/vendor/scs/README.md +9 -218
- data/vendor/scs/include/aa.h +67 -23
- data/vendor/scs/include/cones.h +22 -19
- data/vendor/scs/include/glbopts.h +107 -79
- data/vendor/scs/include/linalg.h +3 -4
- data/vendor/scs/include/linsys.h +58 -44
- data/vendor/scs/include/normalize.h +6 -5
- data/vendor/scs/include/rw.h +8 -2
- data/vendor/scs/include/scs.h +257 -141
- data/vendor/scs/include/scs_types.h +34 -0
- data/vendor/scs/include/scs_work.h +83 -0
- data/vendor/scs/include/util.h +3 -15
- data/vendor/scs/linsys/cpu/direct/private.c +241 -232
- data/vendor/scs/linsys/cpu/direct/private.h +13 -7
- data/vendor/scs/linsys/cpu/indirect/private.c +194 -118
- data/vendor/scs/linsys/cpu/indirect/private.h +7 -4
- data/vendor/scs/linsys/csparse.c +87 -0
- data/vendor/scs/linsys/csparse.h +34 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
- data/vendor/scs/linsys/external/amd/amd_internal.h +1 -1
- data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
- data/vendor/scs/linsys/external/qdldl/changes +2 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.c +29 -46
- data/vendor/scs/linsys/external/qdldl/qdldl.h +33 -41
- data/vendor/scs/linsys/external/qdldl/qdldl_types.h +11 -3
- data/vendor/scs/linsys/gpu/gpu.c +58 -21
- data/vendor/scs/linsys/gpu/gpu.h +70 -35
- data/vendor/scs/linsys/gpu/indirect/private.c +394 -157
- data/vendor/scs/linsys/gpu/indirect/private.h +27 -12
- data/vendor/scs/linsys/scs_matrix.c +478 -0
- data/vendor/scs/linsys/scs_matrix.h +70 -0
- data/vendor/scs/scs.mk +14 -10
- data/vendor/scs/src/aa.c +394 -110
- data/vendor/scs/src/cones.c +497 -359
- data/vendor/scs/src/ctrlc.c +15 -5
- data/vendor/scs/src/linalg.c +107 -26
- data/vendor/scs/src/normalize.c +30 -72
- data/vendor/scs/src/rw.c +202 -27
- data/vendor/scs/src/scs.c +769 -571
- data/vendor/scs/src/scs_version.c +11 -3
- data/vendor/scs/src/util.c +37 -106
- data/vendor/scs/test/minunit.h +22 -8
- data/vendor/scs/test/problem_utils.h +180 -25
- data/vendor/scs/test/problems/degenerate.h +130 -0
- data/vendor/scs/test/problems/hs21_tiny_qp.h +124 -0
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +116 -0
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +100 -0
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +199 -0
- data/vendor/scs/test/problems/random_prob +0 -0
- data/vendor/scs/test/problems/random_prob.h +45 -0
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +188 -31
- data/vendor/scs/test/problems/small_lp.h +14 -13
- data/vendor/scs/test/problems/small_qp.h +352 -0
- data/vendor/scs/test/problems/test_validation.h +43 -0
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +82 -0
- data/vendor/scs/test/random_socp_prob.c +54 -53
- data/vendor/scs/test/rng.h +109 -0
- data/vendor/scs/test/run_from_file.c +20 -11
- data/vendor/scs/test/run_tests.c +35 -2
- metadata +29 -98
- data/vendor/scs/linsys/amatrix.c +0 -305
- data/vendor/scs/linsys/amatrix.h +0 -36
- data/vendor/scs/linsys/amatrix.o +0 -0
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.o +0 -0
- data/vendor/scs/test/data/small_random_socp +0 -0
- data/vendor/scs/test/problems/small_random_socp.h +0 -33
- data/vendor/scs/test/run_tests +0 -2
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
#ifdef __cplusplus
|
|
2
|
+
extern "C" {
|
|
3
|
+
#endif
|
|
4
|
+
|
|
1
5
|
#include "glbopts.h"
|
|
2
6
|
|
|
3
|
-
const char *
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
const char *scs_version(void) {
|
|
8
|
+
return SCS_VERSION;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#ifdef __cplusplus
|
|
12
|
+
}
|
|
13
|
+
#endif
|
data/vendor/scs/src/util.c
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
#include "glbopts.h"
|
|
4
4
|
#include "linsys.h"
|
|
5
|
+
#include "scs_matrix.h"
|
|
5
6
|
|
|
6
7
|
/* return milli-seconds */
|
|
7
8
|
#if (defined NOTIMER)
|
|
8
9
|
|
|
9
|
-
void SCS(tic)(SCS(timer) * t) {
|
|
10
|
-
|
|
10
|
+
void SCS(tic)(SCS(timer) * t) {
|
|
11
|
+
}
|
|
12
|
+
scs_float SCS(tocq)(SCS(timer) * t) {
|
|
13
|
+
return NAN;
|
|
14
|
+
}
|
|
11
15
|
|
|
12
16
|
#elif (defined _WIN32 || _WIN64 || defined _WINDLL)
|
|
13
17
|
|
|
@@ -46,7 +50,9 @@ scs_float SCS(tocq)(SCS(timer) * t) {
|
|
|
46
50
|
|
|
47
51
|
#else
|
|
48
52
|
|
|
49
|
-
void SCS(tic)(SCS(timer) * t) {
|
|
53
|
+
void SCS(tic)(SCS(timer) * t) {
|
|
54
|
+
clock_gettime(CLOCK_MONOTONIC, &t->tic);
|
|
55
|
+
}
|
|
50
56
|
|
|
51
57
|
scs_float SCS(tocq)(SCS(timer) * t) {
|
|
52
58
|
struct timespec temp;
|
|
@@ -65,109 +71,29 @@ scs_float SCS(tocq)(SCS(timer) * t) {
|
|
|
65
71
|
|
|
66
72
|
#endif
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
scs_float time = SCS(tocq)(t);
|
|
70
|
-
scs_printf("time: %8.4f milli-seconds.\n", time);
|
|
71
|
-
return time;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
scs_float SCS(str_toc)(char *str, SCS(timer) * t) {
|
|
75
|
-
scs_float time = SCS(tocq)(t);
|
|
76
|
-
scs_printf("%s - time: %8.4f milli-seconds.\n", str, time);
|
|
77
|
-
return time;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
void SCS(print_cone_data)(const ScsCone *k) {
|
|
81
|
-
scs_int i;
|
|
82
|
-
scs_printf("num zeros = %i\n", (int)k->f);
|
|
83
|
-
scs_printf("num LP = %i\n", (int)k->l);
|
|
84
|
-
scs_printf("num SOCs = %i\n", (int)k->qsize);
|
|
85
|
-
scs_printf("soc array:\n");
|
|
86
|
-
for (i = 0; i < k->qsize; i++) {
|
|
87
|
-
scs_printf("%i\n", (int)k->q[i]);
|
|
88
|
-
}
|
|
89
|
-
scs_printf("num SDCs = %i\n", (int)k->ssize);
|
|
90
|
-
scs_printf("sdc array:\n");
|
|
91
|
-
for (i = 0; i < k->ssize; i++) {
|
|
92
|
-
scs_printf("%i\n", (int)k->s[i]);
|
|
93
|
-
}
|
|
94
|
-
scs_printf("num ep = %i\n", (int)k->ep);
|
|
95
|
-
scs_printf("num ed = %i\n", (int)k->ed);
|
|
96
|
-
scs_printf("num PCs = %i\n", (int)k->psize);
|
|
97
|
-
scs_printf("pow array:\n");
|
|
98
|
-
for (i = 0; i < k->psize; i++) {
|
|
99
|
-
scs_printf("%4f\n", (double)k->p[i]);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
void SCS(print_work)(const ScsWork *w) {
|
|
104
|
-
scs_int i, l = w->n + w->m;
|
|
105
|
-
scs_printf("\n u_t is \n");
|
|
106
|
-
for (i = 0; i < l; i++) {
|
|
107
|
-
scs_printf("%f\n", w->u_t[i]);
|
|
108
|
-
}
|
|
109
|
-
scs_printf("\n u is \n");
|
|
110
|
-
for (i = 0; i < l; i++) {
|
|
111
|
-
scs_printf("%f\n", w->u[i]);
|
|
112
|
-
}
|
|
113
|
-
scs_printf("\n v is \n");
|
|
114
|
-
for (i = 0; i < l; i++) {
|
|
115
|
-
scs_printf("%f\n", w->v[i]);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
void SCS(print_data)(const ScsData *d) {
|
|
120
|
-
scs_printf("m = %i\n", (int)d->m);
|
|
121
|
-
scs_printf("n = %i\n", (int)d->n);
|
|
122
|
-
|
|
123
|
-
scs_printf("max_iters = %i\n", (int)d->stgs->max_iters);
|
|
124
|
-
scs_printf("verbose = %i\n", (int)d->stgs->verbose);
|
|
125
|
-
scs_printf("normalize = %i\n", (int)d->stgs->normalize);
|
|
126
|
-
scs_printf("warm_start = %i\n", (int)d->stgs->warm_start);
|
|
127
|
-
scs_printf("acceleration_lookback = %i\n",
|
|
128
|
-
(int)d->stgs->acceleration_lookback);
|
|
129
|
-
scs_printf("eps = %4f\n", d->stgs->eps);
|
|
130
|
-
scs_printf("alpha = %4f\n", d->stgs->alpha);
|
|
131
|
-
scs_printf("rho_x = %4f\n", d->stgs->rho_x);
|
|
132
|
-
scs_printf("cg_rate = %4f\n", d->stgs->cg_rate);
|
|
133
|
-
scs_printf("scale = %4f\n", d->stgs->scale);
|
|
134
|
-
scs_printf("write_data_filename = %s\n",
|
|
135
|
-
(char *)d->stgs->write_data_filename);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
void SCS(print_array)(const scs_float *arr, scs_int n, const char *name) {
|
|
139
|
-
scs_int i, j, k = 0;
|
|
140
|
-
scs_int num_on_one_line = 10;
|
|
141
|
-
scs_printf("\n");
|
|
142
|
-
for (i = 0; i < n / num_on_one_line; ++i) {
|
|
143
|
-
for (j = 0; j < num_on_one_line; ++j) {
|
|
144
|
-
scs_printf("%s[%li] = %4f, ", name, (long)k, arr[k]);
|
|
145
|
-
k++;
|
|
146
|
-
}
|
|
147
|
-
scs_printf("\n");
|
|
148
|
-
}
|
|
149
|
-
for (j = k; j < n; ++j) {
|
|
150
|
-
scs_printf("%s[%li] = %4f, ", name, (long)j, arr[j]);
|
|
151
|
-
}
|
|
152
|
-
scs_printf("\n");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
void SCS(free_data)(ScsData *d, ScsCone *k) {
|
|
74
|
+
void SCS(free_data)(ScsData *d, ScsCone *k, ScsSettings *stgs) {
|
|
156
75
|
if (d) {
|
|
157
76
|
scs_free(d->b);
|
|
158
77
|
scs_free(d->c);
|
|
159
|
-
scs_free(d->stgs);
|
|
160
78
|
if (d->A) {
|
|
161
|
-
SCS(
|
|
79
|
+
SCS(free_scs_matrix)(d->A);
|
|
80
|
+
}
|
|
81
|
+
if (d->P) {
|
|
82
|
+
SCS(free_scs_matrix)(d->P);
|
|
162
83
|
}
|
|
163
84
|
scs_free(d);
|
|
164
85
|
}
|
|
165
86
|
if (k) {
|
|
87
|
+
scs_free(k->bu);
|
|
88
|
+
scs_free(k->bl);
|
|
166
89
|
scs_free(k->q);
|
|
167
90
|
scs_free(k->s);
|
|
168
91
|
scs_free(k->p);
|
|
169
92
|
scs_free(k);
|
|
170
93
|
}
|
|
94
|
+
if (stgs) {
|
|
95
|
+
scs_free(stgs);
|
|
96
|
+
}
|
|
171
97
|
}
|
|
172
98
|
|
|
173
99
|
void SCS(free_sol)(ScsSolution *sol) {
|
|
@@ -179,18 +105,23 @@ void SCS(free_sol)(ScsSolution *sol) {
|
|
|
179
105
|
}
|
|
180
106
|
}
|
|
181
107
|
|
|
182
|
-
/* assumes
|
|
183
|
-
void
|
|
108
|
+
/* assumes stgs already allocated memory */
|
|
109
|
+
void scs_set_default_settings(ScsSettings *stgs) {
|
|
184
110
|
/* These constants are defined in include/glbopts.h */
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
111
|
+
stgs->max_iters = MAX_ITERS;
|
|
112
|
+
stgs->eps_abs = EPS_ABS;
|
|
113
|
+
stgs->eps_rel = EPS_REL;
|
|
114
|
+
stgs->eps_infeas = EPS_INFEAS;
|
|
115
|
+
stgs->alpha = ALPHA;
|
|
116
|
+
stgs->rho_x = RHO_X;
|
|
117
|
+
stgs->scale = SCALE;
|
|
118
|
+
stgs->verbose = VERBOSE;
|
|
119
|
+
stgs->normalize = NORMALIZE;
|
|
120
|
+
stgs->warm_start = WARM_START;
|
|
121
|
+
stgs->acceleration_lookback = ACCELERATION_LOOKBACK;
|
|
122
|
+
stgs->acceleration_interval = ACCELERATION_INTERVAL;
|
|
123
|
+
stgs->adaptive_scale = ADAPTIVE_SCALE;
|
|
124
|
+
stgs->write_data_filename = WRITE_DATA_FILENAME;
|
|
125
|
+
stgs->log_csv_filename = LOG_CSV_FILENAME;
|
|
126
|
+
stgs->time_limit_secs = TIME_LIMIT_SECS;
|
|
196
127
|
}
|
data/vendor/scs/test/minunit.h
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
/* Taken from http://www.jera.com/techinfo/jtns/jtn002.html */
|
|
2
2
|
|
|
3
3
|
/* Simple Macros for testing */
|
|
4
|
-
#define
|
|
5
|
-
do {
|
|
6
|
-
if (
|
|
4
|
+
#define mu_assert_less(message, a, b) \
|
|
5
|
+
do { \
|
|
6
|
+
if (a > b) { \
|
|
7
|
+
scs_printf("%s: %1.3e > %1.3e\n", message, a, b); \
|
|
8
|
+
return message; \
|
|
9
|
+
} \
|
|
7
10
|
} while (0)
|
|
8
|
-
#define
|
|
9
|
-
do {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
#define mu_assert(message, test) \
|
|
12
|
+
do { \
|
|
13
|
+
if (!(test)) \
|
|
14
|
+
return message; \
|
|
15
|
+
} while (0)
|
|
16
|
+
#define mu_run_test(test) _mu_run_test(#test, test)
|
|
17
|
+
|
|
18
|
+
#define _mu_run_test(name, test) \
|
|
19
|
+
do { \
|
|
20
|
+
scs_printf("*********************************************************\n"); \
|
|
21
|
+
scs_printf("Running test: %s\n", name); \
|
|
22
|
+
const char *message = test(); \
|
|
23
|
+
tests_run++; \
|
|
24
|
+
scs_printf("*********************************************************\n"); \
|
|
25
|
+
if (message) \
|
|
26
|
+
return message; \
|
|
13
27
|
} while (0)
|
|
@@ -1,34 +1,24 @@
|
|
|
1
1
|
#ifndef PUTILS_H_GUARD
|
|
2
2
|
#define PUTILS_H_GUARD
|
|
3
3
|
|
|
4
|
-
#include "amatrix.h"
|
|
5
4
|
#include "cones.h"
|
|
6
5
|
#include "linalg.h"
|
|
6
|
+
#include "linsys.h"
|
|
7
|
+
#include "minunit.h"
|
|
8
|
+
#include "rng.h"
|
|
7
9
|
#include "scs.h"
|
|
10
|
+
#include "scs_matrix.h"
|
|
8
11
|
#include "util.h"
|
|
9
12
|
|
|
10
|
-
#define
|
|
11
|
-
#ifdef DLONG
|
|
12
|
-
#ifdef _WIN64
|
|
13
|
-
/* this is a Microsoft extension, but also works with min_g_w-w64 */
|
|
14
|
-
#define INTRW "%I64d"
|
|
15
|
-
#else
|
|
16
|
-
#define INTRW "%ld"
|
|
17
|
-
#endif
|
|
18
|
-
#else
|
|
19
|
-
#define INTRW "%i"
|
|
20
|
-
#endif
|
|
21
|
-
|
|
22
|
-
void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
|
|
23
|
-
ScsSolution *opt_sol);
|
|
13
|
+
#define _MAX_RAND_VAL (1073741823) /* 2^30 - 1 */
|
|
24
14
|
|
|
25
15
|
/* uniform random number in [-1,1] */
|
|
26
16
|
static scs_float rand_scs_float(void) {
|
|
27
|
-
return 2 * (((scs_float)
|
|
17
|
+
return 2 * (((scs_float)ran_arr_next()) / _MAX_RAND_VAL) - 1; /* in [-1, 1] */
|
|
28
18
|
}
|
|
29
19
|
|
|
30
20
|
void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
|
|
31
|
-
ScsSolution *opt_sol) {
|
|
21
|
+
ScsSolution *opt_sol, scs_int seed) {
|
|
32
22
|
scs_int n = d->n;
|
|
33
23
|
scs_int m = d->m;
|
|
34
24
|
ScsMatrix *A = d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
@@ -39,6 +29,7 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
|
|
|
39
29
|
scs_float *s = opt_sol->s = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
|
40
30
|
/* temporary variables */
|
|
41
31
|
scs_float *z = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
|
32
|
+
ScsConeWork *tmp_cone_work;
|
|
42
33
|
scs_int i, j, r, rn, rm;
|
|
43
34
|
|
|
44
35
|
A->i = (scs_int *)scs_calloc(nnz, sizeof(scs_int));
|
|
@@ -50,8 +41,9 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
|
|
|
50
41
|
for (i = 0; i < m; i++) {
|
|
51
42
|
y[i] = z[i] = rand_scs_float();
|
|
52
43
|
}
|
|
53
|
-
|
|
54
|
-
SCS(proj_dual_cone)(y,
|
|
44
|
+
tmp_cone_work = SCS(init_cone)(k, m);
|
|
45
|
+
SCS(proj_dual_cone)(y, tmp_cone_work, SCS_NULL, SCS_NULL);
|
|
46
|
+
SCS(finish_cone(tmp_cone_work));
|
|
55
47
|
|
|
56
48
|
for (i = 0; i < m; i++) {
|
|
57
49
|
b[i] = s[i] = y[i] - z[i];
|
|
@@ -65,18 +57,15 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
|
|
|
65
57
|
c = -A'*y
|
|
66
58
|
b = A*x + s
|
|
67
59
|
*/
|
|
60
|
+
ran_start(seed);
|
|
68
61
|
A->p[0] = 0;
|
|
69
|
-
scs_printf("Generating random matrix:\n");
|
|
70
62
|
for (j = 0; j < n; j++) { /* column */
|
|
71
|
-
if (j * 100 % n == 0 && (j * 100 / n) % 10 == 0) {
|
|
72
|
-
scs_printf("%ld%%\n", (long)(j * 100 / n));
|
|
73
|
-
}
|
|
74
63
|
r = 0;
|
|
75
64
|
for (i = 0; i < m && r < col_nnz; ++i) {
|
|
76
65
|
/* generate a unique sorted array via Knuths alg */
|
|
77
66
|
rn = m - i;
|
|
78
67
|
rm = col_nnz - r;
|
|
79
|
-
if ((
|
|
68
|
+
if ((ran_arr_next() % rn) < rm) {
|
|
80
69
|
A->x[r + j * col_nnz] = rand_scs_float();
|
|
81
70
|
A->i[r + j * col_nnz] = i;
|
|
82
71
|
b[i] += A->x[r + j * col_nnz] * x[j];
|
|
@@ -86,8 +75,174 @@ void gen_random_prob_data(scs_int nnz, scs_int col_nnz, ScsData *d, ScsCone *k,
|
|
|
86
75
|
}
|
|
87
76
|
A->p[j + 1] = (j + 1) * col_nnz;
|
|
88
77
|
}
|
|
89
|
-
scs_printf("done\n");
|
|
90
78
|
scs_free(z);
|
|
91
79
|
}
|
|
92
80
|
|
|
81
|
+
static scs_float get_dual_cone_dist(const scs_float *y, ScsConeWork *c,
|
|
82
|
+
scs_int m) {
|
|
83
|
+
scs_float dist;
|
|
84
|
+
scs_float *t = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
|
85
|
+
memcpy(t, y, m * sizeof(scs_float));
|
|
86
|
+
SCS(proj_dual_cone)(t, c, SCS_NULL, SCS_NULL);
|
|
87
|
+
dist = SCS(norm_inf_diff)(t, y, m);
|
|
88
|
+
scs_free(t);
|
|
89
|
+
return dist;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* via moreau */
|
|
93
|
+
static scs_float get_pri_cone_dist(const scs_float *s, ScsConeWork *c,
|
|
94
|
+
scs_int m) {
|
|
95
|
+
scs_float dist;
|
|
96
|
+
scs_float *t = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
|
97
|
+
memcpy(t, s, m * sizeof(scs_float));
|
|
98
|
+
SCS(scale_array)(t, -1.0, m);
|
|
99
|
+
SCS(proj_dual_cone)(t, c, SCS_NULL, SCS_NULL);
|
|
100
|
+
dist = SCS(norm_inf)(t, m); /* ||s - Pi_c(s)|| = ||Pi_c*(-s)|| */
|
|
101
|
+
scs_free(t);
|
|
102
|
+
return dist;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const char *verify_solution_correct(ScsData *d, ScsCone *k, ScsSettings *stgs,
|
|
106
|
+
ScsInfo *info, ScsSolution *sol,
|
|
107
|
+
scs_int status) {
|
|
108
|
+
scs_int n = d->n, m = d->m;
|
|
109
|
+
scs_float *x = sol->x;
|
|
110
|
+
scs_float *y = sol->y;
|
|
111
|
+
scs_float *s = sol->s;
|
|
112
|
+
|
|
113
|
+
scs_float *c = d->c;
|
|
114
|
+
scs_float *b = d->b;
|
|
115
|
+
|
|
116
|
+
scs_float *primal = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
|
117
|
+
scs_float *ax = (scs_float *)scs_calloc(m, sizeof(scs_float));
|
|
118
|
+
scs_float *dual = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
|
119
|
+
scs_float *px = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
|
120
|
+
scs_float *aty = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
|
121
|
+
|
|
122
|
+
scs_float res_pri, res_dual, res_infeas, res_unbdd_a, res_unbdd_p;
|
|
123
|
+
scs_float ctx, bty, xt_p_x, gap, pobj, dobj, sty;
|
|
124
|
+
scs_float grl, prl, drl;
|
|
125
|
+
|
|
126
|
+
scs_float sdist = NAN, ydist = NAN;
|
|
127
|
+
|
|
128
|
+
ScsConeWork *cone_work = SCS(init_cone)(k, m);
|
|
129
|
+
|
|
130
|
+
/**************** PRIMAL *********************/
|
|
131
|
+
memset(ax, 0, m * sizeof(scs_float));
|
|
132
|
+
/* Ax */
|
|
133
|
+
SCS(accum_by_a)(d->A, x, ax);
|
|
134
|
+
|
|
135
|
+
memcpy(primal, ax, m * sizeof(scs_float));
|
|
136
|
+
/* Ax + s */
|
|
137
|
+
SCS(add_scaled_array)(primal, s, m, 1.);
|
|
138
|
+
|
|
139
|
+
/* unbounded residual |Ax + s| */
|
|
140
|
+
res_unbdd_a = NORM(primal, m);
|
|
141
|
+
|
|
142
|
+
/* Ax + s - b */
|
|
143
|
+
SCS(add_scaled_array)(primal, b, m, -1.0);
|
|
144
|
+
|
|
145
|
+
res_pri = NORM(primal, m);
|
|
146
|
+
|
|
147
|
+
/**************** DUAL *********************/
|
|
148
|
+
memset(px, 0, n * sizeof(scs_float));
|
|
149
|
+
if (d->P) {
|
|
150
|
+
/* px = Px */
|
|
151
|
+
SCS(accum_by_p)(d->P, x, px);
|
|
152
|
+
xt_p_x = SCS(dot)(px, x, n);
|
|
153
|
+
res_unbdd_p = NORM(px, n);
|
|
154
|
+
} else {
|
|
155
|
+
xt_p_x = 0;
|
|
156
|
+
res_unbdd_p = 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
memset(aty, 0, n * sizeof(scs_float));
|
|
160
|
+
/* aty = A'y */
|
|
161
|
+
SCS(accum_by_atrans)(d->A, y, aty);
|
|
162
|
+
res_infeas = NORM(aty, n);
|
|
163
|
+
|
|
164
|
+
memcpy(dual, aty, n * sizeof(scs_float));
|
|
165
|
+
/* Px + A'y */
|
|
166
|
+
SCS(add_scaled_array)(dual, px, n, 1.);
|
|
167
|
+
/* Px + A'y + c */
|
|
168
|
+
SCS(add_scaled_array)(dual, c, n, 1.0);
|
|
169
|
+
|
|
170
|
+
res_dual = NORM(dual, n);
|
|
171
|
+
|
|
172
|
+
/**************** CONES *****************/
|
|
173
|
+
|
|
174
|
+
if (status == SCS_SOLVED || status == SCS_UNBOUNDED) {
|
|
175
|
+
sdist = get_pri_cone_dist(sol->s, cone_work, m);
|
|
176
|
+
}
|
|
177
|
+
if (status == SCS_SOLVED || status == SCS_INFEASIBLE) {
|
|
178
|
+
ydist = get_dual_cone_dist(sol->y, cone_work, m);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**************** OTHERS *****************/
|
|
182
|
+
sty = SCS(dot)(y, s, m);
|
|
183
|
+
|
|
184
|
+
bty = SCS(dot)(y, b, m);
|
|
185
|
+
ctx = SCS(dot)(x, c, n);
|
|
186
|
+
|
|
187
|
+
gap = ABS(xt_p_x + ctx + bty);
|
|
188
|
+
pobj = xt_p_x / 2. + ctx;
|
|
189
|
+
dobj = -xt_p_x / 2. - bty;
|
|
190
|
+
|
|
191
|
+
/************** OPTIMALITY ****************/
|
|
192
|
+
|
|
193
|
+
grl = MAX(MAX(ABS(xt_p_x), ABS(ctx)), ABS(bty));
|
|
194
|
+
prl = MAX(MAX(NORM(b, m), NORM(s, m)), NORM(ax, m));
|
|
195
|
+
drl = MAX(MAX(NORM(c, n), NORM(px, n)), NORM(aty, n));
|
|
196
|
+
|
|
197
|
+
/**************** CLEANUP *****************/
|
|
198
|
+
scs_free(primal);
|
|
199
|
+
scs_free(dual);
|
|
200
|
+
scs_free(px);
|
|
201
|
+
scs_free(ax);
|
|
202
|
+
scs_free(aty);
|
|
203
|
+
SCS(finish_cone)(cone_work);
|
|
204
|
+
|
|
205
|
+
/**************** ASSERTS *****************/
|
|
206
|
+
if (status == SCS_SOLVED) {
|
|
207
|
+
mu_assert_less("Primal residual ERROR", ABS(res_pri - info->res_pri),
|
|
208
|
+
1e-11);
|
|
209
|
+
mu_assert_less("Dual residual ERROR", ABS(res_dual - info->res_dual),
|
|
210
|
+
1e-11);
|
|
211
|
+
mu_assert_less("Gap ERROR", ABS(gap - info->gap), 1e-8 * (1 + ABS(gap)));
|
|
212
|
+
mu_assert_less("Primal obj ERROR", ABS(pobj - info->pobj),
|
|
213
|
+
1e-9 * (1 + ABS(pobj)));
|
|
214
|
+
mu_assert_less("Dual obj ERROR", ABS(dobj - info->dobj),
|
|
215
|
+
1e-9 * (1 + ABS(dobj)));
|
|
216
|
+
/* slightly looser tol */
|
|
217
|
+
mu_assert_less("Complementary slackness ERROR", ABS(sty),
|
|
218
|
+
1e-8 * MAX(NORM(s, m), NORM(y, m)));
|
|
219
|
+
mu_assert_less("s cone dist ERROR", ABS(sdist), 1e-5);
|
|
220
|
+
mu_assert_less("y cone dist ERROR", ABS(ydist), 1e-5);
|
|
221
|
+
|
|
222
|
+
mu_assert_less("Primal feas ERROR", res_pri,
|
|
223
|
+
stgs->eps_abs + stgs->eps_rel * prl);
|
|
224
|
+
mu_assert_less("Dual feas ERROR", res_dual,
|
|
225
|
+
stgs->eps_abs + stgs->eps_rel * drl);
|
|
226
|
+
mu_assert_less("Gap feas ERROR", gap, stgs->eps_abs + stgs->eps_rel * grl);
|
|
227
|
+
|
|
228
|
+
} else if (status == SCS_INFEASIBLE) {
|
|
229
|
+
mu_assert_less("Infeas ERROR", ABS(res_infeas - info->res_infeas), 1e-8);
|
|
230
|
+
mu_assert_less("bty ERROR", ABS(bty + 1), 1e-12);
|
|
231
|
+
mu_assert_less("y cone dist ERROR", ABS(ydist), 1e-5);
|
|
232
|
+
mu_assert_less("Infeas invalid ERROR", res_infeas, stgs->eps_infeas);
|
|
233
|
+
|
|
234
|
+
} else if (status == SCS_UNBOUNDED) {
|
|
235
|
+
mu_assert_less("Unbdd_a ERROR", ABS(res_unbdd_a - info->res_unbdd_a), 1e-8);
|
|
236
|
+
mu_assert_less("Unbdd_p ERROR", ABS(res_unbdd_p - info->res_unbdd_p), 1e-8);
|
|
237
|
+
mu_assert_less("ctx ERROR", ABS(ctx + 1), 1e-12);
|
|
238
|
+
mu_assert_less("s cone dist ERROR", ABS(sdist), 1e-5);
|
|
239
|
+
mu_assert_less("Unbounded P invalid ERROR", res_unbdd_p, stgs->eps_infeas);
|
|
240
|
+
mu_assert_less("Unbounded A invalid ERROR", res_unbdd_a, stgs->eps_infeas);
|
|
241
|
+
|
|
242
|
+
} else {
|
|
243
|
+
return "INVALID STATUS";
|
|
244
|
+
}
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
|
|
93
248
|
#endif
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#include "glbopts.h"
|
|
2
|
+
#include "linalg.h"
|
|
3
|
+
#include "minunit.h"
|
|
4
|
+
#include "scs.h"
|
|
5
|
+
#include "scs_matrix.h"
|
|
6
|
+
#include "util.h"
|
|
7
|
+
|
|
8
|
+
/* test degenerate cones */
|
|
9
|
+
static const char *degenerate(void) {
|
|
10
|
+
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
11
|
+
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
12
|
+
ScsSettings *stgs = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
13
|
+
ScsSolution *sol = (ScsSolution *)scs_calloc(1, sizeof(ScsSolution));
|
|
14
|
+
ScsInfo info = {0};
|
|
15
|
+
scs_int exitflag, success;
|
|
16
|
+
scs_float tpobj, tdobj, perr, derr;
|
|
17
|
+
const char *fail;
|
|
18
|
+
|
|
19
|
+
/* data */
|
|
20
|
+
scs_float Ax[] = {-10., -1., 1., -1.};
|
|
21
|
+
scs_int Ai[] = {1, 2, 1, 3};
|
|
22
|
+
scs_int Ap[] = {0, 2, 4};
|
|
23
|
+
|
|
24
|
+
scs_float Px[] = {0.02, 2.};
|
|
25
|
+
scs_int Pi[] = {0, 1};
|
|
26
|
+
scs_int Pp[] = {0, 1, 2};
|
|
27
|
+
|
|
28
|
+
scs_float b[] = {1., -1., 2., -0.5};
|
|
29
|
+
scs_float c[] = {1., 2.};
|
|
30
|
+
|
|
31
|
+
scs_int m = 4;
|
|
32
|
+
scs_int n = 2;
|
|
33
|
+
|
|
34
|
+
/* used later: */
|
|
35
|
+
scs_int sq[] = {1};
|
|
36
|
+
|
|
37
|
+
/* end data */
|
|
38
|
+
|
|
39
|
+
d->m = m;
|
|
40
|
+
d->n = n;
|
|
41
|
+
d->b = b;
|
|
42
|
+
d->c = c;
|
|
43
|
+
|
|
44
|
+
d->A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
45
|
+
d->P = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
46
|
+
|
|
47
|
+
d->A->m = m;
|
|
48
|
+
d->A->n = n;
|
|
49
|
+
|
|
50
|
+
d->A->x = Ax;
|
|
51
|
+
d->A->i = Ai;
|
|
52
|
+
d->A->p = Ap;
|
|
53
|
+
|
|
54
|
+
d->P->m = n;
|
|
55
|
+
d->P->n = n;
|
|
56
|
+
|
|
57
|
+
d->P->x = Px;
|
|
58
|
+
d->P->i = Pi;
|
|
59
|
+
d->P->p = Pp;
|
|
60
|
+
|
|
61
|
+
scs_set_default_settings(stgs);
|
|
62
|
+
stgs->eps_abs = 1e-6;
|
|
63
|
+
stgs->eps_rel = 1e-6;
|
|
64
|
+
stgs->eps_infeas = 1e-9;
|
|
65
|
+
|
|
66
|
+
/* positive orthants */
|
|
67
|
+
k->l = 4;
|
|
68
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
69
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
70
|
+
if (fail) {
|
|
71
|
+
return fail;
|
|
72
|
+
}
|
|
73
|
+
mu_assert("bsize: SCS failed to produce outputflag SCS_SOLVED",
|
|
74
|
+
exitflag == SCS_SOLVED);
|
|
75
|
+
|
|
76
|
+
tpobj = info.pobj;
|
|
77
|
+
tdobj = info.dobj;
|
|
78
|
+
|
|
79
|
+
/* degenerate box cone */
|
|
80
|
+
k->bsize = 1;
|
|
81
|
+
k->l = 3;
|
|
82
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
83
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
84
|
+
if (fail) {
|
|
85
|
+
return fail;
|
|
86
|
+
}
|
|
87
|
+
perr = info.pobj - tpobj;
|
|
88
|
+
derr = info.dobj - tdobj;
|
|
89
|
+
success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED;
|
|
90
|
+
mu_assert("degenerate box cone failure", success);
|
|
91
|
+
|
|
92
|
+
/* degenerate SOC cone */
|
|
93
|
+
k->bsize = 0;
|
|
94
|
+
k->q = sq;
|
|
95
|
+
k->qsize = 1;
|
|
96
|
+
k->l = 3;
|
|
97
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
98
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
99
|
+
if (fail) {
|
|
100
|
+
return fail;
|
|
101
|
+
}
|
|
102
|
+
perr = info.pobj - tpobj;
|
|
103
|
+
derr = info.dobj - tdobj;
|
|
104
|
+
success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED;
|
|
105
|
+
mu_assert("degenerate SOC cone failure", success);
|
|
106
|
+
|
|
107
|
+
/* degenerate PSD cone */
|
|
108
|
+
k->q = 0;
|
|
109
|
+
k->qsize = 0;
|
|
110
|
+
k->s = sq;
|
|
111
|
+
k->ssize = 1;
|
|
112
|
+
k->l = 3;
|
|
113
|
+
exitflag = scs(d, k, stgs, sol, &info);
|
|
114
|
+
fail = verify_solution_correct(d, k, stgs, &info, sol, exitflag);
|
|
115
|
+
if (fail) {
|
|
116
|
+
return fail;
|
|
117
|
+
}
|
|
118
|
+
perr = info.pobj - tpobj;
|
|
119
|
+
derr = info.dobj - tdobj;
|
|
120
|
+
success = ABS(perr) < 1e-8 && ABS(derr) < 1e-8 && exitflag == SCS_SOLVED;
|
|
121
|
+
mu_assert("degenerate PSD cone failure", success);
|
|
122
|
+
|
|
123
|
+
SCS(free_sol)(sol);
|
|
124
|
+
scs_free(d->A);
|
|
125
|
+
scs_free(d->P);
|
|
126
|
+
scs_free(k);
|
|
127
|
+
scs_free(stgs);
|
|
128
|
+
scs_free(d);
|
|
129
|
+
return fail;
|
|
130
|
+
}
|