scs 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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