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
@@ -1,43 +1,52 @@
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
+ /* set M = inv ( diag ( rho_x * I + P + A' R_y^{-1} A ) ) */
21
+ static void set_preconditioner(ScsLinSysWork *p) {
22
+ scs_int i, k;
28
23
  scs_float *M = p->M;
24
+ const ScsMatrix *A = p->A;
25
+ const ScsMatrix *P = p->P;
29
26
 
30
- #if EXTRA_VERBOSE > 0
27
+ #if VERBOSITY > 0
31
28
  scs_printf("getting pre-conditioner\n");
32
29
  #endif
33
30
 
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; */
31
+ for (i = 0; i < A->n; ++i) { /* cols */
32
+ M[i] = p->rho_x;
33
+ /* diag(A' R_y^{-1} A) */
34
+ for (k = A->p[i]; k < A->p[i + 1]; ++k) {
35
+ /* A->i[k] is row of entry k with value A->x[k] */
36
+ M[i] += A->x[k] * A->x[k] / p->rho_y_vec[A->i[k]];
37
+ }
38
+ if (P) {
39
+ for (k = P->p[i]; k < P->p[i + 1]; k++) {
40
+ /* diagonal element only */
41
+ if (P->i[k] == i) { /* row == col */
42
+ M[i] += P->x[k];
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ M[i] = 1. / M[i];
38
48
  }
39
-
40
- #if EXTRA_VERBOSE > 0
49
+ #if VERBOSITY > 0
41
50
  scs_printf("finished getting pre-conditioner\n");
42
51
  #endif
43
52
  }
@@ -54,15 +63,16 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
54
63
  scs_float *Ax = A->x;
55
64
 
56
65
  scs_int i, j, q, *z, c1, c2;
57
- #if EXTRA_VERBOSE > 0
66
+ #if VERBOSITY > 0
58
67
  SCS(timer) transpose_timer;
59
68
  scs_printf("transposing A\n");
60
69
  SCS(tic)(&transpose_timer);
61
70
  #endif
62
71
 
63
72
  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 */
73
+ for (i = 0; i < Ap[n]; i++)
74
+ z[Ai[i]]++; /* row counts */
75
+ SCS(cumsum)(Cp, z, m); /* row pointers */
66
76
 
67
77
  for (j = 0; j < n; j++) {
68
78
  c1 = Ap[j];
@@ -76,7 +86,7 @@ static void transpose(const ScsMatrix *A, ScsLinSysWork *p) {
76
86
  }
77
87
  scs_free(z);
78
88
 
79
- #if EXTRA_VERBOSE > 0
89
+ #if VERBOSITY > 0
80
90
  scs_printf("finished transposing A, time: %1.2es\n",
81
91
  SCS(tocq)(&transpose_timer) / 1e3);
82
92
  #endif
@@ -100,40 +110,59 @@ void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
100
110
  }
101
111
  }
102
112
 
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);
113
+ /* vec -> R_y^{-1} vec */
114
+ static void scale_by_diag_r(scs_float *vec, ScsLinSysWork *p) {
115
+ scs_int i;
116
+ for (i = 0; i < p->m; ++i) {
117
+ vec[i] /= p->rho_y_vec[i];
118
+ }
112
119
  }
113
120
 
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);
121
+ /* we use a different accum_by_a here for speed */
122
+ static void accum_by_a(ScsLinSysWork *p, const scs_float *x, scs_float *y) {
123
+ SCS(accum_by_atrans)(p->At, x, y);
117
124
  }
118
125
 
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);
126
+ /* y = (rho_x * I + P + A' R_y^{-1} A) x */
127
+ static void mat_vec(const ScsMatrix *A, const ScsMatrix *P, ScsLinSysWork *p,
128
+ const scs_float *x, scs_float *y) {
129
+ scs_float *z = p->tmp;
130
+ memset(z, 0, A->m * sizeof(scs_float)); /* z = 0 */
131
+ memset(y, 0, A->n * sizeof(scs_float)); /* y = 0 */
132
+ if (P) {
133
+ SCS(accum_by_p)(P, x, y); /* y = Px */
134
+ }
135
+ accum_by_a(p, x, z); /* z = Ax */
136
+ scale_by_diag_r(z, p); /* z = R_y^{-1} A x */
137
+ SCS(accum_by_atrans)(A, z, y); /* y += A'z, y = Px + A' R_y^{-1} Ax */
138
+ /* y = rho_x * x + Px + A' R_y^{-1} A x */
139
+ SCS(add_scaled_array)(y, x, A->n, p->rho_x);
122
140
  }
123
141
 
