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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +11 -6
- data/lib/scs/ffi.rb +30 -13
- data/lib/scs/solver.rb +32 -9
- data/lib/scs/version.rb +1 -1
- data/vendor/scs/CITATION.cff +39 -0
- data/vendor/scs/CMakeLists.txt +7 -8
- data/vendor/scs/Makefile +24 -15
- data/vendor/scs/README.md +5 -263
- data/vendor/scs/include/aa.h +67 -23
- data/vendor/scs/include/cones.h +17 -17
- data/vendor/scs/include/glbopts.h +98 -32
- data/vendor/scs/include/linalg.h +2 -4
- data/vendor/scs/include/linsys.h +58 -44
- data/vendor/scs/include/normalize.h +3 -3
- data/vendor/scs/include/rw.h +8 -2
- data/vendor/scs/include/scs.h +293 -133
- data/vendor/scs/include/util.h +3 -15
- data/vendor/scs/linsys/cpu/direct/private.c +220 -224
- data/vendor/scs/linsys/cpu/direct/private.h +13 -7
- data/vendor/scs/linsys/cpu/direct/private.o +0 -0
- data/vendor/scs/linsys/cpu/indirect/private.c +177 -110
- data/vendor/scs/linsys/cpu/indirect/private.h +8 -4
- data/vendor/scs/linsys/cpu/indirect/private.o +0 -0
- data/vendor/scs/linsys/csparse.c +87 -0
- data/vendor/scs/linsys/csparse.h +34 -0
- data/vendor/scs/linsys/csparse.o +0 -0
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.c +1 -1
- data/vendor/scs/linsys/external/amd/SuiteSparse_config.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_1.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_2.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_aat.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_control.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_defaults.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_dump.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_global.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_info.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_internal.h +1 -1
- data/vendor/scs/linsys/external/amd/amd_order.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_post_tree.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_postorder.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_preprocess.o +0 -0
- data/vendor/scs/linsys/external/amd/amd_valid.o +0 -0
- data/vendor/scs/linsys/external/qdldl/changes +2 -0
- data/vendor/scs/linsys/external/qdldl/qdldl.c +29 -46
- data/vendor/scs/linsys/external/qdldl/qdldl.h +33 -41
- data/vendor/scs/linsys/external/qdldl/qdldl.o +0 -0
- data/vendor/scs/linsys/external/qdldl/qdldl_types.h +11 -3
- data/vendor/scs/linsys/gpu/gpu.c +31 -33
- data/vendor/scs/linsys/gpu/gpu.h +48 -31
- data/vendor/scs/linsys/gpu/indirect/private.c +338 -232
- data/vendor/scs/linsys/gpu/indirect/private.h +23 -14
- data/vendor/scs/linsys/scs_matrix.c +498 -0
- data/vendor/scs/linsys/scs_matrix.h +70 -0
- data/vendor/scs/linsys/scs_matrix.o +0 -0
- data/vendor/scs/scs.mk +13 -9
- data/vendor/scs/src/aa.c +384 -109
- data/vendor/scs/src/aa.o +0 -0
- data/vendor/scs/src/cones.c +440 -353
- data/vendor/scs/src/cones.o +0 -0
- data/vendor/scs/src/ctrlc.c +15 -5
- data/vendor/scs/src/ctrlc.o +0 -0
- data/vendor/scs/src/linalg.c +84 -28
- data/vendor/scs/src/linalg.o +0 -0
- data/vendor/scs/src/normalize.c +22 -64
- data/vendor/scs/src/normalize.o +0 -0
- data/vendor/scs/src/rw.c +160 -21
- data/vendor/scs/src/rw.o +0 -0
- data/vendor/scs/src/scs.c +767 -563
- data/vendor/scs/src/scs.o +0 -0
- data/vendor/scs/src/scs_indir.o +0 -0
- data/vendor/scs/src/scs_version.c +9 -3
- data/vendor/scs/src/scs_version.o +0 -0
- data/vendor/scs/src/util.c +37 -106
- data/vendor/scs/src/util.o +0 -0
- data/vendor/scs/test/minunit.h +17 -8
- data/vendor/scs/test/problem_utils.h +176 -14
- data/vendor/scs/test/problems/degenerate.h +130 -0
- data/vendor/scs/test/problems/hs21_tiny_qp.h +124 -0
- data/vendor/scs/test/problems/hs21_tiny_qp_rw.h +116 -0
- data/vendor/scs/test/problems/infeasible_tiny_qp.h +100 -0
- data/vendor/scs/test/problems/qafiro_tiny_qp.h +199 -0
- data/vendor/scs/test/problems/random_prob +0 -0
- data/vendor/scs/test/problems/random_prob.h +45 -0
- data/vendor/scs/test/problems/rob_gauss_cov_est.h +188 -31
- data/vendor/scs/test/problems/small_lp.h +13 -14
- data/vendor/scs/test/problems/test_fails.h +43 -0
- data/vendor/scs/test/problems/unbounded_tiny_qp.h +82 -0
- data/vendor/scs/test/random_socp_prob.c +54 -53
- data/vendor/scs/test/rng.h +109 -0
- data/vendor/scs/test/run_from_file.c +19 -10
- data/vendor/scs/test/run_tests.c +27 -3
- metadata +20 -8
- data/vendor/scs/linsys/amatrix.c +0 -305
- data/vendor/scs/linsys/amatrix.h +0 -36
- data/vendor/scs/linsys/amatrix.o +0 -0
- data/vendor/scs/test/data/small_random_socp +0 -0
- data/vendor/scs/test/problems/small_random_socp.h +0 -33
- data/vendor/scs/test/run_tests +0 -2
|
@@ -1,221 +1,215 @@
|
|
|
1
1
|
#include "private.h"
|
|
2
|
+
#include "linsys.h"
|
|
2
3
|
|
|
3
|
-
|
|
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, "
|
|
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
|
-
|
|
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
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
|
124
|
-
scs_printf("forming
|
|
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
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
138
|
-
|
|
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] +
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
K->
|
|
150
|
-
K->
|
|
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
|
-
|
|
154
|
-
K->nz
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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(
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
scs_int
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
scs_int *
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
-
|
|
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 =
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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++)
|
|
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++)
|
|
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,
|
|
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
|
-
}
|
|
246
|
-
for (k = 0; k < n; k++)
|
|
247
|
-
|
|
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
|
|
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
|
-
|
|
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),
|
|
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,
|
|
281
|
+
return SCS(cs_done)(C, w, SCS_NULL,
|
|
282
|
+
1); /* success; free workspace, return C */
|
|
294
283
|
}
|
|
295
284
|
|
|
296
|
-
static
|
|
297
|
-
|
|
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,
|
|
300
|
-
|
|
301
|
-
if (!
|
|
302
|
-
return
|
|
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(
|
|
293
|
+
amd_status = _ldl_init(kkt, p->perm, &info);
|
|
305
294
|
if (amd_status < 0) {
|
|
306
|
-
|
|
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->
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
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
|
-
|
|
311
|
+
scs_free(idx_mapping);
|
|
312
|
+
return kkt_perm;
|
|
322
313
|
}
|
|
323
314
|
|
|
324
|
-
|
|
325
|
-
|
|
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->
|
|
329
|
-
p->
|
|
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
|
-
|
|
336
|
-
|
|
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)(
|
|
344
|
-
|
|
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
|
-
|
|
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 "
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
scs_float
|
|
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
|