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/rw.c
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Read/write routines for serializing SCS problem data to binary files
|
|
3
|
+
* and logging solve progress to CSV. Compiled as no-ops when NO_READ_WRITE=1.
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
#include "rw.h"
|
|
2
7
|
|
|
3
8
|
#include <errno.h>
|
|
4
9
|
#include <stdint.h>
|
|
5
10
|
#include <stdio.h>
|
|
6
11
|
#include <stdlib.h>
|
|
12
|
+
#include <string.h>
|
|
7
13
|
|
|
14
|
+
#include "cones.h"
|
|
8
15
|
#include "linalg.h"
|
|
9
16
|
#include "scs.h"
|
|
10
17
|
#include "scs_matrix.h"
|
|
@@ -21,8 +28,13 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
|
21
28
|
/* Failure */
|
|
22
29
|
return -1;
|
|
23
30
|
}
|
|
24
|
-
|
|
25
|
-
|
|
31
|
+
scs_int SCS(open_csv_log_file)(ScsWork *w) {
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
void SCS(close_csv_log_file)(ScsWork *w) {
|
|
35
|
+
/* Do nothing */
|
|
36
|
+
}
|
|
37
|
+
void SCS(log_data_to_csv)(const ScsCone *k, const ScsWork *w, scs_int iter,
|
|
26
38
|
SCS(timer) * solve_timer) {
|
|
27
39
|
/* Do nothing */
|
|
28
40
|
}
|
|
@@ -32,20 +44,82 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
|
|
32
44
|
/* writes/reads problem data to/from filename */
|
|
33
45
|
/* This is a VERY naive implementation, doesn't care about portability etc */
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
#define RW_EXT_MAGIC ((uint32_t)0x53435345u) /* "SCSE" */
|
|
48
|
+
/* Extension-section schema version. Append-only: readers accept any
|
|
49
|
+
* version <= RW_EXT_VERSION, defaulting fields the file predates, and
|
|
50
|
+
* reject only files written by a NEWER schema than they understand.
|
|
51
|
+
* v1: cs/spectral cone arrays + time_limit_secs
|
|
52
|
+
* v2: + adaptive_diag_scale */
|
|
53
|
+
#define RW_EXT_VERSION ((uint32_t)2u)
|
|
54
|
+
|
|
55
|
+
static scs_int checked_fread(void *ptr, size_t size, size_t nmemb, FILE *fin) {
|
|
56
|
+
size_t ret;
|
|
57
|
+
if (nmemb == 0) {
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
ret = fread(ptr, size, nmemb, fin);
|
|
61
|
+
if (ret != nmemb) {
|
|
62
|
+
scs_printf("Error: fread expected %lu items, got %lu\n",
|
|
63
|
+
(unsigned long)nmemb, (unsigned long)ret);
|
|
64
|
+
return -1;
|
|
65
|
+
}
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static scs_int checked_fwrite(const void *ptr, size_t size, size_t nmemb,
|
|
70
|
+
FILE *fout) {
|
|
71
|
+
size_t ret;
|
|
72
|
+
if (nmemb == 0) {
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
75
|
+
if (!ptr) {
|
|
76
|
+
scs_printf("Error: fwrite passed NULL data for %lu items\n",
|
|
77
|
+
(unsigned long)nmemb);
|
|
78
|
+
return -1;
|
|
79
|
+
}
|
|
80
|
+
ret = fwrite(ptr, size, nmemb, fout);
|
|
81
|
+
if (ret != nmemb) {
|
|
82
|
+
scs_printf("Error: fwrite expected %lu items, wrote %lu\n",
|
|
83
|
+
(unsigned long)nmemb, (unsigned long)ret);
|
|
84
|
+
return -1;
|
|
85
|
+
}
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static scs_int write_int_array(const scs_int *x, scs_int n, FILE *fout) {
|
|
90
|
+
if (n < 0) {
|
|
91
|
+
scs_printf("Error: cannot write negative array length %li\n", (long)n);
|
|
92
|
+
return -1;
|
|
93
|
+
}
|
|
94
|
+
return checked_fwrite(x, sizeof(scs_int), (size_t)n, fout);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static scs_int write_float_array(const scs_float *x, scs_int n, FILE *fout) {
|
|
98
|
+
if (n < 0) {
|
|
99
|
+
scs_printf("Error: cannot write negative array length %li\n", (long)n);
|
|
100
|
+
return -1;
|
|
101
|
+
}
|
|
102
|
+
return checked_fwrite(x, sizeof(scs_float), (size_t)n, fout);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static scs_int write_scs_cone(const ScsCone *k, FILE *fout) {
|
|
106
|
+
scs_int box_len = MAX(k->bsize - 1, 0);
|
|
107
|
+
if (checked_fwrite(&(k->z), sizeof(scs_int), 1, fout) < 0 ||
|
|
108
|
+
checked_fwrite(&(k->l), sizeof(scs_int), 1, fout) < 0 ||
|
|
109
|
+
checked_fwrite(&(k->bsize), sizeof(scs_int), 1, fout) < 0 ||
|
|
110
|
+
write_float_array(k->bl, box_len, fout) < 0 ||
|
|
111
|
+
write_float_array(k->bu, box_len, fout) < 0 ||
|
|
112
|
+
checked_fwrite(&(k->qsize), sizeof(scs_int), 1, fout) < 0 ||
|
|
113
|
+
write_int_array(k->q, k->qsize, fout) < 0 ||
|
|
114
|
+
checked_fwrite(&(k->ssize), sizeof(scs_int), 1, fout) < 0 ||
|
|
115
|
+
write_int_array(k->s, k->ssize, fout) < 0 ||
|
|
116
|
+
checked_fwrite(&(k->ep), sizeof(scs_int), 1, fout) < 0 ||
|
|
117
|
+
checked_fwrite(&(k->ed), sizeof(scs_int), 1, fout) < 0 ||
|
|
118
|
+
checked_fwrite(&(k->psize), sizeof(scs_int), 1, fout) < 0 ||
|
|
119
|
+
write_float_array(k->p, k->psize, fout) < 0) {
|
|
120
|
+
return -1;
|
|
121
|
+
}
|
|
122
|
+
return 0;
|
|
49
123
|
}
|
|
50
124
|
|
|
51
125
|
/*
|
|
@@ -53,14 +127,26 @@ static void write_scs_cone(const ScsCone *k, FILE *fout) {
|
|
|
53
127
|
* different to scs_int then it will cast the ints after reading
|
|
54
128
|
* to be compatible with the SCS data types.
|
|
55
129
|
*/
|
|
56
|
-
static
|
|
57
|
-
|
|
130
|
+
static scs_int read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
|
|
131
|
+
FILE *fin) {
|
|
132
|
+
size_t val;
|
|
133
|
+
size_t i;
|
|
134
|
+
if (nitems == 0) {
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
58
137
|
if (file_int_sz == sizeof(scs_int)) {
|
|
59
|
-
return
|
|
138
|
+
return checked_fread(dest, sizeof(scs_int), nitems, fin);
|
|
60
139
|
}
|
|
61
140
|
void *ptr = scs_calloc(nitems, file_int_sz);
|
|
62
|
-
|
|
63
|
-
|
|
141
|
+
if (!ptr)
|
|
142
|
+
return -1;
|
|
143
|
+
val = fread(ptr, file_int_sz, nitems, fin);
|
|
144
|
+
if (val != nitems) {
|
|
145
|
+
scs_printf("Error: fread expected %lu integer items, got %lu\n",
|
|
146
|
+
(unsigned long)nitems, (unsigned long)val);
|
|
147
|
+
scs_free(ptr);
|
|
148
|
+
return -1;
|
|
149
|
+
}
|
|
64
150
|
switch (file_int_sz) {
|
|
65
151
|
case 4:
|
|
66
152
|
for (i = 0; i < nitems; ++i) {
|
|
@@ -72,152 +158,488 @@ static size_t read_int(scs_int *dest, size_t file_int_sz, size_t nitems,
|
|
|
72
158
|
dest[i] = (scs_int)(((long long *)ptr)[i]);
|
|
73
159
|
}
|
|
74
160
|
break;
|
|
75
|
-
|
|
76
|
-
|
|
161
|
+
default:
|
|
162
|
+
scs_printf("Error: unsupported integer size %lu in data file\n",
|
|
163
|
+
(unsigned long)file_int_sz);
|
|
77
164
|
scs_free(ptr);
|
|
165
|
+
return -1;
|
|
166
|
+
}
|
|
167
|
+
scs_free(ptr);
|
|
168
|
+
return 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
static scs_int read_int_array(scs_int **dest, scs_int n, size_t file_int_sz,
|
|
172
|
+
FILE *fin) {
|
|
173
|
+
*dest = SCS_NULL;
|
|
174
|
+
if (n < 0) {
|
|
175
|
+
scs_printf("Error: negative array length %li in data file\n", (long)n);
|
|
176
|
+
return -1;
|
|
177
|
+
}
|
|
178
|
+
if (n == 0) {
|
|
179
|
+
return 0;
|
|
180
|
+
}
|
|
181
|
+
*dest = (scs_int *)scs_calloc(n, sizeof(scs_int));
|
|
182
|
+
if (!*dest) {
|
|
183
|
+
return -1;
|
|
184
|
+
}
|
|
185
|
+
if (read_int(*dest, file_int_sz, (size_t)n, fin) < 0) {
|
|
186
|
+
scs_free(*dest);
|
|
187
|
+
*dest = SCS_NULL;
|
|
188
|
+
return -1;
|
|
78
189
|
}
|
|
79
|
-
return
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
static scs_int read_float_array(scs_float **dest, scs_int n, FILE *fin) {
|
|
194
|
+
*dest = SCS_NULL;
|
|
195
|
+
if (n < 0) {
|
|
196
|
+
scs_printf("Error: negative array length %li in data file\n", (long)n);
|
|
197
|
+
return -1;
|
|
198
|
+
}
|
|
199
|
+
if (n == 0) {
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
*dest = (scs_float *)scs_calloc(n, sizeof(scs_float));
|
|
203
|
+
if (!*dest) {
|
|
204
|
+
return -1;
|
|
205
|
+
}
|
|
206
|
+
if (checked_fread(*dest, sizeof(scs_float), (size_t)n, fin) < 0) {
|
|
207
|
+
scs_free(*dest);
|
|
208
|
+
*dest = SCS_NULL;
|
|
209
|
+
return -1;
|
|
210
|
+
}
|
|
211
|
+
return 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#ifndef USE_SPECTRAL_CONES
|
|
215
|
+
/* skipping helpers: a non-spectral build must step over spectral data */
|
|
216
|
+
static scs_int skip_bytes(FILE *fin, uint64_t bytes) {
|
|
217
|
+
unsigned char buf[4096];
|
|
218
|
+
while (bytes > 0) {
|
|
219
|
+
size_t chunk = bytes < sizeof(buf) ? (size_t)bytes : sizeof(buf);
|
|
220
|
+
if (checked_fread(buf, 1, chunk, fin) < 0) {
|
|
221
|
+
return -1;
|
|
222
|
+
}
|
|
223
|
+
bytes -= chunk;
|
|
224
|
+
}
|
|
225
|
+
return 0;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
static scs_int skip_int_array(FILE *fin, size_t file_int_sz, scs_int n) {
|
|
229
|
+
if (n < 0) {
|
|
230
|
+
scs_printf("Error: negative array length %li in data file\n", (long)n);
|
|
231
|
+
return -1;
|
|
232
|
+
}
|
|
233
|
+
return skip_bytes(fin, (uint64_t)n * (uint64_t)file_int_sz);
|
|
234
|
+
}
|
|
235
|
+
#endif
|
|
236
|
+
|
|
237
|
+
static ScsCone *free_cone_null(ScsCone *k) {
|
|
238
|
+
SCS(free_cone)(k);
|
|
239
|
+
return SCS_NULL;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
static ScsSettings *free_stgs_null(ScsSettings *s) {
|
|
243
|
+
scs_free(s);
|
|
244
|
+
return SCS_NULL;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static ScsMatrix *free_matrix_null(ScsMatrix *A) {
|
|
248
|
+
SCS(free_scs_matrix)(A);
|
|
249
|
+
return SCS_NULL;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static ScsData *free_data_null(ScsData *d) {
|
|
253
|
+
SCS(free_data)(d);
|
|
254
|
+
return SCS_NULL;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static scs_int read_data_cleanup(FILE *fin, ScsData **d, ScsCone **k,
|
|
258
|
+
ScsSettings **stgs) {
|
|
259
|
+
fclose(fin);
|
|
260
|
+
SCS(free_data)(*d);
|
|
261
|
+
SCS(free_cone)(*k);
|
|
262
|
+
scs_free(*stgs);
|
|
263
|
+
*d = SCS_NULL;
|
|
264
|
+
*k = SCS_NULL;
|
|
265
|
+
*stgs = SCS_NULL;
|
|
266
|
+
return -1;
|
|
80
267
|
}
|
|
81
268
|
|
|
82
269
|
static ScsCone *read_scs_cone(FILE *fin, size_t file_int_sz) {
|
|
270
|
+
scs_int box_len;
|
|
83
271
|
ScsCone *k = (ScsCone *)scs_calloc(1, sizeof(ScsCone));
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
read_int(&(k->
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
k->p = (scs_float *)scs_calloc(k->psize, sizeof(scs_float));
|
|
108
|
-
fread(k->p, sizeof(scs_float), k->psize, fin);
|
|
272
|
+
if (!k)
|
|
273
|
+
return SCS_NULL;
|
|
274
|
+
if (read_int(&(k->z), file_int_sz, 1, fin) < 0 ||
|
|
275
|
+
read_int(&(k->l), file_int_sz, 1, fin) < 0 ||
|
|
276
|
+
read_int(&(k->bsize), file_int_sz, 1, fin) < 0) {
|
|
277
|
+
return free_cone_null(k);
|
|
278
|
+
}
|
|
279
|
+
if (k->bsize < 0) {
|
|
280
|
+
scs_printf("Error: negative box cone size in data file\n");
|
|
281
|
+
return free_cone_null(k);
|
|
282
|
+
}
|
|
283
|
+
box_len = MAX(k->bsize - 1, 0);
|
|
284
|
+
if (read_float_array(&(k->bl), box_len, fin) < 0 ||
|
|
285
|
+
read_float_array(&(k->bu), box_len, fin) < 0 ||
|
|
286
|
+
read_int(&(k->qsize), file_int_sz, 1, fin) < 0 ||
|
|
287
|
+
read_int_array(&(k->q), k->qsize, file_int_sz, fin) < 0 ||
|
|
288
|
+
read_int(&(k->ssize), file_int_sz, 1, fin) < 0 ||
|
|
289
|
+
read_int_array(&(k->s), k->ssize, file_int_sz, fin) < 0 ||
|
|
290
|
+
read_int(&(k->ep), file_int_sz, 1, fin) < 0 ||
|
|
291
|
+
read_int(&(k->ed), file_int_sz, 1, fin) < 0 ||
|
|
292
|
+
read_int(&(k->psize), file_int_sz, 1, fin) < 0 ||
|
|
293
|
+
read_float_array(&(k->p), k->psize, fin) < 0) {
|
|
294
|
+
return free_cone_null(k);
|
|
109
295
|
}
|
|
110
296
|
return k;
|
|
111
297
|
}
|
|
112
298
|
|
|
113
|
-
static
|
|
299
|
+
static scs_int write_scs_stgs(const ScsSettings *s, FILE *fout) {
|
|
114
300
|
/* Warm start to false for now */
|
|
115
301
|
scs_int warm_start = 0;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
302
|
+
if (checked_fwrite(&(s->normalize), sizeof(scs_int), 1, fout) < 0 ||
|
|
303
|
+
checked_fwrite(&(s->scale), sizeof(scs_float), 1, fout) < 0 ||
|
|
304
|
+
checked_fwrite(&(s->rho_x), sizeof(scs_float), 1, fout) < 0 ||
|
|
305
|
+
checked_fwrite(&(s->max_iters), sizeof(scs_int), 1, fout) < 0 ||
|
|
306
|
+
checked_fwrite(&(s->eps_abs), sizeof(scs_float), 1, fout) < 0 ||
|
|
307
|
+
checked_fwrite(&(s->eps_rel), sizeof(scs_float), 1, fout) < 0 ||
|
|
308
|
+
checked_fwrite(&(s->eps_infeas), sizeof(scs_float), 1, fout) < 0 ||
|
|
309
|
+
checked_fwrite(&(s->alpha), sizeof(scs_float), 1, fout) < 0 ||
|
|
310
|
+
checked_fwrite(&(s->verbose), sizeof(scs_int), 1, fout) < 0 ||
|
|
311
|
+
checked_fwrite(&warm_start, sizeof(scs_int), 1, fout) < 0 ||
|
|
312
|
+
checked_fwrite(&(s->acceleration_lookback), sizeof(scs_int), 1, fout) <
|
|
313
|
+
0 ||
|
|
314
|
+
checked_fwrite(&(s->acceleration_interval), sizeof(scs_int), 1, fout) <
|
|
315
|
+
0 ||
|
|
316
|
+
checked_fwrite(&(s->acceleration_type_1), sizeof(scs_int), 1, fout) <
|
|
317
|
+
0 ||
|
|
318
|
+
checked_fwrite(&(s->acceleration_regularization), sizeof(scs_float), 1,
|
|
319
|
+
fout) < 0 ||
|
|
320
|
+
checked_fwrite(&(s->acceleration_relaxation), sizeof(scs_float), 1,
|
|
321
|
+
fout) < 0 ||
|
|
322
|
+
checked_fwrite(&(s->adaptive_scale), sizeof(scs_int), 1, fout) < 0) {
|
|
323
|
+
return -1;
|
|
324
|
+
}
|
|
129
325
|
/* Do not write the write_data_filename */
|
|
130
326
|
/* Do not write the log_csv_filename */
|
|
327
|
+
return 0;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* Return 1 if `ver` (e.g. "3.2.11") sorts before 3.3.0, using the
|
|
331
|
+
* numeric major/minor prefix. Unparseable strings are treated as old
|
|
332
|
+
* (the conservative choice: the legacy layout reads fewer bytes). */
|
|
333
|
+
static scs_int rw_version_before_330(const char *ver) {
|
|
334
|
+
long major, minor;
|
|
335
|
+
char *end;
|
|
336
|
+
major = strtol(ver, &end, 10);
|
|
337
|
+
if (end == ver || *end != '.') {
|
|
338
|
+
return 1;
|
|
339
|
+
}
|
|
340
|
+
minor = strtol(end + 1, &end, 10);
|
|
341
|
+
return (major < 3) || (major == 3 && minor < 3);
|
|
131
342
|
}
|
|
132
343
|
|
|
133
|
-
static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz
|
|
344
|
+
static ScsSettings *read_scs_stgs(FILE *fin, size_t file_int_sz,
|
|
345
|
+
scs_int legacy_settings) {
|
|
134
346
|
ScsSettings *s = (ScsSettings *)scs_calloc(1, sizeof(ScsSettings));
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
read_int(&(s->
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
347
|
+
if (!s)
|
|
348
|
+
return SCS_NULL;
|
|
349
|
+
scs_set_default_settings(s);
|
|
350
|
+
if (read_int(&(s->normalize), file_int_sz, 1, fin) < 0 ||
|
|
351
|
+
checked_fread(&(s->scale), sizeof(scs_float), 1, fin) < 0 ||
|
|
352
|
+
checked_fread(&(s->rho_x), sizeof(scs_float), 1, fin) < 0 ||
|
|
353
|
+
read_int(&(s->max_iters), file_int_sz, 1, fin) < 0 ||
|
|
354
|
+
checked_fread(&(s->eps_abs), sizeof(scs_float), 1, fin) < 0 ||
|
|
355
|
+
checked_fread(&(s->eps_rel), sizeof(scs_float), 1, fin) < 0 ||
|
|
356
|
+
checked_fread(&(s->eps_infeas), sizeof(scs_float), 1, fin) < 0 ||
|
|
357
|
+
checked_fread(&(s->alpha), sizeof(scs_float), 1, fin) < 0 ||
|
|
358
|
+
read_int(&(s->verbose), file_int_sz, 1, fin) < 0 ||
|
|
359
|
+
read_int(&(s->warm_start), file_int_sz, 1, fin) < 0 ||
|
|
360
|
+
read_int(&(s->acceleration_lookback), file_int_sz, 1, fin) < 0 ||
|
|
361
|
+
read_int(&(s->acceleration_interval), file_int_sz, 1, fin) < 0) {
|
|
362
|
+
return free_stgs_null(s);
|
|
363
|
+
}
|
|
364
|
+
if (legacy_settings) {
|
|
365
|
+
if (read_int(&(s->adaptive_scale), file_int_sz, 1, fin) < 0) {
|
|
366
|
+
return free_stgs_null(s);
|
|
367
|
+
}
|
|
368
|
+
} else if (read_int(&(s->acceleration_type_1), file_int_sz, 1, fin) < 0 ||
|
|
369
|
+
checked_fread(&(s->acceleration_regularization),
|
|
370
|
+
sizeof(scs_float), 1, fin) < 0 ||
|
|
371
|
+
checked_fread(&(s->acceleration_relaxation), sizeof(scs_float), 1,
|
|
372
|
+
fin) < 0 ||
|
|
373
|
+
read_int(&(s->adaptive_scale), file_int_sz, 1, fin) < 0) {
|
|
374
|
+
return free_stgs_null(s);
|
|
375
|
+
}
|
|
148
376
|
return s;
|
|
149
377
|
}
|
|
150
378
|
|
|
151
|
-
static
|
|
379
|
+
static scs_int write_amatrix(const ScsMatrix *A, FILE *fout) {
|
|
152
380
|
scs_int Anz = A->p[A->n];
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
381
|
+
if (Anz < 0) {
|
|
382
|
+
scs_printf("Error: matrix has negative nonzero count %li\n", (long)Anz);
|
|
383
|
+
return -1;
|
|
384
|
+
}
|
|
385
|
+
if (checked_fwrite(&(A->m), sizeof(scs_int), 1, fout) < 0 ||
|
|
386
|
+
checked_fwrite(&(A->n), sizeof(scs_int), 1, fout) < 0 ||
|
|
387
|
+
write_int_array(A->p, A->n + 1, fout) < 0 ||
|
|
388
|
+
write_float_array(A->x, Anz, fout) < 0 ||
|
|
389
|
+
write_int_array(A->i, Anz, fout) < 0) {
|
|
390
|
+
return -1;
|
|
391
|
+
}
|
|
392
|
+
return 0;
|
|
158
393
|
}
|
|
159
394
|
|
|
160
395
|
static ScsMatrix *read_amatrix(FILE *fin, size_t file_int_sz) {
|
|
161
396
|
scs_int Anz;
|
|
162
397
|
ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
|
|
163
|
-
|
|
164
|
-
|
|
398
|
+
if (!A)
|
|
399
|
+
return SCS_NULL;
|
|
400
|
+
if (read_int(&(A->m), file_int_sz, 1, fin) < 0 ||
|
|
401
|
+
read_int(&(A->n), file_int_sz, 1, fin) < 0) {
|
|
402
|
+
return free_matrix_null(A);
|
|
403
|
+
}
|
|
404
|
+
if (A->m < 0 || A->n < 0) {
|
|
405
|
+
scs_printf("Error: negative matrix dimensions in data file\n");
|
|
406
|
+
return free_matrix_null(A);
|
|
407
|
+
}
|
|
165
408
|
A->p = (scs_int *)scs_calloc(A->n + 1, sizeof(scs_int));
|
|
166
|
-
read_int(A->p, file_int_sz, A->n + 1, fin)
|
|
409
|
+
if (!A->p || read_int(A->p, file_int_sz, A->n + 1, fin) < 0) {
|
|
410
|
+
return free_matrix_null(A);
|
|
411
|
+
}
|
|
167
412
|
Anz = A->p[A->n];
|
|
413
|
+
if (Anz < 0) {
|
|
414
|
+
scs_printf("Error: negative matrix nonzero count in data file\n");
|
|
415
|
+
return free_matrix_null(A);
|
|
416
|
+
}
|
|
168
417
|
A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
|
|
169
418
|
A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
|
|
170
|
-
|
|
171
|
-
|
|
419
|
+
if (!A->x || !A->i ||
|
|
420
|
+
checked_fread(A->x, sizeof(scs_float), Anz, fin) < 0 ||
|
|
421
|
+
read_int(A->i, file_int_sz, Anz, fin) < 0) {
|
|
422
|
+
return free_matrix_null(A);
|
|
423
|
+
}
|
|
172
424
|
return A;
|
|
173
425
|
}
|
|
174
426
|
|
|
175
|
-
static
|
|
427
|
+
static scs_int write_scs_data(const ScsData *d, FILE *fout) {
|
|
176
428
|
scs_int has_p = d->P ? 1 : 0;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
429
|
+
if (checked_fwrite(&(d->m), sizeof(scs_int), 1, fout) < 0 ||
|
|
430
|
+
checked_fwrite(&(d->n), sizeof(scs_int), 1, fout) < 0 ||
|
|
431
|
+
write_float_array(d->b, d->m, fout) < 0 ||
|
|
432
|
+
write_float_array(d->c, d->n, fout) < 0 ||
|
|
433
|
+
write_amatrix(d->A, fout) < 0) {
|
|
434
|
+
return -1;
|
|
435
|
+
}
|
|
182
436
|
/* write has P bit */
|
|
183
|
-
|
|
437
|
+
if (checked_fwrite(&has_p, sizeof(scs_int), 1, fout) < 0) {
|
|
438
|
+
return -1;
|
|
439
|
+
}
|
|
184
440
|
if (d->P) {
|
|
185
|
-
write_amatrix(d->P, fout);
|
|
441
|
+
return write_amatrix(d->P, fout);
|
|
186
442
|
}
|
|
443
|
+
return 0;
|
|
187
444
|
}
|
|
188
445
|
|
|
189
446
|
static ScsData *read_scs_data(FILE *fin, size_t file_int_sz) {
|
|
190
447
|
scs_int has_p = 0;
|
|
191
448
|
ScsData *d = (ScsData *)scs_calloc(1, sizeof(ScsData));
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
read_int(&(d->
|
|
449
|
+
if (!d)
|
|
450
|
+
return SCS_NULL;
|
|
451
|
+
if (read_int(&(d->m), file_int_sz, 1, fin) < 0 ||
|
|
452
|
+
read_int(&(d->n), file_int_sz, 1, fin) < 0) {
|
|
453
|
+
return free_data_null(d);
|
|
454
|
+
}
|
|
455
|
+
if (d->m < 0 || d->n < 0) {
|
|
456
|
+
scs_printf("Error: negative problem dimensions in data file\n");
|
|
457
|
+
return free_data_null(d);
|
|
458
|
+
}
|
|
195
459
|
d->b = (scs_float *)scs_calloc(d->m, sizeof(scs_float));
|
|
196
460
|
d->c = (scs_float *)scs_calloc(d->n, sizeof(scs_float));
|
|
197
|
-
|
|
198
|
-
|
|
461
|
+
if (!d->b || !d->c ||
|
|
462
|
+
checked_fread(d->b, sizeof(scs_float), d->m, fin) < 0 ||
|
|
463
|
+
checked_fread(d->c, sizeof(scs_float), d->n, fin) < 0) {
|
|
464
|
+
return free_data_null(d);
|
|
465
|
+
}
|
|
199
466
|
d->A = read_amatrix(fin, file_int_sz);
|
|
467
|
+
if (!d->A) {
|
|
468
|
+
return free_data_null(d);
|
|
469
|
+
}
|
|
200
470
|
/* If has_p bit is not set or this hits end of file then has_p = 0 */
|
|
201
|
-
|
|
471
|
+
if (read_int(&has_p, file_int_sz, 1, fin) < 0) {
|
|
472
|
+
return free_data_null(d);
|
|
473
|
+
}
|
|
202
474
|
d->P = has_p ? read_amatrix(fin, file_int_sz) : SCS_NULL;
|
|
475
|
+
if (has_p && !d->P) {
|
|
476
|
+
return free_data_null(d);
|
|
477
|
+
}
|
|
203
478
|
return d;
|
|
204
479
|
}
|
|
205
480
|
|
|
481
|
+
static scs_int write_ext_int_array(const scs_int *x, scs_int n, FILE *fout) {
|
|
482
|
+
if (checked_fwrite(&n, sizeof(scs_int), 1, fout) < 0) {
|
|
483
|
+
return -1;
|
|
484
|
+
}
|
|
485
|
+
return write_int_array(x, n, fout);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
static scs_int write_scs_extensions(const ScsCone *k, const ScsSettings *s,
|
|
489
|
+
FILE *fout) {
|
|
490
|
+
#ifndef USE_SPECTRAL_CONES
|
|
491
|
+
scs_int zero = 0;
|
|
492
|
+
#endif
|
|
493
|
+
uint32_t magic = RW_EXT_MAGIC;
|
|
494
|
+
uint32_t version = RW_EXT_VERSION;
|
|
495
|
+
if (checked_fwrite(&magic, sizeof(uint32_t), 1, fout) < 0 ||
|
|
496
|
+
checked_fwrite(&version, sizeof(uint32_t), 1, fout) < 0 ||
|
|
497
|
+
write_ext_int_array(k->cs, k->cssize, fout) < 0) {
|
|
498
|
+
return -1;
|
|
499
|
+
}
|
|
500
|
+
#ifdef USE_SPECTRAL_CONES
|
|
501
|
+
if (write_ext_int_array(k->d, k->dsize, fout) < 0 ||
|
|
502
|
+
checked_fwrite(&(k->nucsize), sizeof(scs_int), 1, fout) < 0 ||
|
|
503
|
+
write_int_array(k->nuc_m, k->nucsize, fout) < 0 ||
|
|
504
|
+
write_int_array(k->nuc_n, k->nucsize, fout) < 0 ||
|
|
505
|
+
write_ext_int_array(k->ell1, k->ell1_size, fout) < 0 ||
|
|
506
|
+
checked_fwrite(&(k->sl_size), sizeof(scs_int), 1, fout) < 0 ||
|
|
507
|
+
write_int_array(k->sl_n, k->sl_size, fout) < 0 ||
|
|
508
|
+
write_int_array(k->sl_k, k->sl_size, fout) < 0) {
|
|
509
|
+
return -1;
|
|
510
|
+
}
|
|
511
|
+
#else
|
|
512
|
+
if (write_ext_int_array(SCS_NULL, zero, fout) < 0 ||
|
|
513
|
+
checked_fwrite(&zero, sizeof(scs_int), 1, fout) < 0 ||
|
|
514
|
+
write_int_array(SCS_NULL, zero, fout) < 0 ||
|
|
515
|
+
write_int_array(SCS_NULL, zero, fout) < 0 ||
|
|
516
|
+
write_ext_int_array(SCS_NULL, zero, fout) < 0 ||
|
|
517
|
+
checked_fwrite(&zero, sizeof(scs_int), 1, fout) < 0 ||
|
|
518
|
+
write_int_array(SCS_NULL, zero, fout) < 0 ||
|
|
519
|
+
write_int_array(SCS_NULL, zero, fout) < 0) {
|
|
520
|
+
return -1;
|
|
521
|
+
}
|
|
522
|
+
#endif
|
|
523
|
+
if (checked_fwrite(&(s->time_limit_secs), sizeof(scs_float), 1, fout) < 0) {
|
|
524
|
+
return -1;
|
|
525
|
+
}
|
|
526
|
+
/* v2 fields */
|
|
527
|
+
return checked_fwrite(&(s->adaptive_diag_scale), sizeof(scs_int), 1, fout);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
static scs_int read_ext_int_array(scs_int **dest, scs_int *n,
|
|
531
|
+
size_t file_int_sz, FILE *fin) {
|
|
532
|
+
if (read_int(n, file_int_sz, 1, fin) < 0) {
|
|
533
|
+
return -1;
|
|
534
|
+
}
|
|
535
|
+
return read_int_array(dest, *n, file_int_sz, fin);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
static scs_int read_scs_extensions(FILE *fin, size_t file_int_sz, ScsCone *k,
|
|
539
|
+
ScsSettings *s) {
|
|
540
|
+
unsigned char magic_buf[sizeof(uint32_t)];
|
|
541
|
+
uint32_t magic, version;
|
|
542
|
+
scs_int dsize, nucsize, sl_size;
|
|
543
|
+
#ifndef USE_SPECTRAL_CONES
|
|
544
|
+
scs_int ell1_size; /* only the skipping path needs it */
|
|
545
|
+
#endif
|
|
546
|
+
size_t ret = fread(magic_buf, 1, sizeof(magic_buf), fin);
|
|
547
|
+
if (ret == 0 && feof(fin)) {
|
|
548
|
+
return 0;
|
|
549
|
+
}
|
|
550
|
+
if (ret != sizeof(magic_buf)) {
|
|
551
|
+
scs_printf("Error: incomplete read/write extension header\n");
|
|
552
|
+
return -1;
|
|
553
|
+
}
|
|
554
|
+
memcpy(&magic, magic_buf, sizeof(magic));
|
|
555
|
+
if (magic != RW_EXT_MAGIC) {
|
|
556
|
+
scs_printf("Warning: ignoring unrecognized trailing data in SCS file\n");
|
|
557
|
+
return 0;
|
|
558
|
+
}
|
|
559
|
+
if (checked_fread(&version, sizeof(uint32_t), 1, fin) < 0) {
|
|
560
|
+
return -1;
|
|
561
|
+
}
|
|
562
|
+
if (version > RW_EXT_VERSION) {
|
|
563
|
+
scs_printf("Error: SCS file uses read/write schema version %lu, this "
|
|
564
|
+
"build supports up to %lu\n",
|
|
565
|
+
(unsigned long)version, (unsigned long)RW_EXT_VERSION);
|
|
566
|
+
return -1;
|
|
567
|
+
}
|
|
568
|
+
if (read_ext_int_array(&(k->cs), &(k->cssize), file_int_sz, fin) < 0 ||
|
|
569
|
+
read_int(&dsize, file_int_sz, 1, fin) < 0) {
|
|
570
|
+
return -1;
|
|
571
|
+
}
|
|
572
|
+
#ifdef USE_SPECTRAL_CONES
|
|
573
|
+
k->dsize = dsize;
|
|
574
|
+
if (read_int_array(&(k->d), k->dsize, file_int_sz, fin) < 0 ||
|
|
575
|
+
read_int(&nucsize, file_int_sz, 1, fin) < 0) {
|
|
576
|
+
return -1;
|
|
577
|
+
}
|
|
578
|
+
k->nucsize = nucsize;
|
|
579
|
+
if (read_int_array(&(k->nuc_m), k->nucsize, file_int_sz, fin) < 0 ||
|
|
580
|
+
read_int_array(&(k->nuc_n), k->nucsize, file_int_sz, fin) < 0 ||
|
|
581
|
+
read_ext_int_array(&(k->ell1), &(k->ell1_size), file_int_sz, fin) < 0 ||
|
|
582
|
+
read_int(&sl_size, file_int_sz, 1, fin) < 0) {
|
|
583
|
+
return -1;
|
|
584
|
+
}
|
|
585
|
+
k->sl_size = sl_size;
|
|
586
|
+
if (read_int_array(&(k->sl_n), k->sl_size, file_int_sz, fin) < 0 ||
|
|
587
|
+
read_int_array(&(k->sl_k), k->sl_size, file_int_sz, fin) < 0) {
|
|
588
|
+
return -1;
|
|
589
|
+
}
|
|
590
|
+
#else
|
|
591
|
+
if (skip_int_array(fin, file_int_sz, dsize) < 0 ||
|
|
592
|
+
read_int(&nucsize, file_int_sz, 1, fin) < 0 ||
|
|
593
|
+
skip_int_array(fin, file_int_sz, nucsize) < 0 ||
|
|
594
|
+
skip_int_array(fin, file_int_sz, nucsize) < 0 ||
|
|
595
|
+
read_int(&ell1_size, file_int_sz, 1, fin) < 0 ||
|
|
596
|
+
skip_int_array(fin, file_int_sz, ell1_size) < 0 ||
|
|
597
|
+
read_int(&sl_size, file_int_sz, 1, fin) < 0 ||
|
|
598
|
+
skip_int_array(fin, file_int_sz, sl_size) < 0 ||
|
|
599
|
+
skip_int_array(fin, file_int_sz, sl_size) < 0) {
|
|
600
|
+
return -1;
|
|
601
|
+
}
|
|
602
|
+
#endif
|
|
603
|
+
if (checked_fread(&(s->time_limit_secs), sizeof(scs_float), 1, fin) < 0) {
|
|
604
|
+
return -1;
|
|
605
|
+
}
|
|
606
|
+
if (version >= 2) {
|
|
607
|
+
if (read_int(&(s->adaptive_diag_scale), file_int_sz, 1, fin) < 0) {
|
|
608
|
+
return -1;
|
|
609
|
+
}
|
|
610
|
+
} /* else: scs_set_default_settings value stands */
|
|
611
|
+
return 0;
|
|
612
|
+
}
|
|
613
|
+
|
|
206
614
|
void SCS(write_data)(const ScsData *d, const ScsCone *k,
|
|
207
615
|
const ScsSettings *stgs) {
|
|
208
616
|
FILE *fout = fopen(stgs->write_data_filename, "wb");
|
|
617
|
+
scs_int status = 0;
|
|
618
|
+
if (!fout) {
|
|
619
|
+
scs_printf("Error: could not open %s for writing\n",
|
|
620
|
+
stgs->write_data_filename);
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
209
623
|
uint32_t scs_int_sz = (uint32_t)sizeof(scs_int);
|
|
210
624
|
uint32_t scs_float_sz = (uint32_t)sizeof(scs_float);
|
|
211
625
|
const char *scs_version = SCS_VERSION;
|
|
212
626
|
uint32_t scs_version_sz = (uint32_t)strlen(scs_version);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
627
|
+
if (checked_fwrite(&(scs_int_sz), sizeof(uint32_t), 1, fout) < 0 ||
|
|
628
|
+
checked_fwrite(&(scs_float_sz), sizeof(uint32_t), 1, fout) < 0 ||
|
|
629
|
+
checked_fwrite(&(scs_version_sz), sizeof(uint32_t), 1, fout) < 0 ||
|
|
630
|
+
checked_fwrite(scs_version, 1, scs_version_sz, fout) < 0 ||
|
|
631
|
+
write_scs_cone(k, fout) < 0 || write_scs_data(d, fout) < 0 ||
|
|
632
|
+
write_scs_stgs(stgs, fout) < 0 ||
|
|
633
|
+
write_scs_extensions(k, stgs, fout) < 0) {
|
|
634
|
+
status = -1;
|
|
635
|
+
}
|
|
636
|
+
if (fclose(fout) != 0) {
|
|
637
|
+
status = -1;
|
|
638
|
+
}
|
|
639
|
+
if (status < 0) {
|
|
640
|
+
scs_printf("Error: failed writing SCS data to %s\n",
|
|
641
|
+
stgs->write_data_filename);
|
|
642
|
+
}
|
|
221
643
|
}
|
|
222
644
|
|
|
223
645
|
scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
@@ -226,16 +648,27 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
|
226
648
|
uint32_t file_float_sz;
|
|
227
649
|
uint32_t file_version_sz;
|
|
228
650
|
char file_version[16];
|
|
651
|
+
scs_int legacy_settings;
|
|
229
652
|
errno = 0;
|
|
230
653
|
FILE *fin = fopen(filename, "rb");
|
|
654
|
+
*d = SCS_NULL;
|
|
655
|
+
*k = SCS_NULL;
|
|
656
|
+
*stgs = SCS_NULL;
|
|
231
657
|
if (!fin) {
|
|
232
658
|
scs_printf("Error reading file %s\n", filename);
|
|
233
659
|
scs_printf("errno:%i:%s\n", errno, strerror(errno));
|
|
234
660
|
return -1;
|
|
235
661
|
}
|
|
236
662
|
scs_printf("Reading data from %s\n", filename);
|
|
237
|
-
|
|
238
|
-
|
|
663
|
+
if (checked_fread(&(file_int_sz), sizeof(uint32_t), 1, fin) < 0 ||
|
|
664
|
+
checked_fread(&(file_float_sz), sizeof(uint32_t), 1, fin) < 0) {
|
|
665
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
666
|
+
}
|
|
667
|
+
if (file_int_sz != 4 && file_int_sz != 8) {
|
|
668
|
+
scs_printf("Error: unsupported file integer size %lu\n",
|
|
669
|
+
(unsigned long)file_int_sz);
|
|
670
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
671
|
+
}
|
|
239
672
|
if (file_int_sz != (uint32_t)sizeof(scs_int)) {
|
|
240
673
|
scs_printf(
|
|
241
674
|
"Warning, sizeof(file int) is %lu, but scs expects sizeof(int) %lu. "
|
|
@@ -248,12 +681,23 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
|
248
681
|
"Error, sizeof(file float) is %lu, but scs expects sizeof(float) %lu, "
|
|
249
682
|
"scs should be recompiled with the correct flags.\n",
|
|
250
683
|
(unsigned long)file_float_sz, (unsigned long)sizeof(scs_float));
|
|
251
|
-
|
|
252
|
-
|
|
684
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
685
|
+
}
|
|
686
|
+
if (checked_fread(&(file_version_sz), sizeof(uint32_t), 1, fin) < 0) {
|
|
687
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
688
|
+
}
|
|
689
|
+
if (file_version_sz >= sizeof(file_version)) {
|
|
690
|
+
scs_printf("Error: file version string length %lu exceeds buffer size\n",
|
|
691
|
+
(unsigned long)file_version_sz);
|
|
692
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
693
|
+
}
|
|
694
|
+
if (checked_fread(file_version, 1, file_version_sz, fin) < 0) {
|
|
695
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
253
696
|
}
|
|
254
|
-
fread(&(file_version_sz), sizeof(uint32_t), 1, fin);
|
|
255
|
-
fread(file_version, 1, file_version_sz, fin);
|
|
256
697
|
file_version[file_version_sz] = '\0';
|
|
698
|
+
/* the settings-block layout changed in 3.3.0; key it off major.minor so
|
|
699
|
+
* files from other 3.3.x builds parse */
|
|
700
|
+
legacy_settings = rw_version_before_330(file_version);
|
|
257
701
|
if (strcmp(file_version, SCS_VERSION) != 0) {
|
|
258
702
|
scs_printf("************************************************************\n"
|
|
259
703
|
"Warning: SCS file version %s, this is SCS version %s.\n"
|
|
@@ -262,25 +706,54 @@ scs_int SCS(read_data)(const char *filename, ScsData **d, ScsCone **k,
|
|
|
262
706
|
file_version, SCS_VERSION);
|
|
263
707
|
}
|
|
264
708
|
*k = read_scs_cone(fin, file_int_sz);
|
|
709
|
+
if (!*k) {
|
|
710
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
711
|
+
}
|
|
265
712
|
*d = read_scs_data(fin, file_int_sz);
|
|
266
|
-
|
|
713
|
+
if (!*d) {
|
|
714
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
715
|
+
}
|
|
716
|
+
*stgs = read_scs_stgs(fin, file_int_sz, legacy_settings);
|
|
717
|
+
if (!*stgs) {
|
|
718
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
719
|
+
}
|
|
720
|
+
if (read_scs_extensions(fin, file_int_sz, *k, *stgs) < 0) {
|
|
721
|
+
return read_data_cleanup(fin, d, k, stgs);
|
|
722
|
+
}
|
|
267
723
|
scs_printf("Finished reading data.\n");
|
|
268
724
|
fclose(fin);
|
|
269
725
|
return 0;
|
|
270
726
|
}
|
|
271
727
|
|
|
272
|
-
|
|
273
|
-
|
|
728
|
+
scs_int SCS(open_csv_log_file)(ScsWork *w) {
|
|
729
|
+
if (!w || !w->stgs || !w->stgs->log_csv_filename) {
|
|
730
|
+
return 0;
|
|
731
|
+
}
|
|
732
|
+
SCS(close_csv_log_file)(w);
|
|
733
|
+
w->log_csv_fout = fopen(w->stgs->log_csv_filename, "w");
|
|
734
|
+
if (!w->log_csv_fout) {
|
|
735
|
+
scs_printf("Error: Could not open %s for writing\n",
|
|
736
|
+
w->stgs->log_csv_filename);
|
|
737
|
+
return -1;
|
|
738
|
+
}
|
|
739
|
+
return 0;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
void SCS(close_csv_log_file)(ScsWork *w) {
|
|
743
|
+
if (w && w->log_csv_fout) {
|
|
744
|
+
fclose(w->log_csv_fout);
|
|
745
|
+
w->log_csv_fout = SCS_NULL;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
void SCS(log_data_to_csv)(const ScsCone *k, const ScsWork *w, scs_int iter,
|
|
274
750
|
SCS(timer) * solve_timer) {
|
|
275
751
|
ScsResiduals *r = w->r_orig;
|
|
276
752
|
ScsResiduals *r_n = w->r_normalized;
|
|
277
753
|
ScsSolution *sol = w->xys_orig;
|
|
278
754
|
ScsSolution *sol_n = w->xys_normalized;
|
|
279
|
-
|
|
280
|
-
FILE *fout = fopen(stgs->log_csv_filename, iter == 0 ? "w" : "a");
|
|
755
|
+
FILE *fout = w->log_csv_fout;
|
|
281
756
|
if (!fout) {
|
|
282
|
-
scs_printf("Error: Could not open %s for writing\n",
|
|
283
|
-
stgs->log_csv_filename);
|
|
284
757
|
return;
|
|
285
758
|
}
|
|
286
759
|
scs_int l = w->d->m + w->d->n + 1;
|
|
@@ -427,7 +900,6 @@ void SCS(log_data_to_csv)(const ScsCone *k, const ScsSettings *stgs,
|
|
|
427
900
|
fprintf(fout, "%.16e,", w->cone_work->newton_stats.residuals[2]);
|
|
428
901
|
#endif
|
|
429
902
|
fprintf(fout, "\n");
|
|
430
|
-
fclose(fout);
|
|
431
903
|
}
|
|
432
904
|
|
|
433
905
|
#endif
|