scs 0.2.2 → 0.3.2

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 (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