scs 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +11 -6
  4. data/lib/scs/ffi.rb +30 -13
  5. data/lib/scs/solver.rb +32 -9
  6. data/lib/scs/version.rb +1 -1
  7. data/vendor/scs/CITATION.cff +39 -0
  8. data/vendor/scs/CMakeLists.txt +7 -8
  9. data/vendor/scs/Makefile +24 -15
  10. data/vendor/scs/README.md +5 -263
  11. data/vendor/scs/include/aa.h +67 -23
  12. data/vendor/scs/include/cones.h +17 -17
  13. data/vendor/scs/include/glbopts.h +98 -32
  14. data/vendor/scs/include/linalg.h +2 -4
  15. data/vendor/scs/include/linsys.h +58 -44
  16. data/vendor/scs/include/normalize.h +3 -3
  17. data/vendor/scs/include/rw.h +8 -2
  18. data/vendor/scs/include/scs.h +293 -133
  19. data/vendor/scs/include/util.h +3 -15
  20. data/vendor/scs/linsys/cpu/direct/private.c +220 -224
  21. data/vendor/scs/linsys/cpu/direct/private.h +13 -7
  22. data/vendor/scs/linsys/cpu/direct/private.o +0 -0
  23. data/vendor/scs/linsys/cpu/indirect/private.c +177 -110
  24. data/vendor/scs/linsys/cpu/indirect/private.h +8 -4
  25. data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
  26. data/vendor/scs/linsys/csparse.c +87 -0
  27. data/vendor/scs/linsys/csparse.h +34 -0
  28. data/vendor/scs/linsys/csparse.o +0 -0
  29. data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +1 -1
  30. data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
  31. data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
  32. data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
  33. data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
  34. data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
  35. data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
  36. data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
  37. data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
  38. data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
  39. data/vendor/scs/linsys/external/amd/amd_internal.h +1 -1
  40. data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
  41. data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
  42. data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
  43. data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
  44. data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
  45. data/vendor/scs/linsys/external/qdldl/changes +2 -0
  46. data/vendor/scs/linsys/external/qdldl/qdldl.c +29 -46
  47. data/vendor/scs/linsys/external/qdldl/qdldl.h +33 -41
  48. data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
  49. data/vendor/scs/linsys/external/qdldl/qdldl_types.h +11 -3
  50. data/vendor/scs/linsys/gpu/gpu.c +31 -33
  51. data/vendor/scs/linsys/gpu/gpu.h +48 -31
  52. data/vendor/scs/linsys/gpu/indirect/private.c +338 -232
  53. data/vendor/scs/linsys/gpu/indirect/private.h +23 -14
  54. data/vendor/scs/linsys/scs_matrix.c +498 -0
  55. data/vendor/scs/linsys/scs_matrix.h +70 -0
  56. data/vendor/scs/linsys/scs_matrix.o +0 -0
  57. data/vendor/scs/scs.mk +13 -9
  58. data/vendor/scs/src/aa.c +384 -109
  59. data/vendor/scs/src/aa.o +0 -0
  60. data/vendor/scs/src/cones.c +440 -353
  61. data/vendor/scs/src/cones.o +0 -0
  62. data/vendor/scs/src/ctrlc.c +15 -5
  63. data/vendor/scs/src/ctrlc.o +0 -0
  64. data/vendor/scs/src/linalg.c +84 -28
  65. data/vendor/scs/src/linalg.o +0 -0
  66. data/vendor/scs/src/normalize.c +22 -64
  67. data/vendor/scs/src/normalize.o +0 -0
  68. data/vendor/scs/src/rw.c +160 -21
  69. data/vendor/scs/src/rw.o +0 -0
  70. data/vendor/scs/src/scs.c +767 -563
  71. data/vendor/scs/src/scs.o +0 -0
  72. data/vendor/scs/src/scs_indir.o +0 -0
  73. data/vendor/scs/src/scs_version.c +9 -3
  74. data/vendor/scs/src/scs_version.o +0 -0
  75. data/vendor/scs/src/util.c +37 -106
  76. data/vendor/scs/src/util.o +0 -0
  77. data/vendor/scs/test/minunit.h +17 -8
  78. data/vendor/scs/test/problem_utils.h +176 -14
  79. data/vendor/scs/test/problems/degenerate.h +130 -0
  80. data/vendor/scs/test/problems/hs21_tiny_qp.h +124 -0
  81. data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +116 -0
  82. data/vendor/scs/test/problems/infeasible_tiny_qp.h +100 -0
  83. data/vendor/scs/test/problems/qafiro_tiny_qp.h +199 -0
  84. data/vendor/scs/test/problems/random_prob +0 -0
  85. data/vendor/scs/test/problems/random_prob.h +45 -0
  86. data/vendor/scs/test/problems/rob_gauss_cov_est.h +188 -31
  87. data/vendor/scs/test/problems/small_lp.h +13 -14
  88. data/vendor/scs/test/problems/test_fails.h +43 -0
  89. data/vendor/scs/test/problems/unbounded_tiny_qp.h +82 -0
  90. data/vendor/scs/test/random_socp_prob.c +54 -53
  91. data/vendor/scs/test/rng.h +109 -0
  92. data/vendor/scs/test/run_from_file.c +19 -10
  93. data/vendor/scs/test/run_tests.c +27 -3
  94. metadata +20 -8
  95. data/vendor/scs/linsys/amatrix.c +0 -305
  96. data/vendor/scs/linsys/amatrix.h +0 -36
  97. data/vendor/scs/linsys/amatrix.o +0 -0
  98. data/vendor/scs/test/data/small_random_socp +0 -0
  99. data/vendor/scs/test/problems/small_random_socp.h +0 -33
  100. data/vendor/scs/test/run_tests +0 -2