124
- static void apply_pre_conditioner(scs_float *M, scs_float *z, scs_float *r,
125
- scs_int n, scs_float *ipzr) {
142
+ static void apply_pre_conditioner(scs_float *z, scs_float *r, scs_int n,
143
+ ScsLinSysWork *pr) {
126
144
  scs_int i;
127
- *ipzr = 0;
145
+ scs_float *M = pr->M;
128
146
  for (i = 0; i < n; ++i) {
129
147
  z[i] = r[i] * M[i];
130
- *ipzr += z[i] * r[i];
131
148
  }
132
149
  }
133
150
 
134
- ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
135
- const ScsSettings *stgs) {
151
+ /* no need to update anything in this case */
152
+ void SCS(update_lin_sys_rho_y_vec)(ScsLinSysWork *p, scs_float *rho_y_vec) {
153
+ p->rho_y_vec = rho_y_vec; /* this isn't needed but do it to be safe */
154
+ set_preconditioner(p);
155
+ }
156
+
157
+ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
158
+ scs_float *rho_y_vec, scs_float rho_x) {
136
159
  ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
160
+ p->A = A;
161
+ p->P = P;
162
+ p->m = A->m;
163
+ p->n = A->n;
164
+ p->rho_x = rho_x;
165
+
137
166
  p->p = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
138
167
  p->r = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
139
168
  p->Gp = (scs_float *)scs_malloc((A->n) * sizeof(scs_float));
@@ -149,11 +178,11 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
149
178
  transpose(A, p);
150
179
 
151
180
  /* 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);
181
+ p->rho_y_vec = rho_y_vec;
182
+ p->z = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
183
+ p->M = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
184
+ set_preconditioner(p);
155
185
 
156
- p->total_solve_time = 0;
157
186
  p->tot_cg_its = 0;
158
187
  if (!p->p || !p->r || !p->Gp || !p->tmp || !p->At || !p->At->i || !p->At->p ||
159
188
  !p->At->x) {
@@ -163,94 +192,132 @@ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
163
192
  return p;
164
193
  }
165
194
 
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,
195
+ /* solves (rho_x * I + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
196
+ * b */
197
+ static scs_int pcg(ScsLinSysWork *pr, const scs_float *s, scs_float *b,
169
198
  scs_int max_its, scs_float tol) {
170
- scs_int i, n = A->n;
171
- scs_float ipzr, ipzr_old, alpha;
199
+ scs_int i, n = pr->n;
200
+ scs_float ztr, ztr_prev, alpha;
172
201
  scs_float *p = pr->p; /* cg direction */
173
202
  scs_float *Gp = pr->Gp; /* updated CG direction */
174
203
  scs_float *r = pr->r; /* cg residual */
175
204
  scs_float *z = pr->z; /* for preconditioning */
176
- scs_float *M = pr->M; /* inverse diagonal preconditioner */
177
205
 
178
- if (s == SCS_NULL) {
206
+ const ScsMatrix *A = pr->A;
207
+ const ScsMatrix *P = pr->P;
208
+
209
+ if (!s) {
210
+ /* take s = 0 */
211
+ /* r = b */
179
212
  memcpy(r, b, n * sizeof(scs_float));
213
+ /* b = 0 */
180
214
  memset(b, 0, n * sizeof(scs_float));
181
215
  } 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);
216
+ /* r = Mat * s */
217
+ mat_vec(A, P, pr, s, r);
218
+ /* r = Mat * s - b */
219
+ SCS(add_scaled_array)(r, b, n, -1.);
220
+ /* r = b - Mat * s */
221
+ SCS(scale_array)(r, -1., n);
222
+ /* b = s */
185
223
  memcpy(b, s, n * sizeof(scs_float));
186
224
  }
187
225
 
188
226
  /* check to see if we need to run CG at all */
189
- if (SCS(norm)(r, n) < MIN(tol, 1e-18)) {
227
+ if (CG_NORM(r, n) < MAX(tol, 1e-12)) {
190
228
  return 0;
191
229
  }
192
230
 
193
- apply_pre_conditioner(M, z, r, n, &ipzr);
231
+ /* z = M r (M is inverse preconditioner) */
232
+ apply_pre_conditioner(z, r, n, pr);
233
+ /* ztr = z'r */
234
+ ztr = SCS(dot)(z, r, n);
235
+ /* p = z */
194
236
  memcpy(p, z, n * sizeof(scs_float));
195
237
 
196
238
  for (i = 0; i < max_its; ++i) {
197
- mat_vec(A, stgs, pr, p, Gp);
198
- alpha = ipzr / SCS(dot)(p, Gp, n);
239
+ /* Gp = Mat * p */
240
+ mat_vec(A, P, pr, p, Gp);
241
+ /* alpha = z'r / p'G p */
242
+ alpha = ztr / SCS(dot)(p, Gp, n);
243
+ /* b += alpha * p */
199
244
  SCS(add_scaled_array)(b, p, n, alpha);
245
+ /* r -= alpha * G p */
200
246
  SCS(add_scaled_array)(r, Gp, n, -alpha);
201
247
 
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);
248
+ #if VERBOSITY > 3
249
+ scs_printf("tol: %.4e, resid: %.4e, iters: %li\n", tol, CG_NORM(r, n),
250
+ (long)i + 1);
206
251
  #endif
252
+ if (CG_NORM(r, n) < tol) {
207
253
  return i + 1;
208
254
  }
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);
255
+ /* z = M r (M is inverse preconditioner) */
256
+ apply_pre_conditioner(z, r, n, pr);
257
+ ztr_prev = ztr;
258
+ /* ztr = z'r */
259
+ ztr = SCS(dot)(z, r, n);
260
+ /* p = beta * p, where beta = ztr / ztr_prev */
261
+ SCS(scale_array)(p, ztr / ztr_prev, n);
262
+ /* p = z + beta * p */
263
+ SCS(add_scaled_array)(p, z, n, 1.);
214
264
  }
