scs 0.2.2 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,43 +1,57 @@
1
1
  #include "private.h"
2
+ #include "linsys.h"
3
+ #include "util.h"
4
+ #include <limits.h>
2
5
 
3
- #define CG_BEST_TOL 1e-9
4
- #define CG_MIN_TOL 1e-1
5
-
6
- char *SCS(get_lin_sys_method)(const ScsMatrix *A, const ScsSettings *stgs) {
7
- char *str = (char *)scs_malloc(sizeof(char) * 128);
8
- sprintf(str, "sparse-indirect, nnz in A = %li, CG tol ~ 1/iter^(%2.2f)",
9
- (long)A->p[A->n], stgs->cg_rate);
10
- return str;
6
+ const char *SCS(get_lin_sys_method)() {
7
+ return "sparse-indirect";
11
8
  }
12
9
 
10
+ /*
13
11
  char *SCS(get_lin_sys_summary)(ScsLinSysWork *p, const ScsInfo *info) {
14
12
  char *str = (char *)scs_malloc(sizeof(char) * 128);
15
- sprintf(str,
16
- "\tLin-sys: avg # CG iterations: %2.2f, avg solve time: %1.2es\n",
17
- (scs_float)p->tot_cg_its / (info->iter + 1),
18
- p->total_solve_time / (info->iter + 1) / 1e3);
13
+ sprintf(str, "lin-sys: avg cg its: %2.2f\n",
14
+ (scs_float)p->tot_cg_its / (info->iter + 1));
19
15
  p->tot_cg_its = 0;
20
- p->total_solve_time = 0;
21
16
  return str;
22
17
  }
18
+ */
23
19
 
24
- /* M = inv ( diag ( RHO_X * I + A'A ) ) */
25
- static void get_preconditioner(const ScsMatrix *A, const ScsSettings *stgs,
26
- ScsLinSysWork *p) {
27
- scs_int i;
20
+ /* Not possible to do this on the fly due to M_ii += a_i' (R_y)^-1 a_i */
21
+ /* set M = inv ( diag ( R_x + P + A' R_y^{-1} A ) ) */
22
+ static void set_preconditioner(ScsLinSysWork *p) {
23
+ scs_int i, k;
28
24
  scs_float *M = p->M;
25
+ const ScsMatrix *A = p->A;
26
+ const ScsMatrix *P = p->P;
29
27
 
30
- #if EXTRA_VERBOSE > 0
28
+ #if VERBOSITY > 0
31
29
  scs_printf("getting pre-conditioner\n");
32
30
  #endif
33
31
 
34
- for (i = 0; i < A->n; ++i) {
35
- M[i] = 1 / (stgs->rho_x +
36
- SCS(norm_sq)(&(A->x[A->p[i]]), A->p[i + 1] - A->p[i]));
37
- /* M[i] = 1; */
32
+ /* M_ii = (R_x)_i + P_ii + a_i' (R_y)^-1 a_i */
33
+ for (i = 0; i < A->n; ++i) { /* cols */
34
+ /* M_ii = (R_x)_i */
35
+ M[i] = p->diag_r[i];
36
+ /* M_ii += a_i' (R_y)^-1 a_i */
37
+ for (k = A->p[i]; k < A->p[i + 1]; ++k) {
38
+ /* A->i[k] is row of entry k with value A->x[k] */
39
+ M[i] += A->x[k] * A->x[k] / p->diag_r[A->n + A->i[k]];
40
+ }
41
+ if (P) {
42
+ for (k = P->p[i]; k < P->p[i + 1]; k++) {
43
+ /* diagonal element only */
44
+ if (P->i[k] == i) { /* row == col */
45
+ /* M_ii += P_ii */
46
+ M[i] += P->x[k];
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ /* finally invert for pre-conditioner */
52
+ M[i] = 1. / M[i];
38
53
  }
39
-
40
- #if EXTRA_VERBOSE > 0
54
+ #if VERBOSITY > 0
41
55
  scs_printf("finished getting pre-conditioner\n");
42
56
  #endif
43
57
  }
@@ -54,15 +68,16 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
54
68
  scs_float *Ax = A->x;
55
69
 
56
70
  scs_int i, j, q, *z, c1, c2;
57
- #if EXTRA_VERBOSE > 0
71
+ #if VERBOSITY > 0
58
72
  SCS(timer) transpose_timer;
59
73
  scs_printf("transposing A\n");
60
74
  SCS(tic)(&transpose_timer);
61
75
  #endif
62
76
 
63
77
  z = (scs_int *)scs_calloc(m, sizeof(scs_int));
64
- for (i = 0; i < Ap[n]; i++) z[Ai[i]]++; /* row counts */
65
- SCS(cumsum)(Cp, z, m); /* row pointers */
78
+ for (i = 0; i < Ap[n]; i++)
79
+ z[Ai[i]]++; /* row counts */
80
+ SCS(cumsum)(Cp, z, m); /* row pointers */
66
81
 
67
82
  for (j = 0; j < n; j++) {
68
83
  c1 = Ap[j];
@@ -76,7 +91,7 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
76
91
  }
77
92
  scs_free(z);
78
93
 
79
- #if EXTRA_VERBOSE > 0
94
+ #if VERBOSITY > 0
80
95
  scs_printf("finished transposing A, time: %1.2es\n",
81
96
  SCS(tocq)(&transpose_timer) / 1e3);
82
97
  #endif
@@ -100,60 +115,86 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
100
115
  }
101
116
  }
102
117
 
103
- /*y = (RHO_X * I + A'A)x */
104
- static void mat_vec(const ScsMatrix *A, const ScsSettings *s, ScsLinSysWork *p,
105
- const scs_float *x, scs_float *y) {
106
- scs_float *tmp = p->tmp;
107
- memset(tmp, 0, A->m * sizeof(scs_float));
108
- SCS(accum_by_a)(A, p, x, tmp);
109
- memset(y, 0, A->n * sizeof(scs_float));
110
- SCS(accum_by_atrans)(A, p, tmp, y);
111
- SCS(add_scaled_array)(y, x, A->n, s->rho_x);
118
+ /* vec -> R_y^{-1} vec */
119
+ static void scale_by_r_y_inv(scs_float *vec, ScsLinSysWork *p) {
120
+ scs_int i;
121
+ for (i = 0; i < p->m; ++i) {
122
+ vec[i] /= p->diag_r[p->n + i];
123
+ }
124
+ }
125
+
126
+ /* y += R_x * x */
127
+ static void accum_by_r_x(scs_float *y, const scs_float *x, ScsLinSysWork *p) {
128
+ scs_int i;
129
+ for (i = 0; i < p->n; ++i) {
130
+ y[i] += p->diag_r[i] * x[i];
131
+ }
112
132
  }
113
133
 
114
- void SCS(accum_by_atrans)(const ScsMatrix *A, ScsLinSysWork *p,
115
- const scs_float *x, scs_float *y) {
116
- SCS(_accum_by_atrans)(A->n, A->x, A->i, A->p, x, y);
134
+ /* we use a different accum_by_a here for speed */
135
+ static void accum_by_a(ScsLinSysWork *p, const scs_float *x, scs_float *y) {
136
+ SCS(accum_by_atrans)(p->At, x, y);
117
137
  }
118
138
 
119
- void SCS(accum_by_a)(const ScsMatrix *A, ScsLinSysWork *p, const scs_float *x,
120
- scs_float *y) {
121
- SCS(_accum_by_atrans)(p->At->n, p->At->x, p->At->i, p->At->p, x, y);
139
+ /* y = (R_x + P + A' R_y^{-1} A) x */
140
+ static void mat_vec(const ScsMatrix *A, const ScsMatrix *P, ScsLinSysWork *p,
141
+ const scs_float *x, scs_float *y) {
142
+ scs_float *z = p->tmp;
143
+ memset(z, 0, A->m * sizeof(scs_float)); /* z = 0 */
144
+ memset(y, 0, A->n * sizeof(scs_float)); /* y = 0 */
145
+ if (P) {
146
+ SCS(accum_by_p)(P, x, y); /* y = Px */
147
+ }
148
+ accum_by_a(p, x, z); /* z = Ax */
149
+ scale_by_r_y_inv(z, p); /* z = R_y^{-1} A x */
150
+ SCS(accum_by_atrans)(A, z, y); /* y += A'z, y = Px + A' R_y^{-1} Ax */
151
+ /* y = R_x * x + Px + A' R_y^{-1} A * x */
152
+ accum_by_r_x(y, x, p);
122
153
  }
123
154
 
124
- static void apply_pre_conditioner(scs_float *M, scs_float *z, scs_float *r,
125
- scs_int n, scs_float *ipzr) {
155
+ static void apply_pre_conditioner(scs_float *z, scs_float *r, scs_int n,
156
+ ScsLinSysWork *pr) {
126
157
  scs_int i;
127
- *ipzr = 0;
158
+ scs_float *M = pr->M;
128
159
  for (i = 0; i < n; ++i) {
129
160
  z[i] = r[i] * M[i];
130
- *ipzr += z[i] * r[i];
131
161
  }
132
162
  }
133
163
 
134
- ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
135
- const ScsSettings *stgs) {
164
+ /* no need to update anything in this case */
165
+ void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
166
+ p->diag_r = diag_r; /* this isn't needed but do it to be safe */
167
+ set_preconditioner(p);
168
+ }
169
+
170
+ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
171
+ const scs_float *diag_r) {
136
172
  ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
137
- p->p = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
138
- p->r = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
139
- p->Gp = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
140
- p->tmp = (scs_float *)scs_malloc((A->m) * sizeof(scs_float));
173
+ p->A = A;
174
+ p->P = P;
175
+ p->m = A->m;
176
+ p->n = A->n;
177
+
178
+ p->p = (scs_float *)scs_calloc((A->n), sizeof(scs_float));
179
+ p->r = (scs_float *)scs_calloc((A->n), sizeof(scs_float));
180
+ p->Gp = (scs_float *)scs_calloc((A->n), sizeof(scs_float));
181
+ p->tmp = (scs_float *)scs_calloc((A->m), sizeof(scs_float));
141
182
 
142
183
  /* memory for A transpose */
143
- p->At = (ScsMatrix *)scs_malloc(sizeof(ScsMatrix));
184
+ p->At = (ScsMatrix *)scs_calloc(1, sizeof(ScsMatrix));
144
185
  p->At->m = A->n;
145
186
  p->At->n = A->m;
146
- p->At->i = (scs_int *)scs_malloc((A->p[A->n]) * sizeof(scs_int));
147
- p->At->p = (scs_int *)scs_malloc((A->m + 1) * sizeof(scs_int));
148
- p->At->x = (scs_float *)scs_malloc((A->p[A->n]) * sizeof(scs_float));
187
+ p->At->i = (scs_int *)scs_calloc((A->p[A->n]), sizeof(scs_int));
188
+ p->At->p = (scs_int *)scs_calloc((A->m + 1), sizeof(scs_int));
189
+ p->At->x = (scs_float *)scs_calloc((A->p[A->n]), sizeof(scs_float));
149
190
  transpose(A, p);
150
191
 
151
192
  /* preconditioner memory */
152
- p->z = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
153
- p->M = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
154
- get_preconditioner(A, stgs, p);
193
+ p->diag_r = diag_r;
194
+ p->z = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
195
+ p->M = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
196
+ set_preconditioner(p);
155
197
 
156
- p->total_solve_time = 0;
157
198
  p->tot_cg_its = 0;
158
199
  if (!p->p || !p->r || !p->Gp || !p->tmp || !p->At || !p->At->i || !p->At->p ||
159
200
  !p->At->x) {
@@ -163,94 +204,129 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
163
204
  return p;
164
205
  }
165
206
 
166
- /* solves (I+A'A)x = b, s warm start, solution stored in b */
167
- static scs_int pcg(const ScsMatrix *A, const ScsSettings *stgs,
168
- ScsLinSysWork *pr, const scs_float *s, scs_float *b,
207
+ /* solves (R_x * I + P + A' R_y^{-1} A)x = b, s warm start, solution in b */
208
+ static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *b,
169
209
  scs_int max_its, scs_float tol) {
170
- scs_int i, n = A->n;
171
- scs_float ipzr, ipzr_old, alpha;
210
+ scs_int i, n = pr->n;
211
+ scs_float ztr, ztr_prev, alpha;
172
212
  scs_float *p = pr->p; /* cg direction */
173
213
  scs_float *Gp = pr->Gp; /* updated CG direction */
174
214
  scs_float *r = pr->r; /* cg residual */
175
215
  scs_float *z = pr->z; /* for preconditioning */
176
- scs_float *M = pr->M; /* inverse diagonal preconditioner */
177
216
 
178
- if (s == SCS_NULL) {
217
+ const ScsMatrix *A = pr->A;
218
+ const ScsMatrix *P = pr->P;
219
+
220
+ if (!s) {
221
+ /* take s = 0 */
222
+ /* r = b */
179
223
  memcpy(r, b, n * sizeof(scs_float));
224
+ /* b = 0 */
180
225
  memset(b, 0, n * sizeof(scs_float));
181
226
  } else {
182
- mat_vec(A, stgs, pr, s, r);
183
- SCS(add_scaled_array)(r, b, n, -1);
184
- SCS(scale_array)(r, -1, n);
227
+ /* r = Mat * s */
228
+ mat_vec(A, P, pr, s, r);
229
+ /* r = Mat * s - b */
230
+ SCS(add_scaled_array)(r, b, n, -1.);
231
+ /* r = b - Mat * s */
232
+ SCS(scale_array)(r, -1., n);
233
+ /* b = s */
185
234
  memcpy(b, s, n * sizeof(scs_float));
186
235
  }
187
236
 
188
237
  /* check to see if we need to run CG at all */
189
- if (SCS(norm)(r, n) < MIN(tol, 1e-18)) {
238
+ if (CG_NORM(r, n) < MAX(tol, 1e-12)) {
190
239
  return 0;
191
240
  }
192
241
 
193
- apply_pre_conditioner(M, z, r, n, &ipzr);
242
+ /* z = M r (M is inverse preconditioner) */
243
+ apply_pre_conditioner(z, r, n, pr);
244
+ /* ztr = z'r */
245
+ ztr = SCS(dot)(z, r, n);
246
+ /* p = z */
194
247
  memcpy(p, z, n * sizeof(scs_float));
195
248
 
196
249
  for (i = 0; i < max_its; ++i) {
197
- mat_vec(A, stgs, pr, p, Gp);
198
- alpha = ipzr / SCS(dot)(p, Gp, n);
250
+ /* Gp = Mat * p */
251
+ mat_vec(A, P, pr, p, Gp);
252
+ /* alpha = z'r / p'G p */
253
+ alpha = ztr / SCS(dot)(p, Gp, n);
254
+ /* b += alpha * p */
199
255
  SCS(add_scaled_array)(b, p, n, alpha);
256
+ /* r -= alpha * G p */
200
257
  SCS(add_scaled_array)(r, Gp, n, -alpha);
201
258
 
202
- if (SCS(norm)(r, n) < tol) {
203
- #if EXTRA_VERBOSE > 0
204
- scs_printf("tol: %.4e, resid: %.4e, iters: %li\n", tol, SCS(norm)(r, n),
205
- (long)i + 1);
259
+ #if VERBOSITY > 3
260
+ scs_printf("tol: %.4e, resid: %.4e, iters: %li\n", tol, CG_NORM(r, n),
261
+ (long)i + 1);
206
262
  #endif
263
+ if (CG_NORM(r, n) < tol) {
207
264
  return i + 1;
208
265
  }
209
- ipzr_old = ipzr;
210
- apply_pre_conditioner(M, z, r, n, &ipzr);
211
-
212
- SCS(scale_array)(p, ipzr / ipzr_old, n);
213
- SCS(add_scaled_array)(p, z, n, 1);
266
+ /* z = M r (M is inverse preconditioner) */
267
+ apply_pre_conditioner(z, r, n, pr);
268
+ ztr_prev = ztr;
269
+ /* ztr = z'r */
270
+ ztr = SCS(dot)(z, r, n);
271
+ /* p = beta * p, where beta = ztr / ztr_prev */
272
+ SCS(scale_array)(p, ztr / ztr_prev, n);
273
+ /* p = z + beta * p */
274
+ SCS(add_scaled_array)(p, z, n, 1.);
214
275
  }
215
276
  return i;
216
277
  }
217
278
 
218
- scs_int SCS(solve_lin_sys)(const ScsMatrix *A, const ScsSettings *stgs,
219
- ScsLinSysWork *p, scs_float *b, const scs_float *s,
220
- scs_int iter) {
221
- scs_int cg_its;
222
- SCS(timer) linsys_timer;
223
- scs_float cg_tol =
224
- SCS(norm)(b, A->n) *
225
- (iter < 0 ? CG_BEST_TOL
226
- : CG_MIN_TOL / POWF((scs_float)iter + 1, stgs->cg_rate));
227
-
228
- SCS(tic)(&linsys_timer);
229
- /* solves Mx = b, for x but stores result in b */
230
- /* s contains warm-start (if available) */
231
- SCS(accum_by_atrans)(A, p, &(b[A->n]), b);
232
- /* solves (I+A'A)x = b, s warm start, solution stored in b */
233
- cg_its = pcg(A, stgs, p, s, b, A->n, MAX(cg_tol, CG_BEST_TOL));
234
- SCS(scale_array)(&(b[A->n]), -1, A->m);
235
- SCS(accum_by_a)(A, p, b, &(b[A->n]));
236
-
237
- if (iter >= 0) {
238
- p->tot_cg_its += cg_its;
279
+ /* solves Mx = b, for x but stores result in b */
280
+ /* s contains warm-start (if available) */
281
+ /*
282
+ * [x] = [R_x + P A' ]^{-1} [rx]
283
+ * [y] [ A -R_y ] [ry]
284
+ *
285
+ * becomes:
286
+ *
287
+ * x = (R_x + P + A' R_y^{-1} A)^{-1} (rx + A' R_y^{-1} ry)
288
+ * y = R_y^{-1} (Ax - ry)
289
+ *
290
+ */
291
+ scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
292
+ scs_float tol) {
293
+ scs_int cg_its, max_iters;
294
+
295
+ if (tol <= 0.) {
296
+ scs_printf("Warning: tol = %4f <= 0, likely compiled without setting "
297
+ "INDIRECT flag.\n",
298
+ tol);
239
299
  }
240
300
 
241
- p->total_solve_time += SCS(tocq)(&linsys_timer);
242
- #if EXTRA_VERBOSE > 0
243
- scs_printf("linsys solve time: %1.2es\n", SCS(tocq)(&linsys_timer) / 1e3);
301
+ if (CG_NORM(b, p->n + p->m) <= 1e-12) {
302
+ memset(b, 0, (p->n + p->m) * sizeof(scs_float));
303
+ return 0;
304
+ }
305
+
306
+ /* use p->tmp here, and in mat_vec, can do both since they don't overlap */
307
+ /* b = [rx; ry] */
308
+ /* tmp = ry */
309
+ memcpy(p->tmp, &(b[p->n]), p->m * sizeof(scs_float));
310
+ /* tmp = R_y^{-1} * ry */
311
+ scale_by_r_y_inv(p->tmp, p);
312
+ /* b[:n] = rx + A' R_y^{-1} ry */
313
+ SCS(accum_by_atrans)(p->A, p->tmp, b);
314
+ /* set max_iters to 10 * n (though in theory n is enough for any tol) */
315
+ max_iters = 10 * p->n;
316
+ /* solves (R_x + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
317
+ * b */
318
+ cg_its = pcg(p, s, b, max_iters, tol); /* b[:n] = x */
319
+
320
+ /* b[n:] = -ry */
321
+ SCS(scale_array)(&(b[p->n]), -1., p->m);
322
+ /* b[n:] = Ax - ry */
323
+ accum_by_a(p, b, &(b[p->n]));
324
+ /* b[n:] = R_y^{-1} (Ax - ry) = y */
325
+ scale_by_r_y_inv(&(b[p->n]), p);
326
+ p->tot_cg_its += cg_its;
327
+ #if VERBOSITY > 1
328
+ scs_printf("tol %.3e\n", tol);
329
+ scs_printf("cg_its %i\n", (int)cg_its);
244
330
  #endif
245
331
  return 0;
246
332
  }
247
-
248
- void SCS(normalize_a)(ScsMatrix *A, const ScsSettings *stgs, const ScsCone *k,
249
- ScsScaling *scal) {
250
- SCS(_normalize_a)(A, stgs, k, scal);
251
- }
252
-
253
- void SCS(un_normalize_a)(ScsMatrix *A, const ScsSettings *stgs,
254
- const ScsScaling *scal) {
255
- SCS(_un_normalize_a)(A, stgs, scal);
256
- }
@@ -5,24 +5,27 @@
5
5
  extern "C" {
6
6
  #endif
7
7
 
8
- #include <math.h>
9
- #include "amatrix.h"
10
8
  #include "glbopts.h"
11
9
  #include "linalg.h"
12
10
  #include "scs.h"
11
+ #include "scs_matrix.h"
12
+ #include <math.h>
13
13
 
14
14
  struct SCS_LIN_SYS_WORK {
15
+ scs_int n, m; /* linear system dimensions */
15
16
  scs_float *p; /* cg iterate */
16
17
  scs_float *r; /* cg residual */
17
18
  scs_float *Gp;
18
19
  scs_float *tmp;
19
- ScsMatrix *At;
20
+ const ScsMatrix *A; /* does *not* own this memory */
21
+ const ScsMatrix *P; /* does *not* own this memory */
22
+ ScsMatrix *At; /* does own this memory */
20
23
  /* preconditioning */
21
24
  scs_float *z;
22
25
  scs_float *M;
23
26
  /* reporting */
24
27
  scs_int tot_cg_its;
25
- scs_float total_solve_time;
28
+ const scs_float *diag_r;
26
29
  };
27
30
 
28
31
  #ifdef __cplusplus
@@ -0,0 +1,87 @@
1
+ /* Routines modified from CSparse, T. Davis et al */
2
+
3
+ #include "csparse.h"
4
+
5
+ csc *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values,
6
+ scs_int triplet) {
7
+ csc *A = (csc *)scs_calloc(1, sizeof(csc)); /* allocate the csc struct */
8
+ if (!A) {
9
+ return SCS_NULL;
10
+ } /* out of memory */
11
+ A->m = m; /* define dimensions and nzmax */
12
+ A->n = n;
13
+ A->nzmax = nzmax = MAX(nzmax, 1);
14
+ A->nz = triplet ? 0 : -1; /* allocate triplet or comp.col */
15
+ A->p = (scs_int *)scs_calloc((triplet ? nzmax : n + 1), sizeof(scs_int));
16
+ A->i = (scs_int *)scs_calloc(nzmax, sizeof(scs_int));
17
+ A->x = values ? (scs_float *)scs_calloc(nzmax, sizeof(scs_float)) : SCS_NULL;
18
+ return (!A->p || !A->i || (values && !A->x)) ? SCS(cs_spfree)(A) : A;
19
+ }
20
+
21
+ csc *SCS(cs_done)(csc *C, void *w, void *x, scs_int ok) {
22
+ scs_free(w); /* free workspace */
23
+ scs_free(x);
24
+ return ok ? C : SCS(cs_spfree)(C); /* return result if OK, else free it */
25
+ }
26
+
27
+ /* C = compressed-column form of a triplet matrix T */
28
+ csc *SCS(cs_compress)(const csc *T, scs_int *idx_mapping) {
29
+ scs_int m, n, nz, p, k, *Cp, *Ci, *w, *Ti, *Tj;
30
+ scs_float *Cx, *Tx;
31
+ csc *C;
32
+ m = T->m;
33
+ n = T->n;
34
+ Ti = T->i;
35
+ Tj = T->p;
36
+ Tx = T->x;
37
+ nz = T->nz;
38
+ C = SCS(cs_spalloc)(m, n, nz, Tx != SCS_NULL, 0); /* allocate result */
39
+ w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */
40
+ if (!C || !w) {
41
+ return SCS(cs_done)(C, w, SCS_NULL, 0);
42
+ } /* out of memory */
43
+ Cp = C->p;
44
+ Ci = C->i;
45
+ Cx = C->x;
46
+ for (k = 0; k < nz; k++) {
47
+ w[Tj[k]]++; /* column counts */
48
+ }
49
+ SCS(cumsum)(Cp, w, n); /* column pointers */
50
+ for (k = 0; k < nz; k++) {
51
+ Ci[p = w[Tj[k]]++] = Ti[k]; /* A(i,j) is the pth entry in C */
52
+ if (idx_mapping) {
53
+ idx_mapping[k] = p;
54
+ } /* old to new indices */
55
+ if (Cx) {
56
+ Cx[p] = Tx[k];
57
+ }
58
+ }
59
+ return SCS(cs_done)(C, w, SCS_NULL, 1); /* success; free w and return C */
60
+ }
61
+
62
+ scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n) {
63
+ scs_int i, nz = 0;
64
+ scs_float nz2 = 0;
65
+ if (!p || !c) {
66
+ return (-1);
67
+ } /* check inputs */
68
+ for (i = 0; i < n; i++) {
69
+ p[i] = nz;
70
+ nz += c[i];
71
+ nz2 += c[i]; /* also in scs_float to avoid scs_int overflow */
72
+ c[i] = p[i]; /* also copy p[0..n-1] back into c[0..n-1]*/
73
+ }
74
+ p[n] = nz;
75
+ return nz2; /* return sum (c [0..n-1]) */
76
+ }
77
+
78
+ csc *SCS(cs_spfree)(csc *A) {
79
+ if (!A) {
80
+ return SCS_NULL;
81
+ } /* do nothing if A already SCS_NULL */
82
+ scs_free(A->p);
83
+ scs_free(A->i);
84
+ scs_free(A->x);
85
+ scs_free(A);
86
+ return (csc *)SCS_NULL; /* free the csc struct and return SCS_NULL */
87
+ }
@@ -0,0 +1,34 @@
1
+ /* Routines modified from CSparse, T. Davis et al */
2
+
3
+ #ifndef CS_H_GUARD
4
+ #define CS_H_GUARD
5
+
6
+ #ifdef __cplusplus
7
+ extern "C" {
8
+ #endif
9
+
10
+ #include "glbopts.h"
11
+ #include "scs.h"
12
+
13
+ /* matrix in compressed-column or triplet form */
14
+ typedef struct SPARSE_MATRIX {
15
+ scs_int nzmax; /* maximum number of entries */
16
+ scs_int m; /* number of rows */
17
+ scs_int n; /* number of columns */
18
+ scs_int *p; /* column pointers (size n+1) or col indices (size nzmax) */
19
+ scs_int *i; /* row indices, size nzmax */
20
+ scs_float *x; /* numerical values, size nzmax */
21
+ scs_int nz; /* # of entries in triplet matrix, -1 for compressed-col */
22
+ } csc;
23
+
24
+ csc *SCS(cs_spalloc)(scs_int m, scs_int n, scs_int nzmax, scs_int values,
25
+ scs_int triplet);
26
+ csc *SCS(cs_done)(csc *C, void *w, void *x, scs_int ok);
27
+ csc *SCS(cs_compress)(const csc *T, scs_int *idx_mapping);
28
+ scs_float SCS(cumsum)(scs_int *p, scs_int *c, scs_int n);
29
+ csc *SCS(cs_spfree)(csc *A);
30
+
31
+ #ifdef __cplusplus
32
+ }
33
+ #endif
34
+ #endif
@@ -18,7 +18,6 @@
18
18
 
19
19
  #ifdef MATLAB_MEX_FILE
20
20
  #include "mex.h"
21
- #include "matrix.h"
22
21
  #endif
23
22
 
24
23
  #ifndef NULL
@@ -51,7 +50,7 @@
51
50
 
52
51
  struct SuiteSparse_config_struct SuiteSparse_config =
53
52
  {
54
- _scs_malloc, _scs_calloc, _scs_realloc, _scs_free, _scs_printf,
53
+ scs_malloc, scs_calloc, scs_realloc, scs_free, _scs_printf,
55
54
  SuiteSparse_hypot,
56
55
  SuiteSparse_divcomplex
57
56
 
@@ -73,12 +72,13 @@ struct SuiteSparse_config_struct SuiteSparse_config =
73
72
  SuiteSparse_start be called prior to calling any SuiteSparse function.
74
73
  */
75
74
 
75
+
76
76
  void SuiteSparse_start ( void )
77
77
  {
78
- SuiteSparse_config.malloc_func = _scs_malloc ;
79
- SuiteSparse_config.calloc_func = _scs_calloc ;
80
- SuiteSparse_config.realloc_func = _scs_realloc ;
81
- SuiteSparse_config.free_func = _scs_free ;
78
+ SuiteSparse_config.malloc_func = scs_malloc ;
79
+ SuiteSparse_config.calloc_func = scs_calloc ;
80
+ SuiteSparse_config.realloc_func = scs_realloc ;
81
+ SuiteSparse_config.free_func = scs_free ;
82
82
  SuiteSparse_config.printf_func = _scs_printf ;
83
83
  /* math functions */
84
84
  SuiteSparse_config.hypot_func = SuiteSparse_hypot ;
@@ -44,7 +44,7 @@ extern "C" {
44
44
 
45
45
  #include <limits.h>
46
46
  #include <stdlib.h>
47
- #include "scs.h"
47
+ #include "glbopts.h"
48
48
  #include "ctrlc.h"
49
49
 
50
50
  /* ========================================================================== */
@@ -71,6 +71,11 @@ extern "C" {
71
71
  #define SuiteSparse_long_id "%" SuiteSparse_long_idd
72
72
  #endif
73
73
 
74
+ #ifndef _scs_printf
75
+ #define _scs_printf scs_printf
76
+ #endif
77
+
78
+
74
79
  /* ========================================================================== */
75
80
  /* === SuiteSparse_config parameters and functions ========================== */
76
81
  /* ========================================================================== */
@@ -66,7 +66,7 @@
66
66
  /* ------------------------------------------------------------------------- */
67
67
 
68
68
  #ifdef MATLAB_MEX_FILE
69
- #include "matrix.h"
69
+ #include "scs_matrix.h"
70
70
  #include "mex.h"
71
71
  #endif
72
72
 
@@ -89,8 +89,8 @@ GLOBAL Int AMD_order
89
89
  }
90
90
 
91
91
  /* allocate two size-n integer workspaces */
92
- Len = SuiteSparse_malloc (n, sizeof (Int)) ;
93
- Pinv = SuiteSparse_malloc (n, sizeof (Int)) ;
92
+ Len = (Int *)SuiteSparse_malloc (n, sizeof (Int)) ;
93
+ Pinv = (Int *)SuiteSparse_malloc (n, sizeof (Int)) ;
94
94
  mem += n ;
95
95
  mem += n ;
96
96
  if (!Len || !Pinv)
@@ -106,8 +106,8 @@ GLOBAL Int AMD_order
106
106
  {
107
107
  /* sort the input matrix and remove duplicate entries */
108
108
  AMD_DEBUG1 (("Matrix is jumbled\n")) ;
109
- Rp = SuiteSparse_malloc (n+1, sizeof (Int)) ;
110
- Ri = SuiteSparse_malloc (nz, sizeof (Int)) ;
109
+ Rp = (Int *)SuiteSparse_malloc (n+1, sizeof (Int)) ;
110
+ Ri = (Int *)SuiteSparse_malloc (nz, sizeof (Int)) ;
111
111
  mem += (n+1) ;
112
112
  mem += MAX (nz,1) ;
113
113
  if (!Rp || !Ri)
@@ -160,7 +160,7 @@ GLOBAL Int AMD_order
160
160
  ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
161
161
  if (ok)
162
162
  {
163
- S = SuiteSparse_malloc (slen, sizeof (Int)) ;
163
+ S = (Int *)SuiteSparse_malloc (slen, sizeof (Int)) ;
164
164
  }
165
165
  AMD_DEBUG1 (("slen %g\n", (scs_float) slen)) ;
166
166
  if (!S)