@@ -5,34 +5,43 @@
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
18
  /* 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 */
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
+ const ScsMatrix *A; /* does *not* own this memory */
27
+ const ScsMatrix *P; /* does *not* own this memory */
28
+ ScsGpuMatrix *Ag; /* A matrix on GPU */
29
+ ScsGpuMatrix *Agt; /* A trans matrix on GPU */
30
+ ScsGpuMatrix *Pg; /* P matrix on GPU */
28
31
  /* CUDA */
29
32
  cublasHandle_t cublas_handle;
30
33
  cusparseHandle_t cusparse_handle;
31
34
  /* CUSPARSE */
32
35
  size_t buffer_size;
33
36
  void *buffer;
34
- cusparseDnVecDescr_t dn_vec_m; /* Dense vector of length m */
35
- cusparseDnVecDescr_t dn_vec_n; /* Dense vector of length n */
37
+ cusparseDnVecDescr_t dn_vec_m; /* Dense vector of length m */
38
+ cusparseDnVecDescr_t dn_vec_n; /* Dense vector of length n */
39
+ cusparseDnVecDescr_t dn_vec_n_p; /* Dense vector of length n */
40
+
41
+ /* rho terms */
42
+ scs_float rho_x;
43
+ scs_float *inv_rho_y_vec; /* inverse rho_y_vec */
44
+ scs_float *inv_rho_y_vec_gpu; /* inverse rho_y_vec on GPU */
36
45
  };
37
46
 
38
47
  #ifdef __cplusplus