215
265
  return i;
216
266
  }
217
267
 
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;
268
+ /* solves Mx = b, for x but stores result in b */
269
+ /* s contains warm-start (if available) */
270
+ /*
271
+ * [x] = [rho_x I + P A' ]^{-1} [rx]
272
+ * [y] [ A -R_y ] [ry]
273
+ *
274
+ * R_y = diag(rho_y_vec)
275
+ *
276
+ * becomes:
277
+ *
278
+ * x = (rho_x I + P + A' R_y^{-1} A)^{-1} (rx + A' R_y^{-1} ry)
279
+ * y = R_y^{-1} (Ax - ry)
280
+ *
281
+ */
282
+ scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
283
+ scs_float tol) {
284
+ scs_int cg_its, max_iters;
285
+
286
+ if (tol <= 0.) {
287
+ scs_printf("Warning: tol = %4f <= 0, likely compiled without setting "
288
+ "INDIRECT flag.\n",
289
+ tol);
290
+ }
291
+
292
+ if (CG_NORM(b, p->n + p->m) <= 1e-12) {
293
+ memset(b, 0, (p->n + p->m) * sizeof(scs_float));
294
+ return 0;
239
295
  }
240
296
 
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);
297
+ /* use p->tmp here, and in mat_vec, can do both since they don't overlap */
298
+ /* b = [rx; ry] */
299
+ /* tmp = ry */
300
+ memcpy(p->tmp, &(b[p->n]), p->m * sizeof(scs_float));
301
+ /* tmp = R_y^{-1} * ry */
302
+ scale_by_diag_r(p->tmp, p);
303
+ /* b[:n] = rx + A' R_y^{-1} ry */
304
+ SCS(accum_by_atrans)(p->A, p->tmp, b);
305
+ /* set max_iters to 10 * n (though in theory n is enough for any tol) */
306
+ max_iters = 10 * p->n;
307
+ /* solves (rho_x I + P + A' R_y^{-1} A)x = b, s warm start, solution stored in
308
+ * b */
309
+ cg_its = pcg(p, s, b, max_iters, tol); /* b[:n] = x */
310
+
311
+ /* b[n:] = -ry */
312
+ SCS(scale_array)(&(b[p->n]), -1., p->m);
313
+ /* b[n:] = Ax - ry */
314
+ accum_by_a(p, b, &(b[p->n]));
315
+ /* b[n:] = R_y^{-1} (Ax - ry) = y */
316
+ scale_by_diag_r(&(b[p->n]), p);
317
+ p->tot_cg_its += cg_its;
318
+ #if VERBOSITY > 1
319
+ scs_printf("tol %.3e\n", tol);
320
+ scs_printf("cg_its %i\n", (int)cg_its);
244
321
  #endif
245
322
  return 0;
246
323
  }
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,28 @@
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
+ scs_float *rho_y_vec;
29
+ scs_float rho_x;
26
30
  };
27
31
 
28
32
  #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_malloc((triplet ? nzmax : n + 1) * sizeof(scs_int));
16
+ A->i = (scs_int *)scs_malloc(nzmax * sizeof(scs_int));
17
+ A->x = values ? (scs_float *)scs_malloc(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
Binary file
@@ -18,7 +18,7 @@
18
18
 
19
19
  #ifdef MATLAB_MEX_FILE
20
20
  #include "mex.h"
21
- #include "matrix.h"
21
+ #include "scs_matrix.h"
22
22
  #endif
23
23
 
24
24
  #ifndef NULL
Binary file
Binary file
@@ -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
 
@@ -1,3 +1,5 @@
1
+ Last qdldl commit: a00d500906621fbf014b39e42a3304d1143eb65f
2
+
1
3
  flatten into one dir
2
4
  create qdldl_types.h from template file
3
5
  add 'include "glbopts.h"' to qdldl_types.h