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,221 +1,223 @@
1
1
  #include "private.h"
2
+ #include "linsys.h"
2
3
 
3
- struct SPARSE_MATRIX /* matrix in compressed-column or triplet form */
4
- {
5
- scs_int nzmax; /* maximum number of entries */
6
- scs_int m; /* number of rows */
7
- scs_int n; /* number of columns */
8
- scs_int *p; /* column pointers (size n+1) or col indices (size nzmax) */
9
- scs_int *i; /* row indices, size nzmax */
10
- scs_float *x; /* numerical values, size nzmax */
11
- scs_int nz; /* # of entries in triplet matrix, -1 for compressed-col */
12
- };
13
-
14
- char *SCS(get_lin_sys_method)(const ScsMatrix *A, const ScsSettings *stgs) {
15
- char *tmp = (char *)scs_malloc(sizeof(char) * 128);
16
- sprintf(tmp, "sparse-direct, nnz in A = %li", (long)A->p[A->n]);
17
- return tmp;
4
+ const char *SCS(get_lin_sys_method)() {
5
+ return "sparse-direct";
18
6
  }
19
7
 
8
+ /*
20
9
  char *SCS(get_lin_sys_summary)(ScsLinSysWork *p, const ScsInfo *info) {
21
10
  char *str = (char *)scs_malloc(sizeof(char) * 128);
22
11
  scs_int n = p->L->n;
23
- sprintf(str, "\tLin-sys: nnz in L factor: %li, avg solve time: %1.2es\n",
24
- (long)(p->L->p[n] + n), p->total_solve_time / (info->iter + 1) / 1e3);
25
- p->total_solve_time = 0;
12
+ sprintf(str, "lin-sys: nnz(L): %li\n", (long)(p->L->p[n] + n));
26
13
  return str;
27
14
  }
28
-
29
- /* wrapper for free */
30
- static void *cs_free(void *p) {
31
- if (p) {
32
- scs_free(p);
33
- } /* free p if it is not already SCS_NULL */
34
- return SCS_NULL; /* return SCS_NULL to simplify the use of cs_free */
35
- }
36
-
37
- static _cs *cs_spfree(_cs *A) {
38
- if (!A) {
39
- return SCS_NULL;
40
- } /* do nothing if A already SCS_NULL */
41
- cs_free(A->p);
42
- cs_free(A->i);
43
- cs_free(A->x);
44
- return (_cs *)cs_free(A); /* free the _cs struct and return SCS_NULL */
45
- }
15
+ */
46
16
 
47
17
  void SCS(free_lin_sys_work)(ScsLinSysWork *p) {
48
18
  if (p) {
49
- cs_spfree(p->L);
50
- scs_free(p->P);
19
+ SCS(cs_spfree)(p->L);
20
+ SCS(cs_spfree)(p->kkt);
21
+ scs_free(p->diag_p);
22
+ scs_free(p->perm);
51
23
  scs_free(p->Dinv);
52
24
  scs_free(p->bp);
25
+ scs_free(p->diag_r_idxs);
26
+ scs_free(p->Lnz);
27
+ scs_free(p->iwork);
28
+ scs_free(p->etree);
29
+ scs_free(p->D);
30
+ scs_free(p->bwork);
31
+ scs_free(p->fwork);
53
32
  scs_free(p);
54
33
  }
55
34
  }
56
35
 
57
- static _cs *cs_spalloc(scs_int m, scs_int n, scs_int nzmax, scs_int values,
58
- scs_int triplet) {
59
- _cs *A = (_cs *)scs_calloc(1, sizeof(_cs)); /* allocate the _cs struct */
60
- if (!A) {
61
- return SCS_NULL;
62
- } /* out of memory */
63
- A->m = m; /* define dimensions and nzmax */
64
- A->n = n;
65
- A->nzmax = nzmax = MAX(nzmax, 1);
66
- A->nz = triplet ? 0 : -1; /* allocate triplet or comp.col */
67
- A->p = (scs_int *)scs_malloc((triplet ? nzmax : n + 1) * sizeof(scs_int));
68
- A->i = (scs_int *)scs_malloc(nzmax * sizeof(scs_int));
69
- A->x = values ? (scs_float *)scs_malloc(nzmax * sizeof(scs_float)) : SCS_NULL;
70
- return (!A->p || !A->i || (values && !A->x)) ? cs_spfree(A) : A;
71
- }
72
-
73
- static _cs *cs_done(_cs *C, void *w, void *x, scs_int ok) {
74
- cs_free(w); /* free workspace */
75
- cs_free(x);
76
- return ok ? C : cs_spfree(C); /* return result if OK, else free it */
77
- }
78
-
79
- /* C = compressed-column form of a triplet matrix T */
80
- static _cs *cs_compress(const _cs *T) {
81
- scs_int m, n, nz, p, k, *Cp, *Ci, *w, *Ti, *Tj;
82
- scs_float *Cx, *Tx;
83
- _cs *C;
84
- m = T->m;
85
- n = T->n;
86
- Ti = T->i;
87
- Tj = T->p;
88
- Tx = T->x;
89
- nz = T->nz;
90
- C = cs_spalloc(m, n, nz, Tx != SCS_NULL, 0); /* allocate result */
91
- w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */
92
- if (!C || !w) {
93
- return cs_done(C, w, SCS_NULL, 0);
94
- } /* out of memory */
95
- Cp = C->p;
96
- Ci = C->i;
97
- Cx = C->x;
98
- for (k = 0; k < nz; k++) w[Tj[k]]++; /* column counts */
99
- SCS(cumsum)(Cp, w, n); /* column pointers */
100
- for (k = 0; k < nz; k++) {
101
- Ci[p = w[Tj[k]]++] = Ti[k]; /* A(i,j) is the pth entry in C */
102
- if (Cx) {
103
- Cx[p] = Tx[k];
104
- }
105
- }
106
- return cs_done(C, w, SCS_NULL, 1); /* success; free w and return C */
107
- }
108
-
109
- static _cs *form_kkt(const ScsMatrix *A, const ScsSettings *s) {
36
+ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P, scs_float *diag_p,
37
+ const scs_float *diag_r, scs_int *diag_r_idxs) {
110
38
  /* ONLY UPPER TRIANGULAR PART IS STUFFED
111
- * forms column compressed KKT matrix
39
+ * forms column compressed kkt matrix
112
40
  * assumes column compressed form A matrix
113
41
  *
114
- * forms upper triangular part of [I A'; A -I]
42
+ * forms upper triangular part of [(I + P) A'; A -I]
43
+ * P : n x n, A: m x n.
115
44
  */
116
- scs_int j, k, kk;
117
- _cs *K_cs;
118
- /* I at top left */
119
- const scs_int Anz = A->p[A->n];
120
- const scs_int Knzmax = A->n + A->m + Anz;
121
- _cs *K = cs_spalloc(A->m + A->n, A->m + A->n, Knzmax, 1, 1);
45
+ scs_int h, i, j, count;
46
+ csc *Kcsc, *K;
47
+ scs_int n = A->n;
48
+ scs_int m = A->m;
49
+ scs_int Anz = A->p[n];
50
+ scs_int Knzmax;
51
+ scs_int *idx_mapping;
52
+ if (P) {
53
+ /* Upper bound P + I upper triangular component as Pnz + n */
54
+ Knzmax = n + m + Anz + P->p[n];
55
+ } else {
56
+ Knzmax = n + m + Anz;
57
+ }
58
+ K = SCS(cs_spalloc)(m + n, m + n, Knzmax, 1, 1);
122
59
 
123
- #if EXTRA_VERBOSE > 0
124
- scs_printf("forming KKT\n");
60
+ #if VERBOSITY > 0
61
+ scs_printf("forming kkt\n");
125
62
  #endif
126
-
63
+ /* Here we generate a triplet matrix and then compress to CSC */
127
64
  if (!K) {
128
65
  return SCS_NULL;
129
66
  }
130
- kk = 0;
131
- for (k = 0; k < A->n; k++) {
132
- K->i[kk] = k;
133
- K->p[kk] = k;
134
- K->x[kk] = s->rho_x;
135
- kk++;
67
+
68
+ count = 0; /* element counter */
69
+ if (P) {
70
+ /* R_x + P in top left */
71
+ for (j = 0; j < n; j++) { /* cols */
72
+ diag_p[j] = 0.;
73
+ /* empty column, add diagonal */
74
+ if (P->p[j] == P->p[j + 1]) {
75
+ K->i[count] = j;
76
+ K->p[count] = j;
77
+ K->x[count] = diag_r[j];
78
+ diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
79
+ count++;
80
+ }
81
+ for (h = P->p[j]; h < P->p[j + 1]; h++) {
82
+ i = P->i[h]; /* row */
83
+ if (i > j) { /* only upper triangular needed */
84
+ break;
85
+ }
86
+ K->i[count] = i;
87
+ K->p[count] = j;
88
+ K->x[count] = P->x[h];
89
+ if (i == j) {
90
+ /* P has diagonal element */
91
+ diag_p[j] = P->x[h];
92
+ K->x[count] += diag_r[j];
93
+ diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
94
+ }
95
+ count++;
96
+ /* reached the end without adding diagonal, do it now */
97
+ if ((i < j) && (h + 1 == P->p[j + 1] || P->i[h + 1] > j)) {
98
+ K->i[count] = j;
99
+ K->p[count] = j;
100
+ K->x[count] = diag_r[j];
101
+ diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
102
+ count++;
103
+ }
104
+ }
105
+ }
106
+ } else {
107
+ /* R_x in top left */
108
+ for (j = 0; j < n; j++) {
109
+ diag_p[j] = 0.;
110
+ K->i[count] = j;
111
+ K->p[count] = j;
112
+ K->x[count] = diag_r[j];
113
+ diag_r_idxs[j] = count; /* store the indices where diag_r occurs */
114
+ count++;
115
+ }
136
116
  }
137
- /* A^T at top right : CCS: */
138
- for (j = 0; j < A->n; j++) {
139
- for (k = A->p[j]; k < A->p[j + 1]; k++) {
140
- K->p[kk] = A->i[k] + A->n;
141
- K->i[kk] = j;
142
- K->x[kk] = A->x[k];
143
- kk++;
117
+
118
+ /* A^T at top right */
119
+ for (j = 0; j < n; j++) {
120
+ for (h = A->p[j]; h < A->p[j + 1]; h++) {
121
+ K->p[count] = A->i[h] + n;
122
+ K->i[count] = j;
123
+ K->x[count] = A->x[h];
124
+ count++;
144
125
  }
145
126
  }
146
- /* -I at bottom right */
147
- for (k = 0; k < A->m; k++) {
148
- K->i[kk] = k + A->n;
149
- K->p[kk] = k + A->n;
150
- K->x[kk] = -1;
151
- kk++;
127
+
128
+ /* -R_y at bottom right */
129
+ for (j = 0; j < m; j++) {
130
+ K->i[count] = j + n;
131
+ K->p[count] = j + n;
132
+ K->x[count] = -diag_r[j + n];
133
+ diag_r_idxs[j + n] = count; /* store the indices where diag_r occurs */
134
+ count++;
135
+ }
136
+
137
+ K->nz = count;
138
+ idx_mapping = (scs_int *)scs_calloc(K->nz, sizeof(scs_int));
139
+ Kcsc = SCS(cs_compress)(K, idx_mapping);
140
+ for (i = 0; i < m + n; i++) {
141
+ diag_r_idxs[i] = idx_mapping[diag_r_idxs[i]];
152
142
  }
153
- /* assert kk == Knzmax */
154
- K->nz = Knzmax;
155
- K_cs = cs_compress(K);
156
- cs_spfree(K);
157
- return K_cs;
143
+ SCS(cs_spfree)(K);
144
+ scs_free(idx_mapping);
145
+ return Kcsc;
158
146
  }
159
147
 
160
- static scs_int _ldl_init(_cs *A, scs_int *P, scs_float **info) {
161
- *info = (scs_float *)scs_malloc(AMD_INFO * sizeof(scs_float));
148
+ static scs_int _ldl_init(csc *A, scs_int *P, scs_float **info) {
149
+ *info = (scs_float *)scs_calloc(AMD_INFO, sizeof(scs_float));
162
150
  return amd_order(A->n, A->p, A->i, P, (scs_float *)SCS_NULL, *info);
163
151
  }
164
152
 
165
- static scs_int _ldl_factor(_cs *A, _cs **L, scs_float **Dinv) {
166
- scs_int factor_status, n = A->n;
167
- scs_int *etree = (scs_int *)scs_malloc(n * sizeof(scs_int));
168
- scs_int *Lnz = (scs_int *)scs_malloc(n * sizeof(scs_int));
169
- scs_int *iwork = (scs_int *)scs_malloc(3 * n * sizeof(scs_int));
170
- scs_float *D, *fwork;
171
- scs_int *bwork;
172
- (*L)->p = (scs_int *)scs_malloc((1 + n) * sizeof(scs_int));
173
- (*L)->nzmax = QDLDL_etree(n, A->p, A->i, iwork, Lnz, etree);
174
- if ((*L)->nzmax < 0) {
153
+ /* call only once */
154
+ static scs_int ldl_prepare(ScsLinSysWork *p) {
155
+ csc *kkt = p->kkt, *L = p->L;
156
+ scs_int n = kkt->n;
157
+ p->etree = (scs_int *)scs_calloc(n, sizeof(scs_int));
158
+ p->Lnz = (scs_int *)scs_calloc(n, sizeof(scs_int));
159
+ p->iwork = (scs_int *)scs_calloc(3 * n, sizeof(scs_int));
160
+ L->p = (scs_int *)scs_calloc((1 + n), sizeof(scs_int));
161
+ L->nzmax = QDLDL_etree(n, kkt->p, kkt->i, p->iwork, p->Lnz, p->etree);
162
+ if (L->nzmax < 0) {
175
163
  scs_printf("Error in elimination tree calculation.\n");
176
- scs_free(Lnz);
177
- scs_free(iwork);
178
- scs_free(etree);
179
- scs_free((*L)->p);
180
- return (*L)->nzmax;
164
+ if (L->nzmax == -1) {
165
+ scs_printf("Matrix is not perfectly upper triangular.\n");
166
+ } else if (L->nzmax == -2) {
167
+ scs_printf("Integer overflow in L nonzero count.\n");
168
+ }
169
+ return L->nzmax;
181
170
  }
182
171
 
183
- (*L)->x = (scs_float *)scs_malloc((*L)->nzmax * sizeof(scs_float));
184
- (*L)->i = (scs_int *)scs_malloc((*L)->nzmax * sizeof(scs_int));
185
- *Dinv = (scs_float *)scs_malloc(n * sizeof(scs_float));
186
- D = (scs_float *)scs_malloc(n * sizeof(scs_float));
187
- bwork = (scs_int *)scs_malloc(n * sizeof(scs_int));
188
- fwork = (scs_float *)scs_malloc(n * sizeof(scs_float));
172
+ L->x = (scs_float *)scs_calloc(L->nzmax, sizeof(scs_float));
173
+ L->i = (scs_int *)scs_calloc(L->nzmax, sizeof(scs_int));
174
+ p->Dinv = (scs_float *)scs_calloc(n, sizeof(scs_float));
175
+ p->D = (scs_float *)scs_calloc(n, sizeof(scs_float));
176
+ p->bwork = (scs_int *)scs_calloc(n, sizeof(scs_int));
177
+ p->fwork = (scs_float *)scs_calloc(n, sizeof(scs_float));
178
+ return L->nzmax;
179
+ }
189
180
 
190
- #if EXTRA_VERBOSE > 0
181
+ /* can call many times */
182
+ static scs_int ldl_factor(ScsLinSysWork *p, scs_int num_vars) {
183
+ scs_int factor_status;
184
+ csc *kkt = p->kkt, *L = p->L;
185
+ #if VERBOSITY > 0
191
186
  scs_printf("numeric factorization\n");
192
187
  #endif
193
- factor_status = QDLDL_factor(n, A->p, A->i, A->x, (*L)->p, (*L)->i, (*L)->x,
194
- D, *Dinv, Lnz, etree, bwork, iwork, fwork);
195
- #if EXTRA_VERBOSE > 0
196
- scs_printf("finished numeric factorization\n");
188
+ factor_status =
189
+ QDLDL_factor(kkt->n, kkt->p, kkt->i, kkt->x, L->p, L->i, L->x, p->D,
190
+ p->Dinv, p->Lnz, p->etree, p->bwork, p->iwork, p->fwork);
191
+ #if VERBOSITY > 0
192
+ scs_printf("finished numeric factorization.\n");
197
193
  #endif
198
-
199
- scs_free(Lnz);
200
- scs_free(iwork);
201
- scs_free(etree);
202
- scs_free(D);
203
- scs_free(bwork);
204
- scs_free(fwork);
194
+ if (factor_status < 0) {
195
+ scs_printf("Error in LDL factorization when computing the nonzero "
196
+ "elements. There are zeros in the diagonal matrix.\n");
197
+ } else if (factor_status < num_vars) {
198
+ scs_printf("Error in LDL factorization when computing the nonzero "
199
+ "elements. The problem seems to be non-convex.\n");
200
+ scs_printf("factor_status: %li, num_vars: %li\n", (long)factor_status,
201
+ (long)num_vars);
202
+ return -1;
203
+ }
204
+ p->factorizations++;
205
205
  return factor_status;
206
206
  }
207
207
 
208
208
  static void _ldl_perm(scs_int n, scs_float *x, scs_float *b, scs_int *P) {
209
209
  scs_int j;
210
- for (j = 0; j < n; j++) x[j] = b[P[j]];
210
+ for (j = 0; j < n; j++)
211
+ x[j] = b[P[j]];
211
212
  }
212
213
 
213
214
  static void _ldl_permt(scs_int n, scs_float *x, scs_float *b, scs_int *P) {
214
215
  scs_int j;
215
- for (j = 0; j < n; j++) x[P[j]] = b[j];
216
+ for (j = 0; j < n; j++)
217
+ x[P[j]] = b[j];
216
218
  }
217
219
 
218
- static void _ldl_solve(scs_float *b, _cs *L, scs_float *Dinv, scs_int *P,
220
+ static void _ldl_solve(scs_float *b, csc *L, scs_float *Dinv, scs_int *P,
219
221
  scs_float *bp) {
220
222
  /* solves PLDL'P' x = b for x */
221
223
  scs_int n = L->n;
@@ -224,41 +226,34 @@ static void _ldl_solve(scs_float *b, _cs *L, scs_float *Dinv, scs_int *P,
224
226
  _ldl_permt(n, b, bp, P);
225
227
  }
226
228
 
227
- void SCS(accum_by_atrans)(const ScsMatrix *A, ScsLinSysWork *p,
228
- const scs_float *x, scs_float *y) {
229
- SCS(_accum_by_atrans)(A->n, A->x, A->i, A->p, x, y);
230
- }
231
-
232
- void SCS(accum_by_a)(const ScsMatrix *A, ScsLinSysWork *p, const scs_float *x,
233
- scs_float *y) {
234
- SCS(_accum_by_a)(A->n, A->x, A->i, A->p, x, y);
235
- }
236
-
237
229
  static scs_int *cs_pinv(scs_int const *p, scs_int n) {
238
230
  scs_int k, *pinv;
239
231
  if (!p) {
240
232
  return SCS_NULL;
241
233
  } /* p = SCS_NULL denotes identity */
242
- pinv = (scs_int *)scs_malloc(n * sizeof(scs_int)); /* allocate result */
234
+ pinv = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* allocate result */
243
235
  if (!pinv) {
244
236
  return SCS_NULL;
245
- } /* out of memory */
246
- for (k = 0; k < n; k++) pinv[p[k]] = k; /* invert the permutation */
247
- return pinv; /* return result */
237
+ } /* out of memory */
238
+ for (k = 0; k < n; k++)
239
+ pinv[p[k]] = k; /* invert the permutation */
240
+ return pinv; /* return result */
248
241
  }
249
242
 
250
- static _cs *cs_symperm(const _cs *A, const scs_int *pinv, scs_int values) {
243
+ static csc *cs_symperm(const csc *A, const scs_int *pinv, scs_int *idx_mapping,
244
+ scs_int values) {
251
245
  scs_int i, j, p, q, i2, j2, n, *Ap, *Ai, *Cp, *Ci, *w;
252
246
  scs_float *Cx, *Ax;
253
- _cs *C;
247
+ csc *C;
254
248
  n = A->n;
255
249
  Ap = A->p;
256
250
  Ai = A->i;
257
251
  Ax = A->x;
258
- C = cs_spalloc(n, n, Ap[n], values && (Ax != SCS_NULL), 0); /* alloc result*/
252
+ C = SCS(cs_spalloc)(n, n, Ap[n], values && (Ax != SCS_NULL),
253
+ 0); /* alloc result*/
259
254
  w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */
260
255
  if (!C || !w) {
261
- return cs_done(C, w, SCS_NULL, 0);
256
+ return SCS(cs_done)(C, w, SCS_NULL, 0);
262
257
  } /* out of memory */
263
258
  Cp = C->p;
264
259
  Ci = C->i;
@@ -288,79 +283,93 @@ static _cs *cs_symperm(const _cs *A, const scs_int *pinv, scs_int values) {
288
283
  if (Cx) {
289
284
  Cx[q] = Ax[p];
290
285
  }
286
+ idx_mapping[p] = q; /* old to new indices */
291
287
  }
292
288
  }
293
- return cs_done(C, w, SCS_NULL, 1); /* success; free workspace, return C */
289
+ return SCS(cs_done)(C, w, SCS_NULL,
290
+ 1); /* success; free workspace, return C */
294
291
  }
295
292
 
296
- static scs_int factorize(const ScsMatrix *A, const ScsSettings *stgs,
297
- ScsLinSysWork *p) {
293
+ static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
294
+ ScsLinSysWork *p, const scs_float *diag_r) {
298
295
  scs_float *info;
299
- scs_int *Pinv, amd_status, ldl_status;
300
- _cs *C, *K = form_kkt(A, stgs);
301
- if (!K) {
302
- return -1;
296
+ scs_int *Pinv, amd_status, *idx_mapping, i;
297
+ csc *kkt_perm, *kkt = form_kkt(A, P, p->diag_p, diag_r, p->diag_r_idxs);
298
+ if (!kkt) {
299
+ return SCS_NULL;
303
300
  }
304
- amd_status = _ldl_init(K, p->P, &info);
301
+ amd_status = _ldl_init(kkt, p->perm, &info);
305
302
  if (amd_status < 0) {
306
- return amd_status;
307
- }
308
- #if EXTRA_VERBOSE > 0
309
- if (stgs->verbose) {
310
- scs_printf("Matrix factorization info:\n");
311
- amd_info(info);
303
+ scs_printf("AMD permutatation error.\n");
304
+ return SCS_NULL;
312
305
  }
306
+ #if VERBOSITY > 0
307
+ scs_printf("Matrix factorization info:\n");
308
+ amd_info(info);
313
309
  #endif
314
- Pinv = cs_pinv(p->P, A->n + A->m);
315
- C = cs_symperm(K, Pinv, 1);
316
- ldl_status = _ldl_factor(C, &p->L, &p->Dinv);
317
- cs_spfree(C);
318
- cs_spfree(K);
310
+ Pinv = cs_pinv(p->perm, A->n + A->m);
311
+ idx_mapping = (scs_int *)scs_calloc(kkt->nzmax, sizeof(scs_int));
312
+ kkt_perm = cs_symperm(kkt, Pinv, idx_mapping, 1);
313
+ for (i = 0; i < A->n + A->m; i++) {
314
+ p->diag_r_idxs[i] = idx_mapping[p->diag_r_idxs[i]];
315
+ }
316
+ SCS(cs_spfree)(kkt);
319
317
  scs_free(Pinv);
320
318
  scs_free(info);
321
- return ldl_status;
319
+ scs_free(idx_mapping);
320
+ return kkt_perm;
322
321
  }
323
322
 
324
- ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
325
- const ScsSettings *stgs) {
323
+ void SCS(update_lin_sys_diag_r)(ScsLinSysWork *p, const scs_float *diag_r) {
324
+ scs_int i, ldl_status;
325
+ for (i = 0; i < p->n; ++i) {
326
+ /* top left is R_x + P, bottom right is -R_y */
327
+ p->kkt->x[p->diag_r_idxs[i]] = p->diag_p[i] + diag_r[i];
328
+ }
329
+ for (i = p->n; i < p->n + p->m; ++i) {
330
+ /* top left is R_x + P, bottom right is -R_y */
331
+ p->kkt->x[p->diag_r_idxs[i]] = -diag_r[i];
332
+ }
333
+ ldl_status = ldl_factor(p, p->n);
334
+ if (ldl_status < 0) {
335
+ scs_printf("Error in LDL factorization when updating.\n");
336
+ /* TODO: this is broken somehow */
337
+ /* SCS(free_lin_sys_work)(p); */
338
+ return;
339
+ }
340
+ }
341
+
342
+ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
343
+ const scs_float *diag_r) {
326
344
  ScsLinSysWork *p = (ScsLinSysWork *)scs_calloc(1, sizeof(ScsLinSysWork));
327
- scs_int n_plus_m = A->n + A->m;
328
- p->P = (scs_int *)scs_malloc(sizeof(scs_int) * n_plus_m);
329
- p->L = (_cs *)scs_malloc(sizeof(_cs));
330
- p->bp = (scs_float *)scs_malloc(n_plus_m * sizeof(scs_float));
345
+ scs_int n_plus_m = A->n + A->m, ldl_status, ldl_prepare_status;
346
+ p->m = A->m;
347
+ p->n = A->n;
348
+ p->diag_p = (scs_float *)scs_calloc(A->n, sizeof(scs_float));
349
+ p->perm = (scs_int *)scs_calloc(sizeof(scs_int), n_plus_m);
350
+ p->L = (csc *)scs_calloc(1, sizeof(csc));
351
+ p->bp = (scs_float *)scs_calloc(n_plus_m, sizeof(scs_float));
352
+ p->diag_r_idxs = (scs_int *)scs_calloc(n_plus_m, sizeof(scs_int));
353
+ p->factorizations = 0;
331
354
  p->L->m = n_plus_m;
332
355
  p->L->n = n_plus_m;
333
356
  p->L->nz = -1;
334
-
335
- if (factorize(A, stgs, p) < 0) {
336
- SCS(free_lin_sys_work)(p);
357
+ p->kkt = permute_kkt(A, P, p, diag_r);
358
+ ldl_prepare_status = ldl_prepare(p);
359
+ ldl_status = ldl_factor(p, A->n);
360
+ if (ldl_prepare_status < 0 || ldl_status < 0) {
361
+ scs_printf("Error in LDL initial factorization.\n");
362
+ /* TODO: this is broken somehow */
363
+ /* SCS(free_lin_sys_work)(p); */
337
364
  return SCS_NULL;
338
365
  }
339
- p->total_solve_time = 0.0;
340
366
  return p;
341
367
  }
342
368
 
343
- scs_int SCS(solve_lin_sys)(const ScsMatrix *A, const ScsSettings *stgs,
344
- ScsLinSysWork *p, scs_float *b, const scs_float *s,
345
- scs_int iter) {
369
+ scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
370
+ scs_float tol) {
346
371
  /* returns solution to linear system */
347
372
  /* Ax = b with solution stored in b */
348
- SCS(timer) linsys_timer;
349
- SCS(tic)(&linsys_timer);
350
- _ldl_solve(b, p->L, p->Dinv, p->P, p->bp);
351
- p->total_solve_time += SCS(tocq)(&linsys_timer);
352
- #if EXTRA_VERBOSE > 0
353
- scs_printf("linsys solve time: %1.2es\n", SCS(tocq)(&linsys_timer) / 1e3);
354
- #endif
373
+ _ldl_solve(b, p->L, p->Dinv, p->perm, p->bp);
355
374
  return 0;
356
375
  }
357
-
358
- void SCS(normalize_a)(ScsMatrix *A, const ScsSettings *stgs, const ScsCone *k,
359
- ScsScaling *scal) {
360
- SCS(_normalize_a)(A, stgs, k, scal);
361
- }
362
-
363
- void SCS(un_normalize_a)(ScsMatrix *A, const ScsSettings *stgs,
364
- const ScsScaling *scal) {
365
- SCS(_un_normalize_a)(A, stgs, scal);
366
- }
@@ -5,19 +5,25 @@
5
5
  extern "C" {
6
6
  #endif
7
7
 
8
- #include "amatrix.h"
8
+ #include "csparse.h"
9
9
  #include "external/amd/amd.h"
10
10
  #include "external/qdldl/qdldl.h"
11
11
  #include "glbopts.h"
12
12
  #include "scs.h"
13
+ #include "scs_matrix.h"
13
14
 
14
- typedef struct SPARSE_MATRIX _cs;
15
15
  struct SCS_LIN_SYS_WORK {
16
- _cs *L; /* KKT, and factorization matrix L resp. */
17
- scs_float *Dinv; /* inverse diagonal matrix of factorization */
18
- scs_int *P; /* permutation of KKT matrix for factorization */
19
- scs_float *bp; /* workspace memory for solves */
20
- scs_float total_solve_time; /* reporting */
16
+ scs_int m, n; /* linear system dimensions */
17
+ csc *kkt, *L; /* KKT, and factorization matrix L resp. */
18
+ scs_float *Dinv; /* inverse diagonal matrix of factorization */
19
+ scs_int *perm; /* permutation of KKT matrix for factorization */
20
+ scs_float *bp; /* workspace memory for solves */
21
+ scs_int *diag_r_idxs;
22
+ scs_int factorizations;
23
+ /* ldl factorization workspace */
24
+ scs_float *D, *fwork;
25
+ scs_int *etree, *iwork, *Lnz, *bwork;
26
+ scs_float *diag_p;
21
27
  };
22
28
 
23
29
  #ifdef __cplusplus