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,221 +1,215 @@
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->perm);
51
22
  scs_free(p->Dinv);
52
23
  scs_free(p->bp);
24
+ scs_free(p->rho_y_vec_idxs);
25
+ scs_free(p->Lnz);
26
+ scs_free(p->iwork);
27
+ scs_free(p->etree);
28
+ scs_free(p->D);
29
+ scs_free(p->bwork);
30
+ scs_free(p->fwork);
53
31
  scs_free(p);
54
32
  }
55
33
  }
56
34
 
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) {
35
+ static csc *form_kkt(const ScsMatrix *A, const ScsMatrix *P,
36
+ scs_float *rho_y_vec, scs_int *rho_y_vec_idxs,
37
+ scs_float rho_x) {
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 i, j, k, kk;
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
+ kk = 0; /* element counter */
69
+ if (P) {
70
+ /* I + P in top left */
71
+ for (j = 0; j < P->n; j++) { /* cols */
72
+ /* empty column, add diagonal */
73
+ if (P->p[j] == P->p[j + 1]) {
74
+ K->i[kk] = j;
75
+ K->p[kk] = j;
76
+ K->x[kk] = rho_x;
77
+ kk++;
78
+ }
79
+ for (k = P->p[j]; k < P->p[j + 1]; k++) {
80
+ i = P->i[k]; /* row */
81
+ if (i > j) { /* only upper triangular needed */
82
+ break;
83
+ }
84
+ K->i[kk] = i;
85
+ K->p[kk] = j;
86
+ K->x[kk] = P->x[k];
87
+ if (i == j) {
88
+ /* P has diagonal element */
89
+ K->x[kk] += rho_x;
90
+ }
91
+ kk++;
92
+ /* reached the end without adding diagonal, do it now */
93
+ if ((i < j) && (k + 1 == P->p[j + 1] || P->i[k + 1] > j)) {
94
+ K->i[kk] = j;
95
+ K->p[kk] = j;
96
+ K->x[kk] = rho_x;
97
+ kk++;
98
+ }
99
+ }
100
+ }
101
+ } else {
102
+ /* rho_x * I in top left */
103
+ for (k = 0; k < A->n; k++) {
104
+ K->i[kk] = k;
105
+ K->p[kk] = k;
106
+ K->x[kk] = rho_x;
107
+ kk++;
108
+ }
136
109
  }
137
- /* A^T at top right : CCS: */
138
- for (j = 0; j < A->n; j++) {
110
+
111
+ /* A^T at top right */
112
+ for (j = 0; j < n; j++) {
139
113
  for (k = A->p[j]; k < A->p[j + 1]; k++) {
140
- K->p[kk] = A->i[k] + A->n;
114
+ K->p[kk] = A->i[k] + n;
141
115
  K->i[kk] = j;
142
116
  K->x[kk] = A->x[k];
143
117
  kk++;
144
118
  }
145
119
  }
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;
120
+
121
+ /* -rho_y_vec * I at bottom right */
122
+ for (k = 0; k < m; k++) {
123
+ K->i[kk] = k + n;
124
+ K->p[kk] = k + n;
125
+ K->x[kk] = -rho_y_vec[k];
126
+ rho_y_vec_idxs[k] = kk; /* store the indices where rho_y_vec occurs */
151
127
  kk++;
152
128
  }
153
- /* assert kk == Knzmax */
154
- K->nz = Knzmax;
155
- K_cs = cs_compress(K);
156
- cs_spfree(K);
157
- return K_cs;
129
+ K->nz = kk;
130
+ idx_mapping = (scs_int *)scs_malloc(K->nz * sizeof(scs_int));
131
+ Kcsc = SCS(cs_compress)(K, idx_mapping);
132
+ for (i = 0; i < A->m; i++) {
133
+ rho_y_vec_idxs[i] = idx_mapping[rho_y_vec_idxs[i]];
134
+ }
135
+ SCS(cs_spfree)(K);
136
+ scs_free(idx_mapping);
137
+ return Kcsc;
158
138
  }
159
139
 
160
- static scs_int _ldl_init(_cs *A, scs_int *P, scs_float **info) {
140
+ static scs_int _ldl_init(csc *A, scs_int *P, scs_float **info) {
161
141
  *info = (scs_float *)scs_malloc(AMD_INFO * sizeof(scs_float));
162
142
  return amd_order(A->n, A->p, A->i, P, (scs_float *)SCS_NULL, *info);
163
143
  }
164
144
 
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) {
145
+ /* call only once */
146
+ static scs_int ldl_prepare(ScsLinSysWork *p) {
147
+ csc *kkt = p->kkt, *L = p->L;
148
+ scs_int n = kkt->n;
149
+ p->etree = (scs_int *)scs_malloc(n * sizeof(scs_int));
150
+ p->Lnz = (scs_int *)scs_malloc(n * sizeof(scs_int));
151
+ p->iwork = (scs_int *)scs_malloc(3 * n * sizeof(scs_int));
152
+ L->p = (scs_int *)scs_malloc((1 + n) * sizeof(scs_int));
153
+ L->nzmax = QDLDL_etree(n, kkt->p, kkt->i, p->iwork, p->Lnz, p->etree);
154
+ if (L->nzmax < 0) {
175
155
  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;
156
+ if (L->nzmax == -1) {
157
+ scs_printf("Matrix is not perfectly upper triangular.\n");
158
+ } else if (L->nzmax == -2) {
159
+ scs_printf("Integer overflow in L nonzero count.\n");
160
+ }
161
+ return L->nzmax;
181
162
  }
182
163
 
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));
164
+ L->x = (scs_float *)scs_malloc(L->nzmax * sizeof(scs_float));
165
+ L->i = (scs_int *)scs_malloc(L->nzmax * sizeof(scs_int));
166
+ p->Dinv = (scs_float *)scs_malloc(n * sizeof(scs_float));
167
+ p->D = (scs_float *)scs_malloc(n * sizeof(scs_float));
168
+ p->bwork = (scs_int *)scs_malloc(n * sizeof(scs_int));
169
+ p->fwork = (scs_float *)scs_malloc(n * sizeof(scs_float));
170
+ return L->nzmax;
171
+ }
189
172
 
190
- #if EXTRA_VERBOSE > 0
173
+ /* can call many times */
174
+ static scs_int ldl_factor(ScsLinSysWork *p, scs_int num_vars) {
175
+ scs_int factor_status;
176
+ csc *kkt = p->kkt, *L = p->L;
177
+ #if VERBOSITY > 0
191
178
  scs_printf("numeric factorization\n");
192
179
  #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");
180
+ factor_status =
181
+ QDLDL_factor(kkt->n, kkt->p, kkt->i, kkt->x, L->p, L->i, L->x, p->D,
182
+ p->Dinv, p->Lnz, p->etree, p->bwork, p->iwork, p->fwork);
183
+ #if VERBOSITY > 0
184
+ scs_printf("finished numeric factorization.\n");
197
185
  #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);
186
+ if (factor_status < 0) {
187
+ scs_printf("Error in LDL factorization when computing the nonzero "
188
+ "elements. There are zeros in the diagonal matrix.\n");
189
+ } else if (factor_status < num_vars) {
190
+ scs_printf("Error in LDL factorization when computing the nonzero "
191
+ "elements. The problem seems to be non-convex.\n");
192
+ scs_printf("factor_status: %li, num_vars: %li\n", (long)factor_status,
193
+ (long)num_vars);
194
+ return -1;
195
+ }
196
+ p->factorizations++;
205
197
  return factor_status;
206
198
  }
207
199
 
208
200
  static void _ldl_perm(scs_int n, scs_float *x, scs_float *b, scs_int *P) {
209
201
  scs_int j;
210
- for (j = 0; j < n; j++) x[j] = b[P[j]];
202
+ for (j = 0; j < n; j++)
203
+ x[j] = b[P[j]];
211
204
  }
212
205
 
213
206
  static void _ldl_permt(scs_int n, scs_float *x, scs_float *b, scs_int *P) {
214
207
  scs_int j;
215
- for (j = 0; j < n; j++) x[P[j]] = b[j];
208
+ for (j = 0; j < n; j++)
209
+ x[P[j]] = b[j];
216
210
  }
217
211
 
218
- static void _ldl_solve(scs_float *b, _cs *L, scs_float *Dinv, scs_int *P,
212
+ static void _ldl_solve(scs_float *b, csc *L, scs_float *Dinv, scs_int *P,
219
213
  scs_float *bp) {
220
214
  /* solves PLDL'P' x = b for x */
221
215
  scs_int n = L->n;
@@ -224,16 +218,6 @@ static void _ldl_solve(scs_float *b, _cs *L, scs_float *Dinv, scs_int *P,
224
218
  _ldl_permt(n, b, bp, P);
225
219
  }
226
220
 
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
221
  static scs_int *cs_pinv(scs_int const *p, scs_int n) {
238
222
  scs_int k, *pinv;
239
223
  if (!p) {
@@ -242,23 +226,26 @@ static scs_int *cs_pinv(scs_int const *p, scs_int n) {
242
226
  pinv = (scs_int *)scs_malloc(n * sizeof(scs_int)); /* allocate result */
243
227
  if (!pinv) {
244
228
  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 */
229
+ } /* out of memory */
230
+ for (k = 0; k < n; k++)
231
+ pinv[p[k]] = k; /* invert the permutation */
232
+ return pinv; /* return result */
248
233
  }
249
234
 
250
- static _cs *cs_symperm(const _cs *A, const scs_int *pinv, scs_int values) {
235
+ static csc *cs_symperm(const csc *A, const scs_int *pinv, scs_int *idx_mapping,
236
+ scs_int values) {
251
237
  scs_int i, j, p, q, i2, j2, n, *Ap, *Ai, *Cp, *Ci, *w;
252
238
  scs_float *Cx, *Ax;
253
- _cs *C;
239
+ csc *C;
254
240
  n = A->n;
255
241
  Ap = A->p;
256
242
  Ai = A->i;
257
243
  Ax = A->x;
258
- C = cs_spalloc(n, n, Ap[n], values && (Ax != SCS_NULL), 0); /* alloc result*/
244
+ C = SCS(cs_spalloc)(n, n, Ap[n], values && (Ax != SCS_NULL),
245
+ 0); /* alloc result*/
259
246
  w = (scs_int *)scs_calloc(n, sizeof(scs_int)); /* get workspace */
260
247
  if (!C || !w) {
261
- return cs_done(C, w, SCS_NULL, 0);
248
+ return SCS(cs_done)(C, w, SCS_NULL, 0);
262
249
  } /* out of memory */
263
250
  Cp = C->p;
264
251
  Ci = C->i;
@@ -288,79 +275,88 @@ static _cs *cs_symperm(const _cs *A, const scs_int *pinv, scs_int values) {
288
275
  if (Cx) {
289
276
  Cx[q] = Ax[p];
290
277
  }
278
+ idx_mapping[p] = q; /* old to new indices */
291
279
  }
292
280
  }
293
- return cs_done(C, w, SCS_NULL, 1); /* success; free workspace, return C */
281
+ return SCS(cs_done)(C, w, SCS_NULL,
282
+ 1); /* success; free workspace, return C */
294
283
  }
295
284
 
296
- static scs_int factorize(const ScsMatrix *A, const ScsSettings *stgs,
297
- ScsLinSysWork *p) {
285
+ static csc *permute_kkt(const ScsMatrix *A, const ScsMatrix *P,
286
+ ScsLinSysWork *p, scs_float *rho_y_vec) {
298
287
  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;
288
+ scs_int *Pinv, amd_status, *idx_mapping, i;
289
+ csc *kkt_perm, *kkt = form_kkt(A, P, rho_y_vec, p->rho_y_vec_idxs, p->rho_x);
290
+ if (!kkt) {
291
+ return SCS_NULL;
303
292
  }
304
- amd_status = _ldl_init(K, p->P, &info);
293
+ amd_status = _ldl_init(kkt, p->perm, &info);
305
294
  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);
295
+ scs_printf("AMD permutatation error.\n");
296
+ return SCS_NULL;
312
297
  }
298
+ #if VERBOSITY > 0
299
+ scs_printf("Matrix factorization info:\n");
300
+ amd_info(info);
313
301
  #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);
302
+ Pinv = cs_pinv(p->perm, A->n + A->m);
303
+ idx_mapping = (scs_int *)scs_malloc(kkt->nzmax * sizeof(scs_int));
304
+ kkt_perm = cs_symperm(kkt, Pinv, idx_mapping, 1);
305
+ for (i = 0; i < A->m; i++) {
306
+ p->rho_y_vec_idxs[i] = idx_mapping[p->rho_y_vec_idxs[i]];
307
+ }
308
+ SCS(cs_spfree)(kkt);
319
309
  scs_free(Pinv);
320
310
  scs_free(info);
321
- return ldl_status;
311
+ scs_free(idx_mapping);
312
+ return kkt_perm;
322
313
  }
323
314
 
324
- ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A,
325
- const ScsSettings *stgs) {
315
+ void SCS(update_lin_sys_rho_y_vec)(ScsLinSysWork *p, scs_float *rho_y_vec) {
316
+ scs_int i, ldl_status;
317
+ for (i = 0; i < p->m; ++i) {
318
+ p->kkt->x[p->rho_y_vec_idxs[i]] = -rho_y_vec[i];
319
+ }
320
+ ldl_status = ldl_factor(p, p->n);
321
+ if (ldl_status < 0) {
322
+ scs_printf("Error in LDL factorization when updating.\n");
323
+ /* TODO: this is broken somehow */
324
+ /* SCS(free_lin_sys_work)(p); */
325
+ return;
326
+ }
327
+ }
328
+
329
+ ScsLinSysWork *SCS(init_lin_sys_work)(const ScsMatrix *A, const ScsMatrix *P,
330
+ scs_float *rho_y_vec, scs_float rho_x) {
326
331
  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));
332
+ scs_int n_plus_m = A->n + A->m, ldl_status, ldl_prepare_status;
333
+ p->m = A->m;
334
+ p->n = A->n;
335
+ p->rho_x = rho_x;
336
+ p->perm = (scs_int *)scs_malloc(sizeof(scs_int) * n_plus_m);
337
+ p->L = (csc *)scs_malloc(sizeof(csc));
330
338
  p->bp = (scs_float *)scs_malloc(n_plus_m * sizeof(scs_float));
339
+ p->rho_y_vec_idxs = (scs_int *)scs_malloc(A->m * sizeof(scs_int));
340
+ p->factorizations = 0;
331
341
  p->L->m = n_plus_m;
332
342
  p->L->n = n_plus_m;
333
343
  p->L->nz = -1;
334
-
335
- if (factorize(A, stgs, p) < 0) {
336
- SCS(free_lin_sys_work)(p);
344
+ p->kkt = permute_kkt(A, P, p, rho_y_vec);
345
+ ldl_prepare_status = ldl_prepare(p);
346
+ ldl_status = ldl_factor(p, A->n);
347
+ if (ldl_prepare_status < 0 || ldl_status < 0) {
348
+ scs_printf("Error in LDL initial factorization.\n");
349
+ /* TODO: this is broken somehow */
350
+ /* SCS(free_lin_sys_work)(p); */
337
351
  return SCS_NULL;
338
352
  }
339
- p->total_solve_time = 0.0;
340
353
  return p;
341
354
  }
342
355
 
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) {
356
+ scs_int SCS(solve_lin_sys)(ScsLinSysWork *p, scs_float *b, const scs_float *s,
357
+ scs_float tol) {
346
358
  /* returns solution to linear system */
347
359
  /* 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
360
+ _ldl_solve(b, p->L, p->Dinv, p->perm, p->bp);
355
361
  return 0;
356
362
  }
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 *rho_y_vec_idxs;
22
+ scs_int factorizations;
23
+ /* ldl factorization workspace */
24
+ scs_float *D, *fwork;
25
+ scs_int *etree, *iwork, *Lnz, *bwork;
26
+ scs_float rho_x;
21
27
  };
22
28
 
23
29
  #ifdef __cplusplus
Binary file