@@ -0,0 +1,498 @@
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_malloc(sizeof(scs_float) * Anz);
22
+ /* A row index, size: NNZ A */
23
+ A->i = (scs_int *)scs_malloc(sizeof(scs_int) * Anz);
24
+ /* A column pointer, size: n+1 */
25
+ A->p = (scs_int *)scs_malloc(sizeof(scs_int) * (src->n + 1));
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, scs_int *boundaries,
112
+ scs_int cone_boundaries_len) {
113
+ scs_int i, j, kk, count, delta;
114
+ scs_float wrk;
115
+
116
+ /**************************** D ****************************/
117
+
118
+ /* initialize D */
119
+ for (i = 0; i < A->m; ++i) {
120
+ /* Dt[i] = 0.; */
121
+ Dt[i] = ABS(b[i]);
122
+ }
123
+
124
+ /* calculate row norms */
125
+ for (i = 0; i < A->n; ++i) {
126
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
127
+ Dt[A->i[j]] = MAX(Dt[A->i[j]], ABS(A->x[j]));
128
+ }
129
+ }
130
+
131
+ /* accumulate D across each cone */
132
+ count = boundaries[0];
133
+ for (i = 1; i < cone_boundaries_len; ++i) {
134
+ delta = boundaries[i];
135
+ wrk = SCS(norm_inf)(&(Dt[count]), delta);
136
+ for (j = count; j < count + delta; ++j) {
137
+ Dt[j] = wrk;
138
+ }
139
+ count += delta;
140
+ }
141
+
142
+ for (i = 0; i < A->m; ++i) {
143
+ Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
144
+ }
145
+
146
+ /**************************** E ****************************/
147
+
148
+ /* initialize E */
149
+ for (i = 0; i < A->n; ++i) {
150
+ /* Et[i] = 0.; */
151
+ Et[i] = ABS(c[i]);
152
+ }
153
+
154
+ /* TODO: test not using P to determine scaling */
155
+ if (P) {
156
+ /* compute norm of cols of P (symmetric upper triangular) */
157
+ /* E = norm of cols of P */
158
+ /* Compute maximum across columns */
159
+ /* P(i, j) contributes to col j and col i (row i) due to symmetry */
160
+ for (j = 0; j < P->n; j++) { /* cols */
161
+ for (kk = P->p[j]; kk < P->p[j + 1]; kk++) {
162
+ i = P->i[kk]; /* row */
163
+ wrk = ABS(P->x[kk]);
164
+ Et[j] = MAX(wrk, Et[j]);
165
+ if (i != j) {
166
+ Et[i] = MAX(wrk, Et[i]);
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ /* calculate col norms, E */
173
+ for (i = 0; i < A->n; ++i) {
174
+ Et[i] = MAX(Et[i], SCS(norm_inf)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]));
175
+ Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Et[i])));
176
+ }
177
+
178
+ /* calculate s value */
179
+ *s = MAX(SCS(norm_inf)(c, A->n), SCS(norm_inf)(b, A->m));
180
+ *s = SAFEDIV_POS(1.0, SQRTF(apply_limit(*s)));
181
+ }
182
+
183
+ static void compute_l2_mats(ScsMatrix *P, ScsMatrix *A, scs_float *b,
184
+ scs_float *c, scs_float *Dt, scs_float *Et,
185
+ scs_float *s, scs_int *boundaries,
186
+ scs_int cone_boundaries_len) {
187
+ scs_int i, j, kk, count, delta;
188
+ scs_float wrk, norm_c, norm_b;
189
+
190
+ /**************************** D ****************************/
191
+
192
+ /* initialize D */
193
+ for (i = 0; i < A->m; ++i) {
194
+ /* Dt[i] = 0.; */
195
+ Dt[i] = b[i] * b[i];
196
+ }
197
+
198
+ /* calculate row norms */
199
+ for (i = 0; i < A->n; ++i) {
200
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
201
+ Dt[A->i[j]] += A->x[j] * A->x[j];
202
+ }
203
+ }
204
+ for (i = 0; i < A->m; ++i) {
205
+ Dt[i] = SQRTF(Dt[i]); /* l2 norm of rows */
206
+ }
207
+
208
+ /* accumulate D across each cone */
209
+ count = boundaries[0];
210
+ for (i = 1; i < cone_boundaries_len; ++i) {
211
+ delta = boundaries[i];
212
+ wrk = 0.;
213
+ for (j = count; j < count + delta; ++j) {
214
+ wrk += Dt[j];
215
+ }
216
+ wrk /= delta;
217
+ for (j = count; j < count + delta; ++j) {
218
+ Dt[j] = wrk;
219
+ }
220
+ count += delta;
221
+ }
222
+
223
+ for (i = 0; i < A->m; ++i) {
224
+ Dt[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(Dt[i])));
225
+ }
226
+
227
+ /**************************** E ****************************/
228
+
229
+ /* initialize E */
230
+ for (i = 0; i < A->n; ++i) {
231
+ /* Et[i] = 0.; */
232
+ Et[i] = c[i] * c[i];
233
+ }
234
+
235
+ /* TODO: test not using P to determine scaling */
236
+ if (P) {
237
+ /* compute norm of cols of P (symmetric upper triangular) */
238
+ /* E = norm of cols of P */
239
+ /* Compute maximum across columns */
240
+ /* P(i, j) contributes to col j and col i (row i) due to symmetry */
241
+ for (j = 0; j < P->n; j++) { /* cols */
242
+ for (kk = P->p[j]; kk < P->p[j + 1]; kk++) {
243
+ i = P->i[kk]; /* row */
244
+ wrk = P->x[kk] * P->x[kk];
245
+ Et[j] += wrk;
246
+ if (i != j) {
247
+ Et[i] += wrk;
248
+ }
249
+ }
250
+ }
251
+ }
252
+
253
+ /* calculate col norms, E */
254
+ for (i = 0; i < A->n; ++i) {
255
+ Et[i] += SCS(norm_sq)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]);
256
+ Et[i] = SAFEDIV_POS(1.0, SQRTF(apply_limit(SQRTF(Et[i]))));
257
+ }
258
+
259
+ /* calculate s value */
260
+ norm_c = SCS(norm_2)(c, A->n);
261
+ norm_b = SCS(norm_2)(b, A->m);
262
+ *s = SQRTF(norm_c * norm_c + norm_b * norm_b);
263
+ *s = SAFEDIV_POS(1.0, SQRTF(apply_limit(*s)));
264
+ }
265
+
266
+ static void rescale(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
267
+ scs_float *Dt, scs_float *Et, scs_float s, ScsScaling *scal,
268
+ scs_int *boundaries, scs_int cone_boundaries_len) {
269
+ scs_int i, j;
270
+ /* scale the rows of A with D */
271
+ for (i = 0; i < A->n; ++i) {
272
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
273
+ A->x[j] *= Dt[A->i[j]];
274
+ }
275
+ }
276
+
277
+ /* scale the cols of A with E */
278
+ for (i = 0; i < A->n; ++i) {
279
+ SCS(scale_array)(&(A->x[A->p[i]]), Et[i], A->p[i + 1] - A->p[i]);
280
+ }
281
+
282
+ if (P) {
283
+ /* scale the rows of P with E */
284
+ for (i = 0; i < P->n; ++i) {
285
+ for (j = P->p[i]; j < P->p[i + 1]; ++j) {
286
+ P->x[j] *= Et[P->i[j]];
287
+ }
288
+ }
289
+ /* scale the cols of P with E */
290
+ for (i = 0; i < P->n; ++i) {
291
+ SCS(scale_array)(&(P->x[P->p[i]]), Et[i], P->p[i + 1] - P->p[i]);
292
+ }
293
+ }
294
+
295
+ /* scale c */
296
+ for (i = 0; i < A->n; ++i) {
297
+ c[i] *= Et[i];
298
+ }
299
+ /* scale b */
300
+ for (i = 0; i < A->m; ++i) {
301
+ b[i] *= Dt[i];
302
+ }
303
+
304
+ /* Accumulate scaling */
305
+ for (i = 0; i < A->m; ++i) {
306
+ scal->D[i] *= Dt[i];
307
+ }
308
+ for (i = 0; i < A->n; ++i) {
309
+ scal->E[i] *= Et[i];
310
+ }
311
+
312
+ /* Apply scaling */
313
+ SCS(scale_array)(c, s, A->n);
314
+ SCS(scale_array)(b, s, A->m);
315
+ /* no need to scale P since primal_scale = dual_scale */
316
+ /*
317
+ if (P) {
318
+ SCS(scale_array)(P->x, primal_scale, P->p[P->n]);
319
+ SCS(scale_array)(P->x, 1.0 / dual_scale, P->p[P->n]);
320
+ }
321
+ */
322
+
323
+ /* Accumulate scaling */
324
+ scal->primal_scale *= s;
325
+ scal->dual_scale *= s;
326
+ }
327
+
328
+ /* Will rescale as P -> EPE, A -> DAE, c -> sEc, b -> sDb, in-place.
329
+ * Essentially trying to rescale this matrix:
330
+ *
331
+ * [P A' c] with [E 0 0] on both sides (D, E diagonal)
332
+ * [A 0 b] [0 D 0]
333
+ * [c' b' 0] [0 0 s]
334
+ *
335
+ * which results in:
336
+ *
337
+ * [ EPE EA'D sEc ]
338
+ * [ DAE 0 sDb ]
339
+ * [ sc'E sb'D 0 ]
340
+ *
341
+ * In other words D rescales the rows of A, b
342
+ * E rescales the cols of A and rows/cols of P, c'
343
+ *
344
+ * will repeatedly set: D^-1 ~ norm of rows of [ A b ]
345
+ *
346
+ * E^-1 ~ norm of cols of [ P ]
347
+ * [ A ]
348
+ * [ c']
349
+ *
350
+ * `s` is incorporated into dual_scale and primal_scale
351
+ *
352
+ * The main complication is that D has to respect cone boundaries.
353
+ *
354
+ */
355
+ void SCS(normalize)(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
356
+ ScsScaling *scal, scs_int *cone_boundaries,
357
+ scs_int cone_boundaries_len) {
358
+ scs_int i;
359
+ scs_float s;
360
+ scs_float *Dt = (scs_float *)scs_malloc(A->m * sizeof(scs_float));
361
+ scs_float *Et = (scs_float *)scs_malloc(A->n * sizeof(scs_float));
362
+ scal->D = (scs_float *)scs_malloc(A->m * sizeof(scs_float));
363
+ scal->E = (scs_float *)scs_malloc(A->n * sizeof(scs_float));
364
+
365
+ #if VERBOSITY > 5
366
+ SCS(timer) normalize_timer;
367
+ SCS(tic)(&normalize_timer);
368
+ scs_printf("normalizing A and P\n");
369
+ #endif
370
+
371
+ /* init D, E */
372
+ for (i = 0; i < A->m; ++i) {
373
+ scal->D[i] = 1.;
374
+ }
375
+ for (i = 0; i < A->n; ++i) {
376
+ scal->E[i] = 1.;
377
+ }
378
+ scal->primal_scale = 1.;
379
+ scal->dual_scale = 1.;
380
+ for (i = 0; i < NUM_RUIZ_PASSES; ++i) {
381
+ compute_ruiz_mats(P, A, b, c, Dt, Et, &s, cone_boundaries,
382
+ cone_boundaries_len);
383
+ rescale(P, A, b, c, Dt, Et, s, scal, cone_boundaries, cone_boundaries_len);
384
+ }
385
+ for (i = 0; i < NUM_L2_PASSES; ++i) {
386
+ compute_l2_mats(P, A, b, c, Dt, Et, &s, cone_boundaries,
387
+ cone_boundaries_len);
388
+ rescale(P, A, b, c, Dt, Et, s, scal, cone_boundaries, cone_boundaries_len);
389
+ }
390
+ scs_free(Dt);
391
+ scs_free(Et);
392
+
393
+ #if VERBOSITY > 5
394
+ scs_printf("finished normalizing A and P, time: %1.2es\n",
395
+ SCS(tocq)(&normalize_timer) / 1e3);
396
+ scs_printf("inf norm A %1.2e\n", SCS(norm_inf)(A->x, A->p[A->n]));
397
+ if (P) {
398
+ scs_printf("inf norm P %1.2e\n", SCS(norm_inf)(P->x, P->p[P->n]));
399
+ }
400
+ scs_printf("primal_scale %g\n", scal->primal_scale);
401
+ scs_printf("dual_scale %g\n", scal->dual_scale);
402
+ scs_printf("norm_b %g\n", SCS(norm_inf)(b, A->m));
403
+ scs_printf("norm_c %g\n", SCS(norm_inf)(c, A->n));
404
+ scs_printf("norm D %g\n", SCS(norm_inf)(scal->D, A->m));
405
+ scs_printf("norm E %g\n", SCS(norm_inf)(scal->E, A->n));
406
+ #endif
407
+ }
408
+
409
+ void SCS(un_normalize)(ScsMatrix *A, ScsMatrix *P, const ScsScaling *scal) {
410
+ scs_int i, j;
411
+ scs_float *D = scal->D;
412
+ scs_float *E = scal->E;
413
+ for (i = 0; i < A->n; ++i) {
414
+ SCS(scale_array)
415
+ (&(A->x[A->p[i]]), 1. / E[i], A->p[i + 1] - A->p[i]);
416
+ }
417
+ for (i = 0; i < A->n; ++i) {
418
+ for (j = A->p[i]; j < A->p[i + 1]; ++j) {
419
+ A->x[j] /= D[A->i[j]];
420
+ }
421
+ }
422
+ if (P) {
423
+ for (i = 0; i < P->n; ++i) {
424
+ SCS(scale_array)
425
+ (&(P->x[P->p[i]]), 1. / E[i], P->p[i + 1] - P->p[i]);
426
+ }
427
+ for (i = 0; i < P->n; ++i) {
428
+ for (j = P->p[i]; j < P->p[i + 1]; ++j) {
429
+ P->x[j] /= E[P->i[j]];
430
+ }
431
+ }
432
+ }
433
+ }
434
+
435
+ void SCS(accum_by_atrans)(const ScsMatrix *A, const scs_float *x,
436
+ scs_float *y) {
437
+ /* y += A'*x
438
+ A in column compressed format
439
+ parallelizes over columns (rows of A')
440
+ */
441
+ scs_int p, j;
442
+ scs_int c1, c2;
443
+ scs_float yj;
444
+ scs_int n = A->n;
445
+ scs_int *Ap = A->p;
446
+ scs_int *Ai = A->i;
447
+ scs_float *Ax = A->x;
448
+ #ifdef _OPENMP
449
+ #pragma omp parallel for private(p, c1, c2, yj)
450
+ #endif
451
+ for (j = 0; j < n; j++) {
452
+ yj = y[j];
453
+ c1 = Ap[j];
454
+ c2 = Ap[j + 1];
455
+ for (p = c1; p < c2; p++) {
456
+ yj += Ax[p] * x[Ai[p]];
457
+ }
458
+ y[j] = yj;
459
+ }
460
+ }
461
+
462
+ void SCS(accum_by_a)(const ScsMatrix *A, const scs_float *x, scs_float *y) {
463
+ /*y += A*x
464
+ A in column compressed format
465
+ */
466
+ scs_int p, j, i;
467
+ scs_int n = A->n;
468
+ scs_int *Ap = A->p;
469
+ scs_int *Ai = A->i;
470
+ scs_float *Ax = A->x;
471
+ for (j = 0; j < n; j++) { /* col */
472
+ for (p = Ap[j]; p < Ap[j + 1]; p++) {
473
+ i = Ai[p]; /* row */
474
+ y[i] += Ax[p] * x[j];
475
+ }
476
+ }
477
+ }
478
+
479
+ /* Since P is upper triangular need to be clever here */
480
+ void SCS(accum_by_p)(const ScsMatrix *P, const scs_float *x, scs_float *y) {
481
+ /* returns y += P x */
482
+ scs_int p, j, i;
483
+ scs_int n = P->n;
484
+ scs_int *Pp = P->p;
485
+ scs_int *Pi = P->i;
486
+ scs_float *Px = P->x;
487
+ /* y += P_upper x but skip diagonal entries*/
488
+ for (j = 0; j < n; j++) { /* col */
489
+ for (p = Pp[j]; p < Pp[j + 1]; p++) {
490
+ i = Pi[p]; /* row */
491
+ if (i != j) { /* skip the diagonal */
492
+ y[i] += Px[p] * x[j];
493
+ }
494
+ }
495
+ }
496
+ /* y += P_lower x */
497
+ SCS(accum_by_atrans)(P, x, y);
498
+ }
@@ -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
+
11
+ /* Normalization routines, used if d->NORMALIZE is true */
12
+ /* normalizes A matrix, sets scal->E and scal->D diagonal scaling matrices,
13
+ * A -> D*A*E. D and E must be all positive entries, D must satisfy cone
14
+ * boundaries */
15
+ void SCS(normalize)(ScsMatrix *P, ScsMatrix *A, scs_float *b, scs_float *c,
16
+ ScsScaling *scal, scs_int *cone_boundaries,
17
+ scs_int cone_boundaries_len);
18
+
19
+ /* unnormalizes A matrix, unnormalizes by w->D and w->E */
20
+ void SCS(un_normalize)(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
Binary file
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):