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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/LICENSE.txt +18 -18
  4. data/README.md +19 -14
  5. data/lib/scs/ffi.rb +31 -20
  6. data/lib/scs/solver.rb +32 -9
  7. data/lib/scs/version.rb +1 -1
  8. data/vendor/scs/CITATION.cff +39 -0
  9. data/vendor/scs/CMakeLists.txt +320 -0
  10. data/vendor/scs/Makefile +32 -23
  11. data/vendor/scs/README.md +9 -218
  12. data/vendor/scs/include/aa.h +67 -23
  13. data/vendor/scs/include/cones.h +22 -19
  14. data/vendor/scs/include/glbopts.h +107 -79
  15. data/vendor/scs/include/linalg.h +3 -4
  16. data/vendor/scs/include/linsys.h +58 -44
  17. data/vendor/scs/include/normalize.h +6 -5
  18. data/vendor/scs/include/rw.h +8 -2
  19. data/vendor/scs/include/scs.h +257 -141
  20. data/vendor/scs/include/scs_types.h +34 -0
  21. data/vendor/scs/include/scs_work.h +83 -0
  22. data/vendor/scs/include/util.h +3 -15
  23. data/vendor/scs/linsys/cpu/direct/private.c +241 -232
  24. data/vendor/scs/linsys/cpu/direct/private.h +13 -7
  25. data/vendor/scs/linsys/cpu/indirect/private.c +194 -118
  26. data/vendor/scs/linsys/cpu/indirect/private.h +7 -4
  27. data/vendor/scs/linsys/csparse.c +87 -0
  28. data/vendor/scs/linsys/csparse.h +34 -0
  29. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +6 -6
  30. data/vendor/scs/linsys/external/amd/SuiteSparse_config.h +6 -1
  31. data/vendor/scs/linsys/external/amd/amd_internal.h +1 -1
  32. data/vendor/scs/linsys/external/amd/amd_order.c +5 -5
  33. data/vendor/scs/linsys/external/qdldl/changes +2 -0
  34. data/vendor/scs/linsys/external/qdldl/qdldl.c +29 -46
  35. data/vendor/scs/linsys/external/qdldl/qdldl.h +33 -41
  36. data/vendor/scs/linsys/external/qdldl/qdldl_types.h +11 -3
  37. data/vendor/scs/linsys/gpu/gpu.c +58 -21
  38. data/vendor/scs/linsys/gpu/gpu.h +70 -35
  39. data/vendor/scs/linsys/gpu/indirect/private.c +394 -157
  40. data/vendor/scs/linsys/gpu/indirect/private.h +27 -12
  41. data/vendor/scs/linsys/scs_matrix.c +478 -0
  42. data/vendor/scs/linsys/scs_matrix.h +70 -0
  43. data/vendor/scs/scs.mk +14 -10
  44. data/vendor/scs/src/aa.c +394 -110
  45. data/vendor/scs/src/cones.c +497 -359
  46. data/vendor/scs/src/ctrlc.c +15 -5
  47. data/vendor/scs/src/linalg.c +107 -26
  48. data/vendor/scs/src/normalize.c +30 -72
  49. data/vendor/scs/src/rw.c +202 -27
  50. data/vendor/scs/src/scs.c +769 -571
  51. data/vendor/scs/src/scs_version.c +11 -3
  52. data/vendor/scs/src/util.c +37 -106
  53. data/vendor/scs/test/minunit.h +22 -8
  54. data/vendor/scs/test/problem_utils.h +180 -25
  55. data/vendor/scs/test/problems/degenerate.h +130 -0
  56. data/vendor/scs/test/problems/hs21_tiny_qp.h +124 -0
  57. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +116 -0
  58. data/vendor/scs/test/problems/infeasible_tiny_qp.h +100 -0
  59. data/vendor/scs/test/problems/qafiro_tiny_qp.h +199 -0
  60. data/vendor/scs/test/problems/random_prob +0 -0
  61. data/vendor/scs/test/problems/random_prob.h +45 -0
  62. data/vendor/scs/test/problems/rob_gauss_cov_est.h +188 -31
  63. data/vendor/scs/test/problems/small_lp.h +14 -13
  64. data/vendor/scs/test/problems/small_qp.h +352 -0
  65. data/vendor/scs/test/problems/test_validation.h +43 -0
  66. data/vendor/scs/test/problems/unbounded_tiny_qp.h +82 -0
  67. data/vendor/scs/test/random_socp_prob.c +54 -53
  68. data/vendor/scs/test/rng.h +109 -0
  69. data/vendor/scs/test/run_from_file.c +20 -11
  70. data/vendor/scs/test/run_tests.c +35 -2
  71. metadata +29 -98
  72. data/vendor/scs/linsys/amatrix.c +0 -305
  73. data/vendor/scs/linsys/amatrix.h +0 -36
  74. data/vendor/scs/linsys/amatrix.o +0 -0
  75. data/vendor/scs/linsys/cpu/direct/private.o +0 -0
  76. data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
  77. data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
  78. data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
  79. data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
  80. data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
  81. data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
  82. data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
  83. data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
  84. data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
  85. data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
  86. data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
  87. data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
  88. data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
  89. data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
  90. data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
  91. data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
  92. data/vendor/scs/src/aa.o +0 -0
  93. data/vendor/scs/src/cones.o +0 -0
  94. data/vendor/scs/src/ctrlc.o +0 -0
  95. data/vendor/scs/src/linalg.o +0 -0
  96. data/vendor/scs/src/normalize.o +0 -0
  97. data/vendor/scs/src/rw.o +0 -0
  98. data/vendor/scs/src/scs.o +0 -0
  99. data/vendor/scs/src/scs_version.o +0 -0
  100. data/vendor/scs/src/util.o +0 -0
  101. data/vendor/scs/test/data/small_random_socp +0 -0
  102. data/vendor/scs/test/problems/small_random_socp.h +0 -33
  103. data/vendor/scs/test/run_tests +0 -2
@@ -5,29 +5,44 @@
5
5
  extern "C" {
6
6
  #endif
7
7
 
8
- #include "gpu.h"
8
+ #include "csparse.h"
9
9
  #include "glbopts.h"
10
+ #include "gpu.h"
10
11
  #include "linalg.h"
11
12
  #include "scs.h"
12
13
 
13
-
14
14
  struct SCS_LIN_SYS_WORK {
15
+ scs_int n, m; /* linear system dimensions */
15
16
  /* reporting */
16
17
  scs_int tot_cg_its;
17
- scs_float total_solve_time;
18
+ scs_float *M; /* preconditioner on cpu */
18
19
  /* ALL BELOW HOSTED ON THE GPU */
19
- scs_float *p; /* cg iterate, n */
20
- scs_float *r; /* cg residual, n */
21
- scs_float *Gp; /* G * p, n */
22
- scs_float *bg; /* b, n */
23
- scs_float *tmp_m; /* m, used in mat_vec */
24
- scs_float *z; /* preconditioned */
25
- scs_float *M; /* preconditioner */
26
- ScsGpuMatrix *Ag; /* A matrix on GPU */
27
- ScsGpuMatrix *Agt; /* A trans matrix on GPU */
20
+ scs_float *p; /* cg iterate, n */
21
+ scs_float *r; /* cg residual, n */
22
+ scs_float *Gp; /* G * p, n */
23
+ scs_float *bg; /* b, n */
24
+ scs_float *tmp_m; /* m, used in mat_vec */
25
+ scs_float *z; /* preconditioned */
26
+ scs_float *M_gpu; /* preconditioner */
27
+ const ScsMatrix *A; /* does *not* own this memory */
28
+ const ScsMatrix *P; /* does *not* own this memory */
29
+ ScsGpuMatrix *Ag; /* A matrix on GPU */
30
+ ScsGpuMatrix *Agt; /* A trans matrix on GPU */
31
+ ScsGpuMatrix *Pg; /* P matrix on GPU */
28
32
  /* CUDA */
29
33
  cublasHandle_t cublas_handle;
30
34
  cusparseHandle_t cusparse_handle;
35
+ /* CUSPARSE */
36
+ size_t buffer_size;
37
+ void *buffer;
38
+ cusparseDnVecDescr_t dn_vec_m; /* Dense vector of length m */
39
+ cusparseDnVecDescr_t dn_vec_n; /* Dense vector of length n */
40
+ cusparseDnVecDescr_t dn_vec_n_p; /* Dense vector of length n */
41
+
42
+ /* rho terms */
43
+ scs_float *r_x_gpu;
44
+ scs_float *inv_r_y; /* inverse R_y */
45
+ scs_float *inv_r_y_gpu; /* inverse R_y on GPU */
31
46
  };
32
47
 
33
48
  #ifdef __cplusplus
@@ -0,0 +1,478 @@
1
+ /* contains routines common to direct and indirect sparse solvers */
2
+ #include "scs_matrix.h"
3
+ #include "linalg.h"
4
+ #include "linsys.h"
5
+ #include "util.h"
6
+
7
+ #define MIN_NORMALIZATION_FACTOR (1e-4)
8
+ #define MAX_NORMALIZATION_FACTOR (1e4)
9
+ #define NUM_RUIZ_PASSES (25) /* additional passes don't help much */
10
+ #define NUM_L2_PASSES (1) /* do one or zero, not more since not stable */
11
+
12
+ scs_int SCS(copy_matrix)(ScsMatrix **dstp, const ScsMatrix *src) {
13
+ scs_int Anz = src->p[src->n];
14
+ ScsMatrix *A = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
15
+ if (!A) {
16
+ return 0;
17
+ }
18
+ A->n = src->n;
19
+ A->m = src->m;
20
+ /* A values, size: NNZ A */
21
+ A->x = (scs_float *)scs_calloc(Anz, sizeof(scs_float));
22
+ /* A row index, size: NNZ A */
23
+ A->i = (scs_int *)scs_calloc(Anz, sizeof(scs_int));
24
+ /* A column pointer, size: n+1 */
25
+ A->p = (scs_int *)scs_calloc(src->n + 1, sizeof(scs_int));
26
+ if (!A->x || !A->i || !A->p) {
27
+ return 0;
28
+ }
29
+ memcpy(A->x, src->x, sizeof(scs_float) * Anz);
30
+ memcpy(A->i, src->i, sizeof(scs_int) * Anz);
31
+ memcpy(A->p, src->p, sizeof(scs_int) * (src->n + 1));
32
+ *dstp = A;
33
+ return 1;
34
+ }
35
+
36
+ scs_int SCS(validate_lin_sys)(const ScsMatrix *A, const ScsMatrix *P) {
37
+ scs_int i, j, r_max, Anz;
38
+ if (!A->x || !A->i || !A->p) {
39
+ scs_printf("data incompletely specified\n");
40
+ return -1;
41
+ }
42
+ /* detects some errors in A col ptrs: */
43
+ Anz = A->p[A->n];
44
+ if (Anz > 0) {
45
+ for (i = 0; i < A->n; ++i) {
46
+ if (A->p[i] == A->p[i + 1]) {
47
+ scs_printf("WARN: A->p (column pointers) not strictly increasing, "
48
+ "column %li empty\n",
49
+ (long)i);
50
+ } else if (A->p[i] > A->p[i + 1]) {
51
+ scs_printf("ERROR: A->p (column pointers) decreasing\n");
52
+ return -1;
53
+ }
54
+ }
55
+ }
56
+ if (((scs_float)Anz / A->m > A->n) || (Anz < 0)) {
57
+ scs_printf("Anz (nonzeros in A) = %li, outside of valid range\n",
58
+ (long)Anz);
59
+ return -1;
60
+ }
61
+ r_max = 0;
62
+ for (i = 0; i < Anz; ++i) {
63
+ if (A->i[i] > r_max) {
64
+ r_max = A->i[i];
65
+ }
66
+ }
67
+ if (r_max > A->m - 1) {
68
+ scs_printf("number of rows in A inconsistent with input dimension\n");
69
+ return -1;
70
+ }
71
+ if (P) {
72
+ if (P->n != A->n) {
73
+ scs_printf("P dimension = %li, inconsistent with n = %li\n", (long)P->n,
74
+ (long)A->n);
75
+ return -1;
76
+ }
77
+ if (P->m != P->n) {
78
+ scs_printf("P is not square\n");
79
+ return -1;
80
+ }
81
+ for (j = 0; j < P->n; j++) { /* cols */
82
+ for (i = P->p[j]; i < P->p[j + 1]; i++) {
83
+ if (P->i[i] > j) { /* if row > */
84
+ scs_printf("P is not upper triangular\n");
85
+ return -1;
86
+ }
87
+ }
88
+ }
89
+ }
90
+ return 0;
91
+ }
92
+
93
+ void SCS(free_scs_matrix)(ScsMatrix *A) {
94
+ if (A) {
95
+ scs_free(A->x);
96
+ scs_free(A->i);
97
+ scs_free(A->p);
98
+ scs_free(A);
99
+ }
100
+ }
101
+
102
+ static inline scs_float apply_limit(scs_float x) {
103
+ /* need to bound to 1 for cols/rows of all zeros, otherwise blows up */
104
+ x = x < MIN_NORMALIZATION_FACTOR ? 1.0 : x;
105
+ x = x > MAX_NORMALIZATION_FACTOR ? MAX_NORMALIZATION_FACTOR : x;
106
+ return x;
107
+ }
108
+
109
+ static void compute_ruiz_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
110
+ scs_float *c, scs_float *Dt, scs_float *Et,
111
+ scs_float *s, ScsConeWork *cone) {
112
+ scs_int i, j, kk;
113
+ scs_float wrk;
114
+
115
+ /**************************** D ****************************/
116
+
117
+ /* initialize D */
118
+ for (i = 0; i < A->m; ++i) {
119
+ /* Dt[i] = 0.; */
120
+ Dt[i] = ABS(b[i]);
121
+ }
122
+
123
+ /* calculate row norms */
124
+ for (i = 0; i < A->n; ++i) {
125
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
126
+ Dt[A->i[j]] = MAX(Dt[A->i[j]], ABS(A->x[j]));
127
+ }
128
+ }
129
+
130
+ /* accumulate D across each cone */
131
+ SCS(enforce_cone_boundaries)(cone, Dt, &SCS(norm_inf));
132
+
133
+ /* invert temporary vec to form D */
134
+ for (i = 0; i < A->m; ++i) {
135
+ Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
136
+ }
137
+
138
+ /**************************** E ****************************/
139
+
140
+ /* initialize E */
141
+ for (i = 0; i < A->n; ++i) {
142
+ /* Et[i] = 0.; */
143
+ Et[i] = ABS(c[i]);
144
+ }
145
+
146
+ /* TODO: test not using P to determine scaling */
147
+ if (P) {
148
+ /* compute norm of cols of P (symmetric upper triangular) */
149
+ /* E = norm of cols of P */
150
+ /* Compute maximum across columns */
151
+ /* P(i, j) contributes to col j and col i (row i) due to symmetry */
152
+ for (j = 0; j < P->n; j++) { /* cols */
153
+ for (kk = P->p[j]; kk < P->p[j + 1]; kk++) {
154
+ i = P->i[kk]; /* row */
155
+ wrk = ABS(P->x[kk]);
156
+ Et[j] = MAX(wrk, Et[j]);
157
+ if (i != j) {
158
+ Et[i] = MAX(wrk, Et[i]);
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ /* calculate col norms, E */
165
+ for (i = 0; i < A->n; ++i) {
166
+ Et[i] = MAX(Et[i], SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]));
167
+ Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Et[i])));
168
+ }
169
+
170
+ /* calculate s value */
171
+ *s = MAX(SCS(norm_inf)(c, A->n), SCS(norm_inf)(b, A->m));
172
+ *s = SAFEDIV_POS(1.0, SQRTF(apply_limit(*s)));
173
+ }
174
+
175
+ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
176
+ scs_float *c, scs_float *Dt, scs_float *Et,
177
+ scs_float *s, ScsConeWork *cone) {
178
+ scs_int i, j, kk;
179
+ scs_float wrk, norm_c, norm_b;
180
+
181
+ /**************************** D ****************************/
182
+
183
+ /* initialize D */
184
+ for (i = 0; i < A->m; ++i) {
185
+ /* Dt[i] = 0.; */
186
+ Dt[i] = b[i] * b[i];
187
+ }
188
+
189
+ /* calculate row norms */
190
+ for (i = 0; i < A->n; ++i) {
191
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
192
+ Dt[A->i[j]] += A->x[j] * A->x[j];
193
+ }
194
+ }
195
+ for (i = 0; i < A->m; ++i) {
196
+ Dt[i] = SQRTF(Dt[i]); /* l2 norm of rows */
197
+ }
198
+
199
+ /* accumulate D across each cone */
200
+ SCS(enforce_cone_boundaries)(cone, Dt, &SCS(mean));
201
+
202
+ for (i = 0; i < A->m; ++i) {
203
+ Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
204
+ }
205
+
206
+ /**************************** E ****************************/
207
+
208
+ /* initialize E */
209
+ for (i = 0; i < A->n; ++i) {
210
+ /* Et[i] = 0.; */
211
+ Et[i] = c[i] * c[i];
212
+ }
213
+
214
+ /* TODO: test not using P to determine scaling */
215
+ if (P) {
216
+ /* compute norm of cols of P (symmetric upper triangular) */
217
+ /* E = norm of cols of P */
218
+ /* Compute maximum across columns */
219
+ /* P(i, j) contributes to col j and col i (row i) due to symmetry */
220
+ for (j = 0; j < P->n; j++) { /* cols */
221
+ for (kk = P->p[j]; kk < P->p[j + 1]; kk++) {
222
+ i = P->i[kk]; /* row */
223
+ wrk = P->x[kk] * P->x[kk];
224
+ Et[j] += wrk;
225
+ if (i != j) {
226
+ Et[i] += wrk;
227
+ }
228
+ }
229
+ }
230
+ }
231
+
232
+ /* calculate col norms, E */
233
+ for (i = 0; i < A->n; ++i) {
234
+ Et[i] += SCS(norm_sq)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
235
+ Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(SQRTF(Et[i]))));
236
+ }
237
+
238
+ /* calculate s value */
239
+ norm_c = SCS(norm_2)(c, A->n);
240
+ norm_b = SCS(norm_2)(b, A->m);
241
+ *s = SQRTF(norm_c * norm_c + norm_b * norm_b);
242
+ *s = SAFEDIV_POS(1.0, SQRTF(apply_limit(*s)));
243
+ }
244
+
245
+ static void rescale(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
246
+ scs_float *Dt, scs_float *Et, scs_float s, ScsScaling *scal,
247
+ ScsConeWork *cone) {
248
+ scs_int i, j;
249
+ /* scale the rows of A with D */
250
+ for (i = 0; i < A->n; ++i) {
251
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
252
+ A->x[j] *= Dt[A->i[j]];
253
+ }
254
+ }
255
+
256
+ /* scale the cols of A with E */
257
+ for (i = 0; i < A->n; ++i) {
258
+ SCS(scale_array)(&(A->x[A->p[i]]), Et[i], A->p[i + 1] - A->p[i]);
259
+ }
260
+
261
+ if (P) {
262
+ /* scale the rows of P with E */
263
+ for (i = 0; i < P->n; ++i) {
264
+ for (j = P->p[i]; j < P->p[i + 1]; ++j) {
265
+ P->x[j] *= Et[P->i[j]];
266
+ }
267
+ }
268
+ /* scale the cols of P with E */
269
+ for (i = 0; i < P->n; ++i) {
270
+ SCS(scale_array)(&(P->x[P->p[i]]), Et[i], P->p[i + 1] - P->p[i]);
271
+ }
272
+ }
273
+
274
+ /* scale c */
275
+ for (i = 0; i < A->n; ++i) {
276
+ c[i] *= Et[i];
277
+ }
278
+ /* scale b */
279
+ for (i = 0; i < A->m; ++i) {
280
+ b[i] *= Dt[i];
281
+ }
282
+
283
+ /* Accumulate scaling */
284
+ for (i = 0; i < A->m; ++i) {
285
+ scal->D[i] *= Dt[i];
286
+ }
287
+ for (i = 0; i < A->n; ++i) {
288
+ scal->E[i] *= Et[i];
289
+ }
290
+
291
+ /* Apply scaling */
292
+ SCS(scale_array)(c, s, A->n);
293
+ SCS(scale_array)(b, s, A->m);
294
+ /* no need to scale P since primal_scale = dual_scale */
295
+ /*
296
+ if (P) {
297
+ SCS(scale_array)(P->x, primal_scale, P->p[P->n]);
298
+ SCS(scale_array)(P->x, 1.0 / dual_scale, P->p[P->n]);
299
+ }
300
+ */
301
+
302
+ /* Accumulate scaling */
303
+ scal->primal_scale *= s;
304
+ scal->dual_scale *= s;
305
+ }
306
+
307
+ /* Will rescale as P -> EPE, A -> DAE, c -> sEc, b -> sDb, in-place.
308
+ * Essentially trying to rescale this matrix:
309
+ *
310
+ * [P A' c] with [E 0 0] on both sides (D, E diagonal)
311
+ * [A 0 b] [0 D 0]
312
+ * [c' b' 0] [0 0 s]
313
+ *
314
+ * which results in:
315
+ *
316
+ * [ EPE EA'D sEc ]
317
+ * [ DAE 0 sDb ]
318
+ * [ sc'E sb'D 0 ]
319
+ *
320
+ * In other words D rescales the rows of A, b
321
+ * E rescales the cols of A and rows/cols of P, c'
322
+ *
323
+ * will repeatedly set: D^-1 ~ norm of rows of [ A b ]
324
+ *
325
+ * E^-1 ~ norm of cols of [ P ]
326
+ * [ A ]
327
+ * [ c']
328
+ *
329
+ * `s` is incorporated into dual_scale and primal_scale
330
+ *
331
+ * The main complication is that D has to respect cone boundaries.
332
+ *
333
+ */
334
+ ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, scs_float *b,
335
+ scs_float *c, ScsConeWork *cone) {
336
+ scs_int i;
337
+ scs_float s;
338
+ ScsScaling *scal = (ScsScaling *)scs_calloc(1, sizeof(ScsScaling));
339
+ scs_float *Dt = (scs_float *)scs_calloc(A->m, sizeof(scs_float));
340
+ scs_float *Et = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
341
+ scal->D = (scs_float *)scs_calloc(A->m, sizeof(scs_float));
342
+ scal->E = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
343
+
344
+ #if VERBOSITY > 5
345
+ SCS(timer) normalize_timer;
346
+ SCS(tic)(&normalize_timer);
347
+ scs_printf("normalizing A and P\n");
348
+ #endif
349
+
350
+ /* init D, E */
351
+ scal->m = A->m;
352
+ for (i = 0; i < A->m; ++i) {
353
+ scal->D[i] = 1.;
354
+ }
355
+ scal->n = A->n;
356
+ for (i = 0; i < A->n; ++i) {
357
+ scal->E[i] = 1.;
358
+ }
359
+ scal->primal_scale = 1.;
360
+ scal->dual_scale = 1.;
361
+ for (i = 0; i < NUM_RUIZ_PASSES; ++i) {
362
+ compute_ruiz_mats(P, A, b, c, Dt, Et, &s, cone);
363
+ rescale(P, A, b, c, Dt, Et, s, scal, cone);
364
+ }
365
+ for (i = 0; i < NUM_L2_PASSES; ++i) {
366
+ compute_l2_mats(P, A, b, c, Dt, Et, &s, cone);
367
+ rescale(P, A, b, c, Dt, Et, s, scal, cone);
368
+ }
369
+ scs_free(Dt);
370
+ scs_free(Et);
371
+
372
+ #if VERBOSITY > 5
373
+ scs_printf("finished normalizing A and P, time: %1.2es\n",
374
+ SCS(tocq)(&normalize_timer) / 1e3);
375
+ scs_printf("inf norm A %1.2e\n", SCS(norm_inf)(A->x, A->p[A->n]));
376
+ if (P) {
377
+ scs_printf("inf norm P %1.2e\n", SCS(norm_inf)(P->x, P->p[P->n]));
378
+ }
379
+ scs_printf("primal_scale %g\n", scal->primal_scale);
380
+ scs_printf("dual_scale %g\n", scal->dual_scale);
381
+ scs_printf("norm_b %g\n", SCS(norm_inf)(b, A->m));
382
+ scs_printf("norm_c %g\n", SCS(norm_inf)(c, A->n));
383
+ scs_printf("norm D %g\n", SCS(norm_inf)(scal->D, A->m));
384
+ scs_printf("norm E %g\n", SCS(norm_inf)(scal->E, A->n));
385
+ #endif
386
+ return scal;
387
+ }
388
+
389
+ void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling *scal) {
390
+ scs_int i, j;
391
+ scs_float *D = scal->D;
392
+ scs_float *E = scal->E;
393
+ for (i = 0; i < A->n; ++i) {
394
+ SCS(scale_array)
395
+ (&(A->x[A->p[i]]), 1. / E[i], A->p[i + 1] - A->p[i]);
396
+ }
397
+ for (i = 0; i < A->n; ++i) {
398
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
399
+ A->x[j] /= D[A->i[j]];
400
+ }
401
+ }
402
+ if (P) {
403
+ for (i = 0; i < P->n; ++i) {
404
+ SCS(scale_array)
405
+ (&(P->x[P->p[i]]), 1. / E[i], P->p[i + 1] - P->p[i]);
406
+ }
407
+ for (i = 0; i < P->n; ++i) {
408
+ for (j = P->p[i]; j < P->p[i + 1]; ++j) {
409
+ P->x[j] /= E[P->i[j]];
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ void SCS(accum_by_atrans)(const ScsMatrix *A, const scs_float *x,
416
+ scs_float *y) {
417
+ /* y += A'*x
418
+ A in column compressed format
419
+ parallelizes over columns (rows of A')
420
+ */
421
+ scs_int p, j;
422
+ scs_int c1, c2;
423
+ scs_float yj;
424
+ scs_int n = A->n;
425
+ scs_int *Ap = A->p;
426
+ scs_int *Ai = A->i;
427
+ scs_float *Ax = A->x;
428
+ #ifdef _OPENMP
429
+ #pragma omp parallel for private(p, c1, c2, yj)
430
+ #endif
431
+ for (j = 0; j < n; j++) {
432
+ yj = y[j];
433
+ c1 = Ap[j];
434
+ c2 = Ap[j + 1];
435
+ for (p = c1; p < c2; p++) {
436
+ yj += Ax[p] * x[Ai[p]];
437
+ }
438
+ y[j] = yj;
439
+ }
440
+ }
441
+
442
+ void SCS(accum_by_a)(const ScsMatrix *A, const scs_float *x, scs_float *y) {
443
+ /*y += A*x
444
+ A in column compressed format
445
+ */
446
+ scs_int p, j, i;
447
+ scs_int n = A->n;
448
+ scs_int *Ap = A->p;
449
+ scs_int *Ai = A->i;
450
+ scs_float *Ax = A->x;
451
+ for (j = 0; j < n; j++) { /* col */
452
+ for (p = Ap[j]; p < Ap[j + 1]; p++) {
453
+ i = Ai[p]; /* row */
454
+ y[i] += Ax[p] * x[j];
455
+ }
456
+ }
457
+ }
458
+
459
+ /* Since P is upper triangular need to be clever here */
460
+ void SCS(accum_by_p)(const ScsMatrix *P, const scs_float *x, scs_float *y) {
461
+ /* returns y += P x */
462
+ scs_int p, j, i;
463
+ scs_int n = P->n;
464
+ scs_int *Pp = P->p;
465
+ scs_int *Pi = P->i;
466
+ scs_float *Px = P->x;
467
+ /* y += P_upper x but skip diagonal entries*/
468
+ for (j = 0; j < n; j++) { /* col */
469
+ for (p = Pp[j]; p < Pp[j + 1]; p++) {
470
+ i = Pi[p]; /* row */
471
+ if (i != j) { /* skip the diagonal */
472
+ y[i] += Px[p] * x[j];
473
+ }
474
+ }
475
+ }
476
+ /* y += P_lower x */
477
+ SCS(accum_by_atrans)(P, x, y);
478
+ }
@@ -0,0 +1,70 @@
1
+ #ifndef SCS_MATRIX_H_GUARD
2
+ #define SCS_MATRIX_H_GUARD
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include "glbopts.h"
9
+ #include "scs.h"
10
+ #include "scs_work.h"
11
+
12
+ /* Normalization routines, used if d->NORMALIZE is true */
13
+ /* normalizes A matrix, sets scal->E and scal->D diagonal scaling matrices,
14
+ * A -> D*A*E. D and E must be all positive entries, D must satisfy cone
15
+ * boundaries */
16
+ ScsScaling *SCS(normalize_a_p)(ScsMatrix *P, ScsMatrix *A, scs_float *b,
17
+ scs_float *c, ScsConeWork *cone);
18
+
19
+ /* unnormalizes A matrix, unnormalizes by w->D and w->E */
20
+ void SCS(un_normalize_a_p)(ScsMatrix *A, ScsMatrix *P, const ScsScaling *scal);
21
+
22
+ /* to free the memory allocated in a ScsMatrix (called on A and P at finish) */
23
+ void SCS(free_scs_matrix)(ScsMatrix *A);
24
+
25
+ /* copies A (instead of in-place normalization), returns 0 for failure,
26
+ * allocates memory for dstp */
27
+ scs_int SCS(copy_matrix)(ScsMatrix **dstp, const ScsMatrix *src);
28
+
29
+ scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n);
30
+
31
+ /**
32
+ * Validate the linear system inputs, returns < 0 if not valid inputs.
33
+ *
34
+ * @param A A data matrix
35
+ * @param P P data matrix
36
+ * @return status < 0 indicates failure
37
+ */
38
+ scs_int SCS(validate_lin_sys)(const ScsMatrix *A, const ScsMatrix *P);
39
+
40
+ /**
41
+ * Forms y += A^T * x
42
+ *
43
+ * @param A A data matrix
44
+ * @param x Input
45
+ * @param y Output
46
+ */
47
+ void SCS(accum_by_atrans)(const ScsMatrix *A, const scs_float *x, scs_float *y);
48
+
49
+ /**
50
+ * Forms y += A * x
51
+ *
52
+ * @param A Data matrix
53
+ * @param x Input
54
+ * @param y Output
55
+ */
56
+ void SCS(accum_by_a)(const ScsMatrix *A, const scs_float *x, scs_float *y);
57
+
58
+ /**
59
+ * Forms y += P * x
60
+ *
61
+ * @param P P data matrix
62
+ * @param x Input
63
+ * @param y Output
64
+ */
65
+ void SCS(accum_by_p)(const ScsMatrix *P, const scs_float *x, scs_float *y);
66
+
67
+ #ifdef __cplusplus
68
+ }
69
+ #endif
70
+ #endif
data/vendor/scs/scs.mk CHANGED
@@ -99,10 +99,6 @@ SFLOAT = 0
99
99
  ifneq ($(SFLOAT), 0)
100
100
  OPT_FLAGS += -DSFLOAT=$(SFLOAT) # use floats rather than doubles
101
101
  endif
102
- NOVALIDATE = 0
103
- ifneq ($(NOVALIDATE), 0)
104
- OPT_FLAGS += -DNOVALIDATE=$(NOVALIDATE)$ # remove data validation step
105
- endif
106
102
  NOTIMER = 0
107
103
  ifneq ($(NOTIMER), 0)
108
104
  OPT_FLAGS += -DNOTIMER=$(NOTIMER) # no timing, times reported as nan
@@ -115,12 +111,20 @@ GPU_TRANSPOSE_MAT = 1
115
111
  ifneq ($(GPU_TRANSPOSE_MAT), 0)
116
112
  OPT_FLAGS += -DGPU_TRANSPOSE_MAT=$(GPU_TRANSPOSE_MAT) # tranpose A mat in GPU memory
117
113
  endif
118
-
119
- ### VERBOSITY LEVELS: 0,1,2
120
- EXTRA_VERBOSE = 0
121
- ifneq ($(EXTRA_VERBOSE), 0)
122
- OPT_FLAGS += -DEXTRA_VERBOSE=$(EXTRA_VERBOSE) # extra verbosity level
114
+ NOVALIDATE = 0
115
+ ifneq ($(NOVALIDATE), 0)
116
+ OPT_FLAGS += -DNOVALIDATE=$(NOVALIDATE) # perform problem validation or skip
117
+ endif
118
+ ### VERBOSITY LEVELS: 0,1,2,...
119
+ VERBOSITY = 0
120
+ ifneq ($(VERBOSITY), 0)
121
+ OPT_FLAGS += -DVERBOSITY=$(VERBOSITY) # verbosity level
123
122
  endif
123
+ COVERAGE = 0
124
+ ifneq ($(COVERAGE), 0)
125
+ override CFLAGS += --coverage # generate test coverage data
126
+ endif
127
+
124
128
 
125
129
  ############ OPENMP: ############
126
130
  # set USE_OPENMP = 1 to allow openmp (multi-threaded matrix multiplies):
@@ -141,7 +145,7 @@ endif
141
145
  USE_LAPACK = 1
142
146
  ifneq ($(USE_LAPACK), 0)
143
147
  # edit these for your setup:
144
- BLASLDFLAGS = -lblas -llapack #-lgfortran
148
+ BLASLDFLAGS = -llapack -lblas # -lgfortran
145
149
  LDFLAGS += $(BLASLDFLAGS)
146
150
  OPT_FLAGS += -DUSE_LAPACK
147